@sleepy_panda_srl/portulan 0.1.1 → 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.
- package/README.md +16 -19
- package/cli/README.md +155 -125
- package/cli/compile.mjs +797 -40
- package/cli/doctor.mjs +59 -2
- package/cli/drills.mjs +1541 -0
- package/cli/fuzz-shell.mjs +880 -0
- package/cli/gate.mjs +3 -2
- package/cli/goldens.mjs +469 -0
- package/cli/index.mjs +92 -42
- package/cli/init.mjs +4 -1
- package/cli/inside.mjs +38 -0
- package/cli/mutants.mjs +925 -0
- package/cli/pack-identity.mjs +9 -2
- package/cli/pack-version.mjs +7 -0
- package/cli/recipe-set.mjs +48 -1
- package/cli/release-eval.mjs +1068 -0
- package/cli/review-meter.mjs +741 -0
- package/cli/skill-goldens.mjs +590 -0
- package/cli/skills-set.mjs +166 -4
- package/cli/stop-gate.mjs +301 -28
- package/cli/telemetry.mjs +1047 -0
- package/cli/version-carriers.mjs +224 -0
- package/core/operating/memory.md +7 -8
- package/core/operating/verification.md +4 -12
- package/core/templates/gate-policy.md +27 -8
- package/evals/README.md +910 -0
- package/evals/releases/0.1.3.json +134 -0
- package/evals/releases/0.1.3.md +64 -0
- package/evals/releases/README.md +32 -0
- package/package.json +7 -2
- package/packs/README.md +11 -21
- package/packs/rituals/checkpoints/README.md +8 -1
- package/packs/rituals/checkpoints/pack.json +1 -1
- package/packs/rituals/checkpoints/skills/pre-commit/SKILL.md +32 -2
- package/packs/tools/README.md +1 -4
- package/spec/README.md +19 -22
- package/spec/migrations/README.md +2 -3
- package/spec/slots.md +30 -11
package/cli/pack-identity.mjs
CHANGED
|
@@ -43,8 +43,15 @@ class CannotRun extends Error {}
|
|
|
43
43
|
|
|
44
44
|
const run = (cmd, args, opts = {}) => execFileSync(cmd, args, { encoding: "buffer", maxBuffer: 64 * 1024 * 1024, ...opts });
|
|
45
45
|
|
|
46
|
-
/**
|
|
47
|
-
|
|
46
|
+
/**
|
|
47
|
+
* What the package would contain, as repo-relative paths.
|
|
48
|
+
*
|
|
49
|
+
* **Exported because `./payload.mjs` classifies exactly this roster**, and two enumerations of *what
|
|
50
|
+
* npm would pack* is the second-carrier defect this repository keeps paying for. That rail asks which
|
|
51
|
+
* files ship; this one asks whether each is byte-identical to its source. One question about
|
|
52
|
+
* membership, asked once, answered here.
|
|
53
|
+
*/
|
|
54
|
+
export function packedPaths(root) {
|
|
48
55
|
let out;
|
|
49
56
|
try {
|
|
50
57
|
out = run("npm", ["pack", "--dry-run", "--json"], { cwd: root, stdio: ["ignore", "pipe", "pipe"] }).toString("utf8");
|
package/cli/pack-version.mjs
CHANGED
|
@@ -13,6 +13,13 @@
|
|
|
13
13
|
// for a single field. `portulan.version` is per-pack, so it cannot contend. Tying the bundle to the pack
|
|
14
14
|
// manifests is arm 4 of the issue and is deliberately NOT here.
|
|
15
15
|
//
|
|
16
|
+
// **Re-measured 2026-08-29: the bundle now agrees with NEITHER pack** — `rituals/checkpoints` moved to
|
|
17
|
+
// `0.3.0` when proposal `0035` added an obligation to its pre-commit verdict, while the bundle stayed
|
|
18
|
+
// `0.2.1` and `tools/github` stayed `0.1.0`. The measurement above is stamped to `c93a819` and remains
|
|
19
|
+
// true of that commit; what changed is that the coincidence it names has ended, which STRENGTHENS the
|
|
20
|
+
// argument rather than dating it. A reader finding three different numbers is looking at three
|
|
21
|
+
// independently versioned things, not at drift.
|
|
22
|
+
//
|
|
16
23
|
// ## Why the whole `contributes` block, not only `gates`
|
|
17
24
|
//
|
|
18
25
|
// The issue's title asks about gate fragments; arm 3's own text says *"touching a pack's `contributes`
|
package/cli/recipe-set.mjs
CHANGED
|
@@ -61,7 +61,8 @@ import fs from "node:fs";
|
|
|
61
61
|
import path from "node:path";
|
|
62
62
|
import { pathToFileURL } from "node:url";
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
// `shadowedCopy` rides along: one carrier for *is this pack shadowed*, per #316.
|
|
65
|
+
import { resolvePack, rootPlan, shadowedCopy } from "./compile.mjs";
|
|
65
66
|
import { AUTO, discoverPackRoots, namedWithAuto } from "./discover.mjs";
|
|
66
67
|
|
|
67
68
|
/**
|
|
@@ -82,6 +83,12 @@ import { AUTO, discoverPackRoots, namedWithAuto } from "./discover.mjs";
|
|
|
82
83
|
export const RECIPE_SET_READERS = Object.freeze([
|
|
83
84
|
".github/workflows/verify.yml",
|
|
84
85
|
"cli/doctor.mjs",
|
|
86
|
+
// Added 2026-08-25 with milestone 8 clause (d). `cli/drills.mjs` reads the set to know which rails
|
|
87
|
+
// it must drill — and it is the reader that shows the live sweep's own boundary: it calls
|
|
88
|
+
// `recipeSet()` rather than enumerating `verify.recipes`, so the sweep for an undeclared
|
|
89
|
+
// *enumeration* could not see it and this roster went stale in the one way the pair above was
|
|
90
|
+
// arranged not to allow. Raised as a suppressed note by Copilot, round 1 on #343.
|
|
91
|
+
"cli/drills.mjs",
|
|
85
92
|
"cli/stop-gate.mjs",
|
|
86
93
|
"cli/vendor.mjs",
|
|
87
94
|
]);
|
|
@@ -288,6 +295,46 @@ export function resolverFor({ workspaceDir, manifest, repoRoot = ".", named = []
|
|
|
288
295
|
if (plan.refusal) throw new Error(`recipe-set: ${plan.refusal}`);
|
|
289
296
|
if (plan.couldNotRun) throw new Error(`recipe-set: ${plan.couldNotRun}`);
|
|
290
297
|
const roots = plan.roots ?? [];
|
|
298
|
+
const originAt = (r) => (plan.origins ?? []).find((o) => path.resolve(o.root) === path.resolve(r))?.origin;
|
|
299
|
+
|
|
300
|
+
// **A shadowed pack is refused here too** (#318), and this tool's ground is the strongest of the
|
|
301
|
+
// three. `compile` refuses even an agreeing shadow because its artifact records which root
|
|
302
|
+
// answered; `index` refuses one although its artifact deliberately does not. Here the answering
|
|
303
|
+
// root is not merely recorded — **it is spliced into the output**: `${PACK_ROOT}` expands to the
|
|
304
|
+
// root that answered, so two copies whose manifests are byte-identical still yield different `run`
|
|
305
|
+
// lines pointing at different files. What CI runs and what a bare local run runs would diverge,
|
|
306
|
+
// with nothing in either output to say so.
|
|
307
|
+
//
|
|
308
|
+
// So the agreeing case is not a carve-out anyone could argue for here, and the honest predicate was
|
|
309
|
+
// never manifest comparison: it is output equality, computable only by resolving both worlds.
|
|
310
|
+
// Refusing the ambiguity is what remains.
|
|
311
|
+
//
|
|
312
|
+
// **Checked HERE rather than inside the returned closure**, which is where a first cut put it. The
|
|
313
|
+
// closure runs during `recipeSet`, outside the `try` that wraps this constructor — so the refusal
|
|
314
|
+
// escaped as an uncaught throw, exit 1 with a stack trace, in a tool whose whole contract is exit 2
|
|
315
|
+
// for could-not-run. Measured, not reasoned about. Throwing from the constructor puts it on the
|
|
316
|
+
// path `plan.refusal` already uses and the caller already catches.
|
|
317
|
+
//
|
|
318
|
+
// **Only where the caller did not choose** — a named root replaces the derived one, `auto` is
|
|
319
|
+
// discovery elected — which is `compile`'s guard shape, bound to it deliberately.
|
|
320
|
+
if (!forced && plan.source !== "named") {
|
|
321
|
+
const declared = Array.isArray(manifest?.packs) ? manifest.packs : [];
|
|
322
|
+
for (const ref of declared) {
|
|
323
|
+
const found = resolvePack(String(ref), roots);
|
|
324
|
+
if (!found?.dir) continue;
|
|
325
|
+
// Path-resolved, matching `compile` — see the sibling note in `index.mjs`.
|
|
326
|
+
const behind = shadowedCopy(String(ref), originAt(found.root), roots, originAt);
|
|
327
|
+
if (!behind) continue;
|
|
328
|
+
throw new Error(
|
|
329
|
+
`recipe-set: \`${ref}\` is SHADOWED — it resolved under ${found.root}, a root discovered on ` +
|
|
330
|
+
`this host, while the root ${path.relative(path.resolve(repoRoot), behind.root)} also carries it. ` +
|
|
331
|
+
"A composed recipe's ${PACK_ROOT} expands to whichever root answered, so the two compose to " +
|
|
332
|
+
"run lines pointing at different files. Refusing to pick: name the root — `--pack-root packs` " +
|
|
333
|
+
"for the tree, which is what CI runs, or `--pack-root auto` for the installed copy.",
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
291
338
|
return (ref) => {
|
|
292
339
|
const found = resolvePack(ref, roots);
|
|
293
340
|
// `resolvePack` returns `manifest` as the PATH to `pack.json`, not as the parsed object —
|