loki-mode 9.50.2 → 9.50.3
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/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/proof-generator.py +7 -5
- package/autonomy/run.sh +228 -5
- package/dashboard/__init__.py +1 -1
- package/docs/COMPETITIVE-INTEL-2026-09.md +444 -0
- package/docs/INSTALLATION.md +1 -1
- package/docs/ONE-RUN-AUDIT.md +277 -0
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/skills/00-index.md +15 -0
- package/skills/factory-operations.md +508 -0
- package/skills/release-cadence.md +382 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# Release Cadence (skill module)
|
|
2
|
+
|
|
3
|
+
**Purpose:** the shortest VERIFIED path from idea to published. Shortest and
|
|
4
|
+
verified are both load-bearing; this repo has shipped fast and shipped nothing
|
|
5
|
+
at the same time, four times in a row, and the cost was invisible for days.
|
|
6
|
+
|
|
7
|
+
**Authority:** the binding procedure is the CLAUDE.md "Release Workflow"
|
|
8
|
+
section (version-bump file list, dashboard build, pre-publish validation,
|
|
9
|
+
distribution verification). This module does not duplicate that list. It
|
|
10
|
+
encodes the CADENCE decisions around it: which gate blocks, what the pipeline
|
|
11
|
+
actually enforces for you, and the failure modes that make a release silently
|
|
12
|
+
publish nothing.
|
|
13
|
+
|
|
14
|
+
**Companion:** `skills/factory-operations.md` for role and coordination rules.
|
|
15
|
+
Section 5 there (release windows) and section 4 here are the same rule seen
|
|
16
|
+
from two sides.
|
|
17
|
+
|
|
18
|
+
**REGISTRATION REQUIRED (blocking).** `tests/test-skill-doc-accuracy.sh:126-133`
|
|
19
|
+
loops every `skills/*.md` and FAILS any file that `skills/00-index.md` cannot
|
|
20
|
+
route to. Measured on creation: the suite went from 57 passed / 0 failed to 57
|
|
21
|
+
passed / 2 failed, both failures being this file and `factory-operations.md`.
|
|
22
|
+
Until a routing row is added to `00-index.md`, the gate is red. A module the
|
|
23
|
+
index cannot name is also a module the agent never loads, however binding it
|
|
24
|
+
claims to be.
|
|
25
|
+
|
|
26
|
+
All measured numbers below carry their measurement date. Line numbers drift;
|
|
27
|
+
each citation also names a string or label to grep.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 1. The gate decision, and why two files appear to disagree
|
|
32
|
+
|
|
33
|
+
**The FAST tier is the release gate. The FULL tier is not a blocker.**
|
|
34
|
+
|
|
35
|
+
That is the founder decision of 2026-07-31, recorded in CLAUDE.md under a
|
|
36
|
+
header that says so explicitly: "Local CI Before Every Push (2026-07-31 mandate
|
|
37
|
+
-- SUPERSEDES 2026-04-26)".
|
|
38
|
+
|
|
39
|
+
The measured basis, all from that date:
|
|
40
|
+
|
|
41
|
+
| Thing | Measured |
|
|
42
|
+
|---|---|
|
|
43
|
+
| GitHub CI Tests | 31 seconds |
|
|
44
|
+
| GitHub CI Release | 2 minutes |
|
|
45
|
+
| Local FULL tier | 26m50s |
|
|
46
|
+
| 323-suite shell run, serial | ~1440s |
|
|
47
|
+
| Same run, sharded 4 ways | 352s (4.1x, 0 failures, identical coverage) |
|
|
48
|
+
|
|
49
|
+
CI is fast because it shards the 323-suite shell run 4 ways; the local full
|
|
50
|
+
tier had no sharding at all. A 26-minute gate cannot sit in front of an hourly
|
|
51
|
+
release cadence.
|
|
52
|
+
|
|
53
|
+
### 1.1 The apparent contradiction, resolved
|
|
54
|
+
|
|
55
|
+
`scripts/local-ci.sh` prints, on a FAST pass:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
All FAST-tier local-ci checks passed.
|
|
59
|
+
This is NOT push authorization.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
and on a FULL pass, `Safe to commit + push.` Read alone, that says the opposite
|
|
63
|
+
of the mandate above.
|
|
64
|
+
|
|
65
|
+
Both are correct, because they answer different questions, and the wording is
|
|
66
|
+
deliberately pinned. `tests/test-local-ci-tiers.sh:60-70` ASSERTS both strings:
|
|
67
|
+
that the fast verdict contains `NOT push authorization`, and that `Safe to
|
|
68
|
+
commit + push` appears ONLY in the full branch. This is an invariant under
|
|
69
|
+
test, not drift to be tidied away.
|
|
70
|
+
|
|
71
|
+
The reconciliation:
|
|
72
|
+
|
|
73
|
+
- **Fast tier is the gate.** A red fast tier BLOCKS the push. It is not
|
|
74
|
+
skippable and it costs about a minute.
|
|
75
|
+
- **Fast green is not a verification certificate.** The verdict line exists to
|
|
76
|
+
stop a fast pass being mistaken for a full one. It names what was deferred:
|
|
77
|
+
282 shell suites (~10+ min), blanket pytest 1793 tests (128s), shellcheck
|
|
78
|
+
(118s), plus SBOM, npm audit, license-audit, bun-parity and MCP handshakes
|
|
79
|
+
(`scripts/local-ci.sh:1911-1918`).
|
|
80
|
+
- **Full tier is not a release precondition** because its BULK moved to CI,
|
|
81
|
+
which runs it faster. The 323-suite shell run and the pytest blanket are
|
|
82
|
+
covered by Tests, and `required-ci` enforces Tests, Bun Parity and Security
|
|
83
|
+
Audit at the exact release SHA (section 3). Blocking locally on those buys
|
|
84
|
+
latency without buying coverage.
|
|
85
|
+
|
|
86
|
+
Be precise about what that does NOT cover, because "CI has it" is false for
|
|
87
|
+
part of the deferred list. Measured by grepping `.github/workflows/`:
|
|
88
|
+
`sbom` appears in four workflows (`sbom.yml`, `provenance.yml`, `release.yml`,
|
|
89
|
+
`security-audit.yml`), but **shellcheck, license-audit and the MCP handshakes
|
|
90
|
+
match no workflow at all.** Those items are checked NOWHERE until somebody runs
|
|
91
|
+
a full tier deliberately. This is the same point CLAUDE.md makes from the other
|
|
92
|
+
direction: "Of seven real defects found on 2026-07-31, four were caught by the
|
|
93
|
+
local gate ALONE -- GitHub CI has no equivalent check."
|
|
94
|
+
|
|
95
|
+
So the trade is explicit: skip the full tier for cadence, and accept that a
|
|
96
|
+
shellcheck or license regression can reach main. Run the FULL tier when
|
|
97
|
+
diagnosing something specific, on a quiet cycle, or after changes concentrated
|
|
98
|
+
in shell scripts or dependencies. Never as a release precondition.
|
|
99
|
+
|
|
100
|
+
Caveat worth carrying: `scripts/local-ci.sh:1903-1905` justifies its verdict
|
|
101
|
+
text by citing "CLAUDE.md mandates the full gate before every push", which is
|
|
102
|
+
the SUPERSEDED 2026-04-26 rule. The string is right and pinned; its stated
|
|
103
|
+
reason is stale. Do not let the comment talk you into blocking a release on the
|
|
104
|
+
full tier.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 2. What the fast tier must contain: the artifact rule
|
|
109
|
+
|
|
110
|
+
**A check that guards the SHIPPED ARTIFACT must run in the FAST tier.** It is
|
|
111
|
+
the only tier that runs before every push, and GitHub CI has no equivalent
|
|
112
|
+
check, because everything works fine from a git checkout.
|
|
113
|
+
|
|
114
|
+
This is the most expensive lesson in this repo's release history. Four releases
|
|
115
|
+
(v8.38.0 to v8.41.0) were spent discovering that the checks guarding the
|
|
116
|
+
shipped package were themselves unguarded:
|
|
117
|
+
|
|
118
|
+
- Four quality-gate detectors under `tests/` were never in `package.json`
|
|
119
|
+
`files[]`, so mutation-integrity fail-closed on EVERY iteration for EVERY npm
|
|
120
|
+
user. First-pass completion was impossible regardless of model output. Found
|
|
121
|
+
only because telemetry showed a gate failing in 0-1 seconds across 3 of 3
|
|
122
|
+
iterations; real analysis cannot run in zero seconds.
|
|
123
|
+
- The committed `loki-ts/dist/loki.js` hardcoded version 8.11.0 for 27
|
|
124
|
+
releases, because the dist-freshness check was DEFERRED by the very fast tier
|
|
125
|
+
that CLAUDE.md justifies with dist freshness.
|
|
126
|
+
- `npm pack tarball contents` was also deferred, and when promoted turned out
|
|
127
|
+
to pass on "6 or more" matches of 6 patterns that healthily produce 8. It
|
|
128
|
+
tolerated losing two required artifacts and could not say which.
|
|
129
|
+
|
|
130
|
+
Those checks are now on the fast-tier keep list by name, each with its measured
|
|
131
|
+
cost (`scripts/local-ci.sh:210-245`, grep `_FAST_KEEP`):
|
|
132
|
+
|
|
133
|
+
| Kept check | Measured cost |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `dist/loki.js is a fresh build of src` | one `bun run build`, ~40ms |
|
|
136
|
+
| `npm pack tarball contents` | 1.6s |
|
|
137
|
+
| `Agent SDK is a resolvable root dependency` | 21ms |
|
|
138
|
+
| `parent checkout is not falsely marked bare` | sub-second |
|
|
139
|
+
|
|
140
|
+
against a roughly 60s tier. The keep list is an ALLOWLIST, not a denylist:
|
|
141
|
+
the fast tier states positively what it runs, so a newly added slow check
|
|
142
|
+
cannot quietly drift into it (`scripts/local-ci.sh:108-127`).
|
|
143
|
+
|
|
144
|
+
### 2.1 The two rules that generalise past packaging
|
|
145
|
+
|
|
146
|
+
**Assert each required thing individually, never a count.** A threshold cannot
|
|
147
|
+
say WHICH artifact vanished, and it absorbs slack it was never meant to have.
|
|
148
|
+
The "6 or more of 6 patterns that produce 8" check is the worked example.
|
|
149
|
+
|
|
150
|
+
**Guard against vacuity.** An empty result is not evidence; it is an absent
|
|
151
|
+
measurement. A substring search over an empty listing reports nothing missing.
|
|
152
|
+
`npm pack` writes its listing to STDERR, so `2>&1 >file` captures build chatter
|
|
153
|
+
instead and makes every assertion pass. Assert the haystack is plausibly sized
|
|
154
|
+
first.
|
|
155
|
+
|
|
156
|
+
The pipeline already implements this rule in two places, and both are worth
|
|
157
|
+
copying rather than reinventing:
|
|
158
|
+
|
|
159
|
+
- `release.yml:120-130` VACUITY GUARD: an empty workflow-runs API result never
|
|
160
|
+
satisfies the wait loop, because "no failing runs" over zero runs is not
|
|
161
|
+
"everything passed."
|
|
162
|
+
- `release.yml:520-535` takes the LAST line of `npm pack --silent`, because
|
|
163
|
+
prepack's bun build writes to stdout too and a naive capture would be three
|
|
164
|
+
lines rather than a filename.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 3. What the pipeline enforces for you
|
|
169
|
+
|
|
170
|
+
Know this before adding a local check: duplicating it wastes cadence, and
|
|
171
|
+
assuming it wastes releases.
|
|
172
|
+
|
|
173
|
+
`on: push, paths: [VERSION], branches: [main]` (`release.yml:3-8`). Then:
|
|
174
|
+
|
|
175
|
+
**`gate`** runs bash syntax validation, then Bun typecheck plus `bun test`,
|
|
176
|
+
then Python tests. The order is not cosmetic. v9.49.0 died on a one-line TS2322
|
|
177
|
+
in `doctor.ts`; because the typecheck ran LAST, the job spent ~3m46s on pip
|
|
178
|
+
installs and the full pytest suite before tsc failed in 7 seconds (measured on
|
|
179
|
+
run 34724377951: gate 4m03s total). Cheapest failing check first is now the
|
|
180
|
+
rule, and nothing about what is verified changed, only the order.
|
|
181
|
+
|
|
182
|
+
**`required-ci`** (`needs: gate`) polls the check-runs API for Tests, Bun Parity
|
|
183
|
+
and Security Audit AT THE EXACT RELEASE SHA, waiting up to 2400s and failing
|
|
184
|
+
closed. Its direction is load-bearing: "cancelled, timed_out, failure, skipped:
|
|
185
|
+
none is a pass." It deliberately polls rather than re-running the matrix inline,
|
|
186
|
+
because re-running would verify a DIFFERENT execution than the one the branch
|
|
187
|
+
was judged on, at double the cost for a weaker guarantee.
|
|
188
|
+
|
|
189
|
+
**`release`** (`needs: [gate, required-ci]`) creates the tag, the GitHub
|
|
190
|
+
release and its artifacts. Publish jobs hang off `needs: release`:
|
|
191
|
+
`publish-npm`, `publish-docker`, and the others are PARALLEL SIBLINGS. That has
|
|
192
|
+
a consequence the npm job documents: "the channel with the assertion cannot
|
|
193
|
+
stop the one without it, and npm has already shipped by the time Docker goes
|
|
194
|
+
red" (`release.yml:523-525`). A per-channel assertion protects only its own
|
|
195
|
+
channel.
|
|
196
|
+
|
|
197
|
+
`publish-npm` asserts the PACKED tarball embeds the current VERSION, not the
|
|
198
|
+
worktree, because `prepack` rebuilds dist during publish and SWALLOWS a failed
|
|
199
|
+
build (`|| echo 'WARN: ... using existing dist if present'`), yielding exit 0
|
|
200
|
+
and a tarball carrying a stale dist. The committed dist legitimately lags
|
|
201
|
+
VERSION: 9dfb18d2 shipped VERSION 9.50.1 with a committed dist embedding
|
|
202
|
+
9.50.0, and npm published 9.50.1 correctly because prepack rebuilt it.
|
|
203
|
+
Asserting on the worktree would have failed that good release.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 4. The two ways a release silently publishes nothing
|
|
208
|
+
|
|
209
|
+
Both have happened more than once. Both look like success from the terminal.
|
|
210
|
+
|
|
211
|
+
### 4.1 The VERSION bump must be the push HEAD
|
|
212
|
+
|
|
213
|
+
`on: push, paths: [VERSION]` fires only if the VERSION-changing commit is the
|
|
214
|
+
HEAD of the push. GitHub creates a workflow run for the push head only. Bump
|
|
215
|
+
VERSION, keep working, push the batch, and the release silently no-ops.
|
|
216
|
+
|
|
217
|
+
Verified through the Actions API (`repos/.../actions/runs?head_sha=<sha>`):
|
|
218
|
+
|
|
219
|
+
| Commit | Tests runs |
|
|
220
|
+
|---|---|
|
|
221
|
+
| `c86115d5` (v9.14.0 bump) | 0 |
|
|
222
|
+
| `5d081dbc` (v9.15.0 bump) | 0 |
|
|
223
|
+
| `151b7401` (v9.16.0 bump) | 0 |
|
|
224
|
+
| push heads (`4158b6c1`, `1b7069ba`, `946cf472`) | 1 each |
|
|
225
|
+
|
|
226
|
+
loki-mode shipped 9.13.0 through 9.16.0 to git with full CHANGELOG entries
|
|
227
|
+
while npm latest stayed 9.12.6, and 15 commits landed after the 9.16.0 bump.
|
|
228
|
+
It survived four rounds because the releases were reported as shipped without
|
|
229
|
+
checking npm.
|
|
230
|
+
|
|
231
|
+
`scripts/release.sh` has always been correct: it commits (`:227`) and pushes
|
|
232
|
+
(`:235`) back to back, so the bump IS the head. The failure came from bumping
|
|
233
|
+
by hand and bypassing it. Use `scripts/release.sh`, or make the VERSION bump
|
|
234
|
+
the last commit before the push.
|
|
235
|
+
|
|
236
|
+
Recovery for an already-stranded bump needs BOTH dispatches, because
|
|
237
|
+
`security-audit.yml` shares the `paths: [VERSION]` trigger and `required-ci`
|
|
238
|
+
fails closed on "Security Audit: not reported yet":
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
gh workflow run security-audit.yml --ref main
|
|
242
|
+
# wait for Tests + Bun Parity + Security Audit green at the SAME sha
|
|
243
|
+
gh workflow run release.yml --ref main
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Note: a fast-tier check named "VERSION is not stranded ahead of the last
|
|
247
|
+
release" was recorded as the going-forward detection for this. It is NOT
|
|
248
|
+
present in `scripts/local-ci.sh` today (grepped on two independent term sets,
|
|
249
|
+
zero matches). Until it exists, this failure mode is caught only by the
|
|
250
|
+
post-release npm verification in section 5. Treat that verification as
|
|
251
|
+
mandatory, not as belt and braces.
|
|
252
|
+
|
|
253
|
+
### 4.2 Pushing during the window cancels the release's Tests
|
|
254
|
+
|
|
255
|
+
After a VERSION push, push NOTHING to that branch until npm shows the new
|
|
256
|
+
version. Any later push moves HEAD, GitHub's concurrency rules CANCEL the older
|
|
257
|
+
Tests run at the release SHA, and `required-ci` correctly refuses to treat
|
|
258
|
+
`cancelled` as a pass.
|
|
259
|
+
|
|
260
|
+
On 2026-08-08 v9.18.0 failed with `FAIL: a required workflow did not succeed at
|
|
261
|
+
8892f477`. Nothing was broken:
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
Tests: completed/cancelled
|
|
265
|
+
Bun Parity: completed/success
|
|
266
|
+
Security Audit: completed/success
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Re-broken on 2026-09-10 by a docs-only commit pushed during v9.27.3's release.
|
|
270
|
+
"It is only docs" is not an exemption: concurrency cancellation keys on the
|
|
271
|
+
BRANCH, not the diff.
|
|
272
|
+
|
|
273
|
+
Diagnose by reading the per-workflow status lines before assuming a test
|
|
274
|
+
failure; `cancelled` and `failure` look identical in the job summary and have
|
|
275
|
+
completely different fixes. Recovery without a version bump: rerun the
|
|
276
|
+
cancelled **Tests** at the release SHA first, then rerun **Release**. A later
|
|
277
|
+
commit that does not touch VERSION fires no Release of its own, so there is
|
|
278
|
+
nothing else to wait for.
|
|
279
|
+
|
|
280
|
+
Rewriting the same VERSION value is "nothing to commit" and the trigger never
|
|
281
|
+
fires. Re-releasing needs a REAL change to VERSION.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## 5. After the push: verify provenance, not the version string
|
|
286
|
+
|
|
287
|
+
A matching version on npm is NOT evidence that your tree shipped.
|
|
288
|
+
|
|
289
|
+
On 2026-08-08 npm `latest` read 9.17.0 within minutes of a release push and the
|
|
290
|
+
version matched the bump. It was a different build: the published tarball's
|
|
291
|
+
`gitHead` was `00b9f4e2`, a commit that is not even an ancestor of main,
|
|
292
|
+
published by a parallel agent's release run that won the race. The package was
|
|
293
|
+
functional and contained none of the fixes its own CHANGELOG described.
|
|
294
|
+
|
|
295
|
+
Several agents run against this checkout at once. Two release workflows for the
|
|
296
|
+
same version both start; the first to reach `npm publish` takes the version and
|
|
297
|
+
the second fails on version-conflict.
|
|
298
|
+
|
|
299
|
+
So verify:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
npm view loki-mode@<V> gitHead
|
|
303
|
+
git merge-base --is-ancestor <gitHead> HEAD
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
and confirm a specific fix is present in the published tarball WITH A POSITIVE
|
|
307
|
+
CONTROL, so an empty grep cannot read as clean:
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
npm pack loki-mode@<V> && tar xzf loki-mode-<V>.tgz
|
|
311
|
+
grep -c "<fix-string>" package/<file> # the fix: expect > 0
|
|
312
|
+
grep -c "<string-that-must-exist>" package/<file> # control: proves the grep works
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
A zero without a control is an absent measurement, not a clean result.
|
|
316
|
+
|
|
317
|
+
### 5.1 Confirm a release-critical fix THREE ways, never one
|
|
318
|
+
|
|
319
|
+
One green reading proves nothing. Require all three, and record all three:
|
|
320
|
+
|
|
321
|
+
1. **LIVE** -- the real check against the real source reads the expected value.
|
|
322
|
+
2. **NEGATIVE control** -- feed it a canned input representing the BAD state and
|
|
323
|
+
confirm it still reports bad. This proves the check can still fail, so a
|
|
324
|
+
green is informative.
|
|
325
|
+
3. **POSITIVE control** -- perturb something that must not matter and confirm
|
|
326
|
+
the answer is unchanged. This proves the green came from the logic, not from
|
|
327
|
+
a coincidence of the input.
|
|
328
|
+
|
|
329
|
+
Worked example, the MCP registry staleness guard (2026-09-14). The guard read
|
|
330
|
+
7.34.1 as live for hours after 9.50.1 was published, because it iterated
|
|
331
|
+
`servers[]` and took the first name match, and the registry keeps every
|
|
332
|
+
published version as a separate still-`active` row. The fix selects on
|
|
333
|
+
`isLatest`. It was confirmed:
|
|
334
|
+
|
|
335
|
+
- LIVE: reads 9.50.1 against the real registry.
|
|
336
|
+
- NEGATIVE: a canned response with `isLatest` on the OLD version still selects
|
|
337
|
+
the old version, proving real drift is still detected.
|
|
338
|
+
- POSITIVE: reversing the live array still selects 9.50.1, proving
|
|
339
|
+
order-independence rather than a lucky ordering.
|
|
340
|
+
|
|
341
|
+
Had only the LIVE reading been taken, a guard that happened to be right for one
|
|
342
|
+
ordering would have been declared fixed. See
|
|
343
|
+
`skills/factory-operations.md` section 7 for why this shape recurs, and for the
|
|
344
|
+
three other instances measured in the same session.
|
|
345
|
+
|
|
346
|
+
Applies to the artifact greps in this section too: a built artifact can contain
|
|
347
|
+
NUL bytes, which makes plain `grep` report no matches and exit 1 on a file that
|
|
348
|
+
demonstrably contains the string. Measured on `dashboard/static/index.html`:
|
|
349
|
+
`grep -c 'Loki'` finds nothing, `grep -ac 'Loki'` finds 27, Python finds 91.
|
|
350
|
+
Always pair a dist grep with a control string known to be present.
|
|
351
|
+
|
|
352
|
+
Then run the post-release distribution validation from CLAUDE.md across npm,
|
|
353
|
+
Docker, Brew and GitHub Release, on BOTH routes (Bun and `LOKI_LEGACY_BASH=1`).
|
|
354
|
+
Cleanup uses `loki_run_tmp_create` / `loki_run_tmp_cleanup` from CLAUDE.md's
|
|
355
|
+
"Test and Resource Cleanup"; never sweep shared ports, process names, `/tmp` or
|
|
356
|
+
`$TMPDIR`.
|
|
357
|
+
|
|
358
|
+
Timing note before calling a job hung: macOS Bun jobs legitimately take ~22
|
|
359
|
+
minutes. Compare against a prior successful run's `startedAt -> completedAt`
|
|
360
|
+
first. And npm's registry lags a green publish job by roughly 4 minutes, so a
|
|
361
|
+
green job is not yet proof the version is fetchable.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## 6. The cadence, end to end
|
|
366
|
+
|
|
367
|
+
1. **Scope locked** by the PM. No guessing (`skills/sdlc-fleet.md:40`).
|
|
368
|
+
2. **Build** inside owned file sets, at most 3 streams
|
|
369
|
+
(`skills/factory-operations.md` section 3).
|
|
370
|
+
3. **Council**: unanimous 3-of-3 APPROVE. Any CONCERN or REJECT means fix and
|
|
371
|
+
re-run the WHOLE council.
|
|
372
|
+
4. **Gate**: `bash scripts/local-ci.sh` (fast tier). Red blocks. One gate run
|
|
373
|
+
at a time, repo-wide.
|
|
374
|
+
5. **Bump VERSION as the push HEAD**, via `scripts/release.sh`.
|
|
375
|
+
6. **Window opens**: nobody pushes to main until npm shows the version.
|
|
376
|
+
7. **Verify provenance**: `gitHead` ancestry plus a fix grep with a positive
|
|
377
|
+
control.
|
|
378
|
+
8. **Window closes.** Queued commits land now.
|
|
379
|
+
|
|
380
|
+
Steps 4 through 7 are the verified part of "shortest verified path". Dropping
|
|
381
|
+
any one of them has already produced a release that reported success and
|
|
382
|
+
shipped nothing.
|