opencode-swarm 7.139.3 → 7.139.4
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.
- package/README.md +2 -2
- package/dist/cli/{config-doctor-75qky762.js → config-doctor-whxr386t.js} +6 -6
- package/dist/cli/{core-nn8ffy5h.js → core-aj5g7an6.js} +4 -4
- package/dist/cli/{curation-policy-f46tf3dw.js → curation-policy-anym2y3v.js} +7 -7
- package/dist/cli/{curator-drift-r52hjskk.js → curator-drift-49p3jnte.js} +6 -6
- package/dist/cli/{curator-m6mk2v1n.js → curator-e8cvb55d.js} +39 -39
- package/dist/cli/curator-llm-factory-h9xbpgmw.js +61 -0
- package/dist/cli/{dispatch-nbv0hezh.js → dispatch-2s23fbcs.js} +3 -3
- package/dist/cli/{evidence-summary-service-sxcq5nrt.js → evidence-summary-service-g82bsjqa.js} +16 -16
- package/dist/cli/{gate-evidence-1982qswy.js → gate-evidence-72cgrvs2.js} +6 -5
- package/dist/cli/guardrail-explain-0be7msvq.js +62 -0
- package/dist/cli/{guardrail-log-320grggj.js → guardrail-log-9mm5443g.js} +8 -8
- package/dist/cli/{hive-promoter-v4w7cjvk.js → hive-promoter-nnzs5x1r.js} +39 -39
- package/dist/cli/{index-xeyr62x0.js → index-0e95eck5.js} +5 -5
- package/dist/cli/{index-5syvwd8g.js → index-0xkjhgrf.js} +5 -5
- package/dist/cli/{index-yh0q21nj.js → index-1kyex7z2.js} +1 -1
- package/dist/cli/{index-6mvbjqbt.js → index-33skgk1a.js} +1 -1
- package/dist/cli/{index-xsxrhakg.js → index-41hkt36g.js} +1 -1
- package/dist/cli/{index-jqn332jx.js → index-5azdnaty.js} +2 -2
- package/dist/cli/{index-kyz7259r.js → index-5s23pfsy.js} +7 -7
- package/dist/cli/{index-xzzcfwwm.js → index-5z2xps64.js} +2 -2
- package/dist/cli/{index-4fr94329.js → index-6nzmp937.js} +53 -108
- package/dist/cli/{index-2eet124q.js → index-6r522srn.js} +1 -1
- package/dist/cli/{index-4xbyy6aw.js → index-6rxgb5r9.js} +10 -6
- package/dist/cli/{index-z6qe8wft.js → index-6vh6vrnk.js} +10 -10
- package/dist/cli/{index-gen82t10.js → index-6z0a940s.js} +7 -7
- package/dist/cli/{index-ba5e5e3n.js → index-9cdj4020.js} +6 -6
- package/dist/cli/{index-1yd38ajy.js → index-e1k9vpqn.js} +4 -4
- package/dist/cli/{index-0mzz46we.js → index-ejbcpbzp.js} +7 -7
- package/dist/cli/{index-mzck763x.js → index-gfmrw2f5.js} +2 -2
- package/dist/cli/{index-mv0czd9c.js → index-j77frjq8.js} +6 -6
- package/dist/cli/{index-1jbj7vzv.js → index-jnfyxeap.js} +4 -4
- package/dist/cli/{index-hwnpd4tw.js → index-k41dn8me.js} +3 -3
- package/dist/cli/{index-k87hs2ff.js → index-k46me75h.js} +3 -3
- package/dist/cli/{index-hckq2r5m.js → index-nrx08gcr.js} +6 -2
- package/dist/cli/{index-6axm8q3s.js → index-pg84msyc.js} +7 -7
- package/dist/cli/{index-a5eba0t8.js → index-rsrx77fg.js} +6 -6
- package/dist/cli/index-s0qc4gj6.js +298 -0
- package/dist/cli/{index-yawwwhmc.js → index-s58vghgj.js} +6 -6
- package/dist/cli/{index-5hyq2mw6.js → index-sa15nfgg.js} +43 -43
- package/dist/cli/{index-ajwmn8gp.js → index-sd657fkp.js} +4 -4
- package/dist/cli/{index-v7g8dnyh.js → index-vfsqpcz6.js} +15 -15
- package/dist/cli/{index-tkg6rapy.js → index-vyqd1hzm.js} +19404 -19355
- package/dist/cli/{index-bcwx1335.js → index-xb1zq933.js} +1 -1
- package/dist/cli/{index-05mms0va.js → index-xmhhhjjw.js} +38 -3
- package/dist/cli/index.js +41 -41
- package/dist/cli/{knowledge-escalator-kkjsjtza.js → knowledge-escalator-a6z30y9p.js} +9 -9
- package/dist/cli/{knowledge-events-jbw9j94n.js → knowledge-events-deq0ds8e.js} +6 -6
- package/dist/cli/{knowledge-link-f6akgbdn.js → knowledge-link-bmbatt8s.js} +5 -5
- package/dist/cli/{knowledge-store-m7vnz62z.js → knowledge-store-vdr19mnq.js} +7 -7
- package/dist/cli/{knowledge-validator-rqj7kech.js → knowledge-validator-5hgacnrf.js} +10 -10
- package/dist/cli/{pending-delegations-14544jpr.js → pending-delegations-7ayryxbg.js} +7 -7
- package/dist/cli/{pr-subscriptions-qdwfm1a8.js → pr-subscriptions-w5y08ebc.js} +7 -7
- package/dist/cli/{runner-mzb3e2s6.js → runner-h7vmgkth.js} +7 -6
- package/dist/cli/{scan-cursor-8e6ryhjq.js → scan-cursor-d6qcg9hr.js} +8 -8
- package/dist/cli/{schema-g7rs20c6.js → schema-y1zekrag.js} +3 -3
- package/dist/cli/{scope-persistence-wy65zyha.js → scope-persistence-tj6qway9.js} +6 -6
- package/dist/cli/{skill-generator-2rv6ftre.js → skill-generator-bw8xhzzn.js} +12 -12
- package/dist/cli/{telemetry-4tgrfhaz.js → telemetry-62cn5t24.js} +1 -1
- package/dist/cli/{worktree-collision-ownership-24s0t62z.js → worktree-collision-ownership-hs5c2qzp.js} +8 -8
- package/dist/evidence/manager.d.ts +4 -1
- package/dist/index.js +590 -588
- package/dist/prm/escalation.d.ts +34 -0
- package/dist/prm/index.d.ts +6 -2
- package/dist/prm/pattern-detector.d.ts +22 -1
- package/dist/prm/types.d.ts +12 -2
- package/dist/state.d.ts +49 -0
- package/dist/summaries/schema.d.ts +2 -2
- package/dist/tools/convene-council.d.ts +1 -1
- package/dist/tools/pre-check-batch.d.ts +4 -0
- package/dist/tools/resolve-working-directory.d.ts +4 -4
- package/dist/tools/submit-phase-council-verdicts.d.ts +1 -1
- package/dist/tools/write-final-council-evidence.d.ts +1 -1
- package/dist/utils/project-boundary.d.ts +34 -0
- package/package.json +1 -1
- package/dist/cli/curator-llm-factory-1r9vz0g2.js +0 -61
- package/dist/cli/guardrail-explain-y2wg00dp.js +0 -62
- package/dist/cli/index-5j6chvj8.js +0 -159
- package/dist/cli/{index-z6xqpmqg.js → index-ee3x66a5.js} +3 -3
package/dist/prm/escalation.d.ts
CHANGED
|
@@ -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.
|
package/dist/prm/index.d.ts
CHANGED
|
@@ -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
|
package/dist/prm/types.d.ts
CHANGED
|
@@ -107,8 +107,18 @@ export interface PrmConfig {
|
|
|
107
107
|
* Per-session escalation tracking state
|
|
108
108
|
*/
|
|
109
109
|
export interface EscalationState {
|
|
110
|
-
/**
|
|
111
|
-
|
|
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<{
|
|
@@ -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
|
|
27
|
-
*
|
|
28
|
-
* defense-in-depth pair: resolveWorkingDirectory is the fast entry filter
|
|
29
|
-
*
|
|
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
|
*
|
|
@@ -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
|
+
"version": "7.139.4",
|
|
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 };
|