diff --git a/.engineering/planning/task/ess-synthesized-implementation.md b/.engineering/planning/task/ess-synthesized-implementation.md new file mode 100644 index 0000000..f745572 --- /dev/null +++ b/.engineering/planning/task/ess-synthesized-implementation.md @@ -0,0 +1,24 @@ +--- +format: aep.planning-md/3 +id: task:ess-synthesized-implementation +kind: task +status: implemented +title: The ess skills route implementation through synthesized code, so a hand-transcribed model cannot drift +owner: human:timo +revision: 4 +transitions: +- {from: "draft", to: "proposed", at: "2026-09-29T16:35:13Z", actor: "human:timo", revision: 2} +- {from: "proposed", to: "active", at: "2026-09-29T16:35:13Z", actor: "human:timo", revision: 3} +- {from: "active", to: "implemented", at: "2026-09-29T16:36:59Z", actor: "human:timo", revision: 4, decided_on: {"asserted":{"test_result":1}}} +--- +## Outcome +The ess skills tell an implementer to build behind `ess generate synthesize` output and never hand-transcribe the model, and say what to do while synthesis refuses a specification. + +## Scope +`plugins/ess/skills/specifying/SKILL.md` (a section beside "Deterministic projections") and `plugins/ess/skills/testing-conformance/SKILL.md` (what a green suite does not prove). No CLI, agent or eval-runner change. + +## Acceptance +Both sections are present in the released ess plugin; `task check` and `agentplugins-check tools` pass; the wording names no downstream product. + +## Authorization +Interactive user approved the plan on 2026-09-29: skill notes, PR, merge and release. diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e87503..431e6e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [0.19.1] — 2026-09-29 + +The ess skills now say where implementation code comes from: the specification, through +`ess generate synthesize`, and never a hand transcription. A hand-transcribed model passed a +669-scenario conformance suite with every entity field unchecked. + +- `ess:specifying` gains "Implementation code comes from the specification": fill the generated + `…Behavior` and `…Query` obligations, commit the generated tree, and fail the gate when a + regeneration differs. When `synthesize` refuses a specification, file the refusal on + beyond10x/ess; until the fix ships, a hand-written model needs a test that compares it with the + compiled IR field by field. +- `ess:testing-conformance`: a green suite proves only the fields its expectations read, and a + synthesized scenario witnesses one value per `any_of` guard. +- `verified.json` does not move: `agentplugins-check tools` still reports aep 0.65.0 and ess 0.43.0 + as newer than verified, and `aep plan artifact divergences` as not a command of aep 0.65.0. The + commands the new sections spell pass against ess 0.43.0. + ## [0.19.0] — 2026-09-29 A new skill investigates what cannot be re-run: a production incident, an outage, or a question diff --git a/Cargo.lock b/Cargo.lock index b67ef37..df6c904 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "agentplugins-check" -version = "0.19.0" +version = "0.19.1" dependencies = [ "clap", "serde", @@ -76,7 +76,7 @@ dependencies = [ [[package]] name = "b10x" -version = "0.19.0" +version = "0.19.1" dependencies = [ "clap", "serde", diff --git a/Cargo.toml b/Cargo.toml index 8f44224..8b99e32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "2" members = ["crates/agentplugins-check", "crates/b10x"] [workspace.package] -version = "0.19.0" +version = "0.19.1" edition = "2021" rust-version = "1.85" license = "Apache-2.0" diff --git a/plugins/aep/.claude-plugin/plugin.json b/plugins/aep/.claude-plugin/plugin.json index 25f1d9c..44fe649 100644 --- a/plugins/aep/.claude-plugin/plugin.json +++ b/plugins/aep/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "aep", "displayName": "AEP", "description": "Plan governed work in the AEP artifact store and deliver it in reviewed waves: decomposition, plan critique, reverse engineering, story scoping, implementation and adversarial review.", - "version": "0.19.0", + "version": "0.19.1", "author": { "name": "Beyond10x" }, diff --git a/plugins/aep/.codex-plugin/plugin.json b/plugins/aep/.codex-plugin/plugin.json index 5d023a0..1fa977b 100644 --- a/plugins/aep/.codex-plugin/plugin.json +++ b/plugins/aep/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "aep", - "version": "0.19.0", + "version": "0.19.1", "description": "Plan governed work in the AEP artifact store and deliver it in reviewed waves.", "author": { "name": "Beyond10x" diff --git a/plugins/aep/skills/diagnosing/SKILL.md b/plugins/aep/skills/diagnosing/SKILL.md index 048355c..3877205 100644 --- a/plugins/aep/skills/diagnosing/SKILL.md +++ b/plugins/aep/skills/diagnosing/SKILL.md @@ -3,7 +3,7 @@ name: diagnosing description: Diagnose a hard bug or a performance regression by building a red-capable feedback loop before any hypothesis, then ranked falsifiable hypotheses, one-variable probes, a regression test at the right seam, and evidence recorded in the AEP store. Use when the user says diagnose, debug, "why is this failing", "this is slow", or reports something broken, throwing, flaky or slower than before. Not for a production incident that cannot be re-run, which is `aep:investigating`; not for a failing CI job whose cause is already named in its log; and not for raising conformance coverage, which is `ess:testing-conformance`. --- -**Skill version 0.19.0** — the version in `.claude-plugin/plugin.json`. +**Skill version 0.19.1** — the version in `.claude-plugin/plugin.json`. # Diagnosing a failure diff --git a/plugins/aep/skills/implementing/SKILL.md b/plugins/aep/skills/implementing/SKILL.md index b87068f..b880045 100644 --- a/plugins/aep/skills/implementing/SKILL.md +++ b/plugins/aep/skills/implementing/SKILL.md @@ -3,7 +3,7 @@ name: implementing description: Implement accepted AEP work, in one of two modes. A wave picks the stories that can be implemented at once, proposes the wave for approval, dispatches one implementor per story into its own worktree, sends each result to the adversary and merges what goes green. A drive hands one story to a governed `metaharness aep drive` run and reports the run id. Use when the operator asks to implement, build or deliver planned stories, to pick or start the next wave, to implement several stories in parallel or fan out across sub-agents, to drive a story or start a governed run, or asks why a wave's rules are instructions and a drive's are enforced. A wave proposes first and stops; a drive starts one run and reports; neither moves an artifact itself. --- -**Skill version 0.19.0** — the version in `.claude-plugin/plugin.json`; a wave's stage-1 proposal quotes it. +**Skill version 0.19.1** — the version in `.claude-plugin/plugin.json`; a wave's stage-1 proposal quotes it. # Implementing accepted work diff --git a/plugins/aep/skills/investigating/SKILL.md b/plugins/aep/skills/investigating/SKILL.md index c73c9e1..84e13eb 100644 --- a/plugins/aep/skills/investigating/SKILL.md +++ b/plugins/aep/skills/investigating/SKILL.md @@ -4,7 +4,7 @@ description: >- Investigate a production incident, an outage or a question about a running system from evidence that can be cited — capture state before anyone remediates, build a sourced UTC timeline, date an onset from an instrument that can see a negative, compare against a healthy peer, and label every claim verified or inferred, with a catalogue of ten techniques. Use when the user says investigate, "what happened", "when did this start", "is it still happening", "has this shipped", "is this deployed", reports an alert, an outage, a hung or crashing process or a customer-visible failure, or asks for an incident report or a postmortem. Not for a defect that can be reproduced on demand, which is `aep:diagnosing`; not for checking a change before it merges, which is `aep:implementing`. --- -**Skill version 0.19.0** — the version in `.claude-plugin/plugin.json`. +**Skill version 0.19.1** — the version in `.claude-plugin/plugin.json`. # Investigating a live system diff --git a/plugins/aep/skills/migrating/SKILL.md b/plugins/aep/skills/migrating/SKILL.md index 8205570..8e91097 100644 --- a/plugins/aep/skills/migrating/SKILL.md +++ b/plugins/aep/skills/migrating/SKILL.md @@ -3,7 +3,7 @@ name: migrating description: Migrate a repository's legacy work tracking — story trees, TODO.md, plan and issue documents — into the governed AEP planning store, without deleting or rewriting the sources. Use when the user asks to migrate, import, port or convert an existing backlog into AEP, when a repository is adopting AEP and already has work written down somewhere, or when a store has been adopted beside a legacy backlog nobody retired. Read it before creating the first artifact in a repository that already tracks work in markdown. --- -**Skill version 0.19.0** — the version in `.claude-plugin/plugin.json`. +**Skill version 0.19.1** — the version in `.claude-plugin/plugin.json`. # Migrating legacy tracking into the store diff --git a/plugins/aep/skills/planning/SKILL.md b/plugins/aep/skills/planning/SKILL.md index 2075b4b..98614a3 100644 --- a/plugins/aep/skills/planning/SKILL.md +++ b/plugins/aep/skills/planning/SKILL.md @@ -3,7 +3,7 @@ name: planning description: Plan engineering work in a governed markdown artifact store — create, relate, move and validate epics, stories, tasks and initiatives through the `aep` CLI. Use when the user mentions planning, a backlog, an epic, a story, a task, decomposing or breaking down work, an artifact's status ("move this to active", "what is still in draft?", "why can't this be implemented?"), or when the project contains a `.engineering/planning/` directory. Use it at adoption too — the user asks to adopt AEP, to migrate from or replace the track plugin, to start a first backlog, or works in a repository with no `.engineering/` directory at all — because § 5 says how a first store is populated and it is worth nothing after one has been hand-written. Also use before editing any file under `.engineering/planning/`. --- -**Skill version 0.19.0** — the version in `.claude-plugin/plugin.json`. +**Skill version 0.19.1** — the version in `.claude-plugin/plugin.json`. # Planning in a governed artifact store diff --git a/plugins/b10x/.claude-plugin/plugin.json b/plugins/b10x/.claude-plugin/plugin.json index 029b02a..a9a7027 100644 --- a/plugins/b10x/.claude-plugin/plugin.json +++ b/plugins/b10x/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "b10x", "displayName": "Beyond10x", "description": "Set up, upgrade and check the Beyond10x plugins and binaries, route work to them, and create portable plugins.", - "version": "0.19.0", + "version": "0.19.1", "author": { "name": "Beyond10x" }, diff --git a/plugins/b10x/.codex-plugin/plugin.json b/plugins/b10x/.codex-plugin/plugin.json index 8813aca..0ef2df8 100644 --- a/plugins/b10x/.codex-plugin/plugin.json +++ b/plugins/b10x/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "b10x", - "version": "0.19.0", + "version": "0.19.1", "description": "Set up, upgrade and check the Beyond10x plugins and binaries, route work to them, and create portable plugins.", "author": { "name": "Beyond10x" diff --git a/plugins/connectors/.claude-plugin/plugin.json b/plugins/connectors/.claude-plugin/plugin.json index 406eb2e..61a2a1b 100644 --- a/plugins/connectors/.claude-plugin/plugin.json +++ b/plugins/connectors/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "connectors", - "version": "0.19.0", + "version": "0.19.1", "description": "Set up, inspect, and invoke governed integrations through the connectors CLI.", "author": { "name": "Beyond10x" }, "license": "Apache-2.0", diff --git a/plugins/connectors/.codex-plugin/plugin.json b/plugins/connectors/.codex-plugin/plugin.json index 101bee2..3e24209 100644 --- a/plugins/connectors/.codex-plugin/plugin.json +++ b/plugins/connectors/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "connectors", - "version": "0.19.0", + "version": "0.19.1", "description": "Set up, inspect, and invoke governed integrations through the connectors CLI.", "author": { "name": "Beyond10x" }, "license": "Apache-2.0", diff --git a/plugins/ess/.claude-plugin/plugin.json b/plugins/ess/.claude-plugin/plugin.json index c89e778..85f5c23 100644 --- a/plugins/ess/.claude-plugin/plugin.json +++ b/plugins/ess/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "ess", "displayName": "ESS", "description": "Write, retrofit, validate and project Executable System Specifications, and hold implementations to them with conformance suites.", - "version": "0.19.0", + "version": "0.19.1", "author": { "name": "Beyond10x" }, diff --git a/plugins/ess/.codex-plugin/plugin.json b/plugins/ess/.codex-plugin/plugin.json index 09ad533..31c93c7 100644 --- a/plugins/ess/.codex-plugin/plugin.json +++ b/plugins/ess/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "ess", - "version": "0.19.0", + "version": "0.19.1", "description": "Write, retrofit, validate and project Executable System Specifications, and hold implementations to them with conformance suites.", "author": { "name": "Beyond10x" diff --git a/plugins/ess/skills/specifying/SKILL.md b/plugins/ess/skills/specifying/SKILL.md index 32332a2..d3c3294 100644 --- a/plugins/ess/skills/specifying/SKILL.md +++ b/plugins/ess/skills/specifying/SKILL.md @@ -227,6 +227,34 @@ The same typed IR must produce the same ordered files and bytes. Compare a regen tree with the committed tree before replacing anything. A stale committed file is drift; a file no projection owns is not authority. +## Implementation code comes from the specification + +**Never hand-transcribe the model into code.** Entities, their states and transitions, command +inputs, outcomes, events, errors and views are generated; the implementation fills in only what the +specification cannot say: + +```console +ess generate synthesize --path --target rust --out +``` + +The generated workspace carries one `…Behavior` trait per command and one `…Query` trait per view, +each stubbed with a typed refusal. Implement those traits and nothing beside them. Commit the +generated tree and hold it in the gate: regenerate into a temporary directory and fail on any +difference, exactly as for projections above. When the specification changes, regenerate; the +compiler then names every handler the change touched. + +A hand transcription drifts, and nothing catches it. One passed a 669-scenario conformance suite +with every entity field unchecked: a scenario only reads the fields its expectations name, so a +wrong field type or a missing field that no expectation reads stays green. + +**When `synthesize` refuses the specification,** the refusal names each position the target cannot +represent. That is a gap in ESS, not a licence to transcribe: file it on beyond10x/ess with the +refusal lines. Until the fix is released, a hand-written model is allowed only with a test that +compares it against `ess specify compile --path --format json`: every entity's +fields and their types, every lifecycle's states and transitions, every command's input, every +event's and error's fields, every view's fields, and every actor's `may` list. Names alone are not +enough. Replace the hand-written model with the generated one as soon as the release is out. + ## Conformance is a record, not a claim In the planning store an `executable-system-specification` is `conforming` because a suite ran and diff --git a/plugins/ess/skills/testing-conformance/SKILL.md b/plugins/ess/skills/testing-conformance/SKILL.md index f7126c9..7c6775f 100644 --- a/plugins/ess/skills/testing-conformance/SKILL.md +++ b/plugins/ess/skills/testing-conformance/SKILL.md @@ -40,6 +40,14 @@ The mechanism generalises, so learn to spot it by reading rather than by mutatin Do the mutation test once per mapping you rely on, and record in the commit that you did it and what failed. A scenario nobody has ever seen fail is a scenario that has never been tested. +**A green suite does not prove the implementation's model.** It proves the fields its expectations +read. If the implementation's entities, events or views were written by hand rather than generated +(`ess:specifying`, "Implementation code comes from the specification"), a field no expectation +names can have the wrong type, or be missing, and every scenario stays green. The same holds for +guards: a synthesized scenario witnesses one value per `any_of`, so a guard over `[A, B]` is +exercised with `A` and never with `B`. Cover the other values with the implementation's own tests, +and prove each one can fail by breaking it once. + **A cheaper check comes first: would the scenario pass against a target that does nothing?** Point the suite at a target whose every `ExecuteCommand` returns an accepted outcome with no state change and whose every `QueryView` returns an empty row. A scenario that passes there asserts only that a diff --git a/plugins/worktree/.claude-plugin/plugin.json b/plugins/worktree/.claude-plugin/plugin.json index 426c724..89318d6 100644 --- a/plugins/worktree/.claude-plugin/plugin.json +++ b/plugins/worktree/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "worktree", "displayName": "Worktree", "description": "Create, lease, finish, audit and safely clean isolated Git worktrees through the worktree CLI.", - "version": "0.19.0", + "version": "0.19.1", "author": { "name": "Beyond10x" }, diff --git a/plugins/worktree/.codex-plugin/plugin.json b/plugins/worktree/.codex-plugin/plugin.json index 75a7815..bc93600 100644 --- a/plugins/worktree/.codex-plugin/plugin.json +++ b/plugins/worktree/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "worktree", - "version": "0.19.0", + "version": "0.19.1", "description": "Create, lease, finish, audit and safely clean isolated Git worktrees through the worktree CLI.", "author": { "name": "Beyond10x"