7a58a530b1
The selector forced every task through the heaviest methodology's
critical path: a behaviour-preserving, type-enumerable change paid the
same specify -> planner -> implement front-half as a novel feature,
because it was neither new behaviour (tdd) nor an observed bug (debug)
and so fell to specify by elimination. Two coupled defects — a selector
with no verification axis, and an all-or-nothing executor — kept the
existing lighter path unreachable and uneconomical. This fixes both.
Part A — verification-keyed selector (boss/SKILL.md):
- Replace the three-way "design line" with an ordered cascade that adds
a verification/enumeration axis ahead of the settled-vs-fork question.
Each lighter arm carries a positive trigger matched by signature, not
reached by elimination.
- New `compiler-driven` arm: a type/signature edit at a definition site
that propagates mechanically. Observe-then-bounce — make the edit,
build, run the suite; clean build AND suite green unchanged commits;
a hole bounces up (specify for a design choice, tdd for discovered
test-specifiable new behaviour); a regression bounces to debug.
- The observed-bug RED-first gate is first in the cascade, so a
mechanical-looking fix cannot bypass it.
- The straddle rule ("add an enum variant") is codified as a rule:
mechanical/forwarding -> compiler-driven; encodes new behaviour ->
tdd/spec; doubt routes up.
- The executor is the elevated inline carve-out plus a shipped workflow,
not a heavy new skill ("the largest concrete win is small").
Part B — Workflow substrate (implement/workflows/):
- implement-loop.js: the per-task loop as a deterministic script. Each
phase (implementer -> spec-compliance -> quality, + tester for E2E) is
a separate top-level agent() call, so a single phase is independently
invokable and inter-phase aggregation/re-loop is code. Retires the
implement-orchestrator agent's inline-role-switch workaround (the four
phase agents survive as the agent-types the script dispatches).
- compiler-driven-edit.js: the observe-then-bounce loop.
- install.sh / uninstall.sh symlink shipped workflows into
~/.claude/workflows/.
- specify and brainstorm stay prose + interactive (human-intent oracle);
only the autonomous/mechanical loops moved. try-and-error is deferred.
Docs (pipeline taxonomy, design, agent-template, migration, README) and
all selector<->executor cross-references updated; the arm and its
executor are co-located so a future re-route through the full loop is a
visible regression.
Verified by an adversarial multi-agent pass: PASS on all six acceptance
criteria; two coherence concerns fixed. The shipped scripts are
syntax-validated but exercised only in a downstream target project (the
skills repo is not itself a pipeline target).
closes #7
144 lines
6.7 KiB
Markdown
144 lines
6.7 KiB
Markdown
# Design
|
|
|
|
## Why split plugin from project
|
|
|
|
The skills system originally evolved inside the AILang project,
|
|
where it grew organically against AILang's specific paths,
|
|
build commands, vocabulary, and contracts. Lifting it into a
|
|
plugin requires a clean separation between what is universal
|
|
(belongs in the plugin) and what is project-specific (belongs
|
|
in the project's `CLAUDE.md`).
|
|
|
|
The litmus test: would a sentence in a SKILL or agent body
|
|
still make sense in a Python web project, a Rust CLI, and a
|
|
TypeScript library? If yes, plugin. If it mentions `cargo`,
|
|
`crates/`, `docs/design/INDEX.md`, `Form A`, or any project-specific
|
|
identifier, it goes to the project's `CLAUDE.md` — either as a
|
|
project fact (the few mechanical facts the skills consume) or as
|
|
sittenkodex (domain contracts, anti-patterns).
|
|
|
|
There is no separate profile file. An earlier design had a
|
|
per-project `dev-cycle-profile.yml`, but it was never parsed — it
|
|
was prose the skill bodies told the model to read, and almost every
|
|
slot was constant across projects, dead, or derivable. So the
|
|
constant parts became fixed conventions (`conventions.md`) and the
|
|
genuinely-varying parts moved into each project's `CLAUDE.md`.
|
|
|
|
## Plugin layer (universal)
|
|
|
|
The plugin owns:
|
|
|
|
- **Pipeline form** — the directed graph of phases:
|
|
`design → plan → execute → review → close`, entered through a
|
|
**selector cascade** of entry paths walked on a verification /
|
|
enumeration axis (observed bug → `debug`; design fork →
|
|
`brainstorm`; behaviour-preserving type/signature edit →
|
|
`compiler-driven`; test-specifiable → `tdd`; else → spec-driven).
|
|
The taxonomy of paths and their oracles lives in
|
|
`pipeline.md` § The methodology taxonomy.
|
|
- **Hard-gates** — spec before plan, plan before implement,
|
|
audit before cycle-close. Skipping rules are codified per
|
|
skill.
|
|
- **Agent template** — every agent file follows the same
|
|
structure: frontmatter (name, description, tools), Iron Law,
|
|
standing reading list, numbered process, status protocol,
|
|
output format, common rationalisations, red flags.
|
|
- **TDD as an independent inner-loop discipline** — the
|
|
implementer agent carries TDD even when the plan task forgot
|
|
to script a RED-first step.
|
|
- **RED-first bug fixes** — non-negotiable for any observable
|
|
misbehaviour; the debug skill is the gate.
|
|
- **Status protocol** — `DONE / DONE_WITH_CONCERNS / PARTIAL /
|
|
BLOCKED / NEEDS_CONTEXT`, plus reviewer-specific terminal
|
|
states.
|
|
- **Working-tree-as-quarantine** — agents write artefacts to
|
|
the working tree, never commit. Only the orchestrator commits.
|
|
- **main HEAD sacrosanct** — no reset, no revert, by any actor.
|
|
main moves forward only via orchestrator commits.
|
|
- **No nested subagent dispatch** — a hard Claude Code platform
|
|
constraint: an agent cannot spawn further agents. Workflows do not
|
|
lift it; a workflow script orchestrates from the **top level**, and
|
|
the agents it spawns still cannot spawn further agents. This is
|
|
exactly why the autonomous execution loops moved onto the Workflow
|
|
substrate: the `implement-loop` and `compiler-driven-edit` scripts
|
|
(`implement/workflows/`) run the per-phase agents as their own
|
|
top-level `agent()` calls, so a single phase is independently
|
|
invokable — which retired the former `implement-orchestrator`
|
|
agent's inline-role-switch workaround (it had to absorb the three
|
|
phases into one context precisely because it could not nest). The
|
|
four phase agents survive as the agent-types the scripts dispatch;
|
|
what was retired is the dispatch/aggregation prose. The interactive
|
|
paths (`specify`, `brainstorm`) stay prose skills — their oracle is
|
|
human intent and needs a human in the loop, which a
|
|
run-to-completion workflow cannot host.
|
|
- **No orphan agents** — every agent lives under the skill
|
|
that dispatches it.
|
|
- **Output budget discipline** — agents have word budgets on
|
|
their reports.
|
|
|
|
## Fixed conventions (universal)
|
|
|
|
The constants that used to be configurable but were the same in
|
|
every project are now plugin conventions, named directly in skill
|
|
and agent bodies and documented once in `conventions.md`:
|
|
spec dir `docs/specs`, plan dir `docs/plans`, 4-digit per-directory
|
|
naming, the vocabulary cycle / iteration / milestone / contract,
|
|
standing reading (`CLAUDE.md` + `git log -10`), git discipline
|
|
(only-orchestrator commits, main sacrosanct), Gitea + `closes #N`,
|
|
and the whole pipeline graph (see `pipeline.md`).
|
|
|
|
## Project facts (project-specific)
|
|
|
|
The handful of facts that genuinely vary per project live in the
|
|
project's `CLAUDE.md` under `## Skills plugin: project facts`:
|
|
code roots, build / test / lint / doc-build commands, regression
|
|
scripts, architect sweeps, design-ledger / glossary / contracts /
|
|
models / bench / public-interface / fieldtest-examples paths,
|
|
by-role standing reading, the issue-tracker repo slug and commands,
|
|
and spec auto-sign. The template is in
|
|
`../templates/CLAUDE.md.fragment`; the per-fact reference is the
|
|
table in `conventions.md`.
|
|
|
|
## Resolution model
|
|
|
|
The plugin uses **convention-and-fact prompts**, not template
|
|
rendering and not a config parser. Each SKILL.md and agent file is
|
|
generic prose that either names a fixed convention directly or
|
|
points at a project fact:
|
|
|
|
> Write the spec to `docs/specs`. Use the project's build command
|
|
> (its CLAUDE.md project facts).
|
|
|
|
The project's `CLAUDE.md` is always in context (it is standing
|
|
reading #1), so the model resolves the facts at read-time. This
|
|
avoids a build step and keeps a single source of truth in the repo.
|
|
|
|
## Sittenkodex split
|
|
|
|
The plugin does **not** carry project-specific anti-patterns,
|
|
feature-acceptance gates, or domain contracts. Those belong in
|
|
the project's own `CLAUDE.md`. The plugin only carries the
|
|
*universal* discipline constants (only-orchestrator commits,
|
|
main sacrosanct, no orphan agents, agents-don't-call-agents)
|
|
which are conditions for the plugin's own correctness.
|
|
|
|
The relationship:
|
|
|
|
- **Plugin** (this repo): mechanics, universal discipline, fixed
|
|
conventions
|
|
- **Project CLAUDE.md**: project facts — the few mechanical facts
|
|
the skills consume (code roots, build/test, tracker slug, …) —
|
|
plus sittenkodex (domain-specific anti-patterns and acceptance
|
|
criteria)
|
|
|
|
## What's out of scope for this plugin
|
|
|
|
- **Issue-tracker integration**: the plugin reads the project's
|
|
issue-tracker commands (the repo slug, list command, and
|
|
single-issue-with-comments command, all in its CLAUDE.md project
|
|
facts) and invokes them, and `specify` may post a reconciliation
|
|
comment or create a seeding issue via the tracker's comment / create
|
|
commands — but the plugin does not directly call Gitea / GitHub /
|
|
Linear APIs. Every read and write goes through the configured shell
|
|
command, so the plugin remains transport-agnostic.
|