@sleepy_panda_srl/portulan 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +18 -6
  2. package/cli/README.md +56 -4
  3. package/cli/advisory.mjs +167 -53
  4. package/cli/cache-risk.mjs +69 -0
  5. package/cli/comments.mjs +8 -5
  6. package/cli/compile.mjs +492 -146
  7. package/cli/context.mjs +204 -43
  8. package/cli/doctor.mjs +211 -33
  9. package/cli/drills.mjs +32 -7
  10. package/cli/finish.md +34 -0
  11. package/cli/finish.mjs +9 -67
  12. package/cli/form.mjs +35 -19
  13. package/cli/frontmatter.mjs +39 -0
  14. package/cli/gate.mjs +14 -12
  15. package/cli/guidance-files.mjs +335 -0
  16. package/cli/handoff-policy.mjs +76 -0
  17. package/cli/html-entities.mjs +2130 -0
  18. package/cli/import-files.mjs +15 -0
  19. package/cli/index.mjs +77 -24
  20. package/cli/init-preview.mjs +553 -0
  21. package/cli/init.mjs +261 -46
  22. package/cli/instructions-journal.mjs +1185 -0
  23. package/cli/instructions.mjs +332 -57
  24. package/cli/ledger.mjs +123 -37
  25. package/cli/librarian.mjs +103 -19
  26. package/cli/persona-routing.mjs +209 -0
  27. package/cli/plugin-lint.mjs +77 -56
  28. package/cli/portulan.mjs +7 -2
  29. package/cli/recipe-output.mjs +91 -0
  30. package/cli/recipe-runner.md +68 -0
  31. package/cli/recipe-runner.mjs +131 -0
  32. package/cli/recipe-set.mjs +12 -3
  33. package/cli/ritual-contexts.mjs +103 -0
  34. package/cli/sessions.mjs +2 -1
  35. package/cli/spend-analysis.mjs +111 -0
  36. package/cli/spend-offer.md +53 -0
  37. package/cli/spend-offer.mjs +93 -0
  38. package/cli/stop-diagnostics.mjs +114 -0
  39. package/cli/stop-gate.mjs +133 -90
  40. package/cli/stop-policy.mjs +14 -0
  41. package/cli/symbols.mjs +55 -8
  42. package/cli/telemetry.mjs +19 -12
  43. package/cli/upgrade.mjs +62 -44
  44. package/cli/vendor.mjs +210 -126
  45. package/core/operating/context.md +368 -60
  46. package/core/operating/evolution.md +3 -2
  47. package/core/operating/loop.md +9 -4
  48. package/core/operating/sessions.md +6 -15
  49. package/core/personas/README.md +52 -10
  50. package/core/personas/implementer.md +3 -0
  51. package/core/personas/librarian.md +3 -0
  52. package/core/personas/reviewer.md +3 -0
  53. package/core/templates/handoff.md +6 -2
  54. package/evals/ab/personas/README.md +111 -0
  55. package/evals/ab/personas/acquisition.json +330 -0
  56. package/evals/ab/personas/bindings/implementer.txt +43 -0
  57. package/evals/ab/personas/bindings/librarian.txt +40 -0
  58. package/evals/ab/personas/bindings/reviewer.txt +41 -0
  59. package/evals/ab/personas/corpus.json +69 -0
  60. package/evals/ab/personas/grader.mjs +171 -0
  61. package/evals/ab/personas/implementer.json +774 -0
  62. package/evals/ab/personas/implementer.md +22 -0
  63. package/evals/ab/personas/librarian.json +758 -0
  64. package/evals/ab/personas/librarian.md +22 -0
  65. package/evals/ab/personas/protocol/continuation.mjs.txt +284 -0
  66. package/evals/ab/personas/protocol/first-outcome.mjs.txt +227 -0
  67. package/evals/ab/personas/protocol/first-probe.mjs.txt +172 -0
  68. package/evals/ab/personas/protocol/publisher.mjs.txt +126 -0
  69. package/evals/ab/personas/protocol/second-probe.mjs.txt +193 -0
  70. package/evals/ab/personas/repairs/first-control-answer.txt +23 -0
  71. package/evals/ab/personas/repairs/grader-before-decode-repair.mjs.txt +143 -0
  72. package/evals/ab/personas/reviewer.json +758 -0
  73. package/evals/ab/personas/reviewer.md +22 -0
  74. package/evals/releases/0.4.0.json +154 -0
  75. package/evals/releases/0.4.0.md +69 -0
  76. package/evals/releases/0.4.1.json +154 -0
  77. package/evals/releases/0.4.1.md +69 -0
  78. package/package.json +6 -2
  79. package/packs/rituals/checkpoints/README.md +35 -0
  80. package/packs/rituals/checkpoints/pack.json +3 -2
  81. package/packs/tools/local-llm/README.md +46 -6
  82. package/packs/tools/local-llm/runner/local-llm.mjs +127 -13
  83. package/packs/tools/local-llm/skills/delegate-local/SKILL.md +26 -2
  84. package/spec/README.md +37 -4
  85. package/spec/migrations/0009-instruction-sections-on-read.mjs +60 -11
  86. package/spec/migrations/0011-persona-bindings-compiled.mjs +23 -0
  87. package/spec/migrations/README.md +6 -0
  88. package/spec/pack.schema.json +12 -3
  89. package/spec/slots.md +262 -117
  90. package/spec/workspace.schema.json +67 -11
package/README.md CHANGED
@@ -20,13 +20,13 @@ workspaces and premium packs delivered as private-marketplace plugins.
20
20
 
21
21
  ## Status
22
22
 
23
- **Current release: `0.3.0`** — recorded in [`CHANGELOG.md`](CHANGELOG.md), which is also the honest
23
+ **Current release: `0.4.1`** — recorded in [`CHANGELOG.md`](CHANGELOG.md), which is also the honest
24
24
  account of what the release does *not* contain.
25
25
 
26
26
  This is pre-release software. The leading `0.` is meant literally: nothing here is stable yet, and
27
27
  the surface may change between minor versions. What is authored today is the engine in [`core/`](core/),
28
28
  the Workspace Definition in [`spec/`](spec/), two complete workspaces, the CLI in [`cli/`](cli/) with
29
- all eight subcommands, the enforcement compiler, the memory lifecycle and the plugin packaging. The remaining directories
29
+ every subcommand, the enforcement compiler, the memory lifecycle and the plugin packaging. The remaining directories
30
30
  fill in milestone by milestone; [`docs/plan.md`](docs/plan.md) is the living map of that work.
31
31
 
32
32
  The repository is **public** — reading, cloning, forking and installing the plugin need no account of
@@ -100,7 +100,13 @@ node cli/doctor.mjs examples
100
100
 
101
101
  To adopt Portulan in your own repository, `portulan init` interviews you, scans the codebase and
102
102
  drafts a workspace; `portulan doctor` validates it; `portulan compile` turns your gate policy into
103
- host enforcement.
103
+ host enforcement. At a terminal, an in-repo draft offers an optional always-tier budget before writing.
104
+ The offer covers current and projected guidance in both supported formats at your explicit ratio.
105
+ Declining or an initially unavailable projection leaves it undeclared. After final confirmation,
106
+ init checks the accepted cap against fresh project inputs. An insufficient cap, a newly unavailable
107
+ measurement or a changed effective handoff cutoff stops before writing and asks you to run init again.
108
+ The cutoff uses eligible dated Markdown handoffs; unrelated filenames cannot advance it. Invalid
109
+ selected dates or file types, or an uninspectable series, stop record-cap adoption before writing.
104
110
 
105
111
  ## Command-line interface
106
112
 
@@ -119,14 +125,15 @@ commit, refusing any packed file that differs from its source.
119
125
  |---|---|
120
126
  | [`init`](cli/init.mjs) | Interview plus codebase scan, producing a drafted workspace |
121
127
  | [`doctor`](cli/doctor.mjs) | Validate a workspace against the Workspace Definition |
122
- | [`compile`](cli/compile.mjs) | Turn gates and verify recipes into host enforcement, and what a pack's persona declares about its context into the agent binding it is given, which Claude Code loads only at a plugin root |
128
+ | [`compile`](cli/compile.mjs) | Turn gates and verify recipes into host enforcement, guidance into host tiers, and declared persona fields into existing plugin or project agent bindings |
123
129
  | [`vendor`](cli/vendor.mjs) | Materialise a workspace where it is needed, in either direction |
124
130
  | [`index`](cli/index.mjs) | Rebuild the declared indexes over memory, handoffs and personas; print changelog fragments for a release |
125
131
  | [`upgrade`](cli/upgrade.mjs) | Migrate a workspace across Workspace Definition versions |
126
132
  | [`new`](cli/new.mjs) | Scaffold a skill, persona, pack, workspace, gate policy or repo card |
127
133
  | [`feedback`](cli/feedback.mjs) | File a bug, improvement or feedback issue you previewed first |
134
+ | [`finish`](cli/finish.mjs) | Close a change in one call: commit and push only when every verify recipe passes |
128
135
 
129
- Beside the eight sit tools that are deliberately not subcommands, and the compiled-hook runners, which
136
+ Beside these sit tools that are deliberately not subcommands, and the compiled-hook runners, which
130
137
  are not subcommands at all. [`cli/README.md`](cli/README.md), rendered from the code, lists that wider roster.
131
138
 
132
139
  ## Repository layout
@@ -138,7 +145,7 @@ are not subcommands at all. [`cli/README.md`](cli/README.md), rendered from the
138
145
  | `cli/` | [The Node CLI](cli/) described above, plus its tests and the compiled-hook runners |
139
146
  | `packs/` | [Composable packs](packs/) — `stacks/`, `tools/`, `rituals/` |
140
147
  | `plugin/` | [The Claude Code adapter](plugin/): the `/portulan` boot skill |
141
- | `agents/` | [The three personas bound to this host's tools](agents/) — `implementer`, `reviewer`, `librarian`. A platform-fixed location; the doctrine they bind stays in [`core/personas/`](core/personas/) |
148
+ | `agents/` | [Host bindings](agents/) for the core implementer, reviewer and librarian plus the composed supervisor and local-worker. Their charters stay in core or the contributing pack; ordinary projects bind roles under `.claude/agents/` |
142
149
  | `examples/` | [A fictional, public demo workspace](examples/) — two products, read end to end |
143
150
  | `docs/` | [`vision.md`](docs/vision.md) (the constitution), [`plan.md`](docs/plan.md) (the milestone map) and [`milestones/`](docs/milestones/) — one file per milestone from 12 on, holding amendment arguments, session notes and close evidence (milestones 0 to 11 read with `git show 8a33f9b:docs/milestones/mNN.md`) |
144
151
  | `evals/` | [The eval corpora](evals/) — golden tasks for the compiled gates and for the core skills — plus the review-loop register, the A/B corpus with its arms, graders and recorded baseline, and [`evals/releases/`](evals/releases/), the eval result each release from `0.1.3` onward carries. **No count is written here**; `git ls-files evals` derives it. _(This cell has now recorded going stale twice, and this is the second repair: it said the **graders** and the **baseline run** were *still to arrive* after both landed on 2026-08-31. The sentence that expires is always the one naming what is next, so this cell no longer names one — what is unbuilt lives in [`evals/README.md`](evals/README.md)'s own *What is NOT built yet*, which is the single carrier for it and is checked by nothing, exactly as this cell was.)_ |
@@ -173,3 +180,8 @@ channels in the order to try them, what is in scope, and what response you can a
173
180
  ## License
174
181
 
175
182
  [Apache-2.0](LICENSE) © 2026 Sleepy Panda SRL. See [`NOTICE`](NOTICE).
183
+
184
+ `portulan doctor --count-tokens MODEL_ID .portulan` optionally sends the measured project always corpus
185
+ to Anthropic for a provider token estimate, using `ANTHROPIC_API_KEY` from the environment. The
186
+ [counting boundary](core/operating/context.md#the-always-tier-is-budgeted-in-tokens) explains exclusions,
187
+ manual ratio assessment and why the estimate is not actual complete host usage. Verification remains offline.
package/cli/README.md CHANGED
@@ -29,6 +29,7 @@ in [`../.portulan/verify/`](../.portulan/verify/), and its operator tooling in
29
29
  | [`upgrade.mjs`](upgrade.mjs) | `portulan upgrade`: migrate a workspace: the Workspace Definition steps it owes, and the repairs a rewriter owes it. |
30
30
  | [`new.mjs`](new.mjs) | `portulan new`: scaffold a skill, persona, pack, workspace, gate policy or repo card from a core template. |
31
31
  | [`feedback.mjs`](feedback.mjs) | `portulan feedback`: file an issue from a report you previewed, seam-scanned before it leaves the machine. |
32
+ | [`finish.mjs`](finish.mjs) | `portulan finish`: close a change in one call, committing and pushing only when every verify recipe passes. |
32
33
 
33
34
  ### Hook runners
34
35
 
@@ -37,8 +38,8 @@ Run by the hooks `compile` writes into a host's settings, never by a person.
37
38
  | File | What it is |
38
39
  |---|---|
39
40
  | [`gate.mjs`](gate.mjs) | The PreToolUse gate runner — the *explanation* half of the enforcement compiler. |
40
- | [`stop-gate.mjs`](stop-gate.mjs) | The Stop-gate runner — "done" is not a thing an agent may simply declare. |
41
- | [`advisory.mjs`](advisory.mjs) | The restart advisory — one line, once, where the agent is, and the same figure for the human. |
41
+ | [`stop-gate.mjs`](stop-gate.mjs) | Stop-gate: bounded recipe and work checks. Hook failures need a verdict, since a crashed hook fails open. |
42
+ | [`advisory.mjs`](advisory.mjs) | Restart comparison with explicit horizon and resume expense; unknown recovery cost stays conditional. |
42
43
 
43
44
  ### Tools and modules
44
45
 
@@ -49,35 +50,53 @@ Run as `node cli/<file>.mjs`, or imported by the files above.
49
50
  | [`ab-grade.mjs`](ab-grade.mjs) | The A/B graders — what an arm's tree says it did, and the discrimination that proves a grader read it. Not shipped. |
50
51
  | [`ab-run.mjs`](ab-run.mjs) | The A/B runner: spawns the agent turns of both arms and records the baseline they measure. Not shipped. |
51
52
  | [`ab.mjs`](ab.mjs) | The A/B arm builder — what "Portulan on" is made of, built rather than described. Not shipped. |
53
+ | [`acquire-personas.mjs`](acquire-personas.mjs) | Acquire the frozen persona comparisons through native children; never run by a recipe. Not shipped. |
54
+ | [`cache-risk.mjs`](cache-risk.mjs) | Potential cache risks from project files; host activation is not inferred. |
55
+ | [`cache-stability.mjs`](cache-stability.mjs) | Prefix baseline. Not shipped. |
52
56
  | [`comments.mjs`](comments.mjs) | `comments` — the comments in a tree that record a change's history instead of what the code cannot show. |
53
- | [`context.mjs`](context.mjs) | What a context loads, measured: what a boot reads in full, and what the host loads into every context. |
57
+ | [`context.mjs`](context.mjs) | Measure boot reads and the project's always tier. |
54
58
  | [`control-chars.mjs`](control-chars.mjs) | `control-chars` — the rail on bytes a reader cannot see. |
55
59
  | [`discover.mjs`](discover.mjs) | Host plugin-cache discovery: reads a host's installed-plugin record to resolve a pointer and find pack roots. |
56
60
  | [`drills.mjs`](drills.mjs) | The forced-red drill harness — every rail broken on purpose, and required to fire. |
57
61
  | [`eval-bundle.mjs`](eval-bundle.mjs) | Cut a named-recipient evaluation bundle of Portulan from a commit. Not shipped. |
58
- | [`finish.mjs`](finish.mjs) | The finishing command — one call closes a change: its recipes, its changelog fragment, its commit, its push. |
59
62
  | [`form.mjs`](form.mjs) | `form` — which form a consumer's records and boot are in, and the files that move them to the new one. |
63
+ | [`frontmatter.mjs`](frontmatter.mjs) | Flat frontmatter for plugin components and host bindings. |
60
64
  | [`fuzz-shell.mjs`](fuzz-shell.mjs) | Grammar-aware fuzzing over this repository's two shell segmenters. |
61
65
  | [`goldens.mjs`](goldens.mjs) | Grade this workspace's compiled gates against a corpus of adversarial fixtures. |
66
+ | [`guidance-files.mjs`](guidance-files.mjs) | Nested instruction ownership and atomic guidance publication. |
67
+ | [`handoff-policy.mjs`](handoff-policy.mjs) | Handoff caps and windows. |
68
+ | [`html-entities.mjs`](html-entities.mjs) | HTML5 named references (semicolon forms): https://html.spec.whatwg.org/entities.json Generated from Python 3 html.entities.html5. |
69
+ | [`import-files.mjs`](import-files.mjs) | Optional project import probes. |
70
+ | [`init-preview.mjs`](init-preview.mjs) | Project guidance preview, shared by init and instruction migration. |
62
71
  | [`inside.mjs`](inside.mjs) | Is one path inside another? One predicate, one file, no dependencies. |
72
+ | [`instructions-journal.mjs`](instructions-journal.mjs) | One CLI split/join, bounded to its original sources. The planner proves the saved operation again. Immutable lease children serialize recovery without deleting a possibly live writer's lock. Terminal proof outlives rollback authority; unproved initialization remains for human review. |
63
73
  | [`instructions.mjs`](instructions.mjs) | `instructions` — the sections a team marks in its own instruction file, moved to on-read units and proved. |
64
74
  | [`ledger.mjs`](ledger.mjs) | What a change spends, measured from the host's own usage records. |
65
75
  | [`librarian.mjs`](librarian.mjs) | `librarian` — the scheduled pass over the curated layer: reindex, staleness, nags, demotion drafts. |
66
76
  | [`local-routing.mjs`](local-routing.mjs) | Verify the shipped operational local roles against their immutable acquired A/B record. No model. Not shipped. |
67
77
  | [`manifest.mjs`](manifest.mjs) | The two facts every tool here needs out of `package.json`, read once and in a module that imports nothing of ours. |
68
78
  | [`mutants.mjs`](mutants.mjs) | Mutation-test this repository's two gate matchers against the corpus that claims to cover them. |
79
+ | [`normalize-personas.mjs`](normalize-personas.mjs) | Publish whitelisted numeric metadata and generic answers from the completed private persona acquisition. Not shipped. |
69
80
  | [`pack-identity.mjs`](pack-identity.mjs) | Every file `npm pack` emits is byte-identical to the tracked blob it came from. |
70
81
  | [`pack-version.mjs`](pack-version.mjs) | A change to a pack's `contributes` must move that pack's `portulan.version`. |
71
82
  | [`payload.mjs`](payload.mjs) | Every `cli/*.mjs` the npm payload carries is classified, and nothing arrives in it unclassified. Not shipped. |
83
+ | [`persona-routing.mjs`](persona-routing.mjs) | Regrade the acquired core-persona records and check their shipped routing without a model. |
72
84
  | [`plugin-lint.mjs`](plugin-lint.mjs) | `plugin-lint` — the packaging validator. |
85
+ | [`recipe-output.mjs`](recipe-output.mjs) | Agent output for any recipe: one green count, complete failure streams. |
86
+ | [`recipe-runner.mjs`](recipe-runner.mjs) | Shared asynchronous recipe execution, bounded output and process-tree cleanup. |
73
87
  | [`recipe-set.mjs`](recipe-set.mjs) | The recipe set: the verify recipes a workspace yields, its own plus each composed pack's, namespaced by pack. |
74
88
  | [`release-eval.mjs`](release-eval.mjs) | Portulan — the eval result a release carries. |
75
89
  | [`review-meter.mjs`](review-meter.mjs) | The review-loop meter: the historical figures of this repository's Copilot review loop, derived from its reviews. |
90
+ | [`ritual-contexts.mjs`](ritual-contexts.mjs) | Own native settings without inventing a gate policy. |
76
91
  | [`roster.mjs`](roster.mjs) | The cli roster: `cli/README.md`, rendered from the files it lists and never edited by hand. Not shipped. |
77
92
  | [`rule-carriers.mjs`](rule-carriers.mjs) | `rule-carriers` — the rail that keeps a reduced rule reduced. |
78
93
  | [`sessions.mjs`](sessions.mjs) | The session switches' texts: the cache-lifetime offer `init` and `upgrade` print, and the one line `doctor` reports on them. |
79
94
  | [`skill-goldens.mjs`](skill-goldens.mjs) | The core-skill golden corpus — every mandate a core skill states, bound to the live artifacts it governs, and graded. |
80
95
  | [`skills-set.mjs`](skills-set.mjs) | The registrable set: the `skills` paths a plugin manifest must declare so a composed pack's skills register. |
96
+ | [`spend-analysis.mjs`](spend-analysis.mjs) | Class indices compare stated assumptions, never bills or route quality. |
97
+ | [`spend-offer.mjs`](spend-offer.mjs) | Local evidence for init's optional spend declaration. |
98
+ | [`stop-diagnostics.mjs`](stop-diagnostics.mjs) | Bounded streaming failure excerpts for the Stop recipe relay. |
99
+ | [`stop-policy.mjs`](stop-policy.mjs) | Stop recipe deadline policy. |
81
100
  | [`symbols.mjs`](symbols.mjs) | A code file's outline, one line per symbol, and a Markdown file's, one line per heading with its size. |
82
101
  | [`telemetry.mjs`](telemetry.mjs) | The OTel emitter: the review-loop figures as OTLP/HTTP JSON, sent only when a committed config opts in. |
83
102
  | [`version-carriers.mjs`](version-carriers.mjs) | Every prose statement of the current version agrees with `package.json`. |
@@ -92,16 +111,26 @@ Node's own runner: `node --test "cli/**/*.test.mjs"`, which the `tests` recipe r
92
111
  | [`ab-grade.test.mjs`](ab-grade.test.mjs) | Tests for `ab-grade` — the A/B graders: staging, attribution, the four scenarios, the two levels and the register. |
93
112
  | [`ab-run.test.mjs`](ab-run.test.mjs) | Tests for `ab-run` — the A/B runner: isolation, the matrix, the journal, the register and the checks behind it. |
94
113
  | [`ab.test.mjs`](ab.test.mjs) | Tests for `ab` — the A/B arm builder: its disposition table, rule-2 matcher, nonces, isolation and stop probe. |
114
+ | [`advisory-crossing.test.mjs`](advisory-crossing.test.mjs) | First recorded crossings survive delayed batches without stale Stop holds. |
115
+ | [`advisory-dedup.test.mjs`](advisory-dedup.test.mjs) | Delayed repeats cannot replace the latest distinct request. |
116
+ | [`advisory-host-trace.test.mjs`](advisory-host-trace.test.mjs) | The shipped host trace is evidence data; CI only replays its public counters. |
95
117
  | [`advisory.test.mjs`](advisory.test.mjs) | Tests for `advisory` — the restart advisory's one line with a tool result or at the prompt, and its figure in the status line. |
96
118
  | [`branch-freshness.test.mjs`](branch-freshness.test.mjs) | Tests for this repository's branch freshness check and trusted workflow. |
119
+ | [`cache-inputs.test.mjs`](cache-inputs.test.mjs) | Missing cache inputs stay unpriced in reports and hooks. |
120
+ | [`cache-risk.test.mjs`](cache-risk.test.mjs) | Project cache warnings are reports; no host state or server is consulted. |
121
+ | [`cache-stability.test.mjs`](cache-stability.test.mjs) | Cache-prefix tests. |
97
122
  | [`checkout-refs.live.test.mjs`](checkout-refs.live.test.mjs) | A workflow that checks out MORE THAN ONCE names the ref of every checkout after the first. |
98
123
  | [`cli-roster.live.test.mjs`](cli-roster.live.test.mjs) | `cli/README.md` is exactly what ./roster.mjs renders from this directory, and the render keeps its shape. |
99
124
  | [`collisions.test.mjs`](collisions.test.mjs) | The collision contract: `init`, `new` and `vendor` answer each contracted state alike, and no fourth `collisions` exists. |
100
125
  | [`comments.test.mjs`](comments.test.mjs) | Tests for `comments`: each language's comments found exactly, and the four kinds of history told from the rest. |
101
126
  | [`compile.test.mjs`](compile.test.mjs) | Tests for `compile` — the enforcement compiler. |
127
+ | [`context-count.test.mjs`](context-count.test.mjs) | On-demand provider counts preserve the measured corpus and remain outside offline verification. |
128
+ | [`context-hosts.test.mjs`](context-hosts.test.mjs) | Independent project context measurements for the two guidance formats. |
102
129
  | [`context.test.mjs`](context.test.mjs) | Tests for `context` — what a boot reads and what the host loads into every context, measured. |
103
130
  | [`control-chars.test.mjs`](control-chars.test.mjs) | Tests for `control-chars` — the rail on bytes a reader cannot see. |
131
+ | [`demo-upgrade.test.mjs`](demo-upgrade.test.mjs) | The demo's pinned bundle replacement reproduces its boot reduction without changing its workspace. |
104
132
  | [`discover.test.mjs`](discover.test.mjs) | Tests for host plugin-cache discovery. |
133
+ | [`doctor-lever.test.mjs`](doctor-lever.test.mjs) | Tests for doctor's savings lever. |
105
134
  | [`doctor.test.mjs`](doctor.test.mjs) | Tests for `doctor` — workspace validation, branch-owned hybrid usage and static-mode isolation. |
106
135
  | [`drills.test.mjs`](drills.test.mjs) | Tests for `drills` — the forced-red drill harness: its table, perturbation guards, pair oracle, hook rails and tree choice. |
107
136
  | [`eval-bundle.test.mjs`](eval-bundle.test.mjs) | The evaluation-bundle cutter, driven on this repository AND on real fixture repositories. |
@@ -114,25 +143,42 @@ Node's own runner: `node --test "cli/**/*.test.mjs"`, which the `tests` recipe r
114
143
  | [`gate.test.mjs`](gate.test.mjs) | The PreToolUse gate runner, driven as the host drives it. |
115
144
  | [`gh-bot.test.mjs`](gh-bot.test.mjs) | The agent identity's wrapper refuses the endpoints it is not for. |
116
145
  | [`goldens.test.mjs`](goldens.test.mjs) | Tests for `goldens` — the gate-corpus rail: the exemption, both rails, every corpus refusal and the CLI. |
146
+ | [`handoff-budget.test.mjs`](handoff-budget.test.mjs) | Handoff budget tests. |
117
147
  | [`index.test.mjs`](index.test.mjs) | Tests for `index` — the memory, handoff and scope indexes, the memory budgets, and changelog fragments. |
148
+ | [`init-budget.test.mjs`](init-budget.test.mjs) | The init interview's declared always-tier choice. |
118
149
  | [`init.test.mjs`](init.test.mjs) | Tests for `init` — the onboarding subcommand that drafts a workspace for a repository that has none. |
150
+ | [`instructions-journal.test.mjs`](instructions-journal.test.mjs) | Process interruption and ownership controls for CLI instruction migration. |
119
151
  | [`instructions.test.mjs`](instructions.test.mjs) | Tests for `instructions`: the sections a team marks, moved to on-read units and proved, and the join back. |
120
152
  | [`ledger.test.mjs`](ledger.test.mjs) | Tests for `ledger` — what a change spends, from the host's own usage records. |
121
153
  | [`librarian.test.mjs`](librarian.test.mjs) | Tests for `librarian` — the scheduled pass over the curated layer. |
122
154
  | [`list-quoting.live.test.mjs`](list-quoting.live.test.mjs) | Every recipe that enumerates the tree reads the pathname git actually carries. |
155
+ | [`local-completion.test.mjs`](local-completion.test.mjs) | Local completion and fenced-code regression tests. |
156
+ | [`local-transport.test.mjs`](local-transport.test.mjs) | Local HTTP deadlines, response bounds and compatibility tests. |
157
+ | [`local-usage.test.mjs`](local-usage.test.mjs) | Usage, exhaustion and rollback tests. |
123
158
  | [`mutants.test.mjs`](mutants.test.mjs) | Tests for `mutants`, the mutation-census rail: its operator table, its imports, its corpus and its refusals. |
159
+ | [`nested-instructions.test.mjs`](nested-instructions.test.mjs) | Nested guidance generation, ownership recovery and consumer parity. |
124
160
  | [`new.test.mjs`](new.test.mjs) | Tests for `new`: scaffolds that validate, written into the user's own layer and never into `core/`. |
125
161
  | [`pack-identity.test.mjs`](pack-identity.test.mjs) | Tests for the byte-identity rail: green, both findings and could-not-run, each exercised. |
126
162
  | [`pack-local-llm.test.mjs`](pack-local-llm.test.mjs) | Tests for the `tools/local-llm` pack's runner — its loopback, input-budget and rollback rails, its eval screen, dedup ranking and A/B record. |
127
163
  | [`pack-version.test.mjs`](pack-version.test.mjs) | The pack-version rail, driven on REAL git repositories rather than an injected history. |
128
164
  | [`payload.test.mjs`](payload.test.mjs) | Tests for the payload-classification rail. |
165
+ | [`persona-acquisition.test.mjs`](persona-acquisition.test.mjs) | Check native invocation and no-resampling guards. |
166
+ | [`persona-capture.test.mjs`](persona-capture.test.mjs) | Force acquired persona, routing and packaging rails red. |
167
+ | [`persona-routing.test.mjs`](persona-routing.test.mjs) | Semantic controls for the acquired core-persona routing comparisons. |
168
+ | [`persona-upgrade.test.mjs`](persona-upgrade.test.mjs) | Exercise historical persona upgrade, ownership and rollback. |
129
169
  | [`pinned-roots.live.test.mjs`](pinned-roots.live.test.mjs) | Required checks name their resolution root, and every suite whose imports reach the host's plugin record empties it. |
130
170
  | [`plugin-lint.test.mjs`](plugin-lint.test.mjs) | Tests for `plugin-lint` — the packaging validator. |
171
+ | [`policyfree-advisory.test.mjs`](policyfree-advisory.test.mjs) | Full compilation wires advice independently of gate policy. |
131
172
  | [`portulan.test.mjs`](portulan.test.mjs) | Tests for the `npx` entry point: dispatch through an injected loader, its refusals, and its version. |
173
+ | [`prompt-footprint.test.mjs`](prompt-footprint.test.mjs) | Owned prompt footprint regression checks. |
174
+ | [`recipe-output.test.mjs`](recipe-output.test.mjs) | Agent recipe output controls. |
175
+ | [`recipe-runner.test.mjs`](recipe-runner.test.mjs) | Recipe cleanup controls use isolated, test-owned process groups and late filesystem writes. |
132
176
  | [`recipe-set.live.test.mjs`](recipe-set.live.test.mjs) | The composed recipe set, against THIS repository rather than against fixtures. |
133
177
  | [`recipe-set.test.mjs`](recipe-set.test.mjs) | The recipe set — one carrier, and every reader reaches it. |
134
178
  | [`release-eval.test.mjs`](release-eval.test.mjs) | The release-eval suite, on the record layer only: `--capture` spawns every other rail, the tests that run this suite included. |
179
+ | [`restart-resume.test.mjs`](restart-resume.test.mjs) | Bounded-run restart comparisons, recovery expense, profitability and Stop refusal controls. |
135
180
  | [`review-meter.test.mjs`](review-meter.test.mjs) | Tests for `review-meter` — the review-loop meter: arithmetic, snapshot contract, register rail, window and shaping. |
181
+ | [`ritual-contexts.test.mjs`](ritual-contexts.test.mjs) | Ritual admission caps and total observed contexts have different units. |
136
182
  | [`rule-carriers.test.mjs`](rule-carriers.test.mjs) | Tests for `rule-carriers` — the rail that keeps a reduced rule reduced. |
137
183
  | [`sessions.test.mjs`](sessions.test.mjs) | `sessions` — the cache lifetime's offer, and `doctor`'s one line on the session switches. |
138
184
  | [`shadowed-pack.test.mjs`](shadowed-pack.test.mjs) | A shadowed pack is refused rather than picked. |
@@ -140,6 +186,9 @@ Node's own runner: `node --test "cli/**/*.test.mjs"`, which the `tests` recipe r
140
186
  | [`skill-goldens.test.mjs`](skill-goldens.test.mjs) | Tests for `skill-goldens`, the core-skill golden corpus: every refusal exercised on a fixture that trips it. |
141
187
  | [`skills-set.live.test.mjs`](skills-set.live.test.mjs) | The registrable set, against THIS repository rather than against fixtures. |
142
188
  | [`skills-set.test.mjs`](skills-set.test.mjs) | The registrable set — what a plugin manifest must declare so a composed pack's skills register. |
189
+ | [`spend-analysis.test.mjs`](spend-analysis.test.mjs) | Numeric class analysis keeps ownership, recency and unknown metadata explicit. |
190
+ | [`spend-offer.test.mjs`](spend-offer.test.mjs) | Init spend offers. |
191
+ | [`stop-diagnostics.test.mjs`](stop-diagnostics.test.mjs) | Stop recipe diagnostics retain failures across noise and stream boundaries. |
143
192
  | [`stop-gate.test.mjs`](stop-gate.test.mjs) | Tests for the Stop-gate runner: its per-reason caps, the handoff date, its verdicts, the did-work signals and the tree it answers about. |
144
193
  | [`symbols.live.test.mjs`](symbols.live.test.mjs) | `symbols` against this repository: tracked code and Markdown files outline, each declaration compiles alone, and heading links land. |
145
194
  | [`symbols.test.mjs`](symbols.test.mjs) | The outline's contract, on fixtures: what each construct prints, and every refusal. |
@@ -159,4 +208,7 @@ What the tools and suites read.
159
208
  | File | What it is |
160
209
  |---|---|
161
210
  | [`eval-license.template.md`](eval-license.template.md) | Portulan Evaluation Issue (`EVAL-LICENSE.md`). Not shipped. |
211
+ | [`finish.md`](finish.md) | Finish verification boundaries |
212
+ | [`recipe-runner.md`](recipe-runner.md) | Recipe execution and cleanup |
213
+ | [`spend-offer.md`](spend-offer.md) | Init's spend offer |
162
214
  | [`fixtures/`](fixtures/) | The fixtures the suites build on; each suite names the ones it reads. Not shipped. |