diff --git a/.engineering/evidence/task/cleanup-request-authorization/20261003T153004Z-000-6919bd4b32f4.json b/.engineering/evidence/task/cleanup-request-authorization/20261003T153004Z-000-6919bd4b32f4.json new file mode 100644 index 0000000..cb98ad8 --- /dev/null +++ b/.engineering/evidence/task/cleanup-request-authorization/20261003T153004Z-000-6919bd4b32f4.json @@ -0,0 +1,13 @@ +{ + "at": "2026-10-03T15:30:04Z", + "actor": "human:timo", + "artifact": "task:cleanup-request-authorization", + "kind": "task", + "revision": 3, + "change": { + "change": "evidence", + "kind": "test_result", + "source": "Rust 1.99 task check: 145 tests and the offline plugin/eval gate passed", + "reference": "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/beyond10x/agentplugins/pull/55" + } +} diff --git a/.engineering/evidence/task/cleanup-request-authorization/20261003T153926Z-000-910fd91214dd.json b/.engineering/evidence/task/cleanup-request-authorization/20261003T153926Z-000-910fd91214dd.json new file mode 100644 index 0000000..5ea8971 --- /dev/null +++ b/.engineering/evidence/task/cleanup-request-authorization/20261003T153926Z-000-910fd91214dd.json @@ -0,0 +1,13 @@ +{ + "at": "2026-10-03T15:39:26Z", + "actor": "human:timo", + "artifact": "task:cleanup-request-authorization", + "kind": "task", + "revision": 5, + "change": { + "change": "evidence", + "kind": "test_result", + "source": "Current CLI gate and two isolated ESS full-package trials passed; 24 and 15 scenarios, no failures or skips, all nine outputs; unchanged baselines", + "reference": "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/beyond10x/agentplugins/pull/55" + } +} diff --git a/.engineering/planning/task/cleanup-request-authorization.md b/.engineering/planning/task/cleanup-request-authorization.md new file mode 100644 index 0000000..3efb74b --- /dev/null +++ b/.engineering/planning/task/cleanup-request-authorization.md @@ -0,0 +1,38 @@ +--- +format: aep.planning-md/3 +id: task:cleanup-request-authorization +kind: task +status: implemented +title: Execute authorized cleanup and restore the merge checks +refs: +- provider: github + reference: https://github.com/beyond10x/agentplugins/pull/55 +relations: +- informed_by: story:worktree-plugin-integrated +revision: 6 +transitions: +- {from: "draft", to: "proposed", at: "2026-10-03T15:27:21Z", actor: "human:timo", revision: 2} +- {from: "proposed", to: "active", at: "2026-10-03T15:27:21Z", actor: "human:timo", revision: 3} +- {from: "active", to: "implemented", at: "2026-10-03T15:39:26Z", actor: "human:timo", revision: 6, decided_on: {"recorded":{"test_result":2}}} +--- +## Context + +An explicit cleanup request was followed by a redundant approval prompt. PR 55 corrects that guidance and the Rust 1.99 and CLI compatibility failures that prevented merging it. + +## Acceptance + +Explicit cleanup authorizes exact eligible removals without a second prompt, inspection requests remain read-only, and the repository and current CLI gates pass with verification pins backed by an isolated ESS full-package trial. + +## Scope + +Worktree cleanup and activity skills; obsolete AEP command inventory entries; existing Rust test assertion diagnostics; verified CLI pins; ESS synthesis language and Go suite placement guidance. Lifecycle safety checks and test assertions retain their semantics. + +## Verification + +Rust 1.99 task check passes all 145 tests and the offline plugin/eval gate. Command verification passes against AEP 0.68.0, ESS 0.52.0 and Worktree 0.8.2, including the ESS syntax example and executable tutorial. Plugin manifest validation passes. + +Two isolated ESS full-package trials used ESS 0.52.0 and the candidate plugin. The first produced all nine outputs and passed 24 scenarios, with zero failures, skips or synthesis refusals and 37 tool calls. Its agent hand-transcribed its Go model after overlooking Go implementation synthesis. A direct released-CLI probe confirmed generated Go model and behavior/query contracts; guidance now names both implementation targets, ports and obligations, and the conformance package location. + +The fresh second trial produced all nine outputs and passed 15 scenarios, with zero failures, skips, synthesis refusals or unmapped markers and 62 tool calls. Isolation and the existing baseline comparison passed for both trials. The second trial imported generated Go types and correctly wired the separately generated conformance module; it still wrote its storage adapter by hand, so these results establish command/output compatibility and conformance, not universal adherence to implementation-synthesis guidance. No generated suite was edited and no baseline was loosened. + +Verification pins advanced only after the trials passed. Private transcripts and fixtures are retained in a credential-free archive with SHA-256 f2feae2d9b8e8242b141aa9f85d0ba331e831b27ea3b218f49d941771c81ca68. PR 55 carries publication and CI evidence. diff --git a/crates/agentplugins-check/src/concept.rs b/crates/agentplugins-check/src/concept.rs index a9f377f..6caa0ea 100644 --- a/crates/agentplugins-check/src/concept.rs +++ b/crates/agentplugins-check/src/concept.rs @@ -1133,9 +1133,18 @@ mod tests { fn cli_versions_are_found_and_skill_versions_are_not() { assert_eq!(quoted_versions("at AEP 0.55.0 the verb"), ["aep 0.55.0"]); assert_eq!(quoted_versions("output of ESS `0.29.0`"), ["ess 0.29.0"]); - assert!(quoted_versions("**Skill version 0.13.1** — the version").is_empty()); - assert!(quoted_versions("ess-cli 0.30.0 is not a quote of a CLI name").is_empty()); - assert!(quoted_versions("aep plan artifact list").is_empty()); + assert_eq!( + quoted_versions("**Skill version 0.13.1** — the version"), + Vec::::new() + ); + assert_eq!( + quoted_versions("ess-cli 0.30.0 is not a quote of a CLI name"), + Vec::::new() + ); + assert_eq!( + quoted_versions("aep plan artifact list"), + Vec::::new() + ); } #[test] diff --git a/crates/agentplugins-check/src/evals.rs b/crates/agentplugins-check/src/evals.rs index ed503f9..7366d3a 100644 --- a/crates/agentplugins-check/src/evals.rs +++ b/crates/agentplugins-check/src/evals.rs @@ -1115,7 +1115,10 @@ mod tests { fn a_case_whose_manifest_pins_nothing_repeats_nothing() { // A single-plugin stream is unambiguous and `aep` reads the treatment out of it, so a // replay that added arguments would be inventing the experiment. - assert!(treatment_args(&case_about(&["b10x"]), Vec::new()).is_empty()); + assert_eq!( + treatment_args(&case_about(&["b10x"]), Vec::new()), + Vec::::new() + ); } #[test] diff --git a/crates/agentplugins-check/src/main.rs b/crates/agentplugins-check/src/main.rs index 02eadd1..1732be4 100644 --- a/crates/agentplugins-check/src/main.rs +++ b/crates/agentplugins-check/src/main.rs @@ -1560,7 +1560,10 @@ one product only: `b10x upgrade ess` retired_hits("a\nplugins/aep-planning/x\n", planning, false), vec![2] ); - assert!(retired_hits("plugins/aep/x\n", planning, false).is_empty()); + assert_eq!( + retired_hits("plugins/aep/x\n", planning, false), + Vec::::new() + ); } /// The marker excuses a line in a specification a transcript is replayed against, and nowhere diff --git a/crates/agentplugins-check/src/report.rs b/crates/agentplugins-check/src/report.rs index aa04325..fb655a9 100644 --- a/crates/agentplugins-check/src/report.rs +++ b/crates/agentplugins-check/src/report.rs @@ -845,13 +845,13 @@ mod tests { failed: 0, skipped: 11, })); - assert!(worse(&full(), &full()).is_empty()); + assert_eq!(worse(&full(), &full()), Vec::::new()); assert!( worse(&full(), &better).is_empty(), "{:?}", worse(&full(), &better) ); - assert!(worse(&Measures::default(), &full()).is_empty()); + assert_eq!(worse(&Measures::default(), &full()), Vec::::new()); } #[test] diff --git a/crates/b10x/src/check.rs b/crates/b10x/src/check.rs index 6600532..9659190 100644 --- a/crates/b10x/src/check.rs +++ b/crates/b10x/src/check.rs @@ -398,15 +398,17 @@ mod tests { )) }; let map = cache("0.30.0"); - assert!(lines( - &catalog, - &plugins, - &found, - Some((1_000, &map)), - 1_000 + 86_400, - &unpinned() - ) - .is_empty()); + assert_eq!( + lines( + &catalog, + &plugins, + &found, + Some((1_000, &map)), + 1_000 + 86_400, + &unpinned() + ), + Vec::::new() + ); } #[test] diff --git a/crates/b10x/src/install.rs b/crates/b10x/src/install.rs index 2101771..267d328 100644 --- a/crates/b10x/src/install.rs +++ b/crates/b10x/src/install.rs @@ -247,7 +247,10 @@ fff b10x-harness-0.13.2-.tar.gz listed_targets(sums, "b10x-harness", "0.13.2"), "a leading v on the tag is not part of the archive name" ); - assert!(listed_targets("", "b10x-harness", "0.13.2").is_empty()); + assert_eq!( + listed_targets("", "b10x-harness", "0.13.2"), + BTreeSet::new() + ); for target in listed_targets(sums, "b10x-harness", "0.13.2") { let name = archive_name("b10x-harness", "0.13.2", &target); assert_eq!(listed_digest(sums, &name), Some("aaa")); diff --git a/plugins/aep/skills/planning/SKILL.md b/plugins/aep/skills/planning/SKILL.md index 98614a3..5cea8e5 100644 --- a/plugins/aep/skills/planning/SKILL.md +++ b/plugins/aep/skills/planning/SKILL.md @@ -69,15 +69,14 @@ or relations. Ask for them at the moment you need them: | What does this one artifact say, frontmatter and body? | `aep plan artifact show ` | | What has happened to it, oldest first? | `aep plan artifact history ` | | Why is it at this status — what did the store admit before each move? | `aep plan artifact explain ` | -| What writes has one side of a hybrid plan taken that the other has not? | `aep plan artifact divergences` | | Which stories may be implemented at once, from their typed `scope` and `depends_on`? | `aep plan artifact waves [--kind k] [--status s] [--format json]` | | What did the latest review of an artifact find that the one before did not? | `aep plan artifact findings [--from --to ]` | | Per reviewer, what did their findings change and what did their verdicts cost? | `aep plan artifact review-value [--since ]` | | Is the whole store still consistent? | `aep plan artifact validate` | -That is every `aep plan artifact` verb that answers a question. The nine that are -missing from it write — `new`, `move`, `relate`, `unrelate`, `body`, `set`, `scope`, `evidence`, -`catch-up` — and guardrail 2 governs those. Run `aep plan artifact --help` when this table and the +That is every `aep plan artifact` verb that answers a question. The eight that are +missing from it write — `new`, `move`, `relate`, `unrelate`, `body`, `set`, `scope`, `evidence` +— and guardrail 2 governs those. Run `aep plan artifact --help` when this table and the CLI disagree; the CLI is right. The reason is the reason this project exists. Lifecycle and relation documents are validated and diff --git a/plugins/ess/skills/specifying/SKILL.md b/plugins/ess/skills/specifying/SKILL.md index d3c3294..6de4230 100644 --- a/plugins/ess/skills/specifying/SKILL.md +++ b/plugins/ess/skills/specifying/SKILL.md @@ -237,8 +237,10 @@ specification cannot say: 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 +Choose the implementation language before writing code: `--target rust` generates a Rust workspace; +`--target go` generates a Go module. Both carry generated model types, `…Behavior` command contracts +and `…Query` view contracts (traits in Rust, interfaces in Go). Read `PLAN.md` and `TARGET.md`, use +the generated behavior where present, and implement the remaining ports and obligations. 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. @@ -279,7 +281,10 @@ subject through what its views publish; no view publishes …` means a wrong-sta changed those fields would pass, and a view publishing them closes it; `declares no not-found and no wrong_state outcome` means an unknown id has no declared answer (`unknown_instance:` in [references/later-formats.md](references/later-formats.md)). Relay every note with the refusals. `--target go` or `--target typescript` writes the suite as a test -package your implementation runs; `ess:testing-conformance` says what to run it against. +package your implementation runs; `ess:testing-conformance` says what to run it against. The Go +suite is written under `/essconform` without a `go.mod`: generate it inside the implementation +module, or give its enclosing directory a module and import it with a local replacement. Keep the +generated suite unchanged. `run` holds a built-in reference implementation to it; `--target` lists the ones this binary carries. `evidence --from` reads the kind, the source and the instant out of the report and refuses a report of no scenarios or with no `spec_digest`. A report/2 (`--report-format 2`) is diff --git a/plugins/worktree/skills/cleanup/SKILL.md b/plugins/worktree/skills/cleanup/SKILL.md index 8f00a19..adb27b2 100644 --- a/plugins/worktree/skills/cleanup/SKILL.md +++ b/plugins/worktree/skills/cleanup/SKILL.md @@ -10,12 +10,5 @@ argument-hint: "[--repo ] [--id ...]" Read `worktree:managing-worktrees` in full, then follow its *Finish and clean up* and *Audit and recovery* sections for the trees named in `$ARGUMENTS`, or for the current repository if none are. -1. `worktree inspect --repo ` (add `--id ` per tree) and read every retention blocker. -2. For a tree whose work must not be published, `worktree archive ` instead of publishing. -3. Release only your own lease, then `worktree finish ` for each tree that is done. -4. `worktree gc --repo --dry-run --id ` for each tree, and show the results as a table. -5. `worktree gc --repo --apply --id ` only for the ids the operator approved - from that table. - -Never force a removal, delete a tree by hand, or clear another session's lease. End with every tree -that was kept and the reason the dry-run or inspect gave for keeping it. +Invoking this command authorizes cleanup in that scope. Review the dry-run results, apply the exact +eligible ids, and report removals and retention reasons without asking for another approval. diff --git a/plugins/worktree/skills/managing-worktrees/SKILL.md b/plugins/worktree/skills/managing-worktrees/SKILL.md index 18e2a68..fb68d4d 100644 --- a/plugins/worktree/skills/managing-worktrees/SKILL.md +++ b/plugins/worktree/skills/managing-worktrees/SKILL.md @@ -30,6 +30,12 @@ After verification, preserve the small logs, reports, or deliverables needed for ## Finish and clean up +An explicit cleanup request authorizes removal of eligible trees in the requested scope. Inspect +that scope, review the dry-run results yourself, and proceed to exact-id apply without another +approval prompt. A request only to inspect, review, or dry-run ends with the findings. Retain trees +with unresolved ownership, recovery, lease, lock, or work-state blockers and report the reason; +cleanup authorization does not waive those checks or authorize publishing someone else's work. + 1. Commit and publish every wanted change. A local-only commit is deliberately not cleanup-safe. Work merged as rebased or cherry-picked copies also qualifies when an advertised ref carries every unique commit's exact patch; GC reports that proof as `patch-equivalent`. When work must not be published, run `worktree archive ` instead. It never modifies the tree; it writes `commits.bundle` (every commit no advertised ref holds), `dirty.patch` (tracked, untracked and ignored changes over HEAD) and a `worktree.archive/1` `manifest.json` below the state directory's `worktree/archives///`, and verifies them. GC then accepts that archive as `archive` proof while HEAD and every file still match it exactly; any later commit or edit is refused as `archive-stale` until `worktree archive --replace ` writes a new one. `--replace` moves the old archive aside and never deletes it. Every ignored file is archived, so remove this task's build output first (see *Bound disposable storage*); submodules, nested repositories, special files and paths containing a newline are refused as `archive-unsupported-entry`. GC apply returns an archived dirty tree to HEAD, removes it without force, and keeps the archive. 2. Preserve required evidence and remove this task's disposable output as described above. Release your own lease, then run `worktree finish `. It refuses locked, unmanaged, live, or mid-operation Git worktrees, and dirty ones unless their archive holds exactly the current state. diff --git a/verified.json b/verified.json index 2583ee3..e98acd2 100644 --- a/verified.json +++ b/verified.json @@ -1,5 +1,5 @@ { - "aep": "0.64.0", - "ess": "0.39.0", + "aep": "0.68.0", + "ess": "0.52.0", "worktree": "0.8.2" }