Releases: jperdior/engineering-loop
Release list
v0.8.0
Fixes the findings of the second end-to-end run (#14).
- The telemetry table drops its cost column:
session | turns | peak context | wall clock | model. launch.shnames the run log after the main checkout, not the worktree directory./shipfilters the run log on the loop's owndelivery-loop:prefix and relays only ticks, pause, escalation, PR and exit.- The review's fix wave stays inside the spec's scope; a finding against a host skill or doc the spec did not name is written as a proposal, not applied.
/shipalways writes the spec with the engine'sspec-writing, reading a host spec skill as input for the host's conventions; the loop reads a grammar only ours writes.- Every skill says the engine's skills are invoked as
/engineering-loop:<name>. /code-reviewreads the gates from the spec, else the host'sAGENTS.md.
Upgrade: /plugin update engineering-loop@engineering-loop, then start a new session.
v0.7.0
Fixes the eleven findings of the first end-to-end run (#13).
loop/launch.shstarts the loop detached with one plain command;/shipuses it. Log under~/.local/state/engineering-loop/runs/, ending indelivery-loop: exit N.- The bell no longer prints
Device not configuredwhen the run is detached. - Pre-flight probes
gh api repos/<owner/repo>and refuses a token that cannot see the repository, naming the settings file and itsGH_TOKEN=line. setup-loop.shwithout a TTY names the file and lines to set, and says a Claude Code!command is not a terminal.- The superpowers lookup follows
CLAUDE_CONFIG_DIR. - The pre-PR telemetry omits the PR row instead of writing an empty cell into the PR body.
/shipwatches the run log with a monitor and a timer, relays only ticks, pause, escalation, PR and exit, and reads telemetry from the state directory./spec-writingsizes the spec to the change (**Size:** bounded | fullin the TLDR; six sections for bounded), proposes a fix to a host skill in the way rather than arguing around it, and fails a section left to the template./pre-implement-specruns one audit agent for a bounded spec, four for a full one, and never builds to audit.
Upgrade: /plugin update engineering-loop@engineering-loop, then start a new session.
v0.6.1
/ship is back in the slash-command index
The ship skill's description contained a colon followed by a space inside an unquoted YAML value, which is a parse error; Claude Code drops a skill whose frontmatter does not parse and says nothing, so a fresh session found nine skills and No commands match "/engineering-loop:ship". Every skill description is now a double-quoted scalar, and tests/test-skills-frontmatter.sh parses each one with a strict reader in CI.
PR #12.
v0.6.0
An independent plugin
Nothing of the engine lives in the host repository. Installing is three lines in Claude Code:
/plugin marketplace add jperdior/engineering-loop
/plugin install engineering-loop@engineering-loop
/plugin install superpowers@claude-plugins-official
- The loop scripts ship inside the plugin, beside the skills. The loop resolves the repository from the directory it is run in.
- Your settings live in
~/.config/engineering-loop/loop.env(setup-loop.shwrites the sandbox tokens there); the loop's state — lock, unit directories, the worktrees it creates, the telemetry — under~/.local/state/engineering-loop/<repo>/. - The telemetry leaves the branch: its table goes into the PR body under Sessions.
- The only local trace in a repository is
.claude/worktrees/in.git/info/exclude, never committed. - The sandbox mounts the plugin, and superpowers when installed, read-only and starts the session with
--plugin-dir. install.shis gone, and so is the vendored.loop/.
Upgrade
Delete .loop/, the ten .claude/skills/ symlinks into it and the .loop/ lines in .gitignore; move .loop/loop.env to ~/.config/engineering-loop/loop.env; install the plugin.
PR #11.
v0.5.0
The host contract lives in the spec
The gates, the per-worktree cleanup, the generated paths and the extra denials are facts about the host and change with it. They are no longer configured anywhere: /spec-writing derives them from the host's AGENTS.md / CLAUDE.md into every spec's ## Gates section, the human approves them at gate 1 with the rest of the spec, and the loop reads them from the branch like the phases.
parse-ledger.sh --gatesand--host cleanup|excludes|denialsread the section with the ledger's strictness.- The loop refuses a spec that declares no gates, reports where its gates came from in
--dry-run, and hands the cleanup to the reclaim and the denials to every session. host.env,host.env.distand theLOOP_*contract keys are gone;install.shremoves a stale template from hosts.
/ship drives the loop from the chat
Phase B starts the loop detached — its own process group, a log under ~/.loop-runs/ — so the run outlives the chat session and the tool-call timeout, then watches the log and relays each event: a phase built, a pause, an escalation, the PR. The terminal commands remain the overnight-over-SSH option.
/ship checks credentials first
gh auth status, jq, timeout; under LOOP_SANDBOX=1 it runs .loop/setup-loop.sh --show and sends the user to the script for a missing token. It never asks for a token in the chat.
A shorter README
Cut from 345 lines to 125: what it does, install, use, what your repository must state, when it stops, settings, the skills. The internals live in the script headers and the skills.
Upgrade from 0.4.0
Delete .loop/host.env and re-run install.sh. Specs written before this need a ## Gates section before the loop will build them.
v0.4.0
The host contract is committed, and found out from the host's own docs
LOOP_GATES, LOOP_CLEAN_WORKTREE, LOOP_SIZE_EXCLUDES and LOOP_DENIALS_EXTRA are facts about the repository, the same for everyone who builds in it. They move out of the gitignored .loop/loop.env into a committed .loop/host.env, reviewed like any other file.
- The loop reads
host.envbeforeloop.env; the shell still overrides both.--dry-runreports where the gates came from. - There is no default gate. A repository that declares none is refused at pre-flight, naming the file.
- The agent finds it out.
/shipgains a step 0: whenhost.envis missing or names no gates, it reads the host'sAGENTS.md/CLAUDE.md, derives the four values from what the host documents, shows each line beside the sentence it came from, and commits the file on the feature branch./run-gatesderives the gates the same way when the file is missing and says so; it never invents a default. loop.envkeeps what is personal: the two sandbox credentials,LOOP_MODEL,LOOP_SANDBOX, the bounds.reclaim-worktree.shandunit-size.shreadhost.envfirst;install.shvendorshost.env.distand leaveshost.envalone.
Upgrade from 0.3.0
Move the four host lines from .loop/loop.env into a committed .loop/host.env (format in .loop/host.env.dist), or let the next /ship write it. Until then pre-flight refuses with the file's name.
v0.3.0
A stop keeps the phase
A session refused for the usage limit, killed, or exited without a sentinel leaves its half-built phase uncommitted in the worktree. The loop now records which session it launched before launching it and a re-run continues that session with claude --resume in the worktree it left. A transcript that is gone falls back to a fresh session told the tree holds a predecessor's work. Only the done path reclaims a worktree the loop created; exits 4 and 5 keep it and say so.
- Builds where it is driven from. From a linked worktree already on the unit's branch, the loop builds in that tree: no second worktree, no checkout, no reclaim. Its state hangs off the main checkout's
.loop/state;loop.envis read from the driver first and the main checkout second. - One loop per unit, several per repository. The lock is
lock/<branch>/, liveness matches the recorded snapshot path, andgit worktree addis serialised on a config lock. - Named, killable session containers under the sandbox, with a cid the teardown kills by; the container sees the common git directory and the unit's own directory only.
- A resumed closing step does not repeat the earlier ones.
/ship: gate 1 is your spoken OK on the spec in the worktree. No spec PR.
A phase names the host skills it builds through
Each phase's ### Phase N section carries a - **Skills:** line naming the host's own skills the phase must use — its scaffolds, test runners, linters — resolved by /spec-writing from the host's skill index (the router table in the root AGENTS.md, else the descriptions under .claude/skills/). parse-ledger.sh --skills "Phase N" reads it, the loop hands the names to the session as a Skills: prompt line and lists them in --dry-run, /implement-spec invokes them before writing, and /pre-implement-spec fails a name that resolves to nothing.
Upgrade
Re-run install.sh in the host. State moves to .loop/state/units/<branch>/; a pre-0.3 repository-wide lock/pid is respected while alive and swept when dead.