create-agent-rig 0.5.0 → 0.6.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 +140 -34
- package/README.md +12 -6
- package/package.json +1 -1
- package/packages/cli/dist/commands/init.js +6 -3
- package/packages/cli/dist/commands/upgrade.js +2 -2
- package/packages/cli/dist/index.js +46 -8
- package/packages/cli/dist/lib/manifest.js +10 -0
- package/scripts/prepare.mjs +1 -1
- package/templates/agent-os/init/AGENTS.md +11 -3
- package/templates/agent-os/init/CLAUDE.md +11 -3
- package/templates/agent-os/stack/aws-cdk/.agents/skills/post-deploy-verify/SKILL.md +8 -1
- package/templates/agent-os/stack/aws-cdk/.claude/agents/cdk-diff-reviewer.md +8 -1
- package/templates/agent-os/stack/aws-cdk/.claude/skills/post-deploy-verify/SKILL.md +8 -1
- package/templates/agent-os/stack/aws-cdk/.codex/agents/cdk-diff-reviewer.toml +1 -1
- package/templates/agent-os/stack/node-ts/.claude/rules/node-ts.md +29 -0
- package/templates/agent-os/universal/.agents/skills/check-premises/SKILL.md +4 -1
- package/templates/agent-os/universal/.agents/skills/loop/SKILL.md +298 -16
- package/templates/agent-os/universal/.agents/skills/pr-ship/SKILL.md +64 -6
- package/templates/agent-os/universal/.claude/agents/code-reviewer.md +8 -1
- package/templates/agent-os/universal/.claude/agents/prose-reviewer.md +8 -1
- package/templates/agent-os/universal/.claude/agents/security-scanner.md +8 -1
- package/templates/agent-os/universal/.claude/hooks/gate-stop-dod.mjs +28 -3
- package/templates/agent-os/universal/.claude/hooks/guard-rulebook.mjs +127 -0
- package/templates/agent-os/universal/.claude/hooks/lib/edit-input.mjs +23 -0
- package/templates/agent-os/universal/.claude/rules/autonomy.md +8 -0
- package/templates/agent-os/universal/.claude/rules/invariants.md +33 -3
- package/templates/agent-os/universal/.claude/scripts/decision-router.mjs +19 -1
- package/templates/agent-os/universal/.claude/scripts/doctor.mjs +351 -0
- package/templates/agent-os/universal/.claude/scripts/lib/gate-coverage.mjs +306 -0
- package/templates/agent-os/universal/.claude/scripts/lib/revalidation-points.mjs +28 -0
- package/templates/agent-os/universal/.claude/scripts/lib/verdict.mjs +37 -8
- package/templates/agent-os/universal/.claude/scripts/preflight.mjs +27 -1
- package/templates/agent-os/universal/.claude/scripts/queue/as-of.mjs +51 -0
- package/templates/agent-os/universal/.claude/scripts/queue/checkout.mjs +62 -2
- package/templates/agent-os/universal/.claude/scripts/queue/core.mjs +479 -9
- package/templates/agent-os/universal/.claude/scripts/queue/github-issues.mjs +89 -15
- package/templates/agent-os/universal/.claude/scripts/queue/index.mjs +138 -15
- package/templates/agent-os/universal/.claude/scripts/queue/jira.mjs +394 -46
- package/templates/agent-os/universal/.claude/scripts/queue/plan-md.mjs +68 -5
- package/templates/agent-os/universal/.claude/scripts/revalidate.mjs +316 -0
- package/templates/agent-os/universal/.claude/scripts/revalidation-report.mjs +180 -0
- package/templates/agent-os/universal/.claude/scripts/run-state.mjs +101 -3
- package/templates/agent-os/universal/.claude/scripts/stop-flag.mjs +15 -8
- package/templates/agent-os/universal/.claude/scripts/unattended-flag.mjs +239 -0
- package/templates/agent-os/universal/.claude/scripts/verdict.mjs +101 -4
- package/templates/agent-os/universal/.claude/settings.json +5 -1
- package/templates/agent-os/universal/.claude/skills/check-premises/SKILL.md +4 -1
- package/templates/agent-os/universal/.claude/skills/loop/SKILL.md +298 -16
- package/templates/agent-os/universal/.claude/skills/pr-ship/SKILL.md +64 -6
- package/templates/agent-os/universal/.codex/agents/code-reviewer.toml +1 -1
- package/templates/agent-os/universal/.codex/agents/prose-reviewer.toml +1 -1
- package/templates/agent-os/universal/.codex/agents/security-scanner.toml +1 -1
- package/templates/agent-os/universal/.codex/hooks.json +6 -1
- package/templates/agent-os/universal/AGENTS.md +3 -1
- package/templates/agent-os/universal/CLAUDE.md +3 -1
- package/templates/agent-os/universal/docs/decisions/gate-coverage.md +83 -0
- package/templates/agent-os/universal/docs/decisions/two-empty-endings.md +18 -6
- package/templates/agent-os/universal/layers.json +9 -0
- package/templates/hash-history.json +309 -49
- package/templates/release-ledger.json +9 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"hooks": {
|
|
4
4
|
"PreToolUse": [
|
|
5
5
|
{
|
|
6
|
-
"matcher": "Write|Edit|apply_patch",
|
|
6
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|apply_patch",
|
|
7
7
|
"hooks": [
|
|
8
8
|
{
|
|
9
9
|
"type": "command",
|
|
@@ -19,6 +19,11 @@
|
|
|
19
19
|
"type": "command",
|
|
20
20
|
"command": "node \"$(git rev-parse --show-toplevel)/.claude/hooks/guard-secret-file.mjs\"",
|
|
21
21
|
"commandWindows": "powershell.exe -NoProfile -NonInteractive -EncodedCommand JAByAGUAcABvAFIAbwBvAHQAIAA9ACAAZwBpAHQAIAByAGUAdgAtAHAAYQByAHMAZQAgAC0ALQBzAGgAbwB3AC0AdABvAHAAbABlAHYAZQBsADsAIABpAGYAIAAoACQATABBAFMAVABFAFgASQBUAEMATwBEAEUAIAAtAG4AZQAgADAAKQAgAHsAIABlAHgAaQB0ACAAJABMAEEAUwBUAEUAWABJAFQAQwBPAEQARQAgAH0AOwAgACQAaABvAG8AawBQAGEAdABoACAAPQAgAEoAbwBpAG4ALQBQAGEAdABoACAAJAByAGUAcABvAFIAbwBvAHQAIAAnAC4AYwBsAGEAdQBkAGUALwBoAG8AbwBrAHMALwBnAHUAYQByAGQALQBzAGUAYwByAGUAdAAtAGYAaQBsAGUALgBtAGoAcwAnADsAIAAmACAAbgBvAGQAZQAgACQAaABvAG8AawBQAGEAdABoADsAIABlAHgAaQB0ACAAJABMAEEAUwBUAEUAWABJAFQAQwBPAEQARQA="
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"type": "command",
|
|
25
|
+
"command": "node \"$(git rev-parse --show-toplevel)/.claude/hooks/guard-rulebook.mjs\"",
|
|
26
|
+
"commandWindows": "powershell.exe -NoProfile -NonInteractive -EncodedCommand JAByAGUAcABvAFIAbwBvAHQAIAA9ACAAZwBpAHQAIAByAGUAdgAtAHAAYQByAHMAZQAgAC0ALQBzAGgAbwB3AC0AdABvAHAAbABlAHYAZQBsADsAIABpAGYAIAAoACQATABBAFMAVABFAFgASQBUAEMATwBEAEUAIAAtAG4AZQAgADAAKQAgAHsAIABlAHgAaQB0ACAAJABMAEEAUwBUAEUAWABJAFQAQwBPAEQARQAgAH0AOwAgACQAaABvAG8AawBQAGEAdABoACAAPQAgAEoAbwBpAG4ALQBQAGEAdABoACAAJAByAGUAcABvAFIAbwBvAHQAIAAnAC4AYwBsAGEAdQBkAGUALwBoAG8AbwBrAHMALwBnAHUAYQByAGQALQByAHUAbABlAGIAbwBvAGsALgBtAGoAcwAnADsAIAAmACAAbgBvAGQAZQAgACQAaABvAG8AawBQAGEAdABoADsAIABlAHgAaQB0ACAAJABMAEEAUwBUAEUAWABJAFQAQwBPAEQARQA="
|
|
22
27
|
}
|
|
23
28
|
]
|
|
24
29
|
},
|
|
@@ -86,7 +86,9 @@ them all; they are one rulebook.
|
|
|
86
86
|
difference is worth keeping straight.
|
|
87
87
|
- **Enforcement is mechanical.** `guard-core-purity` catches an impure edit to
|
|
88
88
|
the core the moment it lands; `guard-web-boundary` keeps the frontend off the
|
|
89
|
-
backend; `guard-
|
|
89
|
+
backend; `guard-rulebook` refuses an edit to the rulebook itself from an
|
|
90
|
+
unattended run outside the item's allow-list (a flag file the `loop` skill
|
|
91
|
+
writes; attended sessions are untouched); `guard-secret-file` refuses an edit that writes a credential — by the
|
|
90
92
|
file's name or by a value in its text, from the one vocabulary in
|
|
91
93
|
`.claude/scripts/lib/secrets.mjs`; `block-no-verify` refuses pre-commit
|
|
92
94
|
bypasses; `guard-bash` refuses
|
|
@@ -86,7 +86,9 @@ them all; they are one rulebook.
|
|
|
86
86
|
difference is worth keeping straight.
|
|
87
87
|
- **Enforcement is mechanical.** `guard-core-purity` catches an impure edit to
|
|
88
88
|
the core the moment it lands; `guard-web-boundary` keeps the frontend off the
|
|
89
|
-
backend; `guard-
|
|
89
|
+
backend; `guard-rulebook` refuses an edit to the rulebook itself from an
|
|
90
|
+
unattended run outside the item's allow-list (a flag file the `loop` skill
|
|
91
|
+
writes; attended sessions are untouched); `guard-secret-file` refuses an edit that writes a credential — by the
|
|
90
92
|
file's name or by a value in its text, from the one vocabulary in
|
|
91
93
|
`.claude/scripts/lib/secrets.mjs`; `block-no-verify` refuses pre-commit
|
|
92
94
|
bypasses; `guard-bash` refuses
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Why the fan-out is checked in `pr-ship`, and never in a hook
|
|
2
|
+
|
|
3
|
+
The check lives in the `pr-ship` skill, step 5 ("Coverage"), and its rule is one
|
|
4
|
+
sentence: *a merge is not gated by a fan-out whose reviewers did not all answer
|
|
5
|
+
for the commit being merged.* This file explains why that check sits in a skill
|
|
6
|
+
rather than in `guard-bash`. The hook version is the one that keeps being
|
|
7
|
+
proposed, and a refusal nobody wrote down gets proposed again. It is not loaded
|
|
8
|
+
into any session.
|
|
9
|
+
|
|
10
|
+
## The shape that was refused
|
|
11
|
+
|
|
12
|
+
The proposal: `guard-bash` denies a merge command unless the run journal holds a
|
|
13
|
+
`SHIP` from every reviewer the router named, for the PR's head commit. It is the
|
|
14
|
+
attractive version — mechanical, at the tool layer, impossible for a hurried
|
|
15
|
+
session to skip.
|
|
16
|
+
|
|
17
|
+
It was refused on four costs, each of them a rule this project already paid for.
|
|
18
|
+
|
|
19
|
+
**1. It needs to recognise a merge command while the brake is off.** The kill
|
|
20
|
+
switch can be coarse — it denies the network clients *as a class of binaries*,
|
|
21
|
+
reading no merge semantics at all, while still allowing the wind-down it asks
|
|
22
|
+
for — because a false block is cheap when the session is already stopped. `invariants.md` states that
|
|
23
|
+
directly: match a rule's precision to the cost of a false positive. A merge gate
|
|
24
|
+
runs during ordinary work, where a false block lands on the last step of finished
|
|
25
|
+
work. The one attempt at enumerating merge routes was reverted, and what it cost
|
|
26
|
+
is recorded where the attempt was made rather than restated here:
|
|
27
|
+
`.claude/hooks/guard-bash.mjs`, the comment above `NETWORK_CLIENTS`.
|
|
28
|
+
|
|
29
|
+
**2. It needs the head commit, inside a hook that must stay pure.** For
|
|
30
|
+
`gh pr merge <number>` the head is only knowable over the network, and
|
|
31
|
+
`guard-bash` records what an unbounded hook costs: killed by its own timeout, and
|
|
32
|
+
a killed hook does not block — so **every** rule silently switched off, not just
|
|
33
|
+
the new one.
|
|
34
|
+
|
|
35
|
+
**3. It needs to parse the journal in a guard that fails open.** The journal
|
|
36
|
+
reader refuses a malformed line by throwing, which is right for a reader and
|
|
37
|
+
fatal for a fail-open guard: the throw resolves to *allow*, again for every rule
|
|
38
|
+
at once. `stop-flag.mjs` is not the precedent it resembles — that is `existsSync`
|
|
39
|
+
over a capped list of fixed paths, not a parse.
|
|
40
|
+
|
|
41
|
+
**4. Its sweep half cannot exist.** The natural companion — audit merged PRs from
|
|
42
|
+
outside — has nothing to read: the run directory is gitignored, and the sweep
|
|
43
|
+
sees labels and PR bodies only.
|
|
44
|
+
|
|
45
|
+
## And the reason the four costs were not worth paying
|
|
46
|
+
|
|
47
|
+
Even fully built, the guard would read a file **the audited run wrote itself**.
|
|
48
|
+
For the threat model a hook actually has — drift, not an adversary — that is
|
|
49
|
+
tolerable, and it is why the skill-level check below is worth having at all. What
|
|
50
|
+
it is not is the *guarantee* the hook version promised, and the four costs above
|
|
51
|
+
were being paid for that word.
|
|
52
|
+
|
|
53
|
+
## What was built instead
|
|
54
|
+
|
|
55
|
+
`.claude/scripts/lib/gate-coverage.mjs` compares the three sets the journal already holds —
|
|
56
|
+
routed, launched, answered — and `pr-ship` runs it through
|
|
57
|
+
`verdict.mjs coverage <commit>` before its own verdict. It sits in the layer that
|
|
58
|
+
already knows the head commit, is allowed to run git, and is allowed to throw.
|
|
59
|
+
|
|
60
|
+
Two limits, and both are stated in the skill beside the step rather than only
|
|
61
|
+
here:
|
|
62
|
+
|
|
63
|
+
- with no `RIG_RUN_DIR` there is no journal, so the check says it was skipped and
|
|
64
|
+
exits 0 — an honest nothing, never a pass;
|
|
65
|
+
- a session that skips `pr-ship` entirely skips this with it. That is the gap the
|
|
66
|
+
hook version was reaching for, and it stays open.
|
|
67
|
+
|
|
68
|
+
So `CLAUDE.md` keeps its sentence unchanged: *no hook launches the gates, so "the
|
|
69
|
+
gate ran" is a claim, not a guarantee.* What changed is narrower and worth
|
|
70
|
+
having on its own — the driver can no longer accept a fan-out that did not
|
|
71
|
+
answer, or one that answered about a commit two pushes ago.
|
|
72
|
+
|
|
73
|
+
## The variant that removes self-report, and why it is not the default
|
|
74
|
+
|
|
75
|
+
Running the reviewers as CI check runs is the only shape where the evidence is
|
|
76
|
+
authored by something other than the audited run, and where the driver cannot
|
|
77
|
+
skip the gate at all. It is not refused on its merits.
|
|
78
|
+
|
|
79
|
+
It is refused **as a default for this layer**: everything under `.claude/` ships
|
|
80
|
+
into every project this rulebook generates, so making it the shape would require
|
|
81
|
+
a model credential in every generated project's CI and a per-PR cost, for
|
|
82
|
+
projects that never asked for either. A project that wants that guarantee should
|
|
83
|
+
adopt it deliberately; the check above is what every project gets.
|
|
@@ -13,9 +13,14 @@ why a parked cause outranks a holding one. It is not loaded into any session.
|
|
|
13
13
|
by a condition that clears when _something else happens_: the elevated spacing
|
|
14
14
|
(a normal item lands — or an elevated one whose paths were all documents, see
|
|
15
15
|
`spacing-rations-mechanisms.md`), a blocker (its item closes), `in-progress`
|
|
16
|
-
(the other session finishes), a trigger (a human declares it)
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
(the other session finishes), a trigger (a human declares it), an owner (the
|
|
17
|
+
item is marked for another repository and a human moves or re-marks it —
|
|
18
|
+
AR-132), a `re-scope` item (a human rewrites it against the current code and
|
|
19
|
+
removes the label — AR-144), and a `deferred` item (it carries the `parked`
|
|
20
|
+
label and a human un-parks it — AR-144).
|
|
21
|
+
|
|
22
|
+
An empty queue wants refilling. A held one wants interleaving, time, or — for a
|
|
23
|
+
trigger or an owner — the human act the stop line names.
|
|
19
24
|
Reporting the second as the first sends the owner to write tickets that already
|
|
20
25
|
exist; reporting the first as the second tells them to wait for nothing.
|
|
21
26
|
|
|
@@ -23,14 +28,21 @@ exist; reporting the first as the second tells them to wait for nothing.
|
|
|
23
28
|
|
|
24
29
|
Parked items are out of play and waiting on a human. They are not work this run
|
|
25
30
|
can take, and they are not why the queue is empty — so they are named separately,
|
|
26
|
-
by cause and count.
|
|
31
|
+
by cause and count. An `obsolete` item (AR-144) is one of them: it waits on a
|
|
32
|
+
human close with a comment naming the evidence, which the loop never writes.
|
|
33
|
+
|
|
34
|
+
⚠ "Parked" here is the pile, not the `parked` **label**. The label (AR-144) means
|
|
35
|
+
"valid work, deliberately not now" — takeable, held, freed by an un-park — so its
|
|
36
|
+
cause is spelled `deferred`, and it is never in this pile. The two were named
|
|
37
|
+
before each other existed; this note is the reconciliation rather than a rename,
|
|
38
|
+
because the pile word runs through the stop line, the tests and this record.
|
|
27
39
|
|
|
28
40
|
How that pile grows is the adapter's business, and the stop line does not guess:
|
|
29
41
|
|
|
30
42
|
| adapter | what lands in the parked pile |
|
|
31
43
|
| ---------------------------------------- | ----------------------------------------------------- |
|
|
32
|
-
| tracker-backed (`github-issues`, `jira`) | an escalated item
|
|
33
|
-
| `plan-md` |
|
|
44
|
+
| tracker-backed (`github-issues`, `jira`) | an escalated item, a filed proposal (both stay open), and an item labelled `obsolete` (AR-144) |
|
|
45
|
+
| `plan-md` | a `[triage]` or an `[obsolete]` line sitting in the Agent queue — nothing else, because a flat list has no per-item state |
|
|
34
46
|
|
|
35
47
|
Under `plan-md` a filed proposal goes to the Operator queue, where selection
|
|
36
48
|
never looks, and an escalation leaves **no mark on the queue at all** — a flat
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
".claude/hooks/gate-stop-dod.mjs",
|
|
16
16
|
".claude/hooks/inject-rules.mjs",
|
|
17
17
|
".claude/hooks/guard-secret-file.mjs",
|
|
18
|
+
".claude/hooks/guard-rulebook.mjs",
|
|
18
19
|
".claude/hooks/lib/edit-input.mjs",
|
|
19
20
|
".claude/skills/pr-ship/SKILL.md",
|
|
20
21
|
".claude/skills/loop/SKILL.md",
|
|
@@ -35,11 +36,17 @@
|
|
|
35
36
|
".claude/scripts/decision-router.mjs",
|
|
36
37
|
".claude/scripts/reconcile-external-prs.mjs",
|
|
37
38
|
".claude/scripts/stop-flag.mjs",
|
|
39
|
+
".claude/scripts/unattended-flag.mjs",
|
|
38
40
|
".claude/scripts/git-env.mjs",
|
|
39
41
|
".claude/scripts/preflight.mjs",
|
|
42
|
+
".claude/scripts/doctor.mjs",
|
|
40
43
|
".claude/scripts/run-journal.mjs",
|
|
41
44
|
".claude/scripts/run-state.mjs",
|
|
42
45
|
".claude/scripts/verdict.mjs",
|
|
46
|
+
".claude/scripts/revalidate.mjs",
|
|
47
|
+
".claude/scripts/revalidation-report.mjs",
|
|
48
|
+
".claude/scripts/lib/gate-coverage.mjs",
|
|
49
|
+
".claude/scripts/lib/revalidation-points.mjs",
|
|
43
50
|
".claude/scripts/lib/verdict.mjs",
|
|
44
51
|
".claude/scripts/lib/secrets.mjs",
|
|
45
52
|
".claude/scripts/queue/core.mjs",
|
|
@@ -47,12 +54,14 @@
|
|
|
47
54
|
".claude/scripts/queue/github-issues.mjs",
|
|
48
55
|
".claude/scripts/queue/jira.mjs",
|
|
49
56
|
".claude/scripts/queue/index.mjs",
|
|
57
|
+
".claude/scripts/queue/as-of.mjs",
|
|
50
58
|
".claude/scripts/queue/checkout.mjs",
|
|
51
59
|
".claude/scripts/queue/state.mjs",
|
|
52
60
|
".claude/scripts/queue/gate-rounds.mjs",
|
|
53
61
|
".claude/queue.json",
|
|
54
62
|
"PLAN.md",
|
|
55
63
|
"journal/README.md",
|
|
64
|
+
"docs/decisions/gate-coverage.md",
|
|
56
65
|
"docs/decisions/fail-open-guards.md",
|
|
57
66
|
"docs/decisions/codex-adapter.md",
|
|
58
67
|
"docs/decisions/closing-a-task.md",
|