@peterxiaoyang/superspec 0.1.14 → 0.1.15-alpha

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 (126) hide show
  1. package/dist/cli.d.ts +2 -0
  2. package/dist/cli.js +302 -0
  3. package/dist/format.d.ts +29 -0
  4. package/dist/format.js +141 -0
  5. package/dist/next.d.ts +3 -0
  6. package/dist/next.js +161 -0
  7. package/dist/openspec.d.ts +9 -0
  8. package/dist/openspec.js +41 -0
  9. package/dist/record.d.ts +20 -0
  10. package/dist/record.js +211 -0
  11. package/dist/skill_loop.d.ts +23 -0
  12. package/dist/skill_loop.js +58 -0
  13. package/dist/store.d.ts +31 -0
  14. package/dist/store.js +213 -0
  15. package/dist/sync.d.ts +3 -0
  16. package/dist/sync.js +135 -0
  17. package/dist/task.d.ts +7 -0
  18. package/dist/task.js +44 -0
  19. package/dist/transition.d.ts +34 -0
  20. package/dist/transition.js +400 -0
  21. package/dist/types.d.ts +138 -0
  22. package/dist/types.js +3 -0
  23. package/package.json +8 -53
  24. package/templates/workflow/skills/superspec-apply/SKILL.md +46 -118
  25. package/templates/workflow/skills/superspec-archive/SKILL.md +22 -47
  26. package/templates/workflow/skills/superspec-explore/SKILL.md +38 -69
  27. package/templates/workflow/skills/superspec-propose/SKILL.md +58 -60
  28. package/templates/workflow/skills/superspec-review/SKILL.md +36 -81
  29. package/adapters/codex/agents/architect.toml +0 -13
  30. package/adapters/codex/agents/code-reviewer.toml +0 -13
  31. package/adapters/codex/agents/critic.toml +0 -13
  32. package/adapters/codex/agents/executor.toml +0 -13
  33. package/adapters/codex/agents/explore.toml +0 -13
  34. package/adapters/codex/agents/test-engineer.toml +0 -13
  35. package/adapters/codex/agents/test-runner.toml +0 -13
  36. package/adapters/codex/agents/verifier.toml +0 -13
  37. package/adapters/codex/install-map.json +0 -116
  38. package/bin/launch.js +0 -37
  39. package/bin/superspec-check.js +0 -4
  40. package/bin/superspec-hook.js +0 -4
  41. package/bin/superspec-init.js +0 -4
  42. package/bin/superspec.js +0 -4
  43. package/dist/src/apply_worker_chain.d.ts +0 -60
  44. package/dist/src/apply_worker_chain.js +0 -1283
  45. package/dist/src/apply_worker_chain_lifecycle.d.ts +0 -21
  46. package/dist/src/apply_worker_chain_lifecycle.js +0 -409
  47. package/dist/src/archive.d.ts +0 -23
  48. package/dist/src/archive.js +0 -430
  49. package/dist/src/cli.d.ts +0 -1
  50. package/dist/src/cli.js +0 -33
  51. package/dist/src/cli_args.d.ts +0 -32
  52. package/dist/src/cli_args.js +0 -454
  53. package/dist/src/core.d.ts +0 -20
  54. package/dist/src/core.js +0 -394
  55. package/dist/src/disclosure.d.ts +0 -35
  56. package/dist/src/disclosure.js +0 -671
  57. package/dist/src/doctor.d.ts +0 -44
  58. package/dist/src/doctor.js +0 -230
  59. package/dist/src/evidence.d.ts +0 -29
  60. package/dist/src/evidence.js +0 -1107
  61. package/dist/src/gates.d.ts +0 -19
  62. package/dist/src/gates.js +0 -1631
  63. package/dist/src/git.d.ts +0 -8
  64. package/dist/src/git.js +0 -112
  65. package/dist/src/hooks/adapter.d.ts +0 -5
  66. package/dist/src/hooks/adapter.js +0 -347
  67. package/dist/src/hooks/guard_api.d.ts +0 -12
  68. package/dist/src/hooks/guard_api.js +0 -797
  69. package/dist/src/hooks/health.d.ts +0 -4
  70. package/dist/src/hooks/health.js +0 -86
  71. package/dist/src/hooks/policy_event.d.ts +0 -41
  72. package/dist/src/hooks/policy_event.js +0 -2634
  73. package/dist/src/hooks/types.d.ts +0 -72
  74. package/dist/src/hooks/types.js +0 -1
  75. package/dist/src/hooks/validation.d.ts +0 -3
  76. package/dist/src/hooks/validation.js +0 -70
  77. package/dist/src/i18n.d.ts +0 -21
  78. package/dist/src/i18n.js +0 -720
  79. package/dist/src/init_cli.d.ts +0 -28
  80. package/dist/src/init_cli.js +0 -404
  81. package/dist/src/install_engine.d.ts +0 -71
  82. package/dist/src/install_engine.js +0 -538
  83. package/dist/src/invariants.d.ts +0 -16
  84. package/dist/src/invariants.js +0 -363
  85. package/dist/src/openspec.d.ts +0 -37
  86. package/dist/src/openspec.js +0 -274
  87. package/dist/src/packet_render.d.ts +0 -5
  88. package/dist/src/packet_render.js +0 -1767
  89. package/dist/src/packet_schema.d.ts +0 -59
  90. package/dist/src/packet_schema.js +0 -1
  91. package/dist/src/paths.d.ts +0 -22
  92. package/dist/src/paths.js +0 -203
  93. package/dist/src/project_init.d.ts +0 -33
  94. package/dist/src/project_init.js +0 -191
  95. package/dist/src/self_update.d.ts +0 -14
  96. package/dist/src/self_update.js +0 -56
  97. package/dist/src/state.d.ts +0 -37
  98. package/dist/src/state.js +0 -464
  99. package/dist/src/tasks.d.ts +0 -38
  100. package/dist/src/tasks.js +0 -373
  101. package/dist/src/util.d.ts +0 -163
  102. package/dist/src/util.js +0 -792
  103. package/dist/superspec.d.ts +0 -6
  104. package/dist/superspec.js +0 -97
  105. package/dist/superspec_guard.d.ts +0 -4
  106. package/dist/superspec_guard.js +0 -19
  107. package/dist/superspec_hook.d.ts +0 -4
  108. package/dist/superspec_hook.js +0 -35
  109. package/dist/superspec_init.d.ts +0 -2
  110. package/dist/superspec_init.js +0 -17
  111. package/schemas/hook-event.schema.json +0 -27
  112. package/schemas/install-manifest.schema.json +0 -97
  113. package/templates/hooks/codex-hooks.json +0 -35
  114. package/templates/sidecar/archive-preservation.json +0 -11
  115. package/templates/sidecar/business-invariants.md +0 -38
  116. package/templates/sidecar/config.yaml +0 -13
  117. package/templates/sidecar/discovery.md +0 -33
  118. package/templates/sidecar/test-contract.md +0 -27
  119. package/templates/workflow/prompts/architect.md +0 -27
  120. package/templates/workflow/prompts/code-reviewer.md +0 -34
  121. package/templates/workflow/prompts/critic.md +0 -30
  122. package/templates/workflow/prompts/executor.md +0 -32
  123. package/templates/workflow/prompts/explore.md +0 -27
  124. package/templates/workflow/prompts/test-engineer.md +0 -28
  125. package/templates/workflow/prompts/test-runner.md +0 -35
  126. package/templates/workflow/prompts/verifier.md +0 -35
@@ -1,430 +0,0 @@
1
- import { closeSync, copyFileSync, existsSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
2
- import { dirname, join, relative } from "node:path";
3
- import { STATE_LOCK_FILENAME, allow, block, now, reason, renderList, repr, runtime, safe_within, sha256_file, sha256_text, toPosix, walkFiles, } from "./util.js";
4
- import { ensure_state_layout, sidecar_artifacts_dir, superspec_dir } from "./paths.js";
5
- export function archive_manifest_path(changeRoot) {
6
- return join(sidecar_artifacts_dir(changeRoot), "archive-preservation.json");
7
- }
8
- export function archive_preservation_dir(changeRoot) {
9
- return join(changeRoot, "superspec-preservation");
10
- }
11
- export function archive_preservation_manifest_path(changeRoot) {
12
- return join(archive_preservation_dir(changeRoot), "manifest.json");
13
- }
14
- function archive_staging_root(changeRoot, runId) {
15
- return join(changeRoot, ".superspec-staging", runId);
16
- }
17
- function fsync_dir_best_effort(dirPath) {
18
- let fd = null;
19
- try {
20
- fd = openSync(dirPath, "r");
21
- fsyncSync(fd);
22
- }
23
- catch {
24
- // Directory fsync is best-effort across platforms.
25
- }
26
- finally {
27
- if (fd !== null)
28
- closeSync(fd);
29
- }
30
- }
31
- function write_text(path, text) {
32
- mkdirSync(dirname(path), { recursive: true });
33
- writeFileSync(path, text, "utf8");
34
- }
35
- function excluded_manifest_entry(relPath) {
36
- if (relPath.endsWith(STATE_LOCK_FILENAME) || relPath.endsWith("superspec-state.tmp"))
37
- return true;
38
- if (relPath === ".superspec/hook-runtime" || relPath.startsWith(".superspec/hook-runtime/"))
39
- return true;
40
- if (relPath === ".superspec/artifacts/archive-preservation.json")
41
- return true;
42
- return false;
43
- }
44
- function manifest_entries(changeRoot, fileOverrides = {}) {
45
- const base = superspec_dir(changeRoot);
46
- const entries = [];
47
- const pendingOverrides = new Set(Object.keys(fileOverrides));
48
- if (existsSync(base) && statSync(base).isDirectory()) {
49
- for (const filePath of walkFiles(base).sort()) {
50
- const relPath = toPosix(relative(changeRoot, filePath));
51
- if (excluded_manifest_entry(relPath))
52
- continue;
53
- if (pendingOverrides.has(relPath)) {
54
- entries.push({ path: relPath, sha256: sha256_text(fileOverrides[relPath]) });
55
- pendingOverrides.delete(relPath);
56
- }
57
- else {
58
- entries.push({ path: relPath, sha256: sha256_file(filePath) });
59
- }
60
- }
61
- }
62
- for (const relPath of [...pendingOverrides].sort()) {
63
- if (excluded_manifest_entry(relPath))
64
- continue;
65
- entries.push({ path: relPath, sha256: sha256_text(fileOverrides[relPath]) });
66
- }
67
- return entries.sort((a, b) => String(a.path).localeCompare(String(b.path)));
68
- }
69
- export function sidecar_manifest_entries(changeRoot) {
70
- return manifest_entries(changeRoot);
71
- }
72
- function archive_manifest_data(change, changeRoot, fileOverrides = {}) {
73
- ensure_state_layout(changeRoot);
74
- return {
75
- schema_version: 1,
76
- change_id: change,
77
- created_at: now(),
78
- kind: "superspec_archive_preservation",
79
- entries: manifest_entries(changeRoot, fileOverrides),
80
- };
81
- }
82
- function write_manifest_file(filePath, manifest) {
83
- write_text(filePath, `${JSON.stringify(manifest, null, 2)}\n`);
84
- return filePath;
85
- }
86
- export function write_archive_manifest(change, changeRoot) {
87
- return write_manifest_file(archive_manifest_path(changeRoot), archive_manifest_data(change, changeRoot));
88
- }
89
- function stage_archive_bundle(change, changeRoot, runId, fileOverrides) {
90
- const stagingRoot = archive_staging_root(changeRoot, runId);
91
- const stagedManifestPath = join(stagingRoot, "next", "archive-preservation.json");
92
- const stagedBundleDir = join(stagingRoot, "next", "superspec-preservation");
93
- const stagedFilesRoot = join(stagedBundleDir, "files");
94
- const manifest = archive_manifest_data(change, changeRoot, fileOverrides);
95
- write_manifest_file(stagedManifestPath, manifest);
96
- for (const entry of manifest.entries ?? []) {
97
- const relPath = entry.path;
98
- if (typeof relPath !== "string")
99
- continue;
100
- const dst = join(stagedFilesRoot, relPath);
101
- if (relPath in fileOverrides) {
102
- write_text(dst, fileOverrides[relPath]);
103
- continue;
104
- }
105
- const src = join(changeRoot, relPath);
106
- if (!existsSync(src) || !statSync(src).isFile())
107
- continue;
108
- mkdirSync(dirname(dst), { recursive: true });
109
- copyFileSync(src, dst);
110
- }
111
- const bundleManifest = {
112
- ...manifest,
113
- kind: "superspec_archive_preservation_bundle",
114
- source_manifest: ".superspec/artifacts/archive-preservation.json",
115
- files_root: "files",
116
- };
117
- const stagedBundleManifestPath = join(stagedBundleDir, "manifest.json");
118
- write_text(stagedBundleManifestPath, `${JSON.stringify(bundleManifest, null, 2)}\n`);
119
- return { staged_manifest_path: stagedManifestPath, staged_bundle_dir: stagedBundleDir };
120
- }
121
- function restore_file_from_backup(finalPath, backupPath, hadFinal) {
122
- if (existsSync(backupPath)) {
123
- if (existsSync(finalPath))
124
- rmSync(finalPath, { force: true });
125
- mkdirSync(dirname(finalPath), { recursive: true });
126
- renameSync(backupPath, finalPath);
127
- }
128
- else if (!hadFinal) {
129
- if (existsSync(finalPath))
130
- rmSync(finalPath, { force: true });
131
- }
132
- else {
133
- throw new Error(`backup missing for ${finalPath}`);
134
- }
135
- }
136
- function restore_dir_from_backup(finalPath, backupPath, hadFinal) {
137
- if (existsSync(backupPath)) {
138
- if (existsSync(finalPath))
139
- rmSync(finalPath, { recursive: true, force: true });
140
- renameSync(backupPath, finalPath);
141
- }
142
- else if (!hadFinal) {
143
- if (existsSync(finalPath))
144
- rmSync(finalPath, { recursive: true, force: true });
145
- }
146
- else {
147
- throw new Error(`backup missing for ${finalPath}`);
148
- }
149
- }
150
- function restore_promoted_bundle(state) {
151
- restore_file_from_backup(state.final_manifest, state.backup_manifest, state.had_final_manifest);
152
- restore_dir_from_backup(state.final_bundle_dir, state.backup_bundle_dir, state.had_final_bundle);
153
- }
154
- function promote_archive_bundle(changeRoot, runId, stagedManifestPath, stagedBundleDir) {
155
- const finalManifest = archive_manifest_path(changeRoot);
156
- const finalBundleDir = archive_preservation_dir(changeRoot);
157
- const stagingRoot = archive_staging_root(changeRoot, runId);
158
- const backupRoot = join(stagingRoot, "backup");
159
- const backupManifest = join(backupRoot, "archive-preservation.json");
160
- const backupBundleDir = join(backupRoot, "superspec-preservation");
161
- const hadFinalManifest = existsSync(finalManifest);
162
- const hadFinalBundle = existsSync(finalBundleDir);
163
- const state = {
164
- staging_root: stagingRoot,
165
- final_manifest: finalManifest,
166
- final_bundle_dir: finalBundleDir,
167
- backup_manifest: backupManifest,
168
- backup_bundle_dir: backupBundleDir,
169
- had_final_manifest: hadFinalManifest,
170
- had_final_bundle: hadFinalBundle,
171
- };
172
- mkdirSync(backupRoot, { recursive: true });
173
- try {
174
- if (hadFinalBundle) {
175
- renameSync(finalBundleDir, backupBundleDir);
176
- fsync_dir_best_effort(changeRoot);
177
- }
178
- if (hadFinalManifest) {
179
- mkdirSync(dirname(backupManifest), { recursive: true });
180
- renameSync(finalManifest, backupManifest);
181
- fsync_dir_best_effort(dirname(finalManifest));
182
- }
183
- renameSync(stagedBundleDir, finalBundleDir);
184
- fsync_dir_best_effort(changeRoot);
185
- if (typeof runtime.after_archive_bundle_promote === "function") {
186
- runtime.after_archive_bundle_promote({
187
- change_root: changeRoot,
188
- final_bundle_dir: finalBundleDir,
189
- final_manifest: finalManifest,
190
- });
191
- }
192
- mkdirSync(dirname(finalManifest), { recursive: true });
193
- renameSync(stagedManifestPath, finalManifest);
194
- fsync_dir_best_effort(dirname(finalManifest));
195
- return state;
196
- }
197
- catch (err) {
198
- try {
199
- restore_promoted_bundle(state);
200
- rmSync(stagingRoot, { recursive: true, force: true });
201
- }
202
- catch (restoreErr) {
203
- throw new Error(`archive preservation promote failed: ${err.message}; rollback failed: ${restoreErr.message}`);
204
- }
205
- throw err;
206
- }
207
- }
208
- export function begin_archive_preservation_bundle(change, changeRoot, opts = {}) {
209
- const runId = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
210
- const staged = stage_archive_bundle(change, changeRoot, runId, opts.file_overrides ?? {});
211
- const promotion = promote_archive_bundle(changeRoot, runId, staged.staged_manifest_path, staged.staged_bundle_dir);
212
- let settled = false;
213
- return {
214
- manifest_path: archive_manifest_path(changeRoot),
215
- bundle_manifest_path: archive_preservation_manifest_path(changeRoot),
216
- commit: () => {
217
- if (settled)
218
- return;
219
- settled = true;
220
- try {
221
- rmSync(promotion.staging_root, { recursive: true, force: true });
222
- }
223
- catch {
224
- // Commit is already durable; staging cleanup is best-effort.
225
- }
226
- },
227
- rollback: () => {
228
- if (settled)
229
- return;
230
- restore_promoted_bundle(promotion);
231
- rmSync(promotion.staging_root, { recursive: true, force: true });
232
- settled = true;
233
- },
234
- };
235
- }
236
- export function write_archive_preservation_bundle(change, changeRoot, opts = {}) {
237
- const txn = begin_archive_preservation_bundle(change, changeRoot, opts);
238
- txn.commit();
239
- return txn.bundle_manifest_path;
240
- }
241
- export function find_archived_change(repoRoot, change) {
242
- const archiveRoot = join(repoRoot, "openspec", "changes", "archive");
243
- if (!existsSync(archiveRoot) || !lstatSync(archiveRoot).isDirectory())
244
- return null;
245
- const candidates = readdirSync(archiveRoot)
246
- .filter((name) => name === change || (/^\d{4}-\d{2}-\d{2}-.+/.test(name) && name.slice(11) === change))
247
- .map((name) => join(archiveRoot, name))
248
- .filter((item) => {
249
- const stat = lstatSync(item);
250
- return !stat.isSymbolicLink() && stat.isDirectory();
251
- })
252
- .sort();
253
- return candidates.at(-1) ?? null;
254
- }
255
- function manifest_change_id_reasons(change, manifest, label) {
256
- if (manifest.change_id !== change) {
257
- return [reason("archive_manifest_mismatch", `${label} manifest change_id=${repr(manifest.change_id)} does not match ${repr(change)}`)];
258
- }
259
- return [];
260
- }
261
- const PRIMARY_ARCHIVE_MANIFEST_KIND = "superspec_archive_preservation";
262
- const FALLBACK_ARCHIVE_MANIFEST_KIND = "superspec_archive_preservation_bundle";
263
- const REQUIRED_ARCHIVE_ENTRIES = [".superspec/ledger.jsonl", ".superspec/superspec-state.json"];
264
- function manifest_shape_reasons(change, manifest, label, expectedKind) {
265
- const reasons = manifest_change_id_reasons(change, manifest, label);
266
- if (manifest.kind !== expectedKind) {
267
- reasons.push(reason("archive_manifest_mismatch", `${label} manifest kind=${repr(manifest.kind)} does not match ${repr(expectedKind)}`));
268
- }
269
- if (!Array.isArray(manifest.entries) || manifest.entries.length === 0) {
270
- reasons.push(reason("archive_manifest_mismatch", `${label} manifest entries must be a non-empty list`));
271
- return reasons;
272
- }
273
- const paths = new Set();
274
- for (const entry of manifest.entries) {
275
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
276
- reasons.push(reason("archive_manifest_mismatch", `${label} manifest entries must be objects`));
277
- continue;
278
- }
279
- if (typeof entry.path === "string")
280
- paths.add(entry.path);
281
- }
282
- const missingRequired = REQUIRED_ARCHIVE_ENTRIES.filter((entry) => !paths.has(entry));
283
- if (missingRequired.length > 0) {
284
- reasons.push(reason("archive_manifest_mismatch", `${label} manifest missing required entries: ${renderList([...missingRequired])}`, [...missingRequired]));
285
- }
286
- return reasons;
287
- }
288
- function manifest_entry_target(baseRoot, relPath) {
289
- if (!relPath.startsWith(".superspec/"))
290
- return null;
291
- return safe_within(baseRoot, relPath);
292
- }
293
- function preserved_file_sha(filePath) {
294
- if (!existsSync(filePath))
295
- return null;
296
- const stat = lstatSync(filePath);
297
- if (stat.isSymbolicLink() || !stat.isFile() || stat.nlink > 1)
298
- return null;
299
- return sha256_file(filePath);
300
- }
301
- export function check_archived(change, repoRoot) {
302
- const archived = find_archived_change(repoRoot, change);
303
- if (archived === null)
304
- return block(change, "archived", [reason("archive_not_found", `archived change not found for ${change}`)]);
305
- const manifestPath = archive_manifest_path(archived);
306
- if (!existsSync(manifestPath) || !statSync(manifestPath).isFile()) {
307
- const fallbackManifest = archive_preservation_manifest_path(archived);
308
- if (!existsSync(fallbackManifest) || !statSync(fallbackManifest).isFile()) {
309
- return block(change, "archived", [reason("superspec_not_preserved", "archive preservation manifest missing")]);
310
- }
311
- return check_archived_preservation_bundle(change, archived, fallbackManifest);
312
- }
313
- let manifest;
314
- try {
315
- manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
316
- }
317
- catch {
318
- return block(change, "archived", [reason("superspec_not_preserved", "archive preservation manifest is invalid JSON")]);
319
- }
320
- const shapeReasons = manifest_shape_reasons(change, manifest, "archive preservation", PRIMARY_ARCHIVE_MANIFEST_KIND);
321
- if (shapeReasons.length > 0)
322
- return block(change, "archived", shapeReasons);
323
- const missing = [];
324
- const mismatched = [];
325
- const invalid = [];
326
- for (const entry of manifest.entries) {
327
- const relPath = entry.path;
328
- const expected = entry.sha256;
329
- if (typeof relPath !== "string" || typeof expected !== "string") {
330
- mismatched.push(String(relPath));
331
- continue;
332
- }
333
- const filePath = manifest_entry_target(archived, relPath);
334
- if (filePath === null) {
335
- invalid.push(relPath);
336
- continue;
337
- }
338
- const actual = preserved_file_sha(filePath);
339
- if (actual === null)
340
- missing.push(relPath);
341
- else if (actual !== expected)
342
- mismatched.push(relPath);
343
- }
344
- const reasons = [];
345
- if (invalid.length > 0)
346
- reasons.push(reason("archive_manifest_mismatch", `archived .superspec manifest paths are invalid: ${renderList(invalid.slice(0, 20))}`, invalid.slice(0, 20)));
347
- if (missing.length > 0)
348
- reasons.push(reason("superspec_not_preserved", `archived .superspec files missing: ${renderList(missing.slice(0, 20))}`));
349
- if (mismatched.length > 0)
350
- reasons.push(reason("archive_manifest_mismatch", `archived .superspec files changed: ${renderList(mismatched.slice(0, 20))}`));
351
- if (reasons.length > 0)
352
- return block(change, "archived", reasons);
353
- return allow(change, "archived", { gate_summary: { archive_root: archived, manifest_entries: (manifest.entries ?? []).length } });
354
- }
355
- export function check_archived_preservation_bundle(change, archived, manifestPath) {
356
- let manifest;
357
- try {
358
- manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
359
- }
360
- catch {
361
- return block(change, "archived", [reason("superspec_not_preserved", "fallback preservation manifest is invalid JSON")]);
362
- }
363
- const shapeReasons = manifest_shape_reasons(change, manifest, "fallback preservation", FALLBACK_ARCHIVE_MANIFEST_KIND);
364
- if (shapeReasons.length > 0)
365
- return block(change, "archived", shapeReasons);
366
- if (typeof manifest.files_root !== "string" || !manifest.files_root) {
367
- return block(change, "archived", [reason("archive_manifest_mismatch", "fallback preservation manifest requires files_root")]);
368
- }
369
- const filesRoot = safe_within(dirname(manifestPath), manifest.files_root);
370
- if (filesRoot === null || !existsSync(filesRoot) || !lstatSync(filesRoot).isDirectory()) {
371
- return block(change, "archived", [reason("archive_manifest_mismatch", `fallback preservation files_root is invalid: ${repr(manifest.files_root)}`)]);
372
- }
373
- const missing = [];
374
- const mismatched = [];
375
- const invalid = [];
376
- for (const entry of manifest.entries) {
377
- const relPath = entry.path;
378
- const expected = entry.sha256;
379
- if (typeof relPath !== "string" || typeof expected !== "string") {
380
- mismatched.push(String(relPath));
381
- continue;
382
- }
383
- const filePath = manifest_entry_target(filesRoot, relPath);
384
- if (filePath === null) {
385
- invalid.push(relPath);
386
- continue;
387
- }
388
- const actual = preserved_file_sha(filePath);
389
- if (actual === null)
390
- missing.push(relPath);
391
- else if (actual !== expected)
392
- mismatched.push(relPath);
393
- }
394
- const reasons = [];
395
- if (invalid.length > 0)
396
- reasons.push(reason("archive_manifest_mismatch", `fallback .superspec manifest paths are invalid: ${renderList(invalid.slice(0, 20))}`, invalid.slice(0, 20)));
397
- if (missing.length > 0)
398
- reasons.push(reason("superspec_not_preserved", `fallback .superspec files missing: ${renderList(missing.slice(0, 20))}`));
399
- if (mismatched.length > 0)
400
- reasons.push(reason("archive_manifest_mismatch", `fallback .superspec files changed: ${renderList(mismatched.slice(0, 20))}`));
401
- if (reasons.length > 0)
402
- return block(change, "archived", reasons);
403
- return allow(change, "archived", {
404
- gate_summary: {
405
- archive_root: archived,
406
- fallback_manifest: toPosix(relative(archived, manifestPath)),
407
- manifest_entries: (manifest.entries ?? []).length,
408
- },
409
- });
410
- }
411
- export function preset_upgrade_required(preset, changedPaths, flags = {}) {
412
- if (preset === "full")
413
- return false;
414
- if (preset === "hotfix")
415
- return changedPaths.length >= 3 || Boolean(flags.architecture) || Boolean(flags.schema) || Boolean(flags.public_api) || Boolean(flags.cross_module);
416
- if (preset === "tweak")
417
- return changedPaths.length >= 5 || Boolean(flags.cross_module) || Number(flags.new_tests ?? 0) >= 5 || Boolean(flags.config_key_add_remove);
418
- return true;
419
- }
420
- export function preset_upgrade_reasons(config, changedPaths, humanConfirmed = false, flags = {}) {
421
- const preset = String(config.preset ?? "full");
422
- if (!preset_upgrade_required(preset, changedPaths, flags))
423
- return [];
424
- if (humanConfirmed)
425
- return [];
426
- return [reason("preset_upgrade_requires_human_confirmation", `preset ${repr(preset)} must upgrade to full before proceeding`)];
427
- }
428
- export function preset_upgrade_required_from_context(config, changedPaths) {
429
- return preset_upgrade_required(String(config.preset ?? "full"), changedPaths);
430
- }
package/dist/src/cli.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function main(argv?: string[]): number;
package/dist/src/cli.js DELETED
@@ -1,33 +0,0 @@
1
- import { block, dispatch, GuardError, printDecision, reason } from "./core.js";
2
- import { emitArgparsePreamble, parse_argv } from "./cli_args.js";
3
- import { dispatch_packet, is_packet_command } from "./packet_render.js";
4
- import { printPacket, printPacketError } from "./util.js";
5
- export function main(argv = process.argv.slice(2)) {
6
- let args = null;
7
- const rawCommand = argv[0] ?? "";
8
- try {
9
- const argparseExit = emitArgparsePreamble(argv);
10
- if (argparseExit !== null)
11
- return argparseExit;
12
- args = parse_argv(argv);
13
- if (is_packet_command(args.command)) {
14
- const result = dispatch_packet(args);
15
- printPacket(result.payload, { format: result.output_format });
16
- return 0;
17
- }
18
- const [decision] = dispatch(args);
19
- printDecision(decision, { command: args.command, format: args.format });
20
- return decision.allowed ? 0 : 1;
21
- }
22
- catch (err) {
23
- if ((args && is_packet_command(args.command)) || is_packet_command(rawCommand)) {
24
- const errCode = err instanceof GuardError ? "guard_error" : "guard_internal_error";
25
- printPacketError(errCode, `${err.message}`);
26
- return 2;
27
- }
28
- const change = args?.change ?? "?";
29
- const errReason = err instanceof GuardError ? reason("guard_error", err.message) : reason("guard_internal_error", `${err.name}: ${err.message}`);
30
- printDecision(block(change, "guard_error", [errReason]), { command: args?.command, format: args?.format });
31
- return 2;
32
- }
33
- }
@@ -1,32 +0,0 @@
1
- import { type DecisionOutputFormat, type PacketOutputFormat } from "./util.ts";
2
- export type ParsedArgs = {
3
- command: string;
4
- change: string;
5
- format?: DecisionOutputFormat;
6
- packet_format?: PacketOutputFormat;
7
- artifact?: string;
8
- gate?: string;
9
- task_id?: string;
10
- test_id?: string;
11
- phase?: "red" | "characterization" | "green";
12
- event_ref?: string;
13
- workflow?: string;
14
- entrypoint_token?: string;
15
- end_reason?: string;
16
- lifecycle_token?: string;
17
- role?: string;
18
- evidence_kind?: string;
19
- round?: number;
20
- executor_report_refs?: string[];
21
- task_code_review_report_refs?: string[];
22
- apply_worker_chain_refs?: string[];
23
- green_test_run_evidence_refs?: string[];
24
- alternative_verification_evidence_refs?: string[];
25
- red_test_run_evidence_refs?: string[];
26
- characterization_test_run_evidence_refs?: string[];
27
- create?: boolean;
28
- force_unlock?: boolean;
29
- rebuild_corrupt?: boolean;
30
- };
31
- export declare function emitArgparsePreamble(argv: string[]): number | null;
32
- export declare function parse_argv(argv: string[]): ParsedArgs;