opencode-swarm 7.199.4 → 7.199.5

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 (120) hide show
  1. package/.opencode/skills/swarm-pr-feedback/references/followup-dispositions.md +1 -0
  2. package/.opencode/skills/swarm-pr-review/SKILL.md +3 -3
  3. package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
  4. package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
  5. package/dist/agents/architect.d.ts +1 -1
  6. package/dist/background/pending-delegations.d.ts +46 -0
  7. package/dist/cli/{auto-checkpoint-75n3s0qj.js → auto-checkpoint-tje4xvtw.js} +12 -11
  8. package/dist/cli/{checkpoint-vdjfn78h.js → checkpoint-wyh8nkhb.js} +21 -21
  9. package/dist/cli/{coder-settlement-wwgdrzcb.js → coder-settlement-d0ca5fb3.js} +18 -18
  10. package/dist/cli/{config-doctor-x8ke4n9r.js → config-doctor-swg02esj.js} +19 -19
  11. package/dist/cli/{core-2zmr3718.js → core-yh8ae69m.js} +7 -7
  12. package/dist/cli/{curation-policy-0smbd33w.js → curation-policy-w9y0db1n.js} +8 -8
  13. package/dist/cli/{curator-7pnzsqe8.js → curator-9vzqhesg.js} +51 -51
  14. package/dist/cli/{curator-drift-2rtecv79.js → curator-drift-85qect05.js} +12 -12
  15. package/dist/cli/curator-llm-factory-dwvftpvm.js +82 -0
  16. package/dist/cli/{dispatch-1pbmmj8z.js → dispatch-sftetpzv.js} +4 -4
  17. package/dist/cli/{doctor-knowledge-receipt-phase-id-0yqb8t1e.js → doctor-knowledge-receipt-phase-id-eqzsh3b7.js} +12 -12
  18. package/dist/cli/{evidence-summary-service-59r4wnbz.js → evidence-summary-service-hc513kyq.js} +27 -27
  19. package/dist/cli/{gate-evidence-7xp8a4s3.js → gate-evidence-a10epye0.js} +13 -13
  20. package/dist/cli/guardrail-explain-rqqhmb44.js +83 -0
  21. package/dist/cli/guardrail-log-caspzygc.js +23 -0
  22. package/dist/cli/{guardrail-reset-2edjt0zn.js → guardrail-reset-48r2n8mz.js} +51 -51
  23. package/dist/cli/hive-promoter-sd3a61mq.js +97 -0
  24. package/dist/cli/{index-h69d3ksz.js → index-0aj9tvms.js} +51 -51
  25. package/dist/cli/{index-dyp5807d.js → index-0je0mees.js} +10 -8
  26. package/dist/cli/{index-eh12k044.js → index-0ra0vs2p.js} +13 -11
  27. package/dist/cli/{index-2mx2gn97.js → index-0veqvgny.js} +1 -1
  28. package/dist/cli/{index-h44592hj.js → index-10wwrgj2.js} +6 -6
  29. package/dist/cli/{index-5mfahvm2.js → index-26dmsdx3.js} +4884 -5746
  30. package/dist/cli/{index-ywb5er8g.js → index-270zfq1f.js} +2 -2
  31. package/dist/cli/{index-ry1jgeqa.js → index-34jat4f2.js} +2 -2
  32. package/dist/cli/{index-97cpeqb2.js → index-3ckvw3j2.js} +2 -2
  33. package/dist/cli/{index-2wsh6d15.js → index-3fz5w2wb.js} +15 -6
  34. package/dist/cli/{index-h349p91m.js → index-3mzc5rqc.js} +2 -2
  35. package/dist/cli/{index-bkscmz4z.js → index-4cyc18bc.js} +11 -11
  36. package/dist/cli/{index-hxav7nr0.js → index-4pbzepgw.js} +1645 -124
  37. package/dist/cli/{index-vnmadnbs.js → index-6ssraqaa.js} +15 -11
  38. package/dist/cli/{index-9gfymmr8.js → index-6xv2hz0e.js} +5 -5
  39. package/dist/cli/{index-dradkxhb.js → index-6xyt6d5m.js} +13 -13
  40. package/dist/cli/{index-t94vcqg6.js → index-76skvj8z.js} +7 -7
  41. package/dist/cli/{index-ffkd1zwc.js → index-85vd6sxy.js} +10 -10
  42. package/dist/cli/{index-k0er6f51.js → index-9c0vp5yj.js} +2 -2
  43. package/dist/cli/{index-sxh861jr.js → index-9n40q82y.js} +4 -4
  44. package/dist/cli/{index-nr1pj3hy.js → index-9y6yk1n0.js} +1 -1
  45. package/dist/cli/{index-j2vv0h13.js → index-axqyjreb.js} +6 -4
  46. package/dist/cli/{index-aaqgsmxr.js → index-b0kr8720.js} +53 -53
  47. package/dist/cli/{index-820pzqd6.js → index-b3ws03kp.js} +7 -5
  48. package/dist/cli/{index-3chx0ed6.js → index-bgydmx8k.js} +11 -11
  49. package/dist/cli/{index-bh6j8qxz.js → index-d7y3cafq.js} +5 -5
  50. package/dist/cli/{index-g1wra8ky.js → index-dengtwpp.js} +5 -4
  51. package/dist/cli/{index-6dtt0brw.js → index-dtwj4hsk.js} +4 -4
  52. package/dist/cli/{index-4s6kdsfr.js → index-dz15f98h.js} +1 -1
  53. package/dist/cli/{index-s41r5s5p.js → index-esakwcr3.js} +1 -1
  54. package/dist/cli/{index-hz2609qt.js → index-eyq1q1xn.js} +9 -7
  55. package/dist/cli/{index-aayv19fb.js → index-gyz59cbh.js} +25 -21
  56. package/dist/cli/{index-7c432abn.js → index-hx2f3j9w.js} +2 -2
  57. package/dist/cli/{index-p5pgjp7n.js → index-j3rfbs45.js} +1 -1
  58. package/dist/cli/{index-w7d8gcj0.js → index-jmhn6ab5.js} +2 -2
  59. package/dist/cli/{index-jhz7qpb4.js → index-my753e0g.js} +21 -17
  60. package/dist/cli/{index-2bc7zfw3.js → index-n1ddn12j.js} +2 -2
  61. package/dist/cli/{index-hfpa3hrz.js → index-p5d32v0x.js} +11 -11
  62. package/dist/cli/{index-2s7dvzff.js → index-qbxk2rn6.js} +42 -41
  63. package/dist/cli/{index-w00dj8p5.js → index-snx2vb1x.js} +2 -2
  64. package/dist/cli/{index-zxdawwc7.js → index-sp2cxpaq.js} +131 -8
  65. package/dist/cli/{index-g4fs6z4e.js → index-spggmr30.js} +6 -2
  66. package/dist/cli/{index-pxdc0qn1.js → index-tsg61z0r.js} +2 -2
  67. package/dist/cli/{index-jwg4wy3g.js → index-v4mremxw.js} +6 -5
  68. package/dist/cli/{index-cjapb4hy.js → index-x5jwegqw.js} +7 -5
  69. package/dist/cli/{index-h3nns8py.js → index-xtda4xsn.js} +403 -170
  70. package/dist/cli/{index-3gr7a9j8.js → index-xyg7des8.js} +4 -4
  71. package/dist/cli/{index-65syfqe1.js → index-ybvnf7rt.js} +8 -8
  72. package/dist/cli/{index-nfpfbce0.js → index-yg5xd4am.js} +18 -16
  73. package/dist/cli/{index-hc6wa3yg.js → index-zbygz217.js} +3 -3
  74. package/dist/cli/{index-x1j0838n.js → index-zdfzrwbk.js} +7 -7
  75. package/dist/cli/{index-4f5ejd03.js → index-zte3djpf.js} +2 -2
  76. package/dist/cli/index.js +52 -52
  77. package/dist/cli/{knowledge-escalator-2kphhk52.js → knowledge-escalator-9wqe0m8j.js} +18 -18
  78. package/dist/cli/{knowledge-events-xw4qjnts.js → knowledge-events-m5vdchaa.js} +16 -16
  79. package/dist/cli/{knowledge-link-1f91bzcc.js → knowledge-link-t0ce3mw7.js} +7 -7
  80. package/dist/cli/{knowledge-store-1cm7y9e6.js → knowledge-store-ff4hy057.js} +8 -8
  81. package/dist/cli/{knowledge-validator-q4r4ng23.js → knowledge-validator-erj5thtq.js} +10 -10
  82. package/dist/cli/{mcp-0548g7fk.js → mcp-d0hz5gfp.js} +1 -1
  83. package/dist/cli/{model-preflight-pdewpzmm.js → model-preflight-p34x0k25.js} +51 -51
  84. package/dist/cli/{pending-delegations-zv9ffy5b.js → pending-delegations-1j6dx1mf.js} +18 -15
  85. package/dist/cli/{pr-subscriptions-0ktv4qaq.js → pr-subscriptions-b1g41jce.js} +15 -15
  86. package/dist/cli/{pr-workflow-gate-71nxjz6p.js → pr-workflow-gate-zjwt050h.js} +59 -59
  87. package/dist/cli/{runner-7sd43gan.js → runner-wq954cda.js} +9 -9
  88. package/dist/cli/{scan-cursor-ty5dqwhm.js → scan-cursor-enz1rp21.js} +11 -10
  89. package/dist/cli/{schema-tnrvn8h1.js → schema-9r8sggpb.js} +1 -1
  90. package/dist/cli/{scope-persistence-camnvcaq.js → scope-persistence-c5n4g9f0.js} +20 -19
  91. package/dist/cli/{server-cr9kvgzz.js → server-8z7pd66d.js} +56 -56
  92. package/dist/cli/{skill-generator-nx2g9975.js → skill-generator-nezzfa0t.js} +20 -20
  93. package/dist/cli/{snapshot-coordination-init-ymsjgsqf.js → snapshot-coordination-init-2j06c7ck.js} +51 -51
  94. package/dist/cli/{speckit-checkoff-1pyx7y0d.js → speckit-checkoff-805cqmrf.js} +7 -6
  95. package/dist/cli/{telemetry-6yv06xyz.js → telemetry-gena5typ.js} +3 -3
  96. package/dist/cli/{workspace-snapshot-4zfj5wnd.js → workspace-snapshot-hzhz0rxw.js} +7 -7
  97. package/dist/cli/{worktree-collision-ownership-twe4r9f2.js → worktree-collision-ownership-xpr0yv7h.js} +22 -21
  98. package/dist/cli/{worktree-isolation-yj3vfp1h.js → worktree-isolation-z6ytes0j.js} +51 -51
  99. package/dist/commands/close/dry-run.d.ts +2 -1
  100. package/dist/commands/close/orchestrator.d.ts +16 -5
  101. package/dist/commands/destructive-purge.d.ts +53 -12
  102. package/dist/commands/git-status-read.d.ts +76 -0
  103. package/dist/commands/rollback-gate.d.ts +24 -5
  104. package/dist/config/schema.d.ts +5 -3
  105. package/dist/evaluation/contracts.d.ts +5 -5
  106. package/dist/hooks/lane-liveness-watchdog.d.ts +6 -1
  107. package/dist/hooks/pr-workflow-gate.d.ts +61 -1
  108. package/dist/index.js +254 -252
  109. package/dist/memory/schema.d.ts +3 -3
  110. package/dist/pr-review/completion.d.ts +63 -2
  111. package/dist/services/diagnose-service.d.ts +7 -8
  112. package/dist/tools/dispatch-lanes.d.ts +2 -1
  113. package/dist/utils/git-executable.d.ts +4 -0
  114. package/opencode-swarm.schema.json +3 -2
  115. package/package.json +1 -1
  116. package/dist/cli/curator-llm-factory-aybwqak6.js +0 -82
  117. package/dist/cli/guardrail-explain-jahptqqd.js +0 -83
  118. package/dist/cli/guardrail-log-csp211g7.js +0 -23
  119. package/dist/cli/hive-promoter-17q1qg8e.js +0 -97
  120. package/dist/cli/{index-fzpt2djt.js → index-te9hq2f4.js} +3 -3
@@ -25,83 +25,83 @@ import {
25
25
  sanitizeWorktreeTaskId,
26
26
  standardWorktreeByCallID,
27
27
  standardWorktreeSerializationSessions
28
- } from "./index-5mfahvm2.js";
29
- import"./index-jhz7qpb4.js";
30
- import"./index-2wsh6d15.js";
31
- import"./index-vnmadnbs.js";
32
- import"./index-j2vv0h13.js";
33
- import"./index-dyp5807d.js";
34
- import"./index-7c432abn.js";
28
+ } from "./index-26dmsdx3.js";
29
+ import"./index-my753e0g.js";
30
+ import"./index-3fz5w2wb.js";
31
+ import"./index-6ssraqaa.js";
32
+ import"./index-axqyjreb.js";
33
+ import"./index-0je0mees.js";
34
+ import"./index-hx2f3j9w.js";
35
35
  import"./index-txdagbh7.js";
36
- import"./index-x1j0838n.js";
36
+ import"./index-zdfzrwbk.js";
37
37
  import"./index-rdec0y3z.js";
38
- import"./index-sxh861jr.js";
39
- import"./index-dradkxhb.js";
40
- import"./index-ffkd1zwc.js";
41
- import"./index-h44592hj.js";
42
- import"./index-hz2609qt.js";
43
- import"./index-bkscmz4z.js";
44
- import"./index-cjapb4hy.js";
45
- import"./index-pxdc0qn1.js";
38
+ import"./index-9n40q82y.js";
39
+ import"./index-6xyt6d5m.js";
40
+ import"./index-85vd6sxy.js";
41
+ import"./index-10wwrgj2.js";
42
+ import"./index-eyq1q1xn.js";
43
+ import"./index-4cyc18bc.js";
44
+ import"./index-x5jwegqw.js";
45
+ import"./index-tsg61z0r.js";
46
+ import"./index-4pbzepgw.js";
47
+ import"./index-8mrentmw.js";
46
48
  import"./index-pt7h91zc.js";
47
49
  import"./index-q7sjgr1y.js";
48
- import"./index-h3nns8py.js";
49
- import"./index-aayv19fb.js";
50
+ import"./index-xtda4xsn.js";
51
+ import"./index-gyz59cbh.js";
50
52
  import"./index-6b295cas.js";
51
53
  import"./index-9nyqt3kb.js";
52
- import"./index-t94vcqg6.js";
54
+ import"./index-76skvj8z.js";
53
55
  import"./index-v3bmwmqw.js";
54
- import"./index-k0er6f51.js";
55
- import"./index-nfpfbce0.js";
56
- import"./index-eh12k044.js";
57
- import"./index-g4fs6z4e.js";
58
- import"./index-hxav7nr0.js";
59
- import"./index-9gfymmr8.js";
60
- import"./index-bh6j8qxz.js";
56
+ import"./index-9c0vp5yj.js";
57
+ import"./index-yg5xd4am.js";
58
+ import"./index-0ra0vs2p.js";
59
+ import"./index-spggmr30.js";
60
+ import"./index-6xv2hz0e.js";
61
+ import"./index-d7y3cafq.js";
61
62
  import"./index-m9zzj4ee.js";
62
- import"./index-820pzqd6.js";
63
- import"./index-2s7dvzff.js";
64
- import"./index-3gr7a9j8.js";
65
- import"./index-2mx2gn97.js";
63
+ import"./index-b3ws03kp.js";
64
+ import"./index-xyg7des8.js";
65
+ import"./index-0veqvgny.js";
66
66
  import"./index-rtry5xyf.js";
67
67
  import {
68
68
  resolveWorktreeIsolationConfig
69
- } from "./index-4f5ejd03.js";
69
+ } from "./index-zte3djpf.js";
70
70
  import"./index-g22dps7x.js";
71
71
  import"./index-0725jpp7.js";
72
- import"./index-hfpa3hrz.js";
73
- import"./index-65syfqe1.js";
74
- import"./index-h349p91m.js";
75
- import"./index-p5pgjp7n.js";
76
- import"./index-nr1pj3hy.js";
77
- import"./index-w00dj8p5.js";
72
+ import"./index-p5d32v0x.js";
73
+ import"./index-j3rfbs45.js";
74
+ import"./index-ybvnf7rt.js";
75
+ import"./index-9y6yk1n0.js";
76
+ import"./index-snx2vb1x.js";
78
77
  import"./index-ry16d01s.js";
79
78
  import"./index-rdm3px0g.js";
79
+ import"./index-3mzc5rqc.js";
80
80
  import"./index-7pmbnjvj.js";
81
- import"./index-hc6wa3yg.js";
82
- import"./index-3chx0ed6.js";
81
+ import"./index-9rwhas09.js";
82
+ import"./index-zbygz217.js";
83
+ import"./index-bgydmx8k.js";
83
84
  import"./index-vzm6zre7.js";
84
85
  import"./index-ae75rja9.js";
85
- import"./index-2bc7zfw3.js";
86
- import"./index-w7d8gcj0.js";
87
- import"./index-4s6kdsfr.js";
86
+ import"./index-n1ddn12j.js";
87
+ import"./index-jmhn6ab5.js";
88
+ import"./index-dz15f98h.js";
88
89
  import"./index-t7hmqgjy.js";
89
- import"./index-6dtt0brw.js";
90
- import"./index-fzpt2djt.js";
90
+ import"./index-dtwj4hsk.js";
91
+ import"./index-te9hq2f4.js";
91
92
  import"./index-ejhxgyvm.js";
92
93
  import"./index-7g4c7s5r.js";
93
- import"./index-ywb5er8g.js";
94
+ import"./index-270zfq1f.js";
94
95
  import"./index-gx2vp8gx.js";
95
- import"./index-97cpeqb2.js";
96
- import"./index-zxdawwc7.js";
97
- import"./index-g1wra8ky.js";
96
+ import"./index-3ckvw3j2.js";
97
+ import"./index-sp2cxpaq.js";
98
+ import"./index-qbxk2rn6.js";
99
+ import"./index-zgwm4ryv.js";
100
+ import"./index-dengtwpp.js";
98
101
  import"./index-xfzkq1k4.js";
99
102
  import"./index-bk5tah7q.js";
100
103
  import"./index-gknz3bv1.js";
101
104
  import"./index-zpsr8rpc.js";
102
- import"./index-8mrentmw.js";
103
- import"./index-9rwhas09.js";
104
- import"./index-zgwm4ryv.js";
105
105
  import"./index-a76rekgs.js";
106
106
  export {
107
107
  standardWorktreeSerializationSessions,
@@ -3,7 +3,8 @@ import type { PlanData } from './context.js';
3
3
  * Builds the `/swarm finalize --dry-run` report. Purely READ-ONLY: inspects the
4
4
  * plan and the filesystem and describes what a real finalize WOULD do, without
5
5
  * acquiring the finalize lock, creating an archive bundle, deleting any file,
6
- * running git, or tearing down session state. (#1692)
6
+ * running any mutating git command (the repository probe below is a read-only
7
+ * `git rev-parse`), or tearing down session state. (#1692)
7
8
  *
8
9
  * The archive-first guard means the clean stage only removes files it first
9
10
  * archived successfully; this report approximates that by listing existing
@@ -1,4 +1,5 @@
1
1
  import { type PurgeCandidate } from '../destructive-purge.js';
2
+ import { type GitStatusReadResult } from '../git-status-read.js';
2
3
  import type { CloseCommandOptions, CloseStageContext } from './context.js';
3
4
  /**
4
5
  * #2508 two-step destructive close: what the destructive portion of close
@@ -25,13 +26,24 @@ export interface ClosePurgeGate {
25
26
  * not trip this signal.
26
27
  */
27
28
  gitStatusFailed: boolean;
29
+ /**
30
+ * #3317: WHY the read failed, when the async reader could tell — error
31
+ * code, exit status, and a bounded stderr tail, interpolated into the
32
+ * abort text with a remedy that matches the cause.
33
+ */
34
+ statusFailure?: {
35
+ code: string | null;
36
+ status: number | null;
37
+ stderrTail: string;
38
+ };
28
39
  }
29
- declare function runCloseGateGit(args: string[], cwd: string): string | null;
30
- /** Test seam for the #2508 gate (simulate git-status read failures). */
40
+ /** Test seam for the #2508 gate (simulate git-status read failures). The
41
+ * default routes through the #3317 async reader; legacy sync stubs returning
42
+ * `string | null` keep their original meaning (await-tolerant). */
31
43
  export declare const _closeGateInternals: {
32
- runGit: typeof runCloseGateGit;
44
+ runGit: (args: string[], cwd: string) => string | null | GitStatusReadResult | Promise<string | null | GitStatusReadResult>;
33
45
  };
34
- export declare function evaluateClosePurgeGate(directory: string, swarmDir: string): ClosePurgeGate;
46
+ export declare function evaluateClosePurgeGate(directory: string, swarmDir: string): Promise<ClosePurgeGate>;
35
47
  export declare function archiveCloseSummary(ctx: Pick<CloseStageContext, 'archiveStageFailed' | 'archiveDir' | 'warnings'>, closeSummaryPath: string, summaryWritten: boolean): Promise<void>;
36
48
  /**
37
49
  * Handles /swarm close command - performs full terminal session finalization:
@@ -63,4 +75,3 @@ export declare function acquireFinalizeLock(directory: string): Promise<{
63
75
  * scans all sessions).
64
76
  */
65
77
  export declare function detectFullAuto(directory: string, sessionID: string): boolean;
66
- export {};
@@ -1,6 +1,34 @@
1
+ /**
2
+ * Issue #2527 / #2508: the shared two-step destructive-purge confirmation
3
+ * primitive (preview + confirm_token → exact-token execution).
4
+ *
5
+ * Contract (frozen by check C8 and the destructive-purge-2527 unit suite):
6
+ * - `previewDestructivePurge` is a side-effect-free preview (counts, exact
7
+ * option label, the confirmation the operator must echo);
8
+ * - `issueConfirmToken` records a single-slot pending purge keyed by a
9
+ * digest over the candidate SET (sorted absolute paths + kind) and
10
+ * returns the confirm token (15-minute TTL);
11
+ * - `executeDestructivePurge` re-derives the CURRENT scope digest and
12
+ * passes only on exact token match AND digest match AND fresh TTL — so
13
+ * replay after the candidate set changes (a lane added, removed, or the
14
+ * scope re-derived differently) is rejected by construction, and the
15
+ * token is single-use (the pending record is consumed on execution; a
16
+ * second execution is rejected with "no pending purge").
17
+ * - TTL expiry: an expired pending record is treated as absent on read
18
+ * (silent); every new issuance overwrites the single slot — the
19
+ * overwritten token can never execute (it is rejected with "confirm
20
+ * token mismatch"; a single-slot store cannot distinguish generations,
21
+ * but rejection is guaranteed either way).
22
+ * - Scope-of-execution: the executor deletes ONLY the recorded candidate
23
+ * paths. The primitive confirms operator intent; CALLERS own scoping —
24
+ * `/swarm reset-session` (and #2508's `/swarm close` when it adopts
25
+ * this) must only construct candidate sets from ownership-gated,
26
+ * base-scoped directories.
27
+ */
1
28
  import { randomBytes } from 'node:crypto';
2
29
  import * as fs from 'node:fs';
3
30
  import { atomicWriteSwarmFileSync } from '../utils/atomic-write';
31
+ import { type GitStatusReadResult } from './git-status-read.js';
4
32
  export interface PurgeCandidate {
5
33
  path: string;
6
34
  reason: string;
@@ -27,19 +55,24 @@ export declare const _internals: {
27
55
  now: () => number;
28
56
  randomBytes: typeof randomBytes;
29
57
  scopeDigest: typeof scopeDigest;
30
- runGitStatus: typeof runGitStatusSync;
58
+ /**
59
+ * #3317: the tracked-dirty status read is async, bounded, and killable
60
+ * through the shared reader. Legacy sync stubs returning `string | null`
61
+ * keep their original meaning (#2953's await-tolerant seam contract).
62
+ */
63
+ runGitStatus: (args: readonly string[], cwd: string) => string | null | GitStatusReadResult | Promise<string | null | GitStatusReadResult>;
31
64
  };
32
65
  /**
33
66
  * Shared argv for every tracked-dirty measurement (issue #2953): the close
34
67
  * gate and the pre-destruction re-check run the identical status command and
35
- * feed the same parser, so the two measurements parse identically. (The two
36
- * reads still go through separate spawn wrappers; equivalence is by
37
- * convention + review, not a single shared call site.)
68
+ * feed the same parser, so the two measurements parse identically. (Both now
69
+ * route through the shared #3317 reader via their own test seam; equivalence
70
+ * is by convention + review, not a single shared call site.)
71
+ * #3317: `--no-optional-locks` leads the argv — a read-only status must not
72
+ * contend on the index write lock. It is a top-level git option and therefore
73
+ * sits BEFORE the subcommand.
38
74
  */
39
- export declare const GIT_STATUS_ARGS: readonly ["status", "--porcelain"];
40
- /** Default bounded status read (invariant 3: array form, cwd, timeout, ignore
41
- * stdin, bounded stdout, windowsHide). Exposed via `_internals` for tests. */
42
- declare function runGitStatusSync(args: readonly string[], cwd: string): string | null;
75
+ export declare const GIT_STATUS_ARGS: readonly ["--no-optional-locks", "status", "--porcelain"];
43
76
  /**
44
77
  * Parse `git status --porcelain` (newline) output into repo-relative
45
78
  * tracked-dirty paths: untracked (`??`) entries are skipped (they survive the
@@ -59,13 +92,21 @@ export declare function parseTrackedDirtyPaths(statusOutput: string): string[];
59
92
  * The close gate composes the same argv + parser directly through its own
60
93
  * long-standing `_closeGateInternals.runGit` seam rather than calling this
61
94
  * helper, so its existing #2508 fail-closed tests keep their injection point.
95
+ * #3317: async — the read is bounded and killable, and legacy sync stubs
96
+ * keep working (awaiting a plain value is a no-op).
62
97
  */
63
- export declare function readTrackedDirtyPaths(directory: string): {
98
+ export declare function readTrackedDirtyPaths(directory: string): Promise<{
64
99
  ok: true;
65
100
  dirtyPaths: string[];
66
101
  } | {
67
102
  ok: false;
68
- };
103
+ /** Structured cause when the reader could tell (absent for legacy `null` stubs). */
104
+ failure?: {
105
+ code: string | null;
106
+ status: number | null;
107
+ stderrTail: string;
108
+ };
109
+ }>;
69
110
  /**
70
111
  * Issue #2953 TOCTOU re-check: re-measure the tracked-dirty set immediately
71
112
  * before a destructive reset and compare it to the set the operator actually
@@ -75,14 +116,14 @@ export declare function readTrackedDirtyPaths(directory: string): {
75
116
  * "unchanged"). A file that got cleaner passes — strictly less destruction
76
117
  * than confirmed.
77
118
  */
78
- export declare function recheckBeforeDestructive(directory: string, expectedDirtyPaths: readonly string[]): {
119
+ export declare function recheckBeforeDestructive(directory: string, expectedDirtyPaths: readonly string[]): Promise<{
79
120
  ok: true;
80
121
  dirtyPaths: string[];
81
122
  } | {
82
123
  ok: false;
83
124
  reason: string;
84
125
  newDirtyPaths: string[];
85
- };
126
+ }>;
86
127
  declare function scopeDigest(kind: string, candidates: PurgeCandidate[]): string;
87
128
  /**
88
129
  * Side-effect-free preview: what would be purged, the counts, the exact
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Async, bounded, killable git-read runner for the user-facing gate paths
3
+ * (issue #3317): /swarm close's destructive-purge gate, the pre-destruction
4
+ * re-check, /swarm rollback's destruction measurement, /swarm diagnose's
5
+ * repository check, and /swarm finalize --dry-run's repository probe.
6
+ *
7
+ * Replaces the private blocking `spawnSync` wrappers that collapsed every
8
+ * failure class (timeout, missing binary, nonzero exit) into `null`, leaving
9
+ * the abort text no cause to name. The gate stays fail-closed — a read that
10
+ * cannot complete is reported as a structured failure, never as a clean tree.
11
+ *
12
+ * Deadline convention (the repo's discriminated-timeout rule, mirroring
13
+ * `runGitAsyncDetailed` in src/background/workspace-snapshot.ts): the
14
+ * caller-side `Promise.race` owns the deadline; `bunSpawn` with
15
+ * `killProcessTree: true` deletes the native timeout so exactly one timer is
16
+ * armed, and the `finally` block tree-kills a child that is still running.
17
+ * The deadline covers the WHOLE attempt — executable resolution is timed
18
+ * against it too, so the advertised timeoutMs is an end-to-end bound. The
19
+ * losing racer carries a no-op catch so a late completion can never surface
20
+ * an unhandled rejection.
21
+ */
22
+ import { bunSpawn } from '../utils/bun-compat';
23
+ export type GitStatusReadResult = {
24
+ ok: true;
25
+ stdout: string;
26
+ } | {
27
+ ok: false;
28
+ /**
29
+ * Failure class: `ETIMEDOUT` (deadline), `ENOENT` (missing binary,
30
+ * both runtimes), `ESIGNAL` (signal-terminated — see the arm's
31
+ * reachability note; Windows external termination lands in the
32
+ * nonzero path), `EOUTPUT` (output exceeded the read safety
33
+ * bound), or another spawn-error code (`EPERM`, `EBUSY`, …).
34
+ * Null only when the child ran and exited nonzero on its own.
35
+ */
36
+ code: string | null;
37
+ /** Child exit status when it ran and exited; null otherwise. */
38
+ status: number | null;
39
+ /** Bounded excerpt of the child's stderr (at most 200 characters, sanitized). */
40
+ stderrTail: string;
41
+ };
42
+ /** Parity with the gates this module replaces (10 s bounded read). */
43
+ export declare const GIT_READ_DEFAULT_TIMEOUT_MS = 10000;
44
+ /** Parity with the replaced wrappers' `maxBuffer: 1024 * 1024`. */
45
+ export declare const GIT_READ_DEFAULT_MAX_BUFFER_BYTES: number;
46
+ /** Bound for the `stderrTail` carried in failure results and abort text. */
47
+ export declare const GIT_READ_STDERR_TAIL_MAX_CHARS = 200;
48
+ /**
49
+ * Test seam (repo convention): `resolveExecutable` defaults to the async git
50
+ * resolver, `spawn` defaults to `bunSpawn`, and `readOnce` is the
51
+ * single-attempt runner `readGitStatusAsync` wraps. All three are late-bound
52
+ * through this object so sibling test files can stub them without
53
+ * `mock.module`.
54
+ */
55
+ export declare const gitStatusReadInternals: {
56
+ readOnce: (args: readonly string[], cwd: string, timeoutMs: number, maxBufferBytes?: number, ignoreOutput?: boolean) => Promise<GitStatusReadResult>;
57
+ resolveExecutable: () => Promise<string>;
58
+ spawn: typeof bunSpawn;
59
+ };
60
+ /**
61
+ * Bounded git read with exactly one retry for transient spawn errors
62
+ * (`ETIMEDOUT`, `EBUSY`, `EPERM`). Definite failures — `ENOENT`, `EOUTPUT`,
63
+ * `ESIGNAL`, nonzero exits — are permanent: one attempt only. A second
64
+ * transient failure is final (two attempts total).
65
+ */
66
+ export declare function readGitStatusAsync(args: readonly string[], cwd: string, opts?: {
67
+ timeoutMs?: number;
68
+ maxBufferBytes?: number;
69
+ }): Promise<GitStatusReadResult>;
70
+ /**
71
+ * Single-attempt repository probe for `/swarm finalize --dry-run`
72
+ * (issue #3317): `rev-parse --git-dir` through the shared reader, mapped to a
73
+ * boolean. Single attempt by design — the dry-run report must stay a fast,
74
+ * non-blocking preview, with no transient-retry chain.
75
+ */
76
+ export declare function readGitRepositoryStatusAsync(cwd: string): Promise<boolean>;
@@ -1,4 +1,5 @@
1
1
  import type { PurgeCandidate } from './destructive-purge';
2
+ import { type GitStatusReadResult } from './git-status-read';
2
3
  /** Destructive-surface kind for the git checkpoint restore path. */
3
4
  export declare const ROLLBACK_GIT_KIND = "swarm-rollback-git";
4
5
  /** Destructive-surface kind for the legacy phase-overwrite restore path. */
@@ -6,10 +7,14 @@ export declare const ROLLBACK_PHASE_KIND = "swarm-rollback-phase";
6
7
  /**
7
8
  * Test seam for the rollback gate (simulate git-status read failures without
8
9
  * spawning real git). Mirrors `_closeGateInternals.runGit`.
10
+ * #3317: the defaults are the async shared reader — bounded, killable, and
11
+ * detail-carrying. Legacy sync stubs returning `string | null` keep their
12
+ * original meaning (await-tolerant); the status argv leads with
13
+ * `--no-optional-locks` and the listing reads keep the 32 MB bound.
9
14
  */
10
15
  export declare const _rollbackGateInternals: {
11
- runGit: (args: string[], cwd: string) => string | null;
12
- runGitBuffered: (args: string[], cwd: string) => string | null;
16
+ runGit: (args: string[], cwd: string) => string | null | GitStatusReadResult | Promise<string | null | GitStatusReadResult>;
17
+ runGitBuffered: (args: string[], cwd: string) => string | null | GitStatusReadResult | Promise<string | null | GitStatusReadResult>;
13
18
  };
14
19
  /**
15
20
  * A real git repository root: `.git` is a linked-worktree/submodule pointer
@@ -42,7 +47,7 @@ export declare function parseTrackedDirtyPaths(statusOutput: string): string[];
42
47
  * listing cannot be read — the tracked-dirty gate above still applies, and
43
48
  * the caller's unreadable-status refusal covers real-repo failures.
44
49
  */
45
- export declare function untrackedPathsInTargetTree(directory: string, targetSha: string): string[];
50
+ export declare function untrackedPathsInTargetTree(directory: string, targetSha: string): Promise<string[]>;
46
51
  /**
47
52
  * The git-kind candidate set: the absolute paths of tracked-dirty files that
48
53
  * `git reset --hard` would destroy. This is the ONLY derivation for
@@ -55,6 +60,16 @@ export declare function trackedDirtyCandidates(directory: string, dirtyRelPaths:
55
60
  * entries the checkpoint copy loop would overwrite.
56
61
  */
57
62
  export declare function swarmOverwriteCandidates(directory: string, overwriteRelPaths: string[]): PurgeCandidate[];
63
+ /**
64
+ * #3317: cause-matched wording for an unreadable destruction measurement —
65
+ * single source shared by the /swarm rollback command and the checkpoint
66
+ * tool sink so the two refusal texts cannot drift.
67
+ */
68
+ export declare function describeUnreadableCause(measurement: {
69
+ code?: string | null;
70
+ status?: number | null;
71
+ stderrTail?: string;
72
+ }): string;
58
73
  /**
59
74
  * Measure the destruction scope for a git checkpoint restore. When
60
75
  * `targetSha` is provided, files that are untracked (or since-ignored) on
@@ -65,9 +80,13 @@ export declare function swarmOverwriteCandidates(directory: string, overwriteRel
65
80
  * it as a clean tree). A non-git or bare-marker root returns an empty
66
81
  * dirty set: nothing tracked to destroy.
67
82
  */
68
- export declare function measureGitDestruction(directory: string, targetSha?: string): {
83
+ export declare function measureGitDestruction(directory: string, targetSha?: string): Promise<{
69
84
  kind: 'ok';
70
85
  dirtyRelPaths: string[];
71
86
  } | {
72
87
  kind: 'unreadable';
73
- };
88
+ /** #3317: why the read failed, when the async reader could tell. */
89
+ code?: string | null;
90
+ status?: number | null;
91
+ stderrTail?: string;
92
+ }>;
@@ -2152,8 +2152,10 @@ export declare const ReviewRoutingConfigSchema: z.ZodObject<{
2152
2152
  export type ReviewRoutingConfig = z.infer<typeof ReviewRoutingConfigSchema>;
2153
2153
  export declare const DEFAULT_REVIEW_ROUTING_CONFIG: ReviewRoutingConfig;
2154
2154
  /**
2155
- * Issue #2506 (G2): the lane-liveness watchdog. Default OFF; each numeric knob
2156
- * disables its own feature at 0. When enabled, `timeout_ms` becomes the ONE
2155
+ * Issue #2506 (G2): the lane-liveness watchdog. Default ON (#3313 AC14
2156
+ * supersedes the #2506 AC1 default-off contract): an omitted section or an
2157
+ * empty section resolves the enabled watchdog, and `enabled: false` (or a 0
2158
+ * knob) is a full opt-out. When enabled, `timeout_ms` becomes the ONE
2157
2159
  * effective PR-lane settlement horizon (the 30-minute reachability floor
2158
2160
  * remains the fallback when the watchdog is off or `timeout_ms` is 0), and
2159
2161
  * stall detection escalates low-output lanes BEFORE that horizon. Parameter
@@ -2314,7 +2316,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
2314
2316
  review_routing: z.ZodOptional<z.ZodObject<{
2315
2317
  enforce_receipts: z.ZodDefault<z.ZodBoolean>;
2316
2318
  }, z.core.$strict>>;
2317
- lane_liveness_watchdog: z.ZodOptional<z.ZodObject<{
2319
+ lane_liveness_watchdog: z.ZodPrefault<z.ZodObject<{
2318
2320
  enabled: z.ZodDefault<z.ZodBoolean>;
2319
2321
  timeout_ms: z.ZodDefault<z.ZodNumber>;
2320
2322
  stall_threshold_ms: z.ZodDefault<z.ZodNumber>;
@@ -7,8 +7,8 @@ export { Sha256Schema as EvaluationSha256Schema };
7
7
  export { RelativePathSchema as EvaluationRelativePathSchema };
8
8
  export declare const EvaluationSplitSchema: z.ZodEnum<{
9
9
  test: "test";
10
- train: "train";
11
10
  validation: "validation";
11
+ train: "train";
12
12
  }>;
13
13
  export type EvaluationSplit = z.infer<typeof EvaluationSplitSchema>;
14
14
  export declare const CostRecordSchema: z.ZodObject<{
@@ -40,8 +40,8 @@ export declare const EvaluationTaskV1Schema: z.ZodObject<{
40
40
  }>;
41
41
  split: z.ZodEnum<{
42
42
  test: "test";
43
- train: "train";
44
43
  validation: "validation";
44
+ train: "train";
45
45
  }>;
46
46
  category: z.ZodString;
47
47
  protected: z.ZodDefault<z.ZodBoolean>;
@@ -196,8 +196,8 @@ export declare const EvaluationRunV1Schema: z.ZodObject<{
196
196
  }, z.core.$strict>;
197
197
  split: z.ZodEnum<{
198
198
  test: "test";
199
- train: "train";
200
199
  validation: "validation";
200
+ train: "train";
201
201
  }>;
202
202
  seed: z.ZodString;
203
203
  models: z.ZodArray<z.ZodString>;
@@ -493,8 +493,8 @@ export declare const TaskSetSnapshotV1Schema: z.ZodObject<{
493
493
  id: z.ZodString;
494
494
  split: z.ZodEnum<{
495
495
  test: "test";
496
- train: "train";
497
496
  validation: "validation";
497
+ train: "train";
498
498
  }>;
499
499
  tasks: z.ZodArray<z.ZodObject<{
500
500
  v: z.ZodLiteral<1>;
@@ -506,8 +506,8 @@ export declare const TaskSetSnapshotV1Schema: z.ZodObject<{
506
506
  }>;
507
507
  split: z.ZodEnum<{
508
508
  test: "test";
509
- train: "train";
510
509
  validation: "validation";
510
+ train: "train";
511
511
  }>;
512
512
  category: z.ZodString;
513
513
  protected: z.ZodDefault<z.ZodBoolean>;
@@ -1,5 +1,10 @@
1
1
  import type { LaneLivenessWatchdogConfig } from '../config/schema.js';
2
- /** The five frozen defaults from the #2506 contract (0 disables a feature). */
2
+ /**
3
+ * The five frozen defaults from the #2506 contract (0 disables a feature).
4
+ * #3313 AC14 supersedes the #2506 AC1 default-off contract: `enabled` resolves
5
+ * `true` here because this constant parses `{}` through the schema whose field
6
+ * default flipped — no literal is pinned in this file, so it cannot drift.
7
+ */
3
8
  export declare const LANE_LIVENESS_WATCHDOG_DEFAULTS: LaneLivenessWatchdogConfig;
4
9
  /**
5
10
  * Upper bound on lane ids named in one `pr_workflow_lane_watchdog` event or
@@ -613,6 +613,18 @@ export interface PrWorkflowGateState {
613
613
  prReviewPartialBaseCoverage?: PrReviewPartialBaseCoverageRecord;
614
614
  prReviewCoverageDisclosurePath?: string;
615
615
  prReviewCoverageDisclosureDigest?: string;
616
+ /**
617
+ * Issue #3312: durable validation-phase skip disclosure persisted by the
618
+ * INCOMPLETE bypass arm in `completePrWorkflow` (a controller-derived
619
+ * projection of derived state — never a lane/model assertion). Mirrors the
620
+ * `PrReviewCompletionState` fields in `src/pr-review/completion.ts`; read by
621
+ * the completion report projection's disclosed-degradation leg only.
622
+ */
623
+ prReviewValidationSkipDisclosure?: PrReviewValidationSkipDisclosureRecord;
624
+ /** Issue #3312: durable path of the validation-skip-disclosure artifact. */
625
+ prReviewValidationSkipDisclosurePath?: string;
626
+ /** Issue #3312: sha256 of the validation-skip-disclosure artifact bytes. */
627
+ prReviewValidationSkipDisclosureDigest?: string;
616
628
  /**
617
629
  * Explicit per-dimension cancellations (issue #2383), written only by the
618
630
  * audited armed-recovery operation. A cancelled dimension is terminal for
@@ -1087,7 +1099,8 @@ export interface PrWorkflowStaleLaneSettlement {
1087
1099
  /**
1088
1100
  * Issue #2506 (G2): optional lane-liveness watchdog options for the on-demand
1089
1101
  * settlement entry points. The two-argument call shape every existing caller
1090
- * uses means "watchdog disabled" (the default-off config contract).
1102
+ * uses means no policy is threaded — the config contract threaded by the tool
1103
+ * wrappers applies (default-on since #3313 AC14).
1091
1104
  */
1092
1105
  export interface PrWorkflowLaneLivenessOptions {
1093
1106
  laneLivenessWatchdog?: LaneLivenessWatchdogConfig;
@@ -1667,6 +1680,36 @@ export declare function reserveActivePrReviewReentryAuthorization(directory: str
1667
1680
  role: PrReviewReentryRole;
1668
1681
  callID: string;
1669
1682
  }): Promise<PrReviewReentryAuthorizationRecord | null>;
1683
+ /**
1684
+ * Issue #3312 (U1): one skipped-phase entry in the INCOMPLETE bypass's durable
1685
+ * validation-skip disclosure. `unsettledItemIds` is bounded by
1686
+ * {@link MAX_SKIP_DISCLOSURE_UNSETTLED_ITEM_IDS} with a final `+N more`
1687
+ * marker when truncated.
1688
+ */
1689
+ interface PrReviewValidationSkipPhaseEntry {
1690
+ phase: 'reviewer' | 'critic' | 'council';
1691
+ reason: string;
1692
+ unsettledItemIds: string[];
1693
+ }
1694
+ /**
1695
+ * Issue #3312 (U1): the durable shape of
1696
+ * `.swarm/pr-review/<runId>/validation-skip-disclosure.json` and of the
1697
+ * `prReviewValidationSkipDisclosure` gate-state mirror. Structurally identical
1698
+ * to the `PrReviewCompletionState` mirror fields in `src/pr-review/completion.ts`
1699
+ * (the state schema is `.passthrough()`, so the fields survive persistence).
1700
+ */
1701
+ interface PrReviewValidationSkipDisclosureRecord {
1702
+ schemaVersion: number;
1703
+ runId: string;
1704
+ prHeadSha: string;
1705
+ revisionDigest: string;
1706
+ createdAt: string;
1707
+ coverageKind: 'COMPLETE' | 'PARTIAL';
1708
+ reportVerdict: 'INCOMPLETE';
1709
+ /** Feedback F6: set when the byte-degrade loop cut any phase's id list. */
1710
+ truncated?: boolean;
1711
+ skippedPhases: PrReviewValidationSkipPhaseEntry[];
1712
+ }
1670
1713
  export declare function completePrWorkflow(directory: string, sessionID: string, expectedMode: PrWorkflowMode, prHeadSha: string, options?: {
1671
1714
  reportVerdict?: PrReviewReportVerdict;
1672
1715
  /** Issue #2506: lane-liveness watchdog config for this settlement. */
@@ -1835,6 +1878,23 @@ export declare const _test_exports: {
1835
1878
  } | undefined;
1836
1879
  prReviewCoverageDisclosurePath?: string | undefined;
1837
1880
  prReviewCoverageDisclosureDigest?: string | undefined;
1881
+ prReviewValidationSkipDisclosurePath?: string | undefined;
1882
+ prReviewValidationSkipDisclosureDigest?: string | undefined;
1883
+ prReviewValidationSkipDisclosure?: {
1884
+ schemaVersion: 1;
1885
+ runId: string;
1886
+ prHeadSha: string;
1887
+ revisionDigest: string;
1888
+ createdAt: string;
1889
+ coverageKind: "COMPLETE" | "PARTIAL";
1890
+ reportVerdict: "INCOMPLETE";
1891
+ skippedPhases: {
1892
+ phase: "reviewer" | "critic" | "council";
1893
+ reason: string;
1894
+ unsettledItemIds: string[];
1895
+ }[];
1896
+ truncated?: boolean | undefined;
1897
+ } | undefined;
1838
1898
  prReviewDimensionCancellations?: Record<"intent-architecture" | "correctness-state" | "tests-falsifiability" | "security-trust" | "reliability-performance" | "compatibility-delivery", {
1839
1899
  reason: string;
1840
1900
  cancelledAt: string;