opencode-swarm 7.145.1 → 7.146.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 (107) hide show
  1. package/.opencode/skills/phase-wrap/SKILL.md +3 -2
  2. package/README.md +5 -1
  3. package/dist/cli/{config-doctor-96jmxr7s.js → config-doctor-vs6hvbew.js} +3 -3
  4. package/dist/cli/{core-w78pc1hh.js → core-jvvm935f.js} +2 -2
  5. package/dist/cli/{curation-policy-smyc2mrm.js → curation-policy-xv0j8zyt.js} +6 -6
  6. package/dist/cli/{curator-59hzdxrv.js → curator-5bxh1djq.js} +28 -28
  7. package/dist/cli/{curator-llm-factory-g794pv51.js → curator-llm-factory-pe6skby4.js} +28 -28
  8. package/dist/cli/{evidence-summary-service-41m0cna6.js → evidence-summary-service-6m9jmzk8.js} +12 -12
  9. package/dist/cli/{gate-evidence-7aywx7qa.js → gate-evidence-84sfx6g8.js} +7 -7
  10. package/dist/cli/{guardrail-explain-j88dhm6w.js → guardrail-explain-jhbxq8yb.js} +29 -29
  11. package/dist/cli/{guardrail-log-xcb3ke8s.js → guardrail-log-vpbp3rm4.js} +4 -4
  12. package/dist/cli/{hive-promoter-nnnx5692.js → hive-promoter-mmmfszv8.js} +28 -28
  13. package/dist/cli/{index-34tawmyx.js → index-0a0asz2s.js} +1 -1
  14. package/dist/cli/{index-2qrd8mfa.js → index-4p3qfb05.js} +1 -1
  15. package/dist/cli/{index-gey2257h.js → index-5e5a1y2r.js} +1 -1
  16. package/dist/cli/{index-17e73wac.js → index-5qwmpamg.js} +1 -1
  17. package/dist/cli/{index-41t3hgaa.js → index-92cxd0r1.js} +247 -29
  18. package/dist/cli/{index-rtkttser.js → index-97psh79d.js} +1 -1
  19. package/dist/cli/{index-gf03198s.js → index-bghwrr59.js} +1 -1
  20. package/dist/cli/{index-tw8ck794.js → index-bma2wrqx.js} +2 -2
  21. package/dist/cli/{index-v3y3qg48.js → index-cpg98bh1.js} +17 -1
  22. package/dist/cli/{index-kxzgnz2h.js → index-d4e6wpkg.js} +14 -7
  23. package/dist/cli/{index-sfemjcb8.js → index-f17j50dx.js} +5 -5
  24. package/dist/cli/{index-7axx11dt.js → index-fay8h6v8.js} +25 -5
  25. package/dist/cli/{index-19v4tccw.js → index-fyr2wbvz.js} +2 -2
  26. package/dist/cli/{index-cqfp05jb.js → index-fzqhn96z.js} +3 -3
  27. package/dist/cli/{index-mrkgxfeh.js → index-g3xt1d16.js} +4 -4
  28. package/dist/cli/{index-evpgszmp.js → index-gxbhp7sx.js} +2 -2
  29. package/dist/cli/{index-mpf01swm.js → index-j20fzn0w.js} +2 -2
  30. package/dist/cli/{index-xz4x17z0.js → index-j43qndgc.js} +30 -30
  31. package/dist/cli/{index-neh8azwc.js → index-jfcgnvg6.js} +3 -3
  32. package/dist/cli/{index-qpke2x5h.js → index-kfmee1cr.js} +6 -6
  33. package/dist/cli/{index-4evasm2b.js → index-kggqpefz.js} +5 -5
  34. package/dist/cli/{index-90w06fqr.js → index-kwxp0z0n.js} +4 -4
  35. package/dist/cli/{index-b7ntt9cw.js → index-n6ke10ck.js} +4 -4
  36. package/dist/cli/{index-fwnhh6s7.js → index-nsr5b69r.js} +2 -2
  37. package/dist/cli/{index-bst6epnr.js → index-pz2py5v7.js} +1876 -1065
  38. package/dist/cli/{index-8ef23wex.js → index-q2mvacjr.js} +4 -4
  39. package/dist/cli/{index-dppzthm9.js → index-qyvjp0bq.js} +2 -2
  40. package/dist/cli/{index-tm0bezd9.js → index-s8qyaqs2.js} +1 -1
  41. package/dist/cli/{index-ymyke19q.js → index-vk15nbh4.js} +2 -2
  42. package/dist/cli/{index-dzan8czb.js → index-x8pm918t.js} +1 -1
  43. package/dist/cli/{index-ff66fbjt.js → index-zd1mfygt.js} +177 -29
  44. package/dist/cli/{index-zpp507z0.js → index-zsmsy1dh.js} +2 -2
  45. package/dist/cli/index.js +28 -28
  46. package/dist/cli/{knowledge-escalator-s6acdpwj.js → knowledge-escalator-c9p3w12b.js} +12 -12
  47. package/dist/cli/{knowledge-events-jprkz49t.js → knowledge-events-d201414m.js} +10 -10
  48. package/dist/cli/{knowledge-link-zvtmj756.js → knowledge-link-82ew2yc4.js} +5 -5
  49. package/dist/cli/{knowledge-store-mc4awds4.js → knowledge-store-ds45k9th.js} +6 -6
  50. package/dist/cli/{knowledge-validator-pe4ncrvj.js → knowledge-validator-707vsncy.js} +8 -8
  51. package/dist/cli/{model-preflight-77dwxfv5.js → model-preflight-7ea00h34.js} +1 -1
  52. package/dist/cli/{pending-delegations-epzht3d7.js → pending-delegations-kkrczqv7.js} +3 -3
  53. package/dist/cli/{pr-subscriptions-2ahy8g87.js → pr-subscriptions-2xn238xt.js} +3 -3
  54. package/dist/cli/{runner-ra9pjhp2.js → runner-pqsf809k.js} +6 -6
  55. package/dist/cli/{scan-cursor-hdzhqwzj.js → scan-cursor-znhqb8xa.js} +7 -7
  56. package/dist/cli/{schema-pg85z06v.js → schema-dnnm0p40.js} +2 -2
  57. package/dist/cli/{scope-persistence-v8we8ja7.js → scope-persistence-4n24a1e2.js} +8 -8
  58. package/dist/cli/{skill-generator-ctskfct2.js → skill-generator-5s0p3y8k.js} +14 -14
  59. package/dist/cli/{telemetry-c21dgffc.js → telemetry-t109dhv7.js} +1 -1
  60. package/dist/cli/{worktree-collision-ownership-f7se4wbf.js → worktree-collision-ownership-2jtg2my1.js} +3 -3
  61. package/dist/cli/{worktree-isolation-j4qb7mgb.js → worktree-isolation-1v2mythh.js} +28 -28
  62. package/dist/commands/memory.d.ts +8 -0
  63. package/dist/commands/registry.d.ts +8 -0
  64. package/dist/config/schema.d.ts +16 -2
  65. package/dist/evidence/task-gate-repair.d.ts +26 -0
  66. package/dist/evidence/task-gate-requirements.d.ts +20 -0
  67. package/dist/gate-evidence.d.ts +7 -0
  68. package/dist/hooks/knowledge-receipt-ledger-storage.d.ts +2 -0
  69. package/dist/hooks/knowledge-receipt-ledger.d.ts +72 -3
  70. package/dist/hooks/knowledge-receipt-observability.d.ts +1 -1
  71. package/dist/hooks/phase-complete-directive-gate.d.ts +9 -0
  72. package/dist/index.js +593 -537
  73. package/dist/memory/config.d.ts +20 -0
  74. package/dist/memory/errors.d.ts +14 -0
  75. package/dist/memory/gateway.d.ts +32 -0
  76. package/dist/memory/index.d.ts +3 -2
  77. package/dist/memory/pii.d.ts +66 -0
  78. package/dist/memory/prompt-block.d.ts +1 -1
  79. package/dist/memory/provider.d.ts +15 -0
  80. package/dist/memory/redaction.d.ts +31 -8
  81. package/dist/memory/schema.d.ts +18 -0
  82. package/dist/memory/sentinel.d.ts +12 -0
  83. package/dist/memory/sqlite-provider.d.ts +93 -0
  84. package/dist/memory/types.d.ts +9 -0
  85. package/dist/plan/manager.d.ts +8 -0
  86. package/dist/review/diff-source.d.ts +30 -0
  87. package/dist/review/engine.d.ts +1 -0
  88. package/dist/review/evidence.d.ts +16 -2
  89. package/dist/review/phase-runner.d.ts +1 -0
  90. package/dist/tools/completion-verify.d.ts +2 -0
  91. package/dist/tools/convene-council.d.ts +1 -1
  92. package/dist/tools/index.d.ts +4 -0
  93. package/dist/tools/manifest.d.ts +4 -0
  94. package/dist/tools/phase-complete/gates/final-review-gate.d.ts +3 -3
  95. package/dist/tools/phase-complete/gates/types.d.ts +2 -2
  96. package/dist/tools/phase-complete/preflight-report.d.ts +66 -0
  97. package/dist/tools/phase-complete/snapshot-identity.d.ts +1 -0
  98. package/dist/tools/phase-complete.d.ts +66 -3
  99. package/dist/tools/record-directive-override.d.ts +14 -0
  100. package/dist/tools/repair-gate-evidence.d.ts +6 -0
  101. package/dist/tools/repair-knowledge-receipt-ledger.d.ts +27 -0
  102. package/dist/tools/run-phase-review.d.ts +37 -0
  103. package/dist/tools/submit-phase-council-verdicts.d.ts +1 -1
  104. package/dist/tools/tool-metadata.d.ts +32 -16
  105. package/dist/tools/write-final-council-evidence.d.ts +1 -1
  106. package/dist/tools/write-retro.d.ts +2 -0
  107. package/package.json +12 -2
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  autoCommitDirty,
4
4
  cleanUntrackedFiles
5
- } from "./index-zpp507z0.js";
5
+ } from "./index-zsmsy1dh.js";
6
6
  import {
7
7
  isPathWithinDeclaredScope,
8
8
  unsafePathTextReason
@@ -26,10 +26,13 @@ import {
26
26
  atomicWriteFile,
27
27
  taskEvidencePath,
28
28
  withTaskEvidenceLock
29
- } from "./index-mpf01swm.js";
29
+ } from "./index-j20fzn0w.js";
30
+ import {
31
+ assertProjectRoot
32
+ } from "./index-bghwrr59.js";
30
33
  import {
31
34
  telemetry
32
- } from "./index-dppzthm9.js";
35
+ } from "./index-qyvjp0bq.js";
33
36
  import {
34
37
  exports_external,
35
38
  init_zod
@@ -40,8 +43,214 @@ import {
40
43
 
41
44
  // src/gate-evidence.ts
42
45
  init_zod();
43
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, realpathSync } from "fs";
44
- import * as path2 from "path";
46
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, realpathSync as realpathSync2 } from "fs";
47
+ import * as path3 from "path";
48
+
49
+ // src/evidence/task-gate-requirements.ts
50
+ init_zod();
51
+ import { createHash } from "crypto";
52
+ import * as fs from "fs";
53
+ import * as path from "path";
54
+ var MAX_TASK_GATE_REQUIREMENTS_BYTES = 256 * 1024;
55
+ var TaskGateRequirementsReceiptSchema = exports_external.object({
56
+ schemaVersion: exports_external.literal(1),
57
+ taskId: exports_external.string().min(1).max(120),
58
+ generation: exports_external.number().int().min(0),
59
+ normalizedRole: exports_external.string().min(1).max(120),
60
+ testEngineerExempt: exports_external.boolean().nullable(),
61
+ requiredGates: exports_external.array(exports_external.string()).min(1).max(16),
62
+ sourceEvent: exports_external.string().min(1).max(120),
63
+ sourceTransitionId: exports_external.string().min(1).max(200).nullable(),
64
+ recordedAt: exports_external.string().min(1).max(128),
65
+ previousChainHash: exports_external.string().regex(/^[a-f0-9]{64}$/).nullable(),
66
+ chainHash: exports_external.string().regex(/^[a-f0-9]{64}$/)
67
+ }).strict();
68
+ function samePath(left, right) {
69
+ const normalize = (value) => process.platform === "win32" ? path.resolve(value).toLowerCase() : path.resolve(value);
70
+ return normalize(left) === normalize(right);
71
+ }
72
+ function assertSafeRequirementsParent(directory, create) {
73
+ assertProjectRoot(directory, undefined, "task gate requirements");
74
+ const rootStat = fs.lstatSync(directory);
75
+ if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
76
+ throw new Error("TASK_GATE_REQUIREMENTS_UNREADABLE: project root is not a regular directory");
77
+ }
78
+ const canonicalRoot = fs.realpathSync(directory);
79
+ const segments = [".swarm", "evidence", "task-gate-requirements"];
80
+ let current = canonicalRoot;
81
+ for (const segment of segments) {
82
+ current = path.join(current, segment);
83
+ let info;
84
+ try {
85
+ info = fs.lstatSync(current);
86
+ } catch (error) {
87
+ if (error.code === "ENOENT") {
88
+ if (!create)
89
+ return current;
90
+ try {
91
+ fs.mkdirSync(current);
92
+ } catch (mkdirError) {
93
+ if (mkdirError.code !== "EEXIST") {
94
+ throw mkdirError;
95
+ }
96
+ }
97
+ info = fs.lstatSync(current);
98
+ } else {
99
+ throw error;
100
+ }
101
+ }
102
+ if (info.isSymbolicLink() || !info.isDirectory()) {
103
+ throw new Error("TASK_GATE_REQUIREMENTS_UNREADABLE: receipt parent is redirected or not a directory");
104
+ }
105
+ const canonicalCurrent = fs.realpathSync(current);
106
+ if (!samePath(canonicalCurrent, current)) {
107
+ throw new Error("TASK_GATE_REQUIREMENTS_UNREADABLE: receipt parent escaped the project root");
108
+ }
109
+ }
110
+ return current;
111
+ }
112
+ function safeTaskGateRequirementsReceiptPath(directory, taskId, createParent) {
113
+ const parent = assertSafeRequirementsParent(directory, createParent);
114
+ return path.join(parent, `${taskId}.jsonl`);
115
+ }
116
+ function sha256(value) {
117
+ return createHash("sha256").update(value).digest("hex");
118
+ }
119
+ function canonicalReceiptPayload(receipt) {
120
+ return JSON.stringify({
121
+ ...receipt,
122
+ requiredGates: [...receipt.requiredGates]
123
+ });
124
+ }
125
+ function computeChainHash(receipt) {
126
+ return sha256(canonicalReceiptPayload(receipt));
127
+ }
128
+ function readBoundedTextFile(filePath) {
129
+ let pathStat;
130
+ try {
131
+ pathStat = fs.lstatSync(filePath);
132
+ } catch (error) {
133
+ if (error.code === "ENOENT")
134
+ return null;
135
+ throw error;
136
+ }
137
+ if (pathStat.isSymbolicLink() || !pathStat.isFile()) {
138
+ throw new Error("TASK_GATE_REQUIREMENTS_UNREADABLE: receipt path is not a regular file");
139
+ }
140
+ if (pathStat.size > MAX_TASK_GATE_REQUIREMENTS_BYTES) {
141
+ throw new Error(`TASK_GATE_REQUIREMENTS_OVERSIZED: ${pathStat.size} bytes exceeds ${MAX_TASK_GATE_REQUIREMENTS_BYTES}`);
142
+ }
143
+ const descriptor = fs.openSync(filePath, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0));
144
+ try {
145
+ const openedStat = fs.fstatSync(descriptor);
146
+ if (!openedStat.isFile() || openedStat.dev !== pathStat.dev || openedStat.ino !== pathStat.ino) {
147
+ throw new Error("TASK_GATE_REQUIREMENTS_UNREADABLE: receipt changed while being opened");
148
+ }
149
+ if (openedStat.size > MAX_TASK_GATE_REQUIREMENTS_BYTES) {
150
+ throw new Error(`TASK_GATE_REQUIREMENTS_OVERSIZED: ${openedStat.size} bytes exceeds ${MAX_TASK_GATE_REQUIREMENTS_BYTES}`);
151
+ }
152
+ return fs.readFileSync(descriptor, "utf-8");
153
+ } finally {
154
+ fs.closeSync(descriptor);
155
+ }
156
+ }
157
+ async function readTaskGateRequirementsReceipts(directory, taskId) {
158
+ const filePath = safeTaskGateRequirementsReceiptPath(directory, taskId, false);
159
+ const text = readBoundedTextFile(filePath);
160
+ if (text === null)
161
+ return [];
162
+ const receipts = [];
163
+ for (const line of text.split(`
164
+ `)) {
165
+ if (!line.trim())
166
+ continue;
167
+ const parsed = TaskGateRequirementsReceiptSchema.parse(JSON.parse(line));
168
+ if (parsed.taskId !== taskId) {
169
+ throw new Error(`TASK_GATE_REQUIREMENTS_IDENTITY_MISMATCH: expected ${taskId}, found ${parsed.taskId}`);
170
+ }
171
+ const { chainHash, ...withoutChainHash } = parsed;
172
+ const expectedHash = computeChainHash(withoutChainHash);
173
+ if (expectedHash !== chainHash) {
174
+ throw new Error(`TASK_GATE_REQUIREMENTS_CHAIN_MISMATCH: receipt for ${taskId} failed hash validation`);
175
+ }
176
+ const previousChainHash = receipts.at(-1)?.chainHash ?? null;
177
+ if (parsed.previousChainHash !== previousChainHash) {
178
+ throw new Error(`TASK_GATE_REQUIREMENTS_CHAIN_MISMATCH: receipt for ${taskId} failed linkage validation`);
179
+ }
180
+ receipts.push(parsed);
181
+ }
182
+ return receipts;
183
+ }
184
+ function deriveReceiptRole(event) {
185
+ switch (event.type) {
186
+ case "accepted_mutation":
187
+ case "dispatch_attempted":
188
+ case "dispatch_no_mutation":
189
+ if (typeof event.agentType === "string" && event.agentType.trim().length > 0) {
190
+ return {
191
+ normalizedRole: event.agentType.trim(),
192
+ testEngineerExempt: event.agentType === "coder" ? event.context?.testEngineerExempt === true : null
193
+ };
194
+ }
195
+ return null;
196
+ case "stage_b_completed":
197
+ case "gate_recorded":
198
+ return {
199
+ normalizedRole: event.gate,
200
+ testEngineerExempt: null
201
+ };
202
+ default:
203
+ return null;
204
+ }
205
+ }
206
+ function shouldAppendReceipt(current, next, role) {
207
+ if (next.required_gates.length === 0)
208
+ return false;
209
+ const currentGeneration = current?.workflow?.generation ?? -1;
210
+ const nextGeneration = next.workflow?.generation ?? -1;
211
+ if (current === null)
212
+ return true;
213
+ if (JSON.stringify(current.required_gates) !== JSON.stringify(next.required_gates)) {
214
+ return true;
215
+ }
216
+ if ((current.test_engineer_exempt ?? null) !== role.testEngineerExempt) {
217
+ return true;
218
+ }
219
+ return currentGeneration !== nextGeneration;
220
+ }
221
+ async function appendTaskGateRequirementsReceiptIfNeeded(directory, taskId, current, next, event) {
222
+ const role = deriveReceiptRole(event);
223
+ if (!role || !shouldAppendReceipt(current, next, role))
224
+ return;
225
+ const filePath = safeTaskGateRequirementsReceiptPath(directory, taskId, true);
226
+ const receipts = await readTaskGateRequirementsReceipts(directory, taskId);
227
+ const latest = receipts.at(-1);
228
+ const baseReceipt = {
229
+ schemaVersion: 1,
230
+ taskId,
231
+ generation: next.workflow?.generation ?? 0,
232
+ normalizedRole: role.normalizedRole,
233
+ testEngineerExempt: role.testEngineerExempt,
234
+ requiredGates: [...next.required_gates],
235
+ sourceEvent: event.type,
236
+ sourceTransitionId: event.transitionId ?? null,
237
+ recordedAt: new Date().toISOString(),
238
+ previousChainHash: latest?.chainHash ?? null
239
+ };
240
+ const receipt = {
241
+ ...baseReceipt,
242
+ chainHash: computeChainHash(baseReceipt)
243
+ };
244
+ if (latest && latest.generation === receipt.generation && latest.normalizedRole === receipt.normalizedRole && latest.testEngineerExempt === receipt.testEngineerExempt && JSON.stringify(latest.requiredGates) === JSON.stringify(receipt.requiredGates) && latest.sourceTransitionId === receipt.sourceTransitionId) {
245
+ return;
246
+ }
247
+ const lines = [...receipts, receipt].map((entry) => JSON.stringify(entry));
248
+ assertSafeRequirementsParent(directory, false);
249
+ await atomicWriteFile(filePath, `${lines.join(`
250
+ `)}
251
+ `);
252
+ assertSafeRequirementsParent(directory, false);
253
+ }
45
254
 
46
255
  // src/validation/task-id.ts
47
256
  var STRICT_TASK_ID_PATTERN = /^\d+\.\d+(\.\d+)*$/;
@@ -90,7 +299,7 @@ function sanitizeTaskId(taskId) {
90
299
  }
91
300
 
92
301
  // src/workflow/workflow-wal-file.ts
93
- import * as fs2 from "fs";
302
+ import * as fs3 from "fs";
94
303
  import { mkdir, open } from "fs/promises";
95
304
  import { dirname } from "path";
96
305
 
@@ -98,11 +307,11 @@ import { dirname } from "path";
98
307
  init_warning_buffer();
99
308
 
100
309
  // src/turbo/lean/recovery.ts
101
- import * as fs from "fs";
102
- import * as path from "path";
310
+ import * as fs2 from "fs";
311
+ import * as path2 from "path";
103
312
  var RECOVERY_DIR_NAME = "recovery";
104
313
  function recoveryDir(directory) {
105
- return path.join(directory, ".swarm", RECOVERY_DIR_NAME);
314
+ return path2.join(directory, ".swarm", RECOVERY_DIR_NAME);
106
315
  }
107
316
  function isRecoveryRecord(value) {
108
317
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
@@ -116,11 +325,11 @@ function readRecoveryRecords(directory) {
116
325
  const dir = recoveryDir(directory);
117
326
  let entries;
118
327
  try {
119
- entries = fs.readdirSync(dir, { withFileTypes: true });
328
+ entries = fs2.readdirSync(dir, { withFileTypes: true });
120
329
  } catch {
121
330
  return {
122
331
  records: [],
123
- errored: fs.existsSync(dir)
332
+ errored: fs2.existsSync(dir)
124
333
  };
125
334
  }
126
335
  const records = [];
@@ -128,9 +337,9 @@ function readRecoveryRecords(directory) {
128
337
  for (const entry of entries) {
129
338
  if (!entry.isFile() || !entry.name.endsWith(".json"))
130
339
  continue;
131
- const full = path.join(dir, entry.name);
340
+ const full = path2.join(dir, entry.name);
132
341
  try {
133
- const parsed = JSON.parse(fs.readFileSync(full, "utf-8"));
342
+ const parsed = JSON.parse(fs2.readFileSync(full, "utf-8"));
134
343
  if (isRecoveryRecord(parsed)) {
135
344
  records.push(parsed);
136
345
  } else {
@@ -189,7 +398,7 @@ init_git_executable();
189
398
  var _internals = {
190
399
  bunSpawn,
191
400
  platform: process.platform,
192
- sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
401
+ sleep: (ms) => new Promise((resolve2) => setTimeout(resolve2, ms)),
193
402
  cleanupOrphanedBranches,
194
403
  startupOrphanRecovery,
195
404
  extractSessionId,
@@ -763,9 +972,9 @@ var SMALL_WORKFLOW_WAL_MAX_BYTES = 1024 * 1024;
763
972
  var CHUNK_BYTES = 64 * 1024;
764
973
  var _internals2 = {
765
974
  openFile: open,
766
- openFileSync: fs2.openSync,
767
- readFileSync: fs2.readSync,
768
- closeFileSync: fs2.closeSync
975
+ openFileSync: fs3.openSync,
976
+ readFileSync: fs3.readSync,
977
+ closeFileSync: fs3.closeSync
769
978
  };
770
979
  function maxBytesFor(kind) {
771
980
  return kind === "coder-settlement" ? CODER_SETTLEMENT_MAX_BYTES : SMALL_WORKFLOW_WAL_MAX_BYTES;
@@ -1017,8 +1226,14 @@ var TaskEvidenceSchema = exports_external.object({
1017
1226
  required_gates: exports_external.array(exports_external.string()).default([]),
1018
1227
  gates: exports_external.record(exports_external.string(), GateEvidenceSchema),
1019
1228
  turbo: exports_external.boolean().optional(),
1229
+ requirements_state: exports_external.enum(["known", "unknown"]).optional(),
1020
1230
  test_engineer_exempt: exports_external.boolean().optional(),
1021
- workflow: TaskWorkflowMetadataSchema.optional()
1231
+ workflow: TaskWorkflowMetadataSchema.optional(),
1232
+ repair_provenance: exports_external.object({
1233
+ source_sha256: exports_external.string().regex(/^[a-f0-9]{64}$/).nullable(),
1234
+ source_generation: exports_external.number().int().min(0).nullable(),
1235
+ requirements_receipt_hash: exports_external.string().regex(/^[a-f0-9]{64}$/).nullable()
1236
+ }).optional()
1022
1237
  });
1023
1238
  function parseTaskEvidence(raw, expectedTaskId) {
1024
1239
  const parsed = TaskEvidenceSchema.parse(JSON.parse(raw));
@@ -1259,18 +1474,18 @@ function reduceTaskWorkflowSnapshot(current, event, context) {
1259
1474
  }
1260
1475
  }
1261
1476
  function getEvidenceDir(directory) {
1262
- const swarmDir = path2.resolve(directory, ".swarm");
1263
- const evidenceDir = path2.join(swarmDir, "evidence");
1264
- mkdirSync2(evidenceDir, { recursive: true });
1477
+ const swarmDir = path3.resolve(directory, ".swarm");
1478
+ const evidenceDir = path3.join(swarmDir, "evidence");
1479
+ mkdirSync3(evidenceDir, { recursive: true });
1265
1480
  let resolvedSwarmDir;
1266
1481
  let resolvedEvidenceDir;
1267
1482
  try {
1268
- resolvedSwarmDir = path2.normalize(realpathSync(swarmDir));
1269
- resolvedEvidenceDir = path2.normalize(realpathSync(evidenceDir));
1483
+ resolvedSwarmDir = path3.normalize(realpathSync2(swarmDir));
1484
+ resolvedEvidenceDir = path3.normalize(realpathSync2(evidenceDir));
1270
1485
  } catch (error) {
1271
1486
  throw new Error(`Unable to resolve evidence directory: ${error.message}`);
1272
1487
  }
1273
- const swarmPrefix = `${resolvedSwarmDir}${path2.sep}`;
1488
+ const swarmPrefix = `${resolvedSwarmDir}${path3.sep}`;
1274
1489
  const withinSwarmBoundary = process.platform === "win32" ? resolvedEvidenceDir.toLowerCase().startsWith(swarmPrefix.toLowerCase()) : resolvedEvidenceDir.startsWith(swarmPrefix);
1275
1490
  if (!withinSwarmBoundary) {
1276
1491
  throw new Error(`Evidence path escapes .swarm boundary: ${resolvedEvidenceDir}`);
@@ -1283,7 +1498,7 @@ function getEvidencePath(directory, taskId) {
1283
1498
  }
1284
1499
  function readExisting(evidencePath, taskId) {
1285
1500
  try {
1286
- const raw = readFileSync2(evidencePath, "utf-8");
1501
+ const raw = readFileSync3(evidencePath, "utf-8");
1287
1502
  return parseTaskEvidence(raw, taskId);
1288
1503
  } catch (error) {
1289
1504
  if (error.code === "ENOENT")
@@ -1399,7 +1614,7 @@ async function withTaskEvidenceTransaction(directory, taskId, agent, callback) {
1399
1614
  assertValidTaskId(taskId);
1400
1615
  return withTaskEvidenceLock(directory, taskId, agent, async () => {
1401
1616
  const resolvedEvidenceDir = getEvidenceDir(directory);
1402
- const evidencePath = path2.join(resolvedEvidenceDir, `${taskId}.json`);
1617
+ const evidencePath = path3.join(resolvedEvidenceDir, `${taskId}.json`);
1403
1618
  let current = null;
1404
1619
  try {
1405
1620
  current = readExisting(evidencePath, taskId);
@@ -1407,12 +1622,15 @@ async function withTaskEvidenceTransaction(directory, taskId, agent, callback) {
1407
1622
  telemetry.gateParseError(taskId, error);
1408
1623
  throw error;
1409
1624
  }
1410
- const persist = async (nextEvidence) => {
1625
+ const persist = async (nextEvidence, event) => {
1411
1626
  const validated = TaskEvidenceSchema.parse({
1412
1627
  ...nextEvidence,
1413
1628
  taskId
1414
1629
  });
1415
1630
  await atomicWriteFile(evidencePath, JSON.stringify(validated, null, 2));
1631
+ if (event) {
1632
+ await appendTaskGateRequirementsReceiptIfNeeded(directory, taskId, current, validated, event);
1633
+ }
1416
1634
  current = validated;
1417
1635
  return validated;
1418
1636
  };
@@ -1423,7 +1641,7 @@ async function withTaskEvidenceTransaction(directory, taskId, agent, callback) {
1423
1641
  assertTaskEvidenceWriteAllowed(directory, taskId, event);
1424
1642
  const nextEvidence = updateEvidenceForTransition(current, event);
1425
1643
  nextEvidence.taskId = taskId;
1426
- return persist(nextEvidence);
1644
+ return persist(nextEvidence, event);
1427
1645
  }
1428
1646
  });
1429
1647
  });
@@ -1480,7 +1698,7 @@ function readTaskEvidenceRaw(directory, taskId) {
1480
1698
  assertValidTaskId(taskId);
1481
1699
  const evidencePath = getEvidencePath(directory, taskId);
1482
1700
  try {
1483
- const raw = readFileSync2(evidencePath, "utf-8");
1701
+ const raw = readFileSync3(evidencePath, "utf-8");
1484
1702
  return parseTaskEvidence(raw, taskId);
1485
1703
  } catch (error) {
1486
1704
  const code = error.code;
@@ -7,7 +7,7 @@ import {
7
7
  } from "./index-zj6t9zgx.js";
8
8
  import {
9
9
  withEvidenceLock
10
- } from "./index-gf03198s.js";
10
+ } from "./index-bghwrr59.js";
11
11
  import {
12
12
  exports_external,
13
13
  init_zod
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  emit
4
- } from "./index-dppzthm9.js";
4
+ } from "./index-qyvjp0bq.js";
5
5
  import {
6
6
  require_proper_lockfile
7
7
  } from "./index-7g4c7s5r.js";
@@ -6,11 +6,11 @@ import {
6
6
  PluginConfigSchema,
7
7
  init_schema,
8
8
  stripKnownSwarmPrefix
9
- } from "./index-7axx11dt.js";
9
+ } from "./index-fay8h6v8.js";
10
10
  import {
11
11
  ALL_AGENT_NAMES,
12
12
  init_constants
13
- } from "./index-v3y3qg48.js";
13
+ } from "./index-cpg98bh1.js";
14
14
  import {
15
15
  log
16
16
  } from "./index-zgwm4ryv.js";
@@ -435,7 +435,23 @@ var init_tool_metadata = __esm(() => {
435
435
  ]
436
436
  },
437
437
  phase_complete: {
438
- description: "mark a phase as complete and track dispatched agents",
438
+ description: "preflight every applicable phase gate, report all blockers, and atomically commit a current passing snapshot",
439
+ agents: ["architect"]
440
+ },
441
+ run_phase_review: {
442
+ description: "run the bounded phase-final review engine and persist complete content-addressed review evidence",
443
+ agents: ["architect"]
444
+ },
445
+ repair_gate_evidence: {
446
+ description: "quarantine corrupt exact-task gate evidence and install a fresh blocked generation that requires every gate to rerun",
447
+ agents: ["architect"]
448
+ },
449
+ repair_knowledge_receipt_ledger: {
450
+ description: "validate or repair authoritative knowledge receipts, preserve corrupt authority in bounded quarantine, and require scoped re-evaluation",
451
+ agents: ["architect"]
452
+ },
453
+ record_directive_override: {
454
+ description: "record an audited architect override for identified critical-directive violations without bypassing unreadable authority",
439
455
  agents: ["architect"]
440
456
  },
441
457
  save_plan: {
@@ -3,7 +3,7 @@ import {
3
3
  EvaluationRunV1Schema,
4
4
  GateAuditResultV1Schema,
5
5
  getProtectedEvaluationRunIds
6
- } from "./index-fwnhh6s7.js";
6
+ } from "./index-nsr5b69r.js";
7
7
  import {
8
8
  loadDatabaseCtor
9
9
  } from "./index-134d35c1.js";
@@ -23,7 +23,7 @@ import {
23
23
  readTaskEvidence,
24
24
  readTaskEvidenceRaw,
25
25
  sanitizeTaskId
26
- } from "./index-41t3hgaa.js";
26
+ } from "./index-92cxd0r1.js";
27
27
  import {
28
28
  LedgerStaleWriterError,
29
29
  appendLedgerEvent,
@@ -43,7 +43,7 @@ import {
43
43
  replayFromLedgerWithStatus,
44
44
  takeSnapshotEvent,
45
45
  takeSnapshotWithRetry
46
- } from "./index-cqfp05jb.js";
46
+ } from "./index-fzqhn96z.js";
47
47
  import {
48
48
  init_executor,
49
49
  isUntrustedEnvKey,
@@ -56,7 +56,7 @@ import {
56
56
  } from "./index-gprxjmm7.js";
57
57
  import {
58
58
  PlanSchema
59
- } from "./index-17e73wac.js";
59
+ } from "./index-5qwmpamg.js";
60
60
  import {
61
61
  GIT_BINARY_ENV_VAR,
62
62
  describeGitResolution,
@@ -76,10 +76,10 @@ import {
76
76
  assertProjectRoot,
77
77
  tryAcquireLock,
78
78
  withEvidenceLock
79
- } from "./index-gf03198s.js";
79
+ } from "./index-bghwrr59.js";
80
80
  import {
81
81
  emit
82
- } from "./index-dppzthm9.js";
82
+ } from "./index-qyvjp0bq.js";
83
83
  import {
84
84
  ZodError,
85
85
  init_zod
@@ -2568,6 +2568,7 @@ async function savePlan(directory, plan, options) {
2568
2568
  const planHashForInit = computePlanHash(validated);
2569
2569
  if (!await ledgerExists(directory)) {
2570
2570
  try {
2571
+ options?.preCommitCheck?.();
2571
2572
  await initLedger(directory, planId, planHashForInit, validated);
2572
2573
  } catch (initErr) {
2573
2574
  const msg = initErr instanceof Error ? initErr.message : String(initErr);
@@ -2584,6 +2585,7 @@ async function savePlan(directory, plan, options) {
2584
2585
  let backupExists = false;
2585
2586
  if (existsSync4(oldLedgerPath)) {
2586
2587
  try {
2588
+ options?.preCommitCheck?.();
2587
2589
  renameSync2(oldLedgerPath, oldLedgerBackupPath);
2588
2590
  backupExists = true;
2589
2591
  } catch (renameErr) {
@@ -2593,6 +2595,7 @@ async function savePlan(directory, plan, options) {
2593
2595
  let initSucceeded = false;
2594
2596
  if (backupExists) {
2595
2597
  try {
2598
+ options?.preCommitCheck?.();
2596
2599
  await initLedger(directory, planId, planHashForInit, validated);
2597
2600
  initSucceeded = true;
2598
2601
  } catch (initErr) {
@@ -2731,6 +2734,7 @@ async function savePlan(directory, plan, options) {
2731
2734
  }
2732
2735
  try {
2733
2736
  for (const missing of missingTasks) {
2737
+ options?.preCommitCheck?.();
2734
2738
  const eventInput = {
2735
2739
  plan_id: derivePlanId(validated),
2736
2740
  event_type: "task_removed",
@@ -2768,6 +2772,7 @@ async function savePlan(directory, plan, options) {
2768
2772
  for (const task of phase.tasks) {
2769
2773
  const oldTask = oldTaskMap.get(task.id);
2770
2774
  if (oldTask && oldTask.status !== task.status) {
2775
+ options?.preCommitCheck?.();
2771
2776
  const eventInput = {
2772
2777
  plan_id: derivePlanId(validated),
2773
2778
  event_type: "task_status_changed",
@@ -2809,6 +2814,7 @@ async function savePlan(directory, plan, options) {
2809
2814
  const replayedBeforeProjection = await replayFromLedger(directory);
2810
2815
  const projectionCandidate = replayedBeforeProjection ? mergeStatusesTakingPrecedence(validated, replayedBeforeProjection, ledgerStatusTaskIds) : validated;
2811
2816
  if (replayedBeforeProjection && computePlanHash(replayedBeforeProjection) !== computePlanHash(projectionCandidate)) {
2817
+ options?.preCommitCheck?.();
2812
2818
  await takeSnapshotEvent(directory, projectionCandidate, {
2813
2819
  planHashAfter: computePlanHash(projectionCandidate),
2814
2820
  source: "savePlan_structural_projection"
@@ -2817,7 +2823,7 @@ async function savePlan(directory, plan, options) {
2817
2823
  const projectedPlan = projectionCandidate;
2818
2824
  const SNAPSHOT_INTERVAL = 50;
2819
2825
  const latestSeq = await getLatestLedgerSeq(directory);
2820
- if (latestSeq > 0 && latestSeq % SNAPSHOT_INTERVAL === 0) {
2826
+ if (!options?.preCommitCheck && latestSeq > 0 && latestSeq % SNAPSHOT_INTERVAL === 0) {
2821
2827
  await takeSnapshotWithRetry(directory, projectedPlan, {
2822
2828
  planHashAfter: computePlanHash(projectedPlan),
2823
2829
  source: "savePlan_manager"
@@ -2828,6 +2834,7 @@ async function savePlan(directory, plan, options) {
2828
2834
  const tempPath = path5.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
2829
2835
  try {
2830
2836
  await bunWrite(tempPath, JSON.stringify(projectedPlan, null, 2));
2837
+ options?.preCommitCheck?.();
2831
2838
  renameSync2(tempPath, planPath);
2832
2839
  } finally {
2833
2840
  try {
@@ -6,12 +6,12 @@ import {
6
6
  resolveSwarmKnowledgePath,
7
7
  transactKnowledge,
8
8
  wordBigrams
9
- } from "./index-qpke2x5h.js";
9
+ } from "./index-kfmee1cr.js";
10
10
  import {
11
11
  queryHistoricalOutcomes,
12
12
  readKnowledgeEvents,
13
13
  recordKnowledgeEvent
14
- } from "./index-ff66fbjt.js";
14
+ } from "./index-zd1mfygt.js";
15
15
  import {
16
16
  init_knowledge_types,
17
17
  isActiveStatus
@@ -224,11 +224,11 @@ async function maybeQuarantineOnContradiction(directory, entryId, threshold, win
224
224
  alreadyInactive: true
225
225
  };
226
226
  }
227
- const { quarantineEntry } = await import("./knowledge-validator-pe4ncrvj.js");
227
+ const { quarantineEntry } = await import("./knowledge-validator-707vsncy.js");
228
228
  let policyConfig;
229
229
  try {
230
- const { KnowledgeConfigSchema } = await import("./schema-pg85z06v.js");
231
- const { loadPluginConfigWithMeta } = await import("./index-b7ntt9cw.js");
230
+ const { KnowledgeConfigSchema } = await import("./schema-dnnm0p40.js");
231
+ const { loadPluginConfigWithMeta } = await import("./index-n6ke10ck.js");
232
232
  const { config: loadedConfig } = loadPluginConfigWithMeta(directory);
233
233
  policyConfig = KnowledgeConfigSchema.parse(loadedConfig.knowledge ?? {});
234
234
  } catch {
@@ -3,7 +3,7 @@ import {
3
3
  ALL_AGENT_NAMES,
4
4
  SUMMARIZER_EXEMPT_TOOL_NAMES,
5
5
  init_constants
6
- } from "./index-v3y3qg48.js";
6
+ } from "./index-cpg98bh1.js";
7
7
  import {
8
8
  OUTCOME_BLOCK_THRESHOLD,
9
9
  init_knowledge_types
@@ -21,7 +21,7 @@ var package_default;
21
21
  var init_package = __esm(() => {
22
22
  package_default = {
23
23
  name: "opencode-swarm",
24
- version: "7.145.1",
24
+ version: "7.146.0",
25
25
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
26
26
  main: "dist/index.js",
27
27
  types: "dist/index.d.ts",
@@ -129,9 +129,11 @@ var init_package = __esm(() => {
129
129
  "repro:1144": "bun scripts/repro-1144.mjs",
130
130
  "repro:1873": "bun build scripts/repro-1873-entry.ts --outdir dist-build-test/repro-1873 --target node --format esm && node scripts/repro-1873.mjs",
131
131
  "check:events": "bun run scripts/check-event-contract.ts",
132
+ "check:retention": "bun run scripts/check-retention-registry.ts",
132
133
  "check:test-file-cap": "bun run scripts/check-test-file-cap.ts",
133
134
  "check:gate-portability": "bun run scripts/check-gate-portability.ts",
134
- "check:bare-spawn": "bun run scripts/check-bare-executable-spawn.ts"
135
+ "check:bare-spawn": "bun run scripts/check-bare-executable-spawn.ts",
136
+ "check:memory-recall": "bun run scripts/memory-recall-regression.ts"
135
137
  },
136
138
  dependencies: {
137
139
  "@opencode-ai/plugin": "^1.18.3",
@@ -151,6 +153,14 @@ var init_package = __esm(() => {
151
153
  "bun-types": "1.3.8",
152
154
  "js-yaml": "^4.1.1",
153
155
  typescript: "^5.7.3"
156
+ },
157
+ peerDependencies: {
158
+ "@xenova/transformers": "^2.17.2"
159
+ },
160
+ peerDependenciesMeta: {
161
+ "@xenova/transformers": {
162
+ optional: true
163
+ }
154
164
  }
155
165
  };
156
166
  });
@@ -1011,8 +1021,18 @@ var init_schema = __esm(() => {
1011
1021
  mode: exports_external.literal("propose").default("propose")
1012
1022
  }).default({ mode: "propose" }),
1013
1023
  redaction: exports_external.object({
1014
- rejectDurableSecrets: exports_external.boolean().default(true)
1015
- }).default({ rejectDurableSecrets: true }),
1024
+ rejectDurableSecrets: exports_external.boolean().default(true),
1025
+ detectPii: exports_external.boolean().default(false),
1026
+ piiDetector: exports_external.enum(["regex", "ner"]).default("regex"),
1027
+ rejectDurablePii: exports_external.boolean().default(false),
1028
+ piiThreshold: exports_external.number().min(0).max(1).refine((v) => v < 1, "piiThreshold must be strictly less than 1 (rejection is score > threshold and scores never reach 1, so 1 would silently disable PII rejection)").default(0.7)
1029
+ }).default({
1030
+ rejectDurableSecrets: true,
1031
+ detectPii: false,
1032
+ piiDetector: "regex",
1033
+ rejectDurablePii: false,
1034
+ piiThreshold: 0.7
1035
+ }),
1016
1036
  maintenance: exports_external.object({
1017
1037
  lowUtilityMaxConfidence: exports_external.number().min(0).max(1).default(0.45),
1018
1038
  lowUtilityMinAgeDays: exports_external.number().int().min(1).max(3650).default(30),