@peterxiaoyang/superspec 0.1.13 → 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 -57
  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 -399
  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 -1759
  89. package/dist/src/packet_schema.d.ts +0 -58
  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 -31
  94. package/dist/src/project_init.js +0 -167
  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,21 +0,0 @@
1
- import type { JsonMap, Reason } from "./util.ts";
2
- export type TakeoverBaseline = {
3
- fingerprint: unknown;
4
- successorGreenRefs: string[];
5
- };
6
- export type ApplyWorkerChainLifecycleState = {
7
- completionReasons: Reason[];
8
- packetBlockers: Reason[];
9
- activeBlockingReasons: Reason[];
10
- activePresence: "none" | "single_open" | "blocked";
11
- active: JsonMap | null;
12
- openActiveChainIds: Set<string>;
13
- validTerminalChainIds: Set<string>;
14
- validClosedChainIds: Set<string>;
15
- validClosedGreenEvidenceIds: Set<string>;
16
- validClosedAlternativeEvidenceIds: Set<string>;
17
- validClosedAlternativeChainIds: Set<string>;
18
- takeoverbaselines: TakeoverBaseline[];
19
- };
20
- export declare function apply_worker_chain_lifecycle_state(repoRoot: string, changeRoot: string, evidences: JsonMap[], taskId: string): ApplyWorkerChainLifecycleState;
21
- export declare function apply_worker_chain_lifecycle_reasons(repoRoot: string, changeRoot: string, evidences: JsonMap[], taskId: string): Reason[];
@@ -1,409 +0,0 @@
1
- import { NO_TDD_REASONS, isObject, reason, renderList, repr } from "./util.js";
2
- import { find_pass, live_pass, live_user_confirmations } from "./evidence.js";
3
- import { effective_superseded_ids } from "./openspec.js";
4
- import { apply_worker_implementation_fingerprint, apply_worker_executor_input_ref_digest, compute_apply_worker_freshness, fingerprint_matches, pinned_artifact_ref_reasons as shared_pinned_artifact_ref_reasons, pre_edit_evidence_ref_reasons, read_pinned_artifact_json, worker_input_ref_digest, worker_test_run_reasons, } from "./apply_worker_chain.js";
5
- function pinned_artifact_ref_matches(changeRoot, refItem, role, taskId, chainId, kind = "worker_report") {
6
- return shared_pinned_artifact_ref_reasons(changeRoot, refItem, `${role}_ref`, { kind, role, taskId, chainId }).length === 0;
7
- }
8
- function executor_worker_test_run_refs_valid(changeRoot, ev, taskId, chainId) {
9
- return worker_test_run_reasons(changeRoot, ev, taskId, chainId).length === 0;
10
- }
11
- function report_origin_matches(refItem, expected) {
12
- return isObject(refItem) && typeof expected === "string" && refItem.origin_packet_fingerprint === expected;
13
- }
14
- function report_input_refs_match(refItem, refs) {
15
- return isObject(refItem) && refItem.input_ref_digest === worker_input_ref_digest(refs);
16
- }
17
- function report_input_digest_matches(refItem, expectedDigest) {
18
- return isObject(refItem) && refItem.input_ref_digest === expectedDigest;
19
- }
20
- function chain_green_ids(ev) {
21
- if (Array.isArray(ev.green_test_run_evidence_refs)) {
22
- return ev.green_test_run_evidence_refs.map(String).filter(Boolean).sort();
23
- }
24
- const greenId = isObject(ev.green_test_run_evidence_ref)
25
- ? String(ev.green_test_run_evidence_ref.evidence_id ?? "")
26
- : String(ev.green_test_run_evidence_ref ?? "");
27
- return greenId ? [greenId] : [];
28
- }
29
- function chain_alternative_ids(ev) {
30
- const refs = new Set();
31
- if (Array.isArray(ev.alternative_verification_evidence_refs)) {
32
- for (const item of ev.alternative_verification_evidence_refs) {
33
- if (isObject(item) && typeof item.evidence_id === "string" && item.evidence_id)
34
- refs.add(item.evidence_id);
35
- else if (typeof item === "string" && item)
36
- refs.add(item);
37
- }
38
- }
39
- const single = ev.alternative_verification_evidence_ref;
40
- if (isObject(single) && typeof single.evidence_id === "string" && single.evidence_id)
41
- refs.add(single.evidence_id);
42
- else if (typeof single === "string" && single)
43
- refs.add(single);
44
- return [...refs].sort();
45
- }
46
- function active_pre_edit_input_refs(evidences, active) {
47
- const preIds = Array.isArray(active.pre_edit_evidence_refs) ? active.pre_edit_evidence_refs.map(String) : [];
48
- return preIds.map((evidenceId) => {
49
- const ev = live_pass(evidences, { kind: "test_run" }).find((item) => String(item.evidence_id ?? "") === evidenceId);
50
- return ev
51
- ? { kind: "test_run", evidence_id: evidenceId, phase: ev.phase, semantic_status: ev.semantic_status }
52
- : { kind: "test_run", evidence_id: evidenceId };
53
- });
54
- }
55
- function active_chain_verifier_input_ref(active) {
56
- const result = {
57
- kind: "apply_worker_chain",
58
- evidence_id: active.evidence_id,
59
- task_id: active.task_id,
60
- apply_worker_chain_id: active.apply_worker_chain_id,
61
- pre_edit_proof_kind: active.pre_edit_proof_kind ?? "red_or_characterization",
62
- pre_edit_evidence_refs: Array.isArray(active.pre_edit_evidence_refs) ? active.pre_edit_evidence_refs.map(String).filter(Boolean).sort() : [],
63
- };
64
- for (const field of ["apply_execution_surface", "tdd_required", "no_tdd_reason"]) {
65
- if (active[field] !== undefined)
66
- result[field] = active[field];
67
- }
68
- return result;
69
- }
70
- function active_no_tdd_declared_valid(active) {
71
- const preIds = Array.isArray(active.pre_edit_evidence_refs) ? active.pre_edit_evidence_refs.map(String).filter(Boolean) : [];
72
- return active.pre_edit_proof_kind === "no_tdd_declared"
73
- && preIds.length === 0
74
- && active.tdd_required === false
75
- && (active.apply_execution_surface === "implementation" || active.apply_execution_surface === "runtime_config")
76
- && NO_TDD_REASONS.has(String(active.no_tdd_reason ?? ""));
77
- }
78
- function alternative_evidence_input_ref(ev) {
79
- return {
80
- kind: ev.kind,
81
- evidence_id: ev.evidence_id,
82
- gate: ev.gate,
83
- task_id: ev.task_id,
84
- };
85
- }
86
- function closed_apply_worker_chain_valid(repoRoot, changeRoot, ev, evidences, taskId, chainId) {
87
- const active = live_pass(evidences, { gate: "task_complete", kind: "apply_worker_chain", task_id: taskId })
88
- .find((item) => item.chain_state === "active" && item.apply_worker_chain_id === chainId);
89
- if (!active)
90
- return false;
91
- if (!pinned_artifact_ref_matches(changeRoot, ev.executor_report_ref, "executor", taskId, chainId))
92
- return false;
93
- if (!pinned_artifact_ref_matches(changeRoot, ev.task_code_review_report_ref, "code-reviewer", taskId, chainId))
94
- return false;
95
- if (!pinned_artifact_ref_matches(changeRoot, ev.verifier_report_ref, "verifier", taskId, chainId))
96
- return false;
97
- if (!report_origin_matches(ev.executor_report_ref, active.executor_packet_fingerprint))
98
- return false;
99
- if (!report_input_digest_matches(ev.executor_report_ref, apply_worker_executor_input_ref_digest(evidences, active)))
100
- return false;
101
- if (!report_input_refs_match(ev.task_code_review_report_ref, [ev.executor_report_ref]))
102
- return false;
103
- if (typeof ev.observed_freshness_fingerprint !== "string" && !(isObject(ev.observed_freshness_fingerprint) && typeof ev.observed_freshness_fingerprint.fingerprint_digest === "string"))
104
- return false;
105
- const verifierReport = read_pinned_artifact_json(changeRoot, ev.verifier_report_ref);
106
- const verifierObserved = verifierReport?.observed_freshness_fingerprint ?? (isObject(ev.verifier_report_ref) ? ev.verifier_report_ref.observed_freshness_fingerprint : undefined);
107
- if (!fingerprint_matches(verifierObserved, ev.observed_freshness_fingerprint))
108
- return false;
109
- const completionProofKind = String(ev.completion_proof_kind ?? "green_tests");
110
- if (completionProofKind !== "green_tests" && completionProofKind !== "alternative_verification")
111
- return false;
112
- const preEditProofKind = String(active.pre_edit_proof_kind ?? "red_or_characterization");
113
- if (completionProofKind === "green_tests" && preEditProofKind !== "red_or_characterization")
114
- return false;
115
- if (completionProofKind === "alternative_verification" && !active_no_tdd_declared_valid(active))
116
- return false;
117
- if (pre_edit_evidence_ref_reasons(changeRoot, evidences, active, taskId).length > 0)
118
- return false;
119
- if (completionProofKind === "alternative_verification") {
120
- const alternativeIds = chain_alternative_ids(ev);
121
- if (alternativeIds.length === 0)
122
- return false;
123
- const alternatives = alternativeIds.map((evidenceId) => live_pass(evidences, { gate: "task_complete", task_id: taskId })
124
- .find((item) => (String(item.evidence_id ?? "") === evidenceId
125
- && (item.kind === "alternative_verification" || item.kind === "manual_verification")))).filter((item) => isObject(item));
126
- if (alternatives.length !== alternativeIds.length)
127
- return false;
128
- if (!report_input_refs_match(ev.verifier_report_ref, [
129
- ev.executor_report_ref,
130
- ev.task_code_review_report_ref,
131
- ...alternatives.map(alternative_evidence_input_ref),
132
- active_chain_verifier_input_ref(active),
133
- ]))
134
- return false;
135
- const currentFreshness = compute_apply_worker_freshness(repoRoot, changeRoot, evidences, taskId, chainId, {
136
- executor_report_ref: ev.executor_report_ref,
137
- task_code_review_report_ref: ev.task_code_review_report_ref,
138
- alternative_verification_evidence_refs: alternativeIds,
139
- completion_proof_kind: "alternative_verification",
140
- verifier_report_ref: ev.verifier_report_ref,
141
- });
142
- if (Array.isArray(currentFreshness.unexpected_guard_owned_dirty_paths) && currentFreshness.unexpected_guard_owned_dirty_paths.length > 0)
143
- return false;
144
- if (Array.isArray(currentFreshness.protected_dirty_paths) && currentFreshness.protected_dirty_paths.length > 0)
145
- return false;
146
- if (!fingerprint_matches(isObject(ev.task_code_review_report_ref) ? ev.task_code_review_report_ref.observed_implementation_fingerprint : undefined, currentFreshness.implementation_fingerprint))
147
- return false;
148
- return fingerprint_matches(currentFreshness, verifierObserved);
149
- }
150
- const greenIds = chain_green_ids(ev);
151
- if (greenIds.length === 0)
152
- return false;
153
- const greenRuns = greenIds.map((greenId) => live_pass(evidences, { gate: "task_complete", kind: "test_run", task_id: taskId }).find((item) => (String(item.evidence_id ?? "") === greenId
154
- && item.semantic_status === "expected_success"
155
- && (item.phase === undefined || item.phase === "green")
156
- && item.apply_execution_chain === "executor_worker"
157
- && item.apply_worker_chain_id === chainId
158
- && executor_worker_test_run_refs_valid(changeRoot, item, taskId, chainId)))).filter((item) => isObject(item));
159
- if (greenRuns.length !== greenIds.length)
160
- return false;
161
- if (!report_input_refs_match(ev.verifier_report_ref, [
162
- ev.executor_report_ref,
163
- ev.task_code_review_report_ref,
164
- ...greenRuns.map((green) => ({ kind: "test_run", evidence_id: String(green.evidence_id ?? ""), phase: green.phase, semantic_status: green.semantic_status })),
165
- ...active_pre_edit_input_refs(evidences, active),
166
- ]))
167
- return false;
168
- const currentFreshness = compute_apply_worker_freshness(repoRoot, changeRoot, evidences, taskId, chainId, {
169
- executor_report_ref: ev.executor_report_ref,
170
- task_code_review_report_ref: ev.task_code_review_report_ref,
171
- green_test_run_evidence_ref: greenIds[0],
172
- green_test_run_evidence_refs: greenIds,
173
- completion_proof_kind: "green_tests",
174
- verifier_report_ref: ev.verifier_report_ref,
175
- });
176
- if (Array.isArray(currentFreshness.unexpected_guard_owned_dirty_paths) && currentFreshness.unexpected_guard_owned_dirty_paths.length > 0)
177
- return false;
178
- if (Array.isArray(currentFreshness.protected_dirty_paths) && currentFreshness.protected_dirty_paths.length > 0)
179
- return false;
180
- if (!greenRuns.every((green) => fingerprint_matches(green.implementation_fingerprint, currentFreshness.implementation_fingerprint)))
181
- return false;
182
- if (!fingerprint_matches(isObject(ev.task_code_review_report_ref) ? ev.task_code_review_report_ref.observed_implementation_fingerprint : undefined, currentFreshness.implementation_fingerprint))
183
- return false;
184
- return fingerprint_matches(currentFreshness, verifierObserved);
185
- }
186
- function pinned_takeover_baseline_valid(changeRoot, refItem, taskId, chainId) {
187
- return shared_pinned_artifact_ref_reasons(changeRoot, refItem, "serial_takeover_baseline_ref", { kind: "status_report", role: "verifier", taskId, chainId }).length === 0;
188
- }
189
- function serial_takeover_baseline_ref_ids(ev) {
190
- const refs = new Set();
191
- if (isObject(ev.serial_takeover_baseline_ref)) {
192
- for (const field of ["path", "ref_path", "evidence_id"]) {
193
- const value = ev.serial_takeover_baseline_ref[field];
194
- if (typeof value === "string" && value)
195
- refs.add(value);
196
- }
197
- }
198
- return [...refs].sort();
199
- }
200
- function serial_takeover_confirmation_valid(evidences, ev, active) {
201
- const confirmationId = String(ev.takeover_confirmation_evidence_id ?? "");
202
- const activeId = String(active.evidence_id ?? "");
203
- const baselineIds = serial_takeover_baseline_ref_ids(ev);
204
- if (!confirmationId || !activeId || baselineIds.length === 0)
205
- return false;
206
- const confirmation = live_user_confirmations(evidences, "serial_takeover")
207
- .find((item) => String(item.evidence_id ?? "") === confirmationId);
208
- if (!confirmation)
209
- return false;
210
- const confirmed = new Set(Array.isArray(confirmation.confirmed_refs) ? confirmation.confirmed_refs.map(String).filter(Boolean) : []);
211
- return confirmed.has(activeId) && baselineIds.some((item) => confirmed.has(item));
212
- }
213
- function abandoned_apply_worker_chain_valid(repoRoot, changeRoot, ev, active, evidences, taskId, chainId) {
214
- if (!active)
215
- return false;
216
- const hasRestored = "restored_implementation_fingerprint" in ev;
217
- const hasSerialTakeover = "serial_takeover_baseline_ref" in ev;
218
- if (hasRestored && hasSerialTakeover)
219
- return false;
220
- if ("restored_implementation_fingerprint" in ev) {
221
- const activeScope = Array.isArray(active.declared_task_write_scope) ? active.declared_task_write_scope.map(String).filter(Boolean) : [];
222
- const current = apply_worker_implementation_fingerprint(repoRoot, changeRoot, [], { declaredTaskWriteScope: activeScope });
223
- if (fingerprint_matches(ev.restored_implementation_fingerprint, active.source_implementation_fingerprint)
224
- && fingerprint_matches(current, active.source_implementation_fingerprint))
225
- return true;
226
- }
227
- if (hasSerialTakeover) {
228
- return pinned_takeover_baseline_valid(changeRoot, ev.serial_takeover_baseline_ref, taskId, chainId)
229
- && serial_takeover_confirmation_valid(evidences, ev, active);
230
- }
231
- return false;
232
- }
233
- export function apply_worker_chain_lifecycle_state(repoRoot, changeRoot, evidences, taskId) {
234
- const chains = find_pass(evidences, { gate: "task_complete", kind: "apply_worker_chain", task_id: taskId });
235
- const supersededIds = effective_superseded_ids(evidences);
236
- const liveChainMarker = (ev) => !supersededIds.has(String(ev.evidence_id ?? ""));
237
- const activeByChain = new Map();
238
- const activeCounts = new Map();
239
- for (const ev of chains) {
240
- if (String(ev.chain_state ?? "") !== "active")
241
- continue;
242
- const chainId = String(ev.apply_worker_chain_id ?? "");
243
- if (!chainId)
244
- continue;
245
- const bucket = activeCounts.get(chainId) ?? [];
246
- bucket.push(ev);
247
- activeCounts.set(chainId, bucket);
248
- if (!activeByChain.has(chainId))
249
- activeByChain.set(chainId, ev);
250
- }
251
- const chainIdsWithActive = new Set([...activeByChain.keys()]);
252
- const terminalValidity = new Map();
253
- const chainIdsWithTerminal = new Set(chains
254
- .filter((ev) => {
255
- const chainId = String(ev.apply_worker_chain_id ?? "");
256
- if (!chainId)
257
- return false;
258
- let valid = false;
259
- if (String(ev.chain_state ?? "") === "closed")
260
- valid = closed_apply_worker_chain_valid(repoRoot, changeRoot, ev, evidences, taskId, chainId);
261
- if (String(ev.chain_state ?? "") === "abandoned")
262
- valid = abandoned_apply_worker_chain_valid(repoRoot, changeRoot, ev, activeByChain.get(chainId), evidences, taskId, chainId);
263
- terminalValidity.set(ev, valid);
264
- return valid && liveChainMarker(ev);
265
- })
266
- .map((ev) => String(ev.apply_worker_chain_id ?? ""))
267
- .filter(Boolean));
268
- const openActiveChainIds = new Set([...activeByChain.keys()].filter((chainId) => !chainIdsWithTerminal.has(chainId)));
269
- const validClosedChainIds = new Set(chains
270
- .filter((ev) => {
271
- const chainId = String(ev.apply_worker_chain_id ?? "");
272
- const valid = String(ev.chain_state ?? "") === "closed" && (terminalValidity.get(ev) ?? closed_apply_worker_chain_valid(repoRoot, changeRoot, ev, evidences, taskId, chainId));
273
- return chainId && valid && liveChainMarker(ev);
274
- })
275
- .map((ev) => String(ev.apply_worker_chain_id ?? ""))
276
- .filter(Boolean));
277
- const validClosedGreenEvidenceIds = new Set(chains
278
- .filter((ev) => {
279
- const chainId = String(ev.apply_worker_chain_id ?? "");
280
- const valid = String(ev.chain_state ?? "") === "closed" && (terminalValidity.get(ev) ?? closed_apply_worker_chain_valid(repoRoot, changeRoot, ev, evidences, taskId, chainId));
281
- return chainId && valid && liveChainMarker(ev);
282
- })
283
- .flatMap(chain_green_ids));
284
- const validClosedAlternativeChainIds = new Set(chains
285
- .filter((ev) => {
286
- const chainId = String(ev.apply_worker_chain_id ?? "");
287
- const valid = String(ev.chain_state ?? "") === "closed" && String(ev.completion_proof_kind ?? "green_tests") === "alternative_verification" && (terminalValidity.get(ev) ?? closed_apply_worker_chain_valid(repoRoot, changeRoot, ev, evidences, taskId, chainId));
288
- return chainId && valid && liveChainMarker(ev);
289
- })
290
- .map((ev) => String(ev.apply_worker_chain_id ?? ""))
291
- .filter(Boolean));
292
- const validClosedAlternativeEvidenceIds = new Set(chains
293
- .filter((ev) => {
294
- const chainId = String(ev.apply_worker_chain_id ?? "");
295
- const valid = String(ev.chain_state ?? "") === "closed" && String(ev.completion_proof_kind ?? "green_tests") === "alternative_verification" && (terminalValidity.get(ev) ?? closed_apply_worker_chain_valid(repoRoot, changeRoot, ev, evidences, taskId, chainId));
296
- return chainId && valid && liveChainMarker(ev);
297
- })
298
- .flatMap(chain_alternative_ids));
299
- const completionReasons = [];
300
- const duplicateActives = [...activeCounts.entries()]
301
- .filter(([chainId]) => openActiveChainIds.has(chainId))
302
- .map(([, items]) => items)
303
- .filter((items) => items.length > 1)
304
- .flatMap((items) => items.map((ev) => String(ev.evidence_id ?? ev.apply_worker_chain_id ?? "")))
305
- .filter(Boolean)
306
- .sort();
307
- const openActiveValues = [...openActiveChainIds].map((chainId) => activeByChain.get(chainId)).filter((ev) => isObject(ev));
308
- const parallelActives = openActiveValues.length > 1
309
- ? openActiveValues.map((ev) => String(ev.evidence_id ?? ev.apply_worker_chain_id ?? "")).filter(Boolean).sort()
310
- : [];
311
- const activeConflicts = [...new Set([...duplicateActives, ...parallelActives])].sort();
312
- if (activeConflicts.length > 0) {
313
- completionReasons.push(reason("apply_worker_chain_active_conflict", `task ${taskId} has conflicting active apply worker chain markers: ${renderList(activeConflicts)}`, activeConflicts));
314
- }
315
- const terminalsByChain = new Map();
316
- for (const ev of chains) {
317
- const state = String(ev.chain_state ?? "");
318
- if (state !== "closed" && state !== "abandoned")
319
- continue;
320
- const chainId = String(ev.apply_worker_chain_id ?? "");
321
- if (!chainId)
322
- continue;
323
- const bucket = terminalsByChain.get(chainId) ?? [];
324
- bucket.push(ev);
325
- terminalsByChain.set(chainId, bucket);
326
- }
327
- const duplicateTerminals = [...terminalsByChain.values()]
328
- .filter((items) => items.length > 1)
329
- .flatMap((items) => items.map((ev) => String(ev.evidence_id ?? ev.apply_worker_chain_id ?? "")))
330
- .filter(Boolean)
331
- .sort();
332
- if (duplicateTerminals.length > 0) {
333
- completionReasons.push(reason("apply_worker_chain_terminal_conflict", `task ${taskId} has duplicate apply worker chain terminal markers: ${renderList(duplicateTerminals)}`, duplicateTerminals));
334
- }
335
- const takeoverbaselines = [];
336
- const invalidTerminals = chains
337
- .filter((ev) => String(ev.chain_state ?? "") === "closed" || String(ev.chain_state ?? "") === "abandoned")
338
- .filter((ev) => {
339
- const chainId = String(ev.apply_worker_chain_id ?? "");
340
- if (!chainId)
341
- return true;
342
- if (String(ev.chain_state ?? "") === "closed")
343
- return !(terminalValidity.get(ev) ?? closed_apply_worker_chain_valid(repoRoot, changeRoot, ev, evidences, taskId, chainId));
344
- const valid = terminalValidity.get(ev) ?? abandoned_apply_worker_chain_valid(repoRoot, changeRoot, ev, activeByChain.get(chainId), evidences, taskId, chainId);
345
- if (valid && isObject(ev.serial_takeover_baseline_ref)) {
346
- const baseline = read_pinned_artifact_json(changeRoot, ev.serial_takeover_baseline_ref);
347
- if (baseline?.implementation_fingerprint !== undefined) {
348
- takeoverbaselines.push({
349
- fingerprint: baseline.implementation_fingerprint,
350
- successorGreenRefs: Array.isArray(ev.successor_green_evidence_refs) ? ev.successor_green_evidence_refs.map(String).filter(Boolean) : [],
351
- });
352
- }
353
- }
354
- return !valid;
355
- })
356
- .map((ev) => String(ev.evidence_id ?? ev.apply_worker_chain_id ?? ""))
357
- .filter(Boolean)
358
- .sort();
359
- if (invalidTerminals.length > 0) {
360
- completionReasons.push(reason("apply_worker_chain_terminal_invalid", `task ${taskId} has invalid apply worker chain terminal markers: ${renderList(invalidTerminals)}`, invalidTerminals));
361
- }
362
- for (const chainId of [...openActiveChainIds].sort()) {
363
- if (!chainIdsWithTerminal.has(chainId)) {
364
- completionReasons.push(reason("apply_worker_chain_active", `task ${taskId} has active apply worker chain and cannot use non-chain task completion: ${chainId}`, [chainId]));
365
- }
366
- }
367
- for (const ev of evidences) {
368
- if (!isObject(ev) || ev._invalid || ev.status !== "pass" || ev.task_id !== taskId)
369
- continue;
370
- const chainId = typeof ev.apply_worker_chain_id === "string" ? ev.apply_worker_chain_id : "";
371
- if (!chainId)
372
- continue;
373
- if (!chainIdsWithActive.has(chainId)) {
374
- completionReasons.push(reason("apply_worker_chain_missing_active", `task ${taskId} references apply_worker_chain_id=${repr(chainId)} without a matching active marker`, [chainId]));
375
- }
376
- }
377
- if (duplicateTerminals.length > 0 || activeConflicts.length > 0) {
378
- validClosedChainIds.clear();
379
- validClosedGreenEvidenceIds.clear();
380
- validClosedAlternativeChainIds.clear();
381
- validClosedAlternativeEvidenceIds.clear();
382
- }
383
- const activeBlockingReasons = completionReasons.filter((item) => (item.code === "apply_worker_chain_active_conflict"
384
- || item.code === "apply_worker_chain_terminal_conflict"
385
- || item.code === "apply_worker_chain_terminal_invalid"
386
- || item.code === "apply_worker_chain_missing_active"));
387
- const activePresence = activeBlockingReasons.length > 0
388
- ? "blocked"
389
- : openActiveValues.length === 1
390
- ? "single_open"
391
- : "none";
392
- return {
393
- completionReasons,
394
- packetBlockers: activeBlockingReasons,
395
- activeBlockingReasons,
396
- activePresence,
397
- active: activePresence === "single_open" ? openActiveValues[0] : null,
398
- openActiveChainIds,
399
- validTerminalChainIds: chainIdsWithTerminal,
400
- validClosedChainIds,
401
- validClosedGreenEvidenceIds,
402
- validClosedAlternativeEvidenceIds,
403
- validClosedAlternativeChainIds,
404
- takeoverbaselines,
405
- };
406
- }
407
- export function apply_worker_chain_lifecycle_reasons(repoRoot, changeRoot, evidences, taskId) {
408
- return apply_worker_chain_lifecycle_state(repoRoot, changeRoot, evidences, taskId).completionReasons;
409
- }
@@ -1,23 +0,0 @@
1
- import type { Decision, JsonMap, Reason } from "./util.ts";
2
- export declare function archive_manifest_path(changeRoot: string): string;
3
- export declare function archive_preservation_dir(changeRoot: string): string;
4
- export declare function archive_preservation_manifest_path(changeRoot: string): string;
5
- export declare function sidecar_manifest_entries(changeRoot: string): JsonMap[];
6
- export declare function write_archive_manifest(change: string, changeRoot: string): string;
7
- export declare function begin_archive_preservation_bundle(change: string, changeRoot: string, opts?: {
8
- file_overrides?: Record<string, string>;
9
- }): {
10
- manifest_path: string;
11
- bundle_manifest_path: string;
12
- commit: () => void;
13
- rollback: () => void;
14
- };
15
- export declare function write_archive_preservation_bundle(change: string, changeRoot: string, opts?: {
16
- file_overrides?: Record<string, string>;
17
- }): string;
18
- export declare function find_archived_change(repoRoot: string, change: string): string | null;
19
- export declare function check_archived(change: string, repoRoot: string): Decision;
20
- export declare function check_archived_preservation_bundle(change: string, archived: string, manifestPath: string): Decision;
21
- export declare function preset_upgrade_required(preset: string, changedPaths: string[], flags?: JsonMap): boolean;
22
- export declare function preset_upgrade_reasons(config: JsonMap, changedPaths: string[], humanConfirmed?: boolean, flags?: JsonMap): Reason[];
23
- export declare function preset_upgrade_required_from_context(config: JsonMap, changedPaths: string[]): boolean;