opencode-swarm 7.139.3 → 7.139.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 (79) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/{config-doctor-75qky762.js → config-doctor-jgv6h8hd.js} +6 -6
  3. package/dist/cli/{core-nn8ffy5h.js → core-aj5g7an6.js} +4 -4
  4. package/dist/cli/{curation-policy-f46tf3dw.js → curation-policy-9a8xmh4x.js} +7 -7
  5. package/dist/cli/{curator-drift-r52hjskk.js → curator-drift-49p3jnte.js} +6 -6
  6. package/dist/cli/curator-llm-factory-7c5s2cdm.js +61 -0
  7. package/dist/cli/{curator-m6mk2v1n.js → curator-xhzdk0qy.js} +39 -39
  8. package/dist/cli/{dispatch-nbv0hezh.js → dispatch-2s23fbcs.js} +3 -3
  9. package/dist/cli/{evidence-summary-service-sxcq5nrt.js → evidence-summary-service-g82bsjqa.js} +16 -16
  10. package/dist/cli/{gate-evidence-1982qswy.js → gate-evidence-72cgrvs2.js} +6 -5
  11. package/dist/cli/guardrail-explain-vw1kz4k1.js +62 -0
  12. package/dist/cli/{guardrail-log-320grggj.js → guardrail-log-j91e1s6q.js} +8 -8
  13. package/dist/cli/{hive-promoter-v4w7cjvk.js → hive-promoter-5rk01jea.js} +39 -39
  14. package/dist/cli/{index-jqn332jx.js → index-0cyqmr36.js} +2 -2
  15. package/dist/cli/{index-5syvwd8g.js → index-0xkjhgrf.js} +5 -5
  16. package/dist/cli/{index-yh0q21nj.js → index-1kyex7z2.js} +1 -1
  17. package/dist/cli/{index-tkg6rapy.js → index-2ga0zt4s.js} +19404 -19355
  18. package/dist/cli/{index-6mvbjqbt.js → index-33skgk1a.js} +1 -1
  19. package/dist/cli/{index-xsxrhakg.js → index-41hkt36g.js} +1 -1
  20. package/dist/cli/{index-xzzcfwwm.js → index-5z2xps64.js} +2 -2
  21. package/dist/cli/{index-4fr94329.js → index-6nzmp937.js} +53 -108
  22. package/dist/cli/{index-2eet124q.js → index-6r522srn.js} +1 -1
  23. package/dist/cli/{index-4xbyy6aw.js → index-6rxgb5r9.js} +10 -6
  24. package/dist/cli/{index-gen82t10.js → index-6z0a940s.js} +7 -7
  25. package/dist/cli/{index-bcwx1335.js → index-9jr92bff.js} +1 -1
  26. package/dist/cli/{index-z6qe8wft.js → index-9rbwfydj.js} +10 -10
  27. package/dist/cli/{index-mzck763x.js → index-9xczz1yh.js} +2 -2
  28. package/dist/cli/{index-yawwwhmc.js → index-fb11cwqr.js} +6 -6
  29. package/dist/cli/{index-ba5e5e3n.js → index-gee0y2d8.js} +6 -6
  30. package/dist/cli/{index-1yd38ajy.js → index-h2zm446q.js} +4 -4
  31. package/dist/cli/{index-v7g8dnyh.js → index-hhgbbceq.js} +15 -15
  32. package/dist/cli/{index-mv0czd9c.js → index-j77frjq8.js} +6 -6
  33. package/dist/cli/{index-xeyr62x0.js → index-jtg7gtky.js} +5 -5
  34. package/dist/cli/{index-k87hs2ff.js → index-k46me75h.js} +3 -3
  35. package/dist/cli/{index-5hyq2mw6.js → index-ngfw3sd4.js} +43 -43
  36. package/dist/cli/{index-hckq2r5m.js → index-nrx08gcr.js} +6 -2
  37. package/dist/cli/{index-hwnpd4tw.js → index-px7z3r1c.js} +3 -3
  38. package/dist/cli/{index-6axm8q3s.js → index-r2bggfra.js} +7 -7
  39. package/dist/cli/{index-a5eba0t8.js → index-rsrx77fg.js} +6 -6
  40. package/dist/cli/index-s0qc4gj6.js +298 -0
  41. package/dist/cli/{index-ajwmn8gp.js → index-sd657fkp.js} +4 -4
  42. package/dist/cli/{index-0mzz46we.js → index-w9tezcdd.js} +7 -7
  43. package/dist/cli/{index-1jbj7vzv.js → index-wqk50bv0.js} +4 -4
  44. package/dist/cli/{index-05mms0va.js → index-xmhhhjjw.js} +38 -3
  45. package/dist/cli/{index-kyz7259r.js → index-z0tt5j2s.js} +7 -7
  46. package/dist/cli/index.js +41 -41
  47. package/dist/cli/{knowledge-escalator-kkjsjtza.js → knowledge-escalator-rhycg2rh.js} +9 -9
  48. package/dist/cli/{knowledge-events-jbw9j94n.js → knowledge-events-yjkszs87.js} +6 -6
  49. package/dist/cli/{knowledge-link-f6akgbdn.js → knowledge-link-bmbatt8s.js} +5 -5
  50. package/dist/cli/{knowledge-store-m7vnz62z.js → knowledge-store-qe7geq48.js} +7 -7
  51. package/dist/cli/{knowledge-validator-rqj7kech.js → knowledge-validator-rwptbkpz.js} +10 -10
  52. package/dist/cli/{pending-delegations-14544jpr.js → pending-delegations-7ayryxbg.js} +7 -7
  53. package/dist/cli/{pr-subscriptions-qdwfm1a8.js → pr-subscriptions-w5y08ebc.js} +7 -7
  54. package/dist/cli/{runner-mzb3e2s6.js → runner-h7vmgkth.js} +7 -6
  55. package/dist/cli/{scan-cursor-8e6ryhjq.js → scan-cursor-v1zkh6st.js} +8 -8
  56. package/dist/cli/{schema-g7rs20c6.js → schema-9v8wgmxf.js} +3 -3
  57. package/dist/cli/{scope-persistence-wy65zyha.js → scope-persistence-tj6qway9.js} +6 -6
  58. package/dist/cli/{skill-generator-2rv6ftre.js → skill-generator-a91bxwv2.js} +12 -12
  59. package/dist/cli/{telemetry-4tgrfhaz.js → telemetry-62cn5t24.js} +1 -1
  60. package/dist/cli/{worktree-collision-ownership-24s0t62z.js → worktree-collision-ownership-hs5c2qzp.js} +8 -8
  61. package/dist/evidence/manager.d.ts +4 -1
  62. package/dist/index.js +590 -588
  63. package/dist/prm/escalation.d.ts +34 -0
  64. package/dist/prm/index.d.ts +6 -2
  65. package/dist/prm/pattern-detector.d.ts +22 -1
  66. package/dist/prm/types.d.ts +12 -2
  67. package/dist/state.d.ts +49 -0
  68. package/dist/summaries/schema.d.ts +2 -2
  69. package/dist/tools/convene-council.d.ts +1 -1
  70. package/dist/tools/pre-check-batch.d.ts +4 -0
  71. package/dist/tools/resolve-working-directory.d.ts +4 -4
  72. package/dist/tools/submit-phase-council-verdicts.d.ts +1 -1
  73. package/dist/tools/write-final-council-evidence.d.ts +1 -1
  74. package/dist/utils/project-boundary.d.ts +34 -0
  75. package/package.json +1 -1
  76. package/dist/cli/curator-llm-factory-1r9vz0g2.js +0 -61
  77. package/dist/cli/guardrail-explain-y2wg00dp.js +0 -62
  78. package/dist/cli/index-5j6chvj8.js +0 -159
  79. package/dist/cli/{index-z6xqpmqg.js → index-ee3x66a5.js} +3 -3
@@ -3,6 +3,30 @@
3
3
  * Implements a 3-strike protocol for pattern detection escalation
4
4
  */
5
5
  import type { CourseCorrection, EscalationState, PatternMatch } from './types';
6
+ /**
7
+ * Resolves the LADDER key for a match — the identity whose 1→2→3 strike count
8
+ * this detection belongs to (issue #2134 follow-up).
9
+ *
10
+ * The ladder used to be keyed by pattern TYPE alone, so unrelated occurrences
11
+ * accumulated into one count: a coder that read-then-re-read three different
12
+ * files produced three `repetition_loop` strikes on three different targets and
13
+ * hit the hard stop, even though it had not repeated itself even twice on any
14
+ * one of them. "Three strikes" has to mean "the same behaviour three times".
15
+ *
16
+ * A pattern reporting exactly ONE affected target gets a per-target ladder —
17
+ * `repetition_loop`, `ping_pong` and `stuck_on_test` all name the single file or
18
+ * target they are about, so that target IS the behaviour's identity.
19
+ *
20
+ * A pattern reporting a SET of targets keeps the per-pattern-type ladder.
21
+ * `context_thrash` and `expansion_drift` describe one ongoing episode over a
22
+ * growing collection of targets; keying those by target would mint a fresh
23
+ * ladder on every tool call and they could never escalate at all — the exact
24
+ * fail-open shape that the per-detector containment review caught the first time.
25
+ *
26
+ * Agents are deliberately not in the key. Escalation is about the work, not who
27
+ * did it, and `ping_pong` names two agents by construction.
28
+ */
29
+ export declare function resolveLadderKey(match: PatternMatch): string;
6
30
  /**
7
31
  * Creates a default EscalationState with all counters reset and flags cleared.
8
32
  * Exported for testing purposes.
@@ -48,6 +72,16 @@ export declare class EscalationTracker {
48
72
  * @returns The current EscalationState copy
49
73
  */
50
74
  getState(): EscalationState;
75
+ /**
76
+ * Returns a defensive copy of just the ladder counts (issue #2134 follow-up).
77
+ *
78
+ * `src/prm/index.ts` mirrors these onto the session after every strike so a
79
+ * tracker rebuilt mid-session restores the same keyspace it counts in. Using
80
+ * `getState()` there deep-cloned the whole state — including `stepRange`,
81
+ * `affectedAgents` and `affectedTargets` of the last match — on the
82
+ * per-tool-call hot path, for one field.
83
+ */
84
+ getLadderCounts(): Map<string, number>;
51
85
  /**
52
86
  * Resets all escalation counts and flags to their default values.
53
87
  * Clears pattern counts and all flags.
@@ -13,8 +13,8 @@
13
13
  * while PRM provides deeper multi-pattern detection and escalation.
14
14
  */
15
15
  export { formatCourseCorrectionForInjection, generateCourseCorrection, } from './course-correction';
16
- export { createDefaultEscalationState, EscalationTracker } from './escalation';
17
- export { detectContextThrash, detectExpansionDrift, detectPatterns, detectPingPong, detectRepetitionLoop, detectStuckOnTest, } from './pattern-detector';
16
+ export { createDefaultEscalationState, EscalationTracker, resolveLadderKey, } from './escalation';
17
+ export { detectContextThrash, detectExpansionDrift, detectPatterns, detectPingPong, detectRepetitionLoop, detectStuckOnTest, resolvePatternThreshold, } from './pattern-detector';
18
18
  export type { CourseCorrection, EscalationState, PatternDetectionResult, PatternMatch, PatternSeverity, PatternType, PrmConfig, TaxonomyCategory, TrajectoryEntry, } from './types';
19
19
  import type { LearningConfig } from '../config/schema.js';
20
20
  import { appendInsightCandidates } from '../hooks/micro-reflector.js';
@@ -78,6 +78,10 @@ interface ResettablePrmSessionState {
78
78
  prmHardStopInjectPending?: boolean;
79
79
  prmTrajectoryStep?: number;
80
80
  prmInjectedAdvisoryKeys?: Set<string>;
81
+ /** Issue #2134 — episode ledger; reset with the trajectory cursor it indexes. */
82
+ prmStruckEpisodes?: Map<string, number>;
83
+ /** Issue #2134 follow-up — ladder counts; reset with the ledger. */
84
+ prmLadderCounts?: Map<string, number>;
81
85
  replayArtifactPath?: string | null;
82
86
  }
83
87
  export declare function resetPrmSessionState(session: ResettablePrmSessionState, sessionId?: string): void;
@@ -2,7 +2,7 @@
2
2
  * PRM Pattern Detector
3
3
  * Rule-based pattern detection for trajectory analysis
4
4
  */
5
- import type { PatternDetectionResult, PatternMatch, PrmConfig, TrajectoryEntry } from './types';
5
+ import type { PatternDetectionResult, PatternMatch, PatternType, PrmConfig, TrajectoryEntry } from './types';
6
6
  /**
7
7
  * Sanitize a string to prevent prompt injection attacks.
8
8
  * Removes newlines, carriage returns, backticks, and common injection patterns.
@@ -12,6 +12,27 @@ import type { PatternDetectionResult, PatternMatch, PrmConfig, TrajectoryEntry }
12
12
  * @returns Sanitized string safe for embedding in prompts
13
13
  */
14
14
  export declare function sanitizeString(input: string): string;
15
+ /**
16
+ * Resolves the configured occurrence threshold for a pattern type, falling back
17
+ * to the built-in default.
18
+ *
19
+ * Exported for the escalation ladder (issue #2134): the ladder re-strikes a
20
+ * still-running episode once it has grown by another threshold's worth of
21
+ * occurrences, so it must resolve the threshold exactly the way the detectors do
22
+ * or the two layers disagree about what "another occurrence" means.
23
+ *
24
+ * The threshold is NOT in a single unit across detectors, and the ladder does not
25
+ * pretend otherwise — it is repeats for `repetition_loop`, run length for
26
+ * `context_thrash`, cycle count for `stuck_on_test`, alternating-entry count for
27
+ * `ping_pong` (whose `occurrenceCount` is ROUND TRIPS, i.e. half that unit, so it
28
+ * re-strikes at twice the nominal spacing), and a growth RATIO for
29
+ * `expansion_drift` (whose `occurrenceCount` is a float near 1.5–3.0, so the
30
+ * growth ground is effectively inert for it and its re-strikes come from the
31
+ * new-episode ground instead — its comparison window steps by `windowSize`, so
32
+ * its episode start step genuinely advances). Every one of the five is verified
33
+ * to still reach a hard stop; see `src/prm/__tests__/issue-2134-episode-gate.test.ts`.
34
+ */
35
+ export declare function resolvePatternThreshold(config: PrmConfig, pattern: PatternType): number;
15
36
  /**
16
37
  * Detect repetition_loop pattern
17
38
  * Same agent targets same file with same action within N steps
@@ -107,8 +107,18 @@ export interface PrmConfig {
107
107
  * Per-session escalation tracking state
108
108
  */
109
109
  export interface EscalationState {
110
- /** Pattern type to detection count mapping */
111
- patternCounts: Map<PatternType, number>;
110
+ /**
111
+ * Ladder identity to strike-count mapping.
112
+ *
113
+ * Keyed by `resolveLadderKey(match)` (issue #2134 follow-up), NOT by pattern
114
+ * type: `pattern|target` for a single-target pattern, bare `pattern` for one
115
+ * reporting a growing target set. Keying the ladder by pattern type alone let
116
+ * unrelated occurrences on different files accumulate into a hard stop.
117
+ *
118
+ * Distinct from `AgentSessionState.prmPatternCounts`, which stays keyed by
119
+ * pattern type as the observable per-pattern tally.
120
+ */
121
+ patternCounts: Map<string, number>;
112
122
  /** Current escalation level (0=none, 1=guidance, 2=strong guidance, 3=hard stop) */
113
123
  escalationLevel: number;
114
124
  /** Last pattern detected (if any) */
package/dist/state.d.ts CHANGED
@@ -414,6 +414,55 @@ export interface AgentSessionState {
414
414
  * fields, and this one is additive.
415
415
  */
416
416
  prmHardStopInjectPending?: boolean;
417
+ /**
418
+ * Issue #2134 — episode ledger for the escalation ladder.
419
+ *
420
+ * Maps an episode key (`patternType|startStep`) to the occurrence count that
421
+ * episode had when it last recorded a strike. A detector re-emits the SAME
422
+ * ongoing episode on every tool call with a growing `stepRange[1]` (a coder
423
+ * reading more files extends one `context_thrash` run), and the trajectory
424
+ * cursor cannot suppress that because the episode's end step always advances
425
+ * past it. Counting each re-emission as a fresh strike walked ONE ordinary
426
+ * episode from level 1 to level 3 in three tool calls and wedged healthy coder
427
+ * sessions behind a hard stop.
428
+ *
429
+ * A match strikes when its episode is new, or when that episode has gained
430
+ * another full threshold's worth of occurrences since it last struck. Both
431
+ * rungs are needed: three of the five detectors never advance an episode's
432
+ * start step while it runs, so without the growth rung they would strike
433
+ * exactly once and could never reach level 2 or 3. See the EPISODE GATE
434
+ * comment in `src/prm/index.ts` for the per-detector derivation.
435
+ *
436
+ * Optional for the same reason as `prmHardStopInjectPending`: ~25 existing
437
+ * test/session literals enumerate the required PRM fields, and this is additive.
438
+ */
439
+ prmStruckEpisodes?: Map<string, number>;
440
+ /**
441
+ * Issue #2134 follow-up — mirror of the escalation tracker's LADDER counts,
442
+ * keyed by `resolveLadderKey(match)` (`pattern|target`, or bare `pattern` for
443
+ * a pattern reporting a growing target set).
444
+ *
445
+ * Deliberately separate from `prmPatternCounts`, which stays keyed by pattern
446
+ * type as the observable per-pattern tally that telemetry and tests read. The
447
+ * two are different keyspaces and must not be conflated: the tracker-rebuild
448
+ * path below used to seed itself from `prmPatternCounts`, which would now
449
+ * hand pattern-type keys to a ladder that counts by target and silently
450
+ * mis-restore every count.
451
+ */
452
+ prmLadderCounts?: Map<string, number>;
453
+ /**
454
+ * Issue #2134 — dispatch identity of the delegation whose start already reset
455
+ * this session's PRM state. Holds the Task tool `callID`, which is unique per
456
+ * dispatch.
457
+ *
458
+ * The reset hook (`delegationGateHooks.taskMetadata`) is driven by
459
+ * `message.part.updated`, which fires repeatedly for the SAME Task part as the
460
+ * child runs. An unguarded reset there would clear the escalation ladder on
461
+ * every part update and disarm PRM permanently — a fail-open far worse than
462
+ * the wedge it is meant to prevent. Comparing against this field makes the
463
+ * reset exactly once per dispatch.
464
+ */
465
+ prmDelegationCallId?: string;
417
466
  /** Per-session escalation tracker instance (set lazily by PRM hook) */
418
467
  prmEscalationTracker?: EscalationTracker;
419
468
  /** Cross-turn set of already-injected PRM advisory dedupe keys
@@ -22,8 +22,8 @@ export declare const MAX_LIST_ITEMS = 5;
22
22
  /** Verdict vocabulary — mirrors the phase-council gate (APPROVE | CONCERNS | REJECT). */
23
23
  export declare const SupervisorVerdictSchema: z.ZodEnum<{
24
24
  APPROVE: "APPROVE";
25
- CONCERNS: "CONCERNS";
26
25
  REJECT: "REJECT";
26
+ CONCERNS: "CONCERNS";
27
27
  }>;
28
28
  export type SupervisorVerdict = z.infer<typeof SupervisorVerdictSchema>;
29
29
  /** Count whitespace-delimited words in a string. */
@@ -130,8 +130,8 @@ export declare const ArchitectureSupervisorReportSchema: z.ZodObject<{
130
130
  phase: z.ZodNumber;
131
131
  verdict: z.ZodEnum<{
132
132
  APPROVE: "APPROVE";
133
- CONCERNS: "CONCERNS";
134
133
  REJECT: "REJECT";
134
+ CONCERNS: "CONCERNS";
135
135
  }>;
136
136
  findings: z.ZodDefault<z.ZodArray<z.ZodObject<{
137
137
  severity: z.ZodEnum<{
@@ -15,8 +15,8 @@ export declare const ArgsSchema: z.ZodObject<{
15
15
  }>;
16
16
  verdict: z.ZodEnum<{
17
17
  APPROVE: "APPROVE";
18
- CONCERNS: "CONCERNS";
19
18
  REJECT: "REJECT";
19
+ CONCERNS: "CONCERNS";
20
20
  }>;
21
21
  confidence: z.ZodNumber;
22
22
  findings: z.ZodArray<z.ZodObject<{
@@ -83,6 +83,10 @@ export interface PreCheckBatchResult {
83
83
  * field and replace optional payloads with bounded, UTF-8-safe summaries.
84
84
  */
85
85
  declare function serializePreCheckResult(result: PreCheckBatchResult): string;
86
+ declare function isAcceptedProjectRootForPlatform(dir: string, workspaceDir: string, platform: NodeJS.Platform, hasExplicitBoundary: boolean): boolean;
87
+ export declare const _test_exports: {
88
+ isAcceptedProjectRootForPlatform: typeof isAcceptedProjectRootForPlatform;
89
+ };
86
90
  /**
87
91
  * Run a function with timeout
88
92
  */
@@ -23,10 +23,10 @@ export interface ResolveError {
23
23
  *
24
24
  * NOTE: This function intentionally does NOT use realpathSync for the resolved path
25
25
  * to avoid Windows 8.3 short filename issues. Symlink-based subdirectory bypasses
26
- * through this coarse filter are caught by the write-time validateProjectRoot guard
27
- * in evidence/manager.ts, which DOES use realpathSync. These two functions form a
28
- * defense-in-depth pair: resolveWorkingDirectory is the fast entry filter,
29
- * validateProjectRoot is the authoritative canonical check at write time.
26
+ * through this coarse filter are caught by the shared canonical project-root
27
+ * assertion at evidence, plan, and scope persistence sinks. These checks form a
28
+ * defense-in-depth pair: resolveWorkingDirectory is the fast entry filter and the
29
+ * persistence assertion is authoritative at write time.
30
30
  *
31
31
  * Priority: explicit working_directory param > injected directory (from createSwarmTool).
32
32
  *
@@ -15,8 +15,8 @@ export declare const ArgsSchema: z.ZodObject<{
15
15
  }>;
16
16
  verdict: z.ZodEnum<{
17
17
  APPROVE: "APPROVE";
18
- CONCERNS: "CONCERNS";
19
18
  REJECT: "REJECT";
19
+ CONCERNS: "CONCERNS";
20
20
  }>;
21
21
  confidence: z.ZodNumber;
22
22
  findings: z.ZodArray<z.ZodObject<{
@@ -16,8 +16,8 @@ export declare const ArgsSchema: z.ZodObject<{
16
16
  }>;
17
17
  verdict: z.ZodEnum<{
18
18
  APPROVE: "APPROVE";
19
- CONCERNS: "CONCERNS";
20
19
  REJECT: "REJECT";
20
+ CONCERNS: "CONCERNS";
21
21
  }>;
22
22
  confidence: z.ZodNumber;
23
23
  findings: z.ZodArray<z.ZodObject<{
@@ -0,0 +1,34 @@
1
+ import * as fs from 'node:fs';
2
+ /** Maximum depth to walk up the directory tree before failing closed. */
3
+ export declare const MAX_PROJECT_ROOT_DEPTH = 20;
4
+ /** File/directory names that indicate a real ancestor project root. */
5
+ export declare const PROJECT_ROOT_INDICATORS: readonly ["package.json", ".git", ".opencode", "Cargo.toml", "go.mod", "pyproject.toml", "Gemfile", "composer.json", "pom.xml", "build.gradle", "CMakeLists.txt"];
6
+ /**
7
+ * Return whether `directory` directly declares its own project boundary.
8
+ *
9
+ * Markers are local declarations, not verified Git metadata. A direct `.git`
10
+ * file/directory covers repositories, linked worktrees, and submodules; a
11
+ * direct `.opencode` directory is the manual opt-in. `lstatSync` is deliberate:
12
+ * marker symlinks/junctions do not grant an exemption. Missing, inaccessible,
13
+ * or ambiguous markers fail closed.
14
+ */
15
+ export declare function hasExplicitProjectBoundary(directory: unknown): boolean;
16
+ /**
17
+ * Test whether `candidate` is a strict lexical descendant of `root` using the
18
+ * host platform's path semantics (including case-insensitive Windows paths).
19
+ */
20
+ export declare function isStrictPathDescendant(candidate: unknown, root: unknown): boolean;
21
+ type ProjectRootProbeDependencies = Pick<typeof fs, 'realpathSync' | 'statSync'>;
22
+ /**
23
+ * Authoritative write-time project-root assertion shared by persistence sinks.
24
+ *
25
+ * Direct boundary markers exempt a nested project from ancestor checks. Ordinary
26
+ * descendants are rejected when an ancestor contains both `.swarm/` and a
27
+ * project indicator. Ambiguous ancestor state fails closed.
28
+ */
29
+ export declare function assertProjectRoot(directory: string, dependencies?: ProjectRootProbeDependencies, artifactLabel?: string): void;
30
+ /** Narrow filesystem seam for deterministic marker error tests. */
31
+ export declare const _internals: {
32
+ lstatSync: typeof fs.lstatSync;
33
+ };
34
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.139.3",
3
+ "version": "7.139.5",
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,61 +0,0 @@
1
- // @bun
2
- import {
3
- createCuratorLLMDelegate
4
- } from "./index-tkg6rapy.js";
5
- import"./index-xsxrhakg.js";
6
- import"./index-ajwmn8gp.js";
7
- import"./index-0mzz46we.js";
8
- import"./index-1yd38ajy.js";
9
- import"./index-4fr94329.js";
10
- import"./index-hckq2r5m.js";
11
- import"./index-y8552snf.js";
12
- import"./index-4905hd2m.js";
13
- import"./index-134d35c1.js";
14
- import"./index-6axm8q3s.js";
15
- import"./index-xeyr62x0.js";
16
- import"./index-ba5e5e3n.js";
17
- import"./index-6mjf4vr1.js";
18
- import"./index-c8s9a3zh.js";
19
- import"./index-9ss2m4rs.js";
20
- import"./index-74hpm6sh.js";
21
- import"./index-xzzcfwwm.js";
22
- import"./index-1jbj7vzv.js";
23
- import"./index-jqn332jx.js";
24
- import"./index-rtry5xyf.js";
25
- import"./index-z6qe8wft.js";
26
- import"./index-hwnpd4tw.js";
27
- import"./index-ae75rja9.js";
28
- import"./index-6mvbjqbt.js";
29
- import"./index-2eet124q.js";
30
- import"./index-yawwwhmc.js";
31
- import"./index-gprxjmm7.js";
32
- import"./index-n832052r.js";
33
- import"./index-kyz7259r.js";
34
- import"./index-bk5tah7q.js";
35
- import"./index-8fwhhayc.js";
36
- import"./index-q1exe2b3.js";
37
- import"./index-5syvwd8g.js";
38
- import"./index-05mms0va.js";
39
- import"./index-556ja8an.js";
40
- import"./index-4xbyy6aw.js";
41
- import"./index-1kz6da87.js";
42
- import"./index-yh0q21nj.js";
43
- import"./index-b8zgtz81.js";
44
- import"./index-gen82t10.js";
45
- import"./index-4rhhvd1a.js";
46
- import"./index-4wjk296r.js";
47
- import"./index-mv0czd9c.js";
48
- import"./index-k87hs2ff.js";
49
- import"./index-ed5ykebp.js";
50
- import"./index-5j6chvj8.js";
51
- import"./index-7g4c7s5r.js";
52
- import"./index-a5eba0t8.js";
53
- import"./index-bpmtbmy9.js";
54
- import"./index-z6xqpmqg.js";
55
- import"./index-zjygnfay.js";
56
- import"./index-4nt52yr9.js";
57
- import"./index-zgwm4ryv.js";
58
- import"./index-a76rekgs.js";
59
- export {
60
- createCuratorLLMDelegate
61
- };
@@ -1,62 +0,0 @@
1
- // @bun
2
- import {
3
- handleGuardrailExplain
4
- } from "./index-mzck763x.js";
5
- import"./index-tkg6rapy.js";
6
- import"./index-xsxrhakg.js";
7
- import"./index-ajwmn8gp.js";
8
- import"./index-0mzz46we.js";
9
- import"./index-1yd38ajy.js";
10
- import"./index-4fr94329.js";
11
- import"./index-hckq2r5m.js";
12
- import"./index-y8552snf.js";
13
- import"./index-4905hd2m.js";
14
- import"./index-134d35c1.js";
15
- import"./index-6axm8q3s.js";
16
- import"./index-xeyr62x0.js";
17
- import"./index-ba5e5e3n.js";
18
- import"./index-6mjf4vr1.js";
19
- import"./index-c8s9a3zh.js";
20
- import"./index-9ss2m4rs.js";
21
- import"./index-74hpm6sh.js";
22
- import"./index-xzzcfwwm.js";
23
- import"./index-1jbj7vzv.js";
24
- import"./index-jqn332jx.js";
25
- import"./index-rtry5xyf.js";
26
- import"./index-z6qe8wft.js";
27
- import"./index-hwnpd4tw.js";
28
- import"./index-ae75rja9.js";
29
- import"./index-6mvbjqbt.js";
30
- import"./index-2eet124q.js";
31
- import"./index-yawwwhmc.js";
32
- import"./index-gprxjmm7.js";
33
- import"./index-n832052r.js";
34
- import"./index-kyz7259r.js";
35
- import"./index-bk5tah7q.js";
36
- import"./index-8fwhhayc.js";
37
- import"./index-q1exe2b3.js";
38
- import"./index-5syvwd8g.js";
39
- import"./index-05mms0va.js";
40
- import"./index-556ja8an.js";
41
- import"./index-4xbyy6aw.js";
42
- import"./index-1kz6da87.js";
43
- import"./index-yh0q21nj.js";
44
- import"./index-b8zgtz81.js";
45
- import"./index-gen82t10.js";
46
- import"./index-4rhhvd1a.js";
47
- import"./index-4wjk296r.js";
48
- import"./index-mv0czd9c.js";
49
- import"./index-k87hs2ff.js";
50
- import"./index-ed5ykebp.js";
51
- import"./index-5j6chvj8.js";
52
- import"./index-7g4c7s5r.js";
53
- import"./index-a5eba0t8.js";
54
- import"./index-bpmtbmy9.js";
55
- import"./index-z6xqpmqg.js";
56
- import"./index-zjygnfay.js";
57
- import"./index-4nt52yr9.js";
58
- import"./index-zgwm4ryv.js";
59
- import"./index-a76rekgs.js";
60
- export {
61
- handleGuardrailExplain
62
- };
@@ -1,159 +0,0 @@
1
- // @bun
2
- import {
3
- require_proper_lockfile
4
- } from "./index-7g4c7s5r.js";
5
- import {
6
- emit
7
- } from "./index-a5eba0t8.js";
8
- import {
9
- __toESM
10
- } from "./index-a76rekgs.js";
11
-
12
- // src/parallel/file-locks.ts
13
- var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
14
- import * as crypto from "crypto";
15
- import * as fs from "fs";
16
- import * as path from "path";
17
- var LOCKS_DIR = ".swarm/locks";
18
- var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
19
- var _internals = {
20
- tryAcquireLock,
21
- writeFile: fs.promises.writeFile
22
- };
23
- function getLockFilePath(directory, filePath) {
24
- const normalized = path.resolve(directory, filePath);
25
- const baseDir = path.resolve(directory) + path.sep;
26
- const pathOk = process.platform === "win32" ? normalized.toLowerCase().startsWith(baseDir.toLowerCase()) : normalized.startsWith(baseDir);
27
- if (!pathOk) {
28
- throw new Error("Invalid file path: path traversal not allowed");
29
- }
30
- const pathForHash = process.platform === "win32" ? normalized.toLowerCase() : normalized;
31
- const hash = crypto.createHash("sha256").update(pathForHash).digest("hex");
32
- const lockPath = path.join(directory, LOCKS_DIR, `${hash}.lock`);
33
- const legacyPaths = [pathForHash];
34
- if (process.platform === "win32" && normalized !== pathForHash) {
35
- legacyPaths.push(normalized);
36
- }
37
- for (const legacyPath of legacyPaths) {
38
- const oldHash = Buffer.from(legacyPath).toString("base64").replace(/[/+=]/g, "_");
39
- const oldLockPath = path.join(directory, LOCKS_DIR, `${oldHash}.lock`);
40
- if (fs.existsSync(oldLockPath)) {
41
- return oldLockPath;
42
- }
43
- }
44
- return lockPath;
45
- }
46
- async function tryAcquireLock(directory, filePath, agent, taskId) {
47
- const lockPath = getLockFilePath(directory, filePath);
48
- const locksDir = path.dirname(lockPath);
49
- if (!fs.existsSync(locksDir)) {
50
- fs.mkdirSync(locksDir, { recursive: true });
51
- }
52
- if (!fs.existsSync(lockPath)) {
53
- fs.writeFileSync(lockPath, "", "utf-8");
54
- }
55
- let release;
56
- try {
57
- release = await import_proper_lockfile.default.lock(lockPath, {
58
- stale: LOCK_TIMEOUT_MS,
59
- retries: {
60
- retries: 5,
61
- minTimeout: 10,
62
- maxTimeout: 500,
63
- factor: 2
64
- },
65
- realpath: false
66
- });
67
- } catch (err) {
68
- const code = err.code;
69
- if (code === "ELOCKED" || code === "EEXIST") {
70
- return { acquired: false };
71
- }
72
- throw err;
73
- }
74
- const lock = {
75
- filePath,
76
- agent,
77
- taskId,
78
- timestamp: new Date().toISOString(),
79
- expiresAt: Date.now() + LOCK_TIMEOUT_MS,
80
- _release: release
81
- };
82
- return { acquired: true, lock };
83
- }
84
-
85
- // src/evidence/lock.ts
86
- class EvidenceLockTimeoutError extends Error {
87
- directory;
88
- evidencePath;
89
- agent;
90
- taskId;
91
- constructor(directory, evidencePath, agent, taskId, timeoutMs) {
92
- super(`Evidence lock timeout after ${timeoutMs}ms for ${evidencePath} (agent=${agent}, task=${taskId})`);
93
- this.name = "EvidenceLockTimeoutError";
94
- this.directory = directory;
95
- this.evidencePath = evidencePath;
96
- this.agent = agent;
97
- this.taskId = taskId;
98
- }
99
- }
100
- var BACKOFF_START_MS = 50;
101
- var BACKOFF_MAX_MS = 2000;
102
- var BACKOFF_JITTER_RATIO = 0.25;
103
- function backoffMs(attempt) {
104
- const base = Math.min(BACKOFF_START_MS * 2 ** attempt, BACKOFF_MAX_MS);
105
- const jitter = base * BACKOFF_JITTER_RATIO * (Math.random() * 2 - 1);
106
- return Math.max(1, Math.round(base + jitter));
107
- }
108
- async function withEvidenceLock(directory, evidencePath, agent, taskId, fn, timeoutMs = 60000) {
109
- const deadline = Date.now() + timeoutMs;
110
- let attempt = 0;
111
- while (true) {
112
- const result = await tryAcquireLock(directory, evidencePath, agent, taskId);
113
- if (result.acquired) {
114
- const lock = result.lock;
115
- if (attempt > 0) {
116
- emit("evidence_lock_stale_recovered", {
117
- directory,
118
- evidencePath,
119
- agent,
120
- taskId,
121
- attempt
122
- });
123
- }
124
- emit("evidence_lock_acquired", {
125
- directory,
126
- evidencePath,
127
- agent,
128
- taskId,
129
- attempt
130
- });
131
- try {
132
- return await fn();
133
- } finally {
134
- if (lock._release) {
135
- try {
136
- await lock._release();
137
- } catch {}
138
- }
139
- }
140
- }
141
- if (Date.now() >= deadline) {
142
- throw new EvidenceLockTimeoutError(directory, evidencePath, agent, taskId, timeoutMs);
143
- }
144
- emit("evidence_lock_contended", {
145
- directory,
146
- evidencePath,
147
- agent,
148
- taskId,
149
- attempt
150
- });
151
- const delay = Math.min(backoffMs(attempt), deadline - Date.now());
152
- if (delay > 0) {
153
- await new Promise((resolve2) => setTimeout(resolve2, delay));
154
- }
155
- attempt++;
156
- }
157
- }
158
-
159
- export { tryAcquireLock, withEvidenceLock };
@@ -1,10 +1,10 @@
1
1
  // @bun
2
- import {
3
- init_merge
4
- } from "./index-zjygnfay.js";
5
2
  import {
6
3
  init_logger
7
4
  } from "./index-zgwm4ryv.js";
5
+ import {
6
+ init_merge
7
+ } from "./index-zjygnfay.js";
8
8
 
9
9
  // src/utils/errors.ts
10
10
  class SwarmError extends Error {