opencode-swarm 7.144.7 → 7.145.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 (86) hide show
  1. package/dist/cli/{capability-probe-976tt4ba.js → capability-probe-va4kk8vg.js} +2 -2
  2. package/dist/cli/{config-doctor-zdvaq4nb.js → config-doctor-dzsv3pqy.js} +2 -2
  3. package/dist/cli/{core-j7f118a5.js → core-qkh9me8x.js} +2 -2
  4. package/dist/cli/{curation-policy-a511r0qz.js → curation-policy-5x6346tf.js} +7 -7
  5. package/dist/cli/{curator-drift-ckjm272w.js → curator-drift-yn5d0mvq.js} +3 -3
  6. package/dist/cli/curator-llm-factory-q5p4578g.js +64 -0
  7. package/dist/cli/{curator-97sm8wn0.js → curator-zssndq5x.js} +34 -33
  8. package/dist/cli/dispatch-ndxbsk98.js +1 -1
  9. package/dist/cli/{evidence-summary-service-kwtb2d14.js → evidence-summary-service-dqcpapj8.js} +15 -14
  10. package/dist/cli/{gate-evidence-rk9j0hc4.js → gate-evidence-bkdqryqg.js} +9 -8
  11. package/dist/cli/guardrail-explain-kspf83x5.js +65 -0
  12. package/dist/cli/{guardrail-log-zbqf4ws6.js → guardrail-log-qg4sq6gr.js} +4 -4
  13. package/dist/cli/{hive-promoter-qzvtp5wx.js → hive-promoter-3h7dhnek.js} +34 -33
  14. package/dist/cli/{index-00fk9c3b.js → index-0jr9zn34.js} +1 -1
  15. package/dist/cli/{index-zq9gs0yk.js → index-0pcq32y2.js} +1 -1
  16. package/dist/cli/{index-gmdgap01.js → index-2dnqazyr.js} +1 -1
  17. package/dist/cli/{index-b44qqqt2.js → index-3g0xk6tk.js} +1 -1
  18. package/dist/cli/{index-yz0hfa4g.js → index-4e5a28h7.js} +2 -2
  19. package/dist/cli/index-4evasm2b.js +514 -0
  20. package/dist/cli/{index-jszgrk71.js → index-4zwjc9sb.js} +10 -29
  21. package/dist/cli/{index-x4q96ejx.js → index-6ezbzd5e.js} +2509 -1995
  22. package/dist/cli/{index-q7zy6dej.js → index-6hqhyb0f.js} +4 -4
  23. package/dist/cli/{index-9s8drsf9.js → index-6q3agdmr.js} +4 -21
  24. package/dist/cli/{index-hkdgkkhb.js → index-77ef8gye.js} +2 -2
  25. package/dist/cli/{index-bx20cv1v.js → index-7g276m9m.js} +2 -2
  26. package/dist/cli/{index-zy7f84cs.js → index-85gkedsf.js} +14 -5
  27. package/dist/cli/{index-7bvd5nh2.js → index-apjdytwx.js} +3 -3
  28. package/dist/cli/{index-pzsezhek.js → index-b3xret0a.js} +5 -5
  29. package/dist/cli/{index-qm0mz7rj.js → index-c13ttmak.js} +8 -8
  30. package/dist/cli/{index-d879g58v.js → index-e00wbqw5.js} +2 -2
  31. package/dist/cli/{index-cwtpqm5f.js → index-e1pxav9g.js} +1 -1
  32. package/dist/cli/{index-n4hwcsbd.js → index-ffdwj1an.js} +5 -5
  33. package/dist/cli/{index-vdha477y.js → index-fp464as8.js} +1 -1
  34. package/dist/cli/{index-c1cfsg9y.js → index-h4hasck4.js} +4 -4
  35. package/dist/cli/{index-39jbnhar.js → index-hfzcztv6.js} +36 -35
  36. package/dist/cli/{index-wknz5c8q.js → index-jy9bwa9k.js} +2 -2
  37. package/dist/cli/{index-xjgwr4c6.js → index-k6pdsct6.js} +1 -1
  38. package/dist/cli/{index-r2q0nd0a.js → index-kp87kr1a.js} +3 -3
  39. package/dist/cli/{index-w9bnt74s.js → index-mkks7jwg.js} +13 -15
  40. package/dist/cli/{index-f9vvg5xb.js → index-pa86tpgt.js} +67 -2
  41. package/dist/cli/{index-77h4xjn5.js → index-qfawexc8.js} +9 -9
  42. package/dist/cli/{index-grkev1g6.js → index-s6cwsnrw.js} +8 -8
  43. package/dist/cli/{index-h1p08s3n.js → index-s72naw1j.js} +1 -1
  44. package/dist/cli/{index-s1xefrx7.js → index-v64kjqvg.js} +19 -16
  45. package/dist/cli/{index-6z5jtf7d.js → index-wk54ey3h.js} +4 -4
  46. package/dist/cli/{index-x4eqd82b.js → index-zfhe7vbb.js} +1 -1
  47. package/dist/cli/{index-1jsmmx7y.js → index-zz5qsjd1.js} +64 -35
  48. package/dist/cli/index.js +34 -33
  49. package/dist/cli/{knowledge-escalator-fhc6ecbv.js → knowledge-escalator-w1mbaktt.js} +14 -13
  50. package/dist/cli/{knowledge-events-31g69mx2.js → knowledge-events-a0dj6gy6.js} +12 -11
  51. package/dist/cli/{knowledge-link-4cg4776a.js → knowledge-link-mzdjvjsd.js} +6 -6
  52. package/dist/cli/{knowledge-store-g389c1cy.js → knowledge-store-8kk3rghx.js} +7 -7
  53. package/dist/cli/{knowledge-validator-sng5xt5a.js → knowledge-validator-91ym56e0.js} +9 -9
  54. package/dist/cli/{pending-delegations-9h1jmtw1.js → pending-delegations-6vsrmw5w.js} +6 -6
  55. package/dist/cli/{pr-subscriptions-8pg34pev.js → pr-subscriptions-zc3skxde.js} +6 -6
  56. package/dist/cli/{runner-cqecp1na.js → runner-jj32v8bk.js} +8 -7
  57. package/dist/cli/{scan-cursor-qm3tsvvw.js → scan-cursor-12jxwd14.js} +8 -8
  58. package/dist/cli/{schema-vnghba3d.js → schema-nq9tcz87.js} +1 -1
  59. package/dist/cli/{scope-persistence-k9mqd414.js → scope-persistence-dv6z7n08.js} +8 -7
  60. package/dist/cli/{skill-generator-v1wdh3ne.js → skill-generator-drscnzq9.js} +16 -15
  61. package/dist/cli/{telemetry-cybx6cfz.js → telemetry-z54dgdrh.js} +1 -1
  62. package/dist/cli/{workspace-snapshot-d89zm6wm.js → workspace-snapshot-q21mgbsh.js} +2 -2
  63. package/dist/cli/{worktree-collision-ownership-vy0kxa98.js → worktree-collision-ownership-rfyyjjct.js} +9 -9
  64. package/dist/cli/{worktree-isolation-bxt3rftm.js → worktree-isolation-4tehtym5.js} +34 -33
  65. package/dist/cli/{worktree-provisioning-owner-zzkjycp1.js → worktree-provisioning-owner-72cyddz5.js} +3 -3
  66. package/dist/commands/close.d.ts +8 -1
  67. package/dist/config/evidence-schema.d.ts +6 -6
  68. package/dist/config/plan-schema.d.ts +2 -2
  69. package/dist/config/schema.d.ts +7 -7
  70. package/dist/evidence/task-file.d.ts +16 -16
  71. package/dist/git/branch.d.ts +9 -0
  72. package/dist/hooks/delegation-gate/worktree-isolation.d.ts +5 -0
  73. package/dist/index.js +561 -531
  74. package/dist/memory/schema.d.ts +3 -3
  75. package/dist/observability/catalog.d.ts +5 -4
  76. package/dist/observability/envelope.d.ts +2 -2
  77. package/dist/sandbox/executor.d.ts +6 -0
  78. package/dist/services/swarm-residue.d.ts +151 -0
  79. package/dist/telemetry.d.ts +20 -1
  80. package/dist/tools/knowledge-receipt.d.ts +1 -1
  81. package/dist/utils/atomic-write.d.ts +185 -0
  82. package/package.json +1 -1
  83. package/dist/cli/curator-llm-factory-eny079d1.js +0 -63
  84. package/dist/cli/guardrail-explain-8gggptqj.js +0 -64
  85. package/dist/cli/{index-f36ybbsv.js → index-b30x236n.js} +3 -3
  86. package/dist/cli/{index-fv0s19g9.js → index-w8pgjr75.js} +3 -3
@@ -48,8 +48,8 @@ export declare const MemoryKindSchema: z.ZodEnum<{
48
48
  }>;
49
49
  export declare const MemorySourceSchema: z.ZodObject<{
50
50
  type: z.ZodEnum<{
51
- file: "file";
52
51
  agent: "agent";
52
+ file: "file";
53
53
  tool: "tool";
54
54
  manual: "manual";
55
55
  test: "test";
@@ -113,8 +113,8 @@ export declare const MemoryRecordSchema: z.ZodObject<{
113
113
  }>;
114
114
  source: z.ZodObject<{
115
115
  type: z.ZodEnum<{
116
- file: "file";
117
116
  agent: "agent";
117
+ file: "file";
118
118
  tool: "tool";
119
119
  manual: "manual";
120
120
  test: "test";
@@ -203,8 +203,8 @@ export declare const MemoryProposalSchema: z.ZodObject<{
203
203
  }>;
204
204
  source: z.ZodObject<{
205
205
  type: z.ZodEnum<{
206
- file: "file";
207
206
  agent: "agent";
207
+ file: "file";
208
208
  tool: "tool";
209
209
  manual: "manual";
210
210
  test: "test";
@@ -1,15 +1,16 @@
1
1
  /**
2
2
  * The event catalog (issue #2029).
3
3
  *
4
- * Exactly 43 entries, matching the `TelemetryEvent` union at
4
+ * Exactly 44 entries, matching the `TelemetryEvent` union at
5
5
  * `src/telemetry.ts:15-92`. Thirty-eight predate the #2029 contract; the 39th is
6
6
  * `agent_conflict_detected` (previously emitted through a force-cast past the
7
7
  * type system), the 40th is `close_archive_result` (issue #2030 — the
8
8
  * structured close/archive result event), the 41st is the bounded diagnostic
9
9
  * projection of authoritative knowledge-receipt transitions (issue #2031).
10
10
  * The 42nd is the human-only `knowledge_maintenance` quarantine audit
11
- * (issue #2033), and the 43rd is the aggregate `context_pruned` transcript
12
- * mutation audit. These late additions are instances of
11
+ * (issue #2033), the 43rd is the aggregate `context_pruned` transcript
12
+ * mutation audit, and the 44th is the bounded `residue_health` atomic-write
13
+ * residue audit (issue #2035). These late additions are instances of
13
14
  * the defect class this contract exists to close: an event kind entering the
14
15
  * stream with no registration.
15
16
  *
@@ -64,7 +65,7 @@ export interface CatalogEntry {
64
65
  /**
65
66
  * Whether an event of this kind must carry `trace.parentSpanId`.
66
67
  *
67
- * `false` for all 43 entries today, and that is a truthful statement about
68
+ * `false` for all 44 entries today, and that is a truthful statement about
68
69
  * the current system rather than a placeholder: no producer supplies a
69
70
  * parent span, so `createObservation` never sets one. Setting this to `true`
70
71
  * for a kind whose producer cannot supply a parent would make every
@@ -38,11 +38,11 @@ export declare const EventCategorySchema: z.ZodEnum<{
38
38
  export type EventCategory = z.infer<typeof EventCategorySchema>;
39
39
  /** Syslog-shaped severity ladder. */
40
40
  export declare const EventSeveritySchema: z.ZodEnum<{
41
- error: "error";
42
41
  debug: "debug";
43
42
  info: "info";
44
43
  notice: "notice";
45
44
  warning: "warning";
45
+ error: "error";
46
46
  critical: "critical";
47
47
  }>;
48
48
  export type EventSeverity = z.infer<typeof EventSeveritySchema>;
@@ -297,11 +297,11 @@ export declare const ObservabilityEventSchema: z.ZodObject<{
297
297
  unrecognized: "unrecognized";
298
298
  }>;
299
299
  severity: z.ZodEnum<{
300
- error: "error";
301
300
  debug: "debug";
302
301
  info: "info";
303
302
  notice: "notice";
304
303
  warning: "warning";
304
+ error: "error";
305
305
  critical: "critical";
306
306
  }>;
307
307
  occurredAt: z.ZodString;
@@ -19,6 +19,12 @@ export declare class SandboxError extends Error {
19
19
  * sandbox command syntax on any platform.
20
20
  */
21
21
  export declare function isValidEnvKey(key: string): boolean;
22
+ /**
23
+ * Returns true when `key` belongs to one of the env-var families that must
24
+ * never be sourced from a repo-resident (untrusted) env file.
25
+ * See `UNTRUSTED_ENV_KEY_PREFIXES` for the rationale.
26
+ */
27
+ export declare function isUntrustedEnvKey(key: string): boolean;
22
28
  /**
23
29
  * Interface for platform-specific sandbox executors.
24
30
  */
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Shared atomic-write residue surface (issue #2035): read-only inventory,
3
+ * gated recoverable quarantine, manifest-backed rollback, and the ONE
4
+ * formatter every reporting surface (close clean stage, close dry-run,
5
+ * config doctor, diagnose) renders from — so close and doctor report the
6
+ * same inventory from a shared implementation by construction.
7
+ *
8
+ * Safety contract (issue #2035 reqs 4-7):
9
+ * - The scanner never traverses outside the canonical project `.swarm/`
10
+ * root, never follows symlinks (Dirent + lstat only), never infers
11
+ * ownership from content, and never reads content except a bounded
12
+ * sha256 at quarantine time.
13
+ * - Quarantine MOVES (never deletes) only verified stale residue: exact
14
+ * registered-grammar match with an instance token, age ≥
15
+ * RESIDUE_STALE_AGE_MS, git-untracked, non-symlink, no active lock,
16
+ * size ≤ RESIDUE_HASH_MAX_BYTES, parsed target present, and unchanged
17
+ * (mtime+size) between scan and move (TOCTOU re-check — a lockless
18
+ * writer still filling its temp mutates these).
19
+ * - Everything else — recent, active, tracked, ambiguous, constant-name,
20
+ * malformed, unmatched, outside-root — is PRESERVED and reported.
21
+ * - Rollback is exact, manifest-verified, and idempotent.
22
+ */
23
+ import { type SwarmTempGrammar } from '../utils/atomic-write';
24
+ /** Age gate: a temp older than this is "old". 30 min exceeds any legitimate
25
+ * single bounded write (≤256 MiB + AV/rename-retry adds seconds), while still
26
+ * catching session-old residue at close time. */
27
+ export declare const RESIDUE_STALE_AGE_MS: number;
28
+ /** Bounded scan: stop (and report `truncated`) beyond this many entries. */
29
+ export declare const MAX_RESIDUE_SCAN_ENTRIES = 20000;
30
+ /** Bounded scan depth below `.swarm/`. */
31
+ export declare const RESIDUE_SCAN_DEPTH = 8;
32
+ /** Hash/move bound per residue file. Larger candidates are reported only. */
33
+ export declare const RESIDUE_HASH_MAX_BYTES: number;
34
+ /** `.swarm/` immediate-child subtrees the scanner never descends into. */
35
+ export declare const RESIDUE_SKIP_DIRS: readonly string[];
36
+ export interface ResidueEntry {
37
+ /** Path relative to the `.swarm/` root (never absolute — no path leak). */
38
+ relPath: string;
39
+ grammarId: string;
40
+ grammarEra: SwarmTempGrammar['era'];
41
+ bytes: number;
42
+ mtimeMs: number;
43
+ ageMs: number;
44
+ isSymlink: boolean;
45
+ tracked: 'tracked' | 'untracked' | 'unknown';
46
+ lockHeld: boolean;
47
+ proposedAction: 'quarantine' | 'report_only';
48
+ reasons: readonly string[];
49
+ }
50
+ export interface ResidueInventorySummary {
51
+ matched: number;
52
+ eligible: number;
53
+ ambiguous: number;
54
+ totalBytes: number;
55
+ oldestAgeMs: number;
56
+ }
57
+ export interface ResidueInventory {
58
+ swarmRoot: string;
59
+ scannedEntries: number;
60
+ truncated: boolean;
61
+ /** Oldest first. Constant-name grammar hits are included only when stale. */
62
+ entries: readonly ResidueEntry[];
63
+ summary: ResidueInventorySummary;
64
+ gitState: 'ok' | 'unknown';
65
+ }
66
+ /**
67
+ * Test seam (repo `_internals` convention — never mock.module). `now` drives
68
+ * age math; `queryTracked`/`activeLockTargets` isolate the git/lock signals.
69
+ */
70
+ export declare const _internals: {
71
+ now: () => number;
72
+ /** Rename seam for the per-entry guarded move (PRR-005 regression tests). */
73
+ renameResidueEntry: (from: string, to: string) => void;
74
+ queryTracked: (projectRoot: string, swarmRoot: string) => {
75
+ tracked: Set<string> | undefined;
76
+ };
77
+ activeLockTargets: (directory: string) => Set<string>;
78
+ sha256File: (absPath: string) => string;
79
+ };
80
+ /** Read-only inventory of registered-grammar residue under `<directory>/.swarm`. */
81
+ export declare function inventorySwarmResidue(directory: string): Promise<ResidueInventory>;
82
+ export interface QuarantineManifestEntry {
83
+ original_rel_path: string;
84
+ stored_rel_path: string;
85
+ sha256: string;
86
+ bytes: number;
87
+ mtime_ms: number;
88
+ grammar_id: string;
89
+ reason: string;
90
+ }
91
+ export interface QuarantineManifest {
92
+ /**
93
+ * Manifest format version. Forward-compat POLICY (PR review PRR-009):
94
+ * rollback hard-rejects any version it does not know — a FUTURE schema
95
+ * bump MUST ship its own reader/migration before (or with) the writer,
96
+ * because payloads on disk are only recoverable through a manifest the
97
+ * current code can parse. Deliberate design: a partial-reader migration
98
+ * is more dangerous than a readable "unsupported manifest shape" error
99
+ * naming the version. Mixed-version operation is therefore unsafe by
100
+ * construction across schema bumps: downgrade with v2 batches present
101
+ * blocks rollback of those batches until the newer plugin returns.
102
+ */
103
+ schema_version: 1;
104
+ batch_id: string;
105
+ created_at: string;
106
+ trigger: string;
107
+ entries: QuarantineManifestEntry[];
108
+ }
109
+ export interface QuarantineOutcomeItem {
110
+ relPath: string;
111
+ status: 'quarantined' | 'preserved';
112
+ reasons: readonly string[];
113
+ }
114
+ export interface QuarantineResult {
115
+ inventory: ResidueInventory;
116
+ /** Batch dir relative to `.swarm/` — undefined when nothing was moved. */
117
+ batchRelDir?: string;
118
+ quarantined: number;
119
+ /** report_only entries preserved at their original location. */
120
+ preserved: readonly QuarantineOutcomeItem[];
121
+ }
122
+ /**
123
+ * Quarantine verified stale residue (moves only — never deletes). Callers
124
+ * that can mutate pass an explicit trigger; `dryRun: true` returns the exact
125
+ * plan without touching the filesystem (preview/confirmation path).
126
+ */
127
+ export declare function quarantineSwarmResidue(directory: string, options?: {
128
+ trigger?: string;
129
+ dryRun?: boolean;
130
+ }): Promise<QuarantineResult>;
131
+ export interface RollbackOutcomeItem {
132
+ relPath: string;
133
+ status: 'restored' | 'already-restored' | 'collision' | 'missing-copy';
134
+ }
135
+ export interface RollbackResult {
136
+ batchRelDir: string;
137
+ items: readonly RollbackOutcomeItem[];
138
+ /** True when every manifest entry resolved and the batch dir was removed. */
139
+ drained: boolean;
140
+ }
141
+ /**
142
+ * Roll back a quarantine batch (default: latest). Idempotent and
143
+ * order-independent across batches: an occupied original is compared by
144
+ * checksum — identical copies are dropped (already restored), differing
145
+ * content is left in place and reported as a collision, never overwritten.
146
+ */
147
+ export declare function rollbackResidueQuarantine(directory: string, batchId?: string): Promise<RollbackResult>;
148
+ /** Bounded human rendering of an inventory (≤ maxEntries detail lines). */
149
+ export declare function formatResidueInventoryLines(inv: ResidueInventory, options?: {
150
+ maxEntries?: number;
151
+ }): string[];
@@ -26,7 +26,7 @@ export type TelemetryEvent = 'session_started' | 'session_ended' | 'agent_activa
26
26
  * `prm_hard_stop` TRIGGER emitted by `src/prm/escalation.ts`. A trigger with
27
27
  * no matching delivery means the containment never reached the agent.
28
28
  */
29
- | 'prm_hard_stop_delivered' | 'agent_conflict_detected' | 'close_archive_result' | 'knowledge_receipt_transition' | 'knowledge_maintenance';
29
+ | 'prm_hard_stop_delivered' | 'agent_conflict_detected' | 'close_archive_result' | 'knowledge_receipt_transition' | 'knowledge_maintenance' | 'residue_health';
30
30
  /** Stable classification for how a reviewer-gate decision was established. */
31
31
  export type ReviewerGateEvidenceKind = 'genuine' | 'fallback' | 'data_quality' | 'block';
32
32
  /**
@@ -206,6 +206,25 @@ export declare const telemetry: {
206
206
  };
207
207
  }>;
208
208
  }): void;
209
+ /**
210
+ * Atomic-write residue health (issue #2035). Emitted after a residue
211
+ * quarantine run (close clean stage / doctor flag). Bounded payload:
212
+ * counts, one bounded age figure, total bytes, and per-grammar counts
213
+ * keyed by the frozen registry ids — never file names, paths, or content,
214
+ * enabling later reporting (PR 16/19) without leaking workspace layout.
215
+ */
216
+ residueHealth(data: {
217
+ trigger: string;
218
+ scanned: number;
219
+ matched: number;
220
+ eligible: number;
221
+ ambiguous: number;
222
+ quarantined: number;
223
+ preserved: number;
224
+ total_bytes: number;
225
+ oldest_age_ms: number;
226
+ grammar_counts: Record<string, number>;
227
+ }): void;
209
228
  /**
210
229
  * Issue #2063 C2 — the PRM hard-stop DENIAL was actually delivered to the
211
230
  * agent (thrown by the guardrails `toolBefore` consumer). `prm_hard_stop`
@@ -17,8 +17,8 @@ import { createSwarmTool } from './create-tool.js';
17
17
  declare const ignoredItem: z.ZodObject<{
18
18
  id: z.ZodString;
19
19
  reason: z.ZodEnum<{
20
- other: "other";
21
20
  stale: "stale";
21
+ other: "other";
22
22
  superseded: "superseded";
23
23
  unsafe: "unsafe";
24
24
  too_generic: "too_generic";
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Canonical atomic-write helper + temp-grammar registry (issue #2035).
3
+ *
4
+ * Single source of truth for:
5
+ * - HOW production code atomically writes files under the project `.swarm/`
6
+ * root: one same-directory write-temp→fsync→rename helper with exact
7
+ * `finally` cleanup of its OWN temp only.
8
+ * - WHAT temporary-file name grammars exist: a frozen registry derived from
9
+ * the writer census so residue scanners classify candidates by exact
10
+ * registered grammars instead of substring guesses.
11
+ *
12
+ * Why the registry lives here: every residue consumer (close clean stage,
13
+ * close dry-run, config doctor, diagnose, quarantine/rollback in
14
+ * `src/services/swarm-residue.ts`) must derive candidates from the SAME
15
+ * registered grammars, and every atomic writer must be classifiable against
16
+ * the same table (see `WRITER_CLASSIFICATION` and its ratchet test).
17
+ *
18
+ * Containment contract (issue #2035 req 1): the canonical target must live
19
+ * under a `.swarm/` root, determined by SPELLING — the nearest `.swarm` path
20
+ * segment between the filesystem root and the target. A pre-existing root
21
+ * must be a real directory (no symlinks), and no path segment between it and
22
+ * the target may be a symlink. Semantics are validateSwarmPath-INSPIRED but
23
+ * NOT identical — see the junction limitation on
24
+ * `assertSwarmContainedTarget`.
25
+ */
26
+ import * as fs from 'node:fs';
27
+ /**
28
+ * A registered temporary-file naming grammar.
29
+ *
30
+ * `match` is applied to the temp file's BASENAME only, case-sensitively —
31
+ * near-misses (unicode/case variants, trailing dots, ADS suffixes) must NOT
32
+ * match, so they are preserved untouched by every scanner.
33
+ */
34
+ export interface SwarmTempGrammar {
35
+ /** Stable id used in reports, manifests, and telemetry (never renamed). */
36
+ readonly id: string;
37
+ readonly era: 'canonical' | 'current' | 'legacy';
38
+ /** Matches the temp basename. Capture group 1 = derivable target basename when `parsesTarget`. */
39
+ readonly match: RegExp;
40
+ /** The grammar embeds a per-invocation uniqueness token (ts/pid/uuid/random). */
41
+ readonly token: 'instance' | 'constant';
42
+ /** Trusted for quarantine when all eligibility gates pass (issue #2035 req 5). */
43
+ readonly quarantineEligible: boolean;
44
+ /** Whether a target basename can be parsed back out of the temp name. */
45
+ readonly parsesTarget: boolean;
46
+ /** Producing writer sites (file:line) — every known producer is listed. */
47
+ readonly producers: readonly string[];
48
+ /** Invariant reason the producer is NOT migrated to the canonical helper. */
49
+ readonly note?: string;
50
+ }
51
+ /**
52
+ * Every temp grammar a swarm writer has ever produced. Grammars marked
53
+ * `quarantineEligible: false` are constant-name temps: with no per-invocation
54
+ * token they are indistinguishable from an in-flight writer of ANY process or
55
+ * from an unrelated file, so scanners report them but never mutate them.
56
+ * ORDER MATTERS: `matchTempGrammar`/`parseTargetBasename` take the FIRST
57
+ * match, so more-specific grammars (uuid, two-token, .json-terminated) must
58
+ * be declared before the generic single-token family.
59
+ */
60
+ export declare const SWARM_TEMP_GRAMMARS: readonly SwarmTempGrammar[];
61
+ /** First registered grammar whose regex matches `basename`, or undefined. */
62
+ export declare function matchTempGrammar(basename: string): SwarmTempGrammar | undefined;
63
+ /**
64
+ * Parse the target basename a temp name was derived from (capture group 1).
65
+ * Returns null for prefix/leading-dot grammars with no derivable target.
66
+ */
67
+ export declare function parseTargetBasename(basename: string): string | null;
68
+ /**
69
+ * Structural classification of every file that constructs temp-file names
70
+ * (ratchet source for tests/unit/utils/atomic-write.test.ts — a new temp
71
+ * constructor must be classified here or the build fails):
72
+ * - migrated: writes through the canonical helper (registry lists its
73
+ * grammar only for historical residue discovery)
74
+ * - registered-bespoke: keeps a dedicated writer with a documented invariant
75
+ * reason in the grammar `note` (issue #2035 req 2)
76
+ * - external: writes outside the `.swarm` containment boundary
77
+ * - reader-only: references temp names without constructing them
78
+ */
79
+ export declare const WRITER_CLASSIFICATION: Readonly<Record<string, 'migrated' | 'registered-bespoke' | 'external' | 'reader-only'>>;
80
+ /**
81
+ * Max depth considered when reasoning about `.swarm` path segments (advisory
82
+ * constant kept for diagnostics; containment itself is spelling-based).
83
+ */
84
+ export declare const MAX_SWARM_ANCESTOR_DEPTH = 8;
85
+ export interface SwarmContainment {
86
+ /** Project root that owns the `.swarm/` directory. */
87
+ projectRoot: string;
88
+ /** Canonical `.swarm/` directory containing the target. */
89
+ swarmRoot: string;
90
+ }
91
+ /**
92
+ * Reject obviously-invalid target spellings before any filesystem access:
93
+ * glob metacharacters, control chars/NUL, and unresolved environment-variable
94
+ * forms (`$VAR`, `%VAR%`, leading `~`). Quarantine/inventory paths and writer
95
+ * paths share this gate (issue #2035 req 7).
96
+ */
97
+ export declare function assertWellFormedTargetPath(targetPath: string): void;
98
+ /**
99
+ * Assert `targetPath` lives beneath a `.swarm/` root.
100
+ *
101
+ * The root is determined by SPELLING: the nearest `.swarm` path segment
102
+ * between the filesystem root and the target. Existence-based ancestor
103
+ * walking is deliberately avoided — a stray `.swarm` in an ancestor (e.g. the
104
+ * OS temp dir) would hijack the walk and reject legitimate first-writes whose
105
+ * own `.swarm` parent does not exist yet (invariant 4: ambiguous ancestor
106
+ * `.swarm` state fails closed). If the `.swarm` root exists it must be a real
107
+ * directory (no symlink), and no existing path segment between it and the
108
+ * target may be a symlink.
109
+ *
110
+ * KNOWN LIMITATION vs `validateSwarmPath` (src/hooks/utils.ts:157, PR review
111
+ * PRR-007): this check detects SYMLINKS via lstatSync().isSymbolicLink(),
112
+ * which returns FALSE for Windows directory JUNCTIONS (a distinct reparse
113
+ * class). validateSwarmPath resolves all reparse points via realpathSync. A
114
+ * junctioned `.swarm/` therefore passes this spelling-based gate. Mitigations
115
+ * in scope: junctions require same-user filesystem write access to create
116
+ * (outside the adversarial-local-process threat model invariant 4 excludes),
117
+ * targets are still spelling-bounded to the `.swarm` subtree, and the
118
+ * spell-time `.swarm` position must already exist in the user's path. Full
119
+ * junction parity would require realpath-resolution of every existing
120
+ * ancestor — deliberately out of budget for the write hot path.
121
+ *
122
+ * Project-boundary enforcement (`.git`/`.opencode` markers, invariant 4) is
123
+ * deliberately NOT re-checked here: that belongs to the tool-layer
124
+ * resolvers (`resolveWorkingDirectory`/`assertProjectRoot`), which have
125
+ * already validated the directory before any writer derived a target from
126
+ * it — validateSwarmPath applies the same split.
127
+ */
128
+ export declare function assertSwarmContainedTarget(targetPath: string): SwarmContainment;
129
+ /** Hard bound on a single atomic write (bounded-write requirement). */
130
+ export declare const MAX_ATOMIC_WRITE_BYTES: number;
131
+ export interface AtomicWriteOptions {
132
+ /** Skip the pre-rename fsync (tests / truly ephemeral data). */
133
+ readonly skipFsync?: boolean;
134
+ /**
135
+ * Override the bounded-write cap (default MAX_ATOMIC_WRITE_BYTES). Exposed
136
+ * so the bound itself is testable without allocating 256 MiB.
137
+ */
138
+ readonly maxBytes?: number;
139
+ }
140
+ /**
141
+ * Dependency-injection seam for failure-injection tests (repo convention;
142
+ * never mock.module — it leaks across bun:test files). Restore in afterEach.
143
+ *
144
+ * The defaults DELEGATE to the live `fs` namespace on every call (instead of
145
+ * capturing the function at module load) so sibling tests that patch
146
+ * `node:fs` via `mock.module` — while still calling through to the real
147
+ * implementation — observe these calls, matching the recording patterns in
148
+ * tests/unit/commands/atomic-writes.test.ts.
149
+ */
150
+ export declare const _internals: {
151
+ randomSuffix: () => string;
152
+ writeSync: (fd: number, buffer: Uint8Array, offset: number, length: number) => number;
153
+ renameSync: (from: string, to: string) => ReturnType<typeof fs.renameSync>;
154
+ unlinkSync: (p: string) => ReturnType<typeof fs.unlinkSync>;
155
+ fsyncSync: (fd: number) => ReturnType<typeof fs.fsyncSync>;
156
+ };
157
+ /**
158
+ * Canonical atomic write under the project `.swarm/` root (issue #2035 req 1):
159
+ * contained target, unique non-predictable same-directory temp, bounded write,
160
+ * fsync+close where supported, platform-safe replace (bounded rename retry on
161
+ * Windows transient locks — never unlink-then-rename, which would break
162
+ * atomicity), and exact finally cleanup of this invocation's temp only.
163
+ *
164
+ * The payload is bounded (≤ MAX_ATOMIC_WRITE_BYTES), so the synchronous
165
+ * temp-write core is the same latency class as the previous per-caller
166
+ * write-temp implementations; the async signature preserves caller shapes.
167
+ */
168
+ export declare function atomicWriteSwarmFile(targetPath: string, content: string | Uint8Array, options?: AtomicWriteOptions): Promise<void>;
169
+ /** Synchronous variant of {@link atomicWriteSwarmFile} (same core). */
170
+ export declare function atomicWriteSwarmFileSync(targetPath: string, content: string | Uint8Array, options?: AtomicWriteOptions): void;
171
+ /**
172
+ * Canonical atomic write WITHOUT the `.swarm` containment requirement.
173
+ *
174
+ * Documented invariant reason this variant exists (issue #2035 req 2): the
175
+ * legacy shared writer `atomicWriteFile` (src/evidence/task-file.ts) serves
176
+ * DUAL destinations — `.swarm/evidence/**` files AND the linked/hive
177
+ * knowledge stores whose platform-data/link directories live OUTSIDE any
178
+ * `.swarm` root (src/hooks/knowledge-store.ts, knowledge-link.ts,
179
+ * memory-link.ts, family migrations). Those callers migrate to this variant
180
+ * so they still gain the canonical grammar, fsync, bounded retry, exact
181
+ * own-temp cleanup, and cache invalidation — everything except root
182
+ * containment, which their destinations make inapplicable. New `.swarm`
183
+ * callers MUST use {@link atomicWriteSwarmFile}.
184
+ */
185
+ export declare function atomicWriteFileAnyRoot(targetPath: string, content: string | Uint8Array, options?: AtomicWriteOptions): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.144.7",
3
+ "version": "7.145.0",
4
4
  "description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,63 +0,0 @@
1
- // @bun
2
- import {
3
- createCuratorLLMDelegate
4
- } from "./index-x4q96ejx.js";
5
- import"./index-gmdgap01.js";
6
- import"./index-00fk9c3b.js";
7
- import"./index-s1xefrx7.js";
8
- import"./index-134d35c1.js";
9
- import"./index-abtrcs16.js";
10
- import"./index-6z5jtf7d.js";
11
- import"./index-wknz5c8q.js";
12
- import"./index-y8552snf.js";
13
- import"./index-d879g58v.js";
14
- import"./index-70ha9e09.js";
15
- import"./index-c8s9a3zh.js";
16
- import"./index-9ss2m4rs.js";
17
- import"./index-f36ybbsv.js";
18
- import"./index-hkdgkkhb.js";
19
- import"./index-w9bnt74s.js";
20
- import"./index-pzsezhek.js";
21
- import"./index-c1cfsg9y.js";
22
- import"./index-vdha477y.js";
23
- import"./index-rtry5xyf.js";
24
- import"./index-zsrtt42s.js";
25
- import"./index-n4hwcsbd.js";
26
- import"./index-cwtpqm5f.js";
27
- import"./index-grkev1g6.js";
28
- import"./index-q7zy6dej.js";
29
- import"./index-jszgrk71.js";
30
- import"./index-7bvd5nh2.js";
31
- import"./index-556ja8an.js";
32
- import"./index-7sy3aa9m.js";
33
- import"./index-wx8zdh4a.js";
34
- import"./index-b44qqqt2.js";
35
- import"./index-zy7f84cs.js";
36
- import"./index-77h4xjn5.js";
37
- import"./index-qm0mz7rj.js";
38
- import"./index-bx20cv1v.js";
39
- import"./index-gprxjmm7.js";
40
- import"./index-n832052r.js";
41
- import"./index-fv0s19g9.js";
42
- import"./index-z6xqpmqg.js";
43
- import"./index-zq9gs0yk.js";
44
- import"./index-x4eqd82b.js";
45
- import"./index-v3y3qg48.js";
46
- import"./index-9e6fdz2h.js";
47
- import"./index-4rhhvd1a.js";
48
- import"./index-zjygnfay.js";
49
- import"./index-ae75rja9.js";
50
- import"./index-h1p08s3n.js";
51
- import"./index-9s8drsf9.js";
52
- import"./index-ed5ykebp.js";
53
- import"./index-bk5tah7q.js";
54
- import"./index-f9vvg5xb.js";
55
- import"./index-1jsmmx7y.js";
56
- import"./index-7g4c7s5r.js";
57
- import"./index-bpmtbmy9.js";
58
- import"./index-zj6t9zgx.js";
59
- import"./index-zgwm4ryv.js";
60
- import"./index-a76rekgs.js";
61
- export {
62
- createCuratorLLMDelegate
63
- };
@@ -1,64 +0,0 @@
1
- // @bun
2
- import {
3
- handleGuardrailExplain
4
- } from "./index-yz0hfa4g.js";
5
- import"./index-x4q96ejx.js";
6
- import"./index-gmdgap01.js";
7
- import"./index-00fk9c3b.js";
8
- import"./index-s1xefrx7.js";
9
- import"./index-134d35c1.js";
10
- import"./index-abtrcs16.js";
11
- import"./index-6z5jtf7d.js";
12
- import"./index-wknz5c8q.js";
13
- import"./index-y8552snf.js";
14
- import"./index-d879g58v.js";
15
- import"./index-70ha9e09.js";
16
- import"./index-c8s9a3zh.js";
17
- import"./index-9ss2m4rs.js";
18
- import"./index-f36ybbsv.js";
19
- import"./index-hkdgkkhb.js";
20
- import"./index-w9bnt74s.js";
21
- import"./index-pzsezhek.js";
22
- import"./index-c1cfsg9y.js";
23
- import"./index-vdha477y.js";
24
- import"./index-rtry5xyf.js";
25
- import"./index-zsrtt42s.js";
26
- import"./index-n4hwcsbd.js";
27
- import"./index-cwtpqm5f.js";
28
- import"./index-grkev1g6.js";
29
- import"./index-q7zy6dej.js";
30
- import"./index-jszgrk71.js";
31
- import"./index-7bvd5nh2.js";
32
- import"./index-556ja8an.js";
33
- import"./index-7sy3aa9m.js";
34
- import"./index-wx8zdh4a.js";
35
- import"./index-b44qqqt2.js";
36
- import"./index-zy7f84cs.js";
37
- import"./index-77h4xjn5.js";
38
- import"./index-qm0mz7rj.js";
39
- import"./index-bx20cv1v.js";
40
- import"./index-gprxjmm7.js";
41
- import"./index-n832052r.js";
42
- import"./index-fv0s19g9.js";
43
- import"./index-z6xqpmqg.js";
44
- import"./index-zq9gs0yk.js";
45
- import"./index-x4eqd82b.js";
46
- import"./index-v3y3qg48.js";
47
- import"./index-9e6fdz2h.js";
48
- import"./index-4rhhvd1a.js";
49
- import"./index-zjygnfay.js";
50
- import"./index-ae75rja9.js";
51
- import"./index-h1p08s3n.js";
52
- import"./index-9s8drsf9.js";
53
- import"./index-ed5ykebp.js";
54
- import"./index-bk5tah7q.js";
55
- import"./index-f9vvg5xb.js";
56
- import"./index-1jsmmx7y.js";
57
- import"./index-7g4c7s5r.js";
58
- import"./index-bpmtbmy9.js";
59
- import"./index-zj6t9zgx.js";
60
- import"./index-zgwm4ryv.js";
61
- import"./index-a76rekgs.js";
62
- export {
63
- handleGuardrailExplain
64
- };
@@ -1,11 +1,11 @@
1
1
  // @bun
2
+ import {
3
+ bunSpawn
4
+ } from "./index-zj6t9zgx.js";
2
5
  import {
3
6
  init_git_executable,
4
7
  resolveGitExecutable
5
8
  } from "./index-9e6fdz2h.js";
6
- import {
7
- bunSpawn
8
- } from "./index-zj6t9zgx.js";
9
9
 
10
10
  // src/background/workspace-snapshot.ts
11
11
  import * as child_process from "child_process";
@@ -2,12 +2,12 @@
2
2
  import {
3
3
  SwarmError
4
4
  } from "./index-z6xqpmqg.js";
5
- import {
6
- readCachedTextFile
7
- } from "./index-ed5ykebp.js";
8
5
  import {
9
6
  bunFile
10
7
  } from "./index-zj6t9zgx.js";
8
+ import {
9
+ readCachedTextFile
10
+ } from "./index-ed5ykebp.js";
11
11
  import {
12
12
  warn
13
13
  } from "./index-zgwm4ryv.js";