Repository navigation
Releases: Atri10/executor
Release list
2.1.1
Patch release — packaging only, no engine behavior changes. The repo is now a Claude Code plugin marketplace.
Added
.claude-plugin/manifests — install from inside Claude Code:/plugin marketplace add Atri10/executor /plugin install executor@executorcommands/— seven slash commands for the verbs a human types:
/executor:new,/executor:next,/executor:status,/executor:decide,
/executor:check,/executor:doctor,/executor:change. Worker traffic
(ingest, repair dispatches) stays inside the skills.- All 13 skills load unchanged; the engine stays bundled inside the
executorskill, so Python 3.11+ remains the only requirement.
Verified
claude plugin validate .clean;sync_engine.py --checkin sync;
validate_skills.pyclean.- 163 tests across
test_cli/test_store/test_layout_v2green
(version-sensitive modules). - Engine logic unchanged from v2.1.0: full 828-test suite measured at
100.00% branch coverage on that release.
2.1.0
An evidence-first audit of the engine against a live 325-event initiative,
and the three structural changes it demanded. Every defect in the register
carries the file and line, the observed behaviour, the command that
reproduces it, and the test that now covers it.
What was wrong
- A worker could latch a halt while
executor deciderefused one. - A commit on an unrelated branch satisfied "the work advanced" — the
ancestry check never required the dispatch base to be a descendant of the
reported head. - The
reviewphase was inert: the whole-plan final audit two documents
promised never dispatched. - No projection was reproducible (wall-clock stamps), so a drift check
and a byte-idempotent migration were both impossible. state.jsonwas 2.76 MB and rewritten whole on every event — 469.7 MB
written over 320 projections, because the fold carried every artifact body.- A constraint could not change mid-run, and the fold had no task →
requirement link at all, so a blast radius could only have been prose. - 37 prose/code divergences; the ones needing code are in the register, the
rest are prose corrections in the same change set.
What shipped
Store layout v2 — a views tree with index.md at its root and one leaf
per plan and per task; plan.json is an index and each task contract is
tasks/<TASK-ID>/task.json in both stores; artifact instances are minted per
kind and an arch may declare components for per-component designs;
slot.json deleted; deterministic projections; the committed index is written
mid-run and verified against a re-render; check also reports a missing
canonical file. The fold cache keeps decisions, not bodies: state.json
2.4 MB → 1.10 MB, bytes written over the run 470 MB → 160 MB
(scripts/measure_store.py prints the curve).
Mid-run change protocol — a journaled, ID-bearing change_request
(executor change <file|->, --list); the engine mints CR-NNNN, computes
the blast radius from fold dependency data (depends_on, cites,
requirement/constraint/criterion ids) with a reported coarse fallback, and
drives a regression lane — revise, re-audit, re-dispatch, re-prove, apply —
that is a pure function of the fold, waits for in-flight dispatches and
pending gates, and is withdrawn by a ruling. change_not_applied verifies the
redraft really carries the change.
Git discipline, enforced — six rules with rejection codes and
clear-the-path hints (descent, base-branch purity, branch ownership, merge
ancestry, merge branch, commit subjects), enforced only for dispatches this
engine minted (rules: v2), so an upgrade never rejects work it inherited.
Command surface — executor change, executor migrate --dry-run|--apply,
a policy: and open-change: line in status, rulings in
views/progress.md, abandoned labelled honestly, sk- keys scanned.
Migration
A store written by 2.0.x is refused by the writer (store_outdated)
rather than half-converted:
executor migrate --dry-run # every write and removal, touching nothing
executor migrate --apply # convert, verify, stamp store_version v2
Deterministic and byte-idempotent: a second --apply rewrites identical bytes
and removes nothing. scripts/migrate_layout.py is the same implementation
from the command line.
Evidence
scripts/run_tests.py → 828 tests, TOTAL 100.00%
scripts/sync_engine.py --check → bundled engine: in sync
scripts/validate_skills.py → skill validation: all clean
scripts/lint-prompt-injection.py skills/ → prompt-injection lint: clean
The reference corpus (a copy; the live store belongs to a sibling project) was
migrated with 139 writes and 13 removals, verified, then re-applied
byte-identically across 658 files; executor check reports chain: ok and
zero store problems.
Breaking changes
- Store layout: 2.0.x stores must be migrated before the writer accepts
them (store_outdatednames the command). haltis human-only;executor ingestrefuses it.mergenow requiresbranch(plan/<PLAN-ID>orinitiative/<INIT-ID>)
and must contain every task head of the plan.slot.jsonis gone from the grammar; the flat per-round verdict views are
gone (a task's rounds live in its one view leaf).- Payload additions are optional only (
task.requirements/constraints,
report.branch,arch.components,design.component,change_request).
2.0.3
Patch release: the Windows suite goes green. The v2.0.2 install path was correct on POSIX, but the matrix — and the main-branch run that followed — exposed three failures: --help crashed under the cp1252 pipe encoding, a test tried to execute the launcher as a native program, which Windows cannot do, and the bundle check trusted a whole-second timestamp cache instead of the bytes.
If you are on v2.0.2 with Windows, upgrade: executor --help and executor new with a non-Latin title can crash or the suite can flake there.
Fixed
- CLI output is UTF-8 even when Windows redirects it. A pipe inherits the locale code page, and
print(__doc__)raisedUnicodeEncodeErroron the help arrow before it could print a line.mainnow reconfigures stdout and stderr where the stream supports it, so help text, JSON withensure_ascii=False, and error messages survive a redirect on a non-UTF-8 Windows console. - The bundle check compares bytes, not cached metadata.
filecmp.cmpkeys its verdict onint(st_mtime), so a drift check that followed a same-second rewrite could report a file stale that had just been synced.scripts/sync_engine.pynow compares contents directly, and a regression test pins the same-second case with a forced mtime. - The bare-launcher test is POSIX-only. Windows has no exec bit and
CreateProcesscannot run a.pyfile without a registered association. The portable spelling —python3 <skill-base-dir>/scripts/executor— remains the tested, documented form on every platform.
Install
npx skills add Atri10/executor
python3 ~/.agents/skills/executor/scripts/executor --version # 2.0.3~/.agents/skills/ is the global install location; use ./.agents/skills/ for a project-local install.
v2.0.2 — An Install Is a Complete Install
Patch release: the engine ships with the skill. Installing the skills used to leave executor undefined — the skills call a bare command that only existed for someone who had cloned the repository and exported PYTHONPATH. Now the engine travels inside the router skill and a launcher beside it resolves the copy relative to itself, so an install needs no path setup at all.
Fixed — an install is now a complete install
- The engine ships inside
skills/executor/.npx skills addcopies a skill directory and nothing outside it, soengine/executor/— a sibling ofskills/— never reached a user. The package now also lives atskills/executor/scripts/lib/executor/, which the installer copies, andskills/executor/scripts/executoris the launcher the skills name. - No
PYTHONPATH, nopip, noPATHedit. The launcher resolvesscripts/lib/from__file__, so it works from any project directory. Python 3.11+ is the only requirement; the engine remains standard library only. scripts/sync_engine.pyis the one writer of the shipped copy, and--checkis a CI gate.engine/executor/stays the source the suite tests; the bundle is generated, so a hand edit to either side failstest_engine_ships_with_skill.pyrather than shipping an engine the repository never tested.- A real install is exercised in CI, not just the repository layout: the skill is copied out of the tree,
PYTHONPATHis dropped, and the launcher runs from an unrelated directory.
Changed — the documents name the command a reader can run
- Every skill states the spelling.
executor <verb>is defined once in the router and restated at the top of each phase skill, so loadingexecutor-executiondirectly no longer leaves an agent to guess at an executable that is not onPATH. - Engine source citations point inside the skill. The references cited
engine/executor/paths.pyandschemas.py— paths an installed user does not have. They now citescripts/lib/executor/, which exists wherever the skill was copied. A test walks the skills tree to keep it that way. - The README install section is the install path. The
PYTHONPATHstep, the one-paste prompt's profile edit, and thepython3 -m executorexamples are replaced by the launcher; working from a clone is documented separately, wherePYTHONPATHis still the honest spelling. CONTRIBUTING.mddescribes this repository. It documentedexec-scan-secrets,validate-skills.sh,test-executor.sh, and a ShellCheck gate — all deleted in the v2 shell-to-Python cutover. The file now names the Python entry points, the 100% branch floor, the bundle rule, and the CI jobs that actually exist.
Install
npx skills add Atri10/executor
python3 ~/.agents/skills/executor/scripts/executor --version # 2.0.2~/.agents/skills/ is the global install location; use ./.agents/skills/ for a project-local install.
v2.0.1 — Concordance
Patch release on top of v2.0.0: the documents say what the engine enforces.
Changed
- The README's merge contract is the slot-free payload ingest actually verifies.
MERGEis emitted once every task in the plan is complete; the action names the plan and each task's head commit; ingest checks the plan is known and unmerged, every task complete, and themerge_sharesolves. The old text claimed a minted slot, arespond_topath, a dispatch binding, and a descent check the engine does not perform. - The exit-code contract names refusals. A payload refusal exits 2, like usage and engine errors; 1 is a check that found problems — corrected in the README and in
cli.py's own docstring. references/branches.mdstops claiming a descent check. The merge bullet lists what ingest verifies; "descends from the plan's head" moves to the procedural list, where it is the skill's job.- Counts catch up with the code. 48 documented refusal codes (was 37) and 722 tests (was 717), in the README and the 2.0.0 changelog entry; a duplicated changelog heading is gone; the shipped v2 entries are folded under 2.0.0 instead of sitting under
Unreleased; the README's CI and store-map rows describe the three-OS matrix and this repo's ignoreddocs/.
Verified
scripts/run_tests.py: 722 passed, 0 failed — 100.00% branch coverage.- CI on
main: all five checks green — ubuntu, macOS, Windows; skill contract + prompt lint; secret scan (both stores).
Full Changelog: v2.0.0...v2.0.1
New Dawn
New Dawn
The executor v2 engine becomes the product. A payload is data and the engine renders every document; the shell scripts are gone; the skills speak the v2 protocol; a payload that means nonsense is refused before it lands.
What changed
- Payloads are data. Sections carry
prose,bullets,tables(columns+rows), andcode. No string in a payload may carry markdown syntax — a pipe table, a fence, or a heading isnotMatch; a row wider than its columns isrow_width; a blank value isnonBlank; a section with no shape isempty_section;sections[].idis unique because a reviewer cites it.engine._render_docis the only writer of document markdown, so the store has exactly one renderer. - Contracts are enforced, not hoped for.
schemas.pyis a closed mini-validator with anchored patterns, back-references tying a task to its plan, numeric bounds pinned by a literal table, named object invariants, and 37 documented refusal codes thattest_docs_agreement.pykeeps in step with the code in both directions. A newreferences/rejections.mdlists every code with its field and the action that clears it. - The store has one writer. The journal is the state — hash-chained, and recomputed by
check, which refuses a store edited by hand. Views are projections. A dispatch is answered exactly once.executor decideexists sogate_decision,ruling, andresumecarryactor: human; a worker cannot approve its own work. - Autonomy is fail-closed. Every phase defaults to
deny; every ambiguity — a missing file, an unlisted phase, a typo'd mode — resolves todeny. The pick-class phases and handoff never clear automatically. An auto-cleared gate is journaled asby: "auto", visibly distinct from a humanpassed. - Plans are audited as a set between planning and execution — coverage, seam closure, ordering, constraint propagation, file ownership. Execution cannot start until every plan is clean or a human waives a finding by
ruling. - Evidence is capability-aware. The verifier records the strongest feasible evidence per criterion, or an explicit
unavailablewith a named blocker — never a claim.executor statuscounts every criterion proven / failed / unavailable / unanswered, because a criterion nobody ran is unproven however obviously it must work. - Cross-platform for real, not by assertion. CI runs the suite on Ubuntu, macOS and Windows. That matrix earned its place immediately: it found a validator that disagreed with itself about path separators, a store lock whose contended acquire held a descriptor for the OS's own retry window, and a linter whose CRLF handling changed line numbers. All three are fixed, and the tree now carries tests that pin each so they cannot return.
Measured, not claimed
| Gate | Result |
|---|---|
| Tests | 722 tests, OK |
| Branch coverage | 100.00% — 2200 statements, 926 branches, 0 missed, 0 partial |
| Mutation | schemas.py 260 mutants, 254 caught, 6 equivalent survivors allow-listed with reasons |
| OS matrix | ubuntu, macos, windows — all green |
| Validators | validate_skills.py exit 0 · lint-prompt-injection.py exit 0 |
Install
npx skills add Atri10/executor
export PYTHONPATH=<clone>/engine
python3 -m executor --version # 2.0.0The engine has no runtime dependencies beyond the standard library. The README is the single design document: the protocol, the reasoning behind each invariant, and the flows that drive it.
v0.7.1 — The Store Helpers Stop Inventing Roots
Patch release on top of v0.7.0.
Fixed
exec_docs_store/exec_run_storeinvented a filesystem root outside a repository. Written asecho "$(exec_root)/docs/executor", the command substitution swallowedexec_root's death — the subshell exited,$( )yielded empty, andechostill succeeded — so the helpers printed/docs/executorand/.executor. Callers then globbed the filesystem root via"$store"/*/INDEX.md. Both helpers now propagate the failure;exec-statusrefuses with "not inside a git repository" instead of printing a digest that reads like an empty project;exec-stepandexec-graphguard their store globs. Found by running the README's own install-verification command in a bare directory — where a fresh install actually runs it.exec-graphdid not parse under bash 3.2. Acasestatement directly inside$( … )is a syntax error on the stock macOS shell (/bin/bash3.2), which is what themacos-latestCI runner uses. The case is hoisted into a function; the suite now runs/bin/bash -nover every shipped script as a parse gate, separate from the existing bash-4-construct grep.
Changed
- Docs describe the scripted write path. The README script table gains
exec,exec-dispatch,exec-ladder,exec-seen,exec-heartbeat,exec-prompt,exec-adjudicate,exec-present,exec-status,exec-graph; the task-loop and shape-of-run diagrams use the current verbs; the execution skill's dispatch table is the real nine-column schema with the write path named; the report-status table routesDONE/DONE_WITH_CONCERNSmechanically and handsBLOCKEDto the SUPERVISOR instead of the controller.
Verified
scripts/test-executor.sh: 145 passed, 0 failed — under bash 5.3 and under/bin/bash3.2. Four new tests cover the store-root defect class.- CI on
main: all six jobs green (macOS + Ubuntu).
v0.7.0 — The Scripted Write Path
Every state mutation the controller used to perform by hand is now a script call behind one exec front door. The engine's core claim — the controller holds no state and makes no judgment — now holds on the write path, not just the read path.
The front door
exec # resume digest: every in-flight run, its next verb, open rows, store drift
exec verbs # the decision table, generated from the machine-readable registry
exec step # any exec-* script by nameAdded
exec-dispatch— one locked act: mints the agent ID, builds the role's input file, marks the ledger, appends the dispatches.md row, renders a bracket-clean prompt.exec-ladder—revive/redispatchrewritesrevived-rvNcells and enforcesEXEC_MAX_REVIVEitself.exec-seen,exec-heartbeat— the two liveness witnesses thatexec-superviseactually consumes.exec-prompt— renders any role template; refuses while a[UPPER_SNAKE]bracket remains unfilled.exec-adjudicate— assembles the adjudication evidence pack mechanically, then dispatches SUPERVISOR. The adjudicated party no longer selects the adjudicator's evidence.exec-present— the fixed-shape gate card for PHASE-GATE; artifact bytes never enter the pump's context.exec-status— one-file resume digest;--writestamps.executor/RESUME.mdso a cold agent reorients in one read.exec-graph check— every verb has exactly one actuator row, every ledger file has a script writer, every role template resolves, every ID grammar carries placeholders, every reference resolves. A dangling reference is a FAIL, not a NOTE.exec-stepverbs —RUN-START,REVIEW,FIX,CRITIQUE;REPORTnarrows to verdict-clean; every emit carries a(wake on …)condition.exec-initiative phase … check— dry-run gate validation that writes nothing.
Fixed
- REPORT livelock — a report with a reviewer in flight emits
WAITindefinitely instead of three identicalREPORTs and anADJUDICATE loopon a healthy run. - Worker status routing — report
result:frontmatter routesblocked→ ADJUDICATE,needs-context→ ASK. A finished worker can no longer silently burn revive rungs. exec_product_exists— crashed BSD/bash-3.2 runs on glob specs; supervisor zombies now report instead of dying.exec-report— refreshes the registry's Tasks cell inside its own store lock (the header had always claimed it did; it never did).exec-gatecheck mode — no longer mutates the phase log it claims to inspect.- bash 3.2 parse —
exec-graph'scaseinside$( )was a syntax error on the stock macOS shell; hoisted out, with a permanent parse gate in the suite.
Verified
scripts/test-executor.sh: 142 passed, 0 failed — under bash 5.3 and under/bin/bash3.2 (the macOS floor).exec-graph check: 50 checks green.- End-to-end on a scratch initiative:
dispatch → heartbeat → suspect → revive → redispatch → report → review → verdict → commit → gate → DONE, with the REPORT livelock proven dead (five consecutive folds during a live review emitWAIT).
0.6.0 Governor
The controller no longer carries the work. The pipeline is two axes of script-driven state with a dispatched subagent at every step that needs judgment, a critique gate on every authoring phase, and a fail-closed path for unattended runs.
Five new scripts, one new skill, 17 prompt templates. 9,633 lines across 52 files.
⚠️ If you installed an earlier v0.6.0The first three v0.6.0 tags shipped
exec-store-checkusing an associative array (declare -A), which is bash 4.0+ only. The scripts use#!/usr/bin/env bash, so on a stock macOS — and on any machine wherebashresolves to the system 3.2 — the script died on that line and every check after it silently never ran. Re-install from this tag if you are on macOS.
Three structural defects this closes
Only 2 of 11 phases could reject a bad deliverable. plan-regression and review dispatched independent critics; design and verification had no artifact gate at all, and architecture and spec ran adversarial self-critiques whose own skills refused the word critic — correctly, since one agent grading its own work is not review.
Upstream drift was structurally undetectable. No reviewer prompt in executor-review ever opened the architecture store, so an implementation satisfying every R-nn and every C-nn while violating the ARCH passed every gate in the system. Adapters importing each other, an ORM row crossing into policy, a seam renamed from its IFCE — there was no seat at which anything could see it. Two seats catch it now: the code component's catalog makes the architecture, IFCE and design stores required inputs, and the final reviewer takes them the same way.
The pump's "never authors" rule had no mechanism behind it. AUTHOR-<phase> was a registered role that nothing ever dispatched. The decision table now says to dispatch it, and the phase-axis loop is written out.
The critique gate
executor-critique generalises the plan-regression contract to all nine authoring components. Each phase's artifacts are audited as a set — the defects worth finding live between documents — and the phase cannot be marked passed until that audit is clean or the human has waived it in writing.
The gate is a script, and it is harder than the stage it generalises from:
verdict: PASSbeside a non-zerohigh/mediumis refused, not believed- the three-round cap is enforced by the script —
audit 04exits 2 - a waiver needs both a note in the row and an initiative ruling naming the artifact
- an empty clearance is not a cleared one
Adding a component is a registry row and a catalog section, not a script. plans proves it: it resolves to the pre-existing plan-regression/ home and reads the same summary.md — one gate, two front doors, not two gates that can disagree.
Unattended runs
exec-gate INIT PHASE --auto clears a gate only when the initiative's autonomous.md permits it, and every ambiguity resolves to deny — no policy file, enabled: false, an unlisted phase, a mode spelled wrong. A typo in a table cell must not become an unattended phase gate. Pick-class phases still require a scored verdict on disk, because a script can count files but cannot choose between designs.
An auto-pass records as **auto-passed**, visibly distinct from a human passed, and a human who disagrees overturns it with one command.
Cross-platform correctness
Four defects that behaved differently across environments while failing silently — each found by running on the environment it actually breaks on, never by reasoning about it:
- bash 3.2 —
declare -Ainexec-store-checkis bash 4.0+, and#!/usr/bin/env bashresolves to the stock macOS 3.2. Underset -ethe script died there, so every check after it never ran. The only bash 4+ construct in the codebase; replaced with a newline-delimited set. - Worker liveness — BSD's
date -j -fignores the date it was handed and returns roughly now; GNU's-dparses it. The same dispatch row readaliveon macOS anddeadhours later on Ubuntu. A false DEAD verdict burns a revive rung and replaces an agent still holding its context. validate-skills— the box-drawing check used a multibyte bracket expression. mawk is byte-oriented, so an em-dash in prose matched. The validator passed on macOS and failed on every Linux runner.exec-store-checktimestamps — BSD'sdate -j -fneeds-u; the offset cancelled in its current call sites, so nothing was broken today, but it was a trap for the next caller.
script-smoke now runs on an [ubuntu-latest, macos-latest] matrix, and the suite prints a toolchain banner so a CI log carries the environment it ran against. A Linux-only job catches these only when the author is on Linux; a macOS-only one never would have.
Every dispatch prompt now covers its edge cases
A prompt is the only definition of what a subagent does, so an undefined state is an unreviewed behaviour. Measured before: one prompt in seventeen had preconditions, none had a refusal channel, none handled a file left behind by an aborted prior run. All seventeen now define their preconditions, edge cases, refusal path, and output-file collisions.
Two bugs worth calling out. component-reauditor-prompt.md hardcoded R01/R02 while claiming R02+, so an R03 dispatch would have written R03's findings into R02's file — the loop would have reported progress it never made. And design-critic-prompt.md required a ranking while stating "you do not pick the winner", pre-empting the human's choice with an unreviewable judgment.
Upgrade notes
This release rewrote main's history to sign every commit. If you cloned before, run git fetch && git reset --hard origin/main — the old commits are gone from every branch.
All commits on main carry verified signatures, as does the v0.6.0 tag.
Verification
123 regression tests, validate-skills, prompt-injection lint, and shellcheck -S warning — all clean on bash 3.2, bash 5, macOS and ubuntu 24.04.
0.5.1 Burnish
Hygiene release — headers, rename, self-contained comments
No behavior changes. Every code file now carries its license, the regression suite has a name that says what it tests, and comments describe the failures they guard against instead of citing closed issue numbers.
Changed
- SPDX headers on all 20 code files — 16 executor scripts, 3 repo scripts, the CI workflow:
# SPDX-License-Identifier: MIT+# Copyright (c) 2026 Atri10, matching LICENSE. Markdown is deliberately left alone: the root LICENSE covers it, and an HTML comment at the top of files agents read is context noise for zero protection. scripts/test-issue9-fixes.sh→scripts/test-executor.sh— the old name referenced a closed issue; the suite covers the executor scripts' contracts. CI, CONTRIBUTING, and the CHANGELOG updated with it.
Fixed
- Stale comments made self-contained — three
issue #Nreferences (inexec-plan-lint,exec-run, and the planning skill's lint description) now describe the failure they guard against: a guessed store path breaks the moment the workspace moves; a completion line without a verdict is an unjudged claim. - Stale documentation — CONTRIBUTING's layout table no longer lists a
docs/directory (the repo keeps none; normative content lives inskills/executor/references/), its references list gainedbranches.mdandtest-quality.md, and its contract-update rule names the branch model. The README'sexec-branchandexec-run checkrows now describe the task/side/spike subcommands and the topology audit.
Verification
Suite 40/40 · validate-skills.sh clean · prompt-injection lint clean · ShellCheck --severity=warning clean · secret scan clean · CI green on every push.
Full diff: v0.5.0...v0.5.1