opencode-swarm 7.156.0 → 7.157.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 (72) hide show
  1. package/dist/background/workspace-snapshot.d.ts +28 -0
  2. package/dist/cli/{coder-settlement-jm7024zm.js → coder-settlement-dz2x352d.js} +9 -9
  3. package/dist/cli/{config-doctor-q9v8yscr.js → config-doctor-4jxf9w9e.js} +3 -3
  4. package/dist/cli/{core-ev3bn503.js → core-xf2f087t.js} +2 -2
  5. package/dist/cli/{curation-policy-jabphe51.js → curation-policy-72qx868r.js} +4 -4
  6. package/dist/cli/{curator-llm-factory-cnatbky1.js → curator-llm-factory-7mfvey3x.js} +30 -30
  7. package/dist/cli/{curator-dnjf9ser.js → curator-pjjw3ja4.js} +30 -30
  8. package/dist/cli/{evidence-summary-service-5drv65qh.js → evidence-summary-service-5ffkbs50.js} +11 -11
  9. package/dist/cli/{gate-evidence-dcyvst7g.js → gate-evidence-ne9rbdtb.js} +5 -5
  10. package/dist/cli/{guardrail-explain-z8f6qhz2.js → guardrail-explain-b9vr4ta3.js} +31 -31
  11. package/dist/cli/{guardrail-log-zwec6ann.js → guardrail-log-hrt36jz5.js} +5 -5
  12. package/dist/cli/{guardrail-reset-ga6e11r9.js → guardrail-reset-pggm9hx4.js} +30 -30
  13. package/dist/cli/{hive-promoter-mpez5tqh.js → hive-promoter-7vxm11sm.js} +30 -30
  14. package/dist/cli/{index-fpg4tzf7.js → index-12e2hztp.js} +1 -1
  15. package/dist/cli/{index-sm2t1awr.js → index-1dzy1j4v.js} +2 -2
  16. package/dist/cli/{index-b91qwpms.js → index-2e60kmzg.js} +1 -1
  17. package/dist/cli/{index-vnn7qq8c.js → index-3f7hqtgg.js} +62 -1
  18. package/dist/cli/{index-17h6ewqp.js → index-3qpr16k2.js} +32 -32
  19. package/dist/cli/{index-98j6z038.js → index-3vqdt1sx.js} +5 -5
  20. package/dist/cli/{index-wn0xm2e8.js → index-4kd1nqd2.js} +8 -3
  21. package/dist/cli/{index-5w87j6j4.js → index-4w20thrc.js} +2 -2
  22. package/dist/cli/{index-5r3zrw81.js → index-61nkp124.js} +2 -2
  23. package/dist/cli/{index-6bqqzfbe.js → index-6sbx96v6.js} +2 -2
  24. package/dist/cli/{index-mdypz60w.js → index-79k7p589.js} +1 -1
  25. package/dist/cli/{index-00hyhg47.js → index-8n602qc2.js} +4 -4
  26. package/dist/cli/{index-fjcm6wwf.js → index-91ybfvy2.js} +1 -1
  27. package/dist/cli/{index-q2khkey7.js → index-93ymj3j5.js} +5 -5
  28. package/dist/cli/{index-myt57pht.js → index-9r7gp6cp.js} +5 -1
  29. package/dist/cli/{index-85p1850w.js → index-b5xm177r.js} +1 -1
  30. package/dist/cli/{index-0q8kywcf.js → index-dwkrdpz2.js} +1 -1
  31. package/dist/cli/{index-g37454vj.js → index-ebratyzr.js} +1 -1
  32. package/dist/cli/{index-6g6qwr8z.js → index-g0j2hnse.js} +5 -5
  33. package/dist/cli/{index-ppx8bnzd.js → index-gk6wpq41.js} +1463 -402
  34. package/dist/cli/{index-aqg7c1z9.js → index-gpf3cjre.js} +1 -1
  35. package/dist/cli/{index-dfmr6pj5.js → index-j3egsxa1.js} +6 -6
  36. package/dist/cli/{index-sfdg1xg5.js → index-n6ayyadp.js} +4 -4
  37. package/dist/cli/{index-fd7wj6fy.js → index-n7gv8m7v.js} +4 -4
  38. package/dist/cli/{index-68098cfj.js → index-nd22bsnt.js} +2 -2
  39. package/dist/cli/{index-gthnsbzf.js → index-ngn6jmad.js} +1 -1
  40. package/dist/cli/{index-xdy28ngt.js → index-nwkr6tvv.js} +17 -1
  41. package/dist/cli/{index-za6bb2fd.js → index-p0by16z8.js} +2 -2
  42. package/dist/cli/{index-164c64z8.js → index-q94gt4n9.js} +3 -3
  43. package/dist/cli/{index-4m3j9q9z.js → index-t0kxka8n.js} +1 -1
  44. package/dist/cli/{index-9n555qz4.js → index-tvtvhjh0.js} +4 -4
  45. package/dist/cli/{index-zdgdf0e9.js → index-vbqssmbs.js} +6 -6
  46. package/dist/cli/{index-ew6fykvv.js → index-xe6zbfps.js} +1 -1
  47. package/dist/cli/{index-kxk8cnx7.js → index-zq7pw6qg.js} +2 -2
  48. package/dist/cli/index.js +30 -30
  49. package/dist/cli/{knowledge-escalator-cq4e6v2j.js → knowledge-escalator-d65mctqy.js} +10 -10
  50. package/dist/cli/{knowledge-events-sr5fqqaq.js → knowledge-events-6aet71sp.js} +8 -8
  51. package/dist/cli/{knowledge-link-4frk38w8.js → knowledge-link-z9cchqdj.js} +3 -3
  52. package/dist/cli/{knowledge-store-2dww3dqz.js → knowledge-store-vvgxbakx.js} +4 -4
  53. package/dist/cli/{knowledge-validator-yprsj4ye.js → knowledge-validator-4fb6pbpn.js} +6 -6
  54. package/dist/cli/{model-preflight-b95w8wxy.js → model-preflight-cv9kvw8h.js} +1 -1
  55. package/dist/cli/{pending-delegations-7qvag076.js → pending-delegations-f52jtanf.js} +1 -1
  56. package/dist/cli/{pr-subscriptions-00evnffe.js → pr-subscriptions-76vg2xya.js} +2 -2
  57. package/dist/cli/{runner-gheaxd5r.js → runner-eagt6gf8.js} +4 -4
  58. package/dist/cli/{scan-cursor-6awybk8b.js → scan-cursor-q3530gc8.js} +5 -5
  59. package/dist/cli/{schema-bf3smw7k.js → schema-5zc62306.js} +2 -2
  60. package/dist/cli/{scope-persistence-kc42c6ph.js → scope-persistence-fzqf115q.js} +7 -7
  61. package/dist/cli/{skill-generator-9k1ztt7c.js → skill-generator-kh1z90tm.js} +12 -12
  62. package/dist/cli/{workspace-snapshot-8269e1p9.js → workspace-snapshot-yq0tc49d.js} +9 -1
  63. package/dist/cli/{worktree-collision-ownership-ej10dhwe.js → worktree-collision-ownership-2qxjtxt6.js} +3 -3
  64. package/dist/cli/{worktree-isolation-r7qqy6ca.js → worktree-isolation-40v34p0s.js} +30 -30
  65. package/dist/commands/registry.d.ts +1 -1
  66. package/dist/hooks/pr-workflow-gate.d.ts +291 -3
  67. package/dist/index.js +72 -70
  68. package/dist/tools/index.d.ts +1 -0
  69. package/dist/tools/invalidate-pr-feedback-publication.d.ts +20 -0
  70. package/dist/tools/manifest.d.ts +1 -0
  71. package/dist/tools/tool-metadata.d.ts +4 -0
  72. package/package.json +1 -1
@@ -6,21 +6,22 @@ import {
6
6
  resolveExecutableFromPath,
7
7
  runEvaluation,
8
8
  runExternalTool
9
- } from "./index-4m3j9q9z.js";
9
+ } from "./index-t0kxka8n.js";
10
10
  import {
11
11
  finalizeShellAuditForClose,
12
12
  isPolicyProtectedPath,
13
+ normalizeToolName,
13
14
  normalizeToolNameLowerCase,
14
15
  protectedRoots,
15
16
  redactDecisionLineForArchive,
16
17
  stableCanonicalStringify
17
- } from "./index-wn0xm2e8.js";
18
+ } from "./index-4kd1nqd2.js";
18
19
  import {
19
20
  detectStraySwarmDirs,
20
21
  readDoctorArtifact,
21
22
  removeStraySwarmDir,
22
23
  runConfigDoctor
23
- } from "./index-68098cfj.js";
24
+ } from "./index-nd22bsnt.js";
24
25
  import {
25
26
  MAX_TRANSIENT_RETRIES,
26
27
  archiveEvidence,
@@ -67,7 +68,7 @@ import {
67
68
  validateProjectRoot,
68
69
  validateSymlinkBoundary,
69
70
  validateTargetWithinRoot
70
- } from "./index-q2khkey7.js";
71
+ } from "./index-93ymj3j5.js";
71
72
  import {
72
73
  EvaluationTaskV1Schema,
73
74
  GateAuditManifestV1Schema,
@@ -84,7 +85,7 @@ import {
84
85
  saveGateAuditResult,
85
86
  savePromotionDecision,
86
87
  saveTaskSetSnapshot
87
- } from "./index-gthnsbzf.js";
88
+ } from "./index-ngn6jmad.js";
88
89
  import {
89
90
  loadDatabaseCtor
90
91
  } from "./index-134d35c1.js";
@@ -110,12 +111,12 @@ import {
110
111
  } from "./index-txdagbh7.js";
111
112
  import {
112
113
  readRecentEscalations
113
- } from "./index-6g6qwr8z.js";
114
+ } from "./index-g0j2hnse.js";
114
115
  import {
115
116
  alreadyCuratedThisGeneration,
116
117
  claimNextScanBatch,
117
118
  resolveCohortId
118
- } from "./index-sm2t1awr.js";
119
+ } from "./index-1dzy1j4v.js";
119
120
  import {
120
121
  CURATOR_INIT_PROMPT,
121
122
  CURATOR_PHASE_PROMPT,
@@ -139,7 +140,7 @@ import {
139
140
  listActive,
140
141
  subscribe,
141
142
  unsubscribe
142
- } from "./index-fjcm6wwf.js";
143
+ } from "./index-91ybfvy2.js";
143
144
  import {
144
145
  clearWorktreeMergeStatus,
145
146
  getAllWorktreeMergeFailures,
@@ -151,12 +152,12 @@ import {
151
152
  listCoderSettlementWalStates,
152
153
  recoverCoderSettlement,
153
154
  recoverStaleCoderSettlements
154
- } from "./index-zdgdf0e9.js";
155
+ } from "./index-vbqssmbs.js";
155
156
  import {
156
157
  WORKTREE_LIFECYCLE_LOCK_FILE,
157
158
  recordWorktreeProvisioningOwner,
158
159
  removeWorktreeProvisioningOwner
159
- } from "./index-0q8kywcf.js";
160
+ } from "./index-dwkrdpz2.js";
160
161
  import {
161
162
  BUNDLED_PROJECT_SKILL_ROOT,
162
163
  DEFAULT_SKILL_MIN_CONFIDENCE,
@@ -177,7 +178,7 @@ import {
177
178
  retireSkill,
178
179
  selectCandidateEntries,
179
180
  syncBundledProjectSkillsIfMissingAsync
180
- } from "./index-sfdg1xg5.js";
181
+ } from "./index-n6ayyadp.js";
181
182
  import {
182
183
  appendUnactionable,
183
184
  quarantineEntry,
@@ -188,11 +189,11 @@ import {
188
189
  validateActionableFields,
189
190
  validateLesson,
190
191
  validateSkillPath
191
- } from "./index-9n555qz4.js";
192
+ } from "./index-tvtvhjh0.js";
192
193
  import {
193
194
  authorizeCuration,
194
195
  buildConfigFingerprintInput
195
- } from "./index-aqg7c1z9.js";
196
+ } from "./index-gpf3cjre.js";
196
197
  import {
197
198
  cohortConfigFingerprint
198
199
  } from "./index-rtry5xyf.js";
@@ -223,12 +224,12 @@ import {
223
224
  transitionTaskWorkflowEvidence,
224
225
  withTaskEvidenceTransaction,
225
226
  writeWorkflowWalFile
226
- } from "./index-5r3zrw81.js";
227
+ } from "./index-61nkp124.js";
227
228
  import {
228
229
  makeWorktreeBranchName,
229
230
  provisionWorktree,
230
231
  removeWorktree
231
- } from "./index-za6bb2fd.js";
232
+ } from "./index-p0by16z8.js";
232
233
  import {
233
234
  DEFAULT_STALE_DELEGATION_TIMEOUT_MS,
234
235
  DELEGATION_COMPACTION_HIGH_WATER_BYTES,
@@ -243,7 +244,7 @@ import {
243
244
  scanBackgroundCoderReservationsForAdmission,
244
245
  scanDelegationsForRecovery,
245
246
  sweepStaleDelegations
246
- } from "./index-fpg4tzf7.js";
247
+ } from "./index-12e2hztp.js";
247
248
  import {
248
249
  compositeSessionKey,
249
250
  sessionKeySuffix
@@ -254,6 +255,7 @@ import {
254
255
  resolveCommitCountSinceAsync,
255
256
  resolveCurrentGitHead,
256
257
  resolveCurrentGitHeadAsync,
258
+ resolveCurrentLocalHeadRefAsync,
257
259
  resolveCurrentUpstreamPushTarget,
258
260
  resolveCurrentUpstreamPushTargetAsync,
259
261
  resolveCurrentUpstreamRemoteRef,
@@ -271,15 +273,17 @@ import {
271
273
  resolvePrWorkflowRevisionDigestDetailedAsync,
272
274
  resolveRemoteRefsContainingHead,
273
275
  resolveRemoteRefsContainingHeadAsync,
276
+ resolveRemoteUrlIdentity,
277
+ resolveRemoteUrlIdentityAsync,
274
278
  switchPrFeedbackTrackingCandidateAsync
275
- } from "./index-vnn7qq8c.js";
279
+ } from "./index-3f7hqtgg.js";
276
280
  import {
277
281
  MAX_PENDING_SCOPE_BINDINGS,
278
282
  canonicalWorkspaceIdentity,
279
283
  clearAllScopes,
280
284
  clearScopeBindingFromDisk,
281
285
  clearScopeBindings
282
- } from "./index-fd7wj6fy.js";
286
+ } from "./index-n7gv8m7v.js";
283
287
  import {
284
288
  appendLedgerEvent,
285
289
  computePlanHash,
@@ -294,7 +298,7 @@ import {
294
298
  readPlanEpochIdentity,
295
299
  replayFromLedgerWithStatus,
296
300
  takeSnapshotEvent
297
- } from "./index-mdypz60w.js";
301
+ } from "./index-79k7p589.js";
298
302
  import {
299
303
  CORE_EVENT_LOCKED,
300
304
  appendCoreEventSync,
@@ -304,7 +308,7 @@ import {
304
308
  hasSpecDriftAuditEvent,
305
309
  hasTaskRepairAuditEvent,
306
310
  readCoreEvents
307
- } from "./index-xdy28ngt.js";
311
+ } from "./index-nwkr6tvv.js";
308
312
  import {
309
313
  sanitizeDiagnosticText
310
314
  } from "./index-556ja8an.js";
@@ -353,7 +357,7 @@ import {
353
357
  transactFile,
354
358
  transactKnowledge,
355
359
  wordBigrams
356
- } from "./index-dfmr6pj5.js";
360
+ } from "./index-j3egsxa1.js";
357
361
  import {
358
362
  MAX_EVENT_LOG_ENTRIES,
359
363
  _internals as _internals2,
@@ -369,10 +373,10 @@ import {
369
373
  recordKnowledgeEvent,
370
374
  recordPhaseCloseIntent,
371
375
  resolveKnowledgeEventsPath
372
- } from "./index-98j6z038.js";
376
+ } from "./index-3vqdt1sx.js";
373
377
  import {
374
378
  resolveWorktreeIsolationConfig
375
- } from "./index-164c64z8.js";
379
+ } from "./index-q94gt4n9.js";
376
380
  import {
377
381
  RetrospectiveEvidenceSchema
378
382
  } from "./index-gprxjmm7.js";
@@ -395,7 +399,7 @@ import {
395
399
  init_loader,
396
400
  loadPluginConfig,
397
401
  loadPluginConfigWithMeta
398
- } from "./index-b91qwpms.js";
402
+ } from "./index-2e60kmzg.js";
399
403
  import {
400
404
  DEFAULT_HARNESS_EVOLUTION_CONFIG,
401
405
  DEFAULT_PR_REVIEW_RESILIENCE_CONFIG,
@@ -411,7 +415,7 @@ import {
411
415
  package_default,
412
416
  resolveAutoReviewConfig,
413
417
  stripKnownSwarmPrefix
414
- } from "./index-5w87j6j4.js";
418
+ } from "./index-4w20thrc.js";
415
419
  import {
416
420
  AGENT_TOOL_MAP,
417
421
  ALL_AGENT_NAMES,
@@ -425,7 +429,7 @@ import {
425
429
  init_agent_names,
426
430
  init_constants,
427
431
  init_tool_metadata
428
- } from "./index-myt57pht.js";
432
+ } from "./index-9r7gp6cp.js";
429
433
  import {
430
434
  init_git_executable,
431
435
  resolveGitExecutable,
@@ -451,10 +455,10 @@ import {
451
455
  resolveLinkDir,
452
456
  sanitizeLinkId,
453
457
  writeLinkPointer
454
- } from "./index-85p1850w.js";
458
+ } from "./index-b5xm177r.js";
455
459
  import {
456
460
  atomicWriteFile
457
- } from "./index-ew6fykvv.js";
461
+ } from "./index-xe6zbfps.js";
458
462
  import {
459
463
  KNOWLEDGE_SCHEMA_VERSION,
460
464
  OUTCOME_BLOCK_THRESHOLD,
@@ -466,7 +470,7 @@ import {
466
470
  atomicWriteSwarmFileSync,
467
471
  matchTempGrammar,
468
472
  parseTargetBasename
469
- } from "./index-6bqqzfbe.js";
473
+ } from "./index-6sbx96v6.js";
470
474
  import {
471
475
  assertProjectRoot,
472
476
  hasExplicitProjectBoundary,
@@ -6915,7 +6919,7 @@ async function commitTaskTerminalUnderPlanLock(options) {
6915
6919
 
6916
6920
  // src/hooks/pr-workflow-gate.ts
6917
6921
  init_zod();
6918
- import { createHash as createHash6, randomUUID as randomUUID2 } from "crypto";
6922
+ import { createHash as createHash7, randomUUID as randomUUID2 } from "crypto";
6919
6923
  import { readFileSync as readFileSync5, statSync as statSync5 } from "fs";
6920
6924
  import * as fsp2 from "fs/promises";
6921
6925
  import * as path12 from "path";
@@ -9121,6 +9125,108 @@ var _internals15 = {
9121
9125
  parsePorcelainV2: parsePorcelainV2Snapshot
9122
9126
  };
9123
9127
 
9128
+ // src/memory/redaction.ts
9129
+ import { createHash as createHash6 } from "crypto";
9130
+ var SECRET_PATTERNS = [
9131
+ { type: "openai_api_key", pattern: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
9132
+ {
9133
+ type: "github_token",
9134
+ pattern: /\b(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{20,}\b/g
9135
+ },
9136
+ { type: "aws_access_key_id", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
9137
+ {
9138
+ type: "private_key_block",
9139
+ pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g
9140
+ },
9141
+ {
9142
+ type: "authorization_bearer",
9143
+ pattern: /\bAuthorization\s*:\s*Bearer\s+[A-Za-z0-9._~+/=-]{12,}/gi
9144
+ },
9145
+ {
9146
+ type: "env_secret",
9147
+ pattern: /\b(?:[A-Z][A-Z0-9]+_)+(?:KEY|TOKEN|SECRET|PASSWORD)\b\s*=\s*["']?[^\s"'`]{8,}["']?/gi
9148
+ },
9149
+ { type: "gitlab_token", pattern: /\bgl(?:pat|ptt)-[A-Za-z0-9_-]{15,}\b/g },
9150
+ { type: "slack_token", pattern: /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g },
9151
+ {
9152
+ type: "jwt_token",
9153
+ pattern: /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g
9154
+ },
9155
+ {
9156
+ type: "aws_secret_access_key",
9157
+ pattern: /\b(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY|secret_access_key|SecretAccessKey)"?\s*[=:]\s*["']?[A-Za-z0-9/+=]{40}\b/g
9158
+ },
9159
+ {
9160
+ type: "aws_secret_access_key_context",
9161
+ pattern: /\bAKIA[0-9A-Z]{16}\b[^\n]{0,200}?\b[A-Za-z0-9/+=]{40}\b/g
9162
+ },
9163
+ {
9164
+ type: "stripe_secret_key",
9165
+ pattern: /\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\b/g
9166
+ },
9167
+ { type: "google_api_key", pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g },
9168
+ {
9169
+ type: "openssh_private_key_block",
9170
+ pattern: /-----BEGIN[ ]OPENSSH[ ]PRIVATE[ ]KEY-----[\s\S]*?-----END[ ]OPENSSH[ ]PRIVATE[ ]KEY-----/g
9171
+ }
9172
+ ];
9173
+ var REDACTION_POLICY_SALT = 2;
9174
+ function computeRedactionPolicyVersion(policy) {
9175
+ return REDACTION_POLICY_SALT * 1e6 + SECRET_PATTERNS.length * 2 + (policy.rejectDurableSecrets ? 1 : 0) + (policy.detectPii ? 4 : 0) + (policy.rejectDurablePii ? 8 : 0) + (policy.piiDetector === "ner" ? 16 : 0);
9176
+ }
9177
+ var FINGERPRINT_ALGORITHM_VERSION = 2;
9178
+ var LEGACY_FINGERPRINT_ALGORITHM_VERSION = 1;
9179
+ var _internals16 = {
9180
+ currentAlgorithmVersion: FINGERPRINT_ALGORITHM_VERSION
9181
+ };
9182
+ function classifyStoredFingerprintAlgorithmVersion(rawStoredVersion, currentVersion = _internals16.currentAlgorithmVersion) {
9183
+ const storedVersion = rawStoredVersion === undefined ? LEGACY_FINGERPRINT_ALGORITHM_VERSION : rawStoredVersion;
9184
+ if (typeof storedVersion !== "number" || !Number.isFinite(storedVersion)) {
9185
+ return { status: "unknown" };
9186
+ }
9187
+ return storedVersion === currentVersion ? { status: "comparable" } : { status: "mismatch", storedVersion, currentVersion };
9188
+ }
9189
+ function computeMemoryCohortFingerprint(input) {
9190
+ const canonical = stableCanonicalStringify(input);
9191
+ return createHash6("sha256").update(canonical).digest("hex").slice(0, 12);
9192
+ }
9193
+ function buildMemoryCohortFingerprintInput(config) {
9194
+ return {
9195
+ provider: config.provider,
9196
+ redaction_policy_version: computeRedactionPolicyVersion({
9197
+ rejectDurableSecrets: config.redaction.rejectDurableSecrets,
9198
+ detectPii: config.redaction.detectPii,
9199
+ rejectDurablePii: config.redaction.rejectDurablePii,
9200
+ piiDetector: config.redaction.piiDetector
9201
+ }),
9202
+ embedding_model: config.embeddings.model,
9203
+ embedding_dimension: config.embeddings.dimension,
9204
+ embedding_version: config.embeddings.version ?? "default"
9205
+ };
9206
+ }
9207
+ function findSecrets(text) {
9208
+ const findings = [];
9209
+ for (const { type, pattern } of SECRET_PATTERNS) {
9210
+ pattern.lastIndex = 0;
9211
+ for (const match of text.matchAll(pattern)) {
9212
+ if (match[0])
9213
+ findings.push({ type, match: match[0] });
9214
+ }
9215
+ }
9216
+ return findings;
9217
+ }
9218
+ function containsSecret(text) {
9219
+ return findSecrets(text).length > 0;
9220
+ }
9221
+ function redactSecrets(text) {
9222
+ let redacted = text;
9223
+ for (const { type, pattern } of SECRET_PATTERNS) {
9224
+ pattern.lastIndex = 0;
9225
+ redacted = redacted.replace(pattern, `[REDACTED:${type}]`);
9226
+ }
9227
+ return redacted;
9228
+ }
9229
+
9124
9230
  // src/hooks/pr-workflow-gate.ts
9125
9231
  init_tool_metadata();
9126
9232
  init_logger();
@@ -9229,6 +9335,10 @@ var PR_REVIEW_MICRO_LANE_FLOORS = {
9229
9335
  M: 6,
9230
9336
  L: PR_REVIEW_REQUIRED_MICRO_LANE_IDS.length
9231
9337
  };
9338
+ var MAX_PUBLICATION_HISTORY_GENERATIONS = 4;
9339
+ var MAX_PUBLICATION_ATTEMPTS = 8;
9340
+ var MAX_PUSH_ATTEMPT_DIAGNOSTIC_CHARS = 500;
9341
+ var PUBLICATION_SCHEMA_VERSION = 1;
9232
9342
  var GATE_SCHEMA_VERSION = 1;
9233
9343
  var MAX_TRACKED_SESSIONS3 = 200;
9234
9344
  var MAX_WORKFLOW_BATCHES = 128;
@@ -9375,6 +9485,86 @@ var PrFeedbackReadyToPublishRecordSchema = exports_external.object({
9375
9485
  remoteRef: exports_external.string().startsWith("refs/remotes/"),
9376
9486
  validatedAt: exports_external.string().min(1)
9377
9487
  }).strict();
9488
+ var PrFeedbackPublicationEvidenceJoinSchema = exports_external.object({
9489
+ stageAValidatedAt: exports_external.string().min(1),
9490
+ batches: exports_external.array(exports_external.object({
9491
+ phase: exports_external.enum([
9492
+ "stage-b-reviewer",
9493
+ "stage-b-test",
9494
+ "closeout-reviewer",
9495
+ "closeout-critic"
9496
+ ]),
9497
+ batchId: exports_external.string().min(1),
9498
+ laneId: exports_external.string().min(1)
9499
+ }).strict())
9500
+ }).strict();
9501
+ var PrFeedbackPublicationGenerationSchema = exports_external.object({
9502
+ schemaVersion: exports_external.literal(PUBLICATION_SCHEMA_VERSION),
9503
+ generation: exports_external.number().int().positive(),
9504
+ state: exports_external.enum([
9505
+ "reviewing",
9506
+ "armed",
9507
+ "invalidated",
9508
+ "push_in_flight",
9509
+ "published",
9510
+ "cancelled_without_publication"
9511
+ ]),
9512
+ workspaceIdentity: exports_external.string().min(1),
9513
+ sessionID: exports_external.string().min(1),
9514
+ prTargetUrl: exports_external.string().min(1).optional(),
9515
+ intakeHeadSha: exports_external.string().min(1),
9516
+ localHeadRef: exports_external.string().min(1),
9517
+ localHead: exports_external.string().min(1),
9518
+ remoteName: exports_external.string().min(1),
9519
+ remoteUrlIdentity: exports_external.string().min(1).optional(),
9520
+ remoteBranchRef: exports_external.string().startsWith("refs/heads/"),
9521
+ remoteRef: exports_external.string().startsWith("refs/remotes/"),
9522
+ revisionDigest: exports_external.string().min(1),
9523
+ evidence: PrFeedbackPublicationEvidenceJoinSchema,
9524
+ invalidationReason: exports_external.string().min(1).optional(),
9525
+ supersededByGeneration: exports_external.number().int().positive().optional(),
9526
+ createdAt: exports_external.string().min(1),
9527
+ armedAt: exports_external.string().min(1).optional(),
9528
+ invalidatedAt: exports_external.string().min(1).optional(),
9529
+ publishedAt: exports_external.string().min(1).optional(),
9530
+ cancelledAt: exports_external.string().min(1).optional()
9531
+ }).strict();
9532
+ var PrFeedbackPushAttemptSchema = exports_external.object({
9533
+ attemptId: exports_external.string().min(1),
9534
+ generation: exports_external.number().int().positive(),
9535
+ sessionID: exports_external.string().min(1),
9536
+ callID: exports_external.string().min(1).optional(),
9537
+ intentDigest: exports_external.string().regex(/^[0-9a-f]{64}$/),
9538
+ intent: exports_external.object({
9539
+ remote: exports_external.string().min(1),
9540
+ sourceSha: exports_external.string().min(1),
9541
+ destRef: exports_external.string().startsWith("refs/heads/")
9542
+ }).strict(),
9543
+ prePush: exports_external.object({
9544
+ localHead: exports_external.string().min(1),
9545
+ worktreeClean: exports_external.boolean(),
9546
+ remoteName: exports_external.string().min(1),
9547
+ remoteBranchRef: exports_external.string().startsWith("refs/heads/"),
9548
+ observedRemoteHead: exports_external.string().min(1).nullable()
9549
+ }).strict(),
9550
+ startedAt: exports_external.string().min(1),
9551
+ result: exports_external.object({
9552
+ outcome: exports_external.enum(["completed", "rejected", "uncertain", "cancelled"]),
9553
+ exitStatus: exports_external.union([exports_external.number().int(), exports_external.literal("not-observed")]),
9554
+ diagnostic: exports_external.string().max(MAX_PUSH_ATTEMPT_DIAGNOSTIC_CHARS),
9555
+ postPush: exports_external.object({
9556
+ localHead: exports_external.string().min(1).nullable(),
9557
+ observedRemoteHead: exports_external.string().min(1).nullable()
9558
+ }).strict(),
9559
+ completedAt: exports_external.string().min(1)
9560
+ }).strict().optional()
9561
+ }).strict();
9562
+ var PrFeedbackPublicationStateSchema = exports_external.object({
9563
+ schemaVersion: exports_external.literal(PUBLICATION_SCHEMA_VERSION),
9564
+ active: PrFeedbackPublicationGenerationSchema.optional(),
9565
+ history: exports_external.array(PrFeedbackPublicationGenerationSchema).max(MAX_PUBLICATION_HISTORY_GENERATIONS),
9566
+ attempts: exports_external.array(PrFeedbackPushAttemptSchema).max(MAX_PUBLICATION_ATTEMPTS)
9567
+ }).strict();
9378
9568
  var PrFeedbackInventoryAmendmentRecordSchema = exports_external.object({
9379
9569
  entry: exports_external.string().min(1),
9380
9570
  amendedAt: exports_external.string().min(1),
@@ -9483,6 +9673,7 @@ var PrWorkflowGateStateSchema = exports_external.object({
9483
9673
  prFeedbackStageA: PrFeedbackStageARecordSchema.optional(),
9484
9674
  prFeedbackGateBatches: exports_external.array(PrFeedbackGateBatchRecordSchema).max(MAX_WORKFLOW_BATCHES).optional(),
9485
9675
  prFeedbackReadyToPublish: PrFeedbackReadyToPublishRecordSchema.optional(),
9676
+ prFeedbackPublication: PrFeedbackPublicationStateSchema.optional(),
9486
9677
  prFeedbackRebindCount: exports_external.number().int().nonnegative().optional(),
9487
9678
  prFeedbackScopes: exports_external.array(PrFeedbackScopeDeclarationRecordSchema).max(MAX_WORKFLOW_BATCHES).optional()
9488
9679
  }).passthrough();
@@ -9785,14 +9976,49 @@ async function finalizeOverriddenProbeRetainedLanes(directory, sessionID, correl
9785
9976
  }
9786
9977
  async function abortPrWorkflow(directory, sessionID, options = { kind: "recovery", reason: "" }) {
9787
9978
  const recovery = await readPrWorkflowGateStateForRecovery(directory, sessionID);
9788
- if (!recovery)
9979
+ if (!recovery) {
9980
+ if (options.cancelPublication) {
9981
+ if (!options.reason.trim()) {
9982
+ throw new Error("BLOCKED: cancel_publication requires a non-empty reason; the cancellation reason is part of the durable audit trail");
9983
+ }
9984
+ const dangling = findDanglingLivePublicationGeneration(directory, sessionID);
9985
+ if (!dangling)
9986
+ throw noActiveGateError(sessionID);
9987
+ appendPublicationEvent(directory, {
9988
+ type: "pr_feedback_publication_cancelled",
9989
+ sessionID: normalizeSessionID(sessionID),
9990
+ generation: dangling.generation,
9991
+ reason: options.reason.trim(),
9992
+ stateFileAbsent: true
9993
+ });
9994
+ return {
9995
+ mode: "PR_FEEDBACK",
9996
+ openLanes: 0,
9997
+ stateSalvaged: false,
9998
+ stateSalvageDisclosure: "The gate state file was already absent; the live publication generation in the audit trail was recorded as cancelled_without_publication (event-only terminal)."
9999
+ };
10000
+ }
9789
10001
  throw noActiveGateError(sessionID);
10002
+ }
9790
10003
  const state = recovery.state;
10004
+ let cancelRevision = null;
9791
10005
  if (options.expectedMode && state.mode !== options.expectedMode) {
9792
10006
  throw wrongModeError(state, options.expectedMode);
9793
10007
  }
9794
- if (state.prFeedbackReadyToPublish || recovery.armedShapeUnreadable) {
9795
- throw new Error(`BLOCKED: ${state.mode} is armed for publication; abort is blocked. Complete the workflow with complete_pr_workflow (or push the bound commit first) before aborting.` + (recovery.armedShapeUnreadable ? " The publication-arming record is itself unreadable, so it is treated as armed (fail-closed)." : ""));
10008
+ if (options.cancelPublication) {
10009
+ if (options.kind === "force") {
10010
+ throw new Error('BLOCKED: cancel_publication cannot be combined with kind "force"; use kind "cancel-publication" with a reason');
10011
+ }
10012
+ if (!options.reason.trim()) {
10013
+ throw new Error("BLOCKED: cancel_publication requires a non-empty reason; the cancellation reason is part of the durable audit trail");
10014
+ }
10015
+ if (state.mode !== "PR_FEEDBACK" || !state.prFeedbackReadyToPublish && !recovery.armedShapeUnreadable && !state.prFeedbackPublication?.active) {
10016
+ throw new Error("BLOCKED: cancel_publication applies only to a PR_FEEDBACK workflow with a publication generation (armed, push_in_flight, or invalidated)");
10017
+ }
10018
+ cancelRevision = await cancelPrFeedbackPublication(directory, sessionID, options.reason.trim());
10019
+ }
10020
+ if ((state.prFeedbackReadyToPublish || recovery.armedShapeUnreadable) && !options.cancelPublication) {
10021
+ throw new Error(`BLOCKED: ${state.mode} is armed for publication; abort is blocked. Complete the workflow with complete_pr_workflow (or push the bound commit first) before aborting, or use the audited cancellation (abort_pr_workflow with cancel_publication and a reason).` + (recovery.armedShapeUnreadable ? " The publication-arming record is itself unreadable, so it is treated as armed (fail-closed)." : ""));
9796
10022
  }
9797
10023
  const laneSettlement = await settlePresumedStalePrWorkflowLanes(directory, state.sessionID);
9798
10024
  const probeRetainedLanes = laneSettlement.probedAliveLaneIds ?? [];
@@ -9841,7 +10067,7 @@ async function abortPrWorkflow(directory, sessionID, options = { kind: "recovery
9841
10067
  const casEscape = recovery.salvaged && !recovery.revisionSalvageable;
9842
10068
  await _test_exports2.beforeAbortClear?.();
9843
10069
  try {
9844
- await clearPrWorkflowGateState(directory, sessionID, casEscape ? undefined : state.revision, { allowSalvagedRead: recovery.salvaged });
10070
+ await clearPrWorkflowGateState(directory, sessionID, casEscape ? undefined : cancelRevision ?? state.revision, { allowSalvagedRead: recovery.salvaged });
9845
10071
  } catch (error2) {
9846
10072
  try {
9847
10073
  appendCoreEventSync(directory, {
@@ -10079,7 +10305,7 @@ async function readAndVerifyCoverageDisclosure(directory, state) {
10079
10305
  throw new Error("BLOCKED: PR_REVIEW partial base coverage disclosure path does not match its bound run");
10080
10306
  }
10081
10307
  const raw = await readBoundedSwarmRegularFile(directory, relativePath, PR_REVIEW_COVERAGE_DISCLOSURE_MAX_BYTES, "PR_REVIEW partial base coverage disclosure");
10082
- const digest2 = createHash6("sha256").update(raw, "utf8").digest("hex");
10308
+ const digest2 = createHash7("sha256").update(raw, "utf8").digest("hex");
10083
10309
  if (digest2 !== expectedDigest) {
10084
10310
  throw new Error("BLOCKED: PR_REVIEW partial base coverage disclosure digest does not match durable state");
10085
10311
  }
@@ -10159,6 +10385,897 @@ async function assertPrReviewValidationSettled(directory, sessionID, phase, gate
10159
10385
  }
10160
10386
  return state;
10161
10387
  }
10388
+ var PR_FEEDBACK_PHASE_ORDER = [
10389
+ "stage-b-reviewer",
10390
+ "stage-b-test",
10391
+ "closeout-reviewer",
10392
+ "closeout-critic"
10393
+ ];
10394
+ async function verifyPublicationIdentityComponent(directory, state, active, component) {
10395
+ switch (component) {
10396
+ case "digest": {
10397
+ try {
10398
+ const digest2 = await currentPrFeedbackRevisionDigest(directory, state);
10399
+ return digest2 === active.revisionDigest ? { kind: "intact" } : {
10400
+ kind: "drift",
10401
+ component,
10402
+ detail: `approved revision digest ${active.revisionDigest} vs current ${digest2}`
10403
+ };
10404
+ } catch (error2) {
10405
+ return {
10406
+ kind: "unresolvable",
10407
+ component,
10408
+ detail: String(error2?.message ?? error2)
10409
+ };
10410
+ }
10411
+ }
10412
+ case "head": {
10413
+ const head = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
10414
+ if (!head)
10415
+ return {
10416
+ kind: "unresolvable",
10417
+ component,
10418
+ detail: "HEAD resolution returned empty"
10419
+ };
10420
+ return head === active.localHead ? { kind: "intact" } : {
10421
+ kind: "drift",
10422
+ component,
10423
+ detail: `approved head ${active.localHead} vs current ${head}`
10424
+ };
10425
+ }
10426
+ case "worktree": {
10427
+ const clean = await _test_exports2.resolveIsWorkingTreeCleanAsync(directory);
10428
+ if (clean !== true && clean !== false)
10429
+ return {
10430
+ kind: "unresolvable",
10431
+ component,
10432
+ detail: "clean-status resolution failed"
10433
+ };
10434
+ return clean === true ? { kind: "intact" } : {
10435
+ kind: "drift",
10436
+ component,
10437
+ detail: "working tree or index is dirty"
10438
+ };
10439
+ }
10440
+ case "upstream": {
10441
+ const target = await _test_exports2.resolveCurrentUpstreamPushTargetAsync(directory);
10442
+ if (!target)
10443
+ return {
10444
+ kind: "unresolvable",
10445
+ component,
10446
+ detail: "upstream target resolution returned empty"
10447
+ };
10448
+ return target.remoteName === active.remoteName && target.remoteBranchRef === active.remoteBranchRef && target.remoteTrackingRef === active.remoteRef ? { kind: "intact" } : {
10449
+ kind: "drift",
10450
+ component,
10451
+ detail: `approved target ${active.remoteName}/${active.remoteBranchRef}/${active.remoteRef} vs current ${target.remoteName}/${target.remoteBranchRef}/${target.remoteTrackingRef}`
10452
+ };
10453
+ }
10454
+ case "remote-url": {
10455
+ if (!active.remoteUrlIdentity) {
10456
+ return {
10457
+ kind: "unresolvable",
10458
+ component,
10459
+ detail: "armed generation carries no remote URL identity"
10460
+ };
10461
+ }
10462
+ const url = await _test_exports2.resolveRemoteUrlIdentityAsync(directory, active.remoteName);
10463
+ if (!url)
10464
+ return {
10465
+ kind: "unresolvable",
10466
+ component,
10467
+ detail: `remote "${active.remoteName}" URL could not be resolved`
10468
+ };
10469
+ return url === active.remoteUrlIdentity ? { kind: "intact" } : {
10470
+ kind: "drift",
10471
+ component,
10472
+ detail: `approved remote URL identity ${active.remoteUrlIdentity} vs current ${url}`
10473
+ };
10474
+ }
10475
+ case "workspace-identity": {
10476
+ const identity = canonicalWorkspaceIdentity(directory);
10477
+ if (!identity)
10478
+ return {
10479
+ kind: "unresolvable",
10480
+ component,
10481
+ detail: "canonical workspace identity could not be resolved"
10482
+ };
10483
+ return identity === active.workspaceIdentity ? { kind: "intact" } : {
10484
+ kind: "drift",
10485
+ component,
10486
+ detail: `generation is bound to a different workspace`
10487
+ };
10488
+ }
10489
+ case "evidence-join": {
10490
+ return publicationEvidenceJoinIntact(state, active) ? { kind: "intact" } : {
10491
+ kind: "drift",
10492
+ component,
10493
+ detail: "the receipt set recorded at arming is no longer the active one"
10494
+ };
10495
+ }
10496
+ default:
10497
+ return { kind: "unresolvable", component, detail: "unknown component" };
10498
+ }
10499
+ }
10500
+ var PUBLICATION_IDENTITY_COMPONENTS = [
10501
+ "digest",
10502
+ "head",
10503
+ "worktree",
10504
+ "upstream",
10505
+ "remote-url",
10506
+ "workspace-identity"
10507
+ ];
10508
+ async function checkPublicationIdentity(directory, state, active) {
10509
+ for (const component of PUBLICATION_IDENTITY_COMPONENTS) {
10510
+ const check = await verifyPublicationIdentityComponent(directory, state, active, component);
10511
+ if (check.kind !== "intact")
10512
+ return check;
10513
+ }
10514
+ if (!publicationEvidenceJoinIntact(state, active)) {
10515
+ return {
10516
+ kind: "drift",
10517
+ component: "evidence-join",
10518
+ detail: "the receipt set recorded at arming is no longer the active one"
10519
+ };
10520
+ }
10521
+ return { kind: "intact" };
10522
+ }
10523
+ function publicationEvidenceJoinIntact(state, active) {
10524
+ if (state.prFeedbackStageA?.validatedAt !== active.evidence.stageAValidatedAt)
10525
+ return false;
10526
+ for (const join11 of active.evidence.batches) {
10527
+ const batch = [...state.prFeedbackGateBatches ?? []].reverse().find((candidate) => candidate.phase === join11.phase);
10528
+ if (!batch || batch.batchId !== join11.batchId || batch.laneId !== join11.laneId)
10529
+ return false;
10530
+ }
10531
+ return true;
10532
+ }
10533
+ function buildPublicationEvidenceJoin(state, currentDigest) {
10534
+ const stageA = state.prFeedbackStageA;
10535
+ if (!stageA || stageA.revisionDigest !== currentDigest || !stageA.validatedAt)
10536
+ return null;
10537
+ const batches = [];
10538
+ for (const phase of PR_FEEDBACK_PHASE_ORDER) {
10539
+ const batch = [...state.prFeedbackGateBatches ?? []].reverse().find((candidate) => candidate.phase === phase && candidate.revisionDigest === currentDigest);
10540
+ if (!batch)
10541
+ return null;
10542
+ batches.push({ phase, batchId: batch.batchId, laneId: batch.laneId });
10543
+ }
10544
+ return { stageAValidatedAt: stageA.validatedAt, batches };
10545
+ }
10546
+ function appendPublicationEvent(directory, event) {
10547
+ try {
10548
+ appendCoreEventSync(directory, { ...event, timestamp: isoNow() });
10549
+ } catch {}
10550
+ }
10551
+ function boundPublicationDiagnostic(text) {
10552
+ const redacted = redactSecrets(text);
10553
+ return redacted.length > MAX_PUSH_ATTEMPT_DIAGNOSTIC_CHARS ? `${redacted.slice(0, MAX_PUSH_ATTEMPT_DIAGNOSTIC_CHARS - 3)}...` : redacted;
10554
+ }
10555
+ function nextPublicationContainer(previous, active, historyAppends = [], attempts = []) {
10556
+ const history = [...previous?.history ?? [], ...historyAppends].slice(-MAX_PUBLICATION_HISTORY_GENERATIONS);
10557
+ return {
10558
+ schemaVersion: PUBLICATION_SCHEMA_VERSION,
10559
+ active,
10560
+ history,
10561
+ attempts: attempts.slice(-MAX_PUBLICATION_ATTEMPTS)
10562
+ };
10563
+ }
10564
+ async function invalidatePublicationGeneration(directory, sessionID, reason, options = {}) {
10565
+ const normalizedSessionID = normalizeSessionID(sessionID);
10566
+ return withSessionStateMutation(directory, normalizedSessionID, async () => {
10567
+ const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
10568
+ if (!state || state.mode !== "PR_FEEDBACK") {
10569
+ throw new Error("BLOCKED: PR_FEEDBACK publication invalidation requires an active PR_FEEDBACK gate");
10570
+ }
10571
+ return applyPublicationInvalidationWhileLocked(directory, state, reason, options);
10572
+ });
10573
+ }
10574
+ async function applyPublicationInvalidationWhileLocked(directory, state, reason, options = {}) {
10575
+ {
10576
+ const active = state.prFeedbackPublication?.active;
10577
+ const legacyRecord = active ? undefined : state.prFeedbackReadyToPublish;
10578
+ if (!active && !legacyRecord) {
10579
+ throw new Error("BLOCKED: no armed publication generation to invalidate");
10580
+ }
10581
+ if (active && active.state !== "armed" && active.state !== "push_in_flight") {
10582
+ throw new Error(`BLOCKED: publication generation ${active.generation} is already ${active.state}`);
10583
+ }
10584
+ if (options.driftReverification && options.drift && active) {
10585
+ const recheck = await verifyPublicationIdentityComponent(directory, state, active, options.drift.component);
10586
+ if (recheck.kind !== "drift") {
10587
+ throw new Error(`BLOCKED: PR_FEEDBACK publication drift on ${options.drift.component} did not re-confirm under the state lock (${recheck.kind}); no invalidation was recorded \u2014 retry from current state`);
10588
+ }
10589
+ options.drift = { component: recheck.component, detail: recheck.detail };
10590
+ }
10591
+ const now = isoNow();
10592
+ let attempts = (state.prFeedbackPublication?.attempts ?? []).map((attempt) => attempt.result ? attempt : {
10593
+ ...attempt,
10594
+ result: {
10595
+ outcome: options.finalizeInFlightAs ?? "uncertain",
10596
+ exitStatus: "not-observed",
10597
+ diagnostic: `finalized by publication invalidation (${reason})`,
10598
+ postPush: { localHead: null, observedRemoteHead: null },
10599
+ completedAt: now
10600
+ }
10601
+ });
10602
+ let invalidated;
10603
+ if (active) {
10604
+ invalidated = {
10605
+ ...active,
10606
+ state: "invalidated",
10607
+ invalidatedAt: now,
10608
+ invalidationReason: reason
10609
+ };
10610
+ } else if (legacyRecord) {
10611
+ invalidated = {
10612
+ schemaVersion: PUBLICATION_SCHEMA_VERSION,
10613
+ generation: 1,
10614
+ state: "invalidated",
10615
+ workspaceIdentity: canonicalWorkspaceIdentity(directory) ?? "unresolvable",
10616
+ sessionID: state.sessionID,
10617
+ intakeHeadSha: state.prHeadSha ?? "unknown",
10618
+ localHeadRef: "unknown",
10619
+ localHead: legacyRecord.localHead,
10620
+ remoteName: legacyRecord.remoteName,
10621
+ remoteUrlIdentity: undefined,
10622
+ remoteBranchRef: legacyRecord.remoteBranchRef,
10623
+ remoteRef: legacyRecord.remoteRef,
10624
+ revisionDigest: legacyRecord.revisionDigest,
10625
+ evidence: {
10626
+ stageAValidatedAt: state.prFeedbackStageA?.validatedAt ?? "unknown",
10627
+ batches: (state.prFeedbackGateBatches ?? []).map((batch) => ({
10628
+ phase: batch.phase,
10629
+ batchId: batch.batchId,
10630
+ laneId: batch.laneId
10631
+ }))
10632
+ },
10633
+ invalidationReason: reason,
10634
+ createdAt: legacyRecord.validatedAt,
10635
+ armedAt: legacyRecord.validatedAt,
10636
+ invalidatedAt: now
10637
+ };
10638
+ } else {
10639
+ throw new Error("BLOCKED: no armed publication generation to invalidate");
10640
+ }
10641
+ if (!active) {
10642
+ attempts = [];
10643
+ }
10644
+ const nextState = {
10645
+ ...state,
10646
+ updatedAt: now,
10647
+ prFeedbackStageA: undefined,
10648
+ prFeedbackVerifications: undefined,
10649
+ prFeedbackGateBatches: undefined,
10650
+ prFeedbackScopes: undefined,
10651
+ prFeedbackReadyToPublish: undefined,
10652
+ prFeedbackPublication: nextPublicationContainer(state.prFeedbackPublication, invalidated, [], attempts)
10653
+ };
10654
+ await writeStateWhileLocked(directory, nextState);
10655
+ appendPublicationEvent(directory, {
10656
+ type: "pr_feedback_publication_invalidated",
10657
+ sessionID: state.sessionID,
10658
+ generation: invalidated.generation,
10659
+ reason,
10660
+ previousState: active?.state ?? "armed",
10661
+ drift: options.drift ?? null,
10662
+ revisionDigest: invalidated.revisionDigest,
10663
+ localHead: invalidated.localHead,
10664
+ remoteName: invalidated.remoteName,
10665
+ remoteBranchRef: invalidated.remoteBranchRef,
10666
+ supersededBatchIds: invalidated.evidence.batches.map((b) => b.batchId)
10667
+ });
10668
+ return { generation: invalidated, state: nextState };
10669
+ }
10670
+ }
10671
+ async function ensurePublicationGenerationCurrent(directory, sessionID) {
10672
+ const normalizedSessionID = normalizeSessionID(sessionID);
10673
+ const state = await readPrWorkflowGateState(directory, normalizedSessionID);
10674
+ if (!state || state.mode !== "PR_FEEDBACK")
10675
+ return state;
10676
+ if (state.prFeedbackPublication || !state.prFeedbackReadyToPublish) {
10677
+ return state;
10678
+ }
10679
+ const legacy = state.prFeedbackReadyToPublish;
10680
+ return withSessionStateMutation(directory, normalizedSessionID, async () => {
10681
+ const locked = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
10682
+ if (!locked || locked.mode !== "PR_FEEDBACK")
10683
+ return locked ?? state;
10684
+ if (locked.prFeedbackPublication || !locked.prFeedbackReadyToPublish) {
10685
+ return locked;
10686
+ }
10687
+ const now = isoNow();
10688
+ const base = {
10689
+ schemaVersion: PUBLICATION_SCHEMA_VERSION,
10690
+ generation: 1,
10691
+ sessionID: locked.sessionID,
10692
+ prTargetUrl: locked.prFeedbackTargetUrl,
10693
+ intakeHeadSha: locked.prHeadSha ?? "unknown",
10694
+ revisionDigest: legacy.revisionDigest,
10695
+ evidence: buildPublicationEvidenceJoin(locked, legacy.revisionDigest) ?? {
10696
+ stageAValidatedAt: "unknown",
10697
+ batches: []
10698
+ },
10699
+ createdAt: legacy.validatedAt,
10700
+ armedAt: legacy.validatedAt
10701
+ };
10702
+ const mismatch = async (reason) => {
10703
+ const invalidated = {
10704
+ ...base,
10705
+ evidence: base.evidence.batches.length > 0 ? base.evidence : {
10706
+ stageAValidatedAt: locked.prFeedbackStageA?.validatedAt ?? "unknown",
10707
+ batches: (locked.prFeedbackGateBatches ?? []).map((batch) => ({
10708
+ phase: batch.phase,
10709
+ batchId: batch.batchId,
10710
+ laneId: batch.laneId
10711
+ }))
10712
+ },
10713
+ state: "invalidated",
10714
+ workspaceIdentity: canonicalWorkspaceIdentity(directory) ?? "unresolvable",
10715
+ localHeadRef: "unknown",
10716
+ localHead: legacy.localHead,
10717
+ remoteName: legacy.remoteName,
10718
+ remoteUrlIdentity: undefined,
10719
+ remoteBranchRef: legacy.remoteBranchRef,
10720
+ remoteRef: legacy.remoteRef,
10721
+ invalidationReason: reason,
10722
+ invalidatedAt: now
10723
+ };
10724
+ const nextState2 = {
10725
+ ...locked,
10726
+ updatedAt: now,
10727
+ prFeedbackStageA: undefined,
10728
+ prFeedbackVerifications: undefined,
10729
+ prFeedbackGateBatches: undefined,
10730
+ prFeedbackScopes: undefined,
10731
+ prFeedbackReadyToPublish: undefined,
10732
+ prFeedbackPublication: nextPublicationContainer(locked.prFeedbackPublication, invalidated)
10733
+ };
10734
+ await writeStateWhileLocked(directory, nextState2);
10735
+ appendPublicationEvent(directory, {
10736
+ type: "pr_feedback_publication_migrated",
10737
+ sessionID: locked.sessionID,
10738
+ generation: 1,
10739
+ outcome: "invalidated",
10740
+ reason
10741
+ });
10742
+ return nextState2;
10743
+ };
10744
+ if (locked.prFeedbackStageA?.revisionDigest !== legacy.revisionDigest || !(locked.prFeedbackGateBatches ?? []).some((batch) => batch.revisionDigest === legacy.revisionDigest)) {
10745
+ return mismatch("legacy-migration-receipt-mismatch");
10746
+ }
10747
+ const workspaceIdentity = canonicalWorkspaceIdentity(directory);
10748
+ if (!workspaceIdentity)
10749
+ return mismatch("legacy-migration-unresolvable");
10750
+ let digest2;
10751
+ try {
10752
+ digest2 = await currentPrFeedbackRevisionDigest(directory, locked);
10753
+ } catch {
10754
+ return mismatch("legacy-migration-unresolvable");
10755
+ }
10756
+ const head = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
10757
+ const target = await _test_exports2.resolveCurrentUpstreamPushTargetAsync(directory);
10758
+ const localHeadRef = await resolveCurrentLocalHeadRefAsync(directory);
10759
+ const remoteUrlIdentity = await _test_exports2.resolveRemoteUrlIdentityAsync(directory, legacy.remoteName);
10760
+ if (digest2 !== legacy.revisionDigest || head !== legacy.localHead || !target || target.remoteName !== legacy.remoteName || target.remoteBranchRef !== legacy.remoteBranchRef || target.remoteTrackingRef !== legacy.remoteRef || !localHeadRef || !remoteUrlIdentity) {
10761
+ return mismatch("legacy-migration-identity-mismatch");
10762
+ }
10763
+ const evidenceJoin = buildPublicationEvidenceJoin(locked, legacy.revisionDigest);
10764
+ if (!evidenceJoin) {
10765
+ return mismatch("legacy-migration-receipt-mismatch");
10766
+ }
10767
+ const upgraded = {
10768
+ ...base,
10769
+ evidence: evidenceJoin,
10770
+ state: "armed",
10771
+ workspaceIdentity,
10772
+ localHeadRef,
10773
+ localHead: legacy.localHead,
10774
+ remoteName: legacy.remoteName,
10775
+ remoteUrlIdentity,
10776
+ remoteBranchRef: legacy.remoteBranchRef,
10777
+ remoteRef: legacy.remoteRef
10778
+ };
10779
+ const nextState = {
10780
+ ...locked,
10781
+ updatedAt: now,
10782
+ prFeedbackPublication: nextPublicationContainer(locked.prFeedbackPublication, upgraded)
10783
+ };
10784
+ await writeStateWhileLocked(directory, nextState);
10785
+ appendPublicationEvent(directory, {
10786
+ type: "pr_feedback_publication_migrated",
10787
+ sessionID: locked.sessionID,
10788
+ generation: 1,
10789
+ outcome: "armed",
10790
+ reason: "legacy-record-proven-equivalent"
10791
+ });
10792
+ return nextState;
10793
+ });
10794
+ }
10795
+ async function reconcileForeignInFlightAttempt(directory, sessionID, currentCallId) {
10796
+ const normalizedSessionID = normalizeSessionID(sessionID);
10797
+ return withSessionStateMutation(directory, normalizedSessionID, async () => {
10798
+ const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
10799
+ const publication = state?.prFeedbackPublication;
10800
+ const active = publication?.active;
10801
+ if (!state || !publication || !active || active.state !== "push_in_flight" || !publication.attempts.some((attempt) => !attempt.result)) {
10802
+ return state;
10803
+ }
10804
+ const now = isoNow();
10805
+ const localHead = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
10806
+ const observedRemoteHead = await _test_exports2.resolveExactRemoteBranchHeadAsync(directory, active.remoteName, active.remoteBranchRef);
10807
+ const attempts = publication.attempts.map((attempt) => attempt.result ? attempt : {
10808
+ ...attempt,
10809
+ result: {
10810
+ outcome: "uncertain",
10811
+ exitStatus: "not-observed",
10812
+ diagnostic: boundPublicationDiagnostic(`recovered without an observed result${currentCallId && attempt.callID === currentCallId ? " (same call)" : ""}`),
10813
+ postPush: { localHead: localHead ?? null, observedRemoteHead },
10814
+ completedAt: now
10815
+ }
10816
+ });
10817
+ const nextState = {
10818
+ ...state,
10819
+ updatedAt: now,
10820
+ prFeedbackPublication: nextPublicationContainer(publication, { ...active, state: "armed" }, [], attempts)
10821
+ };
10822
+ await writeStateWhileLocked(directory, nextState);
10823
+ appendPublicationEvent(directory, {
10824
+ type: "pr_feedback_push_attempt_result",
10825
+ sessionID: state.sessionID,
10826
+ generation: active.generation,
10827
+ outcome: "uncertain",
10828
+ by: "reaper",
10829
+ observedRemoteHead
10830
+ });
10831
+ return nextState;
10832
+ });
10833
+ }
10834
+ async function invalidatePrFeedbackPublication(directory, sessionID, reason) {
10835
+ const trimmed = reason.trim();
10836
+ if (!trimmed) {
10837
+ throw new Error("BLOCKED: invalidate_pr_feedback_publication requires a non-empty reason; the reason is part of the durable audit trail");
10838
+ }
10839
+ await ensurePublicationGenerationCurrent(directory, sessionID);
10840
+ await reconcileForeignInFlightAttempt(directory, sessionID);
10841
+ const result = await invalidatePublicationGeneration(directory, sessionID, `controller-rework:${trimmed}`);
10842
+ return result.generation;
10843
+ }
10844
+ function describePrWorkflowPublicationSection(state) {
10845
+ const active = state.prFeedbackPublication?.active;
10846
+ const history = state.prFeedbackPublication?.history ?? [];
10847
+ const attempts = state.prFeedbackPublication?.attempts ?? [];
10848
+ if (!active && !state.prFeedbackReadyToPublish && history.length === 0) {
10849
+ return null;
10850
+ }
10851
+ const lines = [];
10852
+ if (state.prFeedbackReadyToPublish && !active) {
10853
+ lines.push("publication: legacy armed record awaiting generation migration (fail-closed until the next gated interaction migrates it)");
10854
+ }
10855
+ if (active) {
10856
+ lines.push(`publication: generation ${active.generation} state=${active.state}`);
10857
+ lines.push(` approved: ${active.localHead} -> ${active.remoteName} ${active.remoteBranchRef} (digest ${active.revisionDigest.slice(0, 12)}\u2026)`);
10858
+ if (active.remoteUrlIdentity) {
10859
+ lines.push(` remote url identity: ${active.remoteUrlIdentity}`);
10860
+ }
10861
+ if (active.state === "invalidated" && active.invalidationReason) {
10862
+ lines.push(` invalidated because: ${active.invalidationReason}`);
10863
+ }
10864
+ if (active.supersededByGeneration) {
10865
+ lines.push(` superseded by generation ${active.supersededByGeneration}`);
10866
+ }
10867
+ const generationAttempts = attempts.filter((attempt) => attempt.generation === active.generation);
10868
+ if (generationAttempts.length > 0) {
10869
+ const outcomes = generationAttempts.map((attempt) => attempt.result?.outcome ?? "in-flight");
10870
+ lines.push(` push attempts: ${generationAttempts.length} (${outcomes.join(", ")})`);
10871
+ }
10872
+ switch (active.state) {
10873
+ case "armed":
10874
+ lines.push(" next: run the exact approved push, then complete_pr_workflow");
10875
+ break;
10876
+ case "push_in_flight":
10877
+ lines.push(" next: a push attempt is in flight; the next gated interaction reconciles it (uncertain) and re-verifies the remote before any retry");
10878
+ break;
10879
+ case "invalidated":
10880
+ lines.push(" next: rerun Stage A and every independent gate on the corrected content, then arm a fresh generation with complete_pr_workflow; the exact scoped rework path reopens via prepare_pr_feedback_scope");
10881
+ break;
10882
+ case "published":
10883
+ lines.push(" terminal: published (verified remote head)");
10884
+ break;
10885
+ case "cancelled_without_publication":
10886
+ lines.push(" terminal: cancelled without publication");
10887
+ break;
10888
+ default:
10889
+ lines.push(" next: continue the ordered gates");
10890
+ }
10891
+ }
10892
+ if (history.length > 0) {
10893
+ const summary = history.map((generation) => `gen ${generation.generation}: ${generation.state}${generation.supersededByGeneration ? ` -> ${generation.supersededByGeneration}` : ""}`).join("; ");
10894
+ lines.push(` superseded generations: ${summary}`);
10895
+ }
10896
+ lines.push(" audit: full publication trail in the .swarm events store (pr_feedback_publication_*, pr_feedback_push_attempt_*, pr_feedback_published)");
10897
+ return lines.join(`
10898
+ `);
10899
+ }
10900
+ var PUBLICATION_EVENT_TYPES = new Set([
10901
+ "pr_feedback_publication_armed",
10902
+ "pr_feedback_publication_migrated",
10903
+ "pr_feedback_push_attempt_started",
10904
+ "pr_feedback_publication_invalidated",
10905
+ "pr_feedback_published",
10906
+ "pr_feedback_publication_cancelled"
10907
+ ]);
10908
+ function findDanglingLivePublicationGeneration(directory, sessionID) {
10909
+ let text;
10910
+ try {
10911
+ text = readCoreEvents(directory).text;
10912
+ } catch {
10913
+ return null;
10914
+ }
10915
+ if (!text.trim())
10916
+ return null;
10917
+ let dangling = null;
10918
+ for (const line of text.split(`
10919
+ `)) {
10920
+ if (!line.trim())
10921
+ continue;
10922
+ let event;
10923
+ try {
10924
+ event = JSON.parse(line);
10925
+ } catch {
10926
+ continue;
10927
+ }
10928
+ if (typeof event.type !== "string" || !PUBLICATION_EVENT_TYPES.has(event.type) || event.sessionID !== sessionID) {
10929
+ continue;
10930
+ }
10931
+ const generation = typeof event.generation === "number" ? event.generation : null;
10932
+ switch (event.type) {
10933
+ case "pr_feedback_publication_armed":
10934
+ case "pr_feedback_push_attempt_started":
10935
+ dangling = generation ? { generation } : dangling;
10936
+ break;
10937
+ case "pr_feedback_publication_migrated":
10938
+ if (event.outcome === "armed") {
10939
+ dangling = generation ? { generation } : dangling;
10940
+ } else {
10941
+ dangling = null;
10942
+ }
10943
+ break;
10944
+ default:
10945
+ dangling = null;
10946
+ break;
10947
+ }
10948
+ }
10949
+ return dangling;
10950
+ }
10951
+ function supersedeLivePublicationInPendingState(pending, reason) {
10952
+ const publication = pending.prFeedbackPublication;
10953
+ const active = publication?.active;
10954
+ const live = pending.prFeedbackReadyToPublish != null || active?.state === "armed" || active?.state === "push_in_flight";
10955
+ if (!live)
10956
+ return { state: pending, invalidationEvent: null };
10957
+ const now = isoNow();
10958
+ const attempts = (publication?.attempts ?? []).map((attempt) => attempt.result ? attempt : {
10959
+ ...attempt,
10960
+ result: {
10961
+ outcome: "uncertain",
10962
+ exitStatus: "not-observed",
10963
+ diagnostic: `finalized by publication invalidation (${reason})`,
10964
+ postPush: { localHead: null, observedRemoteHead: null },
10965
+ completedAt: now
10966
+ }
10967
+ });
10968
+ const invalidatedActive = active ? {
10969
+ ...active,
10970
+ state: "invalidated",
10971
+ invalidatedAt: now,
10972
+ invalidationReason: reason
10973
+ } : undefined;
10974
+ const nextState = {
10975
+ ...pending,
10976
+ updatedAt: now,
10977
+ prFeedbackReadyToPublish: undefined,
10978
+ prFeedbackVerifications: undefined,
10979
+ prFeedbackGateBatches: undefined,
10980
+ prFeedbackScopes: undefined,
10981
+ prFeedbackPublication: active ? nextPublicationContainer(publication, invalidatedActive, [], attempts) : pending.prFeedbackPublication
10982
+ };
10983
+ const invalidationEvent = active ? {
10984
+ type: "pr_feedback_publication_invalidated",
10985
+ sessionID: pending.sessionID,
10986
+ generation: active.generation,
10987
+ reason,
10988
+ previousState: active.state,
10989
+ drift: null,
10990
+ revisionDigest: active.revisionDigest,
10991
+ localHead: active.localHead,
10992
+ remoteName: active.remoteName,
10993
+ remoteBranchRef: active.remoteBranchRef,
10994
+ supersededBatchIds: active.evidence.batches.map((b) => b.batchId)
10995
+ } : null;
10996
+ return { state: nextState, invalidationEvent };
10997
+ }
10998
+ function parseExactBoundPushIntent(command, armed) {
10999
+ if (hasUnsafeShellControlSyntax(command)) {
11000
+ return { ok: false, reason: "shell-syntax" };
11001
+ }
11002
+ if (!armed.remoteBranchRef.startsWith("refs/heads/")) {
11003
+ return { ok: false, reason: "unbound-target" };
11004
+ }
11005
+ const tokens = command.trim().split(/\s+/);
11006
+ if (tokens.length !== 4 || tokens[0].toLowerCase() !== "git" || tokens[1].toLowerCase() !== "push" || tokens.some((token) => /["'\\]/.test(token))) {
11007
+ return { ok: false, reason: "token-shape" };
11008
+ }
11009
+ const [remoteToken, refspecToken] = [tokens[2], tokens[3]];
11010
+ if (remoteToken.startsWith("-") || refspecToken.startsWith("-")) {
11011
+ return { ok: false, reason: "flag-or-option" };
11012
+ }
11013
+ if (/[:@]/.test(remoteToken) || remoteToken.includes("://")) {
11014
+ return { ok: false, reason: "credential-bearing-remote" };
11015
+ }
11016
+ const refspecParts = refspecToken.split(":");
11017
+ if (refspecParts.length !== 2) {
11018
+ return {
11019
+ ok: false,
11020
+ reason: refspecParts.length > 2 ? "token-shape" : "invalid-dest-ref"
11021
+ };
11022
+ }
11023
+ const [sourceToken, destToken] = refspecParts;
11024
+ if (!destToken.startsWith("refs/heads/") || destToken === "refs/heads/") {
11025
+ return { ok: false, reason: "invalid-dest-ref" };
11026
+ }
11027
+ if (sourceToken === "") {
11028
+ return { ok: false, reason: "delete-refspec" };
11029
+ }
11030
+ if (sourceToken.includes("*") || destToken.includes("*")) {
11031
+ return { ok: false, reason: "wildcard-refspec" };
11032
+ }
11033
+ if (remoteToken !== armed.remoteName) {
11034
+ return { ok: false, reason: "remote-mismatch" };
11035
+ }
11036
+ if (sourceToken !== armed.localHead) {
11037
+ return { ok: false, reason: "source-mismatch" };
11038
+ }
11039
+ if (destToken !== armed.remoteBranchRef) {
11040
+ return { ok: false, reason: "branch-mismatch" };
11041
+ }
11042
+ const intent = {
11043
+ remote: remoteToken,
11044
+ sourceSha: sourceToken,
11045
+ destRef: destToken
11046
+ };
11047
+ return {
11048
+ ok: true,
11049
+ intent,
11050
+ digest: createHash7("sha256").update(JSON.stringify(intent), "utf8").digest("hex")
11051
+ };
11052
+ }
11053
+ async function admitPrFeedbackPushAttempt(directory, sessionID, callID, intent, intentDigest) {
11054
+ const normalizedSessionID = normalizeSessionID(sessionID);
11055
+ await withSessionStateMutation(directory, normalizedSessionID, async () => {
11056
+ const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
11057
+ const active = state?.prFeedbackPublication?.active;
11058
+ if (!state || state.mode !== "PR_FEEDBACK" || !active) {
11059
+ throw new Error("BLOCKED: PR_FEEDBACK push admission requires an armed publication generation");
11060
+ }
11061
+ if (active.state !== "armed") {
11062
+ throw new Error(`BLOCKED: PR_FEEDBACK push admission requires the armed state, not ${active.state}`);
11063
+ }
11064
+ const check = await checkPublicationIdentity(directory, state, active);
11065
+ if (check.kind === "unresolvable") {
11066
+ throw new Error(`BLOCKED: PR_FEEDBACK could not verify the armed publication identity component "${check.component}" (${check.detail}); the push was not admitted`);
11067
+ }
11068
+ if (check.kind === "drift") {
11069
+ const invalidation = await applyPublicationInvalidationWhileLocked(directory, state, `drift:${check.component}`, { drift: check });
11070
+ throw new Error(`BLOCKED: PR_FEEDBACK publication generation ${invalidation.generation.generation} was INVALIDATED because approved content identity drifted (${check.component}: ${check.detail}). Rerun Stage A and every independent gate, then arm a fresh generation with complete_pr_workflow.`);
11071
+ }
11072
+ const now = isoNow();
11073
+ if (intent.remote !== active.remoteName || intent.sourceSha !== active.localHead || intent.destRef !== active.remoteBranchRef) {
11074
+ throw new Error("BLOCKED: PR_FEEDBACK push intent does not match the armed publication generation under the state lock; the push was not admitted");
11075
+ }
11076
+ const observedRemoteHead = await _test_exports2.resolveExactRemoteBranchHeadAsync(directory, active.remoteName, active.remoteBranchRef);
11077
+ const localHead = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
11078
+ const worktreeClean = await _test_exports2.resolveIsWorkingTreeCleanAsync(directory);
11079
+ const baseAttempt = {
11080
+ attemptId: randomUUID2(),
11081
+ generation: active.generation,
11082
+ sessionID: state.sessionID,
11083
+ callID,
11084
+ intentDigest,
11085
+ intent: {
11086
+ remote: intent.remote,
11087
+ sourceSha: intent.sourceSha,
11088
+ destRef: intent.destRef
11089
+ },
11090
+ prePush: {
11091
+ localHead: active.localHead,
11092
+ worktreeClean: worktreeClean === true,
11093
+ remoteName: active.remoteName,
11094
+ remoteBranchRef: active.remoteBranchRef,
11095
+ observedRemoteHead
11096
+ },
11097
+ startedAt: now
11098
+ };
11099
+ const remoteAlreadyAtApprovedHead = observedRemoteHead?.toLowerCase() === active.localHead.toLowerCase();
11100
+ if (remoteAlreadyAtApprovedHead) {
11101
+ const attempt = {
11102
+ ...baseAttempt,
11103
+ result: {
11104
+ outcome: "completed",
11105
+ exitStatus: "not-observed",
11106
+ diagnostic: "remote branch already observed at the approved head (no-op push)",
11107
+ postPush: {
11108
+ localHead: localHead ?? null,
11109
+ observedRemoteHead: observedRemoteHead ?? null
11110
+ },
11111
+ completedAt: now
11112
+ }
11113
+ };
11114
+ const nextState2 = {
11115
+ ...state,
11116
+ updatedAt: now,
11117
+ prFeedbackPublication: nextPublicationContainer(state.prFeedbackPublication, active, [], [...state.prFeedbackPublication?.attempts ?? [], attempt])
11118
+ };
11119
+ await writeStateWhileLocked(directory, nextState2);
11120
+ appendPublicationEvent(directory, {
11121
+ type: "pr_feedback_push_attempt_result",
11122
+ sessionID: state.sessionID,
11123
+ generation: active.generation,
11124
+ outcome: "completed",
11125
+ by: "no-op-observation",
11126
+ observedRemoteHead
11127
+ });
11128
+ return;
11129
+ }
11130
+ const nextState = {
11131
+ ...state,
11132
+ updatedAt: now,
11133
+ prFeedbackPublication: nextPublicationContainer(state.prFeedbackPublication, { ...active, state: "push_in_flight" }, [], [...state.prFeedbackPublication?.attempts ?? [], baseAttempt])
11134
+ };
11135
+ await writeStateWhileLocked(directory, nextState);
11136
+ appendPublicationEvent(directory, {
11137
+ type: "pr_feedback_push_attempt_started",
11138
+ sessionID: state.sessionID,
11139
+ generation: active.generation,
11140
+ intentDigest,
11141
+ intent,
11142
+ observedRemoteHead
11143
+ });
11144
+ });
11145
+ const publication = await readPrWorkflowGateState(directory, normalizedSessionID);
11146
+ const attempts = publication?.prFeedbackPublication?.attempts ?? [];
11147
+ const last = attempts[attempts.length - 1];
11148
+ return last?.result?.outcome === "completed" ? { kind: "already-published-remotely" } : { kind: "started" };
11149
+ }
11150
+ function describeToolOutputText(output) {
11151
+ if (typeof output === "string")
11152
+ return output;
11153
+ if (output && typeof output === "object" && "output" in output && typeof output.output === "string") {
11154
+ return output.output;
11155
+ }
11156
+ try {
11157
+ return JSON.stringify(output) ?? "";
11158
+ } catch {
11159
+ return "";
11160
+ }
11161
+ }
11162
+ async function recordPrFeedbackPushAttemptResult(directory, input, command, output) {
11163
+ const normalizedTool = (normalizeToolName(input.tool) ?? input.tool).toLowerCase();
11164
+ if (normalizedTool !== "bash" && normalizedTool !== "shell")
11165
+ return;
11166
+ if (!/^\s*git\s+push/i.test(command))
11167
+ return;
11168
+ const normalizedSessionID = normalizeSessionID(input.sessionID);
11169
+ await withSessionStateMutation(directory, normalizedSessionID, async () => {
11170
+ const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
11171
+ const publication = state?.prFeedbackPublication;
11172
+ const active = publication?.active;
11173
+ if (!state || !publication || !active || active.state !== "push_in_flight" || !input.callID) {
11174
+ return;
11175
+ }
11176
+ const attemptIndex = publication.attempts.findIndex((attempt) => !attempt.result && attempt.callID === input.callID);
11177
+ if (attemptIndex < 0)
11178
+ return;
11179
+ const now = isoNow();
11180
+ const localHead = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
11181
+ const observedRemoteHead = await _test_exports2.resolveExactRemoteBranchHeadAsync(directory, active.remoteName, active.remoteBranchRef);
11182
+ const remoteVerifiedAtApprovedHead = observedRemoteHead?.toLowerCase() === active.localHead.toLowerCase();
11183
+ const metadataExit = output?.metadata?.exitCode;
11184
+ const exitStatus = typeof metadataExit === "number" && Number.isInteger(metadataExit) ? metadataExit : "not-observed";
11185
+ let outcome;
11186
+ if (remoteVerifiedAtApprovedHead) {
11187
+ outcome = "completed";
11188
+ } else if (exitStatus !== "not-observed" && exitStatus !== 0) {
11189
+ outcome = "rejected";
11190
+ } else {
11191
+ outcome = "uncertain";
11192
+ }
11193
+ const diagnostic = boundPublicationDiagnostic(remoteVerifiedAtApprovedHead ? `push result observed; remote branch verified at the approved head${exitStatus !== "not-observed" && exitStatus !== 0 ? ` (shell reported nonzero exit ${exitStatus}; the verified remote head is the publication truth)` : ""}` : `push result observed without remote verification at the approved head; exit status ${exitStatus === "not-observed" ? "not observed" : exitStatus}; output: ${describeToolOutputText(output)}`);
11194
+ const attempts = publication.attempts.map((attempt, index) => index === attemptIndex ? {
11195
+ ...attempt,
11196
+ result: {
11197
+ outcome,
11198
+ exitStatus,
11199
+ diagnostic,
11200
+ postPush: {
11201
+ localHead: localHead ?? null,
11202
+ observedRemoteHead: observedRemoteHead ?? null
11203
+ },
11204
+ completedAt: now
11205
+ }
11206
+ } : attempt);
11207
+ const nextState = {
11208
+ ...state,
11209
+ updatedAt: now,
11210
+ prFeedbackPublication: nextPublicationContainer(publication, { ...active, state: "armed" }, [], attempts)
11211
+ };
11212
+ await writeStateWhileLocked(directory, nextState);
11213
+ appendPublicationEvent(directory, {
11214
+ type: "pr_feedback_push_attempt_result",
11215
+ sessionID: state.sessionID,
11216
+ generation: active.generation,
11217
+ outcome,
11218
+ exitStatus,
11219
+ by: "tool-after",
11220
+ observedRemoteHead
11221
+ });
11222
+ });
11223
+ }
11224
+ async function cancelPrFeedbackPublication(directory, sessionID, reason) {
11225
+ const normalizedSessionID = normalizeSessionID(sessionID);
11226
+ let nextRevision = null;
11227
+ let cancelledGeneration = null;
11228
+ let cancelledAttemptsFinalized = 0;
11229
+ try {
11230
+ await withSessionStateMutation(directory, normalizedSessionID, async () => {
11231
+ const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
11232
+ const publication = state?.prFeedbackPublication;
11233
+ const active = publication?.active;
11234
+ if (!state || !publication || !active) {
11235
+ return;
11236
+ }
11237
+ if (active.state !== "armed" && active.state !== "push_in_flight" && active.state !== "invalidated") {
11238
+ return;
11239
+ }
11240
+ const now = isoNow();
11241
+ const observedRemoteHead = await _test_exports2.resolveExactRemoteBranchHeadAsync(directory, active.remoteName, active.remoteBranchRef);
11242
+ const attempts = publication.attempts.map((attempt) => attempt.result ? attempt : {
11243
+ ...attempt,
11244
+ result: {
11245
+ outcome: "cancelled",
11246
+ exitStatus: "not-observed",
11247
+ diagnostic: "finalized by publication cancellation",
11248
+ postPush: { localHead: null, observedRemoteHead },
11249
+ completedAt: now
11250
+ }
11251
+ });
11252
+ const cancelled = {
11253
+ ...active,
11254
+ state: "cancelled_without_publication",
11255
+ cancelledAt: now,
11256
+ invalidationReason: active.invalidationReason ?? `cancelled:${reason}`
11257
+ };
11258
+ const nextState = {
11259
+ ...state,
11260
+ updatedAt: now,
11261
+ prFeedbackReadyToPublish: undefined,
11262
+ prFeedbackPublication: nextPublicationContainer(publication, cancelled, [], attempts)
11263
+ };
11264
+ const written = await writeStateWhileLocked(directory, nextState);
11265
+ nextRevision = written.revision;
11266
+ cancelledGeneration = active.generation;
11267
+ cancelledAttemptsFinalized = attempts.filter((attempt) => attempt.result?.outcome === "cancelled").length;
11268
+ });
11269
+ } catch {}
11270
+ appendPublicationEvent(directory, {
11271
+ type: "pr_feedback_publication_cancelled",
11272
+ sessionID: normalizedSessionID,
11273
+ ...cancelledGeneration !== null ? { generation: cancelledGeneration } : {},
11274
+ reason,
11275
+ ...cancelledAttemptsFinalized > 0 ? { attemptsFinalized: cancelledAttemptsFinalized } : {}
11276
+ });
11277
+ return nextRevision;
11278
+ }
10162
11279
  var PR_REVIEW_HANDOFF_RELATIVE_PATH_PATTERN = /^pr-review\/([A-Za-z0-9][A-Za-z0-9._-]{0,127})\/feedback-handoff\.json$/;
10163
11280
  var PR_REVIEW_FEEDBACK_CONSENT_MAX_BYTES = 64 * 1024;
10164
11281
  var PR_REVIEW_RUN_RESERVATION_MAX_BYTES = 16 * 1024;
@@ -10281,7 +11398,7 @@ function prReviewFeedbackConsentRelativePath(runId) {
10281
11398
  return `pr-review/${runId}/feedback-consent.json`;
10282
11399
  }
10283
11400
  function hashPrReviewFindingIds(ids) {
10284
- return createHash6("sha256").update([...new Set(ids)].sort().join("\x00"), "utf8").digest("hex");
11401
+ return createHash7("sha256").update([...new Set(ids)].sort().join("\x00"), "utf8").digest("hex");
10285
11402
  }
10286
11403
  async function readPrReviewRunReservation(directory, runId) {
10287
11404
  try {
@@ -10353,7 +11470,7 @@ async function readPrReviewFeedbackHandoffArtifact(directory, relativePath) {
10353
11470
  }
10354
11471
  return {
10355
11472
  artifact: parsed.data,
10356
- digest: createHash6("sha256").update(raw, "utf8").digest("hex")
11473
+ digest: createHash7("sha256").update(raw, "utf8").digest("hex")
10357
11474
  };
10358
11475
  }
10359
11476
  var PrReviewFindingProjectionSchema = exports_external.object({
@@ -10414,7 +11531,7 @@ function assertMatchingPrReviewFeedbackConsent(record, input) {
10414
11531
  }
10415
11532
  }
10416
11533
  function workflowIdentity(state) {
10417
- return state.workflowInstanceId ?? `legacy-${createHash6("sha256").update(`${state.sessionID}\x00${state.mode}\x00${state.activatedAt}`).digest("hex").slice(0, 32)}`;
11534
+ return state.workflowInstanceId ?? `legacy-${createHash7("sha256").update(`${state.sessionID}\x00${state.mode}\x00${state.activatedAt}`).digest("hex").slice(0, 32)}`;
10418
11535
  }
10419
11536
  function sameHandoffIds(left, right) {
10420
11537
  const normalizedLeft = [...new Set(left)].sort();
@@ -10687,6 +11804,21 @@ var _test_exports2 = {
10687
11804
  resolveCurrentUpstreamPushTarget,
10688
11805
  resolveCurrentUpstreamPushTargetAsync,
10689
11806
  resolveCurrentUpstreamRemoteRef,
11807
+ resolveCurrentLocalHeadRefAsync,
11808
+ resolveRemoteUrlIdentity,
11809
+ resolveRemoteUrlIdentityAsync,
11810
+ parseExactBoundPushIntent,
11811
+ admitPrFeedbackPushAttempt,
11812
+ recordPrFeedbackPushAttemptResult,
11813
+ reconcileForeignInFlightAttempt,
11814
+ ensurePublicationGenerationCurrent,
11815
+ invalidatePublicationGeneration,
11816
+ invalidatePrFeedbackPublication,
11817
+ cancelPrFeedbackPublication,
11818
+ buildPublicationEvidenceJoin,
11819
+ nextPublicationContainer,
11820
+ supersedeLivePublicationInPendingState,
11821
+ describePrWorkflowPublicationSection,
10690
11822
  resolveExactRemoteBranchHead,
10691
11823
  resolveExactRemoteBranchHeadAsync,
10692
11824
  resolveCommitCountSince,
@@ -10778,6 +11910,7 @@ var PR_REVIEW_CONTROLLER_TOOLS = new Set([
10778
11910
  "write_pr_review_trigger_eval"
10779
11911
  ]);
10780
11912
  var PR_FEEDBACK_CONTROLLER_TOOLS = new Set([
11913
+ "invalidate_pr_feedback_publication",
10781
11914
  "prepare_pr_feedback_scope",
10782
11915
  "run_pr_feedback_stage_a"
10783
11916
  ]);
@@ -10936,6 +12069,16 @@ function normalizePrHeadSha(prHeadSha) {
10936
12069
  }
10937
12070
  return normalized;
10938
12071
  }
12072
+ async function currentPrFeedbackRevisionDigest(directory, state) {
12073
+ if (!state.prHeadSha) {
12074
+ throw new Error("BLOCKED: PR_FEEDBACK revision binding requires pr_head_sha");
12075
+ }
12076
+ const resolved = await resolvePrWorkflowRevisionDigestForGate(directory, state.prHeadSha);
12077
+ if (!resolved.ok) {
12078
+ throw new Error("BLOCKED: PR_FEEDBACK could not compute a bounded current-revision digest" + ` for pr_head_sha "${state.prHeadSha}"; ${describePrWorkflowRevisionDigestFailure(resolved)}`);
12079
+ }
12080
+ return resolved.digest;
12081
+ }
10939
12082
  function describePrWorkflowRevisionDigestFailure(failure) {
10940
12083
  const detail = failure.detail ? ` (${failure.detail})` : "";
10941
12084
  switch (failure.reason) {
@@ -12016,7 +13159,7 @@ function validateReviewerVerdictFields(fields) {
12016
13159
  return parsed.success ? [...parsed.data] : null;
12017
13160
  }
12018
13161
  function reviewerVerdictRowDigest(fields) {
12019
- return createHash6("sha256").update(fields.join("\x00")).digest("hex");
13162
+ return createHash7("sha256").update(fields.join("\x00")).digest("hex");
12020
13163
  }
12021
13164
  function parseLaneItemVerdicts(text, itemIds, phase, reviewerClaims) {
12022
13165
  return parsePrReviewVerdictRows(text, itemIds, phase, reviewerClaims).parsed;
@@ -12605,10 +13748,13 @@ async function readPrWorkflowGateStateForRecovery(directory, sessionID) {
12605
13748
  const salvagedUpdatedAt = exports_external.string().min(1).safeParse(rawRecord.updatedAt);
12606
13749
  const armedKeyPresent = rawRecord.prFeedbackReadyToPublish !== undefined;
12607
13750
  const salvagedArmed = PrFeedbackReadyToPublishRecordSchema.safeParse(rawRecord.prFeedbackReadyToPublish);
13751
+ const publicationKeyPresent = rawRecord.prFeedbackPublication !== undefined;
13752
+ const salvagedPublication = PrFeedbackPublicationStateSchema.safeParse(rawRecord.prFeedbackPublication);
13753
+ const publicationShapeUnreadable = publicationKeyPresent && !salvagedPublication.success;
12608
13754
  const salvagedCheckoutRecovery = PrWorkflowCheckoutRecoveryRecordSchema.safeParse(rawRecord.checkoutRecovery);
12609
- const armedShapeUnreadable = armedKeyPresent && !salvagedArmed.success;
13755
+ const armedShapeUnreadable = armedKeyPresent && !salvagedArmed.success || publicationShapeUnreadable;
12610
13756
  const schemaErrors = parsed.error.issues.slice(0, MAX_SALVAGED_SCHEMA_ERRORS).map((issue) => boundSalvagedSchemaError(`${issue.path.join(".") || "(root)"}: ${issue.message}`));
12611
- const disclosure = `DEGRADED: PR workflow gate state for session "${normalizedSessionID}" failed schema validation ` + `and was SALVAGED for recovery only (abort/status; write and completion paths still refuse it). ` + `Schema errors: ${schemaErrors.join("; ")}.` + (salvagedRevision.success ? "" : " state revision unsalvageable.") + (armedShapeUnreadable ? " prFeedbackReadyToPublish is present but unreadable; treated as ARMED (fail-closed)." : "");
13757
+ const disclosure = `DEGRADED: PR workflow gate state for session "${normalizedSessionID}" failed schema validation ` + `and was SALVAGED for recovery only (abort/status; write and completion paths still refuse it). ` + `Schema errors: ${schemaErrors.join("; ")}.` + (salvagedRevision.success ? "" : " state revision unsalvageable.") + (armedShapeUnreadable ? " prFeedbackReadyToPublish is present but unreadable; treated as ARMED (fail-closed)." : "") + (publicationShapeUnreadable ? " prFeedbackPublication is present but unreadable; treated as ARMED (fail-closed)." : "");
12612
13758
  return {
12613
13759
  state: {
12614
13760
  schemaVersion: GATE_SCHEMA_VERSION,
@@ -12619,6 +13765,7 @@ async function readPrWorkflowGateStateForRecovery(directory, sessionID) {
12619
13765
  updatedAt: salvagedUpdatedAt.success ? salvagedUpdatedAt.data : isoNow(),
12620
13766
  ...salvagedHead.success ? { prHeadSha: salvagedHead.data } : {},
12621
13767
  ...salvagedArmed.success ? { prFeedbackReadyToPublish: salvagedArmed.data } : {},
13768
+ ...salvagedPublication.success ? { prFeedbackPublication: salvagedPublication.data } : {},
12622
13769
  ...salvagedCheckoutRecovery.success ? { checkoutRecovery: salvagedCheckoutRecovery.data } : {}
12623
13770
  },
12624
13771
  salvaged: true,
@@ -12659,7 +13806,7 @@ function workflowGateStateRelativePath(sessionID) {
12659
13806
  function prWorkflowSessionFileStem(sessionID) {
12660
13807
  const normalized = normalizeSessionID(sessionID);
12661
13808
  const slug = normalized.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 80) || "session";
12662
- const digest2 = createHash6("sha256").update(normalized).digest("hex").slice(0, 12);
13809
+ const digest2 = createHash7("sha256").update(normalized).digest("hex").slice(0, 12);
12663
13810
  return `${slug}-${digest2}`;
12664
13811
  }
12665
13812
  function normalizeSessionID(sessionID) {
@@ -12829,6 +13976,14 @@ var USAGE = [
12829
13976
  "Refuses while the workflow is armed for publication (call complete_pr_workflow",
12830
13977
  "instead) or while PR workflow lanes are still in flight (collect their results first).",
12831
13978
  "",
13979
+ "Armed publication (issue #2108): to CHANGE approved content after arming, the agent",
13980
+ "should use the invalidate_pr_feedback_publication tool (audited invalidation; the",
13981
+ "full Stage A + independent-gate ladder re-runs). To CANCEL an armed PR_FEEDBACK",
13982
+ 'workflow without publication, the agent tool supports kind "cancel-publication" with',
13983
+ "cancel_publication: true and a reason \u2014 the publication generation is recorded as",
13984
+ "cancelled_without_publication (terminal; never grants push authority) before the gate",
13985
+ "clears. A plain (recovery or force) abort never clears an armed window.",
13986
+ "",
12832
13987
  "Lane liveness (issue #2251): a lane past the 30-minute staleness horizon whose",
12833
13988
  "session the host still reports as busy or retrying is RETAINED rather than settled,",
12834
13989
  "and keeps blocking every exit. Because nothing ever makes such a lane go idle on a",
@@ -12881,11 +14036,11 @@ ${USAGE}`;
12881
14036
  }
12882
14037
 
12883
14038
  // src/services/spec-drift-recovery.ts
12884
- import { createHash as createHash7 } from "crypto";
14039
+ import { createHash as createHash8 } from "crypto";
12885
14040
  import { mkdir as mkdir4, readFile as readFile4, unlink as unlink2 } from "fs/promises";
12886
14041
  import { dirname as dirname10 } from "path";
12887
14042
  var SPEC_DRIFT_RECOVERY_AGENT = "spec-drift-recovery";
12888
- var _internals16 = {
14043
+ var _internals17 = {
12889
14044
  appendEvent,
12890
14045
  assertProjectRoot,
12891
14046
  bunWrite,
@@ -12910,7 +14065,7 @@ function now() {
12910
14065
  return new Date().toISOString();
12911
14066
  }
12912
14067
  function sha2562(text) {
12913
- return createHash7("sha256").update(text, "utf-8").digest("hex");
14068
+ return createHash8("sha256").update(text, "utf-8").digest("hex");
12914
14069
  }
12915
14070
  function parseMarker(raw) {
12916
14071
  try {
@@ -12969,22 +14124,22 @@ async function writeWal3(walPath, wal) {
12969
14124
  }
12970
14125
  async function verifySnapshot(snapshotPath, currentSpec) {
12971
14126
  if (!currentSpec) {
12972
- await _internals16.unlinkIfExists(snapshotPath);
12973
- const stillExists = await _internals16.readFileText(snapshotPath) !== null;
14127
+ await _internals17.unlinkIfExists(snapshotPath);
14128
+ const stillExists = await _internals17.readFileText(snapshotPath) !== null;
12974
14129
  if (stillExists) {
12975
14130
  throw new Error("spec snapshot verification failed: snapshot still exists after delete");
12976
14131
  }
12977
14132
  return;
12978
14133
  }
12979
14134
  await atomicWriteFile(snapshotPath, currentSpec.content);
12980
- const written = await _internals16.readFileText(snapshotPath);
14135
+ const written = await _internals17.readFileText(snapshotPath);
12981
14136
  if (written !== currentSpec.content) {
12982
14137
  throw new Error("spec snapshot verification failed: snapshot content does not match effective spec");
12983
14138
  }
12984
14139
  }
12985
14140
  async function ensureSnapshotEvent(directory, plan, transitionId) {
12986
- const ledgerPath = _internals16.validateSwarmPath(directory, "plan-ledger.jsonl");
12987
- const raw = await _internals16.readFileText(ledgerPath);
14141
+ const ledgerPath = _internals17.validateSwarmPath(directory, "plan-ledger.jsonl");
14142
+ const raw = await _internals17.readFileText(ledgerPath);
12988
14143
  if (raw !== null) {
12989
14144
  for (const line of raw.split(`
12990
14145
  `)) {
@@ -13004,17 +14159,17 @@ async function ensureSnapshotEvent(directory, plan, transitionId) {
13004
14159
  }
13005
14160
  }
13006
14161
  }
13007
- await _internals16.takeSnapshotEvent(directory, plan, {
14162
+ await _internals17.takeSnapshotEvent(directory, plan, {
13008
14163
  source: "spec_drift_recovery",
13009
14164
  approvalMetadata: { specDriftTransitionId: transitionId }
13010
14165
  });
13011
14166
  }
13012
14167
  async function appendEvent(directory, event) {
13013
- const existing = await _internals16.verifyEventPresence(directory, event.type, event.transitionId);
14168
+ const existing = await _internals17.verifyEventPresence(directory, event.type, event.transitionId);
13014
14169
  if (existing)
13015
14170
  return;
13016
14171
  appendCoreEventSync(directory, { ...event }, { dedupeOnAuthorityKey: true });
13017
- const verified = await _internals16.verifyEventPresence(directory, event.type, event.transitionId);
14172
+ const verified = await _internals17.verifyEventPresence(directory, event.type, event.transitionId);
13018
14173
  if (!verified) {
13019
14174
  throw new Error(`spec drift audit verification failed for transition ${event.transitionId}`);
13020
14175
  }
@@ -13036,7 +14191,7 @@ function buildRecoveryEvent(args) {
13036
14191
  if (args.mode === "acknowledge") {
13037
14192
  return {
13038
14193
  type: "spec_drift_acknowledged",
13039
- timestamp: _internals16.now(),
14194
+ timestamp: _internals17.now(),
13040
14195
  phase: args.phase,
13041
14196
  planTitle: args.planTitle,
13042
14197
  acknowledgedBy: args.actor === "spec_write" ? "unknown" : args.actor,
@@ -13048,7 +14203,7 @@ function buildRecoveryEvent(args) {
13048
14203
  }
13049
14204
  return {
13050
14205
  type: "spec_drift_repaired",
13051
- timestamp: _internals16.now(),
14206
+ timestamp: _internals17.now(),
13052
14207
  phase: args.phase,
13053
14208
  planTitle: args.planTitle,
13054
14209
  repairedBy: args.actor,
@@ -13059,11 +14214,11 @@ function buildRecoveryEvent(args) {
13059
14214
  };
13060
14215
  }
13061
14216
  async function reconcileSpecDrift(directory, options) {
13062
- _internals16.assertProjectRoot(directory);
13063
- const markerPath = _internals16.validateSwarmPath(directory, "spec-staleness.json");
13064
- const walPath = _internals16.validateSwarmPath(directory, "spec-drift-recovery.json");
13065
- const snapshotPath = _internals16.validateSwarmPath(directory, "spec-snapshot.md");
13066
- const markerMaybe = await _internals16.readFileText(markerPath);
14217
+ _internals17.assertProjectRoot(directory);
14218
+ const markerPath = _internals17.validateSwarmPath(directory, "spec-staleness.json");
14219
+ const walPath = _internals17.validateSwarmPath(directory, "spec-drift-recovery.json");
14220
+ const snapshotPath = _internals17.validateSwarmPath(directory, "spec-snapshot.md");
14221
+ const markerMaybe = await _internals17.readFileText(markerPath);
13067
14222
  if (markerMaybe === null) {
13068
14223
  return {
13069
14224
  status: "no_marker",
@@ -13071,7 +14226,7 @@ async function reconcileSpecDrift(directory, options) {
13071
14226
  message: "No spec drift detected."
13072
14227
  };
13073
14228
  }
13074
- const specLockResult = options.specLockAlreadyHeld ? null : await _internals16.tryAcquireLock(directory, "spec.md", SPEC_DRIFT_RECOVERY_AGENT, `spec-${options.mode}-${Date.now()}`);
14229
+ const specLockResult = options.specLockAlreadyHeld ? null : await _internals17.tryAcquireLock(directory, "spec.md", SPEC_DRIFT_RECOVERY_AGENT, `spec-${options.mode}-${Date.now()}`);
13075
14230
  if (specLockResult && !specLockResult.acquired) {
13076
14231
  return {
13077
14232
  status: "retry_later",
@@ -13081,7 +14236,7 @@ async function reconcileSpecDrift(directory, options) {
13081
14236
  }
13082
14237
  let lockResult;
13083
14238
  try {
13084
- lockResult = await _internals16.tryAcquireLock(directory, "plan.json", SPEC_DRIFT_RECOVERY_AGENT, `${options.mode}-${Date.now()}`);
14239
+ lockResult = await _internals17.tryAcquireLock(directory, "plan.json", SPEC_DRIFT_RECOVERY_AGENT, `${options.mode}-${Date.now()}`);
13085
14240
  } catch (error2) {
13086
14241
  if (specLockResult?.acquired && specLockResult.lock._release) {
13087
14242
  await specLockResult.lock._release().catch(() => {});
@@ -13107,7 +14262,7 @@ async function reconcileSpecDrift(directory, options) {
13107
14262
  let errorNewHash;
13108
14263
  try {
13109
14264
  try {
13110
- const authoritativeMarkerRaw = await _internals16.readFileText(markerPath);
14265
+ const authoritativeMarkerRaw = await _internals17.readFileText(markerPath);
13111
14266
  if (authoritativeMarkerRaw === null) {
13112
14267
  return {
13113
14268
  status: "no_marker",
@@ -13115,14 +14270,14 @@ async function reconcileSpecDrift(directory, options) {
13115
14270
  message: "No spec drift detected."
13116
14271
  };
13117
14272
  }
13118
- const marker = _internals16.parseMarker(authoritativeMarkerRaw);
14273
+ const marker = _internals17.parseMarker(authoritativeMarkerRaw);
13119
14274
  if (!marker) {
13120
14275
  return buildCorruptMarkerResult(options.mode);
13121
14276
  }
13122
14277
  errorMarker = marker;
13123
14278
  const markerHash = sha2562(authoritativeMarkerRaw);
13124
- const existingWalRaw = await _internals16.readFileText(walPath);
13125
- const existingWal = existingWalRaw === null ? null : _internals16.parseWal(existingWalRaw);
14279
+ const existingWalRaw = await _internals17.readFileText(walPath);
14280
+ const existingWal = existingWalRaw === null ? null : _internals17.parseWal(existingWalRaw);
13126
14281
  if (existingWalRaw !== null && !existingWal) {
13127
14282
  return {
13128
14283
  status: "failed",
@@ -13132,7 +14287,7 @@ async function reconcileSpecDrift(directory, options) {
13132
14287
  planTitle: marker.planTitle
13133
14288
  };
13134
14289
  }
13135
- const currentSpec = _internals16.readEffectiveSpecSync(directory);
14290
+ const currentSpec = _internals17.readEffectiveSpecSync(directory);
13136
14291
  const proposedNewHash = currentSpec?.hash ?? null;
13137
14292
  const proposedTransitionId = buildTransitionId(options.mode, markerHash, marker.specHash_plan, proposedNewHash);
13138
14293
  const proposedWal = {
@@ -13147,7 +14302,7 @@ async function reconcileSpecDrift(directory, options) {
13147
14302
  newHash: proposedNewHash,
13148
14303
  specContent: currentSpec?.content ?? null,
13149
14304
  actor: options.actor,
13150
- recordedAt: _internals16.now()
14305
+ recordedAt: _internals17.now()
13151
14306
  };
13152
14307
  const markerReplacedDuringPrepared = existingWal?.state === "PREPARED" && existingWal.markerHash !== markerHash;
13153
14308
  const wal = existingWal?.state === "PREPARED" || existingWal?.markerHash === markerHash ? existingWal : proposedWal;
@@ -13156,12 +14311,12 @@ async function reconcileSpecDrift(directory, options) {
13156
14311
  errorTransitionId = transitionId;
13157
14312
  errorNewHash = newHash;
13158
14313
  if (wal === proposedWal) {
13159
- await _internals16.writeWal(walPath, wal);
14314
+ await _internals17.writeWal(walPath, wal);
13160
14315
  }
13161
14316
  if (wal.newHash === null !== (wal.specContent === null) || wal.specContent !== null && sha2562(wal.specContent) !== wal.newHash) {
13162
14317
  throw new Error(`Spec drift recovery WAL ${transitionId} has inconsistent captured spec content`);
13163
14318
  }
13164
- let plan = await _internals16.loadPlanJsonOnly(directory);
14319
+ let plan = await _internals17.loadPlanJsonOnly(directory);
13165
14320
  if (!plan) {
13166
14321
  return {
13167
14322
  status: "failed",
@@ -13192,13 +14347,13 @@ async function reconcileSpecDrift(directory, options) {
13192
14347
  }
13193
14348
  if (planMatchesOld) {
13194
14349
  plan.specHash = newHash ?? undefined;
13195
- await _internals16.savePlan(directory, plan, {
14350
+ await _internals17.savePlan(directory, plan, {
13196
14351
  planLockAlreadyHeld: true
13197
14352
  });
13198
- plan = await _internals16.loadPlanJsonOnly(directory) ?? plan;
14353
+ plan = await _internals17.loadPlanJsonOnly(directory) ?? plan;
13199
14354
  }
13200
- await _internals16.ensureSnapshotEvent(directory, plan, transitionId);
13201
- await _internals16.verifySnapshot(snapshotPath, wal.specContent === null ? null : { content: wal.specContent });
14355
+ await _internals17.ensureSnapshotEvent(directory, plan, transitionId);
14356
+ await _internals17.verifySnapshot(snapshotPath, wal.specContent === null ? null : { content: wal.specContent });
13202
14357
  const event = buildRecoveryEvent({
13203
14358
  mode: wal.mode,
13204
14359
  actor: wal.actor,
@@ -13209,15 +14364,15 @@ async function reconcileSpecDrift(directory, options) {
13209
14364
  previousHash: wal.previousHash,
13210
14365
  transitionId
13211
14366
  });
13212
- await _internals16.appendEvent(directory, event);
13213
- await _internals16.writeWal(walPath, { ...wal, state: "COMMITTED" });
14367
+ await _internals17.appendEvent(directory, event);
14368
+ await _internals17.writeWal(walPath, { ...wal, state: "COMMITTED" });
13214
14369
  }
13215
14370
  if (markerReplacedDuringPrepared) {
13216
14371
  const preservedMarker = {
13217
14372
  ...marker,
13218
14373
  specHash_plan: newHash,
13219
14374
  reason: `prior prepared drift recovery committed before this marker: ${marker.reason}`,
13220
- timestamp: _internals16.now()
14375
+ timestamp: _internals17.now()
13221
14376
  };
13222
14377
  await atomicWriteFile(markerPath, `${JSON.stringify(preservedMarker, null, 2)}
13223
14378
  `);
@@ -13232,7 +14387,7 @@ async function reconcileSpecDrift(directory, options) {
13232
14387
  transitionId
13233
14388
  };
13234
14389
  }
13235
- const latestSpec = _internals16.readEffectiveSpecSync(directory);
14390
+ const latestSpec = _internals17.readEffectiveSpecSync(directory);
13236
14391
  if ((latestSpec?.hash ?? null) !== newHash) {
13237
14392
  const refreshedMarker = {
13238
14393
  planTitle: wal.planTitle,
@@ -13240,7 +14395,7 @@ async function reconcileSpecDrift(directory, options) {
13240
14395
  specHash_plan: newHash,
13241
14396
  specHash_current: latestSpec?.hash ?? null,
13242
14397
  reason: "spec changed while drift recovery was committing",
13243
- timestamp: _internals16.now()
14398
+ timestamp: _internals17.now()
13244
14399
  };
13245
14400
  await atomicWriteFile(markerPath, `${JSON.stringify(refreshedMarker, null, 2)}
13246
14401
  `);
@@ -13256,8 +14411,8 @@ async function reconcileSpecDrift(directory, options) {
13256
14411
  };
13257
14412
  }
13258
14413
  try {
13259
- await _internals16.unlinkIfExists(markerPath);
13260
- _internals16.invalidateCachedArtifact(markerPath);
14414
+ await _internals17.unlinkIfExists(markerPath);
14415
+ _internals17.invalidateCachedArtifact(markerPath);
13261
14416
  } catch (error2) {
13262
14417
  return {
13263
14418
  status: "cleanup_pending",
@@ -13442,7 +14597,7 @@ ${USAGE2}`;
13442
14597
 
13443
14598
  // src/security/write-authority.ts
13444
14599
  import { AsyncLocalStorage } from "async_hooks";
13445
- import { createHash as createHash8, randomUUID as randomUUID3 } from "crypto";
14600
+ import { createHash as createHash9, randomUUID as randomUUID3 } from "crypto";
13446
14601
  import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
13447
14602
  import * as path13 from "path";
13448
14603
  var DEFAULT_TTL_MS = 30 * 60 * 1000;
@@ -13549,7 +14704,7 @@ function leastPrivilege(left, right) {
13549
14704
  return ORIGIN_RANK[left.origin] <= ORIGIN_RANK[right.origin] ? left : right;
13550
14705
  }
13551
14706
  function computeWriteApprovalHash(input) {
13552
- return createHash8("sha256").update(stableSerialize(input)).digest("hex");
14707
+ return createHash9("sha256").update(stableSerialize(input)).digest("hex");
13553
14708
  }
13554
14709
  function getCurrentWriteAuthority() {
13555
14710
  const extent = authorityStore.getStore();
@@ -13754,7 +14909,7 @@ ${USAGE3}`;
13754
14909
 
13755
14910
  // src/commands/archive.ts
13756
14911
  init_loader();
13757
- var _internals17 = {
14912
+ var _internals18 = {
13758
14913
  now: () => new Date
13759
14914
  };
13760
14915
  function artifactLabel(artifact) {
@@ -13810,7 +14965,7 @@ async function handleArchiveCommand(directory, args) {
13810
14965
  const report = await archiveEvidence(directory, maxAgeDays, maxBundles, {
13811
14966
  report: true,
13812
14967
  dryRun,
13813
- now: _internals17.now(),
14968
+ now: _internals18.now(),
13814
14969
  cacheMaxBytes,
13815
14970
  cacheMaxRecords
13816
14971
  });
@@ -15097,7 +16252,7 @@ var SHELL_METACHARACTERS = /[;|&$`(){}<>!'"]/;
15097
16252
  var SAFE_LABEL_PATTERN = /^[a-zA-Z0-9_ -]+$/;
15098
16253
  var CONTROL_CHAR_PATTERN = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/;
15099
16254
  var NON_ASCII_PATTERN = /[^\x20-\x7E]/;
15100
- var _internals18 = {
16255
+ var _internals19 = {
15101
16256
  tryAcquireLock,
15102
16257
  loadPlan,
15103
16258
  gitExec,
@@ -15240,11 +16395,11 @@ function upsertTaskCompletionCheckpointEntry(directory, log2, entry, maxCheckpoi
15240
16395
  }
15241
16396
  }
15242
16397
  function stageAllExcludingSwarm(directory) {
15243
- _internals18.gitExec(["add", "--all", "--", ...NON_SWARM_COMMIT_PATHSPEC], directory);
16398
+ _internals19.gitExec(["add", "--all", "--", ...NON_SWARM_COMMIT_PATHSPEC], directory);
15244
16399
  }
15245
16400
  function gitExec(args, cwd) {
15246
16401
  for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
15247
- const result = child_process.spawnSync(_internals18.resolveGitExecutable(), args, {
16402
+ const result = child_process.spawnSync(_internals19.resolveGitExecutable(), args, {
15248
16403
  cwd,
15249
16404
  encoding: "utf-8",
15250
16405
  timeout: GIT_TIMEOUT_MS2,
@@ -15301,7 +16456,7 @@ function isGitRepo2(directory) {
15301
16456
  }
15302
16457
  }
15303
16458
  function findCommitByExactSubject(directory, subject) {
15304
- const output = _internals18.gitExec([
16459
+ const output = _internals19.gitExec([
15305
16460
  "log",
15306
16461
  "HEAD",
15307
16462
  "--format=%H%x00%s",
@@ -15331,7 +16486,7 @@ async function withTaskCompletionLocksResult(input) {
15331
16486
  attempts++;
15332
16487
  let planLockResult;
15333
16488
  try {
15334
- planLockResult = await _internals18.tryAcquireLock(input.directory, PLAN_LOCK_PATH, CHECKPOINT_AGENT_NAME, `save-task-completion-plan-${input.taskId}`);
16489
+ planLockResult = await _internals19.tryAcquireLock(input.directory, PLAN_LOCK_PATH, CHECKPOINT_AGENT_NAME, `save-task-completion-plan-${input.taskId}`);
15335
16490
  } catch (error2) {
15336
16491
  if (input.onFailure) {
15337
16492
  return input.onFailure(error2);
@@ -15345,13 +16500,13 @@ async function withTaskCompletionLocksResult(input) {
15345
16500
  if (attempts >= CHECKPOINT_LOCK_MAX_ATTEMPTS || Date.now() + CHECKPOINT_LOCK_DELAY_MS > deadline) {
15346
16501
  break;
15347
16502
  }
15348
- await _internals18.sleep(CHECKPOINT_LOCK_DELAY_MS);
16503
+ await _internals19.sleep(CHECKPOINT_LOCK_DELAY_MS);
15349
16504
  continue;
15350
16505
  }
15351
16506
  try {
15352
16507
  let checkpointLockResult;
15353
16508
  try {
15354
- checkpointLockResult = await _internals18.tryAcquireLock(input.directory, CHECKPOINT_LOG_PATH, CHECKPOINT_AGENT_NAME, `save-task-completion-checkpoint-${input.taskId}`);
16509
+ checkpointLockResult = await _internals19.tryAcquireLock(input.directory, CHECKPOINT_LOG_PATH, CHECKPOINT_AGENT_NAME, `save-task-completion-checkpoint-${input.taskId}`);
15355
16510
  } catch (error2) {
15356
16511
  if (input.onFailure) {
15357
16512
  return input.onFailure(error2);
@@ -15365,7 +16520,7 @@ async function withTaskCompletionLocksResult(input) {
15365
16520
  if (attempts >= CHECKPOINT_LOCK_MAX_ATTEMPTS || Date.now() + CHECKPOINT_LOCK_DELAY_MS > deadline) {
15366
16521
  break;
15367
16522
  }
15368
- await _internals18.sleep(CHECKPOINT_LOCK_DELAY_MS);
16523
+ await _internals19.sleep(CHECKPOINT_LOCK_DELAY_MS);
15369
16524
  continue;
15370
16525
  }
15371
16526
  try {
@@ -15421,7 +16576,7 @@ async function withCheckpointMutationLockResult(input) {
15421
16576
  attempts++;
15422
16577
  let lockResult;
15423
16578
  try {
15424
- lockResult = await _internals18.tryAcquireLock(input.directory, CHECKPOINT_LOG_PATH, CHECKPOINT_AGENT_NAME, input.operationKey);
16579
+ lockResult = await _internals19.tryAcquireLock(input.directory, CHECKPOINT_LOG_PATH, CHECKPOINT_AGENT_NAME, input.operationKey);
15425
16580
  } catch (error2) {
15426
16581
  if (input.onFailure) {
15427
16582
  return input.onFailure(error2);
@@ -15458,7 +16613,7 @@ async function withCheckpointMutationLockResult(input) {
15458
16613
  if (attempts >= CHECKPOINT_LOCK_MAX_ATTEMPTS || Date.now() + CHECKPOINT_LOCK_DELAY_MS > deadline) {
15459
16614
  break;
15460
16615
  }
15461
- await _internals18.sleep(CHECKPOINT_LOCK_DELAY_MS);
16616
+ await _internals19.sleep(CHECKPOINT_LOCK_DELAY_MS);
15462
16617
  }
15463
16618
  if (input.onBusy) {
15464
16619
  return input.onBusy(attempts);
@@ -15483,7 +16638,7 @@ function handleSave(label, directory) {
15483
16638
  });
15484
16639
  }
15485
16640
  const timestamp = new Date().toISOString();
15486
- _internals18.stageAllExcludingSwarm(directory);
16641
+ _internals19.stageAllExcludingSwarm(directory);
15487
16642
  const hasStagedChanges = (() => {
15488
16643
  try {
15489
16644
  gitExec(["diff", "--cached", "--quiet"], directory);
@@ -15581,7 +16736,7 @@ async function handleSaveTaskCompletion(taskId, directory) {
15581
16736
  directory,
15582
16737
  taskId,
15583
16738
  run: async () => {
15584
- const plan = await _internals18.loadPlan(directory);
16739
+ const plan = await _internals19.loadPlan(directory);
15585
16740
  if (!plan) {
15586
16741
  return serializeResult("save_task_completion", {
15587
16742
  success: false,
@@ -15601,7 +16756,7 @@ async function handleSaveTaskCompletion(taskId, directory) {
15601
16756
  error: `save_task_completion failed: task "${taskId}" is ${task.status}, not completed`
15602
16757
  });
15603
16758
  }
15604
- await _internals18.afterTaskEligibilityRead?.(directory, task.id);
16759
+ await _internals19.afterTaskEligibilityRead?.(directory, task.id);
15605
16760
  const planIdentityHash = derivePlanIdentityHash(plan);
15606
16761
  const planId = derivePlanId(plan);
15607
16762
  const ledgerEvents = await readLedgerEvents(directory);
@@ -15637,12 +16792,12 @@ async function handleSaveTaskCompletion(taskId, directory) {
15637
16792
  message: `Checkpoint task completion already logged for "${descriptor.taskId}"`
15638
16793
  });
15639
16794
  }
15640
- const recoveredSha = _internals18.findCommitByExactSubject(directory, descriptor.subject);
16795
+ const recoveredSha = _internals19.findCommitByExactSubject(directory, descriptor.subject);
15641
16796
  let committedSha = null;
15642
16797
  committedSha = recoveredSha ?? receipt.sha;
15643
16798
  if (!committedSha) {
15644
- _internals18.stageAllExcludingSwarm(directory);
15645
- _internals18.gitExec([
16799
+ _internals19.stageAllExcludingSwarm(directory);
16800
+ _internals19.gitExec([
15646
16801
  "commit",
15647
16802
  "--allow-empty",
15648
16803
  "-m",
@@ -15906,7 +17061,7 @@ var IPV4_PRIVATE_192 = /^192\.168\./;
15906
17061
  var IPV4_ZERO_NETWORK = /^0\./;
15907
17062
  var IPV6_LINK_LOCAL = /^fe80:/i;
15908
17063
  var IPV6_UNIQUE_LOCAL = /^f[cd][0-9a-f]{2}:/i;
15909
- var _internals19 = {
17064
+ var _internals20 = {
15910
17065
  spawnSync: (cmd, args, options) => {
15911
17066
  const mergedEnv = mergeEnvForChild(options?.env, options?.envOverrides);
15912
17067
  return child_process2.spawnSync(cmd, args, {
@@ -16024,7 +17179,7 @@ function validateAndSanitizeGithubUrl(rawUrl, resource) {
16024
17179
  }
16025
17180
  function detectGitRemote(cwd, laneEnv) {
16026
17181
  try {
16027
- const result = _internals19.spawnSync(resolveGitExecutable(), ["remote", "get-url", "origin"], {
17182
+ const result = _internals20.spawnSync(resolveGitExecutable(), ["remote", "get-url", "origin"], {
16028
17183
  encoding: "utf-8",
16029
17184
  stdio: ["ignore", "pipe", "pipe"],
16030
17185
  timeout: 5000,
@@ -16193,7 +17348,7 @@ init_logger();
16193
17348
  var GIT_TIMEOUT_MS3 = 30000;
16194
17349
  var VALIDATION_TIMEOUT_MS = 5 * 60 * 1000;
16195
17350
  var OUTPUT_LIMIT_BYTES = 12000;
16196
- var _internals20 = {
17351
+ var _internals21 = {
16197
17352
  runExternalTool,
16198
17353
  getDefaultBaseBranch,
16199
17354
  detectDefaultRemoteBranch,
@@ -16207,8 +17362,8 @@ var _internals20 = {
16207
17362
  }
16208
17363
  };
16209
17364
  async function runGit(args, cwd, timeoutMs = GIT_TIMEOUT_MS3) {
16210
- const result = await _internals20.runExternalTool({
16211
- executable: _internals20.resolveGitExecutable(),
17365
+ const result = await _internals21.runExternalTool({
17366
+ executable: _internals21.resolveGitExecutable(),
16212
17367
  args,
16213
17368
  cwd,
16214
17369
  timeoutMs,
@@ -16225,7 +17380,7 @@ async function runGit(args, cwd, timeoutMs = GIT_TIMEOUT_MS3) {
16225
17380
  }
16226
17381
  async function runValidationCommand(cmd, cwd, timeoutMs = VALIDATION_TIMEOUT_MS) {
16227
17382
  const [executable, ...args] = cmd;
16228
- const result = await _internals20.runExternalTool({
17383
+ const result = await _internals21.runExternalTool({
16229
17384
  executable,
16230
17385
  args,
16231
17386
  cwd,
@@ -16253,9 +17408,9 @@ async function getCurrentBranchOrRef(directory) {
16253
17408
  return hashResult.stdout.trim();
16254
17409
  }
16255
17410
  async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated) {
16256
- const rawBase = path19.join(_internals20.osTmpdir(), "swarm-ci-simulate");
17411
+ const rawBase = path19.join(_internals21.osTmpdir(), "swarm-ci-simulate");
16257
17412
  await fsPromises.mkdir(rawBase, { recursive: true });
16258
- const worktreeBase = _internals20.fs.realpathSync(rawBase);
17413
+ const worktreeBase = _internals21.fs.realpathSync(rawBase);
16259
17414
  const worktreeName = `pr-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
16260
17415
  const worktreePath = path19.join(worktreeBase, worktreeName);
16261
17416
  const addResult = await runGit(["worktree", "add", "--detach", worktreePath, baseBranch], projectRoot);
@@ -16270,11 +17425,11 @@ async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated)
16270
17425
  return worktreePath;
16271
17426
  }
16272
17427
  async function cleanupWorktree(worktreePath, projectRoot) {
16273
- const rawBase = path19.resolve(_internals20.osTmpdir(), "swarm-ci-simulate");
16274
- const worktreeBase = _internals20.fs.existsSync(rawBase) ? _internals20.fs.realpathSync(rawBase) : rawBase;
16275
- const resolved = _internals20.fs.existsSync(worktreePath) ? _internals20.fs.realpathSync(worktreePath) : path19.resolve(worktreePath);
16276
- const pathEq = _internals20.platform === "win32" ? (a, b) => a.toLowerCase() === b.toLowerCase() : (a, b) => a === b;
16277
- const pathStartsWith = _internals20.platform === "win32" ? (a, b) => a.toLowerCase().startsWith(b.toLowerCase()) : (a, b) => a.startsWith(b);
17428
+ const rawBase = path19.resolve(_internals21.osTmpdir(), "swarm-ci-simulate");
17429
+ const worktreeBase = _internals21.fs.existsSync(rawBase) ? _internals21.fs.realpathSync(rawBase) : rawBase;
17430
+ const resolved = _internals21.fs.existsSync(worktreePath) ? _internals21.fs.realpathSync(worktreePath) : path19.resolve(worktreePath);
17431
+ const pathEq = _internals21.platform === "win32" ? (a, b) => a.toLowerCase() === b.toLowerCase() : (a, b) => a === b;
17432
+ const pathStartsWith = _internals21.platform === "win32" ? (a, b) => a.toLowerCase().startsWith(b.toLowerCase()) : (a, b) => a.startsWith(b);
16278
17433
  if (!pathEq(resolved, worktreeBase) && !pathStartsWith(resolved, `${worktreeBase}${path19.sep}`)) {
16279
17434
  return `[ci-simulate] refusing to clean up non-contained path ${worktreePath}`;
16280
17435
  }
@@ -16286,11 +17441,11 @@ async function cleanupWorktree(worktreePath, projectRoot) {
16286
17441
  if (!line.startsWith("worktree "))
16287
17442
  return false;
16288
17443
  const raw = line.slice("worktree ".length).trim();
16289
- const canon = _internals20.fs.existsSync(raw) ? _internals20.fs.realpathSync(raw) : path19.resolve(raw);
17444
+ const canon = _internals21.fs.existsSync(raw) ? _internals21.fs.realpathSync(raw) : path19.resolve(raw);
16290
17445
  return pathEq(canon, resolved);
16291
17446
  });
16292
17447
  if (!registered) {
16293
- if (!_internals20.fs.existsSync(resolved))
17448
+ if (!_internals21.fs.existsSync(resolved))
16294
17449
  return null;
16295
17450
  return `[ci-simulate] path ${worktreePath} exists but is not a registered git worktree; remove it manually`;
16296
17451
  }
@@ -16389,7 +17544,7 @@ async function handleCiSimulateCommand(directory, args) {
16389
17544
  steps: []
16390
17545
  };
16391
17546
  try {
16392
- const detectedBranch = _internals20.detectDefaultRemoteBranch(directory);
17547
+ const detectedBranch = _internals21.detectDefaultRemoteBranch(directory);
16393
17548
  let baseBranch = null;
16394
17549
  if (explicitBase) {
16395
17550
  const verify = await runGit(["rev-parse", "--verify", "--quiet", explicitBase], directory);
@@ -16866,7 +18021,7 @@ async function boundedSessionCall(call, timeoutMs, timeoutLabel, failureLabel, s
16866
18021
  })
16867
18022
  ]);
16868
18023
  } catch (error2) {
16869
- _internals21.log(`${failureLabel} for ephemeral session`, {
18024
+ _internals22.log(`${failureLabel} for ephemeral session`, {
16870
18025
  sessionId,
16871
18026
  error: error2 instanceof Error ? error2.message : String(error2)
16872
18027
  });
@@ -16878,21 +18033,21 @@ async function boundedSessionCall(call, timeoutMs, timeoutLabel, failureLabel, s
16878
18033
  async function boundedAbortEphemeralSession(session, sessionId, timeoutMs = DEFAULT_EPHEMERAL_ABORT_TIMEOUT_MS) {
16879
18034
  if (typeof session.abort !== "function")
16880
18035
  return;
16881
- await _internals21.boundedSessionCall(() => session.abort({ path: { id: sessionId } }), timeoutMs, "ephemeral session abort timed out", "ephemeral session abort failed", sessionId);
18036
+ await _internals22.boundedSessionCall(() => session.abort({ path: { id: sessionId } }), timeoutMs, "ephemeral session abort timed out", "ephemeral session abort failed", sessionId);
16882
18037
  }
16883
18038
  async function boundedDeleteEphemeralSession(session, sessionId, timeoutMs = DEFAULT_EPHEMERAL_TEARDOWN_DELETE_TIMEOUT_MS) {
16884
- await _internals21.boundedSessionCall(() => session.delete({ path: { id: sessionId } }), timeoutMs, "ephemeral session delete timed out", "ephemeral session delete failed", sessionId);
18039
+ await _internals22.boundedSessionCall(() => session.delete({ path: { id: sessionId } }), timeoutMs, "ephemeral session delete timed out", "ephemeral session delete failed", sessionId);
16885
18040
  }
16886
18041
  async function teardownEphemeralSession(session, sessionId, options = {}) {
16887
18042
  const abortTimeoutMs = options.abortTimeoutMs ?? DEFAULT_EPHEMERAL_ABORT_TIMEOUT_MS;
16888
18043
  const deleteTimeoutMs = options.deleteTimeoutMs ?? DEFAULT_EPHEMERAL_TEARDOWN_DELETE_TIMEOUT_MS;
16889
18044
  const skipAbort = options.skipAbort ?? false;
16890
18045
  if (!skipAbort) {
16891
- await _internals21.boundedAbort(session, sessionId, abortTimeoutMs);
18046
+ await _internals22.boundedAbort(session, sessionId, abortTimeoutMs);
16892
18047
  }
16893
- await _internals21.boundedDelete(session, sessionId, deleteTimeoutMs);
18048
+ await _internals22.boundedDelete(session, sessionId, deleteTimeoutMs);
16894
18049
  }
16895
- var _internals21 = {
18050
+ var _internals22 = {
16896
18051
  boundedSessionCall,
16897
18052
  boundedAbort: boundedAbortEphemeralSession,
16898
18053
  boundedDelete: boundedDeleteEphemeralSession,
@@ -16900,7 +18055,7 @@ var _internals21 = {
16900
18055
  };
16901
18056
 
16902
18057
  // src/failures/invocation-failure.ts
16903
- import { createHash as createHash10 } from "crypto";
18058
+ import { createHash as createHash11 } from "crypto";
16904
18059
 
16905
18060
  // src/utils/provider-error-classification.ts
16906
18061
  var TRANSIENT_STATUS_CODES = new Set([
@@ -16937,7 +18092,7 @@ function isQuotaError(signal) {
16937
18092
 
16938
18093
  // src/failures/action-identity.ts
16939
18094
  init_schema();
16940
- import { createHash as createHash9 } from "crypto";
18095
+ import { createHash as createHash10 } from "crypto";
16941
18096
  var MAX_STRING_INPUT = 512;
16942
18097
  var MAX_PUBLIC_FIELD_LENGTH = 128;
16943
18098
  var MAX_COLLECTION_ITEMS = 64;
@@ -16987,11 +18142,11 @@ var SCOPE_KEYS = [
16987
18142
  "path",
16988
18143
  "paths"
16989
18144
  ];
16990
- function normalizeToolName(tool2) {
18145
+ function normalizeToolName2(tool2) {
16991
18146
  return tool2.trim().toLowerCase() || "unknown-tool";
16992
18147
  }
16993
18148
  function hashString(value) {
16994
- return createHash9("sha256").update(value).digest("hex");
18149
+ return createHash10("sha256").update(value).digest("hex");
16995
18150
  }
16996
18151
  function readRecord(value) {
16997
18152
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
@@ -17182,7 +18337,7 @@ function createActionIdentity(input) {
17182
18337
  ]);
17183
18338
  const additionalDigest = hashString(JSON.stringify(canonicalizeAdditional(omitKnownKeys(args, knownKeys))));
17184
18339
  const normalized = {
17185
- tool: normalizeToolName(input.tool),
18340
+ tool: normalizeToolName2(input.tool),
17186
18341
  role,
17187
18342
  swarm,
17188
18343
  task,
@@ -17259,7 +18414,7 @@ function boundedUtf8(value, maxBytes = MAX_DISPLAY_BYTES) {
17259
18414
  return buffer.subarray(0, maxBytes).toString("utf8").replace(/\uFFFD+$/g, "");
17260
18415
  }
17261
18416
  function hashValue(value) {
17262
- return createHash10("sha256").update(value).digest("hex");
18417
+ return createHash11("sha256").update(value).digest("hex");
17263
18418
  }
17264
18419
  function redactUrl(match) {
17265
18420
  try {
@@ -17671,7 +18826,7 @@ class ModelDispatchTimeoutError extends Error {
17671
18826
  this.name = "TimeoutError";
17672
18827
  }
17673
18828
  }
17674
- var _internals22 = {
18829
+ var _internals23 = {
17675
18830
  setTimeout,
17676
18831
  clearTimeout
17677
18832
  };
@@ -17681,13 +18836,13 @@ function deadlineError(phase) {
17681
18836
  async function raceWithTimeout(promise, ms, timeoutError) {
17682
18837
  let timer;
17683
18838
  const timeoutPromise = new Promise((_, reject) => {
17684
- timer = _internals22.setTimeout(() => reject(timeoutError), Math.max(0, ms));
18839
+ timer = _internals23.setTimeout(() => reject(timeoutError), Math.max(0, ms));
17685
18840
  });
17686
18841
  try {
17687
18842
  return await Promise.race([promise, timeoutPromise]);
17688
18843
  } finally {
17689
18844
  if (timer !== undefined)
17690
- _internals22.clearTimeout(timer);
18845
+ _internals23.clearTimeout(timer);
17691
18846
  }
17692
18847
  }
17693
18848
  function resolveLegacyFallbackModel(resolveFallback, fallbackIndex) {
@@ -18571,7 +19726,7 @@ async function readLedgerForTransaction(filePath) {
18571
19726
  }
18572
19727
  }
18573
19728
  async function readLedgerStrict(directory) {
18574
- const filePath = _internals23.resolveRecommendationLedgerPath(directory);
19729
+ const filePath = _internals24.resolveRecommendationLedgerPath(directory);
18575
19730
  try {
18576
19731
  return parseLedgerJsonl(await readFile6(filePath, "utf-8"));
18577
19732
  } catch (err) {
@@ -18649,7 +19804,7 @@ async function checkRecommendations(directory, candidates) {
18649
19804
  let ledgerKeys = new Set;
18650
19805
  let degraded = false;
18651
19806
  try {
18652
- const entries = await _internals23.readLedgerStrict(directory);
19807
+ const entries = await _internals24.readLedgerStrict(directory);
18653
19808
  ledgerKeys = new Set(entries.map((entry) => entry.crossKey));
18654
19809
  } catch (err) {
18655
19810
  warn(`[recommendation-ledger] check failed (fail-open, emitting everything): ${err instanceof Error ? err.message : String(err)}`);
@@ -18711,13 +19866,13 @@ async function recordEmittedRecommendations(directory, candidates, options = {})
18711
19866
  if (!candidates.some(hasIdentity)) {
18712
19867
  return { recorded: 0, suppressed: 0, evicted: 0, degraded: false };
18713
19868
  }
18714
- const emittedAt = options.producedAt ?? _internals23.now().toISOString();
19869
+ const emittedAt = options.producedAt ?? _internals24.now().toISOString();
18715
19870
  let recorded = 0;
18716
19871
  let suppressed = 0;
18717
19872
  let evicted = 0;
18718
19873
  try {
18719
- const filePath = _internals23.resolveRecommendationLedgerPath(directory);
18720
- const wrote = await _internals23.transactFile(filePath, readLedgerForTransaction, async (target, data) => {
19874
+ const filePath = _internals24.resolveRecommendationLedgerPath(directory);
19875
+ const wrote = await _internals24.transactFile(filePath, readLedgerForTransaction, async (target, data) => {
18721
19876
  await atomicWriteFile(target, serializeLedger(data));
18722
19877
  }, (existing) => {
18723
19878
  const seen = new Set(existing.map((entry) => entry.crossKey));
@@ -18754,7 +19909,7 @@ async function recordEmittedRecommendations(directory, candidates, options = {})
18754
19909
  return { recorded: 0, suppressed: 0, evicted: 0, degraded: true };
18755
19910
  }
18756
19911
  }
18757
- var _internals23 = {
19912
+ var _internals24 = {
18758
19913
  now: () => new Date,
18759
19914
  transactFile,
18760
19915
  readLedgerStrict,
@@ -18985,7 +20140,7 @@ async function reviseSkill(params) {
18985
20140
  }
18986
20141
  if (!params.delegate) {
18987
20142
  try {
18988
- const revised = _internals24.buildDeterministicRevision(params.currentContent, params.currentVersion, params.violationContexts);
20143
+ const revised = _internals25.buildDeterministicRevision(params.currentContent, params.currentVersion, params.violationContexts);
18989
20144
  const validation = await validateRevisionCandidate(params, revised, "skill_reviser:deterministic");
18990
20145
  if (!validation.passed) {
18991
20146
  return {
@@ -19112,7 +20267,7 @@ async function reviseSkill(params) {
19112
20267
  };
19113
20268
  }
19114
20269
  }
19115
- var _internals24 = {
20270
+ var _internals25 = {
19116
20271
  reviseSkill,
19117
20272
  getSkillVersion,
19118
20273
  buildDeterministicRevision,
@@ -19491,7 +20646,7 @@ function planMerges(active, threshold, maxComparisons, maxMerges) {
19491
20646
  };
19492
20647
  }
19493
20648
  async function sweepActiveNearDuplicates(directory, options = {}) {
19494
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-00hyhg47.js");
20649
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-8n602qc2.js");
19495
20650
  const { config } = loadPluginConfigWithMeta2(directory);
19496
20651
  const sweepConfig = config.learning?.dedup_sweep;
19497
20652
  if (sweepConfig?.enabled === false)
@@ -19607,7 +20762,7 @@ var MAX_CURATOR_PHASE_DIGESTS = 50;
19607
20762
  var MAX_CURATOR_COMPLIANCE_OBSERVATIONS = 200;
19608
20763
  var MAX_CURATOR_RECOMMENDATIONS = 200;
19609
20764
  var MAX_LESSON_CHARS = 280;
19610
- var _internals25 = {
20765
+ var _internals26 = {
19611
20766
  parseKnowledgeRecommendations,
19612
20767
  parseKnowledgeRecommendationsWithDiagnostics,
19613
20768
  readCuratorSummary,
@@ -19742,9 +20897,9 @@ function recordCuratorSkips(directory, skipped) {
19742
20897
  async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs) {
19743
20898
  const observations = [];
19744
20899
  try {
19745
- const skillListResult = await _internals25.listSkills(directory);
19746
- const { entries: usageEntries, coverage } = _internals25.readSkillUsageEntriesWithCoverage(directory);
19747
- const allArchivedIds = await _internals25.getArchivedKnowledgeIds(directory);
20900
+ const skillListResult = await _internals26.listSkills(directory);
20901
+ const { entries: usageEntries, coverage } = _internals26.readSkillUsageEntriesWithCoverage(directory);
20902
+ const allArchivedIds = await _internals26.getArchivedKnowledgeIds(directory);
19748
20903
  let skippedForCoverage = 0;
19749
20904
  for (const active of skillListResult.active) {
19750
20905
  if (excludeSlugs?.has(active.slug))
@@ -19771,7 +20926,7 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
19771
20926
  warn(`[curator] skill '${active.slug}' auto-retire skipped: retained usage window (${skillUsage.length} entries) cannot support the decision`);
19772
20927
  } else {
19773
20928
  const reason = `auto-retire: violation rate ${(violationRate * 100).toFixed(0)}% exceeds 30% threshold`;
19774
- await _internals25.retireSkill(directory, active.slug, reason);
20929
+ await _internals26.retireSkill(directory, active.slug, reason);
19775
20930
  observations.push(`Skill '${active.slug}' auto-retired: ${reason}`);
19776
20931
  warn(`[curator] ${observations[observations.length - 1]}`);
19777
20932
  continue;
@@ -19780,15 +20935,15 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
19780
20935
  let archivedSourceMatched = false;
19781
20936
  if (allArchivedIds.size > 0) {
19782
20937
  try {
19783
- const content = await _internals25.readFileAsync(active.path, "utf-8");
19784
- const sourceIds = _internals25.parseDraftFrontmatter(content)?.sourceKnowledgeIds ?? [];
20938
+ const content = await _internals26.readFileAsync(active.path, "utf-8");
20939
+ const sourceIds = _internals26.parseDraftFrontmatter(content)?.sourceKnowledgeIds ?? [];
19785
20940
  archivedSourceMatched = sourceIds.some((id) => allArchivedIds.has(id));
19786
20941
  } catch {
19787
20942
  archivedSourceMatched = false;
19788
20943
  }
19789
20944
  }
19790
20945
  if (archivedSourceMatched) {
19791
- const result = await _internals25.retireOrMarkStale(directory, path24.dirname(active.path), allArchivedIds);
20946
+ const result = await _internals26.retireOrMarkStale(directory, path24.dirname(active.path), allArchivedIds);
19792
20947
  if (result.action === "retire") {
19793
20948
  observations.push(`Skill '${active.slug}' auto-retired: all source knowledge entries archived`);
19794
20949
  warn(`[curator] ${observations[observations.length - 1]}`);
@@ -19798,7 +20953,7 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
19798
20953
  }
19799
20954
  }
19800
20955
  }
19801
- _internals25.recordCuratorSkips(directory, skippedForCoverage);
20956
+ _internals26.recordCuratorSkips(directory, skippedForCoverage);
19802
20957
  } catch (autoRetireErr) {
19803
20958
  warn(`[curator] auto-retire health check failed: ${autoRetireErr instanceof Error ? autoRetireErr.message : String(autoRetireErr)}`);
19804
20959
  }
@@ -20062,7 +21217,7 @@ async function transactCuratorSummary(directory, mutate) {
20062
21217
  const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
20063
21218
  let invoked = false;
20064
21219
  let mutationResult;
20065
- await _internals25.transactFile(resolvedPath, _internals25.readCuratorSummaryState, _internals25.writeCuratorSummaryState, (state) => {
21220
+ await _internals26.transactFile(resolvedPath, _internals26.readCuratorSummaryState, _internals26.writeCuratorSummaryState, (state) => {
20066
21221
  invoked = true;
20067
21222
  const mutation = mutate(state.summary);
20068
21223
  mutationResult = mutation.result;
@@ -20211,8 +21366,8 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
20211
21366
  const observations = [];
20212
21367
  const timestamp = new Date().toISOString();
20213
21368
  for (const agent of requiredAgents) {
20214
- const normalizedAgent = _internals25.normalizeAgentName(agent);
20215
- const isDispatched = agentsDispatched.some((a) => _internals25.normalizeAgentName(a) === normalizedAgent);
21369
+ const normalizedAgent = _internals26.normalizeAgentName(agent);
21370
+ const isDispatched = agentsDispatched.some((a) => _internals26.normalizeAgentName(a) === normalizedAgent);
20216
21371
  if (!isDispatched) {
20217
21372
  observations.push({
20218
21373
  phase,
@@ -20231,7 +21386,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
20231
21386
  if (e.type === "agent.delegation") {
20232
21387
  const agent = e.agent;
20233
21388
  if (agent && typeof agent === "string") {
20234
- const normalized = _internals25.normalizeAgentName(agent);
21389
+ const normalized = _internals26.normalizeAgentName(agent);
20235
21390
  if (normalized === "coder") {
20236
21391
  coderDelegations.push({ event: e, index: i });
20237
21392
  } else if (normalized === "reviewer") {
@@ -20288,7 +21443,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
20288
21443
  if (e.type === "agent.delegation" && e.agent) {
20289
21444
  const agent = e.agent;
20290
21445
  if (agent && typeof agent === "string") {
20291
- const normalized = _internals25.normalizeAgentName(agent);
21446
+ const normalized = _internals26.normalizeAgentName(agent);
20292
21447
  if (normalized === "sme") {
20293
21448
  smeDelegations.push({ event: e, index: i });
20294
21449
  }
@@ -20312,7 +21467,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
20312
21467
  }
20313
21468
  async function runCuratorInit(directory, config, llmDelegate) {
20314
21469
  try {
20315
- const priorSummary = await _internals25.readCuratorSummary(directory);
21470
+ const priorSummary = await _internals26.readCuratorSummary(directory);
20316
21471
  const knowledgePath = resolveSwarmKnowledgePath(directory);
20317
21472
  const allEntries = await readKnowledge(knowledgePath);
20318
21473
  const highConfidenceEntries = allEntries.filter((e) => typeof e.confidence === "number" && e.confidence >= config.min_knowledge_confidence);
@@ -20353,7 +21508,7 @@ async function runCuratorInit(directory, config, llmDelegate) {
20353
21508
  const maxContextChars = config.max_summary_tokens * 2;
20354
21509
  briefingParts.push(contextMd.slice(0, maxContextChars));
20355
21510
  }
20356
- const latestPostMortemDigest = _internals25.readLatestPostMortemDigest(directory);
21511
+ const latestPostMortemDigest = _internals26.readLatestPostMortemDigest(directory);
20357
21512
  if (latestPostMortemDigest) {
20358
21513
  briefingParts.push(`
20359
21514
  ## Latest Post-Mortem`);
@@ -20440,7 +21595,7 @@ Could not load prior session context.`,
20440
21595
  }
20441
21596
  async function runCuratorPhase(directory, phase, agentsDispatched, config, knowledgeConfig, llmDelegate) {
20442
21597
  try {
20443
- const priorSummary = await _internals25.readCuratorSummary(directory);
21598
+ const priorSummary = await _internals26.readCuratorSummary(directory);
20444
21599
  if (priorSummary?.phase_digests.some((d) => d.phase === phase)) {
20445
21600
  const existingDigest = priorSummary.phase_digests.find((d) => d.phase === phase);
20446
21601
  return {
@@ -20453,7 +21608,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20453
21608
  };
20454
21609
  }
20455
21610
  const eventsWindow = readCoreEvents(directory);
20456
- const phaseEvents = eventsWindow.text.length > 0 ? _internals25.filterPhaseEvents(eventsWindow.text, phase) : [];
21611
+ const phaseEvents = eventsWindow.text.length > 0 ? _internals26.filterPhaseEvents(eventsWindow.text, phase) : [];
20457
21612
  if (eventsWindow.coverage === "truncated") {
20458
21613
  try {
20459
21614
  appendCoreEventSync(directory, {
@@ -20467,7 +21622,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20467
21622
  }
20468
21623
  const contextMd = await readSwarmFileAsync(directory, "context.md");
20469
21624
  const requiredAgents = ["reviewer", "test_engineer"];
20470
- const complianceObservations = _internals25.checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, phase);
21625
+ const complianceObservations = _internals26.checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, phase);
20471
21626
  const plan = await loadPlanJsonOnly(directory);
20472
21627
  const phaseData = plan?.phases.find((p) => p.id === phase);
20473
21628
  const tasksCompleted = phaseData ? phaseData.tasks.filter((t) => t.status === "completed").length : 0;
@@ -20491,7 +21646,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20491
21646
  timestamp: new Date().toISOString(),
20492
21647
  summary: `Phase ${phase} completed. ${tasksCompleted}/${tasksTotal} tasks completed. ${complianceObservations.length} compliance observations.`,
20493
21648
  agents_used: [
20494
- ...new Set(agentsDispatched.map((a) => _internals25.normalizeAgentName(a)))
21649
+ ...new Set(agentsDispatched.map((a) => _internals26.normalizeAgentName(a)))
20495
21650
  ],
20496
21651
  tasks_completed: tasksCompleted,
20497
21652
  tasks_total: tasksTotal,
@@ -20543,7 +21698,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20543
21698
  clearTimeout(timer);
20544
21699
  }
20545
21700
  if (llmOutput?.trim()) {
20546
- const parsed = _internals25.parseKnowledgeRecommendationsWithDiagnostics(llmOutput);
21701
+ const parsed = _internals26.parseKnowledgeRecommendationsWithDiagnostics(llmOutput);
20547
21702
  for (const diagnostic of parsed.diagnostics) {
20548
21703
  warn("[curator] skipped malformed recommendation line", {
20549
21704
  phase,
@@ -20588,7 +21743,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20588
21743
  }
20589
21744
  const sessionId = `session-${Date.now()}`;
20590
21745
  const now2 = new Date().toISOString();
20591
- const summaryUpdated = await _internals25.mergeCuratorPhaseSummary(directory, {
21746
+ const summaryUpdated = await _internals26.mergeCuratorPhaseSummary(directory, {
20592
21747
  phase,
20593
21748
  phaseDigest,
20594
21749
  complianceObservations,
@@ -20621,7 +21776,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20621
21776
  }
20622
21777
  if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
20623
21778
  try {
20624
- const skillModule = await import("./skill-generator-9k1ztt7c.js");
21779
+ const skillModule = await import("./skill-generator-kh1z90tm.js");
20625
21780
  for (const cand of skillCandidates) {
20626
21781
  if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
20627
21782
  continue;
@@ -20639,8 +21794,8 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20639
21794
  }
20640
21795
  const revisedSlugs = new Set;
20641
21796
  try {
20642
- const skillListResult = await _internals25.listSkills(directory);
20643
- const { entries: usageEntries, coverage } = _internals25.readSkillUsageEntriesWithCoverage(directory);
21797
+ const skillListResult = await _internals26.listSkills(directory);
21798
+ const { entries: usageEntries, coverage } = _internals26.readSkillUsageEntriesWithCoverage(directory);
20644
21799
  let revisionCallsThisPhase = 0;
20645
21800
  let skippedForCoverage = 0;
20646
21801
  for (const active of skillListResult.active) {
@@ -20665,8 +21820,8 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20665
21820
  const violations = skillUsage.filter((e) => e.complianceVerdict === "violated").length;
20666
21821
  const violationRate = violations / skillUsage.length;
20667
21822
  if (violationRate > REVISION_VIOLATION_THRESHOLD && violationRate <= 0.3) {
20668
- const content = await _internals25.readFileAsync(active.path, "utf-8");
20669
- const fm = _internals25.parseDraftFrontmatter(content);
21823
+ const content = await _internals26.readFileAsync(active.path, "utf-8");
21824
+ const fm = _internals26.parseDraftFrontmatter(content);
20670
21825
  if (fm && fm.skillOrigin === "promoted_external")
20671
21826
  continue;
20672
21827
  if (!isUsageWindowUsable(coverage, skillUsage.length)) {
@@ -20682,7 +21837,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20682
21837
  reviewerNotes: e.reviewerNotes,
20683
21838
  timestamp: e.timestamp
20684
21839
  }));
20685
- const result2 = await _internals25.reviseSkill({
21840
+ const result2 = await _internals26.reviseSkill({
20686
21841
  directory,
20687
21842
  slug: active.slug,
20688
21843
  skillPath: active.path,
@@ -20698,18 +21853,18 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20698
21853
  revisionCallsThisPhase++;
20699
21854
  }
20700
21855
  }
20701
- _internals25.recordCuratorSkips(directory, skippedForCoverage);
21856
+ _internals26.recordCuratorSkips(directory, skippedForCoverage);
20702
21857
  } catch (revisionErr) {
20703
21858
  warn(`[curator] skill revision check failed: ${revisionErr instanceof Error ? revisionErr.message : String(revisionErr)}`);
20704
21859
  }
20705
21860
  try {
20706
- const peSkillList = await _internals25.listSkills(directory);
20707
- const { entries: peUsageEntries, coverage: peCoverage } = _internals25.readSkillUsageEntriesWithCoverage(directory);
21861
+ const peSkillList = await _internals26.listSkills(directory);
21862
+ const { entries: peUsageEntries, coverage: peCoverage } = _internals26.readSkillUsageEntriesWithCoverage(directory);
20708
21863
  const peRetirementMinAgeDays = 60;
20709
21864
  let skippedForCoverage = 0;
20710
21865
  for (const active of peSkillList.active) {
20711
- const content = await _internals25.readFileAsync(active.path, "utf-8");
20712
- const fm = _internals25.parseDraftFrontmatter(content);
21866
+ const content = await _internals26.readFileAsync(active.path, "utf-8");
21867
+ const fm = _internals26.parseDraftFrontmatter(content);
20713
21868
  if (!fm || fm.skillOrigin !== "promoted_external")
20714
21869
  continue;
20715
21870
  const skillUsage = peUsageEntries.filter((e) => {
@@ -20762,11 +21917,11 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
20762
21917
  phaseDigest.summary += ` [promoted-external skill '${active.slug}' source drift detected]`;
20763
21918
  }
20764
21919
  }
20765
- _internals25.recordCuratorSkips(directory, skippedForCoverage);
21920
+ _internals26.recordCuratorSkips(directory, skippedForCoverage);
20766
21921
  } catch (peErr) {
20767
21922
  warn(`[curator] promoted-external staleness check failed: ${peErr instanceof Error ? peErr.message : String(peErr)}`);
20768
21923
  }
20769
- const autoRetireObservations = await _internals25.autoRetireSkills(directory, curatorKnowledgePath, revisedSlugs);
21924
+ const autoRetireObservations = await _internals26.autoRetireSkills(directory, curatorKnowledgePath, revisedSlugs);
20770
21925
  if (autoRetireObservations.length > 0) {
20771
21926
  const retireNote = ` [${autoRetireObservations.length} skill(s) auto-retired]`;
20772
21927
  phaseDigest.summary += retireNote;
@@ -20903,7 +22058,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
20903
22058
  const authorizedRevisions = new Map;
20904
22059
  let preSnapshot = [];
20905
22060
  if (validRecommendations.length > 0) {
20906
- preSnapshot = await _internals25.readKnowledge(knowledgePath);
22061
+ preSnapshot = await _internals26.readKnowledge(knowledgePath);
20907
22062
  const authorizedRecs = [];
20908
22063
  for (const rec of validRecommendations) {
20909
22064
  if (rec.action !== "archive" && rec.action !== "rewrite") {
@@ -20932,7 +22087,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
20932
22087
  }
20933
22088
  validRecommendations = authorizedRecs;
20934
22089
  }
20935
- const dedupCheck = await _internals25.checkRecommendations(directory, validRecommendations.map((rec) => buildCuratorRecommendationCandidate(canonicalizeRecommendationEntryId(rec, preSnapshot))));
22090
+ const dedupCheck = await _internals26.checkRecommendations(directory, validRecommendations.map((rec) => buildCuratorRecommendationCandidate(canonicalizeRecommendationEntryId(rec, preSnapshot))));
20936
22091
  if (!dedupCheck.degraded) {
20937
22092
  const keptRecommendations = [];
20938
22093
  for (const decision of dedupCheck.decisions) {
@@ -21093,7 +22248,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
21093
22248
  } catch {}
21094
22249
  }
21095
22250
  if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
21096
- const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-cq4e6v2j.js");
22251
+ const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-d65mctqy.js");
21097
22252
  for (const { id } of contradictedEntries) {
21098
22253
  try {
21099
22254
  await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
@@ -21206,7 +22361,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
21206
22361
  currentLessons.push(lesson);
21207
22362
  emittedCandidates.push(buildCuratorRecommendationCandidate(rec));
21208
22363
  }
21209
- await _internals25.recordEmittedRecommendations(directory, emittedCandidates);
22364
+ await _internals26.recordEmittedRecommendations(directory, emittedCandidates);
21210
22365
  return { applied, skipped };
21211
22366
  }
21212
22367
 
@@ -21477,18 +22632,18 @@ async function executePostMortemActions(directory, parsed, options, generation)
21477
22632
  proposals_rejected: 0,
21478
22633
  proposals_skipped: 0
21479
22634
  };
21480
- const knowledgeConfig = options.knowledgeConfig ?? await _internals26.loadDefaultKnowledgeConfig(directory);
22635
+ const knowledgeConfig = options.knowledgeConfig ?? await _internals27.loadDefaultKnowledgeConfig(directory);
21481
22636
  if (parsed.recommendations.length > 0) {
21482
22637
  try {
21483
- const knowledgeResult = await _internals26.applyCuratorKnowledgeUpdates(directory, parsed.recommendations, knowledgeConfig, generation);
22638
+ const knowledgeResult = await _internals27.applyCuratorKnowledgeUpdates(directory, parsed.recommendations, knowledgeConfig, generation);
21484
22639
  result.knowledge_applied = knowledgeResult.applied;
21485
22640
  result.knowledge_skipped = knowledgeResult.skipped;
21486
22641
  } catch (err) {
21487
22642
  warnings.push(`Post-mortem knowledge actions failed: ${err instanceof Error ? err.message : String(err)}`);
21488
22643
  }
21489
22644
  try {
21490
- const entries = await _internals26.readSwarmKnowledge(directory);
21491
- const hiveResult = await _internals26.checkHivePromotions(entries, knowledgeConfig, directory);
22645
+ const entries = await _internals27.readSwarmKnowledge(directory);
22646
+ const hiveResult = await _internals27.checkHivePromotions(entries, knowledgeConfig, directory);
21492
22647
  result.hive_promotions = hiveResult.new_promotions;
21493
22648
  result.hive_encounters_incremented = hiveResult.encounters_incremented;
21494
22649
  result.hive_advancements = hiveResult.advancements;
@@ -21498,7 +22653,7 @@ async function executePostMortemActions(directory, parsed, options, generation)
21498
22653
  }
21499
22654
  if (parsed.queueTriage.length > 0) {
21500
22655
  try {
21501
- const proposalResult = await _internals26.applyProposalTriage(directory, parsed.queueTriage);
22656
+ const proposalResult = await _internals27.applyProposalTriage(directory, parsed.queueTriage);
21502
22657
  result.proposals_approved = proposalResult.approved.length;
21503
22658
  result.proposals_rejected = proposalResult.rejected.length;
21504
22659
  result.proposals_skipped = proposalResult.skipped.length;
@@ -21511,7 +22666,7 @@ async function executePostMortemActions(directory, parsed, options, generation)
21511
22666
  async function verifyPostMortemKnowledgeActions(directory, recommendations) {
21512
22667
  if (recommendations.length === 0)
21513
22668
  return [];
21514
- const entries = await _internals26.readSwarmKnowledge(directory);
22669
+ const entries = await _internals27.readSwarmKnowledge(directory);
21515
22670
  const activeEntries = entries.filter((entry) => isActiveStatus(entry.status));
21516
22671
  const exactIds = new Set(activeEntries.map((entry) => entry.id));
21517
22672
  const prefixMatches = new Map;
@@ -21612,7 +22767,7 @@ async function repairPostMortemActions(llmOutput, diagnostics, options) {
21612
22767
  ].join(`
21613
22768
  `);
21614
22769
  const repaired = await options.llmDelegate("", repairPrompt, ac.signal);
21615
- const parsed = _internals26.parsePostMortemActions(repaired);
22770
+ const parsed = _internals27.parsePostMortemActions(repaired);
21616
22771
  if (parsed.diagnostics.length === 0) {
21617
22772
  return parsed;
21618
22773
  }
@@ -21665,7 +22820,7 @@ function collectRetrospectives(directory) {
21665
22820
  }
21666
22821
  async function collectDriftReports(directory) {
21667
22822
  try {
21668
- const reports = await _internals26.readPriorDriftReports(directory);
22823
+ const reports = await _internals27.readPriorDriftReports(directory);
21669
22824
  return reports.slice(-MAX_DRIFT_REPORTS).map((report) => JSON.stringify(report, null, 2));
21670
22825
  } catch {
21671
22826
  return [];
@@ -21890,7 +23045,7 @@ async function runCuratorPostMortem(directory, options = {}) {
21890
23045
  warnings
21891
23046
  };
21892
23047
  }
21893
- const lock = await _internals26.acquirePostMortemLock(directory, effectivePlanId);
23048
+ const lock = await _internals27.acquirePostMortemLock(directory, effectivePlanId);
21894
23049
  if (!lock.acquired) {
21895
23050
  return {
21896
23051
  success: false,
@@ -21912,7 +23067,7 @@ async function runCuratorPostMortem(directory, options = {}) {
21912
23067
  warnings.push("Failed to collect knowledge summary.");
21913
23068
  }
21914
23069
  try {
21915
- const { getScanStatus } = await import("./scan-cursor-6awybk8b.js");
23070
+ const { getScanStatus } = await import("./scan-cursor-q3530gc8.js");
21916
23071
  const scanStatus = await getScanStatus(directory);
21917
23072
  if (scanStatus.remaining_estimate > 0) {
21918
23073
  warnings.push(`Fair scan: reviewed ${knowledgeSummary.length} entries this sweep (generation ${scanStatus.generation}); ${scanStatus.remaining_estimate} more eligible entries will be visited in future curation sweeps.`);
@@ -21971,20 +23126,20 @@ async function runCuratorPostMortem(directory, options = {}) {
21971
23126
  } finally {
21972
23127
  clearTimeout(timer);
21973
23128
  }
21974
- let parsedActions = _internals26.parsePostMortemActions(llmOutput);
23129
+ let parsedActions = _internals27.parsePostMortemActions(llmOutput);
21975
23130
  if (parsedActions.diagnostics.length > 0) {
21976
23131
  warnings.push(`Post-mortem structured action parse diagnostics: ${parsedActions.diagnostics.join("; ")}`);
21977
- const repaired = await _internals26.repairPostMortemActions(llmOutput, parsedActions.diagnostics, options);
23132
+ const repaired = await _internals27.repairPostMortemActions(llmOutput, parsedActions.diagnostics, options);
21978
23133
  if (repaired) {
21979
23134
  parsedActions = repaired;
21980
23135
  warnings.push("Post-mortem structured actions repaired by LLM.");
21981
23136
  }
21982
23137
  }
21983
23138
  llmSummary = parsedActions.summary;
21984
- const executed = await _internals26.executePostMortemActions(directory, parsedActions, options, scanCursor.generation);
23139
+ const executed = await _internals27.executePostMortemActions(directory, parsedActions, options, scanCursor.generation);
21985
23140
  actionResult = executed.result;
21986
23141
  warnings.push(...executed.warnings);
21987
- const knowledgeVerification = await _internals26.verifyPostMortemKnowledgeActions(directory, parsedActions.recommendations);
23142
+ const knowledgeVerification = await _internals27.verifyPostMortemKnowledgeActions(directory, parsedActions.recommendations);
21988
23143
  for (const item of knowledgeVerification) {
21989
23144
  if (item.status === "not_found" || item.status === "ambiguous_prefix" || item.status === "missing_entry_id") {
21990
23145
  warnings.push(`Post-mortem knowledge action ${item.action} for '${item.input_entry_id ?? "new"}' ${item.status}: ${item.reason}`);
@@ -22023,10 +23178,10 @@ ${actionSummary}`;
22023
23178
  } catch (err) {
22024
23179
  const msg = err instanceof Error ? err.message : String(err);
22025
23180
  warnings.push(`LLM delegate failed, falling back to data-only report: ${msg}`);
22026
- reportContent = _internals26.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
23181
+ reportContent = _internals27.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
22027
23182
  }
22028
23183
  } else {
22029
- reportContent = _internals26.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
23184
+ reportContent = _internals27.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
22030
23185
  }
22031
23186
  try {
22032
23187
  const { mkdirSync: mkdirSync8 } = await import("fs");
@@ -22067,7 +23222,7 @@ ${actionSummary}`;
22067
23222
  }
22068
23223
  }
22069
23224
  }
22070
- var _internals26 = {
23225
+ var _internals27 = {
22071
23226
  acquirePostMortemLock,
22072
23227
  collectKnowledgeSummary,
22073
23228
  collectRetrospectives,
@@ -22084,9 +23239,9 @@ var _internals26 = {
22084
23239
  verifyPostMortemKnowledgeActions,
22085
23240
  repairPostMortemActions,
22086
23241
  loadDefaultKnowledgeConfig: async (directory) => {
22087
- const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-bf3smw7k.js");
23242
+ const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-5zc62306.js");
22088
23243
  try {
22089
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-00hyhg47.js");
23244
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-8n602qc2.js");
22090
23245
  const loaded = loadPluginConfigWithMeta2(directory);
22091
23246
  return KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
22092
23247
  } catch {
@@ -22094,11 +23249,11 @@ var _internals26 = {
22094
23249
  }
22095
23250
  },
22096
23251
  applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig, generation) => {
22097
- const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-dnjf9ser.js");
23252
+ const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-pjjw3ja4.js");
22098
23253
  return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig, generation);
22099
23254
  },
22100
23255
  checkHivePromotions: async (entries, knowledgeConfig, directory) => {
22101
- const { checkHivePromotions } = await import("./hive-promoter-mpez5tqh.js");
23256
+ const { checkHivePromotions } = await import("./hive-promoter-7vxm11sm.js");
22102
23257
  return checkHivePromotions(entries, knowledgeConfig, directory);
22103
23258
  },
22104
23259
  applyProposalTriage: async (directory, triage) => {
@@ -22107,7 +23262,7 @@ var _internals26 = {
22107
23262
  activateProposal,
22108
23263
  listSkills: listSkills2,
22109
23264
  sanitizeSlug
22110
- } = await import("./skill-generator-9k1ztt7c.js");
23265
+ } = await import("./skill-generator-kh1z90tm.js");
22111
23266
  const result = {
22112
23267
  approved: [],
22113
23268
  rejected: [],
@@ -22197,7 +23352,7 @@ function extractCurrentPhaseFromPlan(plan) {
22197
23352
 
22198
23353
  // src/hooks/hive-promoter.ts
22199
23354
  init_schema();
22200
- import { createHash as createHash11 } from "crypto";
23355
+ import { createHash as createHash12 } from "crypto";
22201
23356
  import path27 from "path";
22202
23357
 
22203
23358
  // src/hooks/hive-policy.ts
@@ -22308,10 +23463,10 @@ class HiveStagedAppendError extends Error {
22308
23463
  }
22309
23464
  }
22310
23465
  async function transactHiveStore(mutate) {
22311
- const dataDir = _internals27.resolveHiveDataDir();
22312
- const hivePath = _internals27.resolveHiveKnowledgePath();
22313
- const rejectedPath = _internals27.resolveHiveRejectedPath();
22314
- const eventsPath = _internals27.resolveHiveEventsPath();
23466
+ const dataDir = _internals28.resolveHiveDataDir();
23467
+ const hivePath = _internals28.resolveHiveKnowledgePath();
23468
+ const rejectedPath = _internals28.resolveHiveRejectedPath();
23469
+ const eventsPath = _internals28.resolveHiveEventsPath();
22315
23470
  const diagnostics = [];
22316
23471
  try {
22317
23472
  await mkdir7(dataDir, { recursive: true });
@@ -22322,7 +23477,7 @@ async function transactHiveStore(mutate) {
22322
23477
  let release = null;
22323
23478
  try {
22324
23479
  try {
22325
- release = await _internals27.lockfile.lock(dataDir, {
23480
+ release = await _internals28.lockfile.lock(dataDir, {
22326
23481
  ...HIVE_LOCK_RETRIES,
22327
23482
  stale: HIVE_LOCK_STALE_MS
22328
23483
  });
@@ -22330,7 +23485,7 @@ async function transactHiveStore(mutate) {
22330
23485
  diagnostics.push(`hive lock acquire failed: ${err instanceof Error ? err.message : String(err)}`);
22331
23486
  return { committed: false, return: undefined, diagnostics };
22332
23487
  }
22333
- const entries = await _internals27.readKnowledge(hivePath);
23488
+ const entries = await _internals28.readKnowledge(hivePath);
22334
23489
  const outcome = await mutate({ entries });
22335
23490
  if (outcome.kind === "noop") {
22336
23491
  return { committed: false, return: outcome.return, diagnostics };
@@ -22351,7 +23506,7 @@ async function transactHiveStore(mutate) {
22351
23506
  return { committed: false, return: undefined, diagnostics };
22352
23507
  }
22353
23508
  if (typeof outcome.maxEntries === "number" && committedEntries.length > outcome.maxEntries) {
22354
- committedEntries = _internals27.selectKnowledgeCapSurvivors(committedEntries, outcome.maxEntries);
23509
+ committedEntries = _internals28.selectKnowledgeCapSurvivors(committedEntries, outcome.maxEntries);
22355
23510
  }
22356
23511
  if (outcome.extraStagedAppends && outcome.extraStagedAppends.length > 0) {
22357
23512
  for (const staged of outcome.extraStagedAppends) {
@@ -22362,7 +23517,7 @@ async function transactHiveStore(mutate) {
22362
23517
  const content = committedEntries.map((e) => overrides?.get(e.id) ?? JSON.stringify(e)).join(`
22363
23518
  `) + (committedEntries.length > 0 ? `
22364
23519
  ` : "");
22365
- await _internals27.atomicWriteFile(hivePath, content);
23520
+ await _internals28.atomicWriteFile(hivePath, content);
22366
23521
  if (outcome.rejects && outcome.rejects.length > 0) {
22367
23522
  const rejectBlock = `${outcome.rejects.map((r) => JSON.stringify(r)).join(`
22368
23523
  `)}
@@ -22383,7 +23538,7 @@ async function transactHiveStore(mutate) {
22383
23538
  if (outcome.extraStagedAppends && outcome.extraStagedAppends.length > 0) {
22384
23539
  for (const staged of outcome.extraStagedAppends) {
22385
23540
  try {
22386
- await _internals27.appendFile(staged.path, staged.block, "utf-8");
23541
+ await _internals28.appendFile(staged.path, staged.block, "utf-8");
22387
23542
  } catch (err) {
22388
23543
  throw new HiveStagedAppendError(staged.path, err);
22389
23544
  }
@@ -22447,7 +23602,7 @@ async function trimHiveEventsUnderLock(eventsPath) {
22447
23602
  `)}
22448
23603
  `);
22449
23604
  }
22450
- var _internals27 = {
23605
+ var _internals28 = {
22451
23606
  lockfile: import_proper_lockfile4.default,
22452
23607
  readKnowledge,
22453
23608
  atomicWriteFile,
@@ -22482,7 +23637,7 @@ function terminalHistory(membership) {
22482
23637
  }
22483
23638
  async function loadPromotionEvidenceByEntry(directory, canonicalCohortId) {
22484
23639
  try {
22485
- const history = await _internals28.queryHistoricalOutcomes(directory);
23640
+ const history = await _internals29.queryHistoricalOutcomes(directory);
22486
23641
  if (!history.ok)
22487
23642
  return {};
22488
23643
  const out = {};
@@ -22517,7 +23672,7 @@ async function loadPromotionEvidenceByEntry(directory, canonicalCohortId) {
22517
23672
  return {};
22518
23673
  }
22519
23674
  }
22520
- var _internals28 = { queryHistoricalOutcomes };
23675
+ var _internals29 = { queryHistoricalOutcomes };
22521
23676
 
22522
23677
  // src/hooks/hive-promoter.ts
22523
23678
  function carryActionableFields(source) {
@@ -22613,7 +23768,7 @@ function buildLineage(args) {
22613
23768
  return lineage;
22614
23769
  }
22615
23770
  function lessonRevision(lesson) {
22616
- return createHash11("sha256").update(lesson).digest("hex").slice(0, 12);
23771
+ return createHash12("sha256").update(lesson).digest("hex").slice(0, 12);
22617
23772
  }
22618
23773
  async function checkHivePromotions(swarmEntries, config, directory) {
22619
23774
  const empty = {
@@ -22626,8 +23781,8 @@ async function checkHivePromotions(swarmEntries, config, directory) {
22626
23781
  if (config.hive_enabled === false) {
22627
23782
  return empty;
22628
23783
  }
22629
- const sourceCohort = await _internals29.resolveCohortId(directory);
22630
- const evidence2 = await _internals29.loadPromotionEvidence(directory, sourceCohort.cohortId);
23784
+ const sourceCohort = await _internals30.resolveCohortId(directory);
23785
+ const evidence2 = await _internals30.loadPromotionEvidence(directory, sourceCohort.cohortId);
22631
23786
  const diagnostics = [];
22632
23787
  const activeSwarm = swarmEntries.filter((e) => isActiveStatus(e.status));
22633
23788
  const activeSwarmBigrams = activeSwarm.map((e) => typeof e.lesson === "string" ? wordBigrams(e.lesson) : new Set);
@@ -22647,7 +23802,7 @@ async function checkHivePromotions(swarmEntries, config, directory) {
22647
23802
  diagnostics.push(`skip promote '${swarmEntry.lesson.slice(0, 40)}\u2026': ${decision.reason}`);
22648
23803
  continue;
22649
23804
  }
22650
- const validationResult = _internals29.validateLesson(swarmEntry.lesson, [], {
23805
+ const validationResult = _internals30.validateLesson(swarmEntry.lesson, [], {
22651
23806
  category: swarmEntry.category,
22652
23807
  scope: swarmEntry.scope,
22653
23808
  confidence: swarmEntry.confidence
@@ -22669,7 +23824,7 @@ async function checkHivePromotions(swarmEntries, config, directory) {
22669
23824
  });
22670
23825
  }
22671
23826
  const hiveDir = resolveHiveDataDir();
22672
- const result = await _internals29.transactHiveStore(async (ctx) => {
23827
+ const result = await _internals30.transactHiveStore(async (ctx) => {
22673
23828
  let newPromotions = 0;
22674
23829
  let encounters = 0;
22675
23830
  let advancements = 0;
@@ -22895,7 +24050,7 @@ async function authorizeAndRecordHiveMerge(args) {
22895
24050
  let authorized = true;
22896
24051
  let basis = "config-skipped-unlinked";
22897
24052
  try {
22898
- const decision = await _internals29.authorizeCuration({
24053
+ const decision = await _internals30.authorizeCuration({
22899
24054
  directory: hiveDir,
22900
24055
  action: "merge",
22901
24056
  entryId: survivingEntry.id,
@@ -22925,7 +24080,7 @@ async function authorizeAndRecordHiveMerge(args) {
22925
24080
  authorizationBasis: basis
22926
24081
  });
22927
24082
  }
22928
- var _internals29 = {
24083
+ var _internals30 = {
22929
24084
  readSwarmEntries: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory)),
22930
24085
  checkHivePromotions,
22931
24086
  readCuratorSummary,
@@ -22939,15 +24094,15 @@ var _internals29 = {
22939
24094
  };
22940
24095
  function createHivePromoterHook(directory, config) {
22941
24096
  const hook = async (_input, _output) => {
22942
- const swarmEntries = await _internals29.readSwarmEntries(directory);
22943
- const promotionSummary = await _internals29.checkHivePromotions(swarmEntries, config, directory);
22944
- const curatorSummary = await _internals29.readCuratorSummary(directory);
24097
+ const swarmEntries = await _internals30.readSwarmEntries(directory);
24098
+ const promotionSummary = await _internals30.checkHivePromotions(swarmEntries, config, directory);
24099
+ const curatorSummary = await _internals30.readCuratorSummary(directory);
22945
24100
  if (!curatorSummary)
22946
24101
  return;
22947
24102
  const hasActivity = promotionSummary.new_promotions > 0 || promotionSummary.encounters_incremented > 0 || promotionSummary.advancements > 0;
22948
24103
  if (!hasActivity)
22949
24104
  return;
22950
- await _internals29.appendCuratorRecommendation(directory, {
24105
+ await _internals30.appendCuratorRecommendation(directory, {
22951
24106
  action: "promote",
22952
24107
  lesson: `Hive promotion: ${promotionSummary.new_promotions} new, ${promotionSummary.encounters_incremented} encounters, ${promotionSummary.advancements} advancements, ${promotionSummary.total_hive_entries} total entries`,
22953
24108
  reason: JSON.stringify({
@@ -22985,16 +24140,16 @@ function normalizeManualActionability(fields) {
22985
24140
  async function promoteToHive(directory, lesson, category, options, config, actionable) {
22986
24141
  const trimmedLesson = lesson.trim();
22987
24142
  const actionableFields = normalizeManualActionability(actionable);
22988
- const sourceCohort = await _internals29.resolveCohortId(directory);
22989
- const policyConfig = config ?? _internals29.loadDefaultKnowledgeConfig();
22990
- const result = await _internals29.transactHiveStore(async (ctx) => {
24143
+ const sourceCohort = await _internals30.resolveCohortId(directory);
24144
+ const policyConfig = config ?? _internals30.loadDefaultKnowledgeConfig();
24145
+ const result = await _internals30.transactHiveStore(async (ctx) => {
22991
24146
  if (findNearDuplicate(trimmedLesson, ctx.entries, policyConfig.dedup_threshold)) {
22992
24147
  return {
22993
24148
  kind: "noop",
22994
24149
  return: `Lesson already exists in hive (near-duplicate).`
22995
24150
  };
22996
24151
  }
22997
- const validationResult = _internals29.validateLesson(trimmedLesson, ctx.entries.map((e) => e.lesson), {
24152
+ const validationResult = _internals30.validateLesson(trimmedLesson, ctx.entries.map((e) => e.lesson), {
22998
24153
  category: category || "process",
22999
24154
  scope: "global",
23000
24155
  confidence: 1
@@ -23105,16 +24260,16 @@ async function promoteFromSwarm(directory, lessonId, options, config) {
23105
24260
  if (!swarmEntry) {
23106
24261
  throw new Error(`Lesson ${lessonId} not found in .swarm/knowledge.jsonl`);
23107
24262
  }
23108
- const sourceCohort = await _internals29.resolveCohortId(directory);
23109
- const policyConfig = config ?? _internals29.loadDefaultKnowledgeConfig();
23110
- const result = await _internals29.transactHiveStore(async (ctx) => {
24263
+ const sourceCohort = await _internals30.resolveCohortId(directory);
24264
+ const policyConfig = config ?? _internals30.loadDefaultKnowledgeConfig();
24265
+ const result = await _internals30.transactHiveStore(async (ctx) => {
23111
24266
  if (findNearDuplicate(swarmEntry.lesson, ctx.entries, policyConfig.dedup_threshold)) {
23112
24267
  return {
23113
24268
  kind: "noop",
23114
24269
  return: `Lesson already exists in hive (near-duplicate).`
23115
24270
  };
23116
24271
  }
23117
- const validationResult = _internals29.validateLesson(swarmEntry.lesson, ctx.entries.map((e) => e.lesson), {
24272
+ const validationResult = _internals30.validateLesson(swarmEntry.lesson, ctx.entries.map((e) => e.lesson), {
23118
24273
  category: swarmEntry.category,
23119
24274
  scope: swarmEntry.scope,
23120
24275
  confidence: swarmEntry.confidence
@@ -23202,7 +24357,7 @@ async function promoteFromSwarm(directory, lessonId, options, config) {
23202
24357
  }
23203
24358
 
23204
24359
  // src/hooks/knowledge-curator.ts
23205
- import { createHash as createHash12 } from "crypto";
24360
+ import { createHash as createHash13 } from "crypto";
23206
24361
  import { existsSync as existsSync15 } from "fs";
23207
24362
  import { readFile as readFile9, realpath as realpath3, writeFile as writeFile6 } from "fs/promises";
23208
24363
  import * as path29 from "path";
@@ -23434,12 +24589,12 @@ function recordSeenRetroSection(key, value, timestamp) {
23434
24589
  capSeenRetroSections();
23435
24590
  }
23436
24591
  function hashContent(content) {
23437
- return createHash12("sha1").update(content).digest("hex");
24592
+ return createHash13("sha1").update(content).digest("hex");
23438
24593
  }
23439
24594
  async function loadConfigForPolicyCurator(directory) {
23440
- const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-bf3smw7k.js");
24595
+ const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-5zc62306.js");
23441
24596
  try {
23442
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-00hyhg47.js");
24597
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-8n602qc2.js");
23443
24598
  const { config: loadedConfig } = loadPluginConfigWithMeta2(directory);
23444
24599
  return KnowledgeConfigSchema2.parse(loadedConfig.knowledge ?? {});
23445
24600
  } catch {
@@ -23449,7 +24604,7 @@ async function loadConfigForPolicyCurator(directory) {
23449
24604
  async function canonicalExistingPath(candidate) {
23450
24605
  let resolved = path29.resolve(candidate);
23451
24606
  try {
23452
- resolved = await _internals30.realpath(resolved);
24607
+ resolved = await _internals31.realpath(resolved);
23453
24608
  } catch {}
23454
24609
  return resolved;
23455
24610
  }
@@ -24281,9 +25436,9 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
24281
25436
  } catch {}
24282
25437
  }
24283
25438
  if (!options?.skipAutoPromotion) {
24284
- await _internals30.runAutoPromotion(directory, config);
25439
+ await _internals31.runAutoPromotion(directory, config);
24285
25440
  if (phaseInfo.phase_number > 0) {
24286
- await _internals30.runAutoDemotion(directory, config, phaseInfo.phase_number);
25441
+ await _internals31.runAutoDemotion(directory, config, phaseInfo.phase_number);
24287
25442
  }
24288
25443
  }
24289
25444
  return { stored, reinforced, skipped, rejected, quarantined };
@@ -24398,7 +25553,7 @@ function createKnowledgeCuratorHook(directory, config, options = {}) {
24398
25553
  }
24399
25554
  inFlightEvidenceEntries.add(evidenceKey);
24400
25555
  try {
24401
- await _internals30.curateAndStoreSwarm(batch.lessons, batch.projectName, { phase_number: batch.phaseNumber }, directory, config, {
25556
+ await _internals31.curateAndStoreSwarm(batch.lessons, batch.projectName, { phase_number: batch.phaseNumber }, directory, config, {
24402
25557
  llmDelegate: options.llmDelegateFactory?.(trigger.sessionID),
24403
25558
  enrichmentQuota: options.enrichmentQuota
24404
25559
  });
@@ -24430,14 +25585,14 @@ function createKnowledgeCuratorHook(directory, config, options = {}) {
24430
25585
  const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
24431
25586
  const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
24432
25587
  const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
24433
- await _internals30.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config, {
25588
+ await _internals31.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config, {
24434
25589
  llmDelegate: options.llmDelegateFactory?.(trigger.sessionID),
24435
25590
  enrichmentQuota: options.enrichmentQuota
24436
25591
  });
24437
25592
  };
24438
25593
  return safeHook(handler);
24439
25594
  }
24440
- var _internals30 = {
25595
+ var _internals31 = {
24441
25596
  isWriteToEvidenceFile,
24442
25597
  curateAndStoreSwarm,
24443
25598
  runAutoPromotion,
@@ -24711,7 +25866,7 @@ function isValidTelemetryEntry(value) {
24711
25866
  const nonNegFinite = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
24712
25867
  return typeof obj.timestamp === "string" && typeof obj.task_id === "string" && typeof obj.agent_role === "string" && typeof obj.delegation_reason === "string" && nonNegFinite(obj.token_estimate) && nonNegFinite(obj.cache_hits) && nonNegFinite(obj.cache_misses) && nonNegFinite(obj.stale_entries) && nonNegFinite(obj.recommended_reads) && nonNegFinite(obj.skipped_reads) && typeof obj.success === "boolean";
24713
25868
  }
24714
- var _internals31 = {
25869
+ var _internals32 = {
24715
25870
  appendFileSync: fs14.appendFileSync,
24716
25871
  readFileSync: fs14.readFileSync,
24717
25872
  existsSync: fs14.existsSync,
@@ -24802,25 +25957,25 @@ function parseManifestLine(line) {
24802
25957
  }
24803
25958
  function readBoundedChunk(filePath, maxBytes) {
24804
25959
  try {
24805
- if (!_internals31.existsSync(filePath)) {
25960
+ if (!_internals32.existsSync(filePath)) {
24806
25961
  return { text: "", truncated: false };
24807
25962
  }
24808
- const fd = _internals31.openSync(filePath, "r");
25963
+ const fd = _internals32.openSync(filePath, "r");
24809
25964
  try {
24810
- const size = _internals31.statSync(filePath).size;
25965
+ const size = _internals32.statSync(filePath).size;
24811
25966
  const truncated = size > maxBytes;
24812
25967
  const len = Math.min(size, maxBytes);
24813
25968
  const buf = Buffer.alloc(len);
24814
25969
  let read = 0;
24815
25970
  while (read < len) {
24816
- const n = _internals31.readSync(fd, buf, read, len - read, read);
25971
+ const n = _internals32.readSync(fd, buf, read, len - read, read);
24817
25972
  if (n <= 0)
24818
25973
  break;
24819
25974
  read += n;
24820
25975
  }
24821
25976
  return { text: buf.toString("utf-8", 0, read), truncated };
24822
25977
  } finally {
24823
- _internals31.closeSync(fd);
25978
+ _internals32.closeSync(fd);
24824
25979
  }
24825
25980
  } catch {
24826
25981
  warnThrottled("bounded read failed (transient I/O)");
@@ -24829,9 +25984,9 @@ function readBoundedChunk(filePath, maxBytes) {
24829
25984
  }
24830
25985
  function fileSizeOrZero(filePath) {
24831
25986
  try {
24832
- if (!_internals31.existsSync(filePath))
25987
+ if (!_internals32.existsSync(filePath))
24833
25988
  return 0;
24834
- return _internals31.statSync(filePath).size;
25989
+ return _internals32.statSync(filePath).size;
24835
25990
  } catch {
24836
25991
  return 0;
24837
25992
  }
@@ -24873,17 +26028,17 @@ function atomicReplace(directory, content) {
24873
26028
  const finalPath = telemetryFilePath(directory);
24874
26029
  const tmpPath = tmpFilePath(directory);
24875
26030
  try {
24876
- if (_internals31.existsSync(tmpPath)) {
26031
+ if (_internals32.existsSync(tmpPath)) {
24877
26032
  try {
24878
- _internals31.unlinkSync(tmpPath);
26033
+ _internals32.unlinkSync(tmpPath);
24879
26034
  } catch {}
24880
26035
  }
24881
- _internals31.writeFileSync(tmpPath, content, "utf-8");
24882
- _internals31.renameSync(tmpPath, finalPath);
26036
+ _internals32.writeFileSync(tmpPath, content, "utf-8");
26037
+ _internals32.renameSync(tmpPath, finalPath);
24883
26038
  } catch {
24884
26039
  try {
24885
- if (_internals31.existsSync(tmpPath)) {
24886
- _internals31.unlinkSync(tmpPath);
26040
+ if (_internals32.existsSync(tmpPath)) {
26041
+ _internals32.unlinkSync(tmpPath);
24887
26042
  }
24888
26043
  } catch {}
24889
26044
  throw new Error("context-telemetry atomic replace failed");
@@ -24893,20 +26048,20 @@ function withStoreLock(directory, fn) {
24893
26048
  const lockPath = lockFilePath(directory);
24894
26049
  let acquired = false;
24895
26050
  try {
24896
- _internals31.mkdirSync(path30.dirname(lockPath), { recursive: true });
24897
- const fd = _internals31.openSync(lockPath, "wx");
24898
- _internals31.closeSync(fd);
26051
+ _internals32.mkdirSync(path30.dirname(lockPath), { recursive: true });
26052
+ const fd = _internals32.openSync(lockPath, "wx");
26053
+ _internals32.closeSync(fd);
24899
26054
  acquired = true;
24900
26055
  } catch {
24901
26056
  try {
24902
- const age = Date.now() - _internals31.statSync(lockPath).mtimeMs;
26057
+ const age = Date.now() - _internals32.statSync(lockPath).mtimeMs;
24903
26058
  if (age > 5 * 60000) {
24904
26059
  try {
24905
- _internals31.unlinkSync(lockPath);
26060
+ _internals32.unlinkSync(lockPath);
24906
26061
  } catch {}
24907
26062
  try {
24908
- const fd = _internals31.openSync(lockPath, "wx");
24909
- _internals31.closeSync(fd);
26063
+ const fd = _internals32.openSync(lockPath, "wx");
26064
+ _internals32.closeSync(fd);
24910
26065
  acquired = true;
24911
26066
  } catch {
24912
26067
  acquired = false;
@@ -24922,32 +26077,32 @@ function withStoreLock(directory, fn) {
24922
26077
  return fn();
24923
26078
  } finally {
24924
26079
  try {
24925
- _internals31.unlinkSync(lockPath);
26080
+ _internals32.unlinkSync(lockPath);
24926
26081
  } catch {}
24927
26082
  }
24928
26083
  }
24929
26084
  var _lastWarnAt = 0;
24930
26085
  function warnThrottled(message) {
24931
26086
  const now2 = Date.now();
24932
- if (now2 - _lastWarnAt < _internals31.limits.warnCooldownMs)
26087
+ if (now2 - _lastWarnAt < _internals32.limits.warnCooldownMs)
24933
26088
  return;
24934
26089
  _lastWarnAt = now2;
24935
26090
  warn(`context-telemetry: ${message}`);
24936
26091
  }
24937
26092
  function readStore(directory, bounded) {
24938
26093
  const filePath = telemetryFilePath(directory);
24939
- if (!_internals31.existsSync(filePath)) {
26094
+ if (!_internals32.existsSync(filePath)) {
24940
26095
  return { manifest: null, records: [], corruptLines: 0, truncated: false };
24941
26096
  }
24942
26097
  let text;
24943
26098
  let truncated = false;
24944
26099
  if (bounded) {
24945
- const chunk = readBoundedChunk(filePath, _internals31.limits.readMaxBytes);
26100
+ const chunk = readBoundedChunk(filePath, _internals32.limits.readMaxBytes);
24946
26101
  text = chunk.text;
24947
26102
  truncated = chunk.truncated;
24948
26103
  } else {
24949
26104
  try {
24950
- text = _internals31.readFileSync(filePath, "utf-8");
26105
+ text = _internals32.readFileSync(filePath, "utf-8");
24951
26106
  } catch {
24952
26107
  return { manifest: null, records: [], corruptLines: 0, truncated: false };
24953
26108
  }
@@ -25065,7 +26220,7 @@ function periodMs(oldest, newest) {
25065
26220
  }
25066
26221
  function compactStore(directory, trigger = "compaction", alreadyLocked = false) {
25067
26222
  const filePath = telemetryFilePath(directory);
25068
- if (!_internals31.existsSync(filePath))
26223
+ if (!_internals32.existsSync(filePath))
25069
26224
  return;
25070
26225
  const run = () => {
25071
26226
  const view = readStore(directory, false);
@@ -25077,7 +26232,7 @@ function compactStore(directory, trigger = "compaction", alreadyLocked = false)
25077
26232
  const kept = [];
25078
26233
  for (const rec of view.records) {
25079
26234
  const ts = Date.parse(rec.timestamp);
25080
- if (!Number.isNaN(ts) && now2 - ts > _internals31.limits.ageMaxMs) {
26235
+ if (!Number.isNaN(ts) && now2 - ts > _internals32.limits.ageMaxMs) {
25081
26236
  agePruned.push(rec);
25082
26237
  } else {
25083
26238
  kept.push(rec);
@@ -25088,7 +26243,7 @@ function compactStore(directory, trigger = "compaction", alreadyLocked = false)
25088
26243
  for (let i = kept.length - 1;i >= 0; i -= 1) {
25089
26244
  const rec = kept[i];
25090
26245
  const lineBytes = Buffer.byteLength(JSON.stringify(rec)) + 1;
25091
- if (retained.length >= _internals31.limits.activeMaxEntries || bytes + lineBytes > _internals31.limits.activeMaxBytes) {
26246
+ if (retained.length >= _internals32.limits.activeMaxEntries || bytes + lineBytes > _internals32.limits.activeMaxBytes) {
25092
26247
  break;
25093
26248
  }
25094
26249
  retained.push(rec);
@@ -25131,7 +26286,7 @@ function compactStore(directory, trigger = "compaction", alreadyLocked = false)
25131
26286
  oldest: folded.oldestTimestamp,
25132
26287
  newest: folded.newestTimestamp,
25133
26288
  bytes: fileSizeOrZero(filePath),
25134
- limitBytes: _internals31.limits.activeMaxBytes
26289
+ limitBytes: _internals32.limits.activeMaxBytes
25135
26290
  });
25136
26291
  };
25137
26292
  if (alreadyLocked) {
@@ -25142,10 +26297,10 @@ function compactStore(directory, trigger = "compaction", alreadyLocked = false)
25142
26297
  }
25143
26298
  function migrateCutover(directory, trigger = "compaction", alreadyLocked = false) {
25144
26299
  const filePath = telemetryFilePath(directory);
25145
- if (!_internals31.existsSync(filePath))
26300
+ if (!_internals32.existsSync(filePath))
25146
26301
  return;
25147
26302
  const run = () => {
25148
- if (!_internals31.existsSync(filePath))
26303
+ if (!_internals32.existsSync(filePath))
25149
26304
  return;
25150
26305
  const view = readStore(directory, false);
25151
26306
  if (view.manifest === null && view.records.length === 0)
@@ -25156,7 +26311,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
25156
26311
  const kept = [];
25157
26312
  for (const rec of view.records) {
25158
26313
  const ts = Date.parse(rec.timestamp);
25159
- if (!Number.isNaN(ts) && now2 - ts > _internals31.limits.ageMaxMs) {
26314
+ if (!Number.isNaN(ts) && now2 - ts > _internals32.limits.ageMaxMs) {
25160
26315
  agePruned.push(rec);
25161
26316
  } else {
25162
26317
  kept.push(rec);
@@ -25167,7 +26322,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
25167
26322
  for (let i = kept.length - 1;i >= 0; i -= 1) {
25168
26323
  const rec = kept[i];
25169
26324
  const lb = Buffer.byteLength(JSON.stringify(rec)) + 1;
25170
- if (retained.length >= _internals31.limits.activeMaxEntries || bytes + lb > _internals31.limits.activeMaxBytes) {
26325
+ if (retained.length >= _internals32.limits.activeMaxEntries || bytes + lb > _internals32.limits.activeMaxBytes) {
25171
26326
  break;
25172
26327
  }
25173
26328
  retained.push(rec);
@@ -25186,7 +26341,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
25186
26341
  let foldedBytes = 0;
25187
26342
  for (const cand of candidates) {
25188
26343
  const cb = Buffer.byteLength(JSON.stringify(cand)) + 1;
25189
- if (foldedBytes + cb > _internals31.limits.compactMaxBytes && toFold.size > 0) {
26344
+ if (foldedBytes + cb > _internals32.limits.compactMaxBytes && toFold.size > 0) {
25190
26345
  break;
25191
26346
  }
25192
26347
  toFold.add(cand);
@@ -25229,7 +26384,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
25229
26384
  oldest: folded.oldestTimestamp,
25230
26385
  newest: folded.newestTimestamp,
25231
26386
  bytes: fileSizeOrZero(filePath),
25232
- limitBytes: _internals31.limits.activeMaxBytes
26387
+ limitBytes: _internals32.limits.activeMaxBytes
25233
26388
  });
25234
26389
  };
25235
26390
  if (alreadyLocked) {
@@ -25241,7 +26396,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
25241
26396
  function finalizeContextTelemetry(directory) {
25242
26397
  try {
25243
26398
  const filePath = telemetryFilePath(directory);
25244
- if (!_internals31.existsSync(filePath))
26399
+ if (!_internals32.existsSync(filePath))
25245
26400
  return;
25246
26401
  withStoreLock(directory, () => {
25247
26402
  let prev = Number.POSITIVE_INFINITY;
@@ -25279,7 +26434,7 @@ function emitContextTelemetryHealth(_directory, payload) {
25279
26434
  } catch {}
25280
26435
  }
25281
26436
  function emitHealth(directory, payload) {
25282
- _internals31.emitHealth(directory, payload);
26437
+ _internals32.emitHealth(directory, payload);
25283
26438
  }
25284
26439
 
25285
26440
  // src/memory/finalize-reward-sweep.ts
@@ -25532,100 +26687,6 @@ function summarizePiiFindings(findings) {
25532
26687
  }
25533
26688
  var NER_MODEL_CACHE_DIR = path31.join(os3.homedir(), ".cache", "opencode-swarm", "models");
25534
26689
 
25535
- // src/memory/redaction.ts
25536
- import { createHash as createHash13 } from "crypto";
25537
- var SECRET_PATTERNS = [
25538
- { type: "openai_api_key", pattern: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
25539
- {
25540
- type: "github_token",
25541
- pattern: /\b(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{20,}\b/g
25542
- },
25543
- { type: "aws_access_key_id", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
25544
- {
25545
- type: "private_key_block",
25546
- pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g
25547
- },
25548
- {
25549
- type: "authorization_bearer",
25550
- pattern: /\bAuthorization\s*:\s*Bearer\s+[A-Za-z0-9._~+/=-]{12,}/gi
25551
- },
25552
- {
25553
- type: "env_secret",
25554
- pattern: /\b(?:[A-Z][A-Z0-9]+_)+(?:KEY|TOKEN|SECRET|PASSWORD)\b\s*=\s*["']?[^\s"'`]{8,}["']?/gi
25555
- },
25556
- { type: "gitlab_token", pattern: /\bgl(?:pat|ptt)-[A-Za-z0-9_-]{15,}\b/g },
25557
- { type: "slack_token", pattern: /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g },
25558
- {
25559
- type: "jwt_token",
25560
- pattern: /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g
25561
- },
25562
- {
25563
- type: "aws_secret_access_key",
25564
- pattern: /\b(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY|secret_access_key|SecretAccessKey)"?\s*[=:]\s*["']?[A-Za-z0-9/+=]{40}\b/g
25565
- },
25566
- {
25567
- type: "aws_secret_access_key_context",
25568
- pattern: /\bAKIA[0-9A-Z]{16}\b[^\n]{0,200}?\b[A-Za-z0-9/+=]{40}\b/g
25569
- },
25570
- {
25571
- type: "stripe_secret_key",
25572
- pattern: /\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\b/g
25573
- },
25574
- { type: "google_api_key", pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g },
25575
- {
25576
- type: "openssh_private_key_block",
25577
- pattern: /-----BEGIN[ ]OPENSSH[ ]PRIVATE[ ]KEY-----[\s\S]*?-----END[ ]OPENSSH[ ]PRIVATE[ ]KEY-----/g
25578
- }
25579
- ];
25580
- var REDACTION_POLICY_SALT = 2;
25581
- function computeRedactionPolicyVersion(policy) {
25582
- return REDACTION_POLICY_SALT * 1e6 + SECRET_PATTERNS.length * 2 + (policy.rejectDurableSecrets ? 1 : 0) + (policy.detectPii ? 4 : 0) + (policy.rejectDurablePii ? 8 : 0) + (policy.piiDetector === "ner" ? 16 : 0);
25583
- }
25584
- var FINGERPRINT_ALGORITHM_VERSION = 2;
25585
- var LEGACY_FINGERPRINT_ALGORITHM_VERSION = 1;
25586
- var _internals32 = {
25587
- currentAlgorithmVersion: FINGERPRINT_ALGORITHM_VERSION
25588
- };
25589
- function classifyStoredFingerprintAlgorithmVersion(rawStoredVersion, currentVersion = _internals32.currentAlgorithmVersion) {
25590
- const storedVersion = rawStoredVersion === undefined ? LEGACY_FINGERPRINT_ALGORITHM_VERSION : rawStoredVersion;
25591
- if (typeof storedVersion !== "number" || !Number.isFinite(storedVersion)) {
25592
- return { status: "unknown" };
25593
- }
25594
- return storedVersion === currentVersion ? { status: "comparable" } : { status: "mismatch", storedVersion, currentVersion };
25595
- }
25596
- function computeMemoryCohortFingerprint(input) {
25597
- const canonical = stableCanonicalStringify(input);
25598
- return createHash13("sha256").update(canonical).digest("hex").slice(0, 12);
25599
- }
25600
- function buildMemoryCohortFingerprintInput(config) {
25601
- return {
25602
- provider: config.provider,
25603
- redaction_policy_version: computeRedactionPolicyVersion({
25604
- rejectDurableSecrets: config.redaction.rejectDurableSecrets,
25605
- detectPii: config.redaction.detectPii,
25606
- rejectDurablePii: config.redaction.rejectDurablePii,
25607
- piiDetector: config.redaction.piiDetector
25608
- }),
25609
- embedding_model: config.embeddings.model,
25610
- embedding_dimension: config.embeddings.dimension,
25611
- embedding_version: config.embeddings.version ?? "default"
25612
- };
25613
- }
25614
- function findSecrets(text) {
25615
- const findings = [];
25616
- for (const { type, pattern } of SECRET_PATTERNS) {
25617
- pattern.lastIndex = 0;
25618
- for (const match of text.matchAll(pattern)) {
25619
- if (match[0])
25620
- findings.push({ type, match: match[0] });
25621
- }
25622
- }
25623
- return findings;
25624
- }
25625
- function containsSecret(text) {
25626
- return findSecrets(text).length > 0;
25627
- }
25628
-
25629
26690
  // src/memory/sentinel.ts
25630
26691
  var MEMORY_RECALL_SENTINEL = "## Retrieved Swarm Memory";
25631
26692
 
@@ -35720,7 +36781,7 @@ async function runFinalizeStage(ctx) {
35720
36781
  }
35721
36782
  }
35722
36783
  try {
35723
- const { CuratorConfigSchema: CCS } = await import("./schema-bf3smw7k.js");
36784
+ const { CuratorConfigSchema: CCS } = await import("./schema-5zc62306.js");
35724
36785
  const { config: pmLoadedConfig } = _internals41.loadPluginConfigWithMeta(ctx.directory);
35725
36786
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
35726
36787
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
@@ -37939,9 +39000,9 @@ var _internals45 = {
37939
39000
  loadPluginConfigWithMeta,
37940
39001
  loadCuratorDeps: async () => {
37941
39002
  const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
37942
- import("./schema-bf3smw7k.js"),
37943
- import("./curator-dnjf9ser.js"),
37944
- import("./curator-llm-factory-cnatbky1.js")
39003
+ import("./schema-5zc62306.js"),
39004
+ import("./curator-pjjw3ja4.js"),
39005
+ import("./curator-llm-factory-7mfvey3x.js")
37945
39006
  ]);
37946
39007
  return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
37947
39008
  }
@@ -38950,7 +40011,7 @@ async function computeCurationDiagnostics(directory, entries) {
38950
40011
  let scanCompleted = false;
38951
40012
  let scanRemaining = 0;
38952
40013
  try {
38953
- const { getScanStatus } = await import("./scan-cursor-6awybk8b.js");
40014
+ const { getScanStatus } = await import("./scan-cursor-q3530gc8.js");
38954
40015
  const status = await getScanStatus(directory);
38955
40016
  scanGeneration = status.generation;
38956
40017
  scanCompleted = status.completed;
@@ -38958,19 +40019,19 @@ async function computeCurationDiagnostics(directory, entries) {
38958
40019
  } catch {}
38959
40020
  let configMatch = null;
38960
40021
  try {
38961
- const { isLinked: isLinked2 } = await import("./knowledge-link-4frk38w8.js");
40022
+ const { isLinked: isLinked2 } = await import("./knowledge-link-z9cchqdj.js");
38962
40023
  if (isLinked2(directory)) {
38963
- const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-bf3smw7k.js");
40024
+ const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-5zc62306.js");
38964
40025
  let config;
38965
40026
  try {
38966
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-00hyhg47.js");
40027
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-8n602qc2.js");
38967
40028
  const loaded = loadPluginConfigWithMeta2(directory);
38968
40029
  config = KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
38969
40030
  } catch {
38970
40031
  config = KnowledgeConfigSchema2.parse({});
38971
40032
  }
38972
40033
  const { cohortConfigFingerprint: cohortConfigFingerprint2 } = await import("./config-fingerprint-v22xh5a2.js");
38973
- const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-jabphe51.js");
40034
+ const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-72qx868r.js");
38974
40035
  const currentFp = cohortConfigFingerprint2(buildConfigFingerprintInput2(config));
38975
40036
  const cohortFp = await readCohortConfigFingerprint(directory);
38976
40037
  configMatch = cohortFp === null ? null : currentFp === cohortFp;
@@ -40283,7 +41344,7 @@ async function handleDoctorCommand(directory, args) {
40283
41344
  const result = runConfigDoctor(config, directory);
40284
41345
  let output;
40285
41346
  if (enableAutoFix && result.hasAutoFixableIssues) {
40286
- const { runConfigDoctorWithFixes } = await import("./config-doctor-q9v8yscr.js");
41347
+ const { runConfigDoctorWithFixes } = await import("./config-doctor-4jxf9w9e.js");
40287
41348
  const fixResult = await runConfigDoctorWithFixes(directory, config, true, {
40288
41349
  applyLossy: true
40289
41350
  });
@@ -40321,7 +41382,7 @@ async function handleDoctorCommand(directory, args) {
40321
41382
  `;
40322
41383
  }
40323
41384
  try {
40324
- const { runModelPreflight } = await import("./model-preflight-b95w8wxy.js");
41385
+ const { runModelPreflight } = await import("./model-preflight-cv9kvw8h.js");
40325
41386
  const preflight = await runModelPreflight(config, swarmState.opencodeClient);
40326
41387
  if (preflight.catalogAvailable) {
40327
41388
  const unresolved = preflight.resolutions.filter((resolution) => resolution.status === "unresolved");
@@ -41223,7 +42284,7 @@ async function handleEvidenceCommand(directory, args) {
41223
42284
  return formatTaskEvidenceMarkdown(evidenceData);
41224
42285
  }
41225
42286
  async function handleEvidenceSummaryCommand(directory) {
41226
- const { buildEvidenceSummary } = await import("./evidence-summary-service-5drv65qh.js");
42287
+ const { buildEvidenceSummary } = await import("./evidence-summary-service-5ffkbs50.js");
41227
42288
  const artifact = await buildEvidenceSummary(directory);
41228
42289
  if (!artifact) {
41229
42290
  return "No plan found. Run `/swarm plan` to check plan status.";
@@ -76285,7 +77346,7 @@ async function runValidationWithTransientRetry(input, candidateContent, baseline
76285
77346
  if (!input.dispatcher) {
76286
77347
  throw new Error("no evaluation dispatcher available (cannot run validation)");
76287
77348
  }
76288
- const { createModelEvaluationExecutor: createModelEvaluationExecutor2 } = await import("./runner-gheaxd5r.js");
77349
+ const { createModelEvaluationExecutor: createModelEvaluationExecutor2 } = await import("./runner-eagt6gf8.js");
76289
77350
  const executor = createModelEvaluationExecutor2(input.dispatcher, input.sessionId);
76290
77351
  const result = await withProtectedSetIntegrity([evalInputRoot, ...protectedRoots(input.directory)], () => _internals97.evaluateCandidateV1({
76291
77352
  projectRoot: input.directory,
@@ -78330,7 +79391,7 @@ function buildDetailedHelp(commandName, entry) {
78330
79391
  async function handleHelpCommand(ctx) {
78331
79392
  const targetCommand = ctx.args.join(" ");
78332
79393
  if (!targetCommand) {
78333
- const { buildHelpText } = await import("./index-17h6ewqp.js");
79394
+ const { buildHelpText } = await import("./index-3qpr16k2.js");
78334
79395
  return buildHelpText();
78335
79396
  }
78336
79397
  const tokens = targetCommand.split(/\s+/);
@@ -78339,7 +79400,7 @@ async function handleHelpCommand(ctx) {
78339
79400
  return _internals100.buildDetailedHelp(resolved.key, resolved.entry);
78340
79401
  }
78341
79402
  const similar = _internals100.findSimilarCommands(targetCommand);
78342
- const { buildHelpText: fullHelp } = await import("./index-17h6ewqp.js");
79403
+ const { buildHelpText: fullHelp } = await import("./index-3qpr16k2.js");
78343
79404
  if (similar.length > 0) {
78344
79405
  return `Command '/swarm ${targetCommand}' not found.
78345
79406
 
@@ -78670,7 +79731,7 @@ var COMMAND_REGISTRY = {
78670
79731
  },
78671
79732
  "guardrail explain": {
78672
79733
  handler: async (ctx) => {
78673
- const { handleGuardrailExplain } = await import("./guardrail-explain-z8f6qhz2.js");
79734
+ const { handleGuardrailExplain } = await import("./guardrail-explain-b9vr4ta3.js");
78674
79735
  return handleGuardrailExplain(ctx.directory, ctx.args);
78675
79736
  },
78676
79737
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -78680,7 +79741,7 @@ var COMMAND_REGISTRY = {
78680
79741
  },
78681
79742
  "guardrail reset": {
78682
79743
  handler: async (ctx) => {
78683
- const { handleGuardrailReset } = await import("./guardrail-reset-ga6e11r9.js");
79744
+ const { handleGuardrailReset } = await import("./guardrail-reset-pggm9hx4.js");
78684
79745
  return handleGuardrailReset(ctx.args, ctx.sessionID);
78685
79746
  },
78686
79747
  description: "Reset one exact active invocation/action circuit after repair",
@@ -78689,7 +79750,7 @@ var COMMAND_REGISTRY = {
78689
79750
  },
78690
79751
  "guardrail-explain": {
78691
79752
  handler: async (ctx) => {
78692
- const { handleGuardrailExplain } = await import("./guardrail-explain-z8f6qhz2.js");
79753
+ const { handleGuardrailExplain } = await import("./guardrail-explain-b9vr4ta3.js");
78693
79754
  return handleGuardrailExplain(ctx.directory, ctx.args);
78694
79755
  },
78695
79756
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -78699,7 +79760,7 @@ var COMMAND_REGISTRY = {
78699
79760
  },
78700
79761
  "guardrail-reset": {
78701
79762
  handler: async (ctx) => {
78702
- const { handleGuardrailReset } = await import("./guardrail-reset-ga6e11r9.js");
79763
+ const { handleGuardrailReset } = await import("./guardrail-reset-pggm9hx4.js");
78703
79764
  return handleGuardrailReset(ctx.args, ctx.sessionID);
78704
79765
  },
78705
79766
  description: "Reset one exact active invocation/action circuit after repair",
@@ -78709,7 +79770,7 @@ var COMMAND_REGISTRY = {
78709
79770
  },
78710
79771
  "guardrail-log": {
78711
79772
  handler: async (ctx) => {
78712
- const { handleGuardrailLog } = await import("./guardrail-log-zwec6ann.js");
79773
+ const { handleGuardrailLog } = await import("./guardrail-log-hrt36jz5.js");
78713
79774
  return handleGuardrailLog(ctx.directory, ctx.args);
78714
79775
  },
78715
79776
  description: "Read the guardrail decision log (use --blocks-only for blocks)",
@@ -79155,7 +80216,7 @@ Subcommands:
79155
80216
  handler: (ctx) => handleAbortPrWorkflowCommand(ctx.directory, ctx.args, ctx.sessionID),
79156
80217
  description: "Clear a stuck PR_REVIEW/PR_FEEDBACK mechanical gate and stop the auto-resume loop [mode] [reason]",
79157
80218
  args: "[PR_REVIEW|PR_FEEDBACK] [reason...]",
79158
- details: "Human-only escape hatch for an unrecoverable PR_REVIEW or PR_FEEDBACK mechanical gate. When the architect cannot reach complete_pr_workflow \u2014 for example a compound `git fetch && git checkout` was rejected as read-only shell syntax, the PR head cannot be fetched, or the working tree is on the wrong branch \u2014 running this clears the durable gate state for the current session and stops the auto-resume loop without depending on the trapped model. The agent itself cannot run this command; it must call the abort_pr_workflow tool (or ask you to run this command). Both paths funnel into the same fail-closed abortPrWorkflow hook, which refuses while the workflow is armed for publication or while PR workflow lanes are still in flight. This human-only force path has exactly one exception to that second refusal (issue #2251): when the ONLY lanes still blocking are ones past the 30-minute staleness horizon that the liveness probe reports as still running \u2014 a lane nothing will ever settle on a schedule \u2014 it clears the gate anyway, names exactly which lanes it overrode, and finalizes their delegation records so the session can start a new PR workflow. Those sessions are NOT stopped and their output is NOT collected. A lane with a fresh updatedAt still blocks even under force, and any delegation record that still keeps the session blocked is named in the warning. When checkout preparation preserved a stash, the result instructs the caller to run prepare_pr_workflow_checkout operation=restore after the clear. An audit event is appended to .swarm/events.jsonl.",
80219
+ details: 'Human-only escape hatch for an unrecoverable PR_REVIEW or PR_FEEDBACK mechanical gate. When the architect cannot reach complete_pr_workflow \u2014 for example a compound `git fetch && git checkout` was rejected as read-only shell syntax, the PR head cannot be fetched, or the working tree is on the wrong branch \u2014 running this clears the durable gate state for the current session and stops the auto-resume loop without depending on the trapped model. The agent itself cannot run this command; it must call the abort_pr_workflow tool (or ask you to run this command). Both paths funnel into the same fail-closed abortPrWorkflow hook, which refuses while the workflow is armed for publication or while PR workflow lanes are still in flight. Issue #2108 adds the two audited exits from an armed publication window: the invalidate_pr_feedback_publication tool (change approved content \u2014 every approval of the generation is superseded and the full ladder re-runs) and the abort_pr_workflow tool kind "cancel-publication" with cancel_publication: true and a reason (terminal no-publish cancellation; never grants push authority). A plain recovery or force abort never clears an armed window. This human-only force path has exactly one exception to the lane refusal (issue #2251): when the ONLY lanes still blocking are ones past the 30-minute staleness horizon that the liveness probe reports as still running \u2014 a lane nothing will ever settle on a schedule \u2014 it clears the gate anyway, names exactly which lanes it overrode, and finalizes their delegation records so the session can start a new PR workflow. Those sessions are NOT stopped and their output is NOT collected. A lane with a fresh updatedAt still blocks even under force, and any delegation record that still keeps the session blocked is named in the warning. When checkout preparation preserved a stash, the result instructs the caller to run prepare_pr_workflow_checkout operation=restore after the clear. An audit event is appended to .swarm/events.jsonl.',
79159
80220
  category: "utility",
79160
80221
  toolPolicy: "restricted"
79161
80222
  },
@@ -84696,7 +85757,7 @@ function getDisplayFinalPromptPressure() {
84696
85757
  async function rehydratePrSubscriptions(sessionID, directory) {
84697
85758
  const map = new Map;
84698
85759
  try {
84699
- const { listActive: listActive2 } = await import("./pr-subscriptions-00evnffe.js");
85760
+ const { listActive: listActive2 } = await import("./pr-subscriptions-76vg2xya.js");
84700
85761
  const records = await listActive2(directory);
84701
85762
  for (const record of records) {
84702
85763
  if (record.sessionID !== sessionID)
@@ -85142,7 +86203,7 @@ function isLaneOwnedByCurrentSession(branchName, expectedSessionId) {
85142
86203
  return extracted === expectedSessionId;
85143
86204
  }
85144
86205
  async function inspectStandardWorktreeCollisionOwnership(identity) {
85145
- const collisionOwnership = await import("./worktree-collision-ownership-ej10dhwe.js");
86206
+ const collisionOwnership = await import("./worktree-collision-ownership-2qxjtxt6.js");
85146
86207
  return collisionOwnership.inspectStandardWorktreeCollisionOwnership(identity);
85147
86208
  }
85148
86209
  async function runRecoveryGit(directory, args, timeoutMs = 15000) {
@@ -85551,7 +86612,7 @@ async function precreateStandardWorktreeSession(args) {
85551
86612
  const laneProfile = computeLaneRuntimeProfile(worktreeConfig.runtime_isolation, laneIndex, handle.worktreePath);
85552
86613
  if (laneProfile) {
85553
86614
  try {
85554
- const { writeLaneProfileToDiskReal } = await import("./core-ev3bn503.js");
86615
+ const { writeLaneProfileToDiskReal } = await import("./core-xf2f087t.js");
85555
86616
  await writeLaneProfileToDiskReal(handle.worktreePath, laneProfile.laneIndex, laneProfile.envOverrides);
85556
86617
  } catch {}
85557
86618
  }
@@ -86476,7 +87537,7 @@ async function finishStandardWorktreeDispatch(directory, dispatch, config, callI
86476
87537
  }
86477
87538
  clearWorktreeMergeStatus(statusKey);
86478
87539
  try {
86479
- const { removeLaneProfileFromDiskReal } = await import("./core-ev3bn503.js");
87540
+ const { removeLaneProfileFromDiskReal } = await import("./core-xf2f087t.js");
86480
87541
  await removeLaneProfileFromDiskReal(dispatch.handle.worktreePath, dispatch.laneIndex);
86481
87542
  } catch {}
86482
87543
  const state = serializationStateBySessionID.get(dispatch.parentSessionID);
@@ -86679,4 +87740,4 @@ var _internals102 = {
86679
87740
  resolveGitExecutable
86680
87741
  };
86681
87742
 
86682
- export { resetActionCircuitExternally, getBlockingActionCircuit, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcExtractRecursiveRmTargets, dcEvaluateRecursiveDeleteTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, getSharedClassifierGuardrailBlock, classifyCommand, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, getAgentSession, parseLeanLaneIndex, computeLaneRuntimeProfile, MAX_TRACKED_STANDARD_WORKTREE_CALLS, awaitingMergeByCallID, standardWorktreeByCallID, standardWorktreeSerializationSessions, getStandardWorktreeDegradationReason, resetStandardWorktreeIsolationState, checkStandardWorktreeSerializationRelease, sanitizeWorktreeTaskId, preProvisionCollisionCheck, isLaneOwnedByCurrentSession, precreateStandardWorktreeSession, preserveBackgroundWorktreeOwnershipForCallId, preserveDirtyWorktreeForCallId, preserveDirtyWorktreeAtPath, cleanupStandardWorktreeForCallId, abortStandardWorktreeDispatch, finishStandardWorktreeDispatch, readLaneEnvFileFromDisk, _internals102 as _internals, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleApproveWriteCommand, handleArchiveCommand, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleCiSimulateCommand, handleClarifyCommand, createCuratorLLMDelegate, _internals25 as _internals1, normalizeRecommendationEntryIdToken, parseKnowledgeRecommendations, parseKnowledgeRecommendationsWithDiagnostics, parseStructuredCuratorBlocks, readCuratorSummary, writeCuratorSummary, appendCuratorRecommendation, mergeCuratorPhaseSummary, filterPhaseEvents, checkPhaseCompliance, runCuratorInit, runCuratorPhase, applyCuratorKnowledgeUpdates, isHiveEligible, countDistinctProjects, checkHivePromotions, _internals29 as _internals2, createHivePromoterHook, promoteToHive, promoteFromSwarm, safeRealpathSync, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, VERSION_PINNED_LEAF, discoverVersionPinnedCachePaths, readCachePackageVersion, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleGateAuditCommand, handleGateStatsCommand, handleHandoffCommand, handleBlueprintValidateCommand, handleBlueprintCurrentCommand, handleBlueprintHistoryCommand, handleBlueprintDiffCommand, handleBlueprintExportCommand, handleHarnessCandidateValidateCommand, handleHarnessCandidateShowCommand, handleHarnessCandidateDiffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryValueLogCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleRecoverCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleReviewCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals100 as _internals3, resolveCommand };
87743
+ export { resetActionCircuitExternally, getBlockingActionCircuit, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcExtractRecursiveRmTargets, dcEvaluateRecursiveDeleteTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, getSharedClassifierGuardrailBlock, classifyCommand, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, getAgentSession, parseLeanLaneIndex, computeLaneRuntimeProfile, MAX_TRACKED_STANDARD_WORKTREE_CALLS, awaitingMergeByCallID, standardWorktreeByCallID, standardWorktreeSerializationSessions, getStandardWorktreeDegradationReason, resetStandardWorktreeIsolationState, checkStandardWorktreeSerializationRelease, sanitizeWorktreeTaskId, preProvisionCollisionCheck, isLaneOwnedByCurrentSession, precreateStandardWorktreeSession, preserveBackgroundWorktreeOwnershipForCallId, preserveDirtyWorktreeForCallId, preserveDirtyWorktreeAtPath, cleanupStandardWorktreeForCallId, abortStandardWorktreeDispatch, finishStandardWorktreeDispatch, readLaneEnvFileFromDisk, _internals102 as _internals, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleApproveWriteCommand, handleArchiveCommand, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleCiSimulateCommand, handleClarifyCommand, createCuratorLLMDelegate, _internals26 as _internals1, normalizeRecommendationEntryIdToken, parseKnowledgeRecommendations, parseKnowledgeRecommendationsWithDiagnostics, parseStructuredCuratorBlocks, readCuratorSummary, writeCuratorSummary, appendCuratorRecommendation, mergeCuratorPhaseSummary, filterPhaseEvents, checkPhaseCompliance, runCuratorInit, runCuratorPhase, applyCuratorKnowledgeUpdates, isHiveEligible, countDistinctProjects, checkHivePromotions, _internals30 as _internals2, createHivePromoterHook, promoteToHive, promoteFromSwarm, safeRealpathSync, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, VERSION_PINNED_LEAF, discoverVersionPinnedCachePaths, readCachePackageVersion, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleGateAuditCommand, handleGateStatsCommand, handleHandoffCommand, handleBlueprintValidateCommand, handleBlueprintCurrentCommand, handleBlueprintHistoryCommand, handleBlueprintDiffCommand, handleBlueprintExportCommand, handleHarnessCandidateValidateCommand, handleHarnessCandidateShowCommand, handleHarnessCandidateDiffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryValueLogCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleRecoverCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleReviewCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals100 as _internals3, resolveCommand };