@peterxiaoyang/superspec 0.1.0

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 (68) hide show
  1. package/README.md +47 -0
  2. package/adapters/codex/agents/architect.toml +157 -0
  3. package/adapters/codex/agents/code-reviewer.toml +175 -0
  4. package/adapters/codex/agents/critic.toml +114 -0
  5. package/adapters/codex/agents/test-engineer.toml +163 -0
  6. package/adapters/codex/agents/verifier.toml +119 -0
  7. package/adapters/codex/install-map.json +81 -0
  8. package/bin/launch.js +37 -0
  9. package/bin/superspec-guard.js +4 -0
  10. package/bin/superspec-init.js +4 -0
  11. package/bin/superspec.js +4 -0
  12. package/dist/src/archive.d.ts +23 -0
  13. package/dist/src/archive.js +428 -0
  14. package/dist/src/cli.d.ts +1 -0
  15. package/dist/src/cli.js +20 -0
  16. package/dist/src/cli_args.d.ts +12 -0
  17. package/dist/src/cli_args.js +146 -0
  18. package/dist/src/core.d.ts +19 -0
  19. package/dist/src/core.js +357 -0
  20. package/dist/src/disclosure.d.ts +35 -0
  21. package/dist/src/disclosure.js +671 -0
  22. package/dist/src/evidence.d.ts +28 -0
  23. package/dist/src/evidence.js +849 -0
  24. package/dist/src/gates.d.ts +16 -0
  25. package/dist/src/gates.js +1470 -0
  26. package/dist/src/git.d.ts +8 -0
  27. package/dist/src/git.js +112 -0
  28. package/dist/src/init_cli.d.ts +2 -0
  29. package/dist/src/init_cli.js +145 -0
  30. package/dist/src/install_engine.d.ts +54 -0
  31. package/dist/src/install_engine.js +351 -0
  32. package/dist/src/invariants.d.ts +16 -0
  33. package/dist/src/invariants.js +363 -0
  34. package/dist/src/openspec.d.ts +18 -0
  35. package/dist/src/openspec.js +157 -0
  36. package/dist/src/paths.d.ts +22 -0
  37. package/dist/src/paths.js +203 -0
  38. package/dist/src/project_init.d.ts +4 -0
  39. package/dist/src/project_init.js +161 -0
  40. package/dist/src/state.d.ts +37 -0
  41. package/dist/src/state.js +464 -0
  42. package/dist/src/tasks.d.ts +23 -0
  43. package/dist/src/tasks.js +225 -0
  44. package/dist/src/util.d.ts +120 -0
  45. package/dist/src/util.js +442 -0
  46. package/dist/superspec.d.ts +4 -0
  47. package/dist/superspec.js +57 -0
  48. package/dist/superspec_guard.d.ts +4 -0
  49. package/dist/superspec_guard.js +19 -0
  50. package/dist/superspec_init.d.ts +2 -0
  51. package/dist/superspec_init.js +17 -0
  52. package/package.json +63 -0
  53. package/schemas/install-manifest.schema.json +80 -0
  54. package/templates/sidecar/archive-preservation.json +11 -0
  55. package/templates/sidecar/business-invariants.md +38 -0
  56. package/templates/sidecar/config.yaml +13 -0
  57. package/templates/sidecar/discovery.md +24 -0
  58. package/templates/sidecar/test-contract.md +26 -0
  59. package/templates/workflow/prompts/architect.md +113 -0
  60. package/templates/workflow/prompts/code-reviewer.md +141 -0
  61. package/templates/workflow/prompts/critic.md +80 -0
  62. package/templates/workflow/prompts/test-engineer.md +130 -0
  63. package/templates/workflow/prompts/verifier.md +85 -0
  64. package/templates/workflow/skills/superspec-apply/SKILL.md +72 -0
  65. package/templates/workflow/skills/superspec-archive/SKILL.md +41 -0
  66. package/templates/workflow/skills/superspec-explore/SKILL.md +70 -0
  67. package/templates/workflow/skills/superspec-propose/SKILL.md +79 -0
  68. package/templates/workflow/skills/superspec-review/SKILL.md +237 -0
@@ -0,0 +1,357 @@
1
+ #!/usr/bin/env node
2
+ export * from "./util.js";
3
+ export * from "./openspec.js";
4
+ export * from "./paths.js";
5
+ export * from "./disclosure.js";
6
+ export * from "./evidence.js";
7
+ export * from "./tasks.js";
8
+ export * from "./invariants.js";
9
+ export * from "./git.js";
10
+ export * from "./state.js";
11
+ export * from "./archive.js";
12
+ export * from "./gates.js";
13
+ export * from "./install_engine.js";
14
+ import { existsSync, readFileSync, statSync } from "node:fs";
15
+ import { relative } from "node:path";
16
+ import { GuardError, allow, block, deepEqual, reason, runtime, toPosix, trustWarnings } from "./util.js";
17
+ import { artifact_status_map, gate_route_phase, get_change_root, get_repo_root, openspec_status, openspec_status_shape_reasons, openspec_validate, openspec_version, repo_root_from_cwd, } from "./openspec.js";
18
+ import { config_file, load_config, project_config_file } from "./paths.js";
19
+ import { index_evidence, live_pass } from "./evidence.js";
20
+ import { tasks_structure_hash } from "./tasks.js";
21
+ import { dirty_worktree_paths, dirty_worktree_reasons, dirty_write_scope_red_reasons, file_blob_sha, git_lines, review_diff_coverage_reasons, review_diff_paths, } from "./git.js";
22
+ import { append_ledger, load_state, compute_fingerprints, prepare_recomputed_state_write, read_ledger_text, record_supersede_ledger_events, restore_state_snapshot_locked, state_corrupt_reasons, state_file, state_file_corrupt, state_stale_reasons, force_unlock_state, with_state_lock, write_prepared_state_locked, } from "./state.js";
23
+ import { archive_manifest_path, begin_archive_preservation_bundle, check_archived, preset_upgrade_reasons, preset_upgrade_required_from_context, write_archive_preservation_bundle, } from "./archive.js";
24
+ import { check_archive_ready, check_artifact, check_init, check_superspec_gate, check_review_complete, check_review_ready, check_task_complete, check_task_edit, check_task_reopen, check_verify_complete, evidence_schema_guard, superspec_agent_reasons, superspec_workflow_skill_reasons, openspec_cli_capability_reasons, openspec_init_reasons, } from "./gates.js";
25
+ const RETRY_WAIT = new Int32Array(new SharedArrayBuffer(4));
26
+ const DEFAULT_MAX_STATE_WRITE_RETRIES = 5;
27
+ function sleep_ms(ms) {
28
+ Atomics.wait(RETRY_WAIT, 0, 0, ms);
29
+ }
30
+ function is_retryable_state_error(err) {
31
+ return err instanceof GuardError && err.message.startsWith("state_concurrent_update:");
32
+ }
33
+ function max_state_write_retries() {
34
+ const configured = Number(runtime.max_state_write_retries);
35
+ return Number.isInteger(configured) && configured > 0 ? configured : DEFAULT_MAX_STATE_WRITE_RETRIES;
36
+ }
37
+ export function load_context(change) {
38
+ const status = runtime.openspec_status(change);
39
+ const changeRoot = get_change_root(status);
40
+ const repoRoot = get_repo_root(status);
41
+ const evidences = index_evidence(changeRoot);
42
+ return [status, repoRoot, changeRoot, evidences];
43
+ }
44
+ export function cmd_status(change) {
45
+ const [status, repoRoot, changeRoot] = runtime.load_context(change);
46
+ const amap = artifact_status_map(status);
47
+ const st = load_state(changeRoot);
48
+ const [config, configProblems] = load_config(repoRoot, changeRoot);
49
+ const version = openspec_version();
50
+ const dataProblems = [...configProblems, ...openspec_status_shape_reasons(status), ...state_corrupt_reasons(changeRoot)];
51
+ return {
52
+ allowed: dataProblems.length === 0,
53
+ decision: dataProblems.length === 0 ? "status" : "block",
54
+ change_id: change,
55
+ gate: "status",
56
+ openspec_status_summary: amap,
57
+ superspec_gate_summary: {
58
+ state_present: st !== null,
59
+ guard_route_phase: st?.superspec?.guard_route_phase ?? null,
60
+ config_preset: config.preset,
61
+ // FIX-8: surfaced so agents can copy the exact hash into apply_isolation/scope_expansion confirmations.
62
+ tasks_structure_hash: tasks_structure_hash(changeRoot),
63
+ openspec_version: version,
64
+ project_config_present: existsSync(project_config_file(repoRoot)) && statSync(project_config_file(repoRoot)).isFile(),
65
+ change_config_present: existsSync(config_file(changeRoot)) && statSync(config_file(changeRoot)).isFile(),
66
+ },
67
+ block_reasons: dataProblems,
68
+ next_allowed_actions: status.nextSteps ?? [],
69
+ trust_warnings: trustWarnings(),
70
+ };
71
+ }
72
+ function write_guard_state_checked(change, changeRoot, status, route, decision, opts = {}) {
73
+ const expectedInputs = compute_fingerprints(changeRoot, status);
74
+ let finalDecision = decision;
75
+ with_state_lock(changeRoot, () => {
76
+ if (!opts.allow_corrupt_state_rebuild && state_file_corrupt(changeRoot)) {
77
+ finalDecision = block(change, decision.gate ?? "guard_error", state_corrupt_reasons(changeRoot), {
78
+ task_id: decision.task_id,
79
+ openspec_summary: decision.openspec_status_summary,
80
+ next_actions: ["inspect .superspec/superspec-state.json, then rerun recompute --rebuild-corrupt to explicitly rebuild guard-owned state"],
81
+ });
82
+ return;
83
+ }
84
+ const [lockedStatus, , lockedChangeRoot] = runtime.load_context(change);
85
+ const currentInputs = compute_fingerprints(lockedChangeRoot, lockedStatus);
86
+ if (!deepEqual(currentInputs, expectedInputs)) {
87
+ finalDecision = block(change, decision.gate ?? "guard_error", [
88
+ reason("state_concurrent_update", "guard inputs changed between decision and state write; rerun the guard command"),
89
+ ], {
90
+ task_id: decision.task_id,
91
+ openspec_summary: decision.openspec_status_summary,
92
+ next_actions: ["rerun the guard command after the concurrent artifact/evidence change settles"],
93
+ });
94
+ }
95
+ const prepared = prepare_recomputed_state_write(change, lockedChangeRoot, lockedStatus, route, finalDecision.gate, finalDecision, { ...opts, fingerprints: currentInputs });
96
+ write_prepared_state_locked(lockedChangeRoot, prepared);
97
+ });
98
+ return finalDecision;
99
+ }
100
+ export function cmd_init_summary(change, changeRoot, decision) {
101
+ return {
102
+ allowed: Boolean(decision.allowed),
103
+ decision: decision.decision,
104
+ change_id: change,
105
+ gate: "init",
106
+ initialized: Boolean(decision.allowed),
107
+ sidecar: {
108
+ root: ".superspec",
109
+ state: toPosix(relative(changeRoot, state_file(changeRoot))),
110
+ ledger: ".superspec/ledger.jsonl",
111
+ },
112
+ block_reasons: decision.block_reasons ?? [],
113
+ next_allowed_actions: decision.allowed ? ["continue with superspec-explore/propose/apply guard checks"] : decision.next_allowed_actions ?? [],
114
+ };
115
+ }
116
+ function dispatch_once(args) {
117
+ const change = args.change;
118
+ const cmd = args.command;
119
+ if (cmd === "check-archived")
120
+ return [check_archived(change, repo_root_from_cwd()), "archive"];
121
+ const [status, repoRoot, changeRoot, evidences] = runtime.load_context(change);
122
+ if (cmd === "recompute" && args.force_unlock)
123
+ force_unlock_state(changeRoot);
124
+ const rebuildCorrupt = cmd === "recompute" && Boolean(args.rebuild_corrupt);
125
+ const corruptProblems = rebuildCorrupt ? [] : state_corrupt_reasons(changeRoot);
126
+ const [config, configProblems] = load_config(repoRoot, changeRoot);
127
+ const evProblems = evidence_schema_guard(change, changeRoot, repoRoot, evidences);
128
+ const shapeProblems = openspec_status_shape_reasons(status);
129
+ if (cmd === "status")
130
+ return [cmd_status(change), "status"];
131
+ let presetRequired = false;
132
+ let presetProblems = [];
133
+ let staleProblems = [];
134
+ if (cmd !== "recompute") {
135
+ const changedPaths = String(config.preset ?? "full") !== "full" ? runtime.dirty_worktree_paths(repoRoot) : [];
136
+ presetRequired = preset_upgrade_required_from_context(config, changedPaths);
137
+ const presetHumanConfirmed = live_pass(evidences, { gate: "preset_upgrade", kind: "human_confirmation" }).length > 0;
138
+ presetProblems = preset_upgrade_reasons(config, changedPaths, presetHumanConfirmed);
139
+ if (cmd !== "init")
140
+ staleProblems = state_stale_reasons(changeRoot, status);
141
+ }
142
+ let dec;
143
+ let route;
144
+ if (cmd === "init") {
145
+ if (!args.create)
146
+ throw new GuardError("init requires --create");
147
+ dec = check_init(change, status, repoRoot, changeRoot);
148
+ route = "init";
149
+ }
150
+ else if (cmd === "recompute") {
151
+ if (rebuildCorrupt && state_file_corrupt(changeRoot)) {
152
+ append_ledger(changeRoot, {
153
+ change_id: change,
154
+ kind: "state_corrupt_rebuilt",
155
+ note: "corrupt superspec-state.json explicitly rebuilt via recompute --rebuild-corrupt",
156
+ });
157
+ }
158
+ dec = allow(change, "recompute", { openspec_summary: artifact_status_map(status) });
159
+ route = "init";
160
+ }
161
+ else if (cmd === "check-init") {
162
+ dec = check_init(change, status, repoRoot, changeRoot);
163
+ route = "init";
164
+ }
165
+ else if (cmd === "check-artifact") {
166
+ dec = check_artifact(change, status, changeRoot, evidences, args.artifact ?? "");
167
+ route = "propose";
168
+ }
169
+ else if (cmd === "check-enter") {
170
+ dec = check_superspec_gate(change, status, changeRoot, evidences, args.gate ?? "");
171
+ route = gate_route_phase(args.gate ?? "");
172
+ }
173
+ else if (cmd === "check-apply-ready") {
174
+ dec = check_superspec_gate(change, status, changeRoot, evidences, "propose_complete");
175
+ route = "propose";
176
+ }
177
+ else if (cmd === "check-task-edit") {
178
+ dec = check_task_edit(change, status, changeRoot, evidences, args.task_id ?? "");
179
+ route = "apply";
180
+ }
181
+ else if (cmd === "check-task-reopen") {
182
+ dec = check_task_reopen(change, status, changeRoot, evidences, args.task_id ?? "");
183
+ route = "apply";
184
+ }
185
+ else if (cmd === "check-task-complete") {
186
+ dec = check_task_complete(change, status, changeRoot, evidences, args.task_id ?? "");
187
+ route = "apply";
188
+ }
189
+ else if (cmd === "check-review-ready") {
190
+ dec = check_review_ready(change, status, changeRoot, evidences);
191
+ route = "review";
192
+ }
193
+ else if (cmd === "check-review-complete") {
194
+ dec = check_review_complete(change, status, changeRoot, evidences);
195
+ route = "review";
196
+ }
197
+ else if (cmd === "check-verify-ready") {
198
+ dec = check_verify_complete(change, status, changeRoot, evidences);
199
+ route = "review";
200
+ }
201
+ else if (cmd === "check-archive-ready") {
202
+ dec = check_archive_ready(change, status, changeRoot, evidences);
203
+ route = "archive";
204
+ }
205
+ else {
206
+ throw new GuardError(`unknown command: ${cmd}`);
207
+ }
208
+ if (corruptProblems.length > 0) {
209
+ // FIX-1 fail-closed: block on corrupt state and never write over the corrupted file.
210
+ if (dec.allowed) {
211
+ dec = block(change, dec.gate, corruptProblems, {
212
+ task_id: dec.task_id,
213
+ openspec_summary: dec.openspec_status_summary,
214
+ next_actions: ["inspect .superspec/superspec-state.json, then rerun recompute --rebuild-corrupt to explicitly rebuild guard-owned state"],
215
+ });
216
+ }
217
+ else {
218
+ dec.block_reasons.push(...corruptProblems);
219
+ }
220
+ return [cmd === "init" ? cmd_init_summary(change, changeRoot, dec) : dec, route];
221
+ }
222
+ // FIX-6: record observed supersede facts in the ledger before any state write,
223
+ // regardless of whether the decision below allows or blocks.
224
+ record_supersede_ledger_events(change, changeRoot, evidences);
225
+ if (cmd === "check-archive-ready") {
226
+ with_state_lock(changeRoot, () => {
227
+ const [lockedStatus, lockedRepoRoot, lockedChangeRoot, lockedEvidences] = runtime.load_context(change);
228
+ const [lockedConfig, lockedConfigProblems] = load_config(lockedRepoRoot, lockedChangeRoot);
229
+ const lockedEvProblems = evidence_schema_guard(change, lockedChangeRoot, lockedRepoRoot, lockedEvidences);
230
+ const lockedShapeProblems = openspec_status_shape_reasons(lockedStatus);
231
+ const lockedChangedPaths = String(lockedConfig.preset ?? "full") !== "full" ? runtime.dirty_worktree_paths(lockedRepoRoot) : [];
232
+ const lockedPresetRequired = preset_upgrade_required_from_context(lockedConfig, lockedChangedPaths);
233
+ const lockedPresetHumanConfirmed = live_pass(lockedEvidences, { gate: "preset_upgrade", kind: "human_confirmation" }).length > 0;
234
+ const lockedPresetProblems = preset_upgrade_reasons(lockedConfig, lockedChangedPaths, lockedPresetHumanConfirmed);
235
+ const lockedStaleProblems = state_stale_reasons(lockedChangeRoot, lockedStatus);
236
+ const lockedCorruptProblems = state_corrupt_reasons(lockedChangeRoot);
237
+ dec = check_archive_ready(change, lockedStatus, lockedChangeRoot, lockedEvidences);
238
+ // FIX-5: pin decision-time fingerprints so the written computed_from matches what was judged.
239
+ const lockedFps = compute_fingerprints(lockedChangeRoot, lockedStatus);
240
+ const lockedDataProblems = [...lockedShapeProblems, ...lockedConfigProblems, ...lockedEvProblems, ...lockedStaleProblems, ...lockedPresetProblems, ...lockedCorruptProblems];
241
+ if (lockedDataProblems.length > 0) {
242
+ if (dec.allowed)
243
+ dec = block(change, dec.gate, lockedDataProblems, { task_id: dec.task_id, openspec_summary: dec.openspec_status_summary });
244
+ else
245
+ dec.block_reasons.push(...lockedDataProblems);
246
+ }
247
+ // FIX-1 fail-closed: never write state/ledger over a corrupted state file.
248
+ if (lockedCorruptProblems.length > 0)
249
+ return;
250
+ if (!dec.allowed) {
251
+ const blockedPrepared = prepare_recomputed_state_write(change, lockedChangeRoot, lockedStatus, route, dec.gate, dec, {
252
+ config: lockedConfig,
253
+ preset_upgrade_required: lockedPresetRequired,
254
+ fingerprints: lockedFps,
255
+ });
256
+ write_prepared_state_locked(lockedChangeRoot, blockedPrepared);
257
+ return;
258
+ }
259
+ const allowedPrepared = prepare_recomputed_state_write(change, lockedChangeRoot, lockedStatus, route, dec.gate, dec, {
260
+ config: lockedConfig,
261
+ preset_upgrade_required: lockedPresetRequired,
262
+ fingerprints: lockedFps,
263
+ });
264
+ const previousStateText = existsSync(state_file(lockedChangeRoot)) && statSync(state_file(lockedChangeRoot)).isFile()
265
+ ? readFileSync(state_file(lockedChangeRoot), "utf8")
266
+ : null;
267
+ const previousLedgerText = read_ledger_text(lockedChangeRoot);
268
+ const futureLedgerText = `${read_ledger_text(lockedChangeRoot)}${String(allowedPrepared.ledger_line ?? "")}`;
269
+ let txn = null;
270
+ try {
271
+ txn = runtime.begin_archive_preservation_bundle(change, lockedChangeRoot, {
272
+ file_overrides: {
273
+ ".superspec/superspec-state.json": String(allowedPrepared.state_text),
274
+ ".superspec/ledger.jsonl": futureLedgerText,
275
+ },
276
+ });
277
+ if (txn === null)
278
+ throw new Error("archive preservation transaction missing");
279
+ const activeTxn = txn;
280
+ dec.superspec_gate_summary.archive_manifest = toPosix(relative(lockedChangeRoot, activeTxn.manifest_path));
281
+ dec.superspec_gate_summary.archive_preservation_bundle = toPosix(relative(lockedChangeRoot, activeTxn.bundle_manifest_path));
282
+ write_prepared_state_locked(lockedChangeRoot, allowedPrepared);
283
+ activeTxn.commit();
284
+ }
285
+ catch (err) {
286
+ if (txn !== null) {
287
+ try {
288
+ txn.rollback();
289
+ restore_state_snapshot_locked(lockedChangeRoot, { state_text: previousStateText, ledger_text: previousLedgerText });
290
+ }
291
+ catch (rollbackErr) {
292
+ throw new Error(`archive preservation bundle/state commit failed: ${err.message}; rollback failed: ${rollbackErr.message}`);
293
+ }
294
+ }
295
+ dec = block(change, "archive_ready", [reason("missing_archive_preservation_plan", `archive preservation manifest/bundle could not be written: ${err.message}`)], {
296
+ next_actions: ["fix archive preservation filesystem/materialization failure, then rerun check-archive-ready before openspec archive -y"],
297
+ });
298
+ const blockedPrepared = prepare_recomputed_state_write(change, lockedChangeRoot, lockedStatus, route, dec.gate, dec, {
299
+ config: lockedConfig,
300
+ preset_upgrade_required: lockedPresetRequired,
301
+ fingerprints: lockedFps,
302
+ });
303
+ write_prepared_state_locked(lockedChangeRoot, blockedPrepared);
304
+ }
305
+ });
306
+ return [dec, route];
307
+ }
308
+ const dataProblems = [...shapeProblems, ...configProblems, ...evProblems, ...staleProblems, ...presetProblems];
309
+ if (dataProblems.length > 0) {
310
+ if (dec.allowed)
311
+ dec = block(change, dec.gate, dataProblems, { task_id: dec.task_id, openspec_summary: dec.openspec_status_summary });
312
+ else
313
+ dec.block_reasons.push(...dataProblems);
314
+ }
315
+ dec = write_guard_state_checked(change, changeRoot, status, route, dec, { config, preset_upgrade_required: presetRequired, allow_corrupt_state_rebuild: rebuildCorrupt });
316
+ if (cmd === "init")
317
+ return [cmd_init_summary(change, changeRoot, dec), route];
318
+ return [dec, route];
319
+ }
320
+ export function dispatch(args) {
321
+ const retryLimit = max_state_write_retries();
322
+ for (let attempt = 0; attempt < retryLimit; attempt++) {
323
+ try {
324
+ return dispatch_once(args);
325
+ }
326
+ catch (err) {
327
+ if (!is_retryable_state_error(err) || attempt === retryLimit - 1)
328
+ throw err;
329
+ if (typeof runtime.on_state_retry === "function") {
330
+ runtime.on_state_retry({
331
+ attempt: attempt + 1,
332
+ error: String(err?.message ?? err),
333
+ });
334
+ }
335
+ sleep_ms(50 * (attempt + 1));
336
+ }
337
+ }
338
+ throw new GuardError("state_concurrent_update: retry budget exhausted");
339
+ }
340
+ Object.assign(runtime, {
341
+ openspec_status,
342
+ openspec_validate,
343
+ openspec_cli_capability_reasons,
344
+ openspec_init_reasons,
345
+ superspec_agent_reasons,
346
+ superspec_workflow_skill_reasons,
347
+ file_blob_sha,
348
+ git_lines,
349
+ dirty_worktree_paths,
350
+ dirty_worktree_reasons,
351
+ dirty_write_scope_red_reasons,
352
+ review_diff_paths,
353
+ review_diff_coverage_reasons,
354
+ begin_archive_preservation_bundle,
355
+ write_archive_preservation_bundle,
356
+ load_context,
357
+ });
@@ -0,0 +1,35 @@
1
+ import type { JsonMap, Reason } from "./util.ts";
2
+ export declare const REVIEW_TARGETS_BY_GATE: Record<string, string[]>;
3
+ export declare const DISCLOSURE_REQUIRED_GATES: Set<string>;
4
+ export declare const DISCLOSURE_ROUTES: Set<string>;
5
+ export declare const DISCLOSURE_ROUTES_BY_GATE: Record<string, Set<string>>;
6
+ export declare const MATERIAL_CATEGORIES: Set<string>;
7
+ export declare const FINDING_CATEGORIES: Set<string>;
8
+ export declare const FINDING_TYPES: Set<string>;
9
+ export declare const FINDING_DISPOSITIONS: Set<string>;
10
+ export declare const USER_DECISION_OPTIONS: Set<string>;
11
+ export declare const REVIEW_ROUND_BUDGET = 3;
12
+ export declare function review_round_number(gate: string, roundId: string): number | null;
13
+ export declare function enumerate_review_targets(gate: string, changeRoot: string): Map<string, string> | null;
14
+ export declare function findings_schema_reasons(ev: JsonMap): Reason[];
15
+ export declare function review_digest_schema_reasons(ev: JsonMap): Reason[];
16
+ export declare function user_decision_schema_reasons(ev: JsonMap): Reason[];
17
+ export declare function standing_authorization_schema_reasons(ev: JsonMap): Reason[];
18
+ export type LedgerEntry = {
19
+ uid: string;
20
+ finding_id: string;
21
+ origin: string;
22
+ round: number;
23
+ finding_type: string;
24
+ category: string;
25
+ material: string[];
26
+ scope_key: string;
27
+ summary: string;
28
+ mandatory: boolean;
29
+ superseded_by: string | null;
30
+ disposition: JsonMap | null;
31
+ disposition_round: number;
32
+ };
33
+ export declare function build_finding_ledger(gate: string, evidences: JsonMap[], beforeRound?: number): LedgerEntry[];
34
+ export declare function render_finding_ledger(gate: string, entries: LedgerEntry[]): string;
35
+ export declare function review_disclosure_reasons(gate: string, changeRoot: string, evidences: JsonMap[]): Reason[];