muse-crew 0.14.3 → 0.14.5
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/AGENTS.md +2 -2
- package/docs/decisions/AGENTS.md +1 -0
- package/docs/decisions/publish-path.md +96 -3
- package/docs/guide.md +2 -2
- package/docs/publish-unknown-recovery.md +10 -3
- package/docs/publish-verification.md +126 -62
- package/docs/release-integrity.md +62 -0
- package/docs/reviews/critic-0144.md +83 -0
- package/docs/reviews/critic-0145.md +106 -0
- package/lib/AGENTS.md +12 -4
- package/lib/advance-publish-base.js +8 -0
- package/lib/append-ooda-step.js +12 -3
- package/lib/build-readback-request.js +10 -0
- package/lib/build-registry.js +8 -3
- package/lib/check-intent-freshness.js +101 -0
- package/lib/classify-publish-absence.js +11 -0
- package/lib/classify-surface.js +12 -2
- package/lib/commit-scaffold.js +22 -6
- package/lib/compose-evidence-caption.js +15 -4
- package/lib/compute-publish-diff.js +41 -11
- package/lib/crew-api.js +478 -26
- package/lib/crew-release.sh +233 -1
- package/lib/gitignore.js +23 -5
- package/lib/package.json +1 -0
- package/lib/publish-note-vocabulary.js +64 -0
- package/lib/read-ooda-verdict.js +11 -3
- package/lib/readback-disk.js +9 -0
- package/lib/render-html.js +17 -7
- package/lib/repo-orchestration.js +21 -5
- package/lib/retry-publish.js +116 -72
- package/lib/sample-project.js +22 -6
- package/lib/scaffold-crew.js +11 -2
- package/lib/see-act.js +17 -8
- package/lib/serve-artifact.js +12 -6
- package/lib/setup-project-repo.js +26 -7
- package/lib/update-watch.js +34 -17
- package/lib/ux-doctrine.js +31 -6
- package/lib/verify-publish.js +44 -6
- package/lib/write-ooda-verdict.js +12 -3
- package/package.json +1 -1
- package/seed/cron-body-template.md +50 -16
- package/workflows/bugfix.js +110 -643
- package/workflows/chore.js +110 -643
- package/workflows/crew-dispatch.js +36 -0
- package/workflows/standard.js +118 -633
- package/workflows/upgrade.js +4 -2
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// small JSON summary verbatim. The diff bytes live in a file; the LLM
|
|
15
15
|
// never carries them:
|
|
16
16
|
//
|
|
17
|
-
// node compute-publish-diff.js --repo-path <path> --base <sha> --out <file>
|
|
17
|
+
// node compute-publish-diff.js --repo-path <path> --base <sha> --out <file> [--commit <sha>]
|
|
18
18
|
//
|
|
19
19
|
// --base is the previously-stamped provenance source_commit (or the
|
|
20
20
|
// empty-tree sha 4b825dc642cb6eb9a060e54bf8d69288fbee4904 for a first
|
|
@@ -22,6 +22,14 @@
|
|
|
22
22
|
// script echoes the base it used so the workflow can guard against the
|
|
23
23
|
// agent running the wrong command (fail-closed, as before).
|
|
24
24
|
//
|
|
25
|
+
// --commit is the diff's head end (2026-09-20, critic-0145 F-O2): the
|
|
26
|
+
// script used to ignore it and always diff base..HEAD. Optional, defaults
|
|
27
|
+
// to HEAD; the workflow's first-prepare call passes nothing (HEAD is the
|
|
28
|
+
// merge commit it just created), while the tick's byte-identical
|
|
29
|
+
// regeneration passes the intent's commit explicitly. The ancestor check,
|
|
30
|
+
// the diff range, and the reported `commit` all target --commit, never an
|
|
31
|
+
// implicit HEAD.
|
|
32
|
+
//
|
|
25
33
|
// Stdout contract: exactly one JSON object, always small (no diff text):
|
|
26
34
|
// { ok:true, commit, base, ancestor:"yes", diff_file, sha256, bytes,
|
|
27
35
|
// file_count, changed_lines, files:[<paths>], has_binary, has_rename }
|
|
@@ -40,6 +48,15 @@ import { createHash } from "node:crypto";
|
|
|
40
48
|
import { existsSync, mkdirSync, statSync, writeFileSync, readFileSync } from "node:fs";
|
|
41
49
|
import { dirname, resolve } from "node:path";
|
|
42
50
|
|
|
51
|
+
// --help: before required-arg parsing (shebang⇔CLI contract).
|
|
52
|
+
if (process.argv.slice(2).includes("--help")) {
|
|
53
|
+
console.log(
|
|
54
|
+
"usage: node compute-publish-diff.js --repo-path <path> --base <sha> --out <file> [--commit <sha>]\n" +
|
|
55
|
+
"runs git diff <base> <commit> (default <commit> = HEAD), writes the raw diff bytes to --out, prints the small JSON summary on stdout"
|
|
56
|
+
);
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
|
|
43
60
|
const EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
44
61
|
|
|
45
62
|
function arg(name, required = true) {
|
|
@@ -65,36 +82,49 @@ function git(repoPath, args) {
|
|
|
65
82
|
const repoPath = arg("--repo-path");
|
|
66
83
|
const base = arg("--base");
|
|
67
84
|
const outFile = arg("--out");
|
|
85
|
+
const commitArg = arg("--commit", false);
|
|
68
86
|
|
|
69
87
|
if (!/^[0-9a-f]{40}$/.test(base)) fail("usage", "--base must be a 40-char hex commit SHA (or the empty-tree SHA).", 2);
|
|
70
88
|
let st = null;
|
|
71
89
|
try { st = statSync(repoPath); } catch { /* falls through */ }
|
|
72
90
|
if (!st || !st.isDirectory()) fail("usage", "--repo-path must be an existing directory.", 2);
|
|
73
91
|
|
|
74
|
-
|
|
75
|
-
|
|
92
|
+
// The diff's head end: explicit --commit, or HEAD when omitted (the
|
|
93
|
+
// workflow's first-prepare call passes nothing — HEAD is the merge commit
|
|
94
|
+
// it just created). Validated as a 40-hex commit object in this repo;
|
|
95
|
+
// everything below (ancestor check, diff range, reported commit) targets
|
|
96
|
+
// it, never an implicit HEAD (2026-09-20, critic-0145 F-O2).
|
|
97
|
+
let commit;
|
|
98
|
+
if (commitArg === null) {
|
|
99
|
+
commit = git(repoPath, ["rev-parse", "HEAD"]).trim();
|
|
100
|
+
} else {
|
|
101
|
+
if (!/^[0-9a-f]{40}$/.test(commitArg)) fail("usage", "--commit must be a 40-char hex commit SHA.", 2);
|
|
102
|
+
commit = git(repoPath, ["rev-parse", "--verify", commitArg + "^{commit}"]).trim();
|
|
103
|
+
}
|
|
104
|
+
if (!/^[0-9a-f]{40}$/.test(commit)) fail("git-failed", "could not resolve the diff target to a commit SHA.", 1);
|
|
76
105
|
|
|
77
|
-
// Ancestor check — deterministic, in code
|
|
78
|
-
// git merge-base --is-ancestor fails on it, so
|
|
79
|
-
// ANCESTOR=yes here instead of executing the
|
|
80
|
-
// 2026-09-16: an agent ran merge-base on the empty
|
|
106
|
+
// Ancestor check — deterministic, in code, against the diff target. The
|
|
107
|
+
// empty tree is not a commit: git merge-base --is-ancestor fails on it, so
|
|
108
|
+
// a first publish hardcodes ANCESTOR=yes here instead of executing the
|
|
109
|
+
// conditional (clean-room 2026-09-16: an agent ran merge-base on the empty
|
|
110
|
+
// tree directly and parked).
|
|
81
111
|
let ancestor = "yes";
|
|
82
112
|
if (base !== EMPTY_TREE) {
|
|
83
113
|
try {
|
|
84
|
-
execFileSync("git", ["-C", repoPath, "merge-base", "--is-ancestor", base,
|
|
114
|
+
execFileSync("git", ["-C", repoPath, "merge-base", "--is-ancestor", base, commit], { stdio: "ignore" });
|
|
85
115
|
ancestor = "yes";
|
|
86
116
|
} catch {
|
|
87
117
|
ancestor = "no";
|
|
88
118
|
}
|
|
89
119
|
}
|
|
90
120
|
if (ancestor !== "yes") {
|
|
91
|
-
process.stdout.write(JSON.stringify({ ok: false, error: "not-ancestor", commit
|
|
121
|
+
process.stdout.write(JSON.stringify({ ok: false, error: "not-ancestor", commit, base }) + "\n");
|
|
92
122
|
process.exit(0);
|
|
93
123
|
}
|
|
94
124
|
|
|
95
125
|
const outPath = resolve(outFile);
|
|
96
126
|
mkdirSync(dirname(outPath), { recursive: true });
|
|
97
|
-
const diffText = git(repoPath, ["diff", base,
|
|
127
|
+
const diffText = git(repoPath, ["diff", base, commit]);
|
|
98
128
|
writeFileSync(outPath, diffText, "utf8");
|
|
99
129
|
const bytes = readFileSync(outPath);
|
|
100
130
|
const sha256 = createHash("sha256").update(bytes).digest("hex");
|
|
@@ -131,7 +161,7 @@ for (const line of diffText.split("\n")) {
|
|
|
131
161
|
|
|
132
162
|
process.stdout.write(JSON.stringify({
|
|
133
163
|
ok: true,
|
|
134
|
-
commit
|
|
164
|
+
commit,
|
|
135
165
|
base,
|
|
136
166
|
ancestor: "yes",
|
|
137
167
|
diff_file: outPath,
|