@sleepy_panda_srl/portulan 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,134 @@
1
+ {
2
+ "portulan": {
3
+ "releaseEval": "1"
4
+ },
5
+ "version": "0.1.3",
6
+ "captured": "2026-09-16",
7
+ "source": {
8
+ "commit": "fac7b6d36ce3aa53ce93381ef8cce07e503608e4",
9
+ "clean": true
10
+ },
11
+ "host": {
12
+ "node": "v26.8.1",
13
+ "platform": "darwin"
14
+ },
15
+ "recipes": [
16
+ {
17
+ "id": "docs",
18
+ "exit": 0
19
+ },
20
+ {
21
+ "id": "json",
22
+ "exit": 0
23
+ },
24
+ {
25
+ "id": "doctor",
26
+ "exit": 0
27
+ },
28
+ {
29
+ "id": "tests",
30
+ "exit": 0
31
+ },
32
+ {
33
+ "id": "plugin",
34
+ "exit": 0
35
+ },
36
+ {
37
+ "id": "compile",
38
+ "exit": 0
39
+ },
40
+ {
41
+ "id": "workflow-filters",
42
+ "exit": 0
43
+ },
44
+ {
45
+ "id": "index",
46
+ "exit": 0
47
+ },
48
+ {
49
+ "id": "control-chars",
50
+ "exit": 0
51
+ },
52
+ {
53
+ "id": "rule-carriers",
54
+ "exit": 0
55
+ },
56
+ {
57
+ "id": "pack-version",
58
+ "exit": 0
59
+ },
60
+ {
61
+ "id": "pack-identity",
62
+ "exit": 0
63
+ },
64
+ {
65
+ "id": "payload",
66
+ "exit": 0
67
+ },
68
+ {
69
+ "id": "eval-bundle",
70
+ "exit": 0
71
+ },
72
+ {
73
+ "id": "goldens",
74
+ "exit": 0
75
+ },
76
+ {
77
+ "id": "mutants",
78
+ "exit": 0
79
+ },
80
+ {
81
+ "id": "fuzz-shell",
82
+ "exit": 0
83
+ },
84
+ {
85
+ "id": "version-carriers",
86
+ "exit": 0
87
+ },
88
+ {
89
+ "id": "skill-goldens",
90
+ "exit": 0
91
+ },
92
+ {
93
+ "id": "review-loop",
94
+ "exit": 0
95
+ },
96
+ {
97
+ "id": "telemetry",
98
+ "exit": 0
99
+ },
100
+ {
101
+ "id": "drills",
102
+ "exit": 0
103
+ },
104
+ {
105
+ "id": "ab",
106
+ "exit": 0
107
+ },
108
+ {
109
+ "id": "ab-grade",
110
+ "exit": 0
111
+ },
112
+ {
113
+ "id": "ab-run",
114
+ "exit": 0
115
+ },
116
+ {
117
+ "id": "tools/github:actions-pinned",
118
+ "exit": 0
119
+ }
120
+ ],
121
+ "excluded": [
122
+ {
123
+ "id": "release-eval",
124
+ "why": "a capture cannot be accurate about the record it is inside — captured before the record is written it is red for the record's absence, and captured after it is stale the moment the register is rendered. Its verdict for this release is the rail's own run on the pull request carrying this file."
125
+ }
126
+ ],
127
+ "abBaseline": {
128
+ "snapshot": "evals/ab/baseline.json",
129
+ "register": "evals/ab/baseline.md",
130
+ "captured": "2026-08-31T09:05:32.699Z",
131
+ "commit": "a642d551eec6c146c67ef0acfe3f8ba535c5ce6e",
132
+ "clean": false
133
+ }
134
+ }
@@ -0,0 +1,64 @@
1
+ # Eval result — Portulan 0.1.3
2
+
3
+ > **Generated. Do not edit.** Rendered from [`evals/releases/0.1.3.json`](0.1.3.json) by [`cli/release-eval.mjs`](../../cli/release-eval.mjs) and byte-compared by the `release-eval` verify recipe. This is the eval result milestone 8 requires a release to carry — `docs/plan.md`, Protocol → Versioning.
4
+
5
+ ## What this release was measured at
6
+
7
+ | | |
8
+ |---|---|
9
+ | Version | `0.1.3` |
10
+ | Captured | 2026-09-16 |
11
+ | Commit | `fac7b6d36ce3aa53ce93381ef8cce07e503608e4` |
12
+ | Tree at capture | clean |
13
+ | Node | `v26.8.1` |
14
+ | Platform | `darwin` |
15
+
16
+ ## The rails, and what each returned
17
+
18
+ 26 of the 27 recipes this workspace yielded at capture. The set is derived from [`cli/recipe-set.mjs`](../../cli/recipe-set.mjs) and never listed by hand.
19
+
20
+ | Recipe | Verdict |
21
+ |---|---|
22
+ | `docs` | green |
23
+ | `json` | green |
24
+ | `doctor` | green |
25
+ | `tests` | green |
26
+ | `plugin` | green |
27
+ | `compile` | green |
28
+ | `workflow-filters` | green |
29
+ | `index` | green |
30
+ | `control-chars` | green |
31
+ | `rule-carriers` | green |
32
+ | `pack-version` | green |
33
+ | `pack-identity` | green |
34
+ | `payload` | green |
35
+ | `eval-bundle` | green |
36
+ | `goldens` | green |
37
+ | `mutants` | green |
38
+ | `fuzz-shell` | green |
39
+ | `version-carriers` | green |
40
+ | `skill-goldens` | green |
41
+ | `review-loop` | green |
42
+ | `telemetry` | green |
43
+ | `drills` | green |
44
+ | `ab` | green |
45
+ | `ab-grade` | green |
46
+ | `ab-run` | green |
47
+ | `tools/github:actions-pinned` | green |
48
+
49
+ **`release-eval` is excluded**, and the reason is printed rather than the row silently dropped: a capture cannot be accurate about the record it is inside — captured before the record is written it is red for the record's absence, and captured after it is stale the moment the register is rendered. Its verdict for this release is the rail's own run on the pull request carrying this file.
50
+
51
+ ## The A/B baseline this release ships against
52
+
53
+ [`evals/ab/baseline.md`](../../evals/ab/baseline.md), rendered from `evals/ab/baseline.json` — captured 2026-08-31T09:05:32.699Z at `a642d551eec6c146c67ef0acfe3f8ba535c5ce6e`, over a tree that was **not clean**.
54
+
55
+ **Its figures are not repeated here.** They have one carrier and this is not it.
56
+
57
+ ## What this record does not establish
58
+
59
+ - **A green says this record agrees with its own capture — never that the release is good.** Every line below is what the recipes returned at one commit, and a recipe's own green establishes only what that recipe's documentation says it establishes.
60
+ - **The recipes were not run at the tag.** They ran at `fac7b6d36ce3aa53ce93381ef8cce07e503608e4`, and this record is committed *in* the cut change — so the tagged tree is this commit plus whatever that change still adds after the capture, the record itself at minimum. A record cannot be captured at a commit that does not exist yet, and printing the one it was captured at is the only honest form.
61
+ - **`release-eval` is excluded from the rows above**, because a capture cannot be accurate about the record it is inside. Its verdict for this release is the rail's own run on the pull request that carries this file.
62
+ - **This record measures the Portulan repository's own build**, at the commit named above — never the workspace, project or package this release is installed into. Nothing here has looked at your tree.
63
+ - **The tree was clean at capture**, so the commit named above is what was measured.
64
+ - **The A/B baseline's figures are NOT restated here.** This record names which baseline the release ships against; the figures and everything that may not be concluded from them live in that register alone.
@@ -0,0 +1,32 @@
1
+ # `evals/releases/`
2
+
3
+ The eval result each release carries, one pair per version — milestone 8's ninth clause. The argument,
4
+ the limits and the two designs a fresh context reversed are in [`../README.md`](../README.md); the
5
+ mechanism is [`../../cli/release-eval.mjs`](../../cli/release-eval.mjs). This file does not restate
6
+ either, because a rule with two carriers is obeyed at the narrower one.
7
+
8
+ - `<version>.json` — the **capture**: the verdict every recipe the workspace yielded returned, at a named
9
+ commit, plus the identity of the A/B baseline that release ships against. Written by
10
+ `node cli/release-eval.mjs --capture`, which runs them. **A hand-edited capture is NOT caught by the
11
+ byte comparison** — that holds the register to the capture, so `--write` re-renders the edit and the
12
+ pair agrees perfectly. What guards a capture is the rail's reading of its *contents*: an exclusion
13
+ list that is anything but the self-exclusion, a recorded non-zero exit, a version not matching the
14
+ release it is filed under, a record for a version never cut or for one the clause does not govern.
15
+ This sentence used to claim the opposite, and a sentence claiming a guard that does not exist is what
16
+ makes the gap it describes look unreachable.
17
+ - `<version>.md` — the **register**, rendered from the capture. Generated; do not edit. `--write`
18
+ re-renders it and the `release-eval` recipe refuses any difference.
19
+
20
+ **Which releases have records is not written here.** `ls` this directory, or run
21
+ `node cli/release-eval.mjs --verify`, which prints the governed set and is the carrier — a sentence
22
+ counting the files beside it would be a hand-maintained figure of a subject that grows once per release,
23
+ which is the defect this repository deletes on sight.
24
+
25
+ **What is fixed, and is the only thing this file states about coverage:** the clause binds *from
26
+ milestone 8* — [`../../docs/plan.md`](../../docs/plan.md), Protocol → Versioning — so `v0.1.0`, `v0.1.1`
27
+ and `v0.1.2` carry none and are never asked to. That is history and cannot change.
28
+
29
+ _(This paragraph read **"This directory is empty of records"** as a standing claim. It would have gone
30
+ false in the very commit that wrote the first record — and, since this directory ships inside the npm
31
+ payload, it would then have been **frozen false beside the record it denied**, in a tarball only another
32
+ release could correct. Caught by a second opinion before the first cut rather than by a reader of it.)_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleepy_panda_srl/portulan",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Portulan — an agentic-engineering framework whose product is its files. The CLI wraps the file-based mechanics for hosts beyond Claude Code.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -15,13 +15,18 @@
15
15
  "core/",
16
16
  "spec/",
17
17
  "packs/",
18
+ "evals/releases/",
18
19
  "README.md",
19
20
  "LICENSE",
20
21
  "NOTICE",
21
22
  "!cli/*.test.mjs",
22
23
  "!cli/fixtures",
23
24
  "!cli/eval-bundle.mjs",
24
- "!cli/eval-license.template.md"
25
+ "!cli/eval-license.template.md",
26
+ "!cli/ab.mjs",
27
+ "!cli/ab-run.mjs",
28
+ "!cli/ab-grade.mjs",
29
+ "!cli/payload.mjs"
25
30
  ],
26
31
  "repository": {
27
32
  "type": "git",
@@ -38,7 +38,7 @@ Four verdicts, and which are available depends on the checkpoint.
38
38
  | Verdict | Means | Available at |
39
39
  |---|---|---|
40
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 |
41
+ | **APPROVE-WITH-ADJUSTMENTS** | Proceed once the numbered adjustments are folded in. Not a soft failure — it is what a working checkpoint usually returns. **At pre-commit the fold itself is then graded** — see that skill. | session-open · pre-commit |
42
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
43
  | **CLOSE** | Every clause of the criterion is demonstrated; the milestone may be marked done. | milestone-close only |
44
44
 
@@ -49,6 +49,13 @@ concerns is not a verdict.
49
49
  proceed on a promise to fold something in, and a close is the one decision with nothing downstream of
50
50
  it to catch what was folded in wrongly.
51
51
 
52
+ **That argument reaches one moment earlier, which is why pre-commit's A-W-A grades its own fold**
53
+ (proposal `0035`, 2026-08-29). Session-open's fold *does* have something downstream — the plan it folds
54
+ into becomes a diff, and pre-commit grades that. **Pre-commit's fold has only the commit.** So the
55
+ verdict that lets work proceed on a promise is, at that moment, a promise nothing checks; measured on a
56
+ change where two of three later review findings were created by the fold and were absent from the graded
57
+ diff.
58
+
52
59
  ## The fidelity note
53
60
 
54
61
  What a close leaves in the record once the session that wrote it is gone. Four parts, in one clause:
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "portulan": {
3
3
  "pack": "1.0",
4
- "version": "0.2.1"
4
+ "version": "0.3.0"
5
5
  },
6
6
 
7
7
  "name": "checkpoints",
@@ -65,8 +65,38 @@ whether a status column changed.
65
65
  ## The verdicts this checkpoint may return
66
66
 
67
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.
68
+ - **APPROVE-WITH-ADJUSTMENTS** — fold the numbered adjustments, then **grade the fold**: a pass over
69
+ **the fold delta alone**, in a context that did not perform the fold, before the commit.
70
+ - **REQUEST-CHANGES** — the diff does not meet the criterion; it needs work and a second pre-commit pass
71
+ **over the whole diff**.
72
+
73
+ **Grade a fully staged diff.** The whole procedure below is index-shaped, so anything left unstaged was
74
+ not graded and will not appear in the fold delta either — it would pass through both nets. Stage first,
75
+ then grade; this is what practice here already did, and it is stated because the mechanism now depends
76
+ on it rather than merely benefiting from it.
77
+
78
+ **A checkpoint records the tree it graded** — the index it read, as a tree object (`git write-tree`). The
79
+ fold delta is then **`git diff --cached <graded-tree>`**: the recorded tree against the index, which is
80
+ what is about to be committed. Derived, not reconstructed from memory by the person who folded.
81
+
82
+ _Why the fold is graded at all, and why the A-W-A pass is scoped to the delta._ **The tree that ships is
83
+ not the tree that was graded**, and the difference is where a remediation can inject what the checkpoint
84
+ just caught elsewhere. Measured: on one change, folding an adjustment split a table row and left a
85
+ summary count stale three sections above, and folding another **re-measured a question the checkpoint had
86
+ answered correctly** — with a line-based tool against a normalising scanner — and wrote the wrong answer
87
+ over the right one. Neither defect was in the graded diff. A full re-grade after every A-W-A would double
88
+ the cost of the cheapest verdict, which is the ceremony a definition of done should refuse; **the delta is
89
+ the only region a fold-injected defect can be in.**
90
+
91
+ _The delta is **whatever was staged after the grade** — it *should* be the adjustments and nothing else,
92
+ and the mechanism does not guarantee that. **Where it is wider, that is not noise; it is the finding.**
93
+ Post-grade edits nobody proposed are exactly what escapes a checkpoint today, so a pass that sees them is
94
+ worth more than one over a delta that had been trimmed to what the verdict asked for._
95
+
96
+ _What this does not buy, said plainly: whether a fresh context actually read the delta is not checkable —
97
+ a session can claim a pass it did not run. What changes is that the pass now has a **defined subject**,
98
+ derived from the tree rather than recalled by the one who folded._ Provenance: proposal `0035`,
99
+ accepted 2026-08-29.
70
100
 
71
101
  ## Why it earns its tokens
72
102
 
package/spec/slots.md CHANGED
@@ -771,8 +771,32 @@ Each of these was a candidate; none is an oversight.
771
771
  - **A per-host capability matrix.** The vision's `doctor` includes a per-host capability report, but that
772
772
  is generated from the host and the compiled gates, not declared by the team. It belongs with the
773
773
  enforcement backends in milestone 4.
774
- - **`evals`.** Milestone 8 owns the eval harness; a slot pointing at golden tasks before any exist would
775
- be the emptiest kind of scaffolding.
774
+ - **`evals`.** Milestone 8 owns the eval harness. **The original reason for deferring is spent, and the
775
+ deferral is re-argued rather than left standing on it.** It read *"a slot pointing at golden tasks
776
+ before any exist would be the emptiest kind of scaffolding"* — and golden tasks exist: the gate corpus
777
+ landed at clause (a) and the core-skill corpus at the row's original first subject. The premise
778
+ expired the day it stopped being true and nothing noticed, which is the shape this file elsewhere
779
+ calls a claim outliving its measurement.
780
+
781
+ **What the deferral now rests on.** A slot is the Workspace Definition's promise that every conforming
782
+ workspace can be asked one question and answer it. `evals/` today holds **two corpora with two
783
+ different oracles** — gates answered by the compiler's own `matchesRule`, skills answered by
784
+ mandate-to-artifact bindings — plus a metering register, and a slot naming that directory would
785
+ promise adopters a shape this repository has not settled for itself. **Revisit when milestone 8
786
+ closes**, by which point the row's nine clauses will have decided what an eval artifact is here.
787
+ Filling it is a schema change, a spec version bump and a migration, so it is not a thing to do in
788
+ passing.
789
+
790
+ **Milestone 8 closed 2026-09-09, so this deferral is now DUE and is not discharged here.** The
791
+ close names it rather than filling it, which is what the sentence above asks for: the drafting is
792
+ commissioned by proposal
793
+ [`../.portulan/proposals/0034-one-spec-bump-carries-both-evals-and-telemetry.md`](../.portulan/proposals/0034-one-spec-bump-carries-both-evals-and-telemetry.md)
794
+ — accepted 2026-08-28 — which carries `evals` **and** `telemetry` in **one** MINOR and settles none of
795
+ the shape: the key names, either slot's structure, and whether a migration is owed are the drafted
796
+ work. Doing that drafting inside the close would be the *"splitting on speculation"* this entry warns
797
+ against, in the change that closed the row it was waiting for. **What the close settled is the
798
+ precondition, not the slot:** `evals/` now holds two corpora, a metering register, an A/B capture and
799
+ a per-release record layer, which is the shape a slot would have to name.
776
800
 
777
801
  ## What v2.0 is not
778
802