create-agent-rig 0.7.0 → 0.7.1
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 +85 -0
- package/package.json +1 -1
- package/templates/agent-os/universal/.agents/skills/pr-ship/SKILL.md +70 -9
- package/templates/agent-os/universal/.claude/scripts/revalidate.mjs +380 -19
- package/templates/agent-os/universal/.claude/skills/pr-ship/SKILL.md +70 -9
- package/templates/hash-history.json +78 -24
- package/templates/release-ledger.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,66 @@ Numbering is ordinary semver — **additive is a minor, a fix is a patch** — s
|
|
|
11
11
|
that "I only take minors" remains a usable policy; 0.3.2 shipped additive
|
|
12
12
|
content as a patch by the owner's call and stays recorded as one.
|
|
13
13
|
|
|
14
|
+
## 0.7.1
|
|
15
|
+
|
|
16
|
+
**The gate could not be run on work that has no queue item.** `pr-ship` names
|
|
17
|
+
owner-directed work and hotfixes with no item as a legitimate path — step 4
|
|
18
|
+
tells the fan-out to declare it and have the reviewer skip the item-contract
|
|
19
|
+
check openly. Step 1 then made that path unexecutable: it called
|
|
20
|
+
`revalidate.mjs` with an unconditional `--ticket`, and the script refused
|
|
21
|
+
without one. A newly scaffolded project inherited a rulebook that contradicted
|
|
22
|
+
itself at the one checkpoint before every PR, so the first hotfix in a fresh rig
|
|
23
|
+
had nothing it was allowed to do. Found downstream while integrating published
|
|
24
|
+
0.7.0.
|
|
25
|
+
|
|
26
|
+
A patch: no file is added or removed, no new dependency, and the public CLI of
|
|
27
|
+
the generator is untouched. What changes is one flag on one internal script and
|
|
28
|
+
the skill step that calls it.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **`revalidate.mjs` BEFORE_PR now has two modes, and neither is inferred.**
|
|
33
|
+
`--ticket <key>` is unchanged, including the mandatory claim comparison.
|
|
34
|
+
`--owner-directed` runs the same default-branch drift comparison for work
|
|
35
|
+
with no item, reaching no tracker, no adapter and no claim record — so it
|
|
36
|
+
needs no tracker credentials. Passing both flags, or neither, is exit 1: a
|
|
37
|
+
mode chosen by absence is a mode nobody reviewed.
|
|
38
|
+
|
|
39
|
+
It is not a lighter checkpoint. A default-branch change under a path the
|
|
40
|
+
branch touches, or one a `check-premises` record cited, holds with the same
|
|
41
|
+
exit 2. What it drops is the claim comparison, because work with no item has
|
|
42
|
+
no claim to compare, and it records `ticket: null` rather than inventing an
|
|
43
|
+
id.
|
|
44
|
+
|
|
45
|
+
**Four refusals keep it from becoming a bypass** — exit 1, nothing
|
|
46
|
+
journalled: when the run carries an unresolved `revalidationHold`, when the
|
|
47
|
+
run declares a take-up, when the branch touches a tracked
|
|
48
|
+
`.rig/claims/*.json` in any direction (added, modified, removed or renamed),
|
|
49
|
+
and at `BEFORE_CLOSE`. The first is the one that makes re-running a held or
|
|
50
|
+
`UNVERIFIABLE` ticketed call in this mode a refusal rather than a way past
|
|
51
|
+
it; the run's stop inputs are read fail-closed, so an unreadable
|
|
52
|
+
`state.json` refuses instead of reading as an empty run.
|
|
53
|
+
|
|
54
|
+
An owner-directed HOLD is answered the same way a ticketed one is, with
|
|
55
|
+
`revalidate.mjs outcome` at the same point, passing `--owner-directed`
|
|
56
|
+
instead of `--ticket`. It addresses the detection by mode, since that
|
|
57
|
+
detection carries no ticket to name.
|
|
58
|
+
|
|
59
|
+
⚠ Its stated limits, because a governance mode is trusted as far as it is
|
|
60
|
+
described. Nothing can prove an item does not exist. With no `RIG_RUN_DIR`
|
|
61
|
+
there is no run state, so the hold and take-up refusals cannot fire — the
|
|
62
|
+
command says so on stdout and in `evidence.runState` rather than reporting a
|
|
63
|
+
clean check. The claim refusal reads the branch diff, so a record already on
|
|
64
|
+
the default branch or not yet committed is not seen. And `--base` is the sole
|
|
65
|
+
authority for the verdict here, the claim comparison that would otherwise
|
|
66
|
+
survive a wrong base being absent.
|
|
67
|
+
|
|
68
|
+
- **`pr-ship` step 1 states both paths**, and step 4 now spells the words the
|
|
69
|
+
fan-out is launched with — `no item — owner-directed` — and says that this
|
|
70
|
+
skips the item-contract check and **nothing else**: the checks, the routing,
|
|
71
|
+
the security, code and prose/governance reviews, the coverage check and the
|
|
72
|
+
DoD all still run.
|
|
73
|
+
|
|
14
74
|
## 0.7.0
|
|
15
75
|
|
|
16
76
|
**A durable claim record under the revalidation 0.6.2 already had, and the
|
|
@@ -56,6 +116,31 @@ a patch is the case the rule exists to prevent.
|
|
|
56
116
|
was allowed on the original surface too — and it is unchanged by this
|
|
57
117
|
release.
|
|
58
118
|
|
|
119
|
+
- **A shell command the two shell guards cannot read is refused, where it used
|
|
120
|
+
to be allowed.** `guard-bash` and `block-no-verify` read the `command` a hook
|
|
121
|
+
hands them on a shell tool, and asked only whether it was a string. A command
|
|
122
|
+
that was **there** in some other container — an array of argv words, an
|
|
123
|
+
object — failed that test and returned _allow_ before the kill switch was ever
|
|
124
|
+
consulted, so restating a forbidden command in another shape stepped over an
|
|
125
|
+
armed brake. Those two guards now decide the three outcomes in one shared
|
|
126
|
+
place: an **absent** command still allows, because there is nothing to judge;
|
|
127
|
+
a **string** is inspected as before; a command that is present in a shape they
|
|
128
|
+
cannot read is **refused**, naming the shape they expected.
|
|
129
|
+
|
|
130
|
+
⚠ The scope is those two guards, and it is narrow on purpose — it is **not** a
|
|
131
|
+
repository-wide ruling on the word `command`. `guard-secret-file` reads an
|
|
132
|
+
`apply_patch` `command` that is a _list of strings_, exactly the shape this
|
|
133
|
+
contract calls unreadable, and it is right to; routing a third guard through
|
|
134
|
+
the same place without checking what its tool actually sends would start
|
|
135
|
+
refusing input another guard exists to read.
|
|
136
|
+
|
|
137
|
+
⚠ Two further limits. This changes only the unreadable case — the name-exact
|
|
138
|
+
bound described just above is untouched, and an absent field remains fail-open
|
|
139
|
+
on purpose, since a guard that blocked when handed nothing would be turned off
|
|
140
|
+
within the hour. And the **edit** surfaces are not part of this: what
|
|
141
|
+
`.claude/hooks/lib/edit-input.mjs` does with a `tool_input` it cannot read is
|
|
142
|
+
unchanged by this release.
|
|
143
|
+
|
|
59
144
|
- **An adapter it cannot read is `UNVERIFIABLE`, not a stack trace.** A
|
|
60
145
|
revalidation whose queue adapter could not be reached exited on a raw Node
|
|
61
146
|
stack trace, which a caller could read as noise rather than as a hold. It now
|
package/package.json
CHANGED
|
@@ -57,13 +57,66 @@ blockers.
|
|
|
57
57
|
confidently-wrong reviews. Everything below is scoped to this diff.
|
|
58
58
|
|
|
59
59
|
Then, on the fetched ref, ask whether the branch is still the branch the run
|
|
60
|
-
took up
|
|
60
|
+
took up. **Two paths, and you state which one — the command infers neither.**
|
|
61
|
+
A branch that is a queue item's take-up:
|
|
61
62
|
|
|
62
63
|
```sh
|
|
63
64
|
node .claude/scripts/revalidate.mjs --point BEFORE_PR --ticket <item-id> --base origin/<default>
|
|
64
65
|
```
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
Owner-directed work or a hotfix that has **no item** — the case step 4 below
|
|
68
|
+
already tells you to declare to the reviewers:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
node .claude/scripts/revalidate.mjs --point BEFORE_PR --owner-directed --base origin/<default>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
🔴 **The second path is not a lighter checkpoint, and it is never a skip.**
|
|
75
|
+
It runs the same `main:<path>` comparison and holds on the same exit 2; what
|
|
76
|
+
it drops is the claim comparison, because work with no item has no claim to
|
|
77
|
+
compare. It resolves no queue config, so it reaches no tracker and needs no
|
|
78
|
+
credentials. Passing both flags, or neither, is exit 1.
|
|
79
|
+
|
|
80
|
+
**Four refusals** — exit 1, nothing journalled — keep it from being the way
|
|
81
|
+
around a claim or revalidation failure. It is refused when this run carries
|
|
82
|
+
an **unresolved revalidation hold** (what the ticketed path writes when it
|
|
83
|
+
holds or answers `UNVERIFIABLE`), when this run **declares a take-up**, when
|
|
84
|
+
the branch **touches a tracked `.rig/claims/*.json`** in any direction —
|
|
85
|
+
added, modified, removed or renamed — and at `BEFORE_CLOSE`. So re-running a
|
|
86
|
+
held ticketed call in this mode does not get past it: resolve the hold with
|
|
87
|
+
`outcome` instead.
|
|
88
|
+
|
|
89
|
+
⚠ **What those refusals do not cover**, because a governance mode is trusted
|
|
90
|
+
exactly as far as it is described:
|
|
91
|
+
|
|
92
|
+
- **With no `RIG_RUN_DIR` there is no run state to read**, so the hold and
|
|
93
|
+
take-up refusals cannot fire — and nothing is journalled. The command says
|
|
94
|
+
so on stdout and in `evidence.runState`; it is not evidence that neither
|
|
95
|
+
exists. An attended gate run is exactly this shape, so read that line.
|
|
96
|
+
- The claim refusal reads the **branch diff**, so a claim record already on
|
|
97
|
+
the default branch, or written and not committed, is not seen.
|
|
98
|
+
- **`--base` is the sole authority for the verdict here**, the claim
|
|
99
|
+
comparison that would otherwise survive a wrong base being absent. Pass
|
|
100
|
+
the fetched `origin/<default>`, not a local copy and not `HEAD`.
|
|
101
|
+
- Nothing can prove an item does not exist. The rest is your word, recorded
|
|
102
|
+
as such, with `ticket: null` and no invented id.
|
|
103
|
+
|
|
104
|
+
Pinned in the generator's `test/template/owner-directed-revalidation.test.ts`
|
|
105
|
+
(absent in a generated rig) › "refuses when this run carries an unresolved
|
|
106
|
+
revalidation hold", › "refuses when the declared run already carries a
|
|
107
|
+
take-up", › "refuses when the branch RENAMES a claim record — the case
|
|
108
|
+
--diff-filter=AM could not see" and › "says out loud that an undeclared run
|
|
109
|
+
checked neither the hold nor the take-up".
|
|
110
|
+
|
|
111
|
+
**Exit 2 here is a HOLD with the same shape as the ticketed one**, and the
|
|
112
|
+
same two-step remedy: re-read the default branch on each named path, then
|
|
113
|
+
record what the re-read concluded — `node .claude/scripts/revalidate.mjs
|
|
114
|
+
outcome --point BEFORE_PR --owner-directed --action-changed <true | false>
|
|
115
|
+
--note '…'` — and come back through step 0. The owner-directed detection
|
|
116
|
+
carries no ticket, so `--owner-directed` is how the outcome addresses it;
|
|
117
|
+
the ticketed `--ticket <item-id>` form below cannot match it and is refused.
|
|
118
|
+
|
|
119
|
+
The ticketed path runs the existing revalidation chain against the tracked, versioned
|
|
67
120
|
`.rig/claims/<item-id>.json`: the content-blind `scope` fingerprint set is
|
|
68
121
|
authoritative here, while `takeUps` / `updatedAt` remain evidence only. It
|
|
69
122
|
also names what the default branch changed since this branch forked on paths
|
|
@@ -71,14 +124,18 @@ blockers.
|
|
|
71
124
|
journals one `revalidation` event at `point: BEFORE_PR`; **exit code 2 is a HOLD**, with one blocker per named source: re-read the item, or the default
|
|
72
125
|
branch on that path, record what the re-read concluded —
|
|
73
126
|
`node .claude/scripts/revalidate.mjs outcome --point BEFORE_PR --ticket <item-id> --action-changed <true | false> --note '…'`
|
|
74
|
-
— and come back through step 0.
|
|
75
|
-
|
|
127
|
+
— and come back through step 0. **That `--ticket` form is this path's, not
|
|
128
|
+
both paths'** — the owner-directed detection carries no ticket for it to
|
|
129
|
+
name, and its own `--owner-directed` outcome is written out above. A hold
|
|
130
|
+
with no outcome, in either mode, is counted by the report as a re-read the
|
|
131
|
+
run skipped. A missing, untracked, unreadable or
|
|
76
132
|
unsupported claim is `UNVERIFIABLE`, exits 2, and stops automatic progress;
|
|
77
133
|
so is a tracker whose adapter the command cannot READ, which means the
|
|
78
134
|
question was never put rather than that the claim record is unreadable.
|
|
79
135
|
Neither is ever read as a pass. Exit 1 is the command refusing (unknown
|
|
80
|
-
point,
|
|
81
|
-
not resolve
|
|
136
|
+
point, neither mode or both, a base that is not a revision, or a queue config
|
|
137
|
+
that does not resolve — plus, on the owner-directed path, the four refusals
|
|
138
|
+
above): fix the call or the config — the message says which. Its limits are its own header's; the
|
|
82
139
|
cited-path set is a labelled assumption, not a recorded fact. Pinned in the
|
|
83
140
|
generator's `test/template/revalidate.test.ts` (absent in a generated rig) ›
|
|
84
141
|
"continues when only updatedAt moved and still reports the marker evidence"
|
|
@@ -182,9 +239,13 @@ blockers.
|
|
|
182
239
|
**Whatever you launch, pass it the text of the queue item this branch
|
|
183
240
|
implements.** A reviewer given only a diff cannot check the change against
|
|
184
241
|
what was asked: a cold context has no way to know, and reconstructing it from
|
|
185
|
-
the PR description would mean trusting the run under review.
|
|
186
|
-
item — owner-directed work, a hotfix —
|
|
187
|
-
|
|
242
|
+
the PR description would mean trusting the run under review. When there is
|
|
243
|
+
no item — owner-directed work, a hotfix — launch every reviewer with the
|
|
244
|
+
words **`no item — owner-directed`** instead. That skips the item-contract
|
|
245
|
+
check, openly, and **nothing else**: the checks, the routing, the security,
|
|
246
|
+
code and prose/governance reviews, the coverage check and the DoD all still
|
|
247
|
+
run. It is one check narrower than a ticketed fan-out, not a cheaper gate,
|
|
248
|
+
and the same words are what step 1's `--owner-directed` call records.
|
|
188
249
|
|
|
189
250
|
🔴 **The triggers below are lane-independent and may only ADD.** They read
|
|
190
251
|
*what the code does*; the router reads *paths*, and a path cannot say that a
|
|
@@ -5,6 +5,62 @@
|
|
|
5
5
|
* run took up?
|
|
6
6
|
*
|
|
7
7
|
* node .claude/scripts/revalidate.mjs --point BEFORE_PR --ticket <id> [--base origin/master] [--config <queue.json>] [--json]
|
|
8
|
+
* node .claude/scripts/revalidate.mjs --point BEFORE_PR --owner-directed [--base origin/master] [--json]
|
|
9
|
+
*
|
|
10
|
+
* BEFORE_PR has two mutually exclusive modes and neither is inferred (RP-94):
|
|
11
|
+
* `--ticket` for a branch that is an item's take-up, `--owner-directed` for
|
|
12
|
+
* owner-directed work or a hotfix that has no item — the path `pr-ship` step 4
|
|
13
|
+
* already named while step 1 could not execute it. Passing both, or neither,
|
|
14
|
+
* is exit 1 — owner-directed-revalidation.test.ts › "refuses both modes at
|
|
15
|
+
* once: exit 1, stderr only, nothing journaled" and › "refuses neither mode:
|
|
16
|
+
* exit 1, and the message names both ways forward".
|
|
17
|
+
*
|
|
18
|
+
* Owner-directed mode runs the `main:<path>` comparison below and nothing
|
|
19
|
+
* else. It resolves no queue config, so no tracker or adapter is reached and
|
|
20
|
+
* no credential is needed — owner-directed-revalidation.test.ts › "needs no
|
|
21
|
+
* tracker credentials: an adapter name that cannot resolve is never reached".
|
|
22
|
+
* A `hold` there is the same exit 2 as the ticketed path's — › "HOLDs when the
|
|
23
|
+
* default branch moved under a path the branch touches".
|
|
24
|
+
*
|
|
25
|
+
* FOUR refusals keep it from becoming a way around the claim chain — exit 1,
|
|
26
|
+
* nothing journalled, each with its own test in that file:
|
|
27
|
+
*
|
|
28
|
+
* - an unresolved `revalidationHold` in this run's state, which is what the
|
|
29
|
+
* ticketed path writes when it holds or answers UNVERIFIABLE — › "refuses
|
|
30
|
+
* when this run carries an unresolved revalidation hold";
|
|
31
|
+
* - a take-up this run declares — › "refuses when the declared run already
|
|
32
|
+
* carries a take-up";
|
|
33
|
+
* - a tracked `.rig/claims/*.json` this branch touches, added, modified,
|
|
34
|
+
* removed or renamed — › "refuses when the branch diff adds a tracked claim
|
|
35
|
+
* record", › "refuses when the branch diff modifies a tracked claim record",
|
|
36
|
+
* › "refuses when the branch RENAMES a claim record — the case
|
|
37
|
+
* --diff-filter=AM could not see" and › "refuses when the branch DELETES its
|
|
38
|
+
* claim record";
|
|
39
|
+
* - `BEFORE_CLOSE` — › "refuses owner-directed at BEFORE_CLOSE — the mode
|
|
40
|
+
* exists for BEFORE_PR only".
|
|
41
|
+
*
|
|
42
|
+
* The first of those is the one this mode most needs, and the first version
|
|
43
|
+
* shipped without it: a ticketed call that had already held was re-run here and
|
|
44
|
+
* exited 0 with nothing in the repository changed.
|
|
45
|
+
*
|
|
46
|
+
* ⚠ Its limits, stated because the mode is a governance surface. What makes a
|
|
47
|
+
* call owner-directed is the CALLER's word plus those four refusals: nothing
|
|
48
|
+
* here can prove an item does not exist. Three specific gaps, each measured
|
|
49
|
+
* rather than reasoned:
|
|
50
|
+
*
|
|
51
|
+
* - with no `RIG_RUN_DIR` there is no run state, so the hold and take-up
|
|
52
|
+
* refusals have nothing to read and cannot fire — and nothing is journalled
|
|
53
|
+
* either. The result says so in `evidence.runState`, and the report on
|
|
54
|
+
* stdout says so out loud — › "says out loud that an undeclared run checked
|
|
55
|
+
* neither the hold nor the take-up".
|
|
56
|
+
* - the claim refusal reads the branch DIFF, so a claim record already on the
|
|
57
|
+
* default branch, or written but not committed, is not seen.
|
|
58
|
+
* - `--base` decides more here than the verdict. The claim comparison that
|
|
59
|
+
* would otherwise survive a wrong base is absent, AND the claim-touch refusal
|
|
60
|
+
* reads the same `mergeBase..HEAD` range — so `--base HEAD` empties the
|
|
61
|
+
* branch diff and disarms that refusal as well as reporting `continue`. Pass
|
|
62
|
+
* the up-to-date `origin/<default>`; `pr-ship` step 1 refreshes it, since
|
|
63
|
+
* this script never talks to a remote itself.
|
|
8
64
|
*
|
|
9
65
|
* One existing checkpoint chain, with one authoritative durable baseline:
|
|
10
66
|
*
|
|
@@ -45,18 +101,33 @@
|
|
|
45
101
|
* "re-reads each dependant's state, and names one the tracker no longer
|
|
46
102
|
* offers") for the loop's write-back.
|
|
47
103
|
*
|
|
48
|
-
* `outcome --point <P> --ticket <id> --action-changed
|
|
49
|
-
* (AR-136) is the second half of the
|
|
50
|
-
* `revalidation-outcome` record whose
|
|
51
|
-
* `
|
|
52
|
-
* needs, made by the writer rather than guessed by
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
104
|
+
* `outcome --point <P> {--ticket <id> | --owner-directed} --action-changed
|
|
105
|
+
* true|false [--note …]` (AR-136, extended by RP-94) is the second half of the
|
|
106
|
+
* evidence: after the re-read, it appends a `revalidation-outcome` record whose
|
|
107
|
+
* `answers` is the seq of the latest matching `revalidation` at that point in
|
|
108
|
+
* this run — the join a report needs, made by the writer rather than guessed by
|
|
109
|
+
* the reader.
|
|
110
|
+
*
|
|
111
|
+
* **Which revalidation it matches depends on the mode, and the two never
|
|
112
|
+
* cross.** `--ticket` matches by key and skips owner-directed detections
|
|
113
|
+
* outright; `--owner-directed` matches by `mode`, because such a detection
|
|
114
|
+
* carries `ticket: null` and cannot be addressed by key — and a ticketed
|
|
115
|
+
* `--ticket null` must not answer it either. Pinned in the generator's
|
|
116
|
+
* `test/template/owner-directed-revalidation.test.ts` (absent in a generated
|
|
117
|
+
* rig) › "answers an owner-directed hold with an owner-directed outcome", ›
|
|
118
|
+
* "refuses a ticketed outcome aimed at an owner-directed detection" and ›
|
|
119
|
+
* "refuses an owner-directed outcome when a ticketed hold is the only one this
|
|
120
|
+
* run carries — and leaves that hold latched".
|
|
121
|
+
*
|
|
122
|
+
* It refuses without a run, without a matching revalidation, and with any word
|
|
123
|
+
* but `true`/`false`, and writes nothing then. The typed resolution names the
|
|
124
|
+
* stable detection id and clears only the matching run-level hold — and only a
|
|
125
|
+
* hold whose id it actually names, which is why an owner-directed outcome
|
|
126
|
+
* cannot release a ticketed one. Exit 2 on `hold` or `unverifiable`, 0 on
|
|
127
|
+
* `continue`, and 1 when the call cannot be acted on (unknown point, neither
|
|
128
|
+
* mode or both, a base that is not a revision — or, on the paths that reach it,
|
|
129
|
+
* a queue config that does not resolve) — and then nothing is journalled,
|
|
130
|
+
* because a refusal is not an answer.
|
|
60
131
|
*
|
|
61
132
|
* ⚠ It reads `<base>` as it is in this checkout and never updates the remote
|
|
62
133
|
* ref itself; `pr-ship` step 1 does that before calling this. A stale ref
|
|
@@ -66,17 +137,24 @@
|
|
|
66
137
|
*/
|
|
67
138
|
|
|
68
139
|
import { execFileSync } from 'node:child_process';
|
|
140
|
+
import { createHash } from 'node:crypto';
|
|
69
141
|
import { realpathSync } from 'node:fs';
|
|
70
142
|
import { dirname, join } from 'node:path';
|
|
71
143
|
import { fileURLToPath } from 'node:url';
|
|
72
144
|
import { withoutGitLocation } from './git-env.mjs';
|
|
73
145
|
import { readRun, recordEvent } from './run-journal.mjs';
|
|
74
|
-
import {
|
|
146
|
+
import {
|
|
147
|
+
clearRevalidationHold,
|
|
148
|
+
readState,
|
|
149
|
+
readStateForSelection,
|
|
150
|
+
recordRevalidationHold,
|
|
151
|
+
} from './run-state.mjs';
|
|
75
152
|
import { POINTS as ALL_POINTS, REVALIDATES } from './lib/revalidation-points.mjs';
|
|
76
153
|
import { takeUpEvidenceOf } from './queue/core.mjs';
|
|
77
154
|
import { loadConfig, optionsWithPlanPath, resolveAdapter } from './queue/index.mjs';
|
|
78
155
|
import { projectRootOfConfig } from './queue/index.mjs';
|
|
79
156
|
import {
|
|
157
|
+
CLAIM_SCHEMA_VERSION,
|
|
80
158
|
revalidateClaim,
|
|
81
159
|
targetShaOf,
|
|
82
160
|
unverifiableResult,
|
|
@@ -95,6 +173,7 @@ const parseArgs = (argv) => {
|
|
|
95
173
|
outcome: false,
|
|
96
174
|
point: null,
|
|
97
175
|
ticket: null,
|
|
176
|
+
ownerDirected: false,
|
|
98
177
|
base: 'origin/master',
|
|
99
178
|
config: null,
|
|
100
179
|
json: false,
|
|
@@ -105,6 +184,7 @@ const parseArgs = (argv) => {
|
|
|
105
184
|
for (let i = 0; i < argv.length; i += 1) {
|
|
106
185
|
const arg = argv[i];
|
|
107
186
|
if (i === 0 && arg === 'outcome') args.outcome = true;
|
|
187
|
+
else if (arg === '--owner-directed') args.ownerDirected = true;
|
|
108
188
|
else if (arg === '--json') args.json = true;
|
|
109
189
|
else if (arg === '--action-changed') args.actionChanged = argv[++i] ?? null;
|
|
110
190
|
else if (arg === '--note') args.note = argv[++i] ?? null;
|
|
@@ -300,6 +380,79 @@ const answerUnverifiable = ({ runDir, ticket, point, json }, operation, cause) =
|
|
|
300
380
|
process.exit(2);
|
|
301
381
|
};
|
|
302
382
|
|
|
383
|
+
/**
|
|
384
|
+
* A tracked claim record, by repository-relative path (RP-94).
|
|
385
|
+
*
|
|
386
|
+
* ⚠ It is a SECOND spelling of the path `claimPathFor` builds, and the two are
|
|
387
|
+
* kept in step by `test/template/owner-directed-revalidation.test.ts` (absent
|
|
388
|
+
* in a generated rig) › "matches the path claimPathFor actually builds, from
|
|
389
|
+
* the repository root and from a nested rig root" — a correspondence check
|
|
390
|
+
* rather than a comment asking the next reader to remember. The leading
|
|
391
|
+
* `(^|/)` is why a rig whose root sits below the git root is still matched;
|
|
392
|
+
* this mode resolves no queue config, so it cannot ask where that root is.
|
|
393
|
+
*/
|
|
394
|
+
const CLAIM_RECORD = /(^|\/)\.rig\/claims\/[^/]+\.json$/;
|
|
395
|
+
|
|
396
|
+
const OWNER_DIRECTED = 'owner-directed';
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* The BEFORE_PR verdict for work that has no item (RP-94).
|
|
400
|
+
*
|
|
401
|
+
* It carries the SAME `main:<path>` drift decision the ticketed path reaches —
|
|
402
|
+
* this mode drops the claim comparison because there is no claim, and drops
|
|
403
|
+
* nothing else. `ticket` is `null` rather than a placeholder: a record naming
|
|
404
|
+
* an item that does not exist is worse than one that admits it has none, and
|
|
405
|
+
* every reader downstream distinguishes them by that field.
|
|
406
|
+
*
|
|
407
|
+
* Pinned in the generator's `test/template/owner-directed-revalidation.test.ts`
|
|
408
|
+
* — absent in a generated rig — › "runs BEFORE_PR with no item and no claim
|
|
409
|
+
* when the default branch did not move under the branch" and › "HOLDs when the
|
|
410
|
+
* default branch moved under a path the branch touches".
|
|
411
|
+
*/
|
|
412
|
+
const ownerDirectedResult = ({ point, base, mergeBase, cited, changed, now, runDeclared }) => {
|
|
413
|
+
const source = changed.map((path) => `main:${path}`);
|
|
414
|
+
const held = source.length > 0;
|
|
415
|
+
return {
|
|
416
|
+
schemaVersion: CLAIM_SCHEMA_VERSION,
|
|
417
|
+
// 🔴 `mergeBase` is in the hash, and it is what keeps this id from being a
|
|
418
|
+
// CONSTANT. Without it the digest was `{mode, point, source}` alone — the
|
|
419
|
+
// same value for every `continue` that has ever run, and the same for any
|
|
420
|
+
// two holds naming the same paths. `revalidation-report.mjs` flattens every
|
|
421
|
+
// run into one typed-resolution index, so one `--action-changed false`
|
|
422
|
+
// recorded last week would mark a genuine hold today as already answered:
|
|
423
|
+
// the metric the report exists to produce, quietly wrong. It stays stable
|
|
424
|
+
// across RETRIES of the same checkpoint on the same branch, which is the
|
|
425
|
+
// property `answerUnverifiable`'s identity has and the one that matters.
|
|
426
|
+
id: createHash('sha256')
|
|
427
|
+
.update(JSON.stringify({ mode: OWNER_DIRECTED, point, mergeBase, source }))
|
|
428
|
+
.digest('hex'),
|
|
429
|
+
ticket: null,
|
|
430
|
+
mode: OWNER_DIRECTED,
|
|
431
|
+
point,
|
|
432
|
+
checkpoint: point,
|
|
433
|
+
result: held ? 'CHANGED' : 'CURRENT',
|
|
434
|
+
changed: held,
|
|
435
|
+
source,
|
|
436
|
+
action: held ? 'hold' : 'continue',
|
|
437
|
+
movedFingerprintSet: [],
|
|
438
|
+
sourcePointer: null,
|
|
439
|
+
evidence: {
|
|
440
|
+
claim: 'not compared: owner-directed work has no item, so there is no claim record',
|
|
441
|
+
tracker: 'not read: owner-directed mode resolves no queue adapter',
|
|
442
|
+
// 🔴 "Could not check" is recorded as itself, never as "checked and
|
|
443
|
+
// clean". With no run directory the hold and take-up refusals have
|
|
444
|
+
// nothing to read, and a reader who saw only `continue` would take the
|
|
445
|
+
// pair for having passed.
|
|
446
|
+
runState: runDeclared
|
|
447
|
+
? 'read fail-closed: no unresolved revalidation hold, no declared take-up'
|
|
448
|
+
: 'NOT read: no RIG_RUN_DIR, so neither the revalidation hold nor the take-up was checked',
|
|
449
|
+
},
|
|
450
|
+
observedAt: now,
|
|
451
|
+
task: { changed: null, from: null, to: null },
|
|
452
|
+
main: { base, mergeBase, cited, changed },
|
|
453
|
+
};
|
|
454
|
+
};
|
|
455
|
+
|
|
303
456
|
/** Every adapter call in this script goes through here, or it can still crash. */
|
|
304
457
|
const readAdapter = async (operation, read, context) => {
|
|
305
458
|
try {
|
|
@@ -332,7 +485,31 @@ if (invokedDirectly()) {
|
|
|
332
485
|
if (!known.includes(args.point)) {
|
|
333
486
|
refuse(`unknown point: ${args.point ?? '(none)'}. This script knows ${known.join(', ')}.`);
|
|
334
487
|
}
|
|
335
|
-
|
|
488
|
+
// RP-94. BEFORE_PR has two modes, and neither is ever inferred. `pr-ship`
|
|
489
|
+
// already named owner-directed work with no item as a legitimate path while
|
|
490
|
+
// this script refused every call without `--ticket`, so that path could not
|
|
491
|
+
// be walked at all. The mode is now stated at the call site — silence is a
|
|
492
|
+
// refusal, not a default, because a mode chosen by absence is a mode nobody
|
|
493
|
+
// reviewed.
|
|
494
|
+
if (args.ticket && args.ownerDirected) {
|
|
495
|
+
refuse(
|
|
496
|
+
'--ticket and --owner-directed are mutually exclusive: a branch that is an item\'s ' +
|
|
497
|
+
'take-up is not owner-directed work. Pass exactly one.',
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
if (args.ownerDirected) {
|
|
501
|
+
if (args.point !== 'BEFORE_PR') {
|
|
502
|
+
refuse(
|
|
503
|
+
`--owner-directed is a BEFORE_PR mode only; ${args.point} compares the claim record ` +
|
|
504
|
+
'itself and still needs --ticket.',
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
} else if (!args.ticket) {
|
|
508
|
+
refuse(
|
|
509
|
+
'--ticket is required: the item whose take-up this branch is. For owner-directed ' +
|
|
510
|
+
'work or a hotfix that has no item, pass --owner-directed instead.',
|
|
511
|
+
);
|
|
512
|
+
}
|
|
336
513
|
|
|
337
514
|
const runDir = process.env.RIG_RUN_DIR || null;
|
|
338
515
|
|
|
@@ -342,16 +519,27 @@ if (invokedDirectly()) {
|
|
|
342
519
|
refuse(`--action-changed must be true or false, got ${args.actionChanged ?? '(none)'}.`);
|
|
343
520
|
}
|
|
344
521
|
const { events } = readRun({ runDir });
|
|
522
|
+
// RP-94. An owner-directed detection carries `ticket: null`, so it cannot
|
|
523
|
+
// be addressed by key — `String(null)` would also match a literal ticket
|
|
524
|
+
// named "null". It is addressed by MODE instead, which is the only thing
|
|
525
|
+
// that distinguishes it. Without this, a `hold` the owner-directed path
|
|
526
|
+
// returned had no way to be answered at all: the skill's stated exit-2
|
|
527
|
+
// remedy was a command the script refused, which is the same shape of
|
|
528
|
+
// contradiction RP-94 exists to remove.
|
|
529
|
+
const subject = args.ownerDirected ? `${OWNER_DIRECTED} work` : args.ticket;
|
|
345
530
|
const target = [...events]
|
|
346
531
|
.reverse()
|
|
347
532
|
.find(
|
|
348
533
|
(e) =>
|
|
349
534
|
e.kind === 'revalidation' &&
|
|
350
|
-
|
|
351
|
-
|
|
535
|
+
e.data?.point === args.point &&
|
|
536
|
+
(args.ownerDirected
|
|
537
|
+
? e.data?.mode === OWNER_DIRECTED
|
|
538
|
+
: e.data?.mode !== OWNER_DIRECTED &&
|
|
539
|
+
String(e.data?.ticket) === String(args.ticket)),
|
|
352
540
|
);
|
|
353
541
|
if (!target) {
|
|
354
|
-
refuse(`no revalidation of ${
|
|
542
|
+
refuse(`no revalidation of ${subject} at ${args.point} in ${runDir} for this outcome to answer.`);
|
|
355
543
|
}
|
|
356
544
|
const now = new Date().toISOString();
|
|
357
545
|
const actionRequired = args.actionChanged === 'true';
|
|
@@ -364,7 +552,10 @@ if (invokedDirectly()) {
|
|
|
364
552
|
actionRequired,
|
|
365
553
|
driftOrigin: 'unknown',
|
|
366
554
|
resolvedAt: now,
|
|
367
|
-
|
|
555
|
+
// `null`, never a placeholder, for the same reason the detection this
|
|
556
|
+
// answers carries none.
|
|
557
|
+
ticket: args.ownerDirected ? null : args.ticket,
|
|
558
|
+
...(args.ownerDirected ? { mode: OWNER_DIRECTED } : {}),
|
|
368
559
|
point: args.point,
|
|
369
560
|
actionChanged: actionRequired,
|
|
370
561
|
note: args.note,
|
|
@@ -376,11 +567,181 @@ if (invokedDirectly()) {
|
|
|
376
567
|
process.stdout.write(
|
|
377
568
|
args.json
|
|
378
569
|
? `${JSON.stringify(record, null, 2)}\n`
|
|
379
|
-
: `revalidation-outcome: ${
|
|
570
|
+
: `revalidation-outcome: ${subject} at ${args.point} answers seq ${target.seq} — actionChanged ${args.actionChanged}\n`,
|
|
380
571
|
);
|
|
381
572
|
process.exit(0);
|
|
382
573
|
}
|
|
383
574
|
|
|
575
|
+
if (args.ownerDirected) {
|
|
576
|
+
// RP-94. BEFORE_PR for work that has no item: the same main-vs-branch drift
|
|
577
|
+
// comparison, with no tracker, no adapter and no claim record.
|
|
578
|
+
//
|
|
579
|
+
// 🔴 It sits ABOVE the queue-config resolution on purpose. "This mode reads
|
|
580
|
+
// no tracker" has to be a property of the control flow rather than a
|
|
581
|
+
// promise in a comment — nothing below this block runs, so a missing
|
|
582
|
+
// credential or an adapter name that does not resolve cannot reach it.
|
|
583
|
+
// Pinned by › "needs no tracker credentials: an adapter name that cannot
|
|
584
|
+
// resolve is never reached".
|
|
585
|
+
//
|
|
586
|
+
// The refusals below are what keep the mode from becoming a way around the
|
|
587
|
+
// claim chain, and every one is decided BEFORE anything is journalled: a
|
|
588
|
+
// refusal is not an answer, so it leaves no revalidation record behind.
|
|
589
|
+
//
|
|
590
|
+
// 🔴 Read FAIL-CLOSED. `readState` is the permissive reader and its own
|
|
591
|
+
// header forbids exactly this use — "a corrupt file there may be hiding a
|
|
592
|
+
// persisted stop" — so an unreadable run refuses here instead of reading as
|
|
593
|
+
// "this run declares nothing". The first version used `readState`, and a
|
|
594
|
+
// truncated `state.json` carrying a take-up was measured continuing.
|
|
595
|
+
let state = {};
|
|
596
|
+
if (runDir) {
|
|
597
|
+
try {
|
|
598
|
+
state = readStateForSelection(runDir);
|
|
599
|
+
} catch (error) {
|
|
600
|
+
refuse(
|
|
601
|
+
`--owner-directed refused: this run's state could not be read (${runDir}): ` +
|
|
602
|
+
`${error.message}. An unreadable run may be hiding a stop.`,
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// 🔴 The refusal this mode most needs, and the one its first version did
|
|
608
|
+
// not have. A ticketed BEFORE_PR that holds or comes back UNVERIFIABLE
|
|
609
|
+
// latches `revalidationHold`; re-running the same checkpoint here was
|
|
610
|
+
// MEASURED exiting 0 with nothing in the repository changed — the exact
|
|
611
|
+
// bypass RP-94 names. Neither other refusal can fire in that state, and
|
|
612
|
+
// that is structural rather than unlucky: `takeUps` is never populated on
|
|
613
|
+
// the default `plan-md` adapter at all, and the commonest hold is a
|
|
614
|
+
// MISSING claim record, which is precisely when the branch writes none.
|
|
615
|
+
// This one is adapter-independent because `recordRevalidationHold` is.
|
|
616
|
+
const hold = state.revalidationHold;
|
|
617
|
+
if (hold) {
|
|
618
|
+
// A malformed hold still refuses — it is a hold either way — but it must
|
|
619
|
+
// not print `undefined at undefined`, which reads as a broken command
|
|
620
|
+
// rather than as the stop it is.
|
|
621
|
+
const describe = (value, fallback) => (typeof value === 'string' ? value : fallback);
|
|
622
|
+
refuse(
|
|
623
|
+
`--owner-directed refused: this run carries an unresolved revalidation hold ` +
|
|
624
|
+
`(${describe(hold.ticket, 'an unnamed item')} at ` +
|
|
625
|
+
`${describe(hold.checkpoint, 'an unnamed checkpoint')}, ` +
|
|
626
|
+
`${describe(hold.result, 'result unrecorded')}, detection ` +
|
|
627
|
+
`${describe(hold.detectionId, 'unrecorded')}). ` +
|
|
628
|
+
'Resolve it with `revalidate.mjs outcome`; re-running the checkpoint in the other ' +
|
|
629
|
+
'mode is not a resolution, it is the bypass this mode refuses.',
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
const takeUps = state.takeUps;
|
|
634
|
+
// A present-but-unreadable take-up record is a refusal, not an empty one:
|
|
635
|
+
// `Object.keys` answers `[]` for a number and for a list, which would turn
|
|
636
|
+
// "this cannot be read" into "there is nothing here".
|
|
637
|
+
if (
|
|
638
|
+
takeUps !== undefined &&
|
|
639
|
+
(typeof takeUps !== 'object' || takeUps === null || Array.isArray(takeUps))
|
|
640
|
+
) {
|
|
641
|
+
refuse(
|
|
642
|
+
`--owner-directed refused: this run's take-up record is not readable ` +
|
|
643
|
+
`(takeUps is ${Array.isArray(takeUps) ? 'a list' : typeof takeUps}, expected an object).`,
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
const takenUp = Object.keys(takeUps ?? {});
|
|
647
|
+
if (takenUp.length > 0) {
|
|
648
|
+
refuse(
|
|
649
|
+
`--owner-directed refused: this run already declares a take-up (${takenUp.join(', ')}). ` +
|
|
650
|
+
'A run holding an item revalidates with --ticket; owner-directed is for work with none.',
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
let mergeBase;
|
|
655
|
+
try {
|
|
656
|
+
mergeBase = git(['merge-base', args.base, 'HEAD']).trim();
|
|
657
|
+
} catch (error) {
|
|
658
|
+
refuse(
|
|
659
|
+
`--base ${args.base} is not a revision this checkout can compare against: ${error.message}`,
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Any claim record this branch TOUCHES, in either direction.
|
|
664
|
+
//
|
|
665
|
+
// 🔴 `--no-renames`, and no `--diff-filter`, because both narrower forms
|
|
666
|
+
// were measured letting a claim record through. `--diff-filter=AM` reports
|
|
667
|
+
// NOTHING for `git mv .rig/claims/RP-1.json .rig/claims/RP-2.json` — git
|
|
668
|
+
// calls it `R100` — so a branch that demonstrably ends up carrying a claim
|
|
669
|
+
// record passed the check. And a branch that DELETES its claim makes the
|
|
670
|
+
// ticketed call `UNVERIFIABLE`, so excluding `D` left the deletion on the
|
|
671
|
+
// bypass path rather than out of scope. `--no-renames` splits a rename back
|
|
672
|
+
// into its delete and its add, which is what puts both halves in front of
|
|
673
|
+
// the filter. Match the CLASS — "this branch touched the claim store" —
|
|
674
|
+
// rather than enumerating the statuses that class can wear.
|
|
675
|
+
const claimsTouched = pathsOf(
|
|
676
|
+
git(['diff', '--name-only', '--no-renames', '-z', mergeBase, 'HEAD']),
|
|
677
|
+
).filter((path) => CLAIM_RECORD.test(path));
|
|
678
|
+
if (claimsTouched.length > 0) {
|
|
679
|
+
refuse(
|
|
680
|
+
`--owner-directed refused: this branch touches tracked claim records ` +
|
|
681
|
+
`(${claimsTouched.join(', ')}). A branch that writes, moves or removes a claim is ` +
|
|
682
|
+
"an item's take-up; revalidate it with --ticket.",
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const branchPaths = pathsOf(git(['diff', '--name-only', '-z', mergeBase, 'HEAD']));
|
|
687
|
+
const mainPaths = pathsOf(git(['diff', '--name-only', '-z', mergeBase, args.base]));
|
|
688
|
+
const cited = [...new Set([...branchPaths, ...citedByPremises(runDir)])];
|
|
689
|
+
const mainChanged = mainPaths.filter((path) => cited.includes(path));
|
|
690
|
+
const result = ownerDirectedResult({
|
|
691
|
+
point: args.point,
|
|
692
|
+
base: args.base,
|
|
693
|
+
mergeBase,
|
|
694
|
+
cited,
|
|
695
|
+
changed: mainChanged,
|
|
696
|
+
now: new Date().toISOString(),
|
|
697
|
+
runDeclared: Boolean(runDir),
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
if (runDir) {
|
|
701
|
+
recordEvent({ runDir, kind: 'revalidation', data: result, now: result.observedAt });
|
|
702
|
+
// 🔴 No run-level revalidation hold is recorded here, and the reason is
|
|
703
|
+
// NOT the one first written down. That said "a hold written here could
|
|
704
|
+
// never be cleared" — which stopped being true the moment `outcome
|
|
705
|
+
// --owner-directed` computed the very id `clearRevalidationHold` matches
|
|
706
|
+
// on. The real reason is narrower: `recordRevalidationHold` requires a
|
|
707
|
+
// string ticket, and this mode has none to give it without inventing
|
|
708
|
+
// one, which is the thing the whole mode refuses to do.
|
|
709
|
+
//
|
|
710
|
+
// ⚠ **State the asymmetry rather than let a reader assume symmetry.** A
|
|
711
|
+
// ticketed hold has TWO stops — the exit code, and a latch that
|
|
712
|
+
// `queue/index.mjs` and `unresolvedBlockingDetectionOf` both read (the
|
|
713
|
+
// latter also requires a string ticket, so it skips this one). An
|
|
714
|
+
// owner-directed hold has ONE: the exit code below. A caller who ignores
|
|
715
|
+
// it is not stopped a second time. Widening the latch to a ticketless
|
|
716
|
+
// hold is a run-state schema change — Tier 2, and not this hotfix's.
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
if (args.json) {
|
|
720
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
721
|
+
} else {
|
|
722
|
+
const detail = result.source.length > 0 ? ` — ${result.source.join(', ')}` : '';
|
|
723
|
+
process.stdout.write(
|
|
724
|
+
`revalidate ${args.point}: ${OWNER_DIRECTED} (no item) ${result.action}${detail}\n`,
|
|
725
|
+
);
|
|
726
|
+
if (!runDir) {
|
|
727
|
+
// Loud, on the normal path, not only in the JSON: a run this command
|
|
728
|
+
// could not inspect must not read as a run it inspected and cleared.
|
|
729
|
+
process.stdout.write(
|
|
730
|
+
' ⚠ no RIG_RUN_DIR: the revalidation-hold and take-up refusals were NOT checked,\n' +
|
|
731
|
+
' and nothing was journalled. This is not evidence that neither exists.\n',
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
if (result.action === 'hold') {
|
|
735
|
+
process.stdout.write(
|
|
736
|
+
' re-read the default branch on those paths before opening or updating the PR,\n' +
|
|
737
|
+
' then record what the re-read concluded:\n' +
|
|
738
|
+
` node .claude/scripts/revalidate.mjs outcome --point ${args.point} --owner-directed --action-changed <true | false>\n`,
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
process.exit(result.action === 'hold' ? 2 : 0);
|
|
743
|
+
}
|
|
744
|
+
|
|
384
745
|
const projectRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
385
746
|
const configPath = args.config ?? join(projectRoot, '.claude', 'queue.json');
|
|
386
747
|
// 🔴 The queue CONFIG, not the tracker behind it. `readAdapter` covers every
|
|
@@ -57,13 +57,66 @@ blockers.
|
|
|
57
57
|
confidently-wrong reviews. Everything below is scoped to this diff.
|
|
58
58
|
|
|
59
59
|
Then, on the fetched ref, ask whether the branch is still the branch the run
|
|
60
|
-
took up
|
|
60
|
+
took up. **Two paths, and you state which one — the command infers neither.**
|
|
61
|
+
A branch that is a queue item's take-up:
|
|
61
62
|
|
|
62
63
|
```sh
|
|
63
64
|
node .claude/scripts/revalidate.mjs --point BEFORE_PR --ticket <item-id> --base origin/<default>
|
|
64
65
|
```
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
Owner-directed work or a hotfix that has **no item** — the case step 4 below
|
|
68
|
+
already tells you to declare to the reviewers:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
node .claude/scripts/revalidate.mjs --point BEFORE_PR --owner-directed --base origin/<default>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
🔴 **The second path is not a lighter checkpoint, and it is never a skip.**
|
|
75
|
+
It runs the same `main:<path>` comparison and holds on the same exit 2; what
|
|
76
|
+
it drops is the claim comparison, because work with no item has no claim to
|
|
77
|
+
compare. It resolves no queue config, so it reaches no tracker and needs no
|
|
78
|
+
credentials. Passing both flags, or neither, is exit 1.
|
|
79
|
+
|
|
80
|
+
**Four refusals** — exit 1, nothing journalled — keep it from being the way
|
|
81
|
+
around a claim or revalidation failure. It is refused when this run carries
|
|
82
|
+
an **unresolved revalidation hold** (what the ticketed path writes when it
|
|
83
|
+
holds or answers `UNVERIFIABLE`), when this run **declares a take-up**, when
|
|
84
|
+
the branch **touches a tracked `.rig/claims/*.json`** in any direction —
|
|
85
|
+
added, modified, removed or renamed — and at `BEFORE_CLOSE`. So re-running a
|
|
86
|
+
held ticketed call in this mode does not get past it: resolve the hold with
|
|
87
|
+
`outcome` instead.
|
|
88
|
+
|
|
89
|
+
⚠ **What those refusals do not cover**, because a governance mode is trusted
|
|
90
|
+
exactly as far as it is described:
|
|
91
|
+
|
|
92
|
+
- **With no `RIG_RUN_DIR` there is no run state to read**, so the hold and
|
|
93
|
+
take-up refusals cannot fire — and nothing is journalled. The command says
|
|
94
|
+
so on stdout and in `evidence.runState`; it is not evidence that neither
|
|
95
|
+
exists. An attended gate run is exactly this shape, so read that line.
|
|
96
|
+
- The claim refusal reads the **branch diff**, so a claim record already on
|
|
97
|
+
the default branch, or written and not committed, is not seen.
|
|
98
|
+
- **`--base` is the sole authority for the verdict here**, the claim
|
|
99
|
+
comparison that would otherwise survive a wrong base being absent. Pass
|
|
100
|
+
the fetched `origin/<default>`, not a local copy and not `HEAD`.
|
|
101
|
+
- Nothing can prove an item does not exist. The rest is your word, recorded
|
|
102
|
+
as such, with `ticket: null` and no invented id.
|
|
103
|
+
|
|
104
|
+
Pinned in the generator's `test/template/owner-directed-revalidation.test.ts`
|
|
105
|
+
(absent in a generated rig) › "refuses when this run carries an unresolved
|
|
106
|
+
revalidation hold", › "refuses when the declared run already carries a
|
|
107
|
+
take-up", › "refuses when the branch RENAMES a claim record — the case
|
|
108
|
+
--diff-filter=AM could not see" and › "says out loud that an undeclared run
|
|
109
|
+
checked neither the hold nor the take-up".
|
|
110
|
+
|
|
111
|
+
**Exit 2 here is a HOLD with the same shape as the ticketed one**, and the
|
|
112
|
+
same two-step remedy: re-read the default branch on each named path, then
|
|
113
|
+
record what the re-read concluded — `node .claude/scripts/revalidate.mjs
|
|
114
|
+
outcome --point BEFORE_PR --owner-directed --action-changed <true | false>
|
|
115
|
+
--note '…'` — and come back through step 0. The owner-directed detection
|
|
116
|
+
carries no ticket, so `--owner-directed` is how the outcome addresses it;
|
|
117
|
+
the ticketed `--ticket <item-id>` form below cannot match it and is refused.
|
|
118
|
+
|
|
119
|
+
The ticketed path runs the existing revalidation chain against the tracked, versioned
|
|
67
120
|
`.rig/claims/<item-id>.json`: the content-blind `scope` fingerprint set is
|
|
68
121
|
authoritative here, while `takeUps` / `updatedAt` remain evidence only. It
|
|
69
122
|
also names what the default branch changed since this branch forked on paths
|
|
@@ -71,14 +124,18 @@ blockers.
|
|
|
71
124
|
journals one `revalidation` event at `point: BEFORE_PR`; **exit code 2 is a HOLD**, with one blocker per named source: re-read the item, or the default
|
|
72
125
|
branch on that path, record what the re-read concluded —
|
|
73
126
|
`node .claude/scripts/revalidate.mjs outcome --point BEFORE_PR --ticket <item-id> --action-changed <true | false> --note '…'`
|
|
74
|
-
— and come back through step 0.
|
|
75
|
-
|
|
127
|
+
— and come back through step 0. **That `--ticket` form is this path's, not
|
|
128
|
+
both paths'** — the owner-directed detection carries no ticket for it to
|
|
129
|
+
name, and its own `--owner-directed` outcome is written out above. A hold
|
|
130
|
+
with no outcome, in either mode, is counted by the report as a re-read the
|
|
131
|
+
run skipped. A missing, untracked, unreadable or
|
|
76
132
|
unsupported claim is `UNVERIFIABLE`, exits 2, and stops automatic progress;
|
|
77
133
|
so is a tracker whose adapter the command cannot READ, which means the
|
|
78
134
|
question was never put rather than that the claim record is unreadable.
|
|
79
135
|
Neither is ever read as a pass. Exit 1 is the command refusing (unknown
|
|
80
|
-
point,
|
|
81
|
-
not resolve
|
|
136
|
+
point, neither mode or both, a base that is not a revision, or a queue config
|
|
137
|
+
that does not resolve — plus, on the owner-directed path, the four refusals
|
|
138
|
+
above): fix the call or the config — the message says which. Its limits are its own header's; the
|
|
82
139
|
cited-path set is a labelled assumption, not a recorded fact. Pinned in the
|
|
83
140
|
generator's `test/template/revalidate.test.ts` (absent in a generated rig) ›
|
|
84
141
|
"continues when only updatedAt moved and still reports the marker evidence"
|
|
@@ -182,9 +239,13 @@ blockers.
|
|
|
182
239
|
**Whatever you launch, pass it the text of the queue item this branch
|
|
183
240
|
implements.** A reviewer given only a diff cannot check the change against
|
|
184
241
|
what was asked: a cold context has no way to know, and reconstructing it from
|
|
185
|
-
the PR description would mean trusting the run under review.
|
|
186
|
-
item — owner-directed work, a hotfix —
|
|
187
|
-
|
|
242
|
+
the PR description would mean trusting the run under review. When there is
|
|
243
|
+
no item — owner-directed work, a hotfix — launch every reviewer with the
|
|
244
|
+
words **`no item — owner-directed`** instead. That skips the item-contract
|
|
245
|
+
check, openly, and **nothing else**: the checks, the routing, the security,
|
|
246
|
+
code and prose/governance reviews, the coverage check and the DoD all still
|
|
247
|
+
run. It is one check narrower than a ticketed fan-out, not a cheaper gate,
|
|
248
|
+
and the same words are what step 1's `--owner-directed` call records.
|
|
188
249
|
|
|
189
250
|
🔴 **The triggers below are lane-independent and may only ADD.** They read
|
|
190
251
|
*what the code does*; the router reads *paths*, and a path cannot say that a
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"0.5.0",
|
|
9
9
|
"0.6.0",
|
|
10
10
|
"0.6.1",
|
|
11
|
-
"0.6.2"
|
|
11
|
+
"0.6.2",
|
|
12
|
+
"0.7.0"
|
|
12
13
|
],
|
|
13
14
|
"files": {
|
|
14
15
|
".agents/skills/check-premises/SKILL.md": {
|
|
@@ -24,7 +25,8 @@
|
|
|
24
25
|
"eb52ef41269018107534d8dc2f552c57698e1677a1e76b5e666b5d09c007cac0",
|
|
25
26
|
"47922b182915cb92696f851174f2e88c4ae8c67dc119ef39a3a597ef1300fab5",
|
|
26
27
|
"57f6add0504db45e7577474f97705fe474310e4cd3310cdb348a2c64eabe88cd",
|
|
27
|
-
"18f4300de4c4c7ea380d726fb109fa224da950ef0a4cea5015ab1d408b823be5"
|
|
28
|
+
"18f4300de4c4c7ea380d726fb109fa224da950ef0a4cea5015ab1d408b823be5",
|
|
29
|
+
"0a1b6575f6df8139766c8e71ba7320e14d2a5a5ed8ab26b6b43f7a006153d37d"
|
|
28
30
|
]
|
|
29
31
|
},
|
|
30
32
|
".agents/skills/new-invariant/SKILL.md": {
|
|
@@ -56,7 +58,8 @@
|
|
|
56
58
|
"since": "0.5.0",
|
|
57
59
|
"hashes": [
|
|
58
60
|
"a2fb0d03c65701af9d2d69cbcb2582ae573f097b1e1071eb2916e5e4f7832b37",
|
|
59
|
-
"9616e4767942b2021e34ab7bb76eec9a5c280cc608a0756abb02743741d5fc8a"
|
|
61
|
+
"9616e4767942b2021e34ab7bb76eec9a5c280cc608a0756abb02743741d5fc8a",
|
|
62
|
+
"a6340b95a03000b89fb27f5357cdd9c7ec12b714054b5334b61a30da600405e8"
|
|
60
63
|
]
|
|
61
64
|
},
|
|
62
65
|
".agents/skills/ro-debug/SKILL.md": {
|
|
@@ -117,7 +120,8 @@
|
|
|
117
120
|
"hashes": [
|
|
118
121
|
"c7c86de47b601dcb594ba8d8e23b5624ef8d47dafeddbc1aadd351c72e051d83",
|
|
119
122
|
"ece5a81db41bd48695a1a009239837b682d247baf6d19214eaa859a7519ab246",
|
|
120
|
-
"1646ed80de5268a886a2e861124cb3b871fa46df1857991a645667601f52253b"
|
|
123
|
+
"1646ed80de5268a886a2e861124cb3b871fa46df1857991a645667601f52253b",
|
|
124
|
+
"3d7bcbccd9a163f076bd1d8cc63021b7c8605d1cb1df24a3536db3e57c1d7630"
|
|
121
125
|
]
|
|
122
126
|
},
|
|
123
127
|
".claude/hooks/dod-checks.json": {
|
|
@@ -143,7 +147,8 @@
|
|
|
143
147
|
"4d396f412fc53094188b14348c5af4e79c7542a182630c20c4687d79899c5b0e",
|
|
144
148
|
"e7a513216ebbceaa7f11ec8fb611de8bb5d5925dfdfd75b779dcb7c0ee6e83cc",
|
|
145
149
|
"78047f42dda65076dd2cdb73ad530553db3d4a6f3ea7f0729590ac7286323cb1",
|
|
146
|
-
"5782d91c6c54155ad8bf3e107b6574b3ad4c97baa7be673a5ed252c70b387300"
|
|
150
|
+
"5782d91c6c54155ad8bf3e107b6574b3ad4c97baa7be673a5ed252c70b387300",
|
|
151
|
+
"5ffaba69ffc9b6c39cd3c97c4f29b44627416d55793b50aa1a26ffe5efc45497"
|
|
147
152
|
]
|
|
148
153
|
},
|
|
149
154
|
".claude/hooks/guard-core-purity.mjs": {
|
|
@@ -151,7 +156,8 @@
|
|
|
151
156
|
"hashes": [
|
|
152
157
|
"e36fbb92ee8395c6686fef582f29f2701747074b3b781bed42fe068f5c000bd7",
|
|
153
158
|
"282faa364c2d152808cd92ff7e39da26fd0549a5b2d0af9711d3453be2c666eb",
|
|
154
|
-
"4bdd9a38b1aa4050c109f7809ef924be4d411f5720b6030d57c5264ce3df556d"
|
|
159
|
+
"4bdd9a38b1aa4050c109f7809ef924be4d411f5720b6030d57c5264ce3df556d",
|
|
160
|
+
"15de3ae9a6007270f7b10d71ff9940160aadabd8f5b0995662fc324c483807e5"
|
|
155
161
|
]
|
|
156
162
|
},
|
|
157
163
|
".claude/hooks/guard-rulebook.mjs": {
|
|
@@ -175,7 +181,8 @@
|
|
|
175
181
|
"hashes": [
|
|
176
182
|
"93d4fa0fd1c18261cc8ef2b1ae2abe3a0200cc4b5a7b1d1d4ae433ca92c514b1",
|
|
177
183
|
"8deda7061122b69d72e708222ef2d38a971bb713269ec7fd1ca3440fe0a1150f",
|
|
178
|
-
"df325e672793e06b8315e64b59a329775d110fc166176074ff3bb8dea557c561"
|
|
184
|
+
"df325e672793e06b8315e64b59a329775d110fc166176074ff3bb8dea557c561",
|
|
185
|
+
"60959520dbe326880d284c9e2b76a2a89f72b981ea6a2cb76e2a252b1233bdfc"
|
|
179
186
|
]
|
|
180
187
|
},
|
|
181
188
|
".claude/hooks/inject-rules.mjs": {
|
|
@@ -197,7 +204,8 @@
|
|
|
197
204
|
".claude/hooks/lib/hook-input.mjs": {
|
|
198
205
|
"since": "0.6.2",
|
|
199
206
|
"hashes": [
|
|
200
|
-
"c40320d90e9585a52026e074e399b6883a0dfed704115b28e8da4dea284cf85f"
|
|
207
|
+
"c40320d90e9585a52026e074e399b6883a0dfed704115b28e8da4dea284cf85f",
|
|
208
|
+
"3be3d4af4a25536d2a2bac0441a1370be7efafb5f8aa737b195bdce77db0091b"
|
|
201
209
|
]
|
|
202
210
|
},
|
|
203
211
|
".claude/queue.json": {
|
|
@@ -237,14 +245,16 @@
|
|
|
237
245
|
"518d9b3d7cbae50f30c86d33b2b4bbea11ab3ba6cfef270876e92604b2af5f50",
|
|
238
246
|
"389484f0846c3dd8207c0f41bd56409103fbcc7f58b94b1bf4bd1d81b5af0e87",
|
|
239
247
|
"a2e10499a0bcd2cdc32f3986d27b59077c86e524d40323faabb2e5d78afc002c",
|
|
240
|
-
"c94c33d7ccbd46f191948325dfc7f68ce13b0d3a9470215de1de3f06b1499111"
|
|
248
|
+
"c94c33d7ccbd46f191948325dfc7f68ce13b0d3a9470215de1de3f06b1499111",
|
|
249
|
+
"ce90c1e697fdd444ca3fe2203d7991645f2c284c413ae187e4d6d6c618af52c9"
|
|
241
250
|
]
|
|
242
251
|
},
|
|
243
252
|
".claude/rules/node-ts.md": {
|
|
244
253
|
"since": "0.2.0",
|
|
245
254
|
"hashes": [
|
|
246
255
|
"3db68a4280cc30655be56fed9385179c378f560f3df55e21952a24066427e845",
|
|
247
|
-
"be3b7bf901ef250b5957a37815b9a339083f7a8c4ecc866aeb12e3a0797c3c09"
|
|
256
|
+
"be3b7bf901ef250b5957a37815b9a339083f7a8c4ecc866aeb12e3a0797c3c09",
|
|
257
|
+
"b74979a3a1e57b69a6e1b3ee2d0cf9fc671d4487c411dc947e9ad0a47ac56dd1"
|
|
248
258
|
]
|
|
249
259
|
},
|
|
250
260
|
".claude/rules/workflow.md": {
|
|
@@ -285,12 +295,24 @@
|
|
|
285
295
|
"b022399f287cdce1bcb07329c0aab44bf99714b5f0515f274c962f41ea072b86"
|
|
286
296
|
]
|
|
287
297
|
},
|
|
298
|
+
".claude/scripts/lib/claim-records.mjs": {
|
|
299
|
+
"since": "0.7.0",
|
|
300
|
+
"hashes": [
|
|
301
|
+
"acb1d5702a826832977e7eb01b76c50cab19292528901f1b33693e561dbb0a24"
|
|
302
|
+
]
|
|
303
|
+
},
|
|
288
304
|
".claude/scripts/lib/gate-coverage.mjs": {
|
|
289
305
|
"since": "0.6.0",
|
|
290
306
|
"hashes": [
|
|
291
307
|
"1ef7f355071a747d8a8d9cd5e2072a19fe3d8c11a0e2a5f884d95a33fb95f12d"
|
|
292
308
|
]
|
|
293
309
|
},
|
|
310
|
+
".claude/scripts/lib/revalidation-evidence.mjs": {
|
|
311
|
+
"since": "0.7.0",
|
|
312
|
+
"hashes": [
|
|
313
|
+
"513369213374cf2c5415c7d5ea1f6d5c67300c77cec7af3e9190e710b156969f"
|
|
314
|
+
]
|
|
315
|
+
},
|
|
294
316
|
".claude/scripts/lib/revalidation-points.mjs": {
|
|
295
317
|
"since": "0.6.0",
|
|
296
318
|
"hashes": [
|
|
@@ -305,6 +327,12 @@
|
|
|
305
327
|
"60fab2cc9f2028bccf6139e6a744406b4a86a9039d1367f3cef409902e9b327d"
|
|
306
328
|
]
|
|
307
329
|
},
|
|
330
|
+
".claude/scripts/lib/shell-tools.mjs": {
|
|
331
|
+
"since": "0.7.0",
|
|
332
|
+
"hashes": [
|
|
333
|
+
"402428f4b2c4e507652d775e43b26c1e0a74aadb2cedec3156ac186af17d667a"
|
|
334
|
+
]
|
|
335
|
+
},
|
|
308
336
|
".claude/scripts/lib/verdict.mjs": {
|
|
309
337
|
"since": "0.5.0",
|
|
310
338
|
"hashes": [
|
|
@@ -318,7 +346,8 @@
|
|
|
318
346
|
"21083ff7baeebf8aedbdf85679a353f671276a9e0201a58a8235ae63f55f081c",
|
|
319
347
|
"ceb6d35fa028f9c5e5e2d5965c627095d5ba80c37191a584627b4bc645b6be15",
|
|
320
348
|
"efa193dc543237d82dcb371fa1df6483ccd43c1db88d0e218f5d89769564974c",
|
|
321
|
-
"bed44df40412a7edac96914de21edc796df604ddc275ff1a02764dfcc4d4ede7"
|
|
349
|
+
"bed44df40412a7edac96914de21edc796df604ddc275ff1a02764dfcc4d4ede7",
|
|
350
|
+
"b3893c365de37ef6d9d04ab933296b9fcf09a0886197d7e12313fa63eacdbd89"
|
|
322
351
|
]
|
|
323
352
|
},
|
|
324
353
|
".claude/scripts/queue/as-of.mjs": {
|
|
@@ -340,7 +369,8 @@
|
|
|
340
369
|
"214f36e39f3809da5a121f404005d16a694280ca672ed10150b1b07d47912f6a",
|
|
341
370
|
"d8a5916bae71efcc6a21978af713112c9ec33a7554fd07f5978bdf2c3633b560",
|
|
342
371
|
"1804c2351a4f3042dc6a3fb4203f96e98ae12bec32569b99bda77d002d6ba5f2",
|
|
343
|
-
"b81ae3181e02b9c1c3f0e954688490ab3db3961381c2dc397c47c651c9d07f88"
|
|
372
|
+
"b81ae3181e02b9c1c3f0e954688490ab3db3961381c2dc397c47c651c9d07f88",
|
|
373
|
+
"c9902da15d06de3e952352115db0288433520eae2caac1f70ee6e06753d1f444"
|
|
344
374
|
]
|
|
345
375
|
},
|
|
346
376
|
".claude/scripts/queue/gate-rounds.mjs": {
|
|
@@ -355,7 +385,8 @@
|
|
|
355
385
|
"f473f0ee5fc469f47b2b21ee601310944faa1abed21942e97ed251aba826cd5d",
|
|
356
386
|
"86489ac7fcd06e43e31fb3d0ac9ab23174ef9c95196b08f127f1ae74da620c0c",
|
|
357
387
|
"f84148fee47109a388a248c51d3eb40919ce341785b561dd4135b69c6fedabf3",
|
|
358
|
-
"5ab8f741f17efb935b11caf245edf2b562cb887020c2a43d45464158342c933a"
|
|
388
|
+
"5ab8f741f17efb935b11caf245edf2b562cb887020c2a43d45464158342c933a",
|
|
389
|
+
"b5349837d16de0966139f5b65e2800486592f1b24d7e87087c2b7212cead479d"
|
|
359
390
|
]
|
|
360
391
|
},
|
|
361
392
|
".claude/scripts/queue/index.mjs": {
|
|
@@ -364,7 +395,8 @@
|
|
|
364
395
|
"cd149245dc29ef7489ae0e5394fa5a063dea2cc017bd3cbbface1ace6f8d7b46",
|
|
365
396
|
"7db3c17b781e6876b4822afd09e6affa97e46607b63d443975d987daf1f14464",
|
|
366
397
|
"9edd70b5960f367958e8e7500150b4edd285c99869cca803e40e0537d2d347b0",
|
|
367
|
-
"4cf917ac06708e1068dfe9f8bbebc9376c4748526bd669b9bea32929ba996d0a"
|
|
398
|
+
"4cf917ac06708e1068dfe9f8bbebc9376c4748526bd669b9bea32929ba996d0a",
|
|
399
|
+
"b4a0789be7ad4b401de872edb06665bca349048178b4dd6c5db848ca44f7c977"
|
|
368
400
|
]
|
|
369
401
|
},
|
|
370
402
|
".claude/scripts/queue/jira.mjs": {
|
|
@@ -375,7 +407,8 @@
|
|
|
375
407
|
"13c301f828d4402fcf81e7e0b2b1d22472cbdb50f6fd606770056af4ec215e51",
|
|
376
408
|
"b8be5855809c0d44ece94858456098663296c17c5ad9abb1ea2cf1a8f48ca491",
|
|
377
409
|
"3fc8ff9a06a2e22355a660a31e2943a97f50869f7e5726f768a7931d17b64b5b",
|
|
378
|
-
"f44203af187e855b9f738f8dbedfd313abf9d6a5cc29182fb46cd58d70698d7a"
|
|
410
|
+
"f44203af187e855b9f738f8dbedfd313abf9d6a5cc29182fb46cd58d70698d7a",
|
|
411
|
+
"c2f2af8ac5eadd8d35a15bcdeffe585e32c6f99b4e6ab9ace0f9d7fd9d694943"
|
|
379
412
|
]
|
|
380
413
|
},
|
|
381
414
|
".claude/scripts/queue/plan-md.mjs": {
|
|
@@ -384,7 +417,8 @@
|
|
|
384
417
|
"d137dad23f263b1a12b04b46625247fea648ded36d0fea7c5b4e4f2211a142eb",
|
|
385
418
|
"07eab69bd86b19b7a1f01eb14efe4f8c007481806cbe029d4014fe9bf0703000",
|
|
386
419
|
"27d7ae3832a32219d5c0ab136bc542388eb686e9f34053c3058104cdeea1574d",
|
|
387
|
-
"1320909605824b2cd1ff57878e463ef360463b2b175d2152638eda2dff72f5ea"
|
|
420
|
+
"1320909605824b2cd1ff57878e463ef360463b2b175d2152638eda2dff72f5ea",
|
|
421
|
+
"816aec4cb84492370972f71813a9fec7c0309e5f501951a93620a37cb318ac39"
|
|
388
422
|
]
|
|
389
423
|
},
|
|
390
424
|
".claude/scripts/queue/state.mjs": {
|
|
@@ -403,14 +437,16 @@
|
|
|
403
437
|
"since": "0.6.0",
|
|
404
438
|
"hashes": [
|
|
405
439
|
"32f847a2a3a5136cabcb42f6447da9f8cf98e2d20512212ee5201461128d7798",
|
|
406
|
-
"b62348a27bcaa1d62a0e4ddd53873fab6cb75f9af8e8c69d24f6ce81c592c4e3"
|
|
440
|
+
"b62348a27bcaa1d62a0e4ddd53873fab6cb75f9af8e8c69d24f6ce81c592c4e3",
|
|
441
|
+
"b151045e8083c398e94571b35dc9568dfa0102abcb847cdf764f6f694914d53e"
|
|
407
442
|
]
|
|
408
443
|
},
|
|
409
444
|
".claude/scripts/revalidation-report.mjs": {
|
|
410
445
|
"since": "0.6.0",
|
|
411
446
|
"hashes": [
|
|
412
447
|
"b99a3537158c2851698bfac027f7061811d7d428c3eea57f3ce0f58ea75dc249",
|
|
413
|
-
"78adac5c8f696f2c9cc86f404abf1d55604ccb10f11dd612501c14d4cf5935b1"
|
|
448
|
+
"78adac5c8f696f2c9cc86f404abf1d55604ccb10f11dd612501c14d4cf5935b1",
|
|
449
|
+
"fed627d2c8f0f5e6a4524b7015ac7a1cb5051a8c316ff4544af18be9c61eb163"
|
|
414
450
|
]
|
|
415
451
|
},
|
|
416
452
|
".claude/scripts/run-journal.mjs": {
|
|
@@ -423,7 +459,8 @@
|
|
|
423
459
|
"since": "0.5.0",
|
|
424
460
|
"hashes": [
|
|
425
461
|
"5682b4ef1e63b83e1398da4959d8b34f52aede38f896557c041687d101df015f",
|
|
426
|
-
"82c83fe9a66ff1a48c9e23fdfe84eef7da0de337c420e8d870085e7078d6f5e2"
|
|
462
|
+
"82c83fe9a66ff1a48c9e23fdfe84eef7da0de337c420e8d870085e7078d6f5e2",
|
|
463
|
+
"c502cefafdc720d178de685e8372d2c140cb2663517c9d88b5345a9f0c50d0de"
|
|
427
464
|
]
|
|
428
465
|
},
|
|
429
466
|
".claude/scripts/stop-flag.mjs": {
|
|
@@ -454,7 +491,8 @@
|
|
|
454
491
|
"48212660b2823725c2c9ee785ad739701e4c0e4733b275201a544df1abba28d0",
|
|
455
492
|
"55a6938b4d9967291a26e93301e34e5ffdef74a88f8c773a4d11b5d87d864fff",
|
|
456
493
|
"713718fbb2cda132f05665b29b8f1108a6305729b5e7c789d2053d117c13e08e",
|
|
457
|
-
"e588ab05bee707a099c80c9ea399008be31488e616f3db3c0598f66f3d1b3a52"
|
|
494
|
+
"e588ab05bee707a099c80c9ea399008be31488e616f3db3c0598f66f3d1b3a52",
|
|
495
|
+
"a180578d6e6de6a21900ff2f8a8ade2242170d16d2dd95574e5004435d870b9b"
|
|
458
496
|
]
|
|
459
497
|
},
|
|
460
498
|
".claude/skills/check-premises/SKILL.md": {
|
|
@@ -475,7 +513,8 @@
|
|
|
475
513
|
"eb52ef41269018107534d8dc2f552c57698e1677a1e76b5e666b5d09c007cac0",
|
|
476
514
|
"47922b182915cb92696f851174f2e88c4ae8c67dc119ef39a3a597ef1300fab5",
|
|
477
515
|
"57f6add0504db45e7577474f97705fe474310e4cd3310cdb348a2c64eabe88cd",
|
|
478
|
-
"18f4300de4c4c7ea380d726fb109fa224da950ef0a4cea5015ab1d408b823be5"
|
|
516
|
+
"18f4300de4c4c7ea380d726fb109fa224da950ef0a4cea5015ab1d408b823be5",
|
|
517
|
+
"0a1b6575f6df8139766c8e71ba7320e14d2a5a5ed8ab26b6b43f7a006153d37d"
|
|
479
518
|
]
|
|
480
519
|
},
|
|
481
520
|
".claude/skills/new-invariant/SKILL.md": {
|
|
@@ -510,7 +549,8 @@
|
|
|
510
549
|
"368a50be809f7be865d6d29ab3e54b9d69acd2ea3ba7929c0edeef161c2521b7",
|
|
511
550
|
"75adb84414a330db621ff4f1363b3926f537133199236a9e25bb9880b935e02e",
|
|
512
551
|
"a2fb0d03c65701af9d2d69cbcb2582ae573f097b1e1071eb2916e5e4f7832b37",
|
|
513
|
-
"9616e4767942b2021e34ab7bb76eec9a5c280cc608a0756abb02743741d5fc8a"
|
|
552
|
+
"9616e4767942b2021e34ab7bb76eec9a5c280cc608a0756abb02743741d5fc8a",
|
|
553
|
+
"a6340b95a03000b89fb27f5357cdd9c7ec12b714054b5334b61a30da600405e8"
|
|
514
554
|
]
|
|
515
555
|
},
|
|
516
556
|
".claude/skills/ro-debug/SKILL.md": {
|
|
@@ -565,7 +605,14 @@
|
|
|
565
605
|
"hashes": [
|
|
566
606
|
"c676647d585ec87427545a391598706ecaa74dfe413a7e05877e336bf8942874",
|
|
567
607
|
"89d999c068ef5b6e48913c15a165359e66b1f505b9f97c145d8c730cbf42d09a",
|
|
568
|
-
"1fc2fc35b04fa4ad0859841af72f45695bc346d1a1a9b20ba5d971d48888a910"
|
|
608
|
+
"1fc2fc35b04fa4ad0859841af72f45695bc346d1a1a9b20ba5d971d48888a910",
|
|
609
|
+
"fa9a34eb9f889910e55269b76172608b989d553583de38af34316a31f4ad570b"
|
|
610
|
+
]
|
|
611
|
+
},
|
|
612
|
+
".rig/revalidation.json": {
|
|
613
|
+
"since": "0.7.0",
|
|
614
|
+
"hashes": [
|
|
615
|
+
"312b59f80fcbcf2897ef80fb54be236fb6b2b1745f705dae8e66c58f0bbd3099"
|
|
569
616
|
]
|
|
570
617
|
},
|
|
571
618
|
"AGENTS.md": {
|
|
@@ -603,7 +650,14 @@
|
|
|
603
650
|
"docs/decisions/codex-adapter.md": {
|
|
604
651
|
"since": "0.5.0",
|
|
605
652
|
"hashes": [
|
|
606
|
-
"30e55d866d9a2c7359e594181070c63b1974d9df36e000caf419229284303a2e"
|
|
653
|
+
"30e55d866d9a2c7359e594181070c63b1974d9df36e000caf419229284303a2e",
|
|
654
|
+
"ebf0ef61407944373c862d37e6a80d4965ece72304b931428c6b3fcc5d9527c4"
|
|
655
|
+
]
|
|
656
|
+
},
|
|
657
|
+
"docs/decisions/content-blind-revalidation.md": {
|
|
658
|
+
"since": "0.7.0",
|
|
659
|
+
"hashes": [
|
|
660
|
+
"d640a152428ea4cc6a5f0a19be58e0d23f3a99c44b0ad0b72152ec7b48fe5bfd"
|
|
607
661
|
]
|
|
608
662
|
},
|
|
609
663
|
"docs/decisions/fail-open-guards.md": {
|
|
@@ -8,5 +8,6 @@
|
|
|
8
8
|
"0.5.0": "d78d0e77307a2be128de46ff4f64e3c146b5df2b",
|
|
9
9
|
"0.6.0": "29ca0543368e922349945e52541a92b46ddcc5bd",
|
|
10
10
|
"0.6.1": "f1d1e3dbd2161545d77ee5e7f90fa8e74b8a9f3e",
|
|
11
|
-
"0.6.2": "2a1fc8e10cd2b65deb5c95d937fd7de39f2c92a2"
|
|
11
|
+
"0.6.2": "2a1fc8e10cd2b65deb5c95d937fd7de39f2c92a2",
|
|
12
|
+
"0.7.0": "6589db36e1daa63a99ec595191db1cccf7373196"
|
|
12
13
|
}
|