task-pipeline-skill 1.84.1 → 1.85.2
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 +142 -0
- package/README.md +1 -1
- package/SKILL-CARD.md +1 -1
- package/package.json +1 -1
- package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
- package/plugins/task-pipeline/skills/evidence-docs/SKILL.md +2 -0
- package/plugins/task-pipeline/skills/project-audit/SKILL.md +3 -2
- package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/certification.md +3 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +43 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,145 @@
|
|
|
1
|
+
## v1.85.2 — the two-merge protocol, followed this time
|
|
2
|
+
|
|
3
|
+
**v1.85.1 is a burned tag** — the third of this wave's choreography lessons, and
|
|
4
|
+
this member's own: the release gate on the tag's tree demands a run stamp inside
|
|
5
|
+
the tag's range, the branch run cannot see a tag that does not exist yet, and the
|
|
6
|
+
stamp was never written. Nothing shipped; npm never saw 1.85.1. This version is
|
|
7
|
+
the same change released by the protocol B-134 wrote down: the payload merges
|
|
8
|
+
first, the stamp merges second citing the payload's merge commit, and the tag
|
|
9
|
+
lands on the stamp.
|
|
10
|
+
|
|
11
|
+
Guards: 429 → **429** — nothing but version surfaces, this record, and the
|
|
12
|
+
stamp's own choreography move in this release.
|
|
13
|
+
|
|
14
|
+
## v1.85.1 — five surfaces a reader trusts, each disagreeing with the tree it ships from
|
|
15
|
+
|
|
16
|
+
The family audit of 2026-09-06 (wave `AUDIT-WAVE-0906`) read every member's shipped
|
|
17
|
+
surfaces at once, and five of this member's disagreed with what the tree holds. No
|
|
18
|
+
behaviour changed in this release; what changed is what a reader — a person on the
|
|
19
|
+
marketplace page, or a resolver following a path — is told.
|
|
20
|
+
|
|
21
|
+
- **The marketplace entry taught the old gate vocabulary.** `plugin.json` says *typed
|
|
22
|
+
auto/judgment/manual gates*; `.claude-plugin/marketplace.json` said *typed
|
|
23
|
+
auto/manual*. The `judgment` type has been in the schema since v1.73.0 and the
|
|
24
|
+
v1.80.0 sweep put it on seven surfaces — the marketplace blurb was not one of them,
|
|
25
|
+
because the cross-surface guard reads the schema and `SKILL.md`, never the
|
|
26
|
+
marketplace entry. The two descriptions are byte-equal now, compared rather than
|
|
27
|
+
eyeballed: `json.load` both, `==` → `True` (the sole difference was 9 bytes at
|
|
28
|
+
character 298, the string `judgment/`).
|
|
29
|
+
- **Two in-directory references in `project-audit`'s `SKILL.md` resolved only in the
|
|
30
|
+
sibling skill.** Its §6 named `references/backlog.md` and
|
|
31
|
+
`references/prioritisation.md` bare — directories the flagship skill carries and
|
|
32
|
+
`project-audit` does not — while the routing table at the top of the same file
|
|
33
|
+
already used the `../task-pipeline/references/…` form. Both now use that form, as
|
|
34
|
+
links that resolve from the file that carries them.
|
|
35
|
+
- **`certification.md` pointed at a file no install of this plugin can resolve.**
|
|
36
|
+
`references/statistics.md` lives in `agent-stack`'s `agent-evals` skill, another
|
|
37
|
+
member entirely; the sentence carried it as a bare path beside the owner's name. It
|
|
38
|
+
is a named-owner prose pointer now, with no bare in-repo path left to resolve.
|
|
39
|
+
- **Front matter inside the pack moves together.** `evidence-docs` carried neither
|
|
40
|
+
`license:` nor `compatibility:`; `project-audit` carried no `license:`. Both now
|
|
41
|
+
carry the flagship's keys — `license: MIT`, and a compatibility line true of each
|
|
42
|
+
skill rather than copied: `evidence-docs` ships no scripts, and its line says so.
|
|
43
|
+
- **The `quick` opt-out is retired; the canon refusal replaces it.** *"quick fix"*
|
|
44
|
+
carries the trigger `fix` and the opt-out `quick` in one natural breath, and the
|
|
45
|
+
board already records the escape being used on work that should not have taken it
|
|
46
|
+
(`B-095`). The description now names *'no pipeline' / 'без пайплайна'* — the refusal
|
|
47
|
+
wording the operator's routing doctrine states — and the opt-out guard in
|
|
48
|
+
`test/validate.py` demands exactly that pair, so a description that drops either
|
|
49
|
+
valve fails. No recorded decision protects the old token: the only decision-bearing
|
|
50
|
+
surfaces that name it are `B-095`, which argues against it, and dated records, which
|
|
51
|
+
are not rewritten. No advertised trigger phrase was removed. Measured with
|
|
52
|
+
make-skill's auditor before and after: description 897 → 903 of 1024, inside the
|
|
53
|
+
970-character working limit, all sixteen description checks green both times.
|
|
54
|
+
|
|
55
|
+
The dated spec `docs/evidence/specs/2026-08-10-routing-taxonomy.md` still quotes the
|
|
56
|
+
old opt-out pair, deliberately: it records what was true at its commit, and this
|
|
57
|
+
repository has already decided that dated records are counted, not rewritten.
|
|
58
|
+
|
|
59
|
+
Guards: 429 → **429** — no planted-defect step added or removed; one existing guard's
|
|
60
|
+
needle moved with the surface it reads (`quick` → `no pipeline`). And the gate earned
|
|
61
|
+
its keep on this very release: its first run refused three restated figures this entry's
|
|
62
|
+
own change had gone stale — the board's description budget (897 → 903), its headroom
|
|
63
|
+
(127 → 121 spare), and the README's conformance figure (899 → 905) — each rewritten to
|
|
64
|
+
the value the owning check computes, so the next drift fails the same way this one did.
|
|
65
|
+
|
|
66
|
+
## v1.85.0 — a release stamp names the tag, and the amend rule's sibling one level up
|
|
67
|
+
|
|
68
|
+
`B-124`, filed by the umbrella's coordinator after watching the same class three times:
|
|
69
|
+
`v1.79.1` twice and `v1.80.0`. It recurred again on 2026-09-05 in the umbrella
|
|
70
|
+
repository and **burned two tags** in one afternoon, which is what turns it from a
|
|
71
|
+
memory gap into a mechanism gap — this repository's retro had recorded the lesson twice
|
|
72
|
+
already.
|
|
73
|
+
|
|
74
|
+
**Each step is right on its own**, which is why the amend rule did not cover it: the
|
|
75
|
+
stamp is written on the PR branch → it cites that branch's HEAD → `main` is
|
|
76
|
+
**rebase-merge-only** by ruleset → the rebase mints new SHAs → the object the stamp names
|
|
77
|
+
dies with the branch. Two correct refusals follow, and both cost a full CI round measured
|
|
78
|
+
at 57–97 minutes here:
|
|
79
|
+
|
|
80
|
+
1. the unstamped-release guard reads the tag's own commit range and finds no stamp that
|
|
81
|
+
resolves;
|
|
82
|
+
2. the documentation gate resolves every backticked SHA against a **fresh clone**, where
|
|
83
|
+
the branch commit never existed.
|
|
84
|
+
|
|
85
|
+
**A SHA the author can know before the merge is precisely the SHA the merge destroys**,
|
|
86
|
+
so the rule cannot be *write a better SHA*. `references/retrospective.md` now carries the
|
|
87
|
+
two shapes that survive — cite the release **tag**, or write the stamp **after** the
|
|
88
|
+
merge naming the merge commit, which is the default because the amend rule already
|
|
89
|
+
requires the SHA to exist before a file names it — and the step that ends the class: cut
|
|
90
|
+
the tag locally, run `npm run test:all` against **its** tree, and push only if that is
|
|
91
|
+
green. A tag cannot be repaired; deleting or re-pointing one is refused by repository
|
|
92
|
+
rule, correctly, because a tag is a promise about a tree.
|
|
93
|
+
|
|
94
|
+
`test/validate.py` asserts the section names all five load-bearing strings, so the rule
|
|
95
|
+
cannot rot into an intention the next author reads past — which is how it recurred.
|
|
96
|
+
|
|
97
|
+
Guards: 424 → **429** — one plant per named string, each removing **every** occurrence
|
|
98
|
+
inside the section.
|
|
99
|
+
|
|
100
|
+
### And adding those five plants broke CI silently
|
|
101
|
+
|
|
102
|
+
Not a side note — the mechanism this repository's whole assurance story rests on has a
|
|
103
|
+
budget, and this release spent the last of it.
|
|
104
|
+
|
|
105
|
+
The five plants, written inline, took `.github/workflows/validate.yml` from **508 189 to
|
|
106
|
+
518 928 bytes**, and GitHub **stopped creating runs entirely**. The workflow still
|
|
107
|
+
reported `active` through the API, `head_sha` had zero runs, and `gh pr checks` printed
|
|
108
|
+
*no checks reported* — which reads like a queue delay, not a refusal. The PR sat with no
|
|
109
|
+
CI and nothing said why.
|
|
110
|
+
|
|
111
|
+
**Bracketed by measurement rather than by the documentation alone:**
|
|
112
|
+
|
|
113
|
+
| workflow size | runs created |
|
|
114
|
+
|---|---|
|
|
115
|
+
| 508 189 bytes | yes |
|
|
116
|
+
| **518 928 bytes** | **none** |
|
|
117
|
+
| 511 096 bytes, after the plants were factored into a script | yes |
|
|
118
|
+
|
|
119
|
+
GitHub's documented ceiling is 512 KB and it falls inside that bracket, which is why the
|
|
120
|
+
hard number in the guard is the documented one rather than a guess dressed as a
|
|
121
|
+
measurement. The guard has **two bands**: it fails past 512 000, and it *prints* the
|
|
122
|
+
remaining room past 505 000 — because a ceiling you only learn about by crossing it is
|
|
123
|
+
the defect, not the ceiling.
|
|
124
|
+
|
|
125
|
+
It prints **904 bytes remaining** today.
|
|
126
|
+
|
|
127
|
+
**The rule that bought the room:** a plant's body belongs in `test/plant_*.py`, called
|
|
128
|
+
with an argument. Five inline copies cost 10 739 bytes; one script and five four-line
|
|
129
|
+
steps cost 2 907.
|
|
130
|
+
|
|
131
|
+
**My own measurement was wrong first.** I sized the file with `len(s)` — characters — and
|
|
132
|
+
read 509 350 for a file of 511 096 bytes, because the workflow carries Cyrillic. The
|
|
133
|
+
guard uses `os.path.getsize`.
|
|
134
|
+
|
|
135
|
+
**The check's first draft was itself the defect it guards against.** It searched the whole
|
|
136
|
+
file, and `git merge-base --is-ancestor` already appears under *Every lesson carries its
|
|
137
|
+
commit* — so the plant that removed the command from the new rule **passed**, and the
|
|
138
|
+
check was resting on a different section's sentence. Scoped to the section now, with all
|
|
139
|
+
five needles watched refusing their plant. Two of those plants had to be rewritten to
|
|
140
|
+
remove **every** occurrence: a plant that leaves a second copy behind proves the check is
|
|
141
|
+
inert when it is not.
|
|
142
|
+
|
|
1
143
|
## v1.84.1 — the conformance sentence is computed, and two of its five figures were wrong
|
|
2
144
|
|
|
3
145
|
**A sentence of five measured figures, and nothing derived any of them.** The README's
|
package/README.md
CHANGED
|
@@ -587,7 +587,7 @@ must say so.
|
|
|
587
587
|
### Held to Anthropic's own Skill authoring guidance
|
|
588
588
|
|
|
589
589
|
Audited against the four Agent Skills pages. Most of it already held — `name`
|
|
590
|
-
13/64 chars, `description`
|
|
590
|
+
13/64 chars, `description` 903/1024 chars, `SKILL.md` 262/500 lines, all 38 references
|
|
591
591
|
linked **directly** from `SKILL.md`, and the bundle far under the 30 MB ceiling. What
|
|
592
592
|
did not, now does:
|
|
593
593
|
|
package/SKILL-CARD.md
CHANGED
|
@@ -12,7 +12,7 @@ harmless.
|
|
|
12
12
|
|---|---|
|
|
13
13
|
| **Purpose** | Runs a substantial task through ten gated delivery stages — intake grill, docs study, brainstorm, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs+registers, acceptance — refusing to advance until each gate passes |
|
|
14
14
|
| **Owner** | ssheleg ([github.com/ssheleg/task-pipeline](https://github.com/ssheleg/task-pipeline)) |
|
|
15
|
-
| **Version** | 1.
|
|
15
|
+
| **Version** | 1.85.2 |
|
|
16
16
|
| **Surface** | Claude Code (filesystem skill + plugin) and the vercel `skills` CLI. **Not** uploaded to the Skills API; custom Skills do not sync across surfaces |
|
|
17
17
|
| **Dependencies** | None required. Optional: `context7` (MCP), `figma` (MCP), super-ux, agent-sync, graphify, obsidian-wiki, and **one of two browser channels** — `playwright` (CLI or MCP) or `chrome-devtools` (MCP); either satisfies the browser step and neither is required. Every stage's doctrine ships in-repo; the one conditional requirement is super-ux for the stage-3 UX track on a user-facing task |
|
|
18
18
|
| **Evaluation status** | Suite authored, 5 categories. One recorded run, **self-observed by the author**; **zero blind runs on zero of three models** — the split, and the numbers, live in [`evals/RESULTS.md`](evals/RESULTS.md) and are computed by `evals/run.py` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "task-pipeline-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.85.2",
|
|
4
4
|
"description": "Full-cycle delivery pipeline for coding agents: a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine ships inside the skill — no companion plugin required. This package is the installer CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"task-pipeline": "bin/task-pipeline.js"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "task-pipeline",
|
|
4
4
|
"displayName": "Task Pipeline",
|
|
5
5
|
"description": "Runs a substantial task through a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine is built into the skill — no companion plugin required — with typed auto/judgment/manual gates, a frozen requirement spine that closes with evidence, a work board and a verification ledger that outlive a run, an exposure line naming what shipped unconfirmed, a progress rail computed from the project's own config, a loop guard whose review ceiling measures rather than stops, and stage-3 tracks for what a product does, how it sounds and how it looks. Two modes need no task: `checkup` (what is unverified) and `setup` (audit existing docs). Retro insights can publish upstream as issues, opt-in and redacted.",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.85.2",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "ssheleg",
|
|
9
9
|
"url": "https://x.com/sshlg93"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: evidence-docs
|
|
3
3
|
description: "Use when writing or reviewing anything that will be read as true — a decision record, a README, an acceptance report, a runbook, a changelog entry, an audit finding, or any claim that something was verified. Applies the ten canons of evidence-backed documentation — what makes a claim documentation rather than an assertion — and routes to the doctrine that enforces each one. Also use when a project needs a documentation gate, a decision register, a propagation matrix, or a retrospective that outlives its author. Triggers - 'documentation gate', 'decision record', 'ADR', 'acceptance report', 'runbook', 'is this verified', 'доказательная документация', 'записать решение', 'запиши решение', 'отчёт о приёмке', 'раннбук', 'чем это подтверждено', 'доки в синхроне'. Not for: drafts, chat answers, commit messages or code comments — say 'без доков' to opt out."
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: "Doctrine runs on any agent. No bundled scripts — nothing to install and nothing to degrade."
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Evidence-backed documentation
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: project-audit
|
|
3
3
|
description: "Use when someone asks what is actually true of a whole project right now — what is finished, what is half-built, what is broken, and what nobody has looked at. Walks a cold start: discover what the project is, run a registry of probes chosen from that, read production evidence (published artefact against source, CI history, telemetry present or absent), then leave a self-contained HTML report and a JSON sidecar so the next audit can say what moved. Read-only: it proposes board rows and commits nothing. Triggers - 'project audit', 'audit the project', 'codebase audit', 'state of the project', 'what is unfinished', 'project health check', 'аудит проекта', 'проаудируй проект', 'состояние проекта', 'что не доделано', 'аудит кодовой базы'. Not for: auditing one deliverable inside a run (that is the pipeline's own ladder), reviewing a diff, or checking a skill's construction — say 'без диагностики' to opt out."
|
|
4
|
+
license: MIT
|
|
4
5
|
compatibility: "The collector (scripts/audit.py) needs python3 and reads committed state, so it needs git. Probes needing gh, npm, network or a browser declare it and report blind when it is absent — degraded, never silent."
|
|
5
6
|
---
|
|
6
7
|
|
|
@@ -115,10 +116,10 @@ what ran are the same object.
|
|
|
115
116
|
|
|
116
117
|
**This skill commits nothing.** Findings leave as board rows in the project's
|
|
117
118
|
own vocabulary, priced with **the board header's declared formula** — the shipped
|
|
118
|
-
default is `Sev × Blast + age_bonus` (`references/backlog.md
|
|
119
|
+
default is `Sev × Blast + age_bonus` ([`references/backlog.md`](../task-pipeline/references/backlog.md), the pipeline's
|
|
119
120
|
board doctrine) — and the operator accepts them. Effort never ranks inside an
|
|
120
121
|
audit: what a fix costs is the fixer's decision, not the finder's
|
|
121
|
-
(`references/prioritisation.md`). An audit
|
|
122
|
+
([`references/prioritisation.md`](../task-pipeline/references/prioritisation.md)). An audit
|
|
122
123
|
that edits while it reads cannot be re-run to check itself.
|
|
123
124
|
|
|
124
125
|
## A finding carries its consequence, or it is a hypothesis
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-pipeline
|
|
3
|
-
description: "Use when work changes the repository — feature, fix, refactor, migration, integration, rewrite, adoption or hardening; фича, фикс, рефактор, миграция, интеграция, доработать, починить, внедрить, перевести — or when the output is a finding that lands in it: audit/аудит, bug hunt/проверь ошибки, production check/проверь прод, PR review/ревью PR — or on 'run this through the pipeline' / 'прогони по конвейеру', 'full cycle, the full cycle' / 'полный цикл', /task-pipeline. Runs a substantial task through an intake grill, docs study, brainstorm, spec, plan, build, tests, deploy, post-deploy, docs/wiki sync and acceptance with explicit gates. 'checkup' / 'чекап' reports unconfirmed releases; 'setup' audits existing docs. Not for: answering a question, explaining code, a typo or a one-line edit, a mechanical rename, reconnaissance that lands nothing — say '
|
|
3
|
+
description: "Use when work changes the repository — feature, fix, refactor, migration, integration, rewrite, adoption or hardening; фича, фикс, рефактор, миграция, интеграция, доработать, починить, внедрить, перевести — or when the output is a finding that lands in it: audit/аудит, bug hunt/проверь ошибки, production check/проверь прод, PR review/ревью PR — or on 'run this through the pipeline' / 'прогони по конвейеру', 'full cycle, the full cycle' / 'полный цикл', /task-pipeline. Runs a substantial task through an intake grill, docs study, brainstorm, spec, plan, build, tests, deploy, post-deploy, docs/wiki sync and acceptance with explicit gates. 'checkup' / 'чекап' reports unconfirmed releases; 'setup' audits existing docs. Not for: answering a question, explaining code, a typo or a one-line edit, a mechanical rename, reconnaissance that lands nothing — say 'no pipeline' / 'без пайплайна' to opt out."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: "Doctrine runs on any agent. The bundled scripts need python3; the run needs git. Missing either degrades, never blocks — the graph verbs and seeded gates go unused, and the run says so."
|
|
6
6
|
---
|
|
@@ -116,8 +116,9 @@ severity. Sequential testing cuts the trials such a verdict needs by **78%**.
|
|
|
116
116
|
|
|
117
117
|
So: **two severities for a finding, three verdicts for a stochastic check.** A
|
|
118
118
|
deterministic command exits 0 or it does not, and admitting a maybe there does admit
|
|
119
|
-
everything. The instrument for the other case is `agent-stack`'s `agent-evals` —
|
|
120
|
-
`references/statistics.md
|
|
119
|
+
everything. The instrument for the other case is `agent-stack`'s `agent-evals` skill —
|
|
120
|
+
its own `references/statistics.md`, shipped in that member, says how many runs make a
|
|
121
|
+
difference real — and a gate whose
|
|
121
122
|
subject is non-deterministic belongs on that axis rather than this one
|
|
122
123
|
([`gates.md`](gates.md) → *Axis A*).
|
|
123
124
|
|
|
@@ -33,6 +33,7 @@ file exists to stop.
|
|
|
33
33
|
- Write the entry only for a divergence — and name the layer that owned it
|
|
34
34
|
- Every lesson carries its commit
|
|
35
35
|
- Never amend a commit a record already names
|
|
36
|
+
- A release stamp names the TAG, and the merge commit — never the branch's own SHA
|
|
36
37
|
- The stamp table is capped at ten, and *one line per run* was never a cap
|
|
37
38
|
- `publish:` is a line in the verdict, not a silence
|
|
38
39
|
- Rotation — the archive is how pruning stops losing things
|
|
@@ -113,6 +114,48 @@ The stamp costs one line and one commit. A run that folds it back into the work
|
|
|
113
114
|
the history tidy is trading a reader's ability to find the incident for the appearance of
|
|
114
115
|
tidiness — and the reader is the entire reason the stamp exists.
|
|
115
116
|
|
|
117
|
+
## A release stamp names the TAG, and the merge commit — never the branch's own SHA
|
|
118
|
+
|
|
119
|
+
The sibling of the amend rule, one level up, and it recurred three times after the amend
|
|
120
|
+
rule was written because each step is right on its own: stamp the run on the PR branch →
|
|
121
|
+
the stamp cites that branch's HEAD → `main` is **rebase-merge-only** by ruleset → the
|
|
122
|
+
rebase mints new SHAs → the object the stamp names dies with the branch.
|
|
123
|
+
|
|
124
|
+
Measured across `v1.79.1` (twice) and `v1.80.0`, and again on 2026-09-05 in the umbrella
|
|
125
|
+
repository, where it burned **two tags** in one afternoon. Each recurrence costs the same
|
|
126
|
+
two refusals, both of them correct:
|
|
127
|
+
|
|
128
|
+
1. the **unstamped-release guard** reads the tag's own commit range, finds no stamp that
|
|
129
|
+
resolves, and refuses the release;
|
|
130
|
+
2. the **documentation gate** resolves every backticked commit reference against a *fresh
|
|
131
|
+
clone*, where the branch SHA has never existed, and refuses again.
|
|
132
|
+
|
|
133
|
+
Then it costs one extra PR and one full CI round — measured at 57–97 minutes here.
|
|
134
|
+
|
|
135
|
+
**The shape that survives a rebase-merge is the tag.** A SHA the author can know before
|
|
136
|
+
the merge is precisely the SHA the merge is about to destroy, so the rule cannot be
|
|
137
|
+
"write a better SHA". Two spellings are allowed and nothing else:
|
|
138
|
+
|
|
139
|
+
- **cite the release tag** — `v1.84.1` is immutable, it is the thing being released, and
|
|
140
|
+
it resolves in any clone;
|
|
141
|
+
- **or write the stamp AFTER the merge**, in a second PR, naming the **merge commit**.
|
|
142
|
+
This is the default, because it is what the amend rule already forces one level down:
|
|
143
|
+
once a file names a SHA, that commit is frozen, so the SHA has to exist first.
|
|
144
|
+
|
|
145
|
+
The order for a release run is therefore:
|
|
146
|
+
|
|
147
|
+
1. merge the work; the merge commit is now a real object on `main`;
|
|
148
|
+
2. **then** stamp, in a second PR, naming that merge commit;
|
|
149
|
+
3. cut the tag **locally**, run `npm run test:all` against the tag's own tree, and push
|
|
150
|
+
the tag only if that run is green — `git merge-base --is-ancestor <stamp-sha> HEAD`
|
|
151
|
+
is what the release gate will ask, so ask it first.
|
|
152
|
+
|
|
153
|
+
Step 3 is not optional and it is not the same as a green branch build: the branch tree
|
|
154
|
+
and the tag's tree differ by whatever the merge did, and **a tag cannot be repaired** —
|
|
155
|
+
deleting or re-pointing one is refused by repository rule, correctly, because a tag is a
|
|
156
|
+
promise about a tree. A tag pushed on a green branch build is a promise about a tree
|
|
157
|
+
nobody ran.
|
|
158
|
+
|
|
116
159
|
## The stamp table is capped at ten, and *one line per run* was never a cap
|
|
117
160
|
|
|
118
161
|
Measured 2026-08-10: standing instructions **~1 234 tok** behind a cap of ten, run stamps
|