@sleepy_panda_srl/portulan 0.4.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.
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.4.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
@@ -131,8 +131,9 @@ commit, refusing any packed file that differs from its source.
131
131
  | [`upgrade`](cli/upgrade.mjs) | Migrate a workspace across Workspace Definition versions |
132
132
  | [`new`](cli/new.mjs) | Scaffold a skill, persona, pack, workspace, gate policy or repo card |
133
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 |
134
135
 
135
- 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
136
137
  are not subcommands at all. [`cli/README.md`](cli/README.md), rendered from the code, lists that wider roster.
137
138
 
138
139
  ## Repository layout
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
 
@@ -58,7 +59,6 @@ Run as `node cli/<file>.mjs`, or imported by the files above.
58
59
  | [`discover.mjs`](discover.mjs) | Host plugin-cache discovery: reads a host's installed-plugin record to resolve a pointer and find pack roots. |
59
60
  | [`drills.mjs`](drills.mjs) | The forced-red drill harness — every rail broken on purpose, and required to fire. |
60
61
  | [`eval-bundle.mjs`](eval-bundle.mjs) | Cut a named-recipient evaluation bundle of Portulan from a commit. Not shipped. |
61
- | [`finish.mjs`](finish.mjs) | The finishing command — one call closes a change: its recipes, its changelog fragment, its commit, its push. |
62
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
63
  | [`frontmatter.mjs`](frontmatter.mjs) | Flat frontmatter for plugin components and host bindings. |
64
64
  | [`fuzz-shell.mjs`](fuzz-shell.mjs) | Grammar-aware fuzzing over this repository's two shell segmenters. |
package/cli/drills.mjs CHANGED
@@ -271,7 +271,7 @@ export const DRILLS = [
271
271
  rail: "pack-identity",
272
272
  perturb: {
273
273
  file: "README.md",
274
- find: "**Current release: `0.4.0`**",
274
+ find: "**Current release: `0.4.1`**",
275
275
  replace: "**Current release: `0.1.3`** <!-- the drill edited this and did not stage it -->",
276
276
  },
277
277
  stage: false,
@@ -355,7 +355,7 @@ export const DRILLS = [
355
355
  rail: "version-carriers",
356
356
  perturb: {
357
357
  file: "README.md",
358
- find: "**Current release: `0.4.0`**",
358
+ find: "**Current release: `0.4.1`**",
359
359
  replace: "**Current release: `0.1.3`**",
360
360
  },
361
361
  // Staged: this rail reads the index (`git show :<path>`), so an unstaged edit is invisible to it.
package/cli/finish.mjs CHANGED
@@ -28,6 +28,7 @@ const GIT_TIMEOUT_MS = 2 * 60 * 1000;
28
28
  const USAGE = [
29
29
  "usage: node cli/finish.mjs -m <subject> [-m <paragraph>]... [options]",
30
30
  " node cli/finish.mjs -F <file | -> [options]",
31
+ " portulan finish <the same arguments>, where the package is installed",
31
32
  "",
32
33
  " -m <text> a paragraph of the commit message, the first its subject, as git takes -m",
33
34
  " -F <file | -> the whole commit message, from a file or from standard input",
package/cli/form.mjs CHANGED
@@ -543,7 +543,7 @@ export function draftCard(manifest, read, { workspace, inTree, repoCards = [] })
543
543
  }
544
544
  section(
545
545
  "Records",
546
- 'Close a change with `git add <new files> && node <plugin root>/cli/finish.mjs -m "<subject>" -m "<why>"` after writing its changelog entry, a one-bullet file `changes/<slug>.<section>.md`: it commits and pushes only when every verify recipe passes.',
546
+ 'Close a change with `git add <new files> && portulan finish -m "<subject>" -m "<why>"` after writing its changelog entry, a one-bullet file `changes/<slug>.<section>.md`: it commits and pushes only when every verify recipe passes. Where `portulan` is not on the path, run `npx @sleepy_panda_srl/portulan finish` instead, and do not search the disk for it.',
547
547
  ...(slots.handoffs ? [`A session ending with work not committed and pushed leaves a dated handoff in ${shown(slots.handoffs)}.`] : []),
548
548
  );
549
549
  section(
package/cli/portulan.mjs CHANGED
@@ -55,6 +55,11 @@ export const SUBCOMMANDS = [
55
55
  module: "feedback.mjs",
56
56
  summary: "file an issue from a report you previewed, seam-scanned before it leaves the machine",
57
57
  },
58
+ {
59
+ name: "finish",
60
+ module: "finish.mjs",
61
+ summary: "close a change in one call, committing and pushing only when every verify recipe passes",
62
+ },
58
63
  ];
59
64
 
60
65
  export function find(name) {
@@ -77,8 +82,8 @@ export function usage() {
77
82
  "",
78
83
  "Exit codes: 0 succeeded · 1 a red verdict · 2 could not run.",
79
84
  "",
80
- "Other tools live in cli/ and are deliberately not here — docs/vision.md names these eight",
81
- "subcommands and is human-owned, so a ninth is the maintainer's call. cli/README.md lists them.",
85
+ "Other tools live in cli/ and are deliberately not here — docs/vision.md names these subcommands",
86
+ "and is human-owned, so another is the maintainer's call. cli/README.md lists them.",
82
87
  );
83
88
  return lines.join("\n");
84
89
  }
package/cli/vendor.mjs CHANGED
@@ -540,7 +540,9 @@ export function agentsMd(manifest, host, kernel = null, guidance = null) {
540
540
  "- **A resolved pointer.** Nothing here fetches anything.",
541
541
  ...(cardText?.includes("<plugin root>")
542
542
  ? ["- **The Portulan package.** The card's `<plugin root>` is where it is installed, which this copy is not."]
543
- : []),
543
+ : cardText?.includes("portulan finish")
544
+ ? ["- **The Portulan package.** The card's `portulan finish` runs from it, and this copy does not carry it."]
545
+ : []),
544
546
  "",
545
547
  "Run `portulan doctor .portulan` to see where this stands.",
546
548
  "",
@@ -0,0 +1,154 @@
1
+ {
2
+ "portulan": {
3
+ "releaseEval": "1"
4
+ },
5
+ "version": "0.4.1",
6
+ "captured": "2026-11-11",
7
+ "source": {
8
+ "commit": "a83966a56af78bd76a63c48afdce457aa3c5b0d5",
9
+ "clean": true
10
+ },
11
+ "host": {
12
+ "node": "v26.13.0",
13
+ "platform": "darwin"
14
+ },
15
+ "recipes": [
16
+ {
17
+ "id": "cache-stability",
18
+ "exit": 0
19
+ },
20
+ {
21
+ "id": "docs",
22
+ "exit": 0
23
+ },
24
+ {
25
+ "id": "json",
26
+ "exit": 0
27
+ },
28
+ {
29
+ "id": "doctor",
30
+ "exit": 0
31
+ },
32
+ {
33
+ "id": "tests",
34
+ "exit": 0
35
+ },
36
+ {
37
+ "id": "plugin",
38
+ "exit": 0
39
+ },
40
+ {
41
+ "id": "compile",
42
+ "exit": 0
43
+ },
44
+ {
45
+ "id": "workflow-filters",
46
+ "exit": 0
47
+ },
48
+ {
49
+ "id": "index",
50
+ "exit": 0
51
+ },
52
+ {
53
+ "id": "context",
54
+ "exit": 0
55
+ },
56
+ {
57
+ "id": "ledger",
58
+ "exit": 0
59
+ },
60
+ {
61
+ "id": "control-chars",
62
+ "exit": 0
63
+ },
64
+ {
65
+ "id": "comments",
66
+ "exit": 0
67
+ },
68
+ {
69
+ "id": "rule-carriers",
70
+ "exit": 0
71
+ },
72
+ {
73
+ "id": "pack-version",
74
+ "exit": 0
75
+ },
76
+ {
77
+ "id": "pack-identity",
78
+ "exit": 0
79
+ },
80
+ {
81
+ "id": "payload",
82
+ "exit": 0
83
+ },
84
+ {
85
+ "id": "eval-bundle",
86
+ "exit": 0
87
+ },
88
+ {
89
+ "id": "goldens",
90
+ "exit": 0
91
+ },
92
+ {
93
+ "id": "mutants",
94
+ "exit": 0
95
+ },
96
+ {
97
+ "id": "fuzz-shell",
98
+ "exit": 0
99
+ },
100
+ {
101
+ "id": "version-carriers",
102
+ "exit": 0
103
+ },
104
+ {
105
+ "id": "skill-goldens",
106
+ "exit": 0
107
+ },
108
+ {
109
+ "id": "review-loop",
110
+ "exit": 0
111
+ },
112
+ {
113
+ "id": "telemetry",
114
+ "exit": 0
115
+ },
116
+ {
117
+ "id": "drills",
118
+ "exit": 0
119
+ },
120
+ {
121
+ "id": "ab",
122
+ "exit": 0
123
+ },
124
+ {
125
+ "id": "ab-grade",
126
+ "exit": 0
127
+ },
128
+ {
129
+ "id": "ab-run",
130
+ "exit": 0
131
+ },
132
+ {
133
+ "id": "tools/github:actions-pinned",
134
+ "exit": 0
135
+ },
136
+ {
137
+ "id": "tools/local-llm:runner-rails",
138
+ "exit": 0
139
+ }
140
+ ],
141
+ "excluded": [
142
+ {
143
+ "id": "release-eval",
144
+ "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."
145
+ }
146
+ ],
147
+ "abBaseline": {
148
+ "snapshot": "evals/ab/baseline.json",
149
+ "register": "evals/ab/baseline.md",
150
+ "captured": "2026-08-31T09:05:32.699Z",
151
+ "commit": "a642d551eec6c146c67ef0acfe3f8ba535c5ce6e",
152
+ "clean": false
153
+ }
154
+ }
@@ -0,0 +1,69 @@
1
+ # Eval result — Portulan 0.4.1
2
+
3
+ > **Generated. Do not edit.** Rendered from [`evals/releases/0.4.1.json`](0.4.1.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.4.1` |
10
+ | Captured | 2026-11-11 |
11
+ | Commit | `a83966a56af78bd76a63c48afdce457aa3c5b0d5` |
12
+ | Tree at capture | clean |
13
+ | Node | `v26.13.0` |
14
+ | Platform | `darwin` |
15
+
16
+ ## The rails, and what each returned
17
+
18
+ 31 of the 32 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
+ | `cache-stability` | green |
23
+ | `docs` | green |
24
+ | `json` | green |
25
+ | `doctor` | green |
26
+ | `tests` | green |
27
+ | `plugin` | green |
28
+ | `compile` | green |
29
+ | `workflow-filters` | green |
30
+ | `index` | green |
31
+ | `context` | green |
32
+ | `ledger` | green |
33
+ | `control-chars` | green |
34
+ | `comments` | green |
35
+ | `rule-carriers` | green |
36
+ | `pack-version` | green |
37
+ | `pack-identity` | green |
38
+ | `payload` | green |
39
+ | `eval-bundle` | green |
40
+ | `goldens` | green |
41
+ | `mutants` | green |
42
+ | `fuzz-shell` | green |
43
+ | `version-carriers` | green |
44
+ | `skill-goldens` | green |
45
+ | `review-loop` | green |
46
+ | `telemetry` | green |
47
+ | `drills` | green |
48
+ | `ab` | green |
49
+ | `ab-grade` | green |
50
+ | `ab-run` | green |
51
+ | `tools/github:actions-pinned` | green |
52
+ | `tools/local-llm:runner-rails` | green |
53
+
54
+ **`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.
55
+
56
+ ## The A/B baseline this release ships against
57
+
58
+ [`evals/ab/baseline.md`](https://github.com/sleepy-panda-srl/portulan/blob/v0.4.1/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**.
59
+
60
+ **Its figures are not repeated here.** They have one carrier and this is not it.
61
+
62
+ ## What this record does not establish
63
+
64
+ - **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.
65
+ - **The recipes were not run at the tag.** They ran at `a83966a56af78bd76a63c48afdce457aa3c5b0d5`, 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.
66
+ - **`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.
67
+ - **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.
68
+ - **The tree was clean at capture**, so the commit named above is what was measured.
69
+ - **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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleepy_panda_srl/portulan",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
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",