@sleepy_panda_srl/portulan 0.2.0 → 0.4.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 (100) hide show
  1. package/README.md +15 -4
  2. package/cli/README.md +61 -6
  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 +781 -130
  7. package/cli/context.mjs +204 -43
  8. package/cli/doctor.mjs +248 -31
  9. package/cli/drills.mjs +56 -9
  10. package/cli/finish.md +34 -0
  11. package/cli/finish.mjs +8 -67
  12. package/cli/form.mjs +34 -18
  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 +230 -40
  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 +1 -1
  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/review-meter.mjs +14 -9
  34. package/cli/ritual-contexts.mjs +103 -0
  35. package/cli/sessions.mjs +2 -1
  36. package/cli/spend-analysis.mjs +111 -0
  37. package/cli/spend-offer.md +53 -0
  38. package/cli/spend-offer.mjs +93 -0
  39. package/cli/stop-diagnostics.mjs +114 -0
  40. package/cli/stop-gate.mjs +133 -90
  41. package/cli/stop-policy.mjs +14 -0
  42. package/cli/symbols.mjs +55 -8
  43. package/cli/telemetry.mjs +66 -17
  44. package/cli/upgrade.mjs +62 -44
  45. package/cli/vendor.mjs +207 -125
  46. package/core/operating/context.md +401 -18
  47. package/core/operating/evolution.md +3 -2
  48. package/core/operating/loop.md +9 -4
  49. package/core/operating/sessions.md +6 -15
  50. package/core/personas/README.md +75 -0
  51. package/core/personas/implementer.md +3 -0
  52. package/core/personas/librarian.md +3 -0
  53. package/core/personas/reviewer.md +3 -0
  54. package/core/skills/clarify/SKILL.md +1 -1
  55. package/core/skills/consolidate/SKILL.md +1 -1
  56. package/core/templates/handoff.md +6 -2
  57. package/evals/README.md +23 -7
  58. package/evals/ab/personas/README.md +111 -0
  59. package/evals/ab/personas/acquisition.json +330 -0
  60. package/evals/ab/personas/bindings/implementer.txt +43 -0
  61. package/evals/ab/personas/bindings/librarian.txt +40 -0
  62. package/evals/ab/personas/bindings/reviewer.txt +41 -0
  63. package/evals/ab/personas/corpus.json +69 -0
  64. package/evals/ab/personas/grader.mjs +171 -0
  65. package/evals/ab/personas/implementer.json +774 -0
  66. package/evals/ab/personas/implementer.md +22 -0
  67. package/evals/ab/personas/librarian.json +758 -0
  68. package/evals/ab/personas/librarian.md +22 -0
  69. package/evals/ab/personas/protocol/continuation.mjs.txt +284 -0
  70. package/evals/ab/personas/protocol/first-outcome.mjs.txt +227 -0
  71. package/evals/ab/personas/protocol/first-probe.mjs.txt +172 -0
  72. package/evals/ab/personas/protocol/publisher.mjs.txt +126 -0
  73. package/evals/ab/personas/protocol/second-probe.mjs.txt +193 -0
  74. package/evals/ab/personas/repairs/first-control-answer.txt +23 -0
  75. package/evals/ab/personas/repairs/grader-before-decode-repair.mjs.txt +143 -0
  76. package/evals/ab/personas/reviewer.json +758 -0
  77. package/evals/ab/personas/reviewer.md +22 -0
  78. package/evals/releases/0.3.0.json +150 -0
  79. package/evals/releases/0.3.0.md +68 -0
  80. package/evals/releases/0.4.0.json +154 -0
  81. package/evals/releases/0.4.0.md +69 -0
  82. package/package.json +7 -2
  83. package/packs/.claude-plugin/plugin.json +2 -1
  84. package/packs/README.md +7 -4
  85. package/packs/rituals/checkpoints/README.md +35 -0
  86. package/packs/rituals/checkpoints/pack.json +3 -2
  87. package/packs/tools/README.md +8 -8
  88. package/packs/tools/local-llm/README.md +176 -0
  89. package/packs/tools/local-llm/pack.json +32 -0
  90. package/packs/tools/local-llm/personas/local-worker.md +44 -0
  91. package/packs/tools/local-llm/runner/local-llm.mjs +1779 -0
  92. package/packs/tools/local-llm/skills/delegate-local/SKILL.md +88 -0
  93. package/packs/tools/local-llm/verify/README.md +18 -0
  94. package/spec/README.md +37 -3
  95. package/spec/migrations/0009-instruction-sections-on-read.mjs +60 -11
  96. package/spec/migrations/0011-persona-bindings-compiled.mjs +23 -0
  97. package/spec/migrations/README.md +6 -0
  98. package/spec/pack.schema.json +12 -3
  99. package/spec/slots.md +272 -123
  100. package/spec/workspace.schema.json +67 -11
@@ -21,6 +21,81 @@ context firewalls; Cognition — read-parallel / write-isolated.)_
21
21
  - **Read / write posture** — most personas read in parallel; writes are isolated to one place so two
22
22
  agents never clobber the same file.
23
23
 
24
+ ## What a persona may declare about its context
25
+
26
+ Four optional frontmatter fields say what a fresh context for the role should cost, per
27
+ [`../operating/context.md`](../operating/context.md): `model`, one model name or alias as a single
28
+ token; `effort`, one of `low`, `medium`, `high`, `xhigh` or `max`; `omitClaudeMd`, `true` or `false`
29
+ unquoted, whether the role runs without the project's instruction files; and `cacheLifetime`, `5m` or
30
+ `1h`. The effort levels and the name `omitClaudeMd` are adopted from Claude Code's vocabulary, the first
31
+ host to express them. `effort` sets the host subagent's reasoning effort, and is not the thinking cap the
32
+ `tools/local-llm` runner's `--effort` sends with each request it makes. `doctor` fails malformed values
33
+ in composed pack personas; `compile` validates every persona source it compiles. Neither supplies a value
34
+ the persona did not write. `compile` writes declared fields from composed pack personas into the
35
+ frontmatter of the role's existing host binding: `agents/<name>.md` in a plugin tree and
36
+ `.claude/agents/<name>.md` in an ordinary project. Compiler and doctor share that selection; a malformed,
37
+ unreadable or escaping plugin marker is not treated as an ordinary project. When
38
+ the declared tree resolves to this compiler's own engine root, including a canonical alias, the same
39
+ pipeline also reads `core/personas/*.md` except this README. A foreign tree's matching files do not
40
+ participate. A core source's declared name must match its filename. The compiler leaves every other line of
41
+ that file as its author wrote it; `--check` byte-compares the result, and a line inside the compiled
42
+ block that `compile` did not write is refused rather than removed. One it cannot catch: a line added inside
43
+ the block in exactly the spelling and order `compile` writes reads as compiled, and is dropped once the
44
+ persona no longer declares that field, since the two cannot be told apart. And once a persona declares any
45
+ field, `compile` owns every top-level key it could write, so a hand-written `experimental:` is refused
46
+ even for a key other than `cacheTtl`. A field a host cannot express is
47
+ named, with the persona and the host, in the degradation report `compile` prints. Claude Code takes all
48
+ four on an agent (`cacheLifetime` as `experimental.cacheTtl`), and a vendored `AGENTS.md` takes none.
49
+ `compile` writes only existing bindings; an absent adopter binding remains unbound and is never
50
+ created by compilation. A persona-only workspace can compile its declared fields without a gate
51
+ policy or guidance. Nonregular, escaping and invalid UTF-8 inputs are refused before writes.
52
+ Doctor checks the selected binding's name and declared tool grant, keeping an unread file distinct
53
+ from an absent one. Plugin packaging checks core and actually composed charter owners in both
54
+ directions, including personas declaring no context fields. File equality proves neither plugin
55
+ enablement nor that a running host honored a field. _(Provenance:
56
+ proposal `0036`'s order of work, item 7, and proposal `0039`'s first two rules. The host's keys, values
57
+ and agent locations were read in Claude Code 2.1.317's program text on 2026-11-03.)_
58
+
59
+ This product binds both composed roles. Supervisor still requires a fresh invocation for a checkpoint.
60
+ Local-worker's host wrapper points to its existing loopback runner; loading that role does not itself
61
+ invoke a local model or prove local execution.
62
+
63
+ The three core sources explicitly declare `model: inherit`, `omitClaudeMd: false` and
64
+ `cacheLifetime: 5m`, leaving effort undeclared. These are product-role policy choices: inherit the
65
+ parent model, retain the instruction floor and request a five-minute cache lifetime. In Claude Code,
66
+ explicit `inherit` outranks the ordinary `CLAUDE_CODE_SUBAGENT_MODEL` default; an invocation's model
67
+ selection and `CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1` can override it. Cache lifetime remains subject to
68
+ the host's precedence rules. Compilation proves the committed bytes, with no claim about quality,
69
+ savings or live loading. _(Host precedence checked against the
70
+ [official subagent documentation](https://code.claude.com/docs/en/sub-agents) on 2026-11-09.)_
71
+
72
+ The acquired [implementer](../../evals/ab/personas/implementer.md),
73
+ [reviewer](../../evals/ab/personas/reviewer.md) and
74
+ [librarian](../../evals/ab/personas/librarian.md) comparisons each have three
75
+ frozen artifact cases, one attempt per arm, through native children on Sonnet 5.5
76
+ in Claude Code 2.1.321. Both arms pass all nine cases. Medium has a lower
77
+ cold-normalized cost index in this observation; observed cache costs differ,
78
+ and the reviewer arm's observed cost rises. These results support the retained
79
+ policy on that corpus and model, with no global medium default earned for other
80
+ inherited models. The [protocol](../../evals/ab/personas/README.md) discloses the
81
+ small sample, both probes, full parent/child usage and one retained-answer
82
+ decoder repair after the first outcome. The shipped offline checker regrades
83
+ the records and checks routing and source bytes.
84
+
85
+ A binding has one persona owner across core and composed pack sources, including an unbound persona or one declaring
86
+ no fields; duplicate destinations are refused before any artifact is written. The binding must be a
87
+ regular file whose real path stays in the real declared tree, including its parent directories.
88
+ `omitClaudeMd` accepts only unquoted `true` or `false`, in both declarations and compiled blocks.
89
+
90
+ `upgrade` refreshes existing eligible bindings through the same compiler planner,
91
+ including normal host-cache pack discovery and its shadow refusals. It preserves
92
+ unrelated binding text and modes, creates no absent binding, and writes no gate
93
+ settings. Core sources still participate only in the installed engine's own
94
+ declared tree; an ordinary adopter receives the baked core agents by updating the
95
+ plugin, without installing a foreign core adapter. The command-level historical
96
+ v0.2.0 demonstration is in
97
+ [`../../cli/persona-upgrade.test.mjs`](../../cli/persona-upgrade.test.mjs).
98
+
24
99
  ## Status
25
100
 
26
101
  **Milestone 3 — contract, exemplars, and one host binding.** This README fixes the persona contract; the
@@ -2,6 +2,9 @@
2
2
  name: implementer
3
3
  description: The default working persona. Takes one task through the full loop — research → plan → implement → verify → learn — and hands back a verified change plus what it learned. Delegate a unit of implementation work to it.
4
4
  tools: [read, search, edit-code, run-verify, draft-memory, open-pr]
5
+ model: inherit
6
+ omitClaudeMd: false
7
+ cacheLifetime: 5m
5
8
  ---
6
9
 
7
10
  # Persona — Implementer
@@ -2,6 +2,9 @@
2
2
  name: librarian
3
3
  description: The persona that tends the curated layer — consolidating memory, regenerating the size-budgeted index, drafting rule-change proposals from incidents and PR reviews, and chasing stale rules toward retirement. It drafts and files; it never accepts. Delegate a memory/evolution housekeeping pass to it.
4
4
  tools: [read, search, read-history, draft-memory, draft-proposal, write-index, open-pr]
5
+ model: inherit
6
+ omitClaudeMd: false
7
+ cacheLifetime: 5m
5
8
  ---
6
9
 
7
10
  # Persona — Librarian
@@ -2,6 +2,9 @@
2
2
  name: reviewer
3
3
  description: The last-mile check on a change before it merges. Reads a proposed diff against the task's acceptance criteria and the definition of done, re-runs the verify recipe, and returns a verdict — it does not edit the code or merge. Delegate review of a completed change to it.
4
4
  tools: [read, search, run-verify, post-review]
5
+ model: inherit
6
+ omitClaudeMd: false
7
+ cacheLifetime: 5m
5
8
  ---
6
9
 
7
10
  # Persona — Reviewer
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: clarify
3
- description: Run a bounded clarification pass before planning a full-lane task whose intent is ambiguous or whose acceptance criteria are not yet testable. Use when the ask is underspecified, the constraints conflict, or the criteria can't be written as observable checks — surface the smallest set of decision-questions, get human answers, and fold them into EARS-shaped acceptance criteria before any code is planned.
3
+ description: Run a bounded clarification pass before planning a full-lane task. Use when the ask is underspecified, the constraints conflict, or the criteria can't be written as observable checks — surface the smallest set of decision-questions, get human answers, and fold them into EARS-shaped acceptance criteria before any code is planned.
4
4
  ---
5
5
 
6
6
  # Skill — Clarify
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: consolidate
3
- description: Bring a memory store back under its budget by merging, compressing, splitting, and retiring records — the repair a breached memory budget calls for. Use when the index verify recipe reports a breach, or on the librarian's scheduled pass. The output is drafts through the human gate; raising the budget is not one of the moves.
3
+ description: Bring a memory store back under its budget by merging, compressing, splitting, and retiring records. Use when the index verify recipe reports a breach, or on the librarian's scheduled pass. The output is drafts through the human gate; raising the budget is not one of the moves.
4
4
  ---
5
5
 
6
6
  # Skill — Consolidate
@@ -10,12 +10,16 @@
10
10
  > decisions and their rationale. When one is owed, and why the commit carries the rest:
11
11
  > `../operating/loop.md`.)_
12
12
  >
13
+ > Link the records that own measured figures and durable rules. Keep each open decision and its why.
14
+ > A declared token cap binds new handoffs; compress or move and link facts, never split or drop a why.
15
+ > The heading names the outcome; the filename already carries the date. See `../operating/context.md`.
16
+ >
13
17
  > **The commit a change lands in:** a subject that says what changed, in the present tense and under 72
14
18
  > characters; a blank line; a body of a few lines that says why, and what was rejected when that matters.
15
19
 
16
20
  ---
17
21
 
18
- # Handoff — {task / thread}
22
+ # {outcome / open task}
19
23
 
20
24
  **State.** {where things stand: what is done and committed, what is in progress and uncommitted.}
21
25
 
@@ -30,7 +34,7 @@
30
34
 
31
35
  _A filled one, for a session that stopped mid-change:_
32
36
 
33
- # Handoff — retry the flaky upload test
37
+ # Retry the flaky upload test
34
38
 
35
39
  **State.** The retry wrapper is written and its unit test passes; it is stashed, not committed, because
36
40
  the integration suite still fails once in about ten runs.
package/evals/README.md CHANGED
@@ -122,6 +122,9 @@ node cli/review-meter.mjs --fetch --repo <owner/name> --out <file> the on
122
122
  with `--register evals/review-loop/register.md --write` regenerates it, and the recipe byte-compares it.
123
123
  The criterion's *"rounds per pull request"* is **submissions** per pull request — its unit before *round*
124
124
  was redefined — and the tool prints that name, never the bare word.
125
+ **The register is historical.** The loop it measures is Copilot's, and Copilot review left this
126
+ repository's review path on 2026-10-30, by the maintainer's decision, so the capture is the record of that
127
+ loop rather than a reading of a live one.
125
128
  What each figure is, at length, is in the header at `git show a31da46:cli/review-meter.mjs`.
126
129
 
127
130
  **What it does NOT establish:**
@@ -133,9 +136,9 @@ What each figure is, at length, is in the header at `git show a31da46:cli/review
133
136
  workspace-layer matcher the engine tool refused to copy, since two spellings of one rule on opposite
134
137
  sides of that boundary cannot see each other drift; the matcher left with its workflow on 2026-09-23
135
138
  ([#355](https://github.com/sleepy-panda-srl/portulan/issues/355)).
136
- - **A bound.** It is a meter: rule 4 of
137
- [`a-review-loop-needs-a-bound.md`](../.portulan/memory/a-review-loop-needs-a-bound.md) stops a loop, and
138
- nothing here stops anything.
139
+ - **A bound.** It is a meter, and nothing here stops anything. The bound was rule 4 of
140
+ [`a-review-loop-needs-a-bound.md`](https://github.com/sleepy-panda-srl/portulan/blob/7d72356/.portulan/memory/a-review-loop-needs-a-bound.md),
141
+ retired on 2026-10-30.
139
142
  - **Current data.** The recipe compares the register to the snapshot, never the snapshot to the world, so a
140
143
  stale capture and a current one are the same green. Refreshing is `--fetch`, run by a person
141
144
  ([#356](https://github.com/sleepy-panda-srl/portulan/issues/356)).
@@ -232,12 +235,14 @@ is a new consent question rather than a covered one. It neither queues nor retri
232
235
  path. The send is proven only in the suite, against an injected transport, and no yielded recipe may
233
236
  ever exercise `--export`.
234
237
  - **A network mode reached indirectly.** The suite derives the set of network-capable modules from the
235
- tree, and the offline audit matches a module as a path suffix and a flag as a token; a mode reached
236
- through another script, or through a flag built at runtime, is invisible to it.
238
+ tree, and the offline audit matches a module as a path suffix and a flag as a token, or, for the
239
+ local-llm runner, any invocation but `--verify-offline` alone or `eval --verify` alone on its command; a mode reached through
240
+ another script, or through a flag built at runtime, is invisible to it.
237
241
  - **Scheduled emission.** Nothing fires when nobody runs it —
238
242
  [#344](https://github.com/sleepy-panda-srl/portulan/issues/344)'s silence again.
239
- - **Enforcement of the review-loop bound.** An emitter with no backend reading it is not the checker
240
- [`a-review-loop-needs-a-bound.md`](../.portulan/memory/a-review-loop-needs-a-bound.md) lacks.
243
+ - **Enforcement of the review-loop bound.** An emitter with no backend reading it was never the checker
244
+ [`a-review-loop-needs-a-bound.md`](https://github.com/sleepy-panda-srl/portulan/blob/7d72356/.portulan/memory/a-review-loop-needs-a-bound.md) lacked, and that record
245
+ retired on 2026-10-30.
241
246
  - **Traces.** Metrics only.
242
247
 
243
248
  ## The A/B baseline
@@ -262,6 +267,17 @@ capture. The recipes run no agent; the modes that do — `ab --stop-probe`, `ab-
262
267
  and the register cites it rather than restating it. **The baseline is scoped to the vendored-and-compiled
263
268
  tier** [`ab/arm.md`](ab/arm.md) specifies, and closes row 8 for no other configuration of *Portulan on*.
264
269
 
270
+ ## The local-worker routing capture — milestone 14
271
+
272
+ [`ab/local-worker.json`](ab/local-worker.json) is the immutable acquired local/host capture;
273
+ [`ab/local-worker.md`](ab/local-worker.md) is its generated register. The
274
+ [acquisition note](ab/local-worker-acquisition.md) records conditions, recovery and limitations.
275
+ `node packs/tools/local-llm/runner/local-llm.mjs eval --verify` regrades and byte-compares without a
276
+ model. `node cli/local-routing.mjs` additionally compares the shipped role flags, model IDs and
277
+ capture digest with an independent derivation. Both run beside the original baseline in `ab-run`.
278
+ The acquired five-turn cells support code, while the shared prose role is disabled. These rates
279
+ support no general quality claim, and CI cannot replay the events that produced them.
280
+
265
281
  ## A release carries an eval result
266
282
 
267
283
  ```
@@ -0,0 +1,111 @@
1
+ # Core persona routing comparisons
2
+
3
+ This protocol addresses [#520](https://github.com/sleepy-panda-srl/portulan/issues/520).
4
+ The frozen [corpus](corpus.json) has three artifact tasks per core role and one
5
+ attempt per arm. The [grader](grader.mjs) checks semantic behavior: bounded
6
+ execution and nonmutation for implementer code, executable counterexamples and
7
+ a clean control for reviewer findings, and preservation, escalation and human
8
+ authority for librarian drafts. These observations do not establish general
9
+ quality or a reliability rate.
10
+
11
+ A is the shipped role: inherited model, undeclared effort, instruction floor
12
+ retained and five-minute cache lifetime. B requests medium effort on the same
13
+ concrete inherited model through one native foreground persona child. The parent
14
+ runs at high effort; host request metadata must establish effective child effort.
15
+ The `--agent` main-session override is not this mechanism. Each parent and child
16
+ has a fresh context. Case order alternates A/B then B/A; an invalid invocation or
17
+ failed semantic control stops acquisition without resampling.
18
+
19
+ The observed concrete model is Sonnet 5.5 on Claude Code 2.1.321. A medium win on
20
+ this model and corpus does not establish medium effort for other inherited
21
+ models. The product retains `model: inherit` and undeclared effort; no global
22
+ lower-effort default is earned here.
23
+
24
+ ## Acquisition and accounting
25
+
26
+ Private originals retain the journal, CLI output, parent/child transcripts and
27
+ frozen source snapshots. Publication whitelists generic artifact answers,
28
+ numeric request metadata, normalized command arguments, timestamps and digests.
29
+ Answer presentation replaces only known acquisition and plugin-root prefixes
30
+ with `<acquisition>` and `<plugin>`; the record lists the affected answer and
31
+ retains both original and presented answer digests. Artifact contents and scores
32
+ are unchanged. Original answer wording otherwise remains.
33
+ Request identities and context identities are deterministically hashed; original
34
+ local paths, session identities and unrelated conversation content do not ship.
35
+ Public digests permit integrity checks; fidelity to private originals additionally
36
+ requires the independent acquisition review.
37
+
38
+ Acquisition fidelity **PASS**, signed `/root/checkpoint_520_open`, independent
39
+ read-only reviewer, 2026-11-10, for capture
40
+ `ff3688658bc20af6b78e834a5149ea6bd52bc88027b0340ec98cb52430c6d641`.
41
+ The reviewer independently checked all 80 requests (39 parent, 41 child), native
42
+ invocations, frozen sources, original answers, repair history and cost arithmetic.
43
+ The one disclosed citation normalization matches the deterministic transformation
44
+ and changes no JSON artifact or score. The checker and four capture/package tests
45
+ passed. This establishes retained-event fidelity; the sample, decoder repair,
46
+ reconstructed first-probe command and absence of billing evidence remain limits.
47
+
48
+ Two mechanism probes precede the eighteen quality children. The first used the
49
+ host's then-default Fable 5.2 and exceeded the configured one-dollar host-estimate
50
+ ceiling after a child ran. Its failed parent and child requests remain overhead;
51
+ it earns no quality result. Its command was reconstructed after execution from
52
+ the retained source, which was also snapshotted after execution. It is not a
53
+ contemporaneously recorded command. The second probe selected Sonnet 5.5 before
54
+ any quality outcome and demonstrated the native medium-effort mechanism. Quality
55
+ inference is limited to that model.
56
+
57
+ Every observed parent, child and probe request is counted once. The frozen price
58
+ vector is an index in uncached-input-token equivalents, not a price quotation or
59
+ subscription bill: uncached input 1, five-minute writes 1.25, one-hour writes 2,
60
+ unclassified writes 1.25, reads 0.1 and output 5. Registers separate observed
61
+ cost from a cold-normalized index. Normalization reprices all input in the first
62
+ request of each fresh parent and child context at 1.25, retaining subsequent
63
+ requests' observed classes and all output. Probe overhead is reported separately
64
+ from role comparisons. CLI USD values are host lifecycle estimates; they are not
65
+ added to these indexes.
66
+
67
+ ## Disclosed decoder repair
68
+
69
+ After the first quality outcome, acquisition stopped because the original
70
+ decoder rejected a correct function inside one JSON fence followed by prose.
71
+ The task requested a JSON artifact without forbidding surrounding prose; the
72
+ original decoder already allowed a whole-answer fence. The retained answer
73
+ passed the unchanged semantic execution checks.
74
+
75
+ The [original grader](repairs/grader-before-decode-repair.mjs.txt) and
76
+ [first answer](repairs/first-control-answer.txt) remain. A bounded decoder repair
77
+ accepts exactly one JSON fence with prose and rejects competing artifacts or
78
+ ambiguous fences. Semantic predicates, cases and pricing code stayed byte for
79
+ byte identical. The original false score is preserved alongside the repaired
80
+ true score. An independent checkpoint approved the exact decoder and continuation
81
+ instrument hashes before the remaining seventeen untouched calls. The first
82
+ child is never rerun. This is a post-outcome instrument repair, not an unchanged
83
+ preregistration.
84
+
85
+ ## Offline verification and delivery
86
+
87
+ The offline checker is `node cli/persona-routing.mjs --repo-root .`; it never
88
+ starts a host. It checks the immutable acquisition digest, all three role records,
89
+ semantic scores, generated registers, complete case/arm coverage, source and
90
+ binding bytes, effective effort, unique contexts/requests, frozen task bytes,
91
+ protocol snapshots, repair history and usage accounting. Exit 1 is a finding;
92
+ exit 2 is unavailable data or a failed read. The existing A/B recipe runs it.
93
+
94
+ The records and costs remain observations of source `01ca4887`; later bundle
95
+ changes are not new measurements. Current core charters must remain byte-identical
96
+ to that capture. A current plugin binding may change only its one nonempty,
97
+ single-line description scalar: every other byte, including tools, body and
98
+ context declarations, must match the historical binding. Malformed, duplicate,
99
+ missing or multiline descriptions refuse comparison. This permits the later
100
+ librarian description compression while preserving the acquired routing contract;
101
+ it establishes neither current whole-bundle costs nor equivalent automatic
102
+ delegation after description changes.
103
+
104
+ The npm payload carries the records, frozen protocol evidence, grader and offline
105
+ checker. Live acquisition and private normalization commands remain workshop
106
+ tools. A plugin update delivers the baked `agents/` files. The CLI's persona form
107
+ migration refreshes existing eligible bindings through the compiler planner:
108
+ core sources only in the installed engine's own tree, composed pack sources
109
+ through normal pack resolution. It creates no absent binding, installs no
110
+ foreign core adapter and changes no gate settings. The historical v0.2.0 suite
111
+ demonstrates actual check/write/check, idempotence, refusal and rollback.