Skip to content

Loop mode: /allium drives the whole loop to convergence#54

Merged
yavorpanayotov merged 20 commits into
mainfrom
loop-mode
Jul 3, 2026
Merged

Loop mode: /allium drives the whole loop to convergence#54
yavorpanayotov merged 20 commits into
mainfrom
loop-mode

Conversation

@yavorpanayotov

@yavorpanayotov yavorpanayotov commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Why

Allium's full value is the loop — spec → tests → code driven to agreement — but reaching it used to mean orchestrating several skills by hand. This PR makes the loop the default: give /allium a goal and it drives the whole loop to convergence. One command, and not even a new one — the tool's existing front door now takes a goal.

What

/allium <goal> drives the loop — the allium entry-point skill now runs the loop itself: entry-point detection → per-tick gather/act/verify/route → convergence invariant → stop conditions (6 hard / 2 no-progress / escalate, anti-cheat) → open-question park-vs-escalate → decomposition + integration pass → phase isolation → git-ignored ledger → real-verification guardrails. Layer 1 (in-session); unattended re-invocation (Layer 2) is documented as future work.

Driver procedure lives in skills/allium/references/driving-the-loop.md, which the allium skill follows. There is no separate /allium:loop command and no standalone loop skill — the loop is /allium.

Entry point/allium biases toward the autonomous path: drive the whole loop for a goal/feature, direct-route a clear single task, and present the menu-with-hints (with a recommended starting point) only when the request is bare or ambiguous. Plus the standing nudge to suggest the next phase after a single skill finishes.

Docs — the README "The Allium loop" section + "loop in motion" transcript; the recommended-loops.md reference (gather → act → verify → repeat, spec-first and code-first walkthroughs, the convergence invariant); README skills table + count updated (five skills plus the /allium entry point).

Test hardening (scripts/test-skills.mjs) — offline groups, each mutation-verified to fail on a real break:

  • consistency — version parity across manifests; skill registration identical across skills/, the test registry, and the .claude-plugin skills[] array.
  • broadened links — checks README, all references/*.md, and design notes.
  • loopdocs — the caps (6 / 2) and phase phrase stay consistent across the docs that restate them (now including driving-the-loop.md).
  • hookshooks.json is valid, has a matcher, and points at a script that exists.

Version — manifests at 3.7.0.

Validation

node scripts/test-skills.mjs89 passed, 0 failed, 3 skipped (the 3 need --live). generate-multi-editor.mjs --check clean. CI runs the offline suite on every push.

Note for the marketplace re-vendor (follow-up)

design/loop-mode.md and design/loop-mode-local-testing.md are internal design notes (now carrying "superseded" banners). Per their lifecycle, they should not ship to end users — when re-vendoring to juxt/claude-plugins, exclude design/ from sync-allium.sh so they don't land in the published plugin.

🤖 Generated with Claude Code

yavorpanayotov and others added 15 commits June 23, 2026 16:49
- recommended-loops.md: a single-prompt invocation for spec-first and
  code-first, with the stop conditions (6-iteration hard cap, 2-iteration
  no-progress cap, escalate-on-open-question). Notes there is no separate
  "loop mode" — it's a structured prompt over the existing skills.
- README: a "loop in motion" roleplay transcript under "What this looks
  like in practice", matching the existing style.

Staged on a branch; not released yet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Persist the loop-mode design sketch: the two layers (in-session procedure
vs unattended re-invocation), entry-point detection, the tick, the
verification harness, stop conditions, and a ledger in a dotfile.

Captures two design considerations raised in review:
- Nested loops: elicit's Q&A is an inner loop of the gather phase (and
  distill multi-pass / TDD are inner loops too); the model must support
  loops-within-loops with per-phase exit conditions.
- Open-question scheduling: classify blocking/direction-changing (escalate
  eagerly, avoid throwaway) vs non-blocking/peripheral (park and batch for
  autonomy); elicit's inner loop front-loads the structural questions.

Status: proposed, not implemented. Living doc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve open questions from review:
- Ledger dotfile is git-ignored (auto-added to .gitignore on first use).
- No auto-commit by default — leave the working tree to the user.
- Orchestration delegates phases to skills/agents (not inlined) for DRY,
  agentic composition, and context isolation that keeps long runs in budget.
- Auto-decompose large goals and run autonomously, with one consolidated
  summary at the end; blocking questions still escalate mid-run.
- Caps are overridable defaults (per-invocation flags and config).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Internal design note, not user-facing: retire when /allium:loop ships
(content graduates into the skill + recommended-loops reference), and keep
it out of the vendored plugin until then.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- New "Decomposition & roll-up" section: split along Allium's structural
  seams (entity lifecycle / surface / rule chain), order by the data-flow
  graph, add a whole-spec integration pass so cross-slice seams converge,
  and roll sub-goal mini-reports into one final summary.
- Decision: phases share state through artefacts + ledger only (derived
  data is regenerable/cached; sub-agent return values must be persisted).
- Expand the ledger .gitignore mechanics for non-repos, monorepos,
  already-ignored, and read-only cases (best-effort, mention once).
- "Still open" is now cleared pending the build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New skills/loop/SKILL.md drives the loop to convergence: entry-point
detection, the per-tick procedure (gather → act → verify → route),
convergence invariant, stop conditions (6 / 2 / escalate, anti-cheat),
open-question park-vs-escalate, decomposition + integration pass,
phase isolation, the git-ignored ledger, and real-verification guardrails.

- Register ./skills/loop in .claude-plugin (codex picks it up via ./skills/).
- Add loop to the router routing table + a pointer from the loop section.
- Add loop to the test-skills skill registry.
- Mark the design note status as MVP built.

Validation: node scripts/test-skills.mjs -> 60 passed, 0 failed;
generate-multi-editor.mjs --check clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
elicit and distill are human-in-the-loop, so each splits into the existing
user-facing interactive skill plus an internal isolated worker the loop
spawns. The worker runs in its own context and returns open questions; the
orchestrator escalates them, writes answers to the spec/ledger, and
re-spawns the worker. propagate stays a plain non-interactive worker.
Workers are loop-internal by convention (not enforced — no per-caller ACL).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New 'consistency' group:
- version parity between .claude-plugin and .codex-plugin manifests
- skill registration is identical across skills/ dirs, the test skillNames
  registry, and the .claude-plugin skills[] array (catches a skill that is
  built but never registered — would otherwise ship broken with tests green)

Broadened the 'links' group to also check prose docs (README, all
references/*.md, design notes) via a permissive resolver that catches bare
relative paths, not just ./ and ../ links.

All three verified to fail on mutation and pass after revert. Suite: 78 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- loopdocs group: the loop caps (6 / 2) and the phase phrase
  "gather context → take action → verify → repeat" must stay consistent
  across the docs that restate them (loop skill, recommended-loops, router,
  design note) and README (verb form, checked in order). Canonical values
  live in the test (Option A).
- hooks group: hooks/hooks.json is valid JSON, has a PostToolUse entry with
  a matcher, and its command points at a script that exists.

Both verified to fail on mutation and pass after revert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adding the loop skill left the README stale: bump "five skills" to six and
add a /loop row to the Skills and agents table so it appears in the
human-facing menu, not just the routing table.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The biggest adoption gap is that the full value needs orchestrating several
skills, so people dabble in one or two. Bias the entry point toward the
autonomous path: recommend driving the whole loop (/allium:loop) by default,
direct-route clear single tasks, and only present the menu-with-hints when
the request is bare or ambiguous — leading with the loop and offering the
individual skills as the control path.

- Router: new "Responding to /allium (loop-first)" section.
- README: entry-point row and getting-started prose reflect loop-first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Minor bump for loop mode: the /allium:loop skill and the loop-first entry
point, plus the loop docs and test hardening.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The entry path is detected from project state AND goal intent, announced in
one line (naming the override), then run without a blocking confirmation —
the user interrupts/redirects if it's wrong, or passes an explicit entry.
Clarify that intent (not just file state) decides distill-vs-elicit and
tend-vs-weed. The no-confirm applies to the entry path only; blocking open
questions still pause and escalate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Announce each phase as it begins with a one-line marker
(→ Gather / → Act / → Verify) so a multi-tick run stays legible, while
leaving command-level detail to the harness. Keeps the per-tick summary
and final report. Mirrored in the design note reporting section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per the Allium guidance, .allium specs are checked by allium check on every
edit (hook/LSP), not as a late step. Make the loop faithful: the Gather phase
notes the spec is CLI-checked on edit and must be valid before propagating
(tests are generated from it); Verify focuses on the behavioural checks —
tests, weed (spec↔code drift), and allium analyse (semantic gaps) — rather
than re-running the structural check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@yavorpanayotov

Copy link
Copy Markdown
Collaborator Author

How to use /allium:loop (and what you'll see)

One command drives the whole loop — spec → tests → code, repeating until they agree.

You want to… Run It starts by…
Build a new feature /allium:loop add gift cards to checkout eliciting a spec, then propagate → implement → weed
Work with existing code /allium:loop on an unspecced area distilling a spec, then propagate → run vs code → weed
Just get oriented /allium recommending the loop + a starting point
  • Override the entry if you know better — say distill / tend, or /allium:loop distill <area>.
  • Prefer manual control? Run the phases yourself: /elicit/propagate → implement → /weed, /tend as needs change. (Same loop, hand-driven.)
  • It stops on its own (iteration caps + escalate-on-decision) and never edits a test to fake a pass.

Feedback as it goes — announce-and-proceed, no confirmation gates:

→ No spec here, code present, goal reads as new behaviour → starting with elicit  (say "distill"/"tend" to switch)
→ Gather:  eliciting spec …  (allium check runs on every edit — fix issues before propagating)
→ Act:     propagate tests → confirm RED → implement
→ Verify:  run tests → weed → allium analyse
tick 1 · tests 4/4 · weed clean · openQ 0
✓ Converged — spec, tests and code agree.
  • Entry announcement — what it's starting on (proceeds immediately; interrupt to redirect).
  • Phase markers — one line as each phase begins.
  • Tick summary — tests / weed / open-question counts after each pass.
  • Final report — what converged, anything escalated, leftover questions.
  • Underneath, the harness still shows the real commands (allium check, the test run, file edits) — detail without narrating every line.

Where validation lands (following Allium's continuous-validation model):

  • allium check (spec structure) runs on every spec edit via the hook/LSP — the spec must be valid before propagating, since tests are generated from it.
  • weed (spec ↔ code drift) runs in Verify, once code exists.
  • allium analyse (semantic gaps: dead ends, unreachable states) sharpens elicitation and re-checks the assembled spec in Verify.

Converges when: tests pass and weed is clean and no open questions remain (code-first: also when a fresh distill finds nothing new).

yavorpanayotov and others added 3 commits June 24, 2026 18:03
Document how to load the plugin from a local PR checkout via
--plugin-dir (no marketplace needed, live working-tree edits) and
drive /allium:loop against a throwaway target project. Includes a
spec-first and a bounded track, what to watch for, targeted feedback
prompts, and a known-good reference spec. Linked from the design note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The loop is a skill, so unlike tend/weed it had no editor variant — Copilot
users couldn't run it. Generate .github/prompts/allium-loop.prompt.md from
skills/loop/SKILL.md so VS Code Copilot Chat (Agent mode) surfaces it as
/allium-loop.

Two adaptations beyond adaptBody(), since Copilot lacks two mechanisms the
skill assumes:
- no edit hook / LSP, so the implicit "checked on every edit" becomes an
  explicit "run allium check yourself" instruction;
- reference links are absolutised so the prompt stays valid when copied out
  of this repo into a target project.

Generated, not hand-authored, and covered by test-skills.mjs (structure +
portability + the existing up-to-date guard), so it can't drift from the
skill. Other tools (Claude Code, Codex, Cursor, …) read the unmodified skill
and are unaffected. Docs updated: a Copilot reviewer section in the local
testing recipe and a /allium-loop pointer in the README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The loop is no longer a separate command. The loop skill merges into the
allium entry-point skill, so /allium <goal> drives the whole loop to
convergence; its procedure moves to
skills/allium/references/driving-the-loop.md.

Removes the standalone loop skill, its plugin.json entry, and the redundant
/allium-loop Copilot prompt (plus its generation and tests). Repoints the
loopdocs drift checks, updates the README command table, and adds superseded
banners to the internal design notes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@yavorpanayotov yavorpanayotov changed the title Loop mode: /allium:loop skill + loop-first entry point Loop mode: /allium drives the whole loop to convergence Jul 3, 2026
yavorpanayotov and others added 2 commits July 3, 2026 13:56
Clarify that /allium surfaces as /allium:allium (plugin name == skill name)
so it reads as expected rather than a mistake.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Its recipe referenced the removed /allium-loop Copilot prompt and generation
steps. Drop it and the now-dangling link from the design note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@yavorpanayotov yavorpanayotov merged commit f6b19f5 into main Jul 3, 2026
1 check passed
@yavorpanayotov yavorpanayotov deleted the loop-mode branch July 3, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant