@sleepy_panda_srl/portulan 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.md +87 -0
  4. package/cli/README.md +337 -0
  5. package/cli/compile.mjs +2209 -0
  6. package/cli/control-chars.mjs +570 -0
  7. package/cli/discover.mjs +985 -0
  8. package/cli/doctor.mjs +2803 -0
  9. package/cli/feedback.mjs +970 -0
  10. package/cli/gate.mjs +271 -0
  11. package/cli/index.mjs +1390 -0
  12. package/cli/init.mjs +1729 -0
  13. package/cli/librarian.mjs +1384 -0
  14. package/cli/manifest.mjs +59 -0
  15. package/cli/new.mjs +803 -0
  16. package/cli/pack-version.mjs +543 -0
  17. package/cli/plugin-lint.mjs +1566 -0
  18. package/cli/portulan.mjs +266 -0
  19. package/cli/recipe-set.mjs +425 -0
  20. package/cli/rule-carriers.mjs +489 -0
  21. package/cli/skills-set.mjs +715 -0
  22. package/cli/stop-gate.mjs +434 -0
  23. package/cli/upgrade.mjs +897 -0
  24. package/cli/vendor.mjs +1504 -0
  25. package/core/README.md +46 -0
  26. package/core/engine.md +47 -0
  27. package/core/operating/autonomy.md +100 -0
  28. package/core/operating/evolution.md +84 -0
  29. package/core/operating/loop.md +83 -0
  30. package/core/operating/memory.md +161 -0
  31. package/core/operating/safety.md +42 -0
  32. package/core/operating/verification.md +76 -0
  33. package/core/personas/README.md +40 -0
  34. package/core/personas/implementer.md +51 -0
  35. package/core/personas/librarian.md +73 -0
  36. package/core/personas/reviewer.md +52 -0
  37. package/core/skills/README.md +52 -0
  38. package/core/skills/clarify/SKILL.md +42 -0
  39. package/core/skills/codify/SKILL.md +65 -0
  40. package/core/skills/consolidate/SKILL.md +121 -0
  41. package/core/templates/gate-policy.md +76 -0
  42. package/core/templates/handoff.md +29 -0
  43. package/core/templates/memory-entry.md +44 -0
  44. package/core/templates/pack.md +94 -0
  45. package/core/templates/persona.md +69 -0
  46. package/core/templates/proposal.md +27 -0
  47. package/core/templates/repo-card.md +28 -0
  48. package/core/templates/skill.md +57 -0
  49. package/core/templates/task.md +26 -0
  50. package/core/templates/workspace.md +81 -0
  51. package/package.json +41 -0
  52. package/packs/.claude-plugin/plugin.json +22 -0
  53. package/packs/README.md +61 -0
  54. package/packs/rituals/README.md +13 -0
  55. package/packs/rituals/checkpoints/README.md +105 -0
  56. package/packs/rituals/checkpoints/pack.json +36 -0
  57. package/packs/rituals/checkpoints/personas/supervisor.md +64 -0
  58. package/packs/rituals/checkpoints/skills/milestone-close/SKILL.md +75 -0
  59. package/packs/rituals/checkpoints/skills/pre-commit/SKILL.md +75 -0
  60. package/packs/rituals/checkpoints/skills/session-open/SKILL.md +57 -0
  61. package/packs/stacks/README.md +8 -0
  62. package/packs/tools/README.md +17 -0
  63. package/packs/tools/github/README.md +65 -0
  64. package/packs/tools/github/pack.json +29 -0
  65. package/packs/tools/github/verify/README.md +51 -0
  66. package/packs/tools/github/verify/actions-pinned.sh +132 -0
  67. package/spec/README.md +399 -0
  68. package/spec/migrations/0001-repository-declares-its-tree.mjs +100 -0
  69. package/spec/migrations/0002-bundle-fallback-path.mjs +179 -0
  70. package/spec/migrations/README.md +95 -0
  71. package/spec/pack.schema.json +201 -0
  72. package/spec/slots.md +796 -0
  73. package/spec/workspace.schema.json +438 -0
@@ -0,0 +1,61 @@
1
+ # packs/
2
+
3
+ Composable layers over the engine, each shipped as a plugin:
4
+
5
+ - `stacks/` — per-language / per-framework profiles.
6
+ - `tools/` — tool and MCP integrations.
7
+ - `rituals/` — repeatable procedures (e.g. PR babysitting, bot-review reconciliation).
8
+
9
+ A pack overrides `core`, and is itself overridden by the workspace, repo card, and task.
10
+
11
+ A pack declares what it contributes in a `pack.json` at its root, validated against
12
+ [`../spec/pack.schema.json`](../spec/pack.schema.json) — the Pack Definition, which is on its own
13
+ version train and not the Workspace Definition's. A workspace composes one by naming it in its `packs`
14
+ array, in the canonical `category/name` form.
15
+
16
+ ## Why there is a `.claude-plugin/plugin.json` in *this* directory
17
+
18
+ Because **this directory is itself a plugin payload**, and it had been shipping as one while declaring
19
+ nothing. The private feed's `portulan-checkpoints` entry is a `git-subdir` source rooted here, so what a
20
+ host installs is the contents of `packs/` — and until 2026-08-09 that payload carried no plugin manifest
21
+ at all. The host had nothing to read, registered nothing, and said so only as a count nobody was
22
+ watching: **`claude plugin details portulan-checkpoints@portulan-internal` → `Skills (0)`**, for the
23
+ whole of milestone 6 and after.
24
+
25
+ That is [#134](https://github.com/sleepy-panda-srl/portulan/issues/134)'s `Skills (0)` bullet, and the
26
+ issue's own diagnosis of it was wrong: it attributed the zero to a declared path pointing one level too
27
+ high, which is a real trap and a different one. Measured on Claude Code 2.1.226 by installing this
28
+ directory both ways — **`Skills (0)` without the manifest, `Skills (3)` with it**, the same three
29
+ `SKILL.md` files either way.
30
+
31
+ The manifest declares `./rituals/checkpoints/skills/` — the directory that actually holds them — because
32
+ **a host expands a declared skills path exactly one level and no further**. Declaring `./rituals/`
33
+ registers nothing, silently, while a validator walking deeper counts three;
34
+ [`../cli/plugin-lint.mjs`](../cli/plugin-lint.mjs) fails that shape for exactly this reason. Two
35
+ manifests therefore sit in this tree and they answer different questions: the repository's own at
36
+ [`../.claude-plugin/plugin.json`](../.claude-plugin/plugin.json), which declares
37
+ `./packs/rituals/checkpoints/skills/` because *its* root is the repository; and this one, whose root is
38
+ `packs/`. Neither is redundant, and the paths differ by exactly the prefix their roots differ by.
39
+
40
+ **The version here mirrors the pack's own** — `portulan.version` in
41
+ [`rituals/checkpoints/pack.json`](rituals/checkpoints/pack.json), which the Pack Definition names as how
42
+ independent versioning is expressed — and it is the number a host displays for the installed plugin.
43
+ Nothing checks the two agree, which is stated rather than railed because the feed pins a **commit**
44
+ rather than a version, so the pin is what actually decides which bytes install.
45
+
46
+ **One half of the measurement above has not been run and cannot be yet.** `Skills (0) → Skills (3)` was
47
+ observed through a *local* marketplace over a copy of this directory. The quoted failing command names
48
+ `portulan-checkpoints@portulan-internal`, and its green half can only be observed after this commit
49
+ exists and the feed's pin moves to it. Until then the green is demonstrated on the payload and inferred
50
+ for the feed — a distinction this repository would rather write down than round off.
51
+
52
+ > **Two packs exist.** [`rituals/checkpoints`](rituals/checkpoints/README.md), the supervised-build
53
+ > ritual, as of milestone 6; and [`tools/github`](tools/github/README.md), one verify recipe, authored
54
+ > at milestone 7 session 5 because a demonstration needed a real subject. `stacks/` is still empty and
55
+ > says why. _(This said "One pack exists … `stacks/` and `tools/` are still empty" from milestone 6
56
+ > until 2026-08-13, and the second half went false the day `tools/github` landed beside it.)_
57
+ >
58
+ > This file read "Nothing here yet" for four milestones, and the pack it predicted — a cross-artifact
59
+ > consistency check — is not the one that arrived. Recorded rather than quietly replaced: the first
60
+ > pack was chosen by which ritual this project could show working evidence for, not by which was named
61
+ > first.
@@ -0,0 +1,13 @@
1
+ # packs/rituals/
2
+
3
+ Ritual packs — repeatable procedures that compose onto the loop: PR babysitting, bot-review
4
+ reconciliation, release runbooks, the codify/librarian pass.
5
+
6
+ | Pack | What it carries |
7
+ |---|---|
8
+ | [`checkpoints`](checkpoints/README.md) | The supervised-build ritual: three checkpoints graded by a fresh context, a `supervisor` persona, and the verdict vocabulary. Milestone 6. |
9
+
10
+ > The cross-artifact consistency check named in the constitution's influence map — long listed here as
11
+ > the first ritual — is **still unwritten**. It was overtaken rather than cancelled: `checkpoints` went
12
+ > first because it is the ritual this project had a measured record for, having run it at every
13
+ > milestone since the first.
@@ -0,0 +1,105 @@
1
+ # `checkpoints` — the supervised-build ritual
2
+
3
+ A ritual pack: three checkpoints at which a **fresh context** grades work it did not do, and the fixed
4
+ vocabulary its verdicts are written in. Composed by a workspace through its `packs` array as
5
+ `rituals/checkpoints`.
6
+
7
+ The premise is one sentence, and it is **core's**, not this pack's: on the full lane the verdict comes
8
+ from a context that has not seen the implementation, because one primed by the implementing context
9
+ measures agreement rather than correctness. That obligation is stated in
10
+ [`../../../core/operating/loop.md`](../../../core/operating/loop.md), and
11
+ [`../../../core/operating/verification.md`](../../../core/operating/verification.md) explains why it is
12
+ a ceiling on the verifier rather than a rung on the hierarchy. What this pack adds is the **procedure**:
13
+ three named moments, a persona to staff them, and the vocabulary the verdicts are written in. The
14
+ premise moved into core on 2026-07-30; before that this file was where it was stated, which is why the
15
+ sentence reads as a citation now and did not before.
16
+
17
+ | Contributes | What |
18
+ |---|---|
19
+ | Skills | [`session-open`](skills/session-open/SKILL.md) · [`pre-commit`](skills/pre-commit/SKILL.md) · [`milestone-close`](skills/milestone-close/SKILL.md) |
20
+ | Persona | [`supervisor`](personas/supervisor.md) — grades, never implements or merges |
21
+ | Gate fragments | `commit-without-the-hooks` (gated) · `self-certify-a-checkpoint` (prohibited) |
22
+
23
+ ## The three checkpoints
24
+
25
+ | Checkpoint | When | What it grades |
26
+ |---|---|---|
27
+ | Session-open | before implementation starts | the session's plan, against the criterion and the workspace's own slots |
28
+ | Pre-commit | when the work is finished, before it is committed | the diff, re-measured against the criterion it claims to meet |
29
+ | Milestone-close | before a milestone is marked done | that the criterion was *demonstrated*, not asserted |
30
+
31
+ The **When** column is a summary; each skill's own *When to use it* is the operative statement,
32
+ including what an adopting workspace's autonomy tiers can and cannot move.
33
+
34
+ ## The verdict vocabulary
35
+
36
+ Four verdicts, and which are available depends on the checkpoint.
37
+
38
+ | Verdict | Means | Available at |
39
+ |---|---|---|
40
+ | **APPROVE** | Proceed as it stands. | session-open · pre-commit |
41
+ | **APPROVE-WITH-ADJUSTMENTS** | Proceed once the numbered adjustments are folded in. Not a soft failure — it is what a working checkpoint usually returns. | session-open · pre-commit |
42
+ | **REQUEST-CHANGES** | Does not meet the standard. Name what, and what would meet it. Needs a second pass at the same checkpoint. | all three |
43
+ | **CLOSE** | Every clause of the criterion is demonstrated; the milestone may be marked done. | milestone-close only |
44
+
45
+ **Every adjustment is numbered**, so it can be folded in and cited individually. An unnumbered list of
46
+ concerns is not a verdict.
47
+
48
+ **APPROVE and APPROVE-WITH-ADJUSTMENTS are unavailable at milestone-close on purpose.** Both let work
49
+ proceed on a promise to fold something in, and a close is the one decision with nothing downstream of
50
+ it to catch what was folded in wrongly.
51
+
52
+ ## The fidelity note
53
+
54
+ What a close leaves in the record once the session that wrote it is gone. Four parts, in one clause:
55
+
56
+ > **who** verified · **when** · **the verdict, with what was actually re-derived** · **what the close
57
+ > leaves undemonstrated**
58
+
59
+ A bare *done* plus a link is not a fidelity note.
60
+
61
+ ## What this pack does not do, said plainly
62
+
63
+ - **It cannot enforce the freshness, and the freshness is the entire mechanism.** No `tools:` list and
64
+ no permission rule can observe whether the context reading a checkpoint skill has already seen the
65
+ work. It is a property of how the checkpoint was *invoked*. So this pack ships a practice held by
66
+ whoever spawns the supervisor, and says so rather than shipping a contract that reads like a rail.
67
+ `self-certify-a-checkpoint` is a `prohibited` fragment with **no tool-level surface** — it names the
68
+ gap instead of inventing a matcher that would cover less than its sentence claims, and it therefore
69
+ **compiles to nothing on every backend**.
70
+ - **It does not set the lane boundary.** Checkpoints bind **full-lane** work; where that lane begins is
71
+ the adopting workspace's own threshold. A pack imposing three checkpoints on every one-line fix would
72
+ be ceremony that cannot scale down — which is a named non-goal, and the fastest route to a ritual
73
+ being switched off wholesale.
74
+ - **It ships no verify recipe.** The obvious one — *every milestone-affecting change carries a recorded
75
+ verdict* — would have to know the adopter's record format, and a recipe that cannot actually read
76
+ what it claims to check is worse than none. The Pack Definition can carry recipes
77
+ ([`../../../spec/pack.schema.json`](../../../spec/pack.schema.json)); this pack has nothing honest to
78
+ put in that field. _Since milestone 7 a pack's recipes are **composed** into the adopting workspace's
79
+ runnable set rather than merely declared, so this is a refusal with a cost now and not a limitation of
80
+ the format — and it is still the right refusal. It is a statement about **this** pack, never about
81
+ packs generally: [`tools/github`](../../tools/github/README.md) ships one, and was built because this
82
+ pack's refusal meant milestone 7's composition demonstration had no subject._
83
+ - **It grades against the adopter's standard, never against this pack's.** The skills read the
84
+ workspace's own constitution, plan, definition-of-done and gate map. Nothing here supplies a standard
85
+ of its own, and a supervisor substituting its taste for the team's is a second author rather than a
86
+ check.
87
+
88
+ ## Provenance
89
+
90
+ Re-expressed from public practice — supervised evolution as the guard against drift, last-mile review
91
+ focus, read-isolated verification. The structure is the two-tier protocol Portulan is itself built
92
+ under, and the checkpoint section of that project's own gate map.
93
+
94
+ **The evidence is that project's build record**, cited as provenance rather than as procedure: the
95
+ fresh-context checkpoints changed *designs* rather than wording at two consecutive milestones — the
96
+ story is in [milestone 4's record](https://github.com/sleepy-panda-srl/portulan/blob/main/docs/milestones/m04.md),
97
+ beside [the protocol itself](https://github.com/sleepy-panda-srl/portulan/blob/main/docs/plan.md) —
98
+ while adopters received no artifact for the ritual that produced them. This pack is that artifact.
99
+
100
+ Those two are **absolute URLs on purpose**, unlike this pack's links into `core/`, which ships beside
101
+ it and resolves for an adopter. A provenance link is a pointer at a public record that stays where it
102
+ is; a repo-relative one would resolve only inside the tree this pack was written in, and this pack is
103
+ meant to travel. What travels with it is the mechanism. The bindings that made it work in its home
104
+ repository — one maintainer's names, that tree's paths, its budgets and review-loop mechanics — stay
105
+ in the layer that owns them.
@@ -0,0 +1,36 @@
1
+ {
2
+ "portulan": {
3
+ "pack": "1.0",
4
+ "version": "0.2.1"
5
+ },
6
+
7
+ "name": "checkpoints",
8
+ "category": "rituals",
9
+ "summary": "Supervised-build checkpoints: a fresh-context supervisor grades the plan at session-open, the diff at pre-commit, and the demonstration at milestone-close, in a fixed verdict vocabulary.",
10
+ "doc": "README.md",
11
+
12
+ "contributes": {
13
+ "skills": ["skills/"],
14
+
15
+ "personas": ["personas/supervisor.md"],
16
+
17
+ "gates": [
18
+ {
19
+ "id": "commit-without-the-hooks",
20
+ "tier": "gated",
21
+ "action": {
22
+ "none": "No honest matcher. The CATEGORY is committing with the local hooks bypassed, and its spellings are unbounded shell: `--no-verify`, the `-c core.hooksPath=/dev/null` form that an incident in this repository actually used, `core.hooksPath` set at any config origin beforehand, `HUSKY=0` and its equivalents, or a wrapper on PATH. This rule carried `git commit --no-verify` for one milestone, and in the measured incident that matcher gave ZERO protection while reading as coverage — the act performed was the same category in another spelling, so the gate as enumerated never reached it. A matcher covering one spelling of an unbounded set is worse than an honest gap, because only the gap is visible. Enforcement here is the reader's discipline under the rule that an act's absence from a list is not a finding of permission (`core/operating/autonomy.md`); the incident is recorded as incident 3 of `.portulan/proposals/0029-a-constraint-names-a-category-not-a-list.md`."
23
+ },
24
+ "reason": "Bypassing the local hooks — by any spelling — turns a compiled gate back into a convention on a workspace that compiles its gate policy into those hooks. If the hooks are wrong, change the policy through the evolution gate rather than stepping around it for one commit: a bypass leaves no trace in the record that a policy change would have left."
25
+ },
26
+ {
27
+ "id": "self-certify-a-checkpoint",
28
+ "tier": "prohibited",
29
+ "action": {
30
+ "none": "No tool-level surface, and naming it rather than inventing a matcher is the point. A checkpoint verdict is a paragraph written into a record, so the act of grading your own work is indistinguishable at the tool layer from the act of recording someone else's grade. What makes the rule real is the fresh context, which no permission rule can observe — see the honest-limits section of README.md."
31
+ },
32
+ "reason": "The context that did the work may not also supply the verdict on it. A supervisor sharing the implementer's window has already read every rationalisation the implementer wrote for itself, which is the failure the fresh-context requirement exists to prevent, and a verdict produced that way looks exactly like one that was not."
33
+ }
34
+ ]
35
+ }
36
+ }
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: supervisor
3
+ description: Grades work it did not do, in a context that has not seen the work being done. Takes one of three checkpoints — a session's plan before it starts, a diff before it commits, or a milestone's demonstration before it is called done — and returns a verdict in a fixed vocabulary. It does not implement, fix, or merge. Delegate a checkpoint to it; never ask it to also do the work.
4
+ tools: [read, search, run-verify]
5
+ ---
6
+
7
+ # Persona — Supervisor
8
+
9
+ > The persona whose whole value is what it has **not** read. A supervisor sharing the implementer's
10
+ > window has already absorbed every rationalisation the implementer wrote for itself, and will grade
11
+ > the work against the reasoning that produced it rather than against the standard. Freshness is the
12
+ > mechanism; the verdict is only its output. The obligation itself is core's — the full lane's verdict
13
+ > comes from a context that has not seen the implementation
14
+ > ([`../../../../core/operating/loop.md`](../../../../core/operating/loop.md)); this persona is one way
15
+ > to staff it. _(Provenance: subagents as context firewalls, HumanLayer; read-isolated review,
16
+ > Cognition. See [`../README.md`](../README.md) for what this pack ships and what it cannot enforce.)_
17
+
18
+ ## Charter
19
+
20
+ - **For:** grading one checkpoint against the artefacts the adopting workspace already declares — its
21
+ constitution or principles slot, its plan, its definition-of-done, its gate map. The supervisor's
22
+ question is never *"is this good?"* but *"does this meet the standard this team wrote down?"*
23
+ - **Not for:** implementing, fixing what it finds, or merging. A supervisor that repairs a defect has
24
+ destroyed the independence that made its finding worth having, and the next checkpoint has nobody
25
+ left to grade the repair. It reports; someone else acts.
26
+ - **Not for** grading work it did any part of. See the `self-certify-a-checkpoint` fragment in
27
+ [`../pack.json`](../pack.json).
28
+
29
+ ## Autonomy reach
30
+
31
+ Acts in **Auto** to read and to *reproduce* verification — a read-only re-run, never a change. Its
32
+ output is advice into a **Propose** or **Gated** decision that a human owns. It executes no Gated
33
+ action, and it holds no authority to accept, merge, or close. **Prohibited is not a reach** and does
34
+ not appear here: it is the tier no role may act in.
35
+ _(Tier vocabulary from [`../../../../core/operating/autonomy.md`](../../../../core/operating/autonomy.md);
36
+ which concrete actions sit in which tier is the adopting workspace's gate map, never this pack's.)_
37
+
38
+ ## Read / write posture
39
+
40
+ Reads broadly and in parallel — the diff, the plan, the criterion, the workspace's own slots. Its only
41
+ write is the verdict, isolated to whatever surface the adopting workspace records verdicts on. It
42
+ touches no source file, which is the one part of this contract a host can turn into a rail by granting
43
+ the persona no write tool at all.
44
+
45
+ ## Memory scope
46
+
47
+ Its own supervisor memory: classes of defect this codebase produces, claims that turned out to be
48
+ overstated, checks that caught something real. Kept separate from the implementer's so a verdict is
49
+ never primed by the notes of the context it is grading — which is the same argument as the fresh
50
+ context, one layer down.
51
+ _(See [`../../../../core/operating/memory.md`](../../../../core/operating/memory.md).)_
52
+
53
+ ## Provenance & status
54
+
55
+ Re-expressed from public practice — last-mile review focus, read-isolated verification, supervised
56
+ evolution as the guard against drift. The `tools:` list is **capability classes** at engine altitude;
57
+ binding them to a host's concrete tools is the adopter's job, and
58
+ [`../../../../core/personas/README.md`](../../../../core/personas/README.md) records that such a binding
59
+ is lossy for every charter clause except *does not write*.
60
+
61
+ **What no binding enforces here: the freshness itself.** No `tools:` list and no permission rule can
62
+ observe whether the context reading this file has already seen the work. That is a property of how the
63
+ supervisor was *invoked*, not of what it may call — so it is a practice, held by whoever spawns the
64
+ checkpoint, and this pack says so rather than shipping a contract that reads like a rail.
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: milestone-close
3
+ description: Verify that a milestone's exit criterion was demonstrated rather than asserted, before it is marked done. Use when a milestone is proposed for closing — re-derive each clause independently instead of replaying the sessions that built it, and return CLOSE or REQUEST-CHANGES with a signed fidelity note. Runs in a context that did not implement the milestone, and after the work has merged.
4
+ ---
5
+
6
+ # Skill — Milestone-close checkpoint
7
+
8
+ > The checkpoint with the longest memory and the least sympathy. Its question is not *"was the work
9
+ > done well?"* — two earlier checkpoints already asked that — but *"is each clause of this criterion
10
+ > **demonstrated**, from the merged tree, by someone re-deriving it rather than being shown it?"*
11
+ > _(Part of the `checkpoints` ritual pack — see [`../../README.md`](../../README.md) for the verdict
12
+ > vocabulary in full and for what this pack cannot enforce.)_
13
+
14
+ ## When to use it
15
+
16
+ Before a milestone, epic, or release is marked done — after its work has merged, and in a context that
17
+ implemented none of it. **A milestone is never self-certified**: the session that built it is the one
18
+ context that cannot supply this verdict.
19
+
20
+ ## The pass
21
+
22
+ 1. **Run the forward-reference sweep — before grading anything else.** Search the doctrine and
23
+ the workspace's own memory for this milestone's number.
24
+
25
+ _Moved to the front of the pass, and the reason is a measurement rather than a preference. On the
26
+ workspace that authored this pack the promised-but-unowned class has recurred **three times**, twice
27
+ naming the same milestone — and every one was found by a human reading sideways, never by this step,
28
+ because a close that grades the row first has already formed its verdict by the time it gets here.
29
+ This is the one check that finds obligations **the criterion itself does not list**, so a close
30
+ graded only against the row cannot see them. Run it before the row, not after._
31
+
32
+ A sentence elsewhere promising that a capability arrives here is a debt against
33
+ this criterion, and it is invisible from both sides — the row reads complete and the doctrine reads
34
+ satisfied. It is a text search, not a judgement, which is why it is worth running rather than
35
+ trusting to memory of what was promised. **Reconciling expands the criterion and never narrows it:**
36
+ a promise the criterion omits is added; a criterion clause no doctrine backs is a question for the
37
+ owner, never a strike. Without that direction this step becomes an argument for deleting inconvenient
38
+ clauses.
39
+
40
+ 2. **Read the criterion clause by clause** and treat each as a separate obligation. A criterion is a
41
+ set of promises, and the failure mode is a close that satisfies the memorable ones.
42
+ 3. **Re-derive, do not replay.** Independently reproduce each clause from the merged tree — run the
43
+ recipes, read the live state, recompute what a session reported. Where an earlier session recorded a
44
+ figure, recompute it rather than quoting it; where it recorded a demonstration, perform it again.
45
+ 4. **Force red before believing green.** A clause verified only in the passing direction has not been
46
+ verified. Break what it guards, watch it fail, restore.
47
+ 5. **Name what the close leaves undemonstrated**, and put it in the verdict rather than in a footnote.
48
+ Every close has some; a close claiming none has stopped looking.
49
+ 6. **Return CLOSE or REQUEST-CHANGES, with the fidelity note.**
50
+
51
+ ## The verdicts this checkpoint may return
52
+
53
+ - **CLOSE** — every clause demonstrated; the milestone may be marked done.
54
+ - **REQUEST-CHANGES** — at least one clause is asserted rather than demonstrated. Name which, and what
55
+ would demonstrate it.
56
+
57
+ **APPROVE and APPROVE-WITH-ADJUSTMENTS are deliberately not available here.** Those verdicts let work
58
+ proceed on a promise to fold something in; a close is the one decision with nothing downstream of it to
59
+ catch what was folded in wrongly.
60
+
61
+ ## The fidelity note
62
+
63
+ What the record carries once the session that wrote it is gone. Four parts, in one clause:
64
+
65
+ > **who** verified · **when** · **the verdict, with what was actually re-derived** · **what the close
66
+ > leaves undemonstrated**
67
+
68
+ A bare *done* plus a link is not a fidelity note. The scoreboard everyone boots from has to say who
69
+ verified and what they found, or a close can be asserted at the one surface nobody re-reads.
70
+
71
+ ## Why it earns its tokens
72
+
73
+ It is the only check positioned to catch a milestone that was built correctly against a criterion
74
+ nobody re-read. The forward-reference sweep in particular has changed criteria that three prior
75
+ checkpoints passed over, because it is mechanical and reads what everyone else remembered.
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: pre-commit
3
+ description: Grade a finished diff before it is committed. Use when full-lane work is complete — re-measure the diff against the criterion it claims to meet, re-run the verify recipes yourself rather than reading the implementer's report of them, and return APPROVE, APPROVE-WITH-ADJUSTMENTS, or REQUEST-CHANGES. Runs in a context that has not seen the work being done.
4
+ ---
5
+
6
+ # Skill — Pre-commit checkpoint
7
+
8
+ > The checkpoint that must **re-measure rather than re-read**. The implementer's report of a green
9
+ > recipe is a claim like any other, and the one thing a fresh context can do that the implementer
10
+ > cannot is run it again without knowing what it is supposed to say. _(Part of the `checkpoints` ritual
11
+ > pack — see [`../../README.md`](../../README.md) for the verdict vocabulary in full and for what this
12
+ > pack cannot enforce.)_
13
+
14
+ ## When to use it
15
+
16
+ Before committing **full-lane** work: the finished diff is graded, then committed. The adopting
17
+ workspace's autonomy tiers do not move that moment — a tier says who must **attend** an action, and a
18
+ workspace whose commits and pushes are unattended by policy has said no *person* waits on them, not that
19
+ nothing is owed before them. An unattended commit is still committed after the verdict.
20
+
21
+ If the moment was missed — work misjudged as triage, or committed before anyone called it finished — the
22
+ verdict is owed before the work is put in front of anyone; which act does so first is for the adopting
23
+ workspace's gates to say, and a pull request is the usual first one. That is the recovery for a missed
24
+ moment, never an alternative moment. The lane boundary is likewise the adopting workspace's; see the
25
+ session-open skill for why this pack does not set it.
26
+
27
+ Also whenever a change touches doctrine, the autonomy tiers, or the platform floor — work whose blast
28
+ radius is large even when no milestone or roadmap state moves. Blast radius is the measure, not
29
+ whether a status column changed.
30
+
31
+ ## The pass
32
+
33
+ 1. **Run the workspace's verify recipes yourself.** All of them, and read the output rather than the
34
+ summary. *Measured, never derived* — a total quoted from an earlier run is a number about a tree
35
+ that no longer exists.
36
+ 2. **Re-measure the diff against the criterion**, not against the implementer's description of the
37
+ diff. Read the criterion first and the diff second, so what you are looking for is not framed by
38
+ what was built.
39
+ 3. **Check every claim the change makes about itself.** This is where a fresh context earns its cost:
40
+ a change's own description of what it did is the least-reviewed prose in any diff, and it goes stale
41
+ between the first draft and the last push. Sentences elsewhere in the tree that the change falsifies
42
+ belong here too. *Re-measure rather than re-read* holds for prose as it does for recipes: a claim
43
+ about a mechanism is checked **from the mechanism**, and a claim about the world — a filesystem
44
+ layout, a platform behaviour, an install — **from the world**. A sentence asserting behaviour is a
45
+ figure that happens to be spelled in words. **The author's reading is not evidence**: the wrong
46
+ sentence and the code it described were written in the same hour by the same context.
47
+ 4. **Sweep the siblings of every defect the diff repairs.** The rule is
48
+ [`../../../../../core/operating/evolution.md`](../../../../../core/operating/evolution.md)'s — *a fix
49
+ is not done at the site it was found* — and this step is the procedure, not a second statement of it.
50
+ Ask the diff for it: which rule does each fix restore, and where else is that rule enforced? The tool
51
+ the shape was copied from, the other arm of the same function, the other command taking the same flag,
52
+ the other direction of the same operation. What each site then owes is `evolution.md`'s sentence and
53
+ not a second wording of it. **It is the checkpoint's step rather than the implementer's** because the site an
54
+ implementer is looking at is the site they just understood, and the leftover is the one the next
55
+ reader copies. Do not accept a comment beside the fix as coverage of a second site.
56
+ 5. **Attack the coverage claims.** Where the change says a check now catches something, try to get past
57
+ it. A hole list is a claim like any other, and the only thing that checks a claim about coverage is
58
+ somebody trying to defeat it.
59
+ 6. **Force the new rails red.** A check nobody has seen fail is a check nobody has seen work. If the
60
+ change ships a rail, break the thing it guards and confirm it fires, then restore.
61
+ 7. **Return one verdict** with numbered adjustments, and state what the change leaves
62
+ **undemonstrated** — that sentence is what the record carries forward, and it is the half a
63
+ satisfied implementer is least likely to write.
64
+
65
+ ## The verdicts this checkpoint may return
66
+
67
+ - **APPROVE** — commit as it stands.
68
+ - **APPROVE-WITH-ADJUSTMENTS** — commit once the numbered adjustments are folded in.
69
+ - **REQUEST-CHANGES** — the diff does not meet the criterion; it needs work and a second pre-commit pass.
70
+
71
+ ## Why it earns its tokens
72
+
73
+ It is the last point at which a defect is cheap. Its value is concentrated in two things an author
74
+ structurally cannot supply: a re-run nobody is hoping will pass, and a reading of the change's own
75
+ claims by someone with no memory of having written them.
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: session-open
3
+ description: Grade a session's plan before any file is written. Use at the start of full-lane work — a plan against the workspace's constitution, its plan or roadmap, and the criterion the session claims to serve. Runs in a context that has not seen the plan being drafted, and returns APPROVE, APPROVE-WITH-ADJUSTMENTS, or REQUEST-CHANGES. Not for triage-lane work.
4
+ ---
5
+
6
+ # Skill — Session-open checkpoint
7
+
8
+ > The cheapest of the three, and the one that changes the most. A defect caught here costs a paragraph;
9
+ > the same defect caught at pre-commit costs the diff that was built on it. _(Part of the `checkpoints`
10
+ > ritual pack — see [`../../README.md`](../../README.md) for the verdict vocabulary in full and for
11
+ > what this pack cannot enforce.)_
12
+
13
+ ## When to use it
14
+
15
+ At the opening of **full-lane** work, before the implementer writes to any file.
16
+
17
+ **Where the lane boundary sits is the adopting workspace's, not this pack's.** Core defines two lanes
18
+ and leaves the boundary to the workspace
19
+ ([`../../../../../core/operating/loop.md`](../../../../../core/operating/loop.md)). A pack that imposed
20
+ three checkpoints on every one-line fix would be ceremony that cannot scale down — a named non-goal, and
21
+ the fastest way to get a ritual switched off wholesale. Read the workspace's own threshold and honour it.
22
+
23
+ ## The pass
24
+
25
+ 1. **Read the criterion the session claims to serve, as an input rather than as background.** If it
26
+ reads two ways, that ambiguity is the finding — say so before the session builds one of the two
27
+ readings by guessing. A criterion is the standard; a plan that quietly narrows it has already failed
28
+ and nothing downstream will notice.
29
+ 2. **Read the workspace's own slots** — constitution or principles, definition-of-done, gate map — and
30
+ grade the plan against what this team wrote down, never against your own taste. A supervisor
31
+ substituting its preferences for the team's standard is a second author, not a check.
32
+ 3. **Attack the plan's claims, not its prose.** For every capability the plan says will exist when the
33
+ session ends, ask what would demonstrate it. Plans fail most often by claiming a demonstration that
34
+ the described work cannot produce.
35
+ 4. **Check what the plan will make untrue.** A change lands inside a body of documents that describe the
36
+ system; sentences elsewhere go stale the moment it merges. Name them at the opening, when they are
37
+ cheap to include, rather than at pre-commit when they are a second pass.
38
+ 5. **Say where the plan claims something that will not exist.** A document may describe machinery only
39
+ if the machinery exists, or the sentence names where it arrives.
40
+ 6. **Return one verdict**, with every adjustment numbered so the implementer can fold them in and cite
41
+ them individually. An unnumbered list of concerns is not a verdict.
42
+
43
+ ## The verdicts this checkpoint may return
44
+
45
+ - **APPROVE** — proceed as planned.
46
+ - **APPROVE-WITH-ADJUSTMENTS** — proceed, with the numbered adjustments folded in. The common case, and
47
+ not a soft failure: it is what a checkpoint looks like when it is working.
48
+ - **REQUEST-CHANGES** — the plan needs reworking and a second opening pass before implementation starts.
49
+
50
+ ## Why it earns its tokens
51
+
52
+ It enforces a real rule — that a session's plan is graded against the standard before it is built,
53
+ by something that did not draft it. **The freshness is the mechanism and no host enforces it**: nothing
54
+ in a tool grant can observe whether this context already saw the plan being written. That makes it a
55
+ practice held by whoever spawns the checkpoint, which is why it is stated here rather than assumed.
56
+ A checkpoint that never changes a plan is a candidate for demotion; one that changes designs rather
57
+ than wording is doing the job.
@@ -0,0 +1,8 @@
1
+ # packs/stacks/
2
+
3
+ Stack packs — per-language and per-framework profiles (build/test commands, idioms, conventions)
4
+ that a workspace composes in.
5
+
6
+ > Placeholder. No stack pack exists yet, and none is scheduled: one becomes worth writing when a
7
+ > workspace declares a stack that needs it. This repository's own stack is deliberately too thin to
8
+ > justify one.
@@ -0,0 +1,17 @@
1
+ # packs/tools/
2
+
3
+ Tool packs — integrations for the tools and MCP servers an agent drives (issue trackers, cloud
4
+ CLIs, design tools, databases), with the how-to and the gate classification for each.
5
+
6
+ > **One tool pack exists** — [`github/`](github/README.md), since milestone 7 session 5. _(This read
7
+ > "No tool pack exists yet" until 2026-08-13, beside the directory that refutes it.)_ What changed at
8
+ > milestone 6 was the machinery rather
9
+ > than this directory. Milestone 4 built the thing that would read one — a gate policy in a
10
+ > host-neutral vocabulary, dispatched on by [`../../cli/compile.mjs`](../../cli/compile.mjs) — and the
11
+ > cascade's missing middle (`core < pack < workspace`) is now bridged: a pack's `contributes.gates`
12
+ > fragments are resolved and merged into the policy, **tighten-only**, by the same compiler.
13
+ >
14
+ > The first pack to use it is a *ritual* one ([`../rituals/checkpoints/`](../rituals/checkpoints/)), so
15
+ > the promise this file has carried since it was written — that a tool pack ships "with the gate
16
+ > classification for each" — is now buildable and still unbuilt. A tool pack becomes worth writing when
17
+ > a workspace here drives a tool that needs one.
@@ -0,0 +1,65 @@
1
+ # `tools/github` — GitHub Actions hygiene, as a composed verify recipe
2
+
3
+ A tool pack. It contributes **one verify recipe** to the workspace that composes it, and nothing else —
4
+ no skills, no personas, no gate fragments. Composed through a workspace's `packs` array as
5
+ `tools/github`.
6
+
7
+ | Contributes | What |
8
+ |---|---|
9
+ | Verify | [`actions-pinned`](verify/actions-pinned.sh) — every `uses:` in a GitHub Actions workflow is pinned to a full commit SHA ([limits](verify/README.md)) |
10
+
11
+ ## Why this pack exists, said plainly
12
+
13
+ It is the first pack in this project to ship a `contributes.verify` recipe, and it was built because
14
+ **milestone 7's D6 needed a subject**. Row 7 requires a demonstration that a composed recipe *runs from
15
+ the adopting workspace, is refused when it would shadow one the workspace owns, and is could-not-run
16
+ when it cannot resolve* — and the only pack that existed, [`rituals/checkpoints`](../../rituals/checkpoints/README.md),
17
+ declares no recipe **by argued policy**: it has nothing honest to put in that field, and reversing that
18
+ to serve a demonstration would have made an honest pack dishonest.
19
+
20
+ So the subject is a real pack with a real recipe rather than a fixture. That choice is deliberate and
21
+ this project has paid for the alternative: a check written to exercise your own change inherits your
22
+ change's blind spot, which is how a discovery draft found neither plugin its own feed shipped while the
23
+ suite stayed green.
24
+
25
+ **Its bound, so the row grows no unscheduled obligation:** one pack, one recipe, its documentation. No
26
+ marketplace entry, no feed publication, no second recipe, and nothing D6 does not exercise.
27
+
28
+ ## What the recipe checks — and the honest reason it earns its place
29
+
30
+ `uses: owner/action@<40-hex>` is pinned. A tag or a branch is not: the code that runs in the workflow
31
+ tomorrow is whatever the tag points at then, and a tag can be moved by whoever owns it.
32
+
33
+ **GitHub can already enforce this, and this repository has it enforced.** `sha_pinning_required` is set
34
+ at the organisation and at the repository, and the platform refuses an unpinned action outright — a
35
+ measured rail, recorded in this project's own gate map and platform-floor table. Saying so is not
36
+ optional: a pack claiming to be the only thing standing between an adopter and an unpinned action would
37
+ be claiming an enforcement it does not solely provide, which is the defect this repository has a memory
38
+ record about.
39
+
40
+ Two things the recipe buys anyway, and they are the reason it ships rather than an apology for it:
41
+
42
+ 1. **Tree-time versus run-time.** The platform refuses the action when the workflow *runs*. This refuses
43
+ it at the **pull request**, before merge. The gap is not theoretical for a scheduled workflow: an
44
+ unpinned `uses:` in a `schedule`-triggered job merges green on a Friday and fails at 06:00 on Monday,
45
+ with nobody watching.
46
+ 2. **Portability, which is the whole point of a pack.** An adopter who has not set the organisation
47
+ policy — or cannot, on a plan that does not offer it — gets this check as the *only* carrier. A pack
48
+ travels; a platform setting does not travel with it.
49
+
50
+ ## What it does not check
51
+
52
+ Named here rather than left to be discovered — see [`verify/README.md`](verify/README.md) for the full
53
+ list with reasons. In short: it reads one `uses:` per line and would not see a folded or flow-mapping
54
+ spelling; it exempts local (`./…`) and container (`docker://…`) references, which have no commit to pin;
55
+ and it does not verify that a pinned SHA is *reachable* in the action's repository, which would need a
56
+ network call — and a network call inside a verify recipe is a standing prohibition in this project, not
57
+ a decision this pack gets to make.
58
+
59
+ ## Provenance
60
+
61
+ Built for milestone 7, session 5, as D6's subject, on the maintainer's ruling of 2026-08-09 that the
62
+ demonstration take a real pack rather than a fixture or a reversal of another pack's refusal. The
63
+ composition contract it exercises — additive only, namespaced by pack, never the workspace's
64
+ `verify.default`, could-not-run rather than silently absent — is row 7's, ratified 2026-07-31, and is
65
+ carried in code by [`cli/recipe-set.mjs`](../../../cli/recipe-set.mjs).
@@ -0,0 +1,29 @@
1
+ {
2
+ "portulan": {
3
+ "pack": "1.0",
4
+ "version": "0.1.0"
5
+ },
6
+ "name": "github",
7
+ "category": "tools",
8
+ "summary": "GitHub Actions hygiene as a verify recipe: every `uses:` in a workflow is pinned to a full commit SHA, checked in the tree at pull-request time rather than trusted to a platform setting the adopter may not have.",
9
+ "doc": "README.md",
10
+ "contributes": {
11
+ "verify": [
12
+ {
13
+ "id": "actions-pinned",
14
+ "run": "bash ${PACK_ROOT}/verify/actions-pinned.sh",
15
+ "requires": [
16
+ "bash",
17
+ "find",
18
+ "grep",
19
+ "sed",
20
+ "sort",
21
+ "cut",
22
+ "wc",
23
+ "tr"
24
+ ],
25
+ "doc": "verify/README.md"
26
+ }
27
+ ]
28
+ }
29
+ }