opencode-swarm 7.143.4 → 7.143.6

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 (53) hide show
  1. package/.opencode/skills/swarm-pr-review/SKILL.md +5 -5
  2. package/.opencode/skills/swarm-pr-review/references/lane-output-recoverability.md +129 -0
  3. package/dist/background/pending-delegations.d.ts +42 -1
  4. package/dist/background/pr-review-trigger-contract.d.ts +17 -0
  5. package/dist/cli/{config-doctor-az6nqawx.js → config-doctor-72zp0k4x.js} +2 -2
  6. package/dist/cli/{core-a6rzajem.js → core-aj0wmbg8.js} +1 -1
  7. package/dist/cli/{curator-tbw9przg.js → curator-2gt2835v.js} +18 -18
  8. package/dist/cli/{curator-llm-factory-j42j5rcr.js → curator-llm-factory-x1vjhrnc.js} +18 -18
  9. package/dist/cli/{evidence-summary-service-3f319cst.js → evidence-summary-service-yjr0662r.js} +6 -6
  10. package/dist/cli/{gate-evidence-k2yycngf.js → gate-evidence-r3c7eqpz.js} +2 -2
  11. package/dist/cli/{guardrail-explain-tsgsw91f.js → guardrail-explain-f3zysesy.js} +19 -19
  12. package/dist/cli/{guardrail-log-70cxb3va.js → guardrail-log-eat71fnh.js} +3 -3
  13. package/dist/cli/{hive-promoter-nksqxfs4.js → hive-promoter-fyb40am9.js} +18 -18
  14. package/dist/cli/{index-19wyta2k.js → index-02nm8qhk.js} +3 -3
  15. package/dist/cli/{index-8fq18k02.js → index-0adcjpyx.js} +3 -3
  16. package/dist/cli/{index-f39n8pbr.js → index-36vry26a.js} +1 -1
  17. package/dist/cli/{index-gz3z9d64.js → index-5d8ydxae.js} +399 -77
  18. package/dist/cli/{index-8aabbfhv.js → index-6vmazy9f.js} +8 -5
  19. package/dist/cli/{index-bt47jrhx.js → index-72zhsqgy.js} +2 -2
  20. package/dist/cli/{index-z4g05zbr.js → index-7bs015gm.js} +1 -1
  21. package/dist/cli/{index-dmtq7tvd.js → index-92bm9ys3.js} +1 -1
  22. package/dist/cli/{index-td2ga37v.js → index-bbv64s17.js} +1 -1
  23. package/dist/cli/{index-mewk624g.js → index-dtf2va28.js} +20 -20
  24. package/dist/cli/{index-jmgm1npc.js → index-fn0k0vsa.js} +1 -1
  25. package/dist/cli/{index-z0j133c4.js → index-gzxz0s50.js} +1 -1
  26. package/dist/cli/{index-8qmnqd6g.js → index-hjy4txgr.js} +1 -1
  27. package/dist/cli/{index-seedt8m3.js → index-kc2x117y.js} +3 -3
  28. package/dist/cli/{index-6htwcbxh.js → index-nd1j9wkw.js} +1 -1
  29. package/dist/cli/{index-9m5gz9ea.js → index-peqmw3wr.js} +2 -2
  30. package/dist/cli/{index-gbr0jbxy.js → index-s7nb33pc.js} +1 -1
  31. package/dist/cli/{index-f3xf9dv5.js → index-scj2asek.js} +5 -5
  32. package/dist/cli/{index-c9d5y70c.js → index-w1q9yy1e.js} +3 -3
  33. package/dist/cli/{index-ja15rdzd.js → index-whyrhjsk.js} +1 -1
  34. package/dist/cli/{index-5qqyvwqw.js → index-wjk00vwk.js} +4 -4
  35. package/dist/cli/{index-v9qmhrj9.js → index-z4cv77tq.js} +2 -2
  36. package/dist/cli/index.js +18 -18
  37. package/dist/cli/{knowledge-escalator-8akk4n18.js → knowledge-escalator-ejpyrby0.js} +6 -6
  38. package/dist/cli/{knowledge-events-51qk8fq2.js → knowledge-events-yw2kydyy.js} +4 -4
  39. package/dist/cli/{knowledge-store-7rsezhav.js → knowledge-store-j6gkk62e.js} +1 -1
  40. package/dist/cli/{knowledge-validator-nq75s9et.js → knowledge-validator-xervpe5k.js} +2 -2
  41. package/dist/cli/{pending-delegations-b3pt3w5w.js → pending-delegations-19wg9j08.js} +5 -1
  42. package/dist/cli/{scan-cursor-em4vrcw6.js → scan-cursor-x7a99wmq.js} +2 -2
  43. package/dist/cli/{schema-1wmfgtm9.js → schema-z141arx9.js} +1 -1
  44. package/dist/cli/{scope-persistence-8ehnjgsg.js → scope-persistence-js90c1f4.js} +4 -4
  45. package/dist/cli/{skill-generator-3jstr1sx.js → skill-generator-t202jza0.js} +7 -7
  46. package/dist/cli/{worktree-collision-ownership-bfz3drxm.js → worktree-collision-ownership-42bb3gcb.js} +1 -1
  47. package/dist/cli/{worktree-isolation-cc3x13ng.js → worktree-isolation-fbfvxw9a.js} +18 -18
  48. package/dist/hooks/pr-workflow-gate.d.ts +135 -1
  49. package/dist/index.js +20 -18
  50. package/dist/tools/complete-pr-workflow.d.ts +3 -1
  51. package/dist/tools/pr-workflow-status.d.ts +2 -2
  52. package/dist/tools/write-pr-review-trigger-eval.d.ts +2 -1
  53. package/package.json +1 -1
@@ -1,13 +1,13 @@
1
1
  // @bun
2
2
  import {
3
3
  stableCanonicalStringify
4
- } from "./index-6htwcbxh.js";
4
+ } from "./index-nd1j9wkw.js";
5
5
  import {
6
6
  detectStraySwarmDirs,
7
7
  readDoctorArtifact,
8
8
  removeStraySwarmDir,
9
9
  runConfigDoctor
10
- } from "./index-ja15rdzd.js";
10
+ } from "./index-whyrhjsk.js";
11
11
  import {
12
12
  MAX_TRANSIENT_RETRIES,
13
13
  archiveEvidence,
@@ -54,7 +54,7 @@ import {
54
54
  updateTaskCheckpointReceipt,
55
55
  updateTaskStatus,
56
56
  validateProjectRoot
57
- } from "./index-c9d5y70c.js";
57
+ } from "./index-w1q9yy1e.js";
58
58
  import {
59
59
  loadDatabaseCtor
60
60
  } from "./index-134d35c1.js";
@@ -106,7 +106,7 @@ import {
106
106
  alreadyCuratedThisGeneration,
107
107
  claimNextScanBatch,
108
108
  resolveCohortId
109
- } from "./index-dmtq7tvd.js";
109
+ } from "./index-92bm9ys3.js";
110
110
  import {
111
111
  CURATOR_INIT_PROMPT,
112
112
  CURATOR_PHASE_PROMPT,
@@ -141,7 +141,7 @@ import {
141
141
  startupOrphanRecovery,
142
142
  withTaskEvidenceTransaction,
143
143
  writeWorkflowWalFile
144
- } from "./index-td2ga37v.js";
144
+ } from "./index-bbv64s17.js";
145
145
  import {
146
146
  changedFilesSinceSnapshot,
147
147
  parsePorcelainV2Snapshot,
@@ -188,16 +188,16 @@ import {
188
188
  retireSkill,
189
189
  selectCandidateEntries,
190
190
  syncBundledProjectSkillsIfMissingAsync
191
- } from "./index-19wyta2k.js";
191
+ } from "./index-02nm8qhk.js";
192
192
  import {
193
193
  readRecentEscalations
194
- } from "./index-f3xf9dv5.js";
194
+ } from "./index-scj2asek.js";
195
195
  import {
196
196
  MAX_PENDING_SCOPE_BINDINGS,
197
197
  clearAllScopes,
198
198
  clearScopeBindingFromDisk,
199
199
  clearScopeBindings
200
- } from "./index-v9qmhrj9.js";
200
+ } from "./index-z4cv77tq.js";
201
201
  import {
202
202
  appendLedgerEvent,
203
203
  computePlanHash,
@@ -210,7 +210,7 @@ import {
210
210
  readPlanEpochIdentity,
211
211
  replayFromLedgerWithStatus,
212
212
  takeSnapshotEvent
213
- } from "./index-8qmnqd6g.js";
213
+ } from "./index-hjy4txgr.js";
214
214
  import {
215
215
  isPathWithinDeclaredScope
216
216
  } from "./index-556ja8an.js";
@@ -232,13 +232,15 @@ import {
232
232
  removeWorktreeProvisioningOwner
233
233
  } from "./index-k3cxyk66.js";
234
234
  import {
235
+ DEFAULT_STALE_DELEGATION_TIMEOUT_MS,
235
236
  findByBatchId,
236
- readDelegations
237
- } from "./index-8aabbfhv.js";
237
+ readDelegations,
238
+ sweepStaleDelegations
239
+ } from "./index-6vmazy9f.js";
238
240
  import {
239
241
  provisionWorktree,
240
242
  removeWorktree
241
- } from "./index-gbr0jbxy.js";
243
+ } from "./index-s7nb33pc.js";
242
244
  import {
243
245
  SandboxCapabilityProbe,
244
246
  init_capability_probe
@@ -262,10 +264,10 @@ import {
262
264
  recordKnowledgeEvent,
263
265
  recordPhaseCloseIntent,
264
266
  resolveKnowledgeEventsPath
265
- } from "./index-8fq18k02.js";
267
+ } from "./index-0adcjpyx.js";
266
268
  import {
267
269
  resolveWorktreeIsolationConfig
268
- } from "./index-9m5gz9ea.js";
270
+ } from "./index-peqmw3wr.js";
269
271
  import {
270
272
  RetrospectiveEvidenceSchema
271
273
  } from "./index-gprxjmm7.js";
@@ -275,7 +277,7 @@ import {
275
277
  init_loader,
276
278
  loadPluginConfig,
277
279
  loadPluginConfigWithMeta
278
- } from "./index-f39n8pbr.js";
280
+ } from "./index-36vry26a.js";
279
281
  import {
280
282
  DEFAULT_SKILL_OPT_CONFIG,
281
283
  FALLBACK_MODELS_MAX,
@@ -289,7 +291,7 @@ import {
289
291
  package_default,
290
292
  resolveAutoReviewConfig,
291
293
  stripKnownSwarmPrefix
292
- } from "./index-z4g05zbr.js";
294
+ } from "./index-7bs015gm.js";
293
295
  import {
294
296
  readSwarmFileAsync,
295
297
  safeHook,
@@ -324,7 +326,7 @@ import {
324
326
  validateActionableFields,
325
327
  validateLesson,
326
328
  validateSkillPath
327
- } from "./index-z0j133c4.js";
329
+ } from "./index-gzxz0s50.js";
328
330
  import {
329
331
  authorizeCuration,
330
332
  buildConfigFingerprintInput
@@ -361,7 +363,7 @@ import {
361
363
  transactFile,
362
364
  transactKnowledge,
363
365
  wordBigrams
364
- } from "./index-5qqyvwqw.js";
366
+ } from "./index-wjk00vwk.js";
365
367
  import {
366
368
  resolveHiveDataDir,
367
369
  resolveHiveEventsPath,
@@ -4153,7 +4155,7 @@ async function cleanupRecoveredWorktree(directory, descriptor) {
4153
4155
  awaitingMergeByCallID,
4154
4156
  cleanupStandardWorktreeForCallId,
4155
4157
  standardWorktreeByCallID
4156
- } = await import("./worktree-isolation-cc3x13ng.js");
4158
+ } = await import("./worktree-isolation-fbfvxw9a.js");
4157
4159
  standardWorktreeByCallID.delete(descriptor.callID);
4158
4160
  if (hasResidue)
4159
4161
  awaitingMergeByCallID.set(descriptor.callID, {
@@ -4232,7 +4234,7 @@ async function recoverCoderSettlement(directory, taskId) {
4232
4234
  awaitingMergeByCallID,
4233
4235
  finishStandardWorktreeDispatch,
4234
4236
  standardWorktreeByCallID
4235
- } = await import("./worktree-isolation-cc3x13ng.js");
4237
+ } = await import("./worktree-isolation-fbfvxw9a.js");
4236
4238
  const descriptor = wal.worktree;
4237
4239
  const reconstructedDispatch = {
4238
4240
  callID: descriptor.callID,
@@ -6261,7 +6263,8 @@ var V2ReceiptSchema = ReceiptEnvelopeSchema.extend({
6261
6263
  not_triggered_count: exports_external.number().int().min(0),
6262
6264
  no_match_count: exports_external.number().int().min(0),
6263
6265
  rows: exports_external.array(V2RowSchema),
6264
- coverage_degradations: exports_external.array(TriggerCoverageDegradationSchema).default([])
6266
+ coverage_degradations: exports_external.array(TriggerCoverageDegradationSchema).default([]),
6267
+ base_verification: exports_external.enum(["live", "bound_fallback"]).optional()
6265
6268
  }).strict();
6266
6269
  function assertCanonicalDefinitionFields(rows) {
6267
6270
  const definitions = new Map(PR_REVIEW_TRIGGER_DEFINITIONS.map((definition) => [
@@ -6303,13 +6306,14 @@ var V1ReceiptSchema = ReceiptEnvelopeSchema.extend({
6303
6306
  rows: exports_external.array(LegacyRowSchema)
6304
6307
  }).strict();
6305
6308
  var UnversionedRowOnlyReceiptSchema = exports_external.object({ rows: exports_external.array(exports_external.unknown()) }).strict();
6306
- function parsedReceipt(schemaVersion, rows, coverageDegradations = []) {
6309
+ function parsedReceipt(schemaVersion, rows, coverageDegradations = [], baseVerification) {
6307
6310
  return {
6308
6311
  schemaVersion,
6309
6312
  rows,
6310
6313
  matchedRows: rows.filter((row) => row.result === "MATCHED"),
6311
6314
  notTriggeredRows: rows.filter((row) => row.result === "NOT_TRIGGERED"),
6312
- coverageDegradations
6315
+ coverageDegradations,
6316
+ ...baseVerification ? { baseVerification } : {}
6313
6317
  };
6314
6318
  }
6315
6319
  function parsePrReviewTriggerReceipt(input) {
@@ -6342,7 +6346,7 @@ function parsePrReviewTriggerReceipt(input) {
6342
6346
  throw new Error(`PR_REVIEW trigger receipt ${field} is inconsistent: expected ${expected}`);
6343
6347
  }
6344
6348
  }
6345
- return parsedReceipt(2, validated2.rows, receipt.coverage_degradations);
6349
+ return parsedReceipt(2, validated2.rows, receipt.coverage_degradations, receipt.base_verification);
6346
6350
  }
6347
6351
  if (schemaVersion !== undefined && schemaVersion !== 1) {
6348
6352
  throw new Error(`Unsupported PR_REVIEW trigger schema_version: ${schemaVersion}`);
@@ -6594,6 +6598,7 @@ var MAX_WORKFLOW_BATCHES = 128;
6594
6598
  var MAX_RETIRED_REVIEWER_SESSION_IDS = 1024;
6595
6599
  var MAX_RETIRED_CONSOLIDATED_LANES = 64;
6596
6600
  var MAX_RETIRED_FEEDBACK_ITEM_OWNERS = 4096;
6601
+ var MAX_PR_FEEDBACK_INVENTORY_AMENDMENTS = 128;
6597
6602
  var WINDOWS_RENAME_MAX_RETRIES = 3;
6598
6603
  var RENAME_RETRY_DELAY_MS = 10;
6599
6604
  var STATE_MUTATION_LOCK_MAX_ATTEMPTS = 50;
@@ -6700,6 +6705,11 @@ var PrFeedbackReadyToPublishRecordSchema = exports_external.object({
6700
6705
  remoteRef: exports_external.string().startsWith("refs/remotes/"),
6701
6706
  validatedAt: exports_external.string().min(1)
6702
6707
  }).strict();
6708
+ var PrFeedbackInventoryAmendmentRecordSchema = exports_external.object({
6709
+ entry: exports_external.string().min(1),
6710
+ amendedAt: exports_external.string().min(1),
6711
+ batch: exports_external.number().int().positive()
6712
+ }).strict();
6703
6713
  var PrReviewValidationBatchRecordSchema = exports_external.object({
6704
6714
  batchId: exports_external.string().min(1),
6705
6715
  phase: exports_external.enum(["council", "reviewer", "critic"]),
@@ -6789,6 +6799,7 @@ var PrWorkflowGateStateSchema = exports_external.object({
6789
6799
  prFeedbackTargetUrl: exports_external.string().url().max(2000).optional(),
6790
6800
  prFeedbackReviewHandoff: PrFeedbackReviewHandoffRecordSchema.optional(),
6791
6801
  prFeedbackInventory: exports_external.array(exports_external.string().min(1)).min(1).optional(),
6802
+ prFeedbackInventoryAmendments: exports_external.array(PrFeedbackInventoryAmendmentRecordSchema).max(MAX_PR_FEEDBACK_INVENTORY_AMENDMENTS).optional(),
6792
6803
  prFeedbackVerifications: exports_external.array(PrFeedbackVerificationRecordSchema).max(MAX_WORKFLOW_BATCHES).optional(),
6793
6804
  prFeedbackRetiredItemOwnership: exports_external.record(exports_external.string().min(1), exports_external.string().min(1)).refine((entries) => Object.keys(entries).length <= MAX_RETIRED_FEEDBACK_ITEM_OWNERS, `prFeedbackRetiredItemOwnership may not exceed ${MAX_RETIRED_FEEDBACK_ITEM_OWNERS} entries`).optional(),
6794
6805
  prFeedbackVerification: PrFeedbackVerificationRecordSchema.optional(),
@@ -6880,11 +6891,11 @@ async function readPrWorkflowGateState(directory, sessionID) {
6880
6891
  }
6881
6892
  return state;
6882
6893
  }
6883
- async function clearPrWorkflowGateState(directory, sessionID, expectedRevision) {
6894
+ async function clearPrWorkflowGateState(directory, sessionID, expectedRevision, options = {}) {
6884
6895
  const normalizedSessionID = normalizeSessionID(sessionID);
6885
6896
  await withSessionStateMutation(directory, normalizedSessionID, async () => {
6886
6897
  if (expectedRevision !== undefined) {
6887
- const current = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
6898
+ const current = options.allowSalvagedRead ? (await readPrWorkflowGateStateForRecovery(directory, normalizedSessionID))?.state ?? null : await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
6888
6899
  if (!current || current.revision !== expectedRevision) {
6889
6900
  throw new Error("BLOCKED: PR workflow gate state changed during terminal completion; revalidate the current session state before retrying");
6890
6901
  }
@@ -6901,18 +6912,71 @@ async function clearPrWorkflowGateState(directory, sessionID, expectedRevision)
6901
6912
  trackedStatesByProjectSession.delete(stateCacheKey(directory, normalizedSessionID));
6902
6913
  });
6903
6914
  }
6915
+ var PR_WORKFLOW_STALE_LANE_TIMEOUT_MS = DEFAULT_STALE_DELEGATION_TIMEOUT_MS;
6916
+ var MAX_DISCLOSED_LANE_IDS = 10;
6917
+ var PR_WORKFLOW_SWEEPABLE_LANE_STATUSES = new Set(["pending", "running"]);
6918
+ var CAS_ESCAPE_DISCLOSURE = "state revision unsalvageable; cleared without compare-and-swap";
6919
+ function prWorkflowLaneLabel(record) {
6920
+ return record.laneId ?? record.subagentSessionId ?? "unknown";
6921
+ }
6922
+ function isOpenPrWorkflowLane(record, sessionID) {
6923
+ return record.parentSessionId === sessionID && record.mode?.startsWith("swarm-pr-") === true && (record.status === "pending" || record.status === "running");
6924
+ }
6925
+ async function settlePresumedStalePrWorkflowLanes(directory, sessionID) {
6926
+ const now = Date.now();
6927
+ const open2 = [];
6928
+ const presumedStale = [];
6929
+ for (const record of readDelegations(directory)) {
6930
+ if (!isOpenPrWorkflowLane(record, sessionID))
6931
+ continue;
6932
+ if (now - record.updatedAt > PR_WORKFLOW_STALE_LANE_TIMEOUT_MS) {
6933
+ presumedStale.push(record);
6934
+ } else {
6935
+ open2.push(record);
6936
+ }
6937
+ }
6938
+ const presumedStaleLaneIds = presumedStale.map(prWorkflowLaneLabel);
6939
+ const openLaneIds = open2.map(prWorkflowLaneLabel);
6940
+ if (presumedStale.length === 0) {
6941
+ return { openLaneIds, openLanes: open2.length, presumedStaleLaneIds };
6942
+ }
6943
+ const disclosure = `${presumedStaleLaneIds.length} lane(s) stale >` + `${Math.round(PR_WORKFLOW_STALE_LANE_TIMEOUT_MS / 60000)}min, ` + `treated as settled: ${presumedStaleLaneIds.slice(0, MAX_DISCLOSED_LANE_IDS).join(", ")}`;
6944
+ await sweepStaleDelegations(directory, PR_WORKFLOW_STALE_LANE_TIMEOUT_MS, {
6945
+ statuses: PR_WORKFLOW_SWEEPABLE_LANE_STATUSES
6946
+ });
6947
+ try {
6948
+ await fsp2.appendFile(validateSwarmPath(directory, "events.jsonl"), `${JSON.stringify({
6949
+ type: "pr_workflow_lanes_presumed_stale",
6950
+ timestamp: isoNow(),
6951
+ sessionID,
6952
+ presumedStaleLanes: presumedStaleLaneIds.slice(0, MAX_DISCLOSED_LANE_IDS),
6953
+ staleTimeoutMs: PR_WORKFLOW_STALE_LANE_TIMEOUT_MS,
6954
+ disclosure
6955
+ })}
6956
+ `, "utf-8");
6957
+ } catch {}
6958
+ return {
6959
+ openLaneIds,
6960
+ openLanes: open2.length,
6961
+ presumedStaleLaneIds,
6962
+ disclosure
6963
+ };
6964
+ }
6904
6965
  async function abortPrWorkflow(directory, sessionID, options = { kind: "recovery", reason: "" }) {
6905
- const state = await requireAnyActiveState(directory, sessionID);
6966
+ const recovery = await readPrWorkflowGateStateForRecovery(directory, sessionID);
6967
+ if (!recovery)
6968
+ throw noActiveGateError(sessionID);
6969
+ const state = recovery.state;
6906
6970
  if (options.expectedMode && state.mode !== options.expectedMode) {
6907
6971
  throw wrongModeError(state, options.expectedMode);
6908
6972
  }
6909
- if (state.prFeedbackReadyToPublish) {
6910
- 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.`);
6973
+ if (state.prFeedbackReadyToPublish || recovery.armedShapeUnreadable) {
6974
+ 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)." : ""));
6911
6975
  }
6912
- const openLanes = readDelegations(directory).filter((record) => record.parentSessionId === state.sessionID && record.mode?.startsWith("swarm-pr-") && (record.status === "pending" || record.status === "running"));
6913
- if (openLanes.length > 0) {
6914
- const laneIds = openLanes.map((record) => record.laneId ?? record.subagentSessionId ?? "unknown").filter(Boolean).slice(0, 10).join(", ");
6915
- throw new Error(`BLOCKED: ${state.mode} abort refused while ${openLanes.length} PR workflow lane(s) are still in flight (lane ids: ${laneIds}). Collect their results or let them settle before aborting.`);
6976
+ const laneSettlement = await settlePresumedStalePrWorkflowLanes(directory, state.sessionID);
6977
+ if (laneSettlement.openLanes > 0) {
6978
+ const laneIds = laneSettlement.openLaneIds.filter(Boolean).slice(0, MAX_DISCLOSED_LANE_IDS).join(", ");
6979
+ throw new Error(`BLOCKED: ${state.mode} abort refused while ${laneSettlement.openLanes} PR workflow lane(s) are still in flight (lane ids: ${laneIds}). Collect their results or let them settle before aborting.`);
6916
6980
  }
6917
6981
  const sanitizedReason = typeof options.reason === "string" && options.reason.trim().length > 0 ? options.reason.trim().slice(0, 500) : undefined;
6918
6982
  if (sanitizedReason === undefined) {
@@ -6926,7 +6990,16 @@ async function abortPrWorkflow(directory, sessionID, options = { kind: "recovery
6926
6990
  kind: options.kind,
6927
6991
  ...state.prHeadSha ? { prHeadSha: state.prHeadSha } : {},
6928
6992
  ...state.checkoutRecovery ? { hadTerminalRecovery: true } : {},
6929
- openLanes: openLanes.length,
6993
+ openLanes: laneSettlement.openLanes,
6994
+ ...laneSettlement.presumedStaleLaneIds.length > 0 ? {
6995
+ presumedStaleLanes: laneSettlement.presumedStaleLaneIds.slice(0, MAX_DISCLOSED_LANE_IDS),
6996
+ presumedStaleDisclosure: laneSettlement.disclosure
6997
+ } : {},
6998
+ ...recovery.salvaged ? {
6999
+ stateSalvaged: true,
7000
+ stateSalvageDisclosure: recovery.disclosure,
7001
+ ...recovery.revisionSalvageable ? {} : { casEscapeDisclosure: CAS_ESCAPE_DISCLOSURE }
7002
+ } : {},
6930
7003
  reason: sanitizedReason
6931
7004
  };
6932
7005
  try {
@@ -6934,11 +7007,39 @@ async function abortPrWorkflow(directory, sessionID, options = { kind: "recovery
6934
7007
  await fsp2.appendFile(eventsPath, `${JSON.stringify(abortEvent)}
6935
7008
  `, "utf-8");
6936
7009
  } catch {}
6937
- await clearPrWorkflowGateState(directory, sessionID, state.revision);
7010
+ const casEscape = recovery.salvaged && !recovery.revisionSalvageable;
7011
+ await _test_exports.beforeAbortClear?.();
7012
+ try {
7013
+ await clearPrWorkflowGateState(directory, sessionID, casEscape ? undefined : state.revision, { allowSalvagedRead: recovery.salvaged });
7014
+ } catch (error2) {
7015
+ try {
7016
+ await fsp2.appendFile(validateSwarmPath(directory, "events.jsonl"), `${JSON.stringify({
7017
+ type: "pr_workflow_abort_not_completed",
7018
+ timestamp: isoNow(),
7019
+ sessionID: state.sessionID,
7020
+ mode: state.mode,
7021
+ ...state.prHeadSha ? { prHeadSha: state.prHeadSha } : {},
7022
+ reason: sanitizedReason,
7023
+ failure: (error2 instanceof Error ? error2.message : String(error2)).slice(0, MAX_BASE_COVERAGE_DIAGNOSTIC_CHARS),
7024
+ disclosure: "RETRACTION: the pr_workflow_aborted record for this session did NOT complete \u2014 " + "the clear failed and the gate state may still be active. Revalidate the current " + "session state before retrying the abort."
7025
+ })}
7026
+ `, "utf-8");
7027
+ } catch {}
7028
+ throw error2;
7029
+ }
6938
7030
  return {
6939
7031
  mode: state.mode,
6940
7032
  ...state.prHeadSha ? { prHeadSha: state.prHeadSha } : {},
6941
- openLanes: openLanes.length
7033
+ openLanes: laneSettlement.openLanes,
7034
+ ...laneSettlement.presumedStaleLaneIds.length > 0 ? {
7035
+ presumedStaleLanes: laneSettlement.presumedStaleLaneIds,
7036
+ presumedStaleDisclosure: laneSettlement.disclosure
7037
+ } : {},
7038
+ ...recovery.salvaged ? {
7039
+ stateSalvaged: true,
7040
+ stateSalvageDisclosure: recovery.disclosure
7041
+ } : {},
7042
+ ...casEscape ? { casEscapeDisclosure: CAS_ESCAPE_DISCLOSURE } : {}
6942
7043
  };
6943
7044
  }
6944
7045
  async function bindPrWorkflowHeadWhileLocked(directory, normalizedSessionID, prHeadSha) {
@@ -7343,9 +7444,9 @@ function assertSamePrFeedbackHandoff(state, relativePath, read, requestedPrUrl)
7343
7444
  async function assertPrReviewTerminalReady(directory, sessionID) {
7344
7445
  const state = await requireBoundState(directory, sessionID, "PR_REVIEW");
7345
7446
  await assertPrReviewCleanCheckout(directory, "PR_REVIEW");
7346
- const open2 = readDelegations(directory).filter((record) => record.parentSessionId === state.sessionID && record.mode?.startsWith("swarm-pr-") && (record.status === "pending" || record.status === "running"));
7347
- if (open2.length > 0) {
7348
- throw new Error(`BLOCKED: PR_REVIEW transition has ${open2.length} unsettled PR workflow lane(s)`);
7447
+ const laneSettlement = await settlePresumedStalePrWorkflowLanes(directory, state.sessionID);
7448
+ if (laneSettlement.openLanes > 0) {
7449
+ throw new Error(`BLOCKED: PR_REVIEW transition has ${laneSettlement.openLanes} unsettled PR workflow lane(s)`);
7349
7450
  }
7350
7451
  const ctx = await createPrReviewGateContext(directory, state);
7351
7452
  await assertPrReviewBaseCoverageSettled(directory, sessionID, ctx);
@@ -7490,6 +7591,7 @@ var _test_exports = {
7490
7591
  pendingCheckoutMutationsByProject.clear();
7491
7592
  completedCheckoutLockOwners.clear();
7492
7593
  _test_exports.beforeTerminalClear = undefined;
7594
+ _test_exports.beforeAbortClear = undefined;
7493
7595
  _test_exports.beforePrFeedbackTransitionLock = undefined;
7494
7596
  _test_exports.beforePrFeedbackTrackingSwitch = undefined;
7495
7597
  _test_exports.afterPrFeedbackTrackingSwitch = undefined;
@@ -7506,6 +7608,7 @@ var _test_exports = {
7506
7608
  _test_exports.classifyPrWorkflowGitStateAsync = classifyPrWorkflowGitState;
7507
7609
  },
7508
7610
  beforeTerminalClear: undefined,
7611
+ beforeAbortClear: undefined,
7509
7612
  beforePrFeedbackTransitionLock: undefined,
7510
7613
  beforePrFeedbackTrackingSwitch: undefined,
7511
7614
  afterPrFeedbackTrackingSwitch: undefined,
@@ -7565,11 +7668,13 @@ var _test_exports = {
7565
7668
  rename: fsp2.rename,
7566
7669
  nowMs: () => Date.now()
7567
7670
  };
7671
+ function noActiveGateError(sessionID) {
7672
+ return new Error(`BLOCKED: no active PR workflow gate for session "${normalizeSessionID(sessionID)}". ` + `The gate is activated by running \`/swarm pr-review <pr-ref>\` (PR_REVIEW) or \`/swarm pr-feedback <pr-ref>\` (PR_FEEDBACK), ` + `or by the first dispatch_lanes_async call with mode "swarm-pr-review:*" / "swarm-pr-feedback:*".`);
7673
+ }
7568
7674
  async function requireAnyActiveState(directory, sessionID) {
7569
7675
  const state = await readPrWorkflowGateState(directory, sessionID);
7570
- if (!state) {
7571
- throw new Error(`BLOCKED: no active PR workflow gate for session "${normalizeSessionID(sessionID)}". ` + `The gate is activated by running \`/swarm pr-review <pr-ref>\` (PR_REVIEW) or \`/swarm pr-feedback <pr-ref>\` (PR_FEEDBACK), ` + `or by the first dispatch_lanes_async call with mode "swarm-pr-review:*" / "swarm-pr-feedback:*".`);
7572
- }
7676
+ if (!state)
7677
+ throw noActiveGateError(sessionID);
7573
7678
  return state;
7574
7679
  }
7575
7680
  async function requireBoundState(directory, sessionID, expectedMode) {
@@ -9263,6 +9368,76 @@ async function readPrWorkflowGateStateFileFromDisk(filePath, stateLabel) {
9263
9368
  }
9264
9369
  return parsed.data;
9265
9370
  }
9371
+ var MAX_SALVAGED_SCHEMA_ERRORS = 10;
9372
+ var MAX_SALVAGED_SCHEMA_ERROR_CHARS = 240;
9373
+ function boundSalvagedSchemaError(message) {
9374
+ return message.length <= MAX_SALVAGED_SCHEMA_ERROR_CHARS ? message : `${message.slice(0, MAX_SALVAGED_SCHEMA_ERROR_CHARS - 1)}\u2026`;
9375
+ }
9376
+ async function readPrWorkflowGateStateForRecovery(directory, sessionID) {
9377
+ const normalizedSessionID = normalizeSessionID(sessionID);
9378
+ const filePath = workflowGateStatePath(directory, normalizedSessionID);
9379
+ let raw;
9380
+ try {
9381
+ raw = await fsp2.readFile(filePath, "utf-8");
9382
+ } catch (error2) {
9383
+ if (error2.code === "ENOENT")
9384
+ return null;
9385
+ throw error2;
9386
+ }
9387
+ let parsedJson;
9388
+ try {
9389
+ parsedJson = JSON.parse(raw);
9390
+ } catch {
9391
+ throw new Error(`BLOCKED: PR workflow gate state for session "${normalizedSessionID}" is not valid JSON`);
9392
+ }
9393
+ const parsed = PrWorkflowGateStateSchema.safeParse(parsedJson);
9394
+ if (parsed.success) {
9395
+ return {
9396
+ state: parsed.data,
9397
+ salvaged: false,
9398
+ schemaErrors: [],
9399
+ revisionSalvageable: true,
9400
+ armedShapeUnreadable: false
9401
+ };
9402
+ }
9403
+ const invalidError = new Error(`BLOCKED: PR workflow gate state for session "${normalizedSessionID}" is invalid`);
9404
+ if (typeof parsedJson !== "object" || parsedJson === null || Array.isArray(parsedJson)) {
9405
+ throw invalidError;
9406
+ }
9407
+ const rawRecord = parsedJson;
9408
+ const salvagedSessionID = exports_external.string().min(1).safeParse(rawRecord.sessionID);
9409
+ const salvagedMode = exports_external.enum(["PR_REVIEW", "PR_FEEDBACK"]).safeParse(rawRecord.mode);
9410
+ if (!salvagedSessionID.success || !salvagedMode.success)
9411
+ throw invalidError;
9412
+ const salvagedRevision = exports_external.number().int().nonnegative().safeParse(rawRecord.revision);
9413
+ const salvagedHead = exports_external.string().min(1).safeParse(rawRecord.prHeadSha);
9414
+ const salvagedActivatedAt = exports_external.string().min(1).safeParse(rawRecord.activatedAt);
9415
+ const salvagedUpdatedAt = exports_external.string().min(1).safeParse(rawRecord.updatedAt);
9416
+ const armedKeyPresent = rawRecord.prFeedbackReadyToPublish !== undefined;
9417
+ const salvagedArmed = PrFeedbackReadyToPublishRecordSchema.safeParse(rawRecord.prFeedbackReadyToPublish);
9418
+ const salvagedCheckoutRecovery = PrWorkflowCheckoutRecoveryRecordSchema.safeParse(rawRecord.checkoutRecovery);
9419
+ const armedShapeUnreadable = armedKeyPresent && !salvagedArmed.success;
9420
+ const schemaErrors = parsed.error.issues.slice(0, MAX_SALVAGED_SCHEMA_ERRORS).map((issue) => boundSalvagedSchemaError(`${issue.path.join(".") || "(root)"}: ${issue.message}`));
9421
+ 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)." : "");
9422
+ return {
9423
+ state: {
9424
+ schemaVersion: GATE_SCHEMA_VERSION,
9425
+ revision: salvagedRevision.success ? salvagedRevision.data : 0,
9426
+ sessionID: salvagedSessionID.data,
9427
+ mode: salvagedMode.data,
9428
+ activatedAt: salvagedActivatedAt.success ? salvagedActivatedAt.data : isoNow(),
9429
+ updatedAt: salvagedUpdatedAt.success ? salvagedUpdatedAt.data : isoNow(),
9430
+ ...salvagedHead.success ? { prHeadSha: salvagedHead.data } : {},
9431
+ ...salvagedArmed.success ? { prFeedbackReadyToPublish: salvagedArmed.data } : {},
9432
+ ...salvagedCheckoutRecovery.success ? { checkoutRecovery: salvagedCheckoutRecovery.data } : {}
9433
+ },
9434
+ salvaged: true,
9435
+ schemaErrors,
9436
+ disclosure,
9437
+ revisionSalvageable: salvagedRevision.success,
9438
+ armedShapeUnreadable
9439
+ };
9440
+ }
9266
9441
  function rememberState(directory, state) {
9267
9442
  const cacheKey = stateCacheKey(directory, state.sessionID);
9268
9443
  trackedStatesByProjectSession.delete(cacheKey);
@@ -14931,7 +15106,7 @@ function planMerges(active, threshold, maxComparisons, maxMerges) {
14931
15106
  };
14932
15107
  }
14933
15108
  async function sweepActiveNearDuplicates(directory, options = {}) {
14934
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-seedt8m3.js");
15109
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-kc2x117y.js");
14935
15110
  const { config } = loadPluginConfigWithMeta2(directory);
14936
15111
  const sweepConfig = config.learning?.dedup_sweep;
14937
15112
  if (sweepConfig?.enabled === false)
@@ -16015,7 +16190,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
16015
16190
  }
16016
16191
  if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
16017
16192
  try {
16018
- const skillModule = await import("./skill-generator-3jstr1sx.js");
16193
+ const skillModule = await import("./skill-generator-t202jza0.js");
16019
16194
  for (const cand of skillCandidates) {
16020
16195
  if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
16021
16196
  continue;
@@ -16475,7 +16650,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
16475
16650
  } catch {}
16476
16651
  }
16477
16652
  if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
16478
- const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-8akk4n18.js");
16653
+ const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-ejpyrby0.js");
16479
16654
  for (const { id } of contradictedEntries) {
16480
16655
  try {
16481
16656
  await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
@@ -17294,7 +17469,7 @@ async function runCuratorPostMortem(directory, options = {}) {
17294
17469
  warnings.push("Failed to collect knowledge summary.");
17295
17470
  }
17296
17471
  try {
17297
- const { getScanStatus } = await import("./scan-cursor-em4vrcw6.js");
17472
+ const { getScanStatus } = await import("./scan-cursor-x7a99wmq.js");
17298
17473
  const scanStatus = await getScanStatus(directory);
17299
17474
  if (scanStatus.remaining_estimate > 0) {
17300
17475
  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.`);
@@ -17466,9 +17641,9 @@ var _internals23 = {
17466
17641
  verifyPostMortemKnowledgeActions,
17467
17642
  repairPostMortemActions,
17468
17643
  loadDefaultKnowledgeConfig: async (directory) => {
17469
- const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-1wmfgtm9.js");
17644
+ const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-z141arx9.js");
17470
17645
  try {
17471
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-seedt8m3.js");
17646
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-kc2x117y.js");
17472
17647
  const loaded = loadPluginConfigWithMeta2(directory);
17473
17648
  return KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
17474
17649
  } catch {
@@ -17476,11 +17651,11 @@ var _internals23 = {
17476
17651
  }
17477
17652
  },
17478
17653
  applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig, generation) => {
17479
- const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-tbw9przg.js");
17654
+ const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-2gt2835v.js");
17480
17655
  return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig, generation);
17481
17656
  },
17482
17657
  checkHivePromotions: async (entries, knowledgeConfig, directory) => {
17483
- const { checkHivePromotions } = await import("./hive-promoter-nksqxfs4.js");
17658
+ const { checkHivePromotions } = await import("./hive-promoter-fyb40am9.js");
17484
17659
  return checkHivePromotions(entries, knowledgeConfig, directory);
17485
17660
  },
17486
17661
  applyProposalTriage: async (directory, triage) => {
@@ -17489,7 +17664,7 @@ var _internals23 = {
17489
17664
  activateProposal,
17490
17665
  listSkills: listSkills2,
17491
17666
  sanitizeSlug
17492
- } = await import("./skill-generator-3jstr1sx.js");
17667
+ } = await import("./skill-generator-t202jza0.js");
17493
17668
  const result = {
17494
17669
  approved: [],
17495
17670
  rejected: [],
@@ -18825,9 +19000,9 @@ function hashContent(content) {
18825
19000
  return createHash7("sha1").update(content).digest("hex");
18826
19001
  }
18827
19002
  async function loadConfigForPolicyCurator(directory) {
18828
- const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-1wmfgtm9.js");
19003
+ const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-z141arx9.js");
18829
19004
  try {
18830
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-seedt8m3.js");
19005
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-kc2x117y.js");
18831
19006
  const { config: loadedConfig } = loadPluginConfigWithMeta2(directory);
18832
19007
  return KnowledgeConfigSchema2.parse(loadedConfig.knowledge ?? {});
18833
19008
  } catch {
@@ -27669,7 +27844,7 @@ async function runFinalizeStage(ctx) {
27669
27844
  }
27670
27845
  }
27671
27846
  try {
27672
- const { CuratorConfigSchema: CCS } = await import("./schema-1wmfgtm9.js");
27847
+ const { CuratorConfigSchema: CCS } = await import("./schema-z141arx9.js");
27673
27848
  const { config: pmLoadedConfig } = _internals36.loadPluginConfigWithMeta(ctx.directory);
27674
27849
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
27675
27850
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
@@ -29947,9 +30122,9 @@ var _internals41 = {
29947
30122
  loadPluginConfigWithMeta,
29948
30123
  loadCuratorDeps: async () => {
29949
30124
  const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
29950
- import("./schema-1wmfgtm9.js"),
29951
- import("./curator-tbw9przg.js"),
29952
- import("./curator-llm-factory-j42j5rcr.js")
30125
+ import("./schema-z141arx9.js"),
30126
+ import("./curator-2gt2835v.js"),
30127
+ import("./curator-llm-factory-x1vjhrnc.js")
29953
30128
  ]);
29954
30129
  return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
29955
30130
  }
@@ -30854,7 +31029,7 @@ async function computeCurationDiagnostics(directory, entries) {
30854
31029
  let scanCompleted = false;
30855
31030
  let scanRemaining = 0;
30856
31031
  try {
30857
- const { getScanStatus } = await import("./scan-cursor-em4vrcw6.js");
31032
+ const { getScanStatus } = await import("./scan-cursor-x7a99wmq.js");
30858
31033
  const status = await getScanStatus(directory);
30859
31034
  scanGeneration = status.generation;
30860
31035
  scanCompleted = status.completed;
@@ -30864,10 +31039,10 @@ async function computeCurationDiagnostics(directory, entries) {
30864
31039
  try {
30865
31040
  const { isLinked: isLinked2 } = await import("./knowledge-link-fn5j3r4q.js");
30866
31041
  if (isLinked2(directory)) {
30867
- const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-1wmfgtm9.js");
31042
+ const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-z141arx9.js");
30868
31043
  let config;
30869
31044
  try {
30870
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-seedt8m3.js");
31045
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-kc2x117y.js");
30871
31046
  const loaded = loadPluginConfigWithMeta2(directory);
30872
31047
  config = KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
30873
31048
  } catch {
@@ -32085,7 +32260,7 @@ async function handleDoctorCommand(directory, args) {
32085
32260
  const result = runConfigDoctor(config, directory);
32086
32261
  let output;
32087
32262
  if (enableAutoFix && result.hasAutoFixableIssues) {
32088
- const { runConfigDoctorWithFixes } = await import("./config-doctor-az6nqawx.js");
32263
+ const { runConfigDoctorWithFixes } = await import("./config-doctor-72zp0k4x.js");
32089
32264
  const fixResult = await runConfigDoctorWithFixes(directory, config, true, {
32090
32265
  applyLossy: true
32091
32266
  });
@@ -32922,7 +33097,7 @@ async function handleEvidenceCommand(directory, args) {
32922
33097
  return formatTaskEvidenceMarkdown(evidenceData);
32923
33098
  }
32924
33099
  async function handleEvidenceSummaryCommand(directory) {
32925
- const { buildEvidenceSummary } = await import("./evidence-summary-service-3f319cst.js");
33100
+ const { buildEvidenceSummary } = await import("./evidence-summary-service-yjr0662r.js");
32926
33101
  const artifact = await buildEvidenceSummary(directory);
32927
33102
  if (!artifact) {
32928
33103
  return "No plan found. Run `/swarm plan` to check plan status.";
@@ -32957,12 +33132,13 @@ async function handleEvidenceSummaryCommand(directory) {
32957
33132
  `);
32958
33133
  }
32959
33134
  // src/services/export-service.ts
33135
+ init_package();
32960
33136
  async function getExportData(directory) {
32961
33137
  const planStructured = await loadPlanJsonOnly(directory);
32962
33138
  const planContent = await readSwarmFileAsync(directory, "plan.md");
32963
33139
  const contextContent = await readSwarmFileAsync(directory, "context.md");
32964
33140
  return {
32965
- version: "4.5.0",
33141
+ version: package_default.version,
32966
33142
  exported: new Date().toISOString(),
32967
33143
  plan: planStructured || planContent,
32968
33144
  context: contextContent,
@@ -43175,6 +43351,7 @@ var _internals63 = {
43175
43351
  };
43176
43352
 
43177
43353
  // src/services/preflight-service.ts
43354
+ init_zod();
43178
43355
  import * as fs33 from "fs";
43179
43356
  import * as path78 from "path";
43180
43357
 
@@ -48546,6 +48723,15 @@ async function runEvidenceCheck(dir) {
48546
48723
  };
48547
48724
  }
48548
48725
  }
48726
+ var ReqCoverageReportSchema = exports_external.object({
48727
+ success: exports_external.boolean(),
48728
+ phase: exports_external.number().int().nonnegative(),
48729
+ totalRequirements: exports_external.number().int().nonnegative(),
48730
+ coveredCount: exports_external.number().int().nonnegative(),
48731
+ missingCount: exports_external.number().int().nonnegative(),
48732
+ requirements: exports_external.array(exports_external.unknown())
48733
+ });
48734
+ var REQ_COVERAGE_MAX_JSON_BYTES = 500 * 1024;
48549
48735
  async function runRequirementCoverageCheck(dir, currentPhase) {
48550
48736
  const startTime = Date.now();
48551
48737
  try {
@@ -48559,20 +48745,156 @@ async function runRequirementCoverageCheck(dir, currentPhase) {
48559
48745
  };
48560
48746
  }
48561
48747
  const coverage = await checkRequirementCoverage(currentPhase, dir);
48562
- if (coverage.exists) {
48748
+ if (!coverage.exists) {
48563
48749
  return {
48564
48750
  type: "req_coverage",
48565
- status: "pass",
48566
- message: "Requirement coverage report found",
48751
+ status: "fail",
48752
+ message: "Requirement coverage report missing but effective spec exists",
48753
+ details: { expectedPath: coverage.path },
48754
+ durationMs: Date.now() - startTime
48755
+ };
48756
+ }
48757
+ let raw;
48758
+ try {
48759
+ const stat7 = await fs33.promises.stat(coverage.path);
48760
+ if (stat7.size > REQ_COVERAGE_MAX_JSON_BYTES) {
48761
+ return {
48762
+ type: "req_coverage",
48763
+ status: "fail",
48764
+ message: `Requirement coverage report exceeds ${REQ_COVERAGE_MAX_JSON_BYTES} byte cap and cannot be validated`,
48765
+ details: { path: coverage.path, sizeBytes: stat7.size },
48766
+ durationMs: Date.now() - startTime
48767
+ };
48768
+ }
48769
+ raw = await fs33.promises.readFile(coverage.path, "utf-8");
48770
+ } catch (readError) {
48771
+ return {
48772
+ type: "req_coverage",
48773
+ status: "fail",
48774
+ message: `Requirement coverage report unreadable: ${readError instanceof Error ? readError.message : String(readError)}`,
48775
+ details: { path: coverage.path },
48776
+ durationMs: Date.now() - startTime
48777
+ };
48778
+ }
48779
+ const trimmed = raw.trim();
48780
+ if (trimmed.length === 0) {
48781
+ return {
48782
+ type: "req_coverage",
48783
+ status: "fail",
48784
+ message: "Requirement coverage report is empty",
48567
48785
  details: { path: coverage.path },
48568
48786
  durationMs: Date.now() - startTime
48569
48787
  };
48570
48788
  }
48789
+ let parsed;
48790
+ try {
48791
+ parsed = JSON.parse(trimmed);
48792
+ } catch (parseError) {
48793
+ const parseErrorMessage = parseError instanceof Error ? parseError.message : String(parseError);
48794
+ return {
48795
+ type: "req_coverage",
48796
+ status: "fail",
48797
+ message: `Requirement coverage report is not valid JSON: ${parseErrorMessage}`,
48798
+ details: { path: coverage.path },
48799
+ durationMs: Date.now() - startTime
48800
+ };
48801
+ }
48802
+ const report = ReqCoverageReportSchema.safeParse(parsed);
48803
+ if (!report.success) {
48804
+ return {
48805
+ type: "req_coverage",
48806
+ status: "fail",
48807
+ message: "Requirement coverage report does not match the expected report shape",
48808
+ details: { path: coverage.path },
48809
+ durationMs: Date.now() - startTime
48810
+ };
48811
+ }
48812
+ const {
48813
+ success,
48814
+ phase,
48815
+ totalRequirements,
48816
+ coveredCount,
48817
+ missingCount,
48818
+ requirements
48819
+ } = report.data;
48820
+ if (!success) {
48821
+ return {
48822
+ type: "req_coverage",
48823
+ status: "fail",
48824
+ message: "Requirement coverage report indicates the coverage run itself failed (success: false)",
48825
+ details: { path: coverage.path },
48826
+ durationMs: Date.now() - startTime
48827
+ };
48828
+ }
48829
+ if (phase !== currentPhase) {
48830
+ return {
48831
+ type: "req_coverage",
48832
+ status: "fail",
48833
+ message: `Requirement coverage report phase (${phase}) does not match the current phase (${currentPhase})`,
48834
+ details: { path: coverage.path, reportPhase: phase, currentPhase },
48835
+ durationMs: Date.now() - startTime
48836
+ };
48837
+ }
48838
+ if (totalRequirements === 0) {
48839
+ return {
48840
+ type: "req_coverage",
48841
+ status: "fail",
48842
+ message: "Requirement coverage report contains no requirements (totalRequirements is 0) but effective spec exists",
48843
+ details: { path: coverage.path, totalRequirements },
48844
+ durationMs: Date.now() - startTime
48845
+ };
48846
+ }
48847
+ if (coveredCount + missingCount !== totalRequirements) {
48848
+ return {
48849
+ type: "req_coverage",
48850
+ status: "fail",
48851
+ message: `Requirement coverage report counts are inconsistent: coveredCount (${coveredCount}) + missingCount (${missingCount}) !== totalRequirements (${totalRequirements})`,
48852
+ details: {
48853
+ path: coverage.path,
48854
+ totalRequirements,
48855
+ coveredCount,
48856
+ missingCount
48857
+ },
48858
+ durationMs: Date.now() - startTime
48859
+ };
48860
+ }
48861
+ if (requirements.length !== totalRequirements) {
48862
+ return {
48863
+ type: "req_coverage",
48864
+ status: "fail",
48865
+ message: `Requirement coverage report requirements array length (${requirements.length}) does not match totalRequirements (${totalRequirements})`,
48866
+ details: {
48867
+ path: coverage.path,
48868
+ totalRequirements,
48869
+ requirementsLength: requirements.length
48870
+ },
48871
+ durationMs: Date.now() - startTime
48872
+ };
48873
+ }
48874
+ if (missingCount > 0) {
48875
+ return {
48876
+ type: "req_coverage",
48877
+ status: "fail",
48878
+ message: `Requirement coverage report has ${missingCount} uncovered requirement(s)`,
48879
+ details: {
48880
+ path: coverage.path,
48881
+ totalRequirements,
48882
+ coveredCount,
48883
+ missingCount
48884
+ },
48885
+ durationMs: Date.now() - startTime
48886
+ };
48887
+ }
48571
48888
  return {
48572
48889
  type: "req_coverage",
48573
- status: "fail",
48574
- message: "Requirement coverage report missing but effective spec exists",
48575
- details: { expectedPath: coverage.path },
48890
+ status: "pass",
48891
+ message: `Requirement coverage report found: ${coveredCount}/${totalRequirements} requirement(s) covered`,
48892
+ details: {
48893
+ path: coverage.path,
48894
+ totalRequirements,
48895
+ coveredCount,
48896
+ missingCount
48897
+ },
48576
48898
  durationMs: Date.now() - startTime
48577
48899
  };
48578
48900
  } catch (error2) {
@@ -57474,7 +57796,7 @@ function buildDetailedHelp(commandName, entry) {
57474
57796
  async function handleHelpCommand(ctx) {
57475
57797
  const targetCommand = ctx.args.join(" ");
57476
57798
  if (!targetCommand) {
57477
- const { buildHelpText } = await import("./index-mewk624g.js");
57799
+ const { buildHelpText } = await import("./index-dtf2va28.js");
57478
57800
  return buildHelpText();
57479
57801
  }
57480
57802
  const tokens = targetCommand.split(/\s+/);
@@ -57483,7 +57805,7 @@ async function handleHelpCommand(ctx) {
57483
57805
  return _internals87.buildDetailedHelp(resolved.key, resolved.entry);
57484
57806
  }
57485
57807
  const similar = _internals87.findSimilarCommands(targetCommand);
57486
- const { buildHelpText: fullHelp } = await import("./index-mewk624g.js");
57808
+ const { buildHelpText: fullHelp } = await import("./index-dtf2va28.js");
57487
57809
  if (similar.length > 0) {
57488
57810
  return `Command '/swarm ${targetCommand}' not found.
57489
57811
 
@@ -57660,7 +57982,7 @@ var COMMAND_REGISTRY = {
57660
57982
  },
57661
57983
  "guardrail explain": {
57662
57984
  handler: async (ctx) => {
57663
- const { handleGuardrailExplain } = await import("./guardrail-explain-tsgsw91f.js");
57985
+ const { handleGuardrailExplain } = await import("./guardrail-explain-f3zysesy.js");
57664
57986
  return handleGuardrailExplain(ctx.directory, ctx.args);
57665
57987
  },
57666
57988
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -57670,7 +57992,7 @@ var COMMAND_REGISTRY = {
57670
57992
  },
57671
57993
  "guardrail-explain": {
57672
57994
  handler: async (ctx) => {
57673
- const { handleGuardrailExplain } = await import("./guardrail-explain-tsgsw91f.js");
57995
+ const { handleGuardrailExplain } = await import("./guardrail-explain-f3zysesy.js");
57674
57996
  return handleGuardrailExplain(ctx.directory, ctx.args);
57675
57997
  },
57676
57998
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -57680,7 +58002,7 @@ var COMMAND_REGISTRY = {
57680
58002
  },
57681
58003
  "guardrail-log": {
57682
58004
  handler: async (ctx) => {
57683
- const { handleGuardrailLog } = await import("./guardrail-log-70cxb3va.js");
58005
+ const { handleGuardrailLog } = await import("./guardrail-log-eat71fnh.js");
57684
58006
  return handleGuardrailLog(ctx.directory, ctx.args);
57685
58007
  },
57686
58008
  description: "Read the guardrail decision log (use --blocks-only for blocks)",
@@ -64892,7 +65214,7 @@ function isLaneOwnedByCurrentSession(branchName, expectedSessionId) {
64892
65214
  return extracted === expectedSessionId;
64893
65215
  }
64894
65216
  async function inspectStandardWorktreeCollisionOwnership(identity) {
64895
- const collisionOwnership = await import("./worktree-collision-ownership-bfz3drxm.js");
65217
+ const collisionOwnership = await import("./worktree-collision-ownership-42bb3gcb.js");
64896
65218
  return collisionOwnership.inspectStandardWorktreeCollisionOwnership(identity);
64897
65219
  }
64898
65220
  async function precreateStandardWorktreeSession(args) {
@@ -65040,7 +65362,7 @@ async function precreateStandardWorktreeSession(args) {
65040
65362
  const laneProfile = computeLaneRuntimeProfile(worktreeConfig.runtime_isolation, laneIndex, provisionResult.worktreePath);
65041
65363
  if (laneProfile) {
65042
65364
  try {
65043
- const { writeLaneProfileToDiskReal } = await import("./core-a6rzajem.js");
65365
+ const { writeLaneProfileToDiskReal } = await import("./core-aj0wmbg8.js");
65044
65366
  await writeLaneProfileToDiskReal(provisionResult.worktreePath, laneProfile.laneIndex, laneProfile.envOverrides);
65045
65367
  } catch {}
65046
65368
  }
@@ -65539,7 +65861,7 @@ async function finishStandardWorktreeDispatch(directory, dispatch, config, callI
65539
65861
  }
65540
65862
  clearWorktreeMergeStatus(statusKey);
65541
65863
  try {
65542
- const { removeLaneProfileFromDiskReal } = await import("./core-a6rzajem.js");
65864
+ const { removeLaneProfileFromDiskReal } = await import("./core-aj0wmbg8.js");
65543
65865
  await removeLaneProfileFromDiskReal(dispatch.handle.worktreePath, dispatch.laneIndex);
65544
65866
  } catch {}
65545
65867
  const state = serializationStateBySessionID.get(dispatch.parentSessionID);