opencode-swarm 6.80.1 → 6.81.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.
- package/README.md +54 -0
- package/dist/cli/index.js +20 -0
- package/dist/config/schema.d.ts +27 -0
- package/dist/hooks/adversarial-detector.d.ts +2 -2
- package/dist/hooks/trajectory-logger.d.ts +14 -2
- package/dist/index.js +1560 -448
- package/dist/prm/__tests__/course-correction.test.d.ts +1 -0
- package/dist/prm/__tests__/escalation-queue-drain.test.d.ts +1 -0
- package/dist/prm/__tests__/escalation.test.d.ts +1 -0
- package/dist/prm/__tests__/index.test.d.ts +1 -0
- package/dist/prm/__tests__/integration.test.d.ts +1 -0
- package/dist/prm/__tests__/pattern-detector.test.d.ts +5 -0
- package/dist/prm/__tests__/replay.test.d.ts +1 -0
- package/dist/prm/__tests__/trajectory-store.test.d.ts +7 -0
- package/dist/prm/course-correction.d.ts +20 -0
- package/dist/prm/escalation.d.ts +73 -0
- package/dist/prm/index.d.ts +58 -0
- package/dist/prm/pattern-detector.d.ts +71 -0
- package/dist/prm/replay.d.ts +44 -0
- package/dist/prm/trajectory-store.d.ts +66 -0
- package/dist/prm/types.d.ts +120 -0
- package/dist/state.d.ts +14 -0
- package/dist/telemetry.d.ts +5 -1
- package/dist/types/events.d.ts +33 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -91,6 +91,60 @@ All project state lives in `.swarm/`:
|
|
|
91
91
|
|
|
92
92
|
Swarm is resumable by design. If `.swarm/` already exists, the architect goes straight into **RESUME** → **EXECUTE** instead of repeating discovery.
|
|
93
93
|
|
|
94
|
+
## Process Remediation Model (PRM)
|
|
95
|
+
|
|
96
|
+
Swarm includes a lightweight Process Remediation Model that monitors agent trajectories and injects course-correction guidance before loops form. Based on research from SWE-PRM (arXiv 2509.02360), taxonomy-guided PRMs improve task resolution by detecting failure patterns early.
|
|
97
|
+
|
|
98
|
+
### Detected Patterns
|
|
99
|
+
|
|
100
|
+
The PRM detects five trajectory patterns:
|
|
101
|
+
|
|
102
|
+
1. **Repetition Loop** — Same agent performs the same action on the same target file repeatedly
|
|
103
|
+
2. **Ping-Pong** — Agent A hands off to B, B hands back to A, and A hands to B again
|
|
104
|
+
3. **Expansion Drift** — Successive plans grow in scope beyond the original task
|
|
105
|
+
4. **Stuck-on-Test** — Coder edits → tests fail → coder edits same file → tests fail, repeating
|
|
106
|
+
5. **Context Thrashing** — Agent requests increasingly large file sets without narrowing scope
|
|
107
|
+
|
|
108
|
+
### Escalation Protocol
|
|
109
|
+
|
|
110
|
+
When a pattern is detected, the PRM tracks escalation levels:
|
|
111
|
+
|
|
112
|
+
- **Level 1 (1st detection):** Course-correction guidance is added to `pendingAdvisoryMessages` and injected via the `[ADVISORIES]` block. Sets `escalationLevel = 1`.
|
|
113
|
+
- **Level 2 (2nd detection):** Additional guidance added to `pendingAdvisoryMessages`, `architectAlertPending = true` is set, and `telemetry.prmEscalationTriggered()` is emitted. Sets `escalationLevel = 2`.
|
|
114
|
+
- **Level 3 (3rd+ detection):** Guidance added to `pendingAdvisoryMessages`, plus a hard stop directive is injected separately via `[HARD STOP]` block. Sets `escalationLevel = 3` and `hardStopPending = true`. Emits `telemetry.prmHardStop()`.
|
|
115
|
+
|
|
116
|
+
### Configuration
|
|
117
|
+
|
|
118
|
+
PRM behavior is controlled via the `prm` section in your configuration:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"prm": {
|
|
123
|
+
"enabled": true,
|
|
124
|
+
"pattern_thresholds": {
|
|
125
|
+
"repetition_loop": 2,
|
|
126
|
+
"ping_pong": 4,
|
|
127
|
+
"expansion_drift": 3,
|
|
128
|
+
"stuck_on_test": 3,
|
|
129
|
+
"context_thrash": 5
|
|
130
|
+
},
|
|
131
|
+
"max_trajectory_lines": 100,
|
|
132
|
+
"escalation_enabled": true,
|
|
133
|
+
"detection_timeout_ms": 5000
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
> **Note:** `max_trajectory_lines`, `escalation_enabled`, and `detection_timeout_ms` are defined in the schema but not yet enforced at runtime. The default trajectory limit is 1000 lines.
|
|
139
|
+
|
|
140
|
+
### Replay Recording
|
|
141
|
+
|
|
142
|
+
PRM records all pattern detections, course corrections, escalations, and hard stops to `.swarm/replays/{sessionId}-{timestamp}.jsonl` for post-mortem analysis. Use the replay artifacts to understand why loops formed and how they were resolved.
|
|
143
|
+
|
|
144
|
+
### Performance
|
|
145
|
+
|
|
146
|
+
Pattern detection runs in less than 100ms per step using rule-based analysis — no LLM calls required for detection.
|
|
147
|
+
|
|
94
148
|
---
|
|
95
149
|
|
|
96
150
|
## Quick Start
|
package/dist/cli/index.js
CHANGED
|
@@ -19424,6 +19424,25 @@ var CompactionConfigSchema = exports_external.object({
|
|
|
19424
19424
|
emergencyThreshold: exports_external.number().min(1).max(99).default(80),
|
|
19425
19425
|
preserveLastNTurns: exports_external.number().int().min(1).default(5)
|
|
19426
19426
|
});
|
|
19427
|
+
var PrmConfigSchema = exports_external.object({
|
|
19428
|
+
enabled: exports_external.boolean().default(true),
|
|
19429
|
+
pattern_thresholds: exports_external.object({
|
|
19430
|
+
repetition_loop: exports_external.number().min(1).default(2),
|
|
19431
|
+
ping_pong: exports_external.number().min(1).default(2),
|
|
19432
|
+
expansion_drift: exports_external.number().min(1).default(3),
|
|
19433
|
+
stuck_on_test: exports_external.number().min(1).default(3),
|
|
19434
|
+
context_thrash: exports_external.number().min(1).default(3)
|
|
19435
|
+
}).default(() => ({
|
|
19436
|
+
repetition_loop: 2,
|
|
19437
|
+
ping_pong: 2,
|
|
19438
|
+
expansion_drift: 3,
|
|
19439
|
+
stuck_on_test: 3,
|
|
19440
|
+
context_thrash: 3
|
|
19441
|
+
})),
|
|
19442
|
+
max_trajectory_lines: exports_external.number().min(10).default(1000),
|
|
19443
|
+
escalation_enabled: exports_external.boolean().default(true),
|
|
19444
|
+
detection_timeout_ms: exports_external.number().min(10).default(100)
|
|
19445
|
+
});
|
|
19427
19446
|
var AgentAuthorityRuleSchema = exports_external.object({
|
|
19428
19447
|
readOnly: exports_external.boolean().optional(),
|
|
19429
19448
|
blockedExact: exports_external.array(exports_external.string()).optional(),
|
|
@@ -19504,6 +19523,7 @@ var PluginConfigSchema = exports_external.object({
|
|
|
19504
19523
|
}).optional(),
|
|
19505
19524
|
incremental_verify: IncrementalVerifyConfigSchema.optional(),
|
|
19506
19525
|
compaction_service: CompactionConfigSchema.optional(),
|
|
19526
|
+
prm: PrmConfigSchema.optional(),
|
|
19507
19527
|
council: CouncilConfigSchema.optional(),
|
|
19508
19528
|
parallelization: ParallelizationConfigSchema.optional(),
|
|
19509
19529
|
turbo_mode: exports_external.boolean().default(false).optional(),
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -477,6 +477,20 @@ export declare const CompactionConfigSchema: z.ZodObject<{
|
|
|
477
477
|
preserveLastNTurns: z.ZodDefault<z.ZodNumber>;
|
|
478
478
|
}, z.core.$strip>;
|
|
479
479
|
export type CompactionConfig = z.infer<typeof CompactionConfigSchema>;
|
|
480
|
+
export declare const PrmConfigSchema: z.ZodObject<{
|
|
481
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
482
|
+
pattern_thresholds: z.ZodDefault<z.ZodObject<{
|
|
483
|
+
repetition_loop: z.ZodDefault<z.ZodNumber>;
|
|
484
|
+
ping_pong: z.ZodDefault<z.ZodNumber>;
|
|
485
|
+
expansion_drift: z.ZodDefault<z.ZodNumber>;
|
|
486
|
+
stuck_on_test: z.ZodDefault<z.ZodNumber>;
|
|
487
|
+
context_thrash: z.ZodDefault<z.ZodNumber>;
|
|
488
|
+
}, z.core.$strip>>;
|
|
489
|
+
max_trajectory_lines: z.ZodDefault<z.ZodNumber>;
|
|
490
|
+
escalation_enabled: z.ZodDefault<z.ZodBoolean>;
|
|
491
|
+
detection_timeout_ms: z.ZodDefault<z.ZodNumber>;
|
|
492
|
+
}, z.core.$strip>;
|
|
493
|
+
export type PrmConfig = z.infer<typeof PrmConfigSchema>;
|
|
480
494
|
export declare const AgentAuthorityRuleSchema: z.ZodObject<{
|
|
481
495
|
readOnly: z.ZodOptional<z.ZodBoolean>;
|
|
482
496
|
blockedExact: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -886,6 +900,19 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
886
900
|
emergencyThreshold: z.ZodDefault<z.ZodNumber>;
|
|
887
901
|
preserveLastNTurns: z.ZodDefault<z.ZodNumber>;
|
|
888
902
|
}, z.core.$strip>>;
|
|
903
|
+
prm: z.ZodOptional<z.ZodObject<{
|
|
904
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
905
|
+
pattern_thresholds: z.ZodDefault<z.ZodObject<{
|
|
906
|
+
repetition_loop: z.ZodDefault<z.ZodNumber>;
|
|
907
|
+
ping_pong: z.ZodDefault<z.ZodNumber>;
|
|
908
|
+
expansion_drift: z.ZodDefault<z.ZodNumber>;
|
|
909
|
+
stuck_on_test: z.ZodDefault<z.ZodNumber>;
|
|
910
|
+
context_thrash: z.ZodDefault<z.ZodNumber>;
|
|
911
|
+
}, z.core.$strip>>;
|
|
912
|
+
max_trajectory_lines: z.ZodDefault<z.ZodNumber>;
|
|
913
|
+
escalation_enabled: z.ZodDefault<z.ZodBoolean>;
|
|
914
|
+
detection_timeout_ms: z.ZodDefault<z.ZodNumber>;
|
|
915
|
+
}, z.core.$strip>>;
|
|
889
916
|
council: z.ZodOptional<z.ZodObject<{
|
|
890
917
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
891
918
|
maxRounds: z.ZodDefault<z.ZodNumber>;
|
|
@@ -42,9 +42,9 @@ export declare function handleDebuggingSpiral(match: AdversarialPatternMatch, ta
|
|
|
42
42
|
* Record a tool call for debugging spiral detection.
|
|
43
43
|
* Call this from toolAfter to track repetitive patterns.
|
|
44
44
|
*/
|
|
45
|
-
export declare function recordToolCall(tool: string, args: unknown): void;
|
|
45
|
+
export declare function recordToolCall(tool: string, args: unknown, sessionId: string): void;
|
|
46
46
|
/**
|
|
47
47
|
* Detect debugging spiral: same tool called 5+ times in a row with similar args
|
|
48
48
|
* within a 5-minute window. Indicates the agent is stuck in a loop.
|
|
49
49
|
*/
|
|
50
|
-
export declare function detectDebuggingSpiral(_directory: string): Promise<AdversarialPatternMatch | null>;
|
|
50
|
+
export declare function detectDebuggingSpiral(_directory: string, sessionId: string): Promise<AdversarialPatternMatch | null>;
|
|
@@ -12,11 +12,16 @@ export interface TrajectoryConfig {
|
|
|
12
12
|
max_lines: number;
|
|
13
13
|
}
|
|
14
14
|
export interface TrajectoryEntry {
|
|
15
|
+
step: number;
|
|
16
|
+
agent: string;
|
|
17
|
+
action: string;
|
|
18
|
+
target: string;
|
|
19
|
+
intent: string;
|
|
20
|
+
timestamp: string;
|
|
21
|
+
result: 'success' | 'failure' | 'pending';
|
|
15
22
|
tool: string;
|
|
16
23
|
args_summary: string;
|
|
17
24
|
verdict: string;
|
|
18
|
-
timestamp: string;
|
|
19
|
-
agent: string;
|
|
20
25
|
elapsed_ms: number;
|
|
21
26
|
}
|
|
22
27
|
/**
|
|
@@ -46,6 +51,13 @@ export declare function createTrajectoryLoggerHook(config: Partial<TrajectoryCon
|
|
|
46
51
|
metadata: unknown;
|
|
47
52
|
}) => Promise<void>;
|
|
48
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Resets the step counter for a session. Called when a new session starts
|
|
56
|
+
* or when trajectory tracking should restart from step 1.
|
|
57
|
+
*
|
|
58
|
+
* @param sessionId - Session identifier
|
|
59
|
+
*/
|
|
60
|
+
export declare function resetTrajectoryStep(sessionId: string): void;
|
|
49
61
|
/**
|
|
50
62
|
* Records the start time for a tool call (called from toolBefore).
|
|
51
63
|
* Stored in a module-level Map for correlation with toolAfter.
|