@sabaiway/agent-workflow-kit 10.5.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +139 -0
- package/SKILL.md +9 -1
- package/bridges/antigravity-cli-bridge/SKILL.md +1 -1
- package/bridges/antigravity-cli-bridge/bin/agy-review.sh +6 -6
- package/bridges/antigravity-cli-bridge/capability.json +1 -1
- package/bridges/codex-cli-bridge/SKILL.md +1 -1
- package/bridges/codex-cli-bridge/bin/codex-exec.sh +1 -1
- package/bridges/codex-cli-bridge/bin/codex-review.sh +6 -6
- package/bridges/codex-cli-bridge/capability.json +1 -1
- package/capability.json +1 -1
- package/package.json +1 -1
- package/references/modes/commit-guard.md +2 -2
- package/references/modes/control-bytes.md +91 -0
- package/references/modes/core-evidence.md +1 -1
- package/references/modes/flow-writer.md +16 -4
- package/references/modes/procedures.md +5 -1
- package/references/modes/review-state.md +3 -3
- package/references/modes/robustness-brief.md +61 -0
- package/references/modes/velocity.md +2 -0
- package/references/robustness-literals.json +107 -0
- package/tools/changed-surface.mjs +1 -1
- package/tools/commands.mjs +14 -0
- package/tools/commit-guard.mjs +24 -12
- package/tools/control-bytes.mjs +264 -0
- package/tools/core-evidence.mjs +33 -20
- package/tools/coverage-check.mjs +1 -1
- package/tools/dispatch-store-read.mjs +269 -0
- package/tools/dispatch-store.mjs +21 -357
- package/tools/flow-check-git-lane.mjs +2 -1
- package/tools/flow-delta-proof.mjs +4 -4
- package/tools/flow-record-shape.mjs +44 -2
- package/tools/flow-round-gates.mjs +151 -0
- package/tools/flow-store-read.mjs +1 -1
- package/tools/flow-writer.mjs +235 -82
- package/tools/fold-scope.mjs +7 -3
- package/tools/fs-read-nofollow.mjs +56 -4
- package/tools/git-env.mjs +120 -0
- package/tools/grounding.mjs +4 -3
- package/tools/held-session.mjs +165 -0
- package/tools/plan-shape-facts.mjs +23 -10
- package/tools/plan-shape.mjs +8 -0
- package/tools/procedures.mjs +47 -4
- package/tools/repo-lex.mjs +29 -0
- package/tools/review-state.mjs +127 -39
- package/tools/robustness-brief.mjs +209 -0
- package/tools/robustness-literals.mjs +101 -0
- package/tools/sandbox-masks.mjs +2 -1
- package/tools/set-flow.mjs +2 -1
- package/tools/source-size-scope.mjs +19 -25
- package/tools/tracked-tree-census.mjs +3 -3
- package/tools/velocity-profile.mjs +5 -2
- package/tools/worktree-handoff-return.mjs +2 -2
- package/tools/worktrees.mjs +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,145 @@ Semantically versioned ([semver](https://semver.org)), newest first. The `versio
|
|
|
4
4
|
is the current release. `upgrade` mode reads a project's `docs/ai/.workflow-version` and applies
|
|
5
5
|
every `migrations/<version>-<slug>.md` newer than it, in semver order.
|
|
6
6
|
|
|
7
|
+
## 11.0.0 — the per-fold walk is a record, the cap is a refusal at the round table's own signal, and the fingerprint argv has one home (AD-130)
|
|
8
|
+
|
|
9
|
+
Plan 2's two attestation rounds on CONVERGED bytes each found one member of the kit's own robustness
|
|
10
|
+
list that the executor never received: the tagged sweep row got its brief, the untagged suite and
|
|
11
|
+
generator rows did not. Nothing asked "does the tag cover the row" before the dispatch, nothing
|
|
12
|
+
recorded the adversarial walk a fold owes, and past the round table's `cap reached` / `crossover`
|
|
13
|
+
signal nothing refused the next round — on the release-run feature the table printed CROSSOVER from
|
|
14
|
+
round 2 for eleven rounds and nothing acted on it. Rungs 4 and 5 of the first-pass-quality series
|
|
15
|
+
close that, and the two fingerprint classes plan 1 measured RED (Issue-023 / Issue-024) close with
|
|
16
|
+
them. Contracts: `robustness-literals.md` rev 2 (S10–S11 bound), `plan-review-loop/index.md` rev 6
|
|
17
|
+
(S30–S33 bound), `release-run/index.md` rev 2.
|
|
18
|
+
|
|
19
|
+
**Coverage is the generator's second mode.** `robustness-brief.mjs --plan <plan> --coverage` judges
|
|
20
|
+
every `create`/`modify` row except a document (`.md`, `.txt`) or the shipped list itself: a class is
|
|
21
|
+
PRESENT when the row file's BYTES carry a member literal of kind env/flag/ref/syscall/errno/argv as a
|
|
22
|
+
BOUNDED token (a comment counts, `state` members are never searched), `uncovered` = present minus
|
|
23
|
+
tagged, a `delete` row and an absent file are LISTED, a sweep row is judged over every path the facts
|
|
24
|
+
leaf expands (`expandSweepPaths`, one home in `plan-shape-facts.mjs`); exit 0 covered / 1 naming each
|
|
25
|
+
`row:class:literal` / 2 on a row file the 1 MiB no-follow read cannot deliver. Measured on itself: the
|
|
26
|
+
first run over this very plan named `R01:spawn-outcome:ENOENT` and the tag grew before the next
|
|
27
|
+
dispatch. `references/modes/robustness-brief.md` states the mode, its read surface and the bounds.
|
|
28
|
+
|
|
29
|
+
**Every fold owes a walk, recorded.** `flow-writer internal-attestation <planId> --walk <file>` reads a
|
|
30
|
+
closed JSON walk (`{ listVersion, rows: [{ id, class, checked }] }`) relative to the git COMMON dir,
|
|
31
|
+
derives the obligation from the ADOPTED plan (every judged row, every class in TAGGED ∪ PRESENT needs a
|
|
32
|
+
non-empty `checked`), records `uncovered` and never refuses on it; `round-open` for every round after
|
|
33
|
+
the first refuses without an authoritative walk-carrying attestation at round N's coordinates, and
|
|
34
|
+
`--justification` lifts that refusal as an echoed INPUT whose durable trail is the attestation's
|
|
35
|
+
absence. A plan with no judgeable row owes no walk; a plan that lost adoption coverage fails closed
|
|
36
|
+
by name (`resolveAdoptedPlan`, one home).
|
|
37
|
+
|
|
38
|
+
**The cap is the round table's own signal, and terminal is digest equality.** The new pure leaf
|
|
39
|
+
`tools/flow-round-gates.mjs` (`blockingItems`, `roundsForSignal`, `capIssue`, `walkIssue`,
|
|
40
|
+
`escalationIssue`, `validateWalk`; `signalFor` imported from `review-rounds.mjs`, never modified)
|
|
41
|
+
builds one round per authoritative head from its LANDED dispatches; on `cap reached` or `crossover`
|
|
42
|
+
only, `round-open` refuses unless every blocking ITEM of every landed receipt of the latest head is
|
|
43
|
+
covered by a disposition whose `findingDigest` equals `sha256(itemText)` — text mode the wrapper's own
|
|
44
|
+
line, schema mode the `issue` field verbatim — and prints every uncovered item beside its digest. An
|
|
45
|
+
enumeration failure on a readable manifest falls back to the `>= 1` floor with an ADVISORY; the
|
|
46
|
+
checks run cap → walk → floor in the lock-free pass and again on the locked snapshot.
|
|
47
|
+
|
|
48
|
+
**A finding with no proven narrow fix is never queued; a lost manifest is a record.** `round-land
|
|
49
|
+
--dispose queued --finding <quote> --claim <invariant> --proof-kind consult-attestation|red-proof
|
|
50
|
+
--proof-digest <d>` mints only on `decideFoldScope` ACCEPT `new-invariant`, with `debtId`/`debtDigest`
|
|
51
|
+
DERIVED from the ONE resolved queue row `fold-scope` now returns (`normalize` exported, one home); a
|
|
52
|
+
consult-attestation proof binds through `proposedFixDigest === sha256(itemDigest + "\n" + claim)`, a
|
|
53
|
+
red-proof through the head's `base`, the tree `round-land` runs on and the row's `proof` field. The
|
|
54
|
+
fourth arm `escalated --finding <quote> --override-digest <d>` resolves a `maintainer-override` of THIS round's vetoing
|
|
55
|
+
receipt; the FIFTH arm `custody-lost --receipt <receiptDigest>` mints only on a REAL loss (`absent |
|
|
56
|
+
foreign | error | malformed | foreign-identity | swapped`), covers every item of that receipt for the
|
|
57
|
+
cap and is recordable whenever the loss is real. `flow-record-shape.mjs` admits `walk`, the queued
|
|
58
|
+
trio (all-or-none), `escalated` and `custody-lost`; `FLOW_SCHEMA_VERSION` does not move.
|
|
59
|
+
|
|
60
|
+
**The fingerprint argv has one home.** `core-evidence.mjs` exports `FINGERPRINT_CACHED_DIFF_ARGV` /
|
|
61
|
+
`FINGERPRINT_UNSTAGED_DIFF_ARGV` carrying `--no-ext-diff --no-textconv --ignore-submodules=none`;
|
|
62
|
+
`flow-delta-proof.mjs` imports them; both wrappers' bash twins (`emit_fingerprint_payload`,
|
|
63
|
+
`assemble_code_diff`, the no-diff preflight) carry the flags, mirrored into `bridges/`, and
|
|
64
|
+
`test/review-fingerprint-parity.test.mjs` EXTRACTS the preflight line and proves it on real git with a
|
|
65
|
+
gitlink under `diff.ignoreSubmodules=all`. Issue-023 and Issue-024 close; `commit-guard`'s
|
|
66
|
+
content-free refusal 2 narrows to a fail-closed backstop with a generic message that names no flag
|
|
67
|
+
and no config key (`references/modes/commit-guard.md`).
|
|
68
|
+
|
|
69
|
+
**Tests and records.** New suite `flow-round-gates.test.mjs`; the touched suites (`robustness-brief`,
|
|
70
|
+
`flow-record`, `flow-writer`, `flow-dogfood.integration`, `core-evidence-hostile`,
|
|
71
|
+
`commit-guard-content-free`, `review-fingerprint-parity`, `package-content` — the tarball pin 284 →
|
|
72
|
+
285 — and `fold-scope`) green with real git; thirteen red-proof cases (34 `core-evidence red-proof`
|
|
73
|
+
re-observations on the parked pre-fix trees); the source-size baseline re-recorded under one stated reason. Every fold of the three diff
|
|
74
|
+
rounds rode the delegate's held session (AD-127): fourteen accounted dispatches, one session.
|
|
75
|
+
|
|
76
|
+
### BREAKING
|
|
77
|
+
|
|
78
|
+
- **Minimum bridge versions: codex-cli-bridge 3.7.0, antigravity-cli-bridge 5.6.0.** The fingerprint
|
|
79
|
+
domain moves on a repository configuring `textconv` (neutralised by `--no-textconv`) or
|
|
80
|
+
`diff.ignoreSubmodules` / `submodule.<name>.ignore` in `.git/config` or `.gitmodules` (both overridden
|
|
81
|
+
by `--ignore-submodules=none`): a kit-11 receipt and a pre-3.7.0 / pre-5.6.0 wrapper receipt hash the
|
|
82
|
+
same tree differently. `init` and `upgrade`
|
|
83
|
+
refresh a placed bridge (`bin/install.mjs`); a bridge never placed is never placed by them.
|
|
84
|
+
- **`round-land --dispose queued` changes its operands:** `--debt-id` / `--debt-digest` are gone;
|
|
85
|
+
`--claim`, `--proof-kind` and `--proof-digest` are required together with `--finding`.
|
|
86
|
+
- **`round-open` refuses where `--justification` used to lift:** past the round table's signal the
|
|
87
|
+
cap is never lifted by a justification; a missing walk is.
|
|
88
|
+
- **The one-way door:** a flow store carrying any post-rung record form — an `internal-attestation`
|
|
89
|
+
with `walk`, a `queued` disposition with `claim`/`proofKind`/`proofDigest`, an `escalated` or a
|
|
90
|
+
`custody-lost` disposition — reads under kit >= 11 only. A pre-rung store still reads.
|
|
91
|
+
|
|
92
|
+
## 10.6.0 — a fold on delegated code rides the delegate's held session, judged from the ledger the kit already mints (AD-127)
|
|
93
|
+
|
|
94
|
+
The 2026-08-30 `release-run` execution took thirteen diff-review rounds, and every fold was made by
|
|
95
|
+
the orchestrator by hand while the executor's session id sat on disk the whole time. The delegate that
|
|
96
|
+
wrote the code knows what it wrote; a fold made elsewhere does not. The held session is now a VALUE the
|
|
97
|
+
kit reads from the delegation ledger it already mints — no new record kind, no new receipt field, no
|
|
98
|
+
new contract-header field — a line two renders carry, and a refusal at the commit gate. Contract
|
|
99
|
+
`docs/ai/specs/kit/held-session.md` (live, rev 1, S1-S7, each bound once).
|
|
100
|
+
|
|
101
|
+
**Two new leaves.** `tools/dispatch-store-read.mjs` is the read half of the delegation ledger — path,
|
|
102
|
+
parser, reader, thread state and the semantic audit — split out of `dispatch-store.mjs` (the facade
|
|
103
|
+
re-exports it, so no caller changes, and the advisor's read graph never reaches the append lane).
|
|
104
|
+
`tools/held-session.mjs` is the pure judge: over the ledger records in file order, inside the commit
|
|
105
|
+
EPOCH (the `code` threads dispatched strictly after HEAD's committer second — the same second counts
|
|
106
|
+
BEFORE the commit, so the wrong direction is "holds nothing"; an unborn branch admits every thread; a
|
|
107
|
+
git error fails closed), HELD is the `sessionId` of the FIRST folded delegated thread; a later thread
|
|
108
|
+
is CONTINUED when its return carries that id or when it is a `retryOf` dispatch, SUBSTITUTED when it
|
|
109
|
+
carries another, OPEN without a return, FAILED when its return identifies no session (the failed-run
|
|
110
|
+
lane — never a substitution).
|
|
111
|
+
Every unresolved substitution is kept by nonce; a fold clears only its own retry chain's; otherwise
|
|
112
|
+
only the existing `core-evidence degrade` record for the execute wrapper `codex-exec` at that return's
|
|
113
|
+
own `postTreeDigest` lifts one, standing after later folds move the tree. The judge is wall-clock and
|
|
114
|
+
worktree-blind — both stated residuals, neither a schema change.
|
|
115
|
+
|
|
116
|
+
**`review-state` names it, `--check` refuses it, the guard inherits.** The plain run prints
|
|
117
|
+
`held session: <id> — <n> fold(s) rode it` / `none` / the substitution line; under the CONFIGURED
|
|
118
|
+
`plan-execution.execute = delegated` (the raw config, never a per-run override) with a plan in flight
|
|
119
|
+
and a dirty tree, `--check` audits the ledger BEFORE the review-recipe early return and refuses a
|
|
120
|
+
substituted held session; an absent ledger is inert, while an unreadable, malformed, foreign or
|
|
121
|
+
audit-refused ledger and a failed HEAD read fail closed with their own reason; `--await` ends on the
|
|
122
|
+
refusal at once. `commit-guard` strips `AW_DELEGATION_STORE` beside its three seams.
|
|
123
|
+
`references/modes/core-evidence.md` states the backend name's second reading: `codex-exec` is the
|
|
124
|
+
accepted-replacement escape the arm honours; the review receipt id `codex` never grants it.
|
|
125
|
+
|
|
126
|
+
**The fold lane in the advisor.** `procedures plan-execution` renders, right after a delegated
|
|
127
|
+
execute slot's driving contract, `codex-exec --resume <held id> --nonce <nonce> <fold-brief>` with the
|
|
128
|
+
held id populated from the audited ledger (shell-quoted); one `caveat:` line replaces the id in each
|
|
129
|
+
no-id case — no ledger, no folded code session in the epoch, a recorded substitution, an
|
|
130
|
+
unresolvable / unreadable / malformed / audit-refused ledger, a failed HEAD read, an id a one-line
|
|
131
|
+
render cannot carry; `foldLane` carries the same lines under `--json` and is `[]` outside
|
|
132
|
+
`plan-execution` or when execute resolves to Solo or Subagent. The sidecar `.codex-last-session` is
|
|
133
|
+
never read.
|
|
134
|
+
|
|
135
|
+
**Measured on itself.** Executed DELEGATED: the first dispatch executed nothing inside a nested
|
|
136
|
+
sandbox and was degrade-closed; the retry returned every row; seven folds rode the held session by
|
|
137
|
+
`codex-exec --resume`; the live report reads `8 fold(s) rode it`. Council 2 rounds + five attestation runs.
|
|
138
|
+
|
|
139
|
+
Tarball pin 275 -> 277 (the delegation read leaf and the pure held-session judge). Five new test files
|
|
140
|
+
(`held-session.test.mjs`, `procedures-fold-lane.test.mjs`, `review-state-held-session.test.mjs`,
|
|
141
|
+
`commit-guard-held-session.test.mjs`, `delegation-harness.test.mjs`). Source-size recorded on four
|
|
142
|
+
files under one reason: "held-session: the review-state arm, the fold-lane render, the S6 pin and the two payload pins"
|
|
143
|
+
(`review-state.mjs` 826 -> 905, `procedures.mjs` 753 -> 782, the engine's `procedures-canon.test.mjs`
|
|
144
|
+
410 -> 429, `package-content.test.mjs` 755 -> 759).
|
|
145
|
+
|
|
7
146
|
## 10.5.0 — the plan-review loop's measured costs are rungs, values and receipt fields (AD-125)
|
|
8
147
|
|
|
9
148
|
One feature cost five hours of review by the kit's own defaults: plan findings that were plan SHAPE
|
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: agent-workflow-kit
|
|
|
3
3
|
description: Deploy or upgrade a portable AI-agent memory-and-workflow system in any project. Use when the user wants to bootstrap `docs/ai/` + an entry-point `AGENTS.md` (+ `CLAUDE.md` alias) + cap/archive/index enforcement in a new or existing repo, set up the Memory Map and session protocols, install the docs-rotation pre-commit hook, or run `/agent-workflow-kit` / `/agent-workflow-kit upgrade`. Triggers on phrases like "set up the memory system", "deploy the AI workflow here", "bootstrap docs/ai", "upgrade the workflow".
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
metadata:
|
|
6
|
-
version: '
|
|
6
|
+
version: '11.0.0'
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# agent-workflow-kit
|
|
@@ -183,6 +183,14 @@ guarded — read `${CLAUDE_SKILL_DIR}/references/modes/bridge-settings.md` befor
|
|
|
183
183
|
|
|
184
184
|
read-only — read `${CLAUDE_SKILL_DIR}/references/modes/review-state.md` before acting.
|
|
185
185
|
|
|
186
|
+
### Mode: control-bytes
|
|
187
|
+
|
|
188
|
+
read-only — read `${CLAUDE_SKILL_DIR}/references/modes/control-bytes.md` before acting.
|
|
189
|
+
|
|
190
|
+
### Mode: robustness-brief
|
|
191
|
+
|
|
192
|
+
read-only — read `${CLAUDE_SKILL_DIR}/references/modes/robustness-brief.md` before acting.
|
|
193
|
+
|
|
186
194
|
### Mode: receipt-deadline
|
|
187
195
|
|
|
188
196
|
read-only — read `${CLAUDE_SKILL_DIR}/references/modes/receipt-deadline.md` before acting.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: antigravity-cli-bridge
|
|
3
3
|
description: Delegate work to Google's Antigravity CLI (`agy`) — the successor to Gemini CLI — to reach Gemini, Claude, and GPT-OSS models under a Google AI Pro/Ultra subscription from the terminal. Use when the user wants to run a headless `agy` prompt, hand a focused task or second-opinion review to `agy`, install or authenticate Antigravity CLI, check or economise its quota/models, bridge project context into `agy`, set up a second delegated-execution backend beside Codex, or troubleshoot `agy` flags, models, auth, conversations, or its headless behaviour.
|
|
4
4
|
metadata:
|
|
5
|
-
version: '5.
|
|
5
|
+
version: '5.6.0'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# antigravity-cli-bridge
|
|
@@ -343,7 +343,7 @@ DEFAULT_AGY_REVIEW_MODEL="Gemini 3.7 Flash (High)"
|
|
|
343
343
|
# Review-receipt identity (AD-038). AW_BRIDGE_VERSION mirrors this bridge's SKILL.md/capability.json
|
|
344
344
|
# version (drift-guarded by agy-review.test.mjs against capability.json).
|
|
345
345
|
AW_RECEIPT_BACKEND="agy"
|
|
346
|
-
AW_BRIDGE_VERSION="5.
|
|
346
|
+
AW_BRIDGE_VERSION="5.6.0" # aw-version-anchor
|
|
347
347
|
# `-` not `:-` so an EXPLICIT empty AGY_MODEL= survives (drop --model, use settings.json — agy.sh:52).
|
|
348
348
|
AGY_MODEL="${AGY_MODEL-$DEFAULT_AGY_REVIEW_MODEL}"
|
|
349
349
|
# D5 control-byte screen — IMMEDIATELY after resolution, BEFORE the off-frontier advisory (or any
|
|
@@ -867,8 +867,8 @@ warn_never_committable_untracked() {
|
|
|
867
867
|
# implements the SAME serialization in node — cross-checked by the kit's
|
|
868
868
|
# review-fingerprint-parity.test.mjs.
|
|
869
869
|
emit_fingerprint_payload() {
|
|
870
|
-
git diff --cached --no-ext-diff
|
|
871
|
-
git diff --no-ext-diff
|
|
870
|
+
git diff --cached --no-ext-diff --no-textconv --ignore-submodules=none
|
|
871
|
+
git diff --no-ext-diff --no-textconv --ignore-submodules=none
|
|
872
872
|
local path
|
|
873
873
|
while IFS= read -r -d '' path; do
|
|
874
874
|
if [[ -L "$path" ]]; then
|
|
@@ -1556,10 +1556,10 @@ assemble_code_diff() {
|
|
|
1556
1556
|
emit_status_porcelain_filtered
|
|
1557
1557
|
echo
|
|
1558
1558
|
echo "=== staged diff (git diff --cached) ==="
|
|
1559
|
-
git diff --cached --no-ext-diff
|
|
1559
|
+
git diff --cached --no-ext-diff --no-textconv --ignore-submodules=none
|
|
1560
1560
|
echo
|
|
1561
1561
|
echo "=== unstaged diff (git diff) ==="
|
|
1562
|
-
git diff --no-ext-diff
|
|
1562
|
+
git diff --no-ext-diff --no-textconv --ignore-submodules=none
|
|
1563
1563
|
echo
|
|
1564
1564
|
echo "=== untracked file contents ==="
|
|
1565
1565
|
local path
|
|
@@ -1834,7 +1834,7 @@ else
|
|
|
1834
1834
|
cd "$(git rev-parse --show-toplevel)"
|
|
1835
1835
|
# No-diff preflight — never spend a run on a clean tree. Never-committable untracked masks do
|
|
1836
1836
|
# not count: the FILTERED domain is the review surface.
|
|
1837
|
-
if git diff --quiet && git diff --cached --quiet && ! has_reviewable_untracked; then
|
|
1837
|
+
if git diff --quiet --no-ext-diff --no-textconv --ignore-submodules=none && git diff --cached --quiet --no-ext-diff --no-textconv --ignore-submodules=none && ! has_reviewable_untracked; then
|
|
1838
1838
|
echo "agy-review: no uncommitted changes to review — the working tree is clean." >&2
|
|
1839
1839
|
warn_never_committable_untracked
|
|
1840
1840
|
exit 0
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: codex-cli-bridge
|
|
3
3
|
description: Delegate work to the OpenAI Codex CLI (`codex`) under a ChatGPT subscription — run plan/instruction EXECUTION in a sandboxed workspace, or get a read-only ADVISORY review of a plan or working-tree diff — as a second delegated-execution backend beside Antigravity. Use when the user wants to hand a bounded coding task or plan to `codex exec`, get a second-opinion review from codex, install or authenticate Codex CLI, understand its sandbox/network/approval policy, drive codex efficiently from the main agent (exec vs review, resume, the commit boundary), bridge project context (`AGENTS.md`) into codex, or troubleshoot codex flags, models, auth, or its no-TTY headless behaviour.
|
|
4
4
|
metadata:
|
|
5
|
-
version: '3.
|
|
5
|
+
version: '3.7.0'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# codex-cli-bridge
|
|
@@ -372,7 +372,7 @@ CHATGPT_LOGIN_GUARD="Logged in using ChatGPT"
|
|
|
372
372
|
# receipt this wrapper mints; scripts/release/version-sync.mjs bumps it under the one-anchor-per-file
|
|
373
373
|
# rule, so a release can never leave it behind (the AD-053 drift class).
|
|
374
374
|
AW_RECEIPT_BACKEND="codex"
|
|
375
|
-
AW_BRIDGE_VERSION="3.
|
|
375
|
+
AW_BRIDGE_VERSION="3.7.0" # aw-version-anchor
|
|
376
376
|
# The kill grace handed to timeout(1) as --kill-after, and recorded in the receipt as killGraceS:
|
|
377
377
|
# ONE constant, so the number the ledger checks against the dispatch deadline is the number the run
|
|
378
378
|
# actually applied.
|
|
@@ -284,7 +284,7 @@ DEFAULT_CODEX_EFFORT="xhigh"
|
|
|
284
284
|
# Review-receipt identity (AD-038). AW_BRIDGE_VERSION mirrors this bridge's SKILL.md/capability.json
|
|
285
285
|
# version (drift-guarded by codex-review.test.mjs against capability.json).
|
|
286
286
|
AW_RECEIPT_BACKEND="codex"
|
|
287
|
-
AW_BRIDGE_VERSION="3.
|
|
287
|
+
AW_BRIDGE_VERSION="3.7.0" # aw-version-anchor
|
|
288
288
|
CODEX_MODEL="${CODEX_MODEL:-$DEFAULT_CODEX_MODEL}"
|
|
289
289
|
CODEX_EFFORT="${CODEX_EFFORT:-$DEFAULT_CODEX_EFFORT}"
|
|
290
290
|
# Generous hard cap for a slow xhigh review (subscription latency varies).
|
|
@@ -527,8 +527,8 @@ warn_never_committable_untracked() {
|
|
|
527
527
|
# implements the SAME serialization in node — cross-checked by the kit's
|
|
528
528
|
# review-fingerprint-parity.test.mjs.
|
|
529
529
|
emit_fingerprint_payload() {
|
|
530
|
-
git diff --cached --no-ext-diff
|
|
531
|
-
git diff --no-ext-diff
|
|
530
|
+
git diff --cached --no-ext-diff --no-textconv --ignore-submodules=none
|
|
531
|
+
git diff --no-ext-diff --no-textconv --ignore-submodules=none
|
|
532
532
|
local path
|
|
533
533
|
while IFS= read -r -d '' path; do
|
|
534
534
|
if [[ -L "$path" ]]; then
|
|
@@ -811,10 +811,10 @@ assemble_code_diff() {
|
|
|
811
811
|
emit_status_porcelain_filtered
|
|
812
812
|
echo
|
|
813
813
|
echo "=== staged diff (git diff --cached) ==="
|
|
814
|
-
git diff --cached --no-ext-diff
|
|
814
|
+
git diff --cached --no-ext-diff --no-textconv --ignore-submodules=none
|
|
815
815
|
echo
|
|
816
816
|
echo "=== unstaged diff (git diff) ==="
|
|
817
|
-
git diff --no-ext-diff
|
|
817
|
+
git diff --no-ext-diff --no-textconv --ignore-submodules=none
|
|
818
818
|
echo
|
|
819
819
|
echo "=== untracked file contents ==="
|
|
820
820
|
local path
|
|
@@ -923,7 +923,7 @@ case "$mode" in
|
|
|
923
923
|
code)
|
|
924
924
|
# No-diff preflight — never spend a subscription run on a clean tree. Never-committable
|
|
925
925
|
# untracked masks do not count: the FILTERED domain is the review surface.
|
|
926
|
-
if git diff --quiet && git diff --cached --quiet && ! has_reviewable_untracked; then
|
|
926
|
+
if git diff --quiet --no-ext-diff --no-textconv --ignore-submodules=none && git diff --cached --quiet --no-ext-diff --no-textconv --ignore-submodules=none && ! has_reviewable_untracked; then
|
|
927
927
|
echo "codex-review: no uncommitted changes to review — the working tree is clean." >&2
|
|
928
928
|
warn_never_committable_untracked
|
|
929
929
|
exit 0
|
package/capability.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sabaiway/agent-workflow-kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.0",
|
|
4
4
|
"description": "Portable, cross-agent memory & workflow for AI coding agents — Claude Code, Codex, Cursor, Devin Desktop. One command deploys an AGENTS.md entry point + docs/ai context with cap/archive/index enforcement into any repo.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
|
@@ -7,7 +7,7 @@ The **read-only pre-commit guard** (strip-the-kit D10) — the last line of the
|
|
|
7
7
|
Run `node ${CLAUDE_SKILL_DIR}/tools/commit-guard.mjs --check [--cwd <dir>]` — it refuses, each with a named recovery, on:
|
|
8
8
|
|
|
9
9
|
1. **an INDEX that lags the verified working tree** — the gates and the fingerprint both describe the WORKING tree, while `git commit` builds the commit from the INDEX alone, and the fingerprint domain is identical whether a hunk sits staged or unstaged (staging a lone tracked modification does not even move it). So this arm runs FIRST, before the fingerprint is computed: it refuses when the working tree holds anything the index does not — tracked paths differing between index and worktree, or reviewable untracked-not-ignored paths (the SAME never-committable stat filter the fingerprint applies; ignored paths never refuse). An index entry carrying **skip-worktree** or **assume-unchanged** is invisible to `git diff`, so those entries are compared DIRECTLY against the worktree (type, symlink target, executable bit where `core.fileMode` says so, and the blob oid through git's own clean filters) — a de-materialised skip-worktree path is an ordinary sparse checkout and never refuses, while a missing assume-unchanged path does. The submodule probe forces `--ignore-submodules=none`, so `diff.ignoreSubmodules` / `submodule.<name>.ignore` cannot erase a dirty submodule from the comparison. Offending paths are named in THREE categories — plain lagging paths, paths held back by an index bit, and submodules — because their recoveries differ; ONE shared cap spans all of them, each category reserves a slot so no clause is ever nameless, the remainder is stated once, and every path is rendered as one escaped line. Recovery is ONE ordered sequence, and `git add -A` alone is NOT it: a bit-carrying entry must have its `skip-worktree` / `assume-unchanged` bit cleared FIRST (scoped to the paths the refusal names — never to everything `git ls-files -v` reports, which includes de-materialised sparse paths whose deletions would then be staged), then `git add -A`, then re-run `run-gates --final` at its RESOLVED path beside this tool, then commit the WHOLE tree. The listed paths are capped, so the loop is the completion signal: re-run the guard until it names none. A tracked **submodule** the index cannot prove current is named separately with its own recovery — commit or clean inside the submodule and stage the gitlink — because a root-level `git add -A` cannot capture a submodule's internal worktree changes. A submodule whose gitlink itself carries one of those index bits is **not probed at all**: it lags by construction. That is a deliberate REDUCTION — three consecutive review rounds each found a new way for a nested probe to answer "clean" wrongly (inherited superproject `GIT_*`, status config blindness, the submodule's OWN flagged entries, a symlink standing in for the directory) — and it stays a CONVERGING refusal, since clearing the bit is a recovery the guard prints and then falls silent on. An UNflagged submodule is judged by the ordinary probe exactly as before. **Fail-closed:** an undecidable git probe refuses with its own named cause, never a silent pass;
|
|
10
|
-
2. **a CONTENT-FREE fingerprint over a DIRTY index** — the payload carries no bytes while the index really carries a change
|
|
10
|
+
2. **a CONTENT-FREE fingerprint over a DIRTY index** — the payload carries no bytes while the index really carries a change: staged content the payload cannot see. No receipt can describe what that commit will carry, so the guard refuses fail-closed. Recovery names no flag or config key: make the staged change visible to `git diff --cached`, then re-run the resolved `run-gates --final`; re-staging alone is not the recovery because the change is already staged;
|
|
11
11
|
3. no completed final record for the CURRENT fingerprint (the tree moved after the final run — any edit re-stales it);
|
|
12
12
|
4. a RED latest attempt (a dead green never revives — the latest attempt at a fingerprint is authoritative);
|
|
13
13
|
5. fingerprint before ≠ after on the receipt (the tree moved UNDER the final run);
|
|
@@ -24,7 +24,7 @@ Run `node ${CLAUDE_SKILL_DIR}/tools/commit-guard.mjs --check [--cwd <dir>]` —
|
|
|
24
24
|
|
|
25
25
|
**Boundary — what «the commit captures the tree» means for submodules.** The guard proves the SUPERPROJECT commit captures the SUPERPROJECT working tree. A superproject commit stores a submodule as a gitlink OID and never captures its file content — that content is the submodule's own commit boundary. The dirty-submodule refusal is therefore a best-effort COURTESY beyond the guard's boundary, and its completeness is bounded by what the submodule itself reports: a file held behind a `skip-worktree` / `assume-unchanged` bit in the SUBMODULE's own index is invisible to the submodule's status and so to this refusal. Deepening the nested probe was tried and abandoned — three consecutive review rounds each produced a new way for it to answer wrongly — so the honest contract is the boundary, not a completeness claim. Tracked as its own class.
|
|
26
26
|
|
|
27
|
-
**Stated residual — the
|
|
27
|
+
**Stated residual — the payload flags close the config-blind class.** The fingerprint argv in the ONE node home, `core-evidence.mjs`, carries `--no-textconv --ignore-submodules=none` beside `--no-ext-diff`; both bash twins are parity-pinned to that set for their fingerprint and review-payload diffs, so host textconv and submodule-ignore configuration cannot hide staged bytes. Refusal 2 remains the fail-closed backstop for any DIRTY index whose staged content the payload still cannot see: it names making the change visible to `git diff --cached` and re-running the final gate, without guessing a flag or configuration key.
|
|
28
28
|
|
|
29
29
|
**Human residual (stated, accepted):** `git commit --no-verify` bypasses any pre-commit hook — a self-discipline mechanism, not a security boundary.
|
|
30
30
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
### Mode: control-bytes
|
|
2
|
+
|
|
3
|
+
<!-- opt-in-capability: none — a read-only gate entry; declaring the gate matrix is covered by gates-declaration -->
|
|
4
|
+
|
|
5
|
+
Read-only **control-byte gate** over the work tree — it makes *"a raw control byte in a source"* a
|
|
6
|
+
mechanical refusal instead of a reviewer's find. Measured 2026-08-30: an editor tool wrote a raw NUL
|
|
7
|
+
into a test source, git classed the file as binary, and a NUL-carrying blob is exactly what a
|
|
8
|
+
letter-level checker skips by kind. This mode judges BYTES, never letters, so it is language-neutral:
|
|
9
|
+
every consumer of the kit can declare it, whatever language the project is written in.
|
|
10
|
+
|
|
11
|
+
**What it judges.** The review-payload domain over the WORK TREE, from the work-tree root: tracked
|
|
12
|
+
paths (`git ls-files -z`) plus untracked-not-ignored paths (`git ls-files --others --exclude-standard
|
|
13
|
+
-z`). Three surfaces per path, in this order: the NAME is always judged; a regular file's CONTENT is
|
|
14
|
+
judged unless the attribute skip below covers it (the skip covers content only); a symlink's TARGET
|
|
15
|
+
string is always judged and the link is never followed. A path's kind is the index mode for a tracked
|
|
16
|
+
path (`git ls-files -s -z`; a gitlink is name-only) and the lstat for an untracked one; the descriptor
|
|
17
|
+
the read opens must report the same kind, or the path is unreadable. The predicate is over raw bytes:
|
|
18
|
+
any byte in 0x00–0x08, 0x0B, 0x0C, 0x0E–0x1F or 0x7F refuses; TAB, LF and CR are the only admitted C0
|
|
19
|
+
bytes; bytes at or above 0x80 are not judged (UTF-8 validity and C1 controls are not this tool's
|
|
20
|
+
business). A finding names the path, the surface, the byte offset and the byte in hex; the render is
|
|
21
|
+
injective — bytes decode as UTF-8 where valid, a control or line-separator code point (and a valid
|
|
22
|
+
U+FFFD) renders as `\u{XXXX}`, an invalid byte as `\xNN`, a backslash as `\\` — so no output line carries a raw control
|
|
23
|
+
byte or U+FFFD and two names differing only in an unrenderable byte render differently.
|
|
24
|
+
|
|
25
|
+
**Binary by KIND, never by guess.** A path whose git attribute says `binary` or `-diff` has its
|
|
26
|
+
CONTENT skipped by kind and is NAMED in the summary (one `git check-attr --stdin -z binary diff`
|
|
27
|
+
over the whole domain — git's own answer, global and system attributes files included, because the
|
|
28
|
+
tool runs under your env); its name and target are still judged. There is no extension allow-list
|
|
29
|
+
and no size heuristic — a NUL in an unattributed file is the finding this gate exists for. A fixture
|
|
30
|
+
that genuinely needs a control byte keeps it as an escape in source (`\x00`, `String.fromCharCode(0)`):
|
|
31
|
+
the runtime string is byte-identical and the SOURCE stays clean. A never-committable stat class
|
|
32
|
+
(device, FIFO, socket) and an untracked nested repository (git's `nested/` entry) are skipped by
|
|
33
|
+
kind and counted — name judged, no content surface. On a host that materialises symlinks
|
|
34
|
+
(`core.symlinks=false`) a tracked symlink's placeholder file is judged as its target string.
|
|
35
|
+
|
|
36
|
+
Run `node ${CLAUDE_SKILL_DIR}/tools/control-bytes.mjs [--check] [--cwd <dir>]` (`--cwd` anchors at
|
|
37
|
+
that directory's work-tree root):
|
|
38
|
+
|
|
39
|
+
1. Plain run → the human report: the work-tree root, the counts (paths judged · skipped by attribute,
|
|
40
|
+
each named · skipped by kind · findings), then every finding as one line
|
|
41
|
+
`<path> <surface> offset <n>: 0x<hex>` (`(+N more)` when that surface carries more than one) —
|
|
42
|
+
under the SAME exit table as `--check`: the plain run is never a silent 0.
|
|
43
|
+
2. **`--check`** → the gate spelling: the same report (counts, the named attribute skips, the
|
|
44
|
+
finding lines), then the gate exit code. **Exit 0** clean. **Exit 1** on a finding OR on a refusal —
|
|
45
|
+
refusals never pass and never skip silently, each with its own message: an UNREADABLE path
|
|
46
|
+
(EACCES, EIO, a descriptor whose kind disagrees with the named kind — distinct from an ABSENT
|
|
47
|
+
path git named that vanished before the read; a TRACKED absent path with the skip-worktree bit is
|
|
48
|
+
a sparse checkout, skipped by kind and counted); a git command that fails, is killed by a signal or
|
|
49
|
+
is not on PATH; an UNMERGED index; an EMPTY domain; a file over the read cap (16 MiB — read as at
|
|
50
|
+
most cap+1 bytes on the descriptor, never trusting the fstat size, so a file that grows after the
|
|
51
|
+
fstat still refuses; the message names the cap and the path); a git LOCATION that is not a work
|
|
52
|
+
tree. The location is a closed table of six states shared with the fingerprint and index
|
|
53
|
+
consumers through the kit's git-location leaf, judged on the REALPATH identity of the git dir,
|
|
54
|
+
the common dir and the work-tree top under the ambient env against the discovery from cwd with
|
|
55
|
+
every variable whose upper-cased name starts with `GIT_` removed (a case-insensitive host honours
|
|
56
|
+
`git_dir` too): `work-tree` (all three agree) proceeds; `not-a-repository` (git
|
|
57
|
+
itself answers not-a-git-repository, exit 128); `error` (ENOENT, a synchronous throw, a signal, a
|
|
58
|
+
realpath that cannot resolve, any other non-zero or unparsable answer); `redirected` (any of the
|
|
59
|
+
three differs — `GIT_WORK_TREE` at a second tree with the same git dir, or `GIT_COMMON_DIR` at a
|
|
60
|
+
second repository); `no-work-tree` (the git
|
|
61
|
+
dir agrees but `--show-toplevel` fails: bare, or cwd inside `.git`); `env-only` (the ambient env
|
|
62
|
+
reaches a repository the stripped discovery does not) — each refuses by its own state name. A
|
|
63
|
+
pre-commit hook's own env (`GIT_INDEX_FILE`, `GIT_PREFIX`, `GIT_CONFIG_PARAMETERS`,
|
|
64
|
+
`GIT_EXEC_PATH`) agrees and passes: the check is agreement, never a variable ban. **Exit 2**
|
|
65
|
+
usage — every operand is validated at parse; an unknown argument is usage. Every content read is
|
|
66
|
+
descriptor-bound (open, fstat, read on the descriptor), never a path read that a symlink swap
|
|
67
|
+
could redirect.
|
|
68
|
+
3. **Wire it as a gate by hand — never without consent (AD-021/D9).** The candidate line for your
|
|
69
|
+
own `docs/ai/gates.json`: `{ "id": "control-bytes", "title": "No raw control byte in the work
|
|
70
|
+
tree", "cmd": "node \"<path-to-this-skill>/tools/control-bytes.mjs\" --check" }` — with the path
|
|
71
|
+
your project actually reaches the kit by, double-quoted inside the JSON string so a path with
|
|
72
|
+
spaces survives, executable from the project root. `gates-init` does not offer this entry; the full consent-fill contract for the
|
|
73
|
+
matrix is in `${CLAUDE_SKILL_DIR}/references/modes/gates.md`. Once declared, the opt-in
|
|
74
|
+
`${CLAUDE_SKILL_DIR}/references/modes/hook.md` auto-approves it like any other declared gate.
|
|
75
|
+
|
|
76
|
+
**Honest bounds (stated, accepted):** the work tree is judged at the moment of the read — a byte
|
|
77
|
+
written after the run is caught on the next run, which is why the gate belongs in the pre-commit
|
|
78
|
+
matrix; the attribute is the only "binary" signal, so a binary file with no attribute refuses until
|
|
79
|
+
the project declares it; the tool reports and never edits — the remedy is the escape in source; a
|
|
80
|
+
checkout PATH that is itself not valid UTF-8 is unreachable by any Node consumer (cwd is a string
|
|
81
|
+
before git ever answers) and a non-UTF-8 LINKED git dir or common dir path refuses as `error` — a
|
|
82
|
+
stated bound, not a case this tool judges; `O_NOFOLLOW` guards the
|
|
83
|
+
LEAF only — a parent directory swapped for a symlink between git's answer and the open redirects the
|
|
84
|
+
read (Node exposes no `openat2`/component-wise no-follow walk), so a mid-run parent swap is the same
|
|
85
|
+
moment-of-the-read race bound as a byte written after the run: caught on the next run, inside the
|
|
86
|
+
work tree the gate's verdict still refuses-or-reports, never silently skips.
|
|
87
|
+
|
|
88
|
+
**Invariants:** read-only · never writes · never commits · spawns read-only `git` queries only
|
|
89
|
+
(`ls-files`, `check-attr`, `config --get core.symlinks`, `rev-parse`) · judges bytes, never decoded text · skips by kind only, every
|
|
90
|
+
skip named or counted · exit 0 clean / 1 finding or refusal / 2 usage · `main(argv, deps)` returns,
|
|
91
|
+
never exits.
|
|
@@ -7,7 +7,7 @@ The ONE **loop-evidence writer** (strip-the-kit D6a/D7) — every core evidence
|
|
|
7
7
|
Run `node ${CLAUDE_SKILL_DIR}/tools/core-evidence.mjs <verb> …`:
|
|
8
8
|
|
|
9
9
|
1. **`red-proof "<test-file>#<test-name-pattern>"`** — the D3(c) observed-red DECLARATION, minted **BEFORE a bugfix is applied**: it runs the named test N times (default 3, `AW_CORE_EVIDENCE_RERUNS`; per-run timeout `AW_CORE_EVIDENCE_TIMEOUT_S`) on the CURRENT (pre-fix) tree, requires red N/N (observed green / unresolvable / mixed / timed-out are DISTINGUISHED refusals — nothing is written; mixed/timeout is QUARANTINE, no override lane), and records { testId · repo-relative file · content sha256 (custody) · N/N red · base = HEAD sha · the pre-fix tree fingerprint }. The final run (`coverage-check --check`) then requires every current-base record's test green N/N with the hash unchanged; a record whose pre-fix fingerprint EQUALS the current tree never satisfies (nothing changed — reuse/forgery); a commit expires records (base moves); editing a bound test file means re-observing red (the new record supersedes the old — same {base, testId} key).
|
|
10
|
-
2. **`degrade --backend <name> --reason "<why>"`** — the ONLY escape from a required review backend (D3(b)): an explicit per-backend record at the CURRENT fingerprint. Never all backends: the review gate still requires ≥1 non-degraded ship-class receipt whenever ≥1 backend is configured. Any tree edit that MOVES the fingerprint re-stales
|
|
10
|
+
2. **`degrade --backend <name> --reason "<why>"`** — the ONLY escape from a required review backend (D3(b)): an explicit per-backend record at the CURRENT fingerprint. The backend name also has a second reading: the execute wrapper name `codex-exec` is the accepted-replacement escape honoured by the held-session arm; for the held-session arm the record binds the substituted return's `postTreeDigest` and keeps standing after later folds move the tree; the record form and writer are unchanged, and the review receipt id `codex` never grants that escape. Never all review backends: the review gate still requires ≥1 non-degraded ship-class receipt whenever ≥1 backend is configured. Any tree edit that MOVES the fingerprint re-stales a review-backend degrade record — which is every edit the payload can see, and no more: a change the payload cannot see (a gitlink hidden from `git diff` by an ignore configuration) leaves the record standing. **The per-tree claim has one honest exception, and it is not a corner case:** a degrade minted while the work tree is CLEAN binds the CONTENT-FREE fingerprint — the one value every clean moment of every repository shares — so it identifies no working state and, since the record carries no base, no moment either. Such a record is therefore OUTSIDE the `#64` degrade-before-final ordering rung (`flow-check` records the skip as an advisory naming how many were skipped), because the ORDER of two records that cannot be shown to belong to the same moment states nothing about any tree. The writer still accepts it — refusing would strand the one lane that honestly records an unavailable backend during a plan round, which attests no tree at all. Closing the exception needs a durable `base` on the record, which is the queued store migration.
|
|
11
11
|
3. **`summary`** — the ONE stateless end-of-loop render (D6): gate result from the latest final attempt, per-backend verdicts from the review receipts, red-proof outcomes, degrade records. Computed from the stores at read time — no ledger, no rounds, nothing remembered. A malformed store exits non-zero and WITHHOLDS the affected section, never renders a partial as complete. The final-run line NAMES an absent coverage verdict from the `coverage` token the run RECORDED (an ADDITIVE optional field on the `final` record — the closed `certified | not-run | unknown` set, never `none`, and `certified` requires a bound `lcovSha256`): GREEN never renders unqualified over a run that issued no verdict. A LEGACY receipt carrying no token and no lcov digest is named as exactly that, never as a claim about what it read — the withheld verdict travels here too, as DETAIL beside the unchanged status word.
|
|
12
12
|
|
|
13
13
|
**Promptless writer lane (D7):** both verbs ride plain `node ${CLAUDE_SKILL_DIR}/tools/core-evidence.mjs …` invocations — surface the paste-ready allow entries once (`.claude/settings.json`), and a full loop transcript runs at zero writer approval prompts.
|
|
@@ -19,16 +19,28 @@ Run **`node ${CLAUDE_SKILL_DIR}/tools/flow-writer.mjs <arm> …`** — the arm s
|
|
|
19
19
|
| `degrade-justification --backend <b> [--down-mark <d>] [--degrade-digest <d>]` | binds a core degrade to a then-active down-mark (#25) — both digests resolve automatically; an explicit digest only VERIFIES the resolved authority (a foreign digest never mints), and the store's locked preflight re-refuses a mark closed in the race window |
|
|
20
20
|
| `maintainer-override <planId> --backend <b> --checkpoint-approved` | the checkpoint-approved ship-over-veto record — it **prints the FULL bound set** it is about to record and **requires the explicit flag** (#38); without the flag the bound set still prints and nothing is written |
|
|
21
21
|
| `consult-attestation <planId> --backend <b> --nonce <n> --proposed-fix-digest <d>` | binds a consult to a real dispatch's findings (#11/#33): `findingDigest` is **computed from the `{backend, nonce}`-named finding manifest** beside the receipts file (never hand-supplied); `proposedFixDigest` is the explicit consult-time input; refuses without an open step, or without a readable identity-matching manifest |
|
|
22
|
-
| `round-open <planId> --backend <b> [--backend <b> …] [--step <stepId>] [--new-cycle] [--justification <t>]` | the round's **pre-dispatch half** (#41): mints
|
|
23
|
-
| `round-land <planId> [--dispose
|
|
22
|
+
| `round-open <planId> --backend <b> [--backend <b> …] [--step <stepId>] [--new-cycle] [--justification <t>]` | the round's **pre-dispatch half** (#41): mints before any backend runs and applies the cap, walk and completeness gates detailed below |
|
|
23
|
+
| `round-land <planId> [--dispose <action> …]` | the round's **post-arrival half** (#42/#13/#33): binds exact arrivals and records one of the five dispositions detailed below |
|
|
24
24
|
| `freeze <planId>` / `converged <planId>` | the step terminals, gated on **completeness + the sanctioned-move rule** (no premature terminal): every dispatch landed or **justified-degraded** at the dispatched tree (a core degrade + a mint-time-valid `degrade-justification` at the round's `{base, fingerprint}` — a bare degrade is not base-bound); every landed non-ship receipt rides a round with a non-empty disposition ledger (a form floor — semantic per-finding completeness is an honest limit); the tree sits at the last round's fingerprint or reached it through an **anchored** declared bookkeeping-delta chain + refresh (a pre-round chain never re-certifies a later move). Both walks **re-run on the locked store snapshot** at append time |
|
|
25
25
|
| `unfreeze <planId> [--justification <t>]` | reopens the frozen step (in-step) or the just-converged terminal (boundary); **cap 1 per cycle** — the design's post-freeze checkpoint |
|
|
26
|
-
| `internal-attestation <planId> --lens <l> … [--degraded <b> …] --model <m> [--effort <e>] [--tier <t>] --authority <a
|
|
26
|
+
| `internal-attestation <planId> --lens <l> … [--degraded <b> …] --model <m> [--effort <e>] [--tier <t>] --authority <a> [--walk <file>]` | the #28 internal-review attestation at the open step's round, gated on #68 adoption coverage. `--walk` is a capped, no-follow closed JSON file relative to the absolute git common dir; for every judged plan row every class in TAGGED ∪ PRESENT needs non-empty `checked`, while extra entries are ignored and PRESENT minus TAGGED is recorded as `walk.uncovered`. |
|
|
27
27
|
| `write-plan-id <plan-file> --plan-id <id>` | adds the frontmatter `planId` line — bounded to an EXISTING regular file under `docs/plans/` (never a symlink), contained-atomic, same-id idempotent, **different-id refuses** (#58) |
|
|
28
28
|
|
|
29
|
+
`round-open` mints the round record BEFORE any backend runs — per `--backend` a fresh nonce + receipts watermark; stdout prints one `dispatch backend=<b> nonce=<n> watermark=<w>` line per dispatch (pass the nonce as `--nonce <n>` on the wrapper invocation — the plain-argument lane onto the `AW_REVIEW_NONCE` seam; hand the pair to `receipt-deadline`).
|
|
30
|
+
|
|
31
|
+
Every round after the first requires an authoritative walk-carrying attestation at the preceding round's `{planId, cycle, stepId, round}` and the CURRENT tree's `{base, fingerprint}` when the adopted plan has a judgeable ledger row; `--justification` may lift that absence as an echoed input, and the ABSENCE of the attestation is its durable trail. At `cap reached` or `crossover`, every blocking item from the latest head's landed receipts must be covered by equal item digest: uncovered items print verbatim, enumeration failure is an advisory plus the existing disposition floor, and a lost manifest is covered only by `custody-lost`; this cap refusal is never lifted by `--justification`.
|
|
32
|
+
|
|
33
|
+
Both lock-free and locked `round-open` checks run cap → walk → completeness floor. Boundary invocations need `--step`; `--new-cycle` opens the next cycle; a fingerprint move opens a new round.
|
|
34
|
+
|
|
35
|
+
For `round-land`, exactly one fresh code-artifact non-probe line of the dispatched backend **carrying the dispatch's exact nonce** (the wrapper stamps `AW_REVIEW_NONCE` into the receipt — a delayed or cross-chain answer can never cross-bind) past the watermark is the candidate, and only the canonical **ATTESTING** class binds. It revises the ONE round record in place with five closed actions.
|
|
36
|
+
|
|
37
|
+
`folded --finding <quote> --proof-kind … --proof-digest <d>` and `rejected --finding <quote> --reason <r>` retain their bindings; `queued --finding <quote> --claim <invariant> --proof-kind consult-attestation|red-proof --proof-digest <d>` requires `decideFoldScope` ACCEPT, derives `debtId` from the resolved row and computes `debtDigest` from its block, then binds the proof to this head, item and claim.
|
|
38
|
+
|
|
39
|
+
`escalated --finding <quote> --override-digest <d>` binds a veto override and only that receipt's findings; `custody-lost --receipt <receiptDigest>` carries no quote, is recordable whenever the carrier loss is real, covers that receipt for the cap, and excludes it from later manifest re-reads. Arrivals still bind only canonical attesting receipts and identity-matching manifest bytes.
|
|
40
|
+
|
|
29
41
|
Operand shapes: a positional operand may follow a literal `--` and a value flag accepts `--flag=<value>` — the lanes a leading-dash id or value rides; the checker's printed recoveries compose exactly these shapes. Every arm computes its **tree context** (owner, base, fingerprint; cycle/round from the chain walk) — you never hand-supply tree identity. Chain arms **refuse a foreign worktree's chain** (#57): move a chain only from the worktree that adopted it.
|
|
30
42
|
|
|
31
|
-
**Round-machinery caps (enforced at the arms; the store owns transition legality):** HARD_MAX **3 rounds per {cycle, step}** and **1 post-freeze unfreeze per cycle**.
|
|
43
|
+
**Round-machinery caps (enforced at the arms; the store owns transition legality):** HARD_MAX **3 rounds per {cycle, step}** and **1 post-freeze unfreeze per cycle**. The walk obligation holds when the adopted plan's ledger parses with at least one valid row; a plan with no judgeable row owes no walk. Both lock-free and locked round-open checks run cap → walk → completeness floor. The justification predicate is `overCap || walkRefusalFired`: a non-empty justification lifts only a design-cap or missing-walk refusal and is echoed; an in-cap invocation with its walk satisfied refuses it as usage. The blocking-item cap is independent and never lifted. A `custody-lost` entry is recordable whenever the carrier loss is real. One-way door: records carrying `walk`, the queued proof trio, `escalated`, or `custody-lost` require kit >= 11 to read; pre-rung records remain valid.
|
|
32
44
|
|
|
33
45
|
**Exit codes:** `0` success (incl. the `write-plan-id` idempotent no-op); `2` usage; `1` refusal (a store STOP verbatim, a derivation failure, or the missing checkpoint flag).
|
|
34
46
|
|
|
@@ -18,7 +18,9 @@ Run **`node ${CLAUDE_SKILL_DIR}/tools/procedures.mjs <activity> [--override <slo
|
|
|
18
18
|
2. **Default resolution (config silent):** `review` → Reviewed if any review-capable backend is `ready`, else Solo (never Council by default); `execute`, `author`, `fold`, `carrier` → Solo (Delegated and Subagent are opt-in; a placed executor never flips a default); `parallel` → on. **Degradation:** a config/computed default degrades **gracefully with a stated reason** (Council → Reviewed → Solo; Delegated → Solo; Subagent → Solo when the executor vehicle is missing or unusable, the reason naming the apply command; a switch never degrades); a per-run **`--override <slot>=<value>`** that can't be satisfied degrades **loudly** (a flagged warning, so you tell the user) — but is **still exit 0** (a valid request that gracefully degraded).
|
|
19
19
|
3. **Exit codes:** `0` success; `2` usage (unknown `<activity>` / bad `--override` — a bare `--override <recipe>`, an unknown slot, a value outside the slot's list, or a duplicate slot); `1` config error (malformed / schema-invalid / unreadable `orchestration.json`) **or** engine error (the installed engine is absent / invalid / **too old** to ship `references/procedures.md` — upgrade it with `npx @sabaiway/agent-workflow-engine@latest init`). A `1`/`2` failure is loud (`path: reason`), never a silent fallback. **Lagging-kit honesty:** a kit predating the `"flow"` key that reads a config carrying one fails this config load loudly (exit `1`, reddening its full gate matrix); the `set-flow` arming path now enforces the declared `kitMinVersion` floor with a null-guarded comparison (an unparseable version never passes), while tolerate-first ordering remains the only protection for readers older than the `"flow"` key itself — no in-config floor can reach a kit that dies on the unknown key.
|
|
20
20
|
|
|
21
|
-
**The dispatch form (a slot resolved to `subagent`).** A carrier that is only NAMED is a name, not an instruction, so after such a slot's resolved-recipe line the advisor prints — indented under it, in place of the one-line vehicle mention — the form the dispatch must take, in five parts: (1) what a SLICE is for THIS slot — for `execute`, a set of file-disjoint ledger rows, wording copied verbatim where wording is a red line; for `author`, a brief naming the goal, the governing spec(s) and the ledger constraints, whose returned draft the orchestrator reviews as its own; for `fold`, the round's findings with their dispositions, whose edits the orchestrator follows with the self-consistency read; for `routine.carrier`, a bounded mechanical task, where a read-only chore (a sweep, gate triage) rides its placed read-only vehicle — or is carried solo with a stated reason when that vehicle is absent — a write-capable one (a regeneration, a fixture build) rides the executor, and the changelog stays the orchestrator's; (2) the vehicle and its surveyed state — `.claude/agents/executor.md` (`placed` / `customized` / `unusable` / `missing`, from the same survey `status` and the advisor read) — dispatched **in the background**; (3) that the orchestrator **verifies every returned slice by running its suites itself**; (4) that the subagent is **never told to commit, never a review backend, never a bridge substitute**; (5) the **honest limit** — a Claude Code lane: on a host that cannot dispatch the vehicle, follow this form BY HAND and say so, never report it as a subagent dispatch. The wording is the kit's own (`tools/carriers.mjs`) and is printed, never re-worded.
|
|
21
|
+
**The dispatch form (a slot resolved to `subagent`).** A carrier that is only NAMED is a name, not an instruction, so after such a slot's resolved-recipe line the advisor prints — indented under it, in place of the one-line vehicle mention — the form the dispatch must take, in five parts: (1) what a SLICE is for THIS slot — for `execute`, a set of file-disjoint ledger rows, wording copied verbatim where wording is a red line; for `author`, a brief naming the goal, the governing spec(s) and the ledger constraints, whose returned draft the orchestrator reviews as its own; for `fold`, the round's findings with their dispositions, whose edits the orchestrator follows with the self-consistency read; for `routine.carrier`, a bounded mechanical task, where a read-only chore (a sweep, gate triage) rides its placed read-only vehicle — or is carried solo with a stated reason when that vehicle is absent — a write-capable one (a regeneration, a fixture build) rides the executor, and the changelog stays the orchestrator's; (2) the vehicle and its surveyed state — `.claude/agents/executor.md` (`placed` / `customized` / `unusable` / `missing`, from the same survey `status` and the advisor read) — dispatched **in the background**; (3) that the orchestrator **verifies every returned slice by running its suites itself**; (4) that the subagent is **never told to commit, never a review backend, never a bridge substitute**; (5) the **honest limit** — a Claude Code lane: on a host that cannot dispatch the vehicle, follow this form BY HAND and say so, never report it as a subagent dispatch. The wording is the kit's own (`tools/carriers.mjs`) and is printed, never re-worded. The dispatch-form branch is unchanged for a slot resolved to `solo` or `delegated`.
|
|
22
|
+
|
|
23
|
+
**Fold lane (an execute slot resolved to `delegated`).** Immediately after that slot's driving contract, the advisor renders `codex-exec --resume <held id> --nonce <nonce> <fold-brief>` under the populated `run:` prefix, with the audited ledger's held id shell-quoted. `<nonce>` and `<fold-brief>` stay placeholders. One `caveat:` line replaces the id in each no-id case: no ledger; no folded code session in the commit epoch; a recorded substitution; an unresolvable, unreadable, malformed or audit-refused ledger (the reader reason verbatim); a failed HEAD read; or an id a one-line render cannot carry. An unborn branch runs the judge and is not a caveat. The block is advisory and never changes the exit code; `foldLane` carries the identical lines under `--json`, and is `[]` outside `plan-execution` or when execute resolves to Solo or Subagent. The sidecar is never read.
|
|
22
24
|
|
|
23
25
|
**`routine`'s `parallel` switch renders against the EFFECTIVE carrier.** The flag always renders with its source (`parallel: on` / `parallel: off`); the concurrency claim — *file-disjoint slices dispatch concurrently* — renders **only** while the resolved `carrier` is `subagent`. Under a `solo` carrier the line states its own inertness instead, `(no effect while the carrier is solo)`: a switch never degrades, so the flag keeps the value you set and the render simply stops promising a concurrency nothing can perform. That makes four cells (`on`/`off` x `subagent`/`solo`), and only the `subagent`+`on` cell claims concurrency.
|
|
24
26
|
|
|
@@ -34,6 +36,8 @@ Run **`node ${CLAUDE_SKILL_DIR}/tools/procedures.mjs <activity> [--override <slo
|
|
|
34
36
|
|
|
35
37
|
**Spec-store block (the feature-spec layer, `plan-execution` only).** After a `plan-execution` render the advisor also prints `Spec store (the feature-spec layer) — …`: the two POPULATED `spec-check` commands and the session register they read. **Session lane** — `--ops-file docs/plans/spec-ops.list` (or repeated `--op <add|modify|remove>=<path>` / `rename=<old>:<new>`) judges the closure of the declared change: the targets plus each one's listing parent, on their post-state, their reader verdict, their per-kind line cap, their scenario bindings and the containment of every path they name. **Store lane** — `--all` judges the whole store instead and adds the four cross-document invariants (an unlisted child, DISTINCT from an orphan · acyclicity · store-wide slug uniqueness · module overlap); an absent store root refuses the run rather than reporting an empty clean store. The two lanes are exclusive. **Register lifecycle:** `docs/plans/spec-ops.list` is *session scratch* — the session writes it, the plan's Phase Cleanup deletes it — and it is **never defaulted** by the tool, because an unnamed register would attest a post-state nobody declared (the `fold-scope --queue` precedent). `--json` carries the same lines under **`specCheck`** (an empty array outside `plan-execution`). Advisory like the finding-scope block: nothing records that it ran. Exit `0` clean · `1` findings · `2` usage.
|
|
36
38
|
|
|
39
|
+
**Robustness-brief block (`plan-execution` only).** The advisor renders `node ${CLAUDE_SKILL_DIR}/tools/robustness-brief.mjs --plan <plan>` populated when exactly one plan is in flight and names the zero/several-plan placeholder reason otherwise. `--json` carries the identical lines under **`robustnessBrief`**, an empty array outside `plan-execution`; human and structured renders share one block.
|
|
40
|
+
|
|
37
41
|
**Cap-soft-skip degradation (the feature's only AUTO route).** The activity procedures are auto-discoverable only through the one-line **`workflow:methodology`** pointer (this kit + the engine carry `disable-model-invocation:true`, so NL like "write a plan" does **not** auto-load this skill). On a deployment whose methodology pointer was cap-soft-skipped — or whose pre-existing customized pointer lacks the procedures clause — the procedures are still reachable by **explicitly** invoking `/agent-workflow-kit procedures`; surface that plainly rather than treating it as a gap.
|
|
38
42
|
|
|
39
43
|
**Invariants:** read-only · never writes · never commits · never runs a subscription CLI · the deterministic resolution is the kit's, the recipe execution is the orchestrator's.
|
|
@@ -6,10 +6,10 @@ Read-only **review-receipt checker** (AD-038) — it makes *"reviewed ≠ shippe
|
|
|
6
6
|
|
|
7
7
|
Run `node ${CLAUDE_SKILL_DIR}/tools/review-state.mjs [--check] [--json]`:
|
|
8
8
|
|
|
9
|
-
1. Plain run → the human report: resolved recipe + source, plan-in-flight, tree fingerprint, per-backend receipt state (current / stale / ungrounded / probe / rejected / missing) with verdict + grounding + timestamp.
|
|
10
|
-
2. **`--check`** → the gate exit code. The **normative exit contract lives in the tool header** (the single home — do not re-enumerate it elsewhere): exit 0 for a CONFIGURED solo recipe (a computed readiness-degrade NEVER silently becomes solo — it needs the explicit degrade record below), no plan in flight (the `docs/plans` naming convention: `queue.md` and `EXECUTE-`/`FEEDBACK-`-prefixed or `PROMPT`/`prompt`/`handoff`-carrying names are scratch), a clean tree, a non-
|
|
9
|
+
1. Plain run → the human report: resolved recipe + source, plan-in-flight, tree fingerprint, the `held session: <id> — <n> fold(s) rode it` / `none` / substitution line when configured delegated execution arms it, and per-backend receipt state (current / stale / ungrounded / probe / rejected / missing) with verdict + grounding + timestamp.
|
|
10
|
+
2. **`--check`** → the gate exit code. Before the review-recipe early return, a configured `plan-execution.execute = delegated` with a plan in flight and a dirty, fingerprintable tree audits the delegation ledger and refuses a substituted held session; an absent ledger is inert, while an unreadable, malformed, foreign, audit-refused ledger or failed HEAD read fails closed with its own reason. The accepted-replacement escape is a `codex-exec` degrade at the substituted return's tree, standing after every later fold, never the review receipt id `codex`. The remaining **normative exit contract lives in the tool header** (the single home — do not re-enumerate it elsewhere): exit 0 for a CONFIGURED solo recipe (after the held-session arm above) (a computed readiness-degrade NEVER silently becomes solo — it needs the explicit degrade record below), no plan in flight (the `docs/plans` naming convention: `queue.md` and `EXECUTE-`/`FEEDBACK-`-prefixed or `PROMPT`/`prompt`/`handoff`-carrying names are scratch), a clean tree, a cwd where git ITSELF answers not-a-repository under both discoveries (the ONLY non-work-tree location that passes — `error`, `redirected`, `no-work-tree` and `env-only` refuse by their state name once a receipt could be required), or every recipe-named backend SATISFIED for the current tree. **A clean-tree PASS under a NON-SOLO review obligation is never silent about a latent arm:** when a `reviewed` or `council` recipe is configured, it NAMES every plan in flight and states that this gate arms as soon as the tree is dirty — the condition is discoverable BEFORE it blocks, instead of surfacing at the worst moment (a pending commit, or the landing of a feature worktree when main first turns dirty). Nothing is announced under a configured `solo` recipe or a not-a-repository cwd, where the gate can never arm. **Satisfaction is ship-class-only on the LATEST NORMAL receipt (D3(b)):** per backend, the latest probe-free current-fingerprint receipt is selected FIRST and THEN verdict-checked — only the recognized ship-class vocabulary (`ship` / `ship with nits`) satisfies; a recognized NEGATIVE (`revise` / `rethink` / `rework`) is an authoritative VETO (an earlier ship never survives a later revise); an UNRECOGNIZED verdict (e.g. `unknown` from a dead run) fails CLOSED unconditionally — a later `unknown` never lets an earlier SHIP stand, and a fresh normal re-run supersedes it. **The ONLY review-backend escape is an explicit degrade RECORD** (`core-evidence.mjs degrade --backend <name> --reason "…"`, fingerprint-bound to the current tree) — and never all backends: ≥1 non-degraded ship-class receipt is required whenever ≥1 backend is configured; a malformed evidence store denies the escape fail-closed but never fails an independently-satisfied tree. Exit 1 otherwise — missing, **stale** (ANY edit after a review moves the fingerprint), ungrounded, vetoed, or unrecognized. Plan/diff receipts and continuations (`agy-review --continue`) are **informational-only**: after a fold, only a **fresh grounded re-run** (`codex-review code`; `agy-review code --facts @f`) restores green. **Probe receipts never attest either:** a `CODEX_PROBE=1` / `AGY_PROBE=1` review runs with the frontier-model/max-effort guard OFF, so the wrapper stamps `probe:true` and this checker excludes it — per receipt, so a real review at the same fingerprint still satisfies. **Silence is not a declaration:** a malformed *or* absent probe marker is rejected fail-closed and stated in the check line. Honest bound: receipts are **not authenticated** (a forger could write `probe:false` as easily as any other field) — like the rest of the receipt this is a self-discipline mechanism, not a security boundary.
|
|
11
11
|
3. **Wire it as a gate by hand OR via the explicit-consent init preview — never without consent (AD-021/D9).** The candidate line for your own `docs/ai/gates.json`: `{ "id": "review-state", "title": "Review receipts current for the uncommitted tree", "cmd": "node <path-to-this-skill>/tools/review-state.mjs --check" }` — with the path your project actually reaches the kit by, QUOTED so a path with spaces survives, executable from the project root. The consent-gated gates-init preview — `node ${CLAUDE_SKILL_DIR}/tools/gates-init.mjs --cwd <project>` (dry-run: it prints the derived entries and writes NOTHING; `--apply --only review-state` writes exactly this one on your explicit yes) — offers exactly this entry, path resolved and quoted, ONLY when your `docs/ai/orchestration.json` declares `reviewed`/`council` on `plan-execution.review` (the slot this checker enforces). The full consent-fill contract is in `${CLAUDE_SKILL_DIR}/references/modes/gates.md`. Once declared, the opt-in `${CLAUDE_SKILL_DIR}/references/modes/hook.md` auto-approves it like any other declared gate — and `run-gates --final` requires this check among its canonical core gates.
|
|
12
|
-
4. **`--await [--timeout <s>]`** (BUGFREE-3 / AD-049) → BLOCK until every recipe-named backend is SATISFIED for the current tree (i.e. until `--check` would PASS), or the bounded timeout elapses (a loud exit 1; default 900s). Run it after dispatching the review bridges to WAIT for their receipts to land instead of hand-polling a pid: the durable completion signal is the **receipt**, never a process event (a harness "completed" notification fires early; a bridge's output late-flushes). It inherits the `--check` decision whole — a backend with a current-tree degrade RECORD stops being waited on (the shared decideCheck), so you never hand-`--await` around a known degrade. **
|
|
12
|
+
4. **`--await [--timeout <s>]`** (BUGFREE-3 / AD-049) → BLOCK until every recipe-named backend is SATISFIED for the current tree (i.e. until `--check` would PASS), or the bounded timeout elapses (a loud exit 1; default 900s). Run it after dispatching the review bridges to WAIT for their receipts to land instead of hand-polling a pid: the durable completion signal is the **receipt**, never a process event (a harness "completed" notification fires early; a bridge's output late-flushes). It inherits the `--check` decision whole — a backend with a current-tree degrade RECORD stops being waited on (the shared decideCheck), so you never hand-`--await` around a known degrade. A held-session refusal and an **AUTHORITATIVE veto terminate the wait loudly BEFORE the deadline**: neither can be moved by waiting; only the held-session retry/degrade lane or a fresh review can move its corresponding refusal. Still read-only (it re-reads the receipts + the evidence store); solo / no-plan / clean-tree resolve instantly. For waiting on **one dispatch's arrival** (never obligation satisfaction) use the receipt-arrival deadline runner, `${CLAUDE_SKILL_DIR}/references/modes/receipt-deadline.md`.
|
|
13
13
|
|
|
14
14
|
**Human residual (stated, accepted):** `git commit --no-verify` and receipt-file deletion/forgery remain possible — this is a self-discipline mechanism against silent process drift, not a security boundary.
|
|
15
15
|
|