opencode-swarm 7.115.0 → 7.116.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 (127) hide show
  1. package/README.md +3 -1
  2. package/dist/cli/{curator-hpc4tsjv.js → curator-7s5yw6hw.js} +15 -14
  3. package/dist/cli/{curator-llm-factory-6n9sgaj8.js → curator-llm-factory-x96dr0zf.js} +15 -14
  4. package/dist/cli/{dispatch-mczsxy5s.js → dispatch-07jgc3hn.js} +1 -1
  5. package/dist/cli/{evidence-summary-service-fehwj116.js → evidence-summary-service-ef6kgtev.js} +5 -5
  6. package/dist/cli/{gate-evidence-vkpqt300.js → gate-evidence-thqt0beq.js} +4 -4
  7. package/dist/cli/{guardrail-explain-hecpd738.js → guardrail-explain-kwqfkwch.js} +16 -15
  8. package/dist/cli/{hive-promoter-0kfb4vjk.js → hive-promoter-rkkx40qv.js} +15 -14
  9. package/dist/cli/{index-2etc05tv.js → index-3b8n3dbd.js} +26 -18
  10. package/dist/cli/{index-8f2270hc.js → index-3yh67t1h.js} +3 -3
  11. package/dist/cli/{index-4sckv7y6.js → index-42cx6g2h.js} +9 -4
  12. package/dist/cli/index-4905hd2m.js +19 -0
  13. package/dist/cli/{index-4h2ea8h5.js → index-81vzywh3.js} +2 -2
  14. package/dist/cli/{index-6f6y2rbp.js → index-8bvh0qfa.js} +3 -3
  15. package/dist/cli/{index-80jkseqw.js → index-a6f8b0vn.js} +1 -1
  16. package/dist/cli/{index-0p660a87.js → index-bbsaxnj5.js} +1 -1
  17. package/dist/cli/{index-yrrqs4b0.js → index-cnrhj56z.js} +1160 -47
  18. package/dist/cli/{index-n18yy0z1.js → index-jyetmzcn.js} +3 -3
  19. package/dist/cli/{index-rk6qhyng.js → index-k5ey429j.js} +4 -4
  20. package/dist/cli/{index-m766gvdt.js → index-me46ffm2.js} +6804 -1940
  21. package/dist/cli/{index-ga4ta3cr.js → index-nprawcc0.js} +7 -1
  22. package/dist/cli/{index-pa6t33pt.js → index-q2rrv0cy.js} +11 -0
  23. package/dist/cli/{index-g40r5d08.js → index-qgeeyy75.js} +1 -1
  24. package/dist/cli/{index-x12hvfpf.js → index-s385axt1.js} +3 -3
  25. package/dist/cli/{index-m0rce3x6.js → index-tvgvb5pa.js} +1 -1
  26. package/dist/cli/index.js +15 -14
  27. package/dist/cli/{knowledge-escalator-5gwp1ar8.js → knowledge-escalator-0bq62d34.js} +7 -7
  28. package/dist/cli/{knowledge-events-m304swh6.js → knowledge-events-cwwky393.js} +5 -5
  29. package/dist/cli/{knowledge-store-9babt8rd.js → knowledge-store-q8x4h82m.js} +5 -5
  30. package/dist/cli/{knowledge-validator-t9sym59g.js → knowledge-validator-zr0djm02.js} +6 -6
  31. package/dist/cli/{pending-delegations-ddbkbgxy.js → pending-delegations-rr9x47rd.js} +2 -2
  32. package/dist/cli/{pr-subscriptions-vwv7zm2p.js → pr-subscriptions-cny2jz2d.js} +3 -3
  33. package/dist/cli/runtime-ykafcwc6.js +3397 -0
  34. package/dist/cli/{skill-generator-tav44xpm.js → skill-generator-mz267btk.js} +8 -8
  35. package/dist/cli/{telemetry-jny76r83.js → telemetry-qh78ymq4.js} +1 -1
  36. package/dist/commands/archive.d.ts +4 -4
  37. package/dist/commands/command-dispatch.d.ts +2 -0
  38. package/dist/commands/gate-audit.d.ts +28 -0
  39. package/dist/commands/gate-stats.d.ts +1 -0
  40. package/dist/commands/index.d.ts +4 -0
  41. package/dist/commands/registry.d.ts +19 -2
  42. package/dist/config/plan-schema.d.ts +7 -7
  43. package/dist/evaluation/contracts.d.ts +545 -0
  44. package/dist/evaluation/disposable-worktree.d.ts +38 -0
  45. package/dist/evaluation/fixtures.d.ts +8 -0
  46. package/dist/evaluation/gate-audit.d.ts +32 -0
  47. package/dist/evaluation/gate-ground-truth.d.ts +43 -0
  48. package/dist/evaluation/gate-stats.d.ts +47 -0
  49. package/dist/evaluation/hashing.d.ts +34 -0
  50. package/dist/evaluation/index.d.ts +17 -0
  51. package/dist/evaluation/model-dispatcher.d.ts +30 -0
  52. package/dist/evaluation/public-api.d.ts +87 -0
  53. package/dist/evaluation/retention.d.ts +56 -0
  54. package/dist/evaluation/runner.d.ts +48 -0
  55. package/dist/evaluation/statistics.d.ts +9 -0
  56. package/dist/evaluation/store.d.ts +26 -0
  57. package/dist/evidence/manager.d.ts +18 -0
  58. package/dist/index.d.ts +4 -0
  59. package/dist/index.js +461 -447
  60. package/dist/mutation/engine.d.ts +29 -5
  61. package/dist/telemetry.d.ts +11 -1
  62. package/dist/tools/plugin-registration.d.ts +2 -1
  63. package/dist/tools/sast-scan.d.ts +9 -0
  64. package/dist/tools/swarm-command.d.ts +2 -1
  65. package/dist/tools/update-task-status.d.ts +16 -4
  66. package/dist/utils/external-tool-runner.d.ts +2 -1
  67. package/evaluation-fixtures/tier1/boundary-error/environment/baseline.ts +3 -0
  68. package/evaluation-fixtures/tier1/boundary-error/environment/defect.test.ts +3 -0
  69. package/evaluation-fixtures/tier1/boundary-error/environment/defect.ts +3 -0
  70. package/evaluation-fixtures/tier1/boundary-error/instruction.md +1 -0
  71. package/evaluation-fixtures/tier1/boundary-error/manifest.json +1 -0
  72. package/evaluation-fixtures/tier1/branch-swap/environment/baseline.ts +3 -0
  73. package/evaluation-fixtures/tier1/branch-swap/environment/defect.test.ts +3 -0
  74. package/evaluation-fixtures/tier1/branch-swap/environment/defect.ts +3 -0
  75. package/evaluation-fixtures/tier1/branch-swap/instruction.md +1 -0
  76. package/evaluation-fixtures/tier1/branch-swap/manifest.json +1 -0
  77. package/evaluation-fixtures/tier1/curated-off-by-one/environment/baseline.ts +3 -0
  78. package/evaluation-fixtures/tier1/curated-off-by-one/environment/defect.test.ts +3 -0
  79. package/evaluation-fixtures/tier1/curated-off-by-one/environment/defect.ts +3 -0
  80. package/evaluation-fixtures/tier1/curated-off-by-one/instruction.md +1 -0
  81. package/evaluation-fixtures/tier1/curated-off-by-one/manifest.json +1 -0
  82. package/evaluation-fixtures/tier1/guard-removal/environment/baseline.ts +3 -0
  83. package/evaluation-fixtures/tier1/guard-removal/environment/defect.test.ts +3 -0
  84. package/evaluation-fixtures/tier1/guard-removal/environment/defect.ts +3 -0
  85. package/evaluation-fixtures/tier1/guard-removal/instruction.md +1 -0
  86. package/evaluation-fixtures/tier1/guard-removal/manifest.json +1 -0
  87. package/evaluation-fixtures/tier1/injection-prone-string/environment/baseline.ts +3 -0
  88. package/evaluation-fixtures/tier1/injection-prone-string/environment/defect.test.ts +3 -0
  89. package/evaluation-fixtures/tier1/injection-prone-string/environment/defect.ts +3 -0
  90. package/evaluation-fixtures/tier1/injection-prone-string/instruction.md +1 -0
  91. package/evaluation-fixtures/tier1/injection-prone-string/manifest.json +1 -0
  92. package/evaluation-fixtures/tier1/missing-auth-check/environment/baseline.ts +4 -0
  93. package/evaluation-fixtures/tier1/missing-auth-check/environment/defect.test.ts +3 -0
  94. package/evaluation-fixtures/tier1/missing-auth-check/environment/defect.ts +3 -0
  95. package/evaluation-fixtures/tier1/missing-auth-check/instruction.md +1 -0
  96. package/evaluation-fixtures/tier1/missing-auth-check/manifest.json +1 -0
  97. package/evaluation-fixtures/tier1/missing-await/environment/baseline.ts +7 -0
  98. package/evaluation-fixtures/tier1/missing-await/environment/defect.test.ts +3 -0
  99. package/evaluation-fixtures/tier1/missing-await/environment/defect.ts +4 -0
  100. package/evaluation-fixtures/tier1/missing-await/instruction.md +1 -0
  101. package/evaluation-fixtures/tier1/missing-await/manifest.json +1 -0
  102. package/evaluation-fixtures/tier1/mutation-off-by-one/environment/baseline.ts +3 -0
  103. package/evaluation-fixtures/tier1/mutation-off-by-one/environment/defect.test.ts +3 -0
  104. package/evaluation-fixtures/tier1/mutation-off-by-one/environment/defect.ts +3 -0
  105. package/evaluation-fixtures/tier1/mutation-off-by-one/instruction.md +1 -0
  106. package/evaluation-fixtures/tier1/mutation-off-by-one/manifest.json +1 -0
  107. package/evaluation-fixtures/tier1/null-substitution/environment/baseline.ts +3 -0
  108. package/evaluation-fixtures/tier1/null-substitution/environment/defect.test.ts +3 -0
  109. package/evaluation-fixtures/tier1/null-substitution/environment/defect.ts +3 -0
  110. package/evaluation-fixtures/tier1/null-substitution/instruction.md +1 -0
  111. package/evaluation-fixtures/tier1/null-substitution/manifest.json +1 -0
  112. package/evaluation-fixtures/tier1/operator-swap/environment/baseline.ts +3 -0
  113. package/evaluation-fixtures/tier1/operator-swap/environment/defect.test.ts +3 -0
  114. package/evaluation-fixtures/tier1/operator-swap/environment/defect.ts +3 -0
  115. package/evaluation-fixtures/tier1/operator-swap/instruction.md +1 -0
  116. package/evaluation-fixtures/tier1/operator-swap/manifest.json +1 -0
  117. package/evaluation-fixtures/tier1/side-effect-deletion/environment/baseline.ts +4 -0
  118. package/evaluation-fixtures/tier1/side-effect-deletion/environment/defect.test.ts +3 -0
  119. package/evaluation-fixtures/tier1/side-effect-deletion/environment/defect.ts +3 -0
  120. package/evaluation-fixtures/tier1/side-effect-deletion/instruction.md +1 -0
  121. package/evaluation-fixtures/tier1/side-effect-deletion/manifest.json +1 -0
  122. package/evaluation-fixtures/tier1/swallowed-error/environment/baseline.ts +3 -0
  123. package/evaluation-fixtures/tier1/swallowed-error/environment/defect.test.ts +3 -0
  124. package/evaluation-fixtures/tier1/swallowed-error/environment/defect.ts +3 -0
  125. package/evaluation-fixtures/tier1/swallowed-error/instruction.md +1 -0
  126. package/evaluation-fixtures/tier1/swallowed-error/manifest.json +1 -0
  127. package/package.json +2 -1
@@ -1,6 +1,6 @@
1
1
  import { spawnSync } from 'node:child_process';
2
- type SpawnSyncFn = typeof spawnSync;
3
- export type MutationOutcome = 'killed' | 'survived' | 'timeout' | 'error' | 'equivalent' | 'skipped';
2
+ import { resolveExecutableFromPath, runExternalTool } from '../utils/external-tool-runner.js';
3
+ export type MutationOutcome = 'killed' | 'survived' | 'timeout' | 'cancelled' | 'error' | 'equivalent' | 'skipped';
4
4
  /**
5
5
  * Known test runner executables permitted as the first element of testCommand.
6
6
  * Validated as the basename (without extension) to support platform-specific
@@ -35,6 +35,7 @@ export interface MutationReport {
35
35
  killed: number;
36
36
  survived: number;
37
37
  timeout: number;
38
+ cancelled: number;
38
39
  equivalent: number;
39
40
  skipped: number;
40
41
  errors: number;
@@ -55,13 +56,36 @@ export interface MutationReport {
55
56
  timestamp: string;
56
57
  }
57
58
  export declare const MAX_MUTATIONS_PER_FUNCTION = 10;
59
+ type LegacySpawnSyncFn = typeof spawnSync;
60
+ export type MutationCommandResult = {
61
+ status: 'completed' | 'timeout' | 'cancelled' | 'spawn-error';
62
+ exitCode: number | null;
63
+ stdout: string;
64
+ stderr: string;
65
+ message?: string;
66
+ };
67
+ export type MutationCommandRunner = (args: {
68
+ executable: string;
69
+ args: string[];
70
+ cwd: string;
71
+ timeoutMs: number;
72
+ abortSignal?: AbortSignal;
73
+ }) => Promise<MutationCommandResult>;
74
+ export type MutationExecutionOptions = {
75
+ abortSignal?: AbortSignal;
76
+ runner?: MutationCommandRunner;
77
+ };
78
+ export declare const runMutationCommand: MutationCommandRunner;
58
79
  export declare const _internals: {
59
80
  executeMutation: typeof executeMutation;
60
81
  computeReport: typeof computeReport;
61
82
  executeMutationSuite: typeof executeMutationSuite;
62
- spawnSync: SpawnSyncFn;
83
+ spawnSync: LegacySpawnSyncFn;
84
+ runCommand: MutationCommandRunner;
85
+ runExternalTool: typeof runExternalTool;
86
+ resolveExecutableFromPath: typeof resolveExecutableFromPath;
63
87
  };
64
- export declare function executeMutation(patch: MutationPatch, testCommand: string[], testFiles: string[], workingDir: string): Promise<MutationResult>;
88
+ export declare function executeMutation(patch: MutationPatch, testCommand: string[], testFiles: string[], workingDir: string, options?: MutationExecutionOptions): Promise<MutationResult>;
65
89
  export declare function computeReport(results: MutationResult[], durationMs: number, budgetMs?: number): MutationReport;
66
- export declare function executeMutationSuite(patches: MutationPatch[], testCommand: string[], testFiles: string[], workingDir: string, budgetMs?: number, onProgress?: (completed: number, total: number, result: MutationResult) => void, sourceFiles?: Map<string, string>): Promise<MutationReport>;
90
+ export declare function executeMutationSuite(patches: MutationPatch[], testCommand: string[], testFiles: string[], workingDir: string, budgetMs?: number, onProgress?: (completed: number, total: number, result: MutationResult) => void, sourceFiles?: Map<string, string>, options?: MutationExecutionOptions): Promise<MutationReport>;
67
91
  export {};
@@ -1,5 +1,14 @@
1
1
  import type { DelegationCostFields } from './services/cost-accounting.js';
2
- export type TelemetryEvent = 'session_started' | 'session_ended' | 'agent_activated' | 'delegation_begin' | 'delegation_end' | 'task_state_changed' | 'gate_passed' | 'gate_failed' | 'gate_parse_error' | 'phase_changed' | 'budget_updated' | 'model_fallback' | 'hard_limit_hit' | 'revision_limit_hit' | 'loop_detected' | 'scope_violation' | 'qa_skip_violation' | 'heartbeat' | 'turbo_mode_changed' | 'auto_oversight_escalation' | 'environment_detected' | 'evidence_lock_acquired' | 'evidence_lock_contended' | 'evidence_lock_stale_recovered' | 'plan_ledger_cas_retry' | 'plan_md_write_failed' | 'snapshot_failed' | 'prm_pattern_detected' | 'prm_course_correction_injected' | 'prm_escalation_triggered' | 'prm_hard_stop';
2
+ export type TelemetryEvent = 'session_started' | 'session_ended' | 'agent_activated' | 'delegation_begin' | 'delegation_end' | 'task_state_changed' | 'gate_passed' | 'gate_failed' | 'gate_parse_error' | 'reviewer_gate_decision' | 'phase_changed' | 'budget_updated' | 'model_fallback' | 'hard_limit_hit' | 'revision_limit_hit' | 'loop_detected' | 'scope_violation' | 'qa_skip_violation' | 'heartbeat' | 'turbo_mode_changed' | 'auto_oversight_escalation' | 'environment_detected' | 'evidence_lock_acquired' | 'evidence_lock_contended' | 'evidence_lock_stale_recovered' | 'plan_ledger_cas_retry' | 'plan_md_write_failed' | 'snapshot_failed' | 'prm_pattern_detected' | 'prm_course_correction_injected' | 'prm_escalation_triggered' | 'prm_hard_stop';
3
+ /** Stable classification for how a reviewer-gate decision was established. */
4
+ export type ReviewerGateEvidenceKind = 'genuine' | 'fallback' | 'data_quality' | 'block';
5
+ /**
6
+ * Stable reason codes for reviewer-gate decision telemetry.
7
+ *
8
+ * These values are persisted in telemetry.jsonl and consumed by offline gate
9
+ * analytics, so additions are allowed but existing values must not be renamed.
10
+ */
11
+ export type ReviewerGateReasonCode = 'lean_turbo_completed_lane' | 'standard_turbo_non_tier3' | 'durable_evidence_complete' | 'workflow_state_complete' | 'stage_b_parallel_complete' | 'no_active_sessions' | 'zero_valid_sessions' | 'restart_recovery_complete' | 'scoped_delegation_complete' | 'unscoped_delegation_complete' | 'corrupt_evidence' | 'required_gates_missing' | 'inspection_error';
3
12
  export type TelemetryListener = (event: TelemetryEvent, data: Record<string, unknown>) => void;
4
13
  /**
5
14
  * Number of emits between rotation checks. 50 keeps the overhead at one
@@ -48,6 +57,7 @@ export declare const telemetry: {
48
57
  gatePassed(sessionId: string, gate: string, taskId: string): void;
49
58
  gateParseError(taskId: string, error: Error): void;
50
59
  gateFailed(sessionId: string, gate: string, taskId: string, reason: string): void;
60
+ reviewerGateDecision(sessionId: string, taskId: string, blocked: boolean, reasonCode: ReviewerGateReasonCode, evidenceKind: ReviewerGateEvidenceKind): void;
51
61
  phaseChanged(sessionId: string, oldPhase: number, newPhase: number): void;
52
62
  budgetUpdated(sessionId: string, budgetPct: number, agentName: string): void;
53
63
  modelFallback(sessionId: string, agentName: string, fromModel: string, toModel: string, reason: string): void;
@@ -11,6 +11,7 @@
11
11
  import type { ToolDefinition } from '@opencode-ai/plugin/tool';
12
12
  import type { AgentDefinition } from '../agents/index.js';
13
13
  import type { PluginConfig } from '../config/index.js';
14
+ import type { EvaluationModelDispatcher } from '../evaluation/model-dispatcher.js';
14
15
  /**
15
16
  * Construct the plugin tool object: one handler per manifest entry, with
16
17
  * `swarm_command` overridden by its dependency-injected instance.
@@ -21,4 +22,4 @@ import type { PluginConfig } from '../config/index.js';
21
22
  *
22
23
  * Knowledge tools are conditionally excluded when config.knowledge.enabled = false.
23
24
  */
24
- export declare function buildPluginToolObject(agents: Record<string, AgentDefinition>, config?: PluginConfig): Record<string, ToolDefinition>;
25
+ export declare function buildPluginToolObject(agents: Record<string, AgentDefinition>, config?: PluginConfig, evaluationModelDispatcher?: EvaluationModelDispatcher): Record<string, ToolDefinition>;
@@ -5,9 +5,16 @@
5
5
  import type { ToolDefinition } from '@opencode-ai/plugin/tool';
6
6
  import type { PluginConfig } from '../config';
7
7
  import type { EvidenceVerdict } from '../config/evidence-schema';
8
+ import { isSemgrepAvailable, runSemgrep } from '../sast/semgrep';
8
9
  export interface SastScanInput {
9
10
  /** List of files to scan */
10
11
  changed_files: string[];
12
+ /**
13
+ * Restrict execution to built-in Tier A rules. This is used by isolated,
14
+ * reproducible evaluation runs where PATH discovery and Semgrep execution
15
+ * (including remote `--config=auto`) are forbidden.
16
+ */
17
+ offline_only?: boolean;
11
18
  /** Minimum severity that causes failure (default: 'medium') */
12
19
  severity_threshold?: 'low' | 'medium' | 'high' | 'critical';
13
20
  /**
@@ -94,4 +101,6 @@ export declare const sast_scan: ToolDefinition;
94
101
  export declare const _internals: {
95
102
  sastScan: typeof sastScan;
96
103
  sast_scan: typeof sast_scan;
104
+ isSemgrepAvailable: typeof isSemgrepAvailable;
105
+ runSemgrep: typeof runSemgrep;
97
106
  };
@@ -1,4 +1,5 @@
1
1
  import type { AgentDefinition } from '../agents/index.js';
2
+ import type { EvaluationModelDispatcher } from '../evaluation/model-dispatcher.js';
2
3
  import { createSwarmTool } from './create-tool.js';
3
- export declare function createSwarmCommandTool(agents: Record<string, AgentDefinition>): ReturnType<typeof createSwarmTool>;
4
+ export declare function createSwarmCommandTool(agents: Record<string, AgentDefinition>, evaluationModelDispatcher?: EvaluationModelDispatcher): ReturnType<typeof createSwarmTool>;
4
5
  export declare const swarm_command: ReturnType<typeof createSwarmTool>;
@@ -3,8 +3,12 @@
3
3
  * Allows agents to mark tasks as pending, in_progress, completed, or blocked.
4
4
  */
5
5
  import type { ToolContext, ToolDefinition } from '@opencode-ai/plugin/tool';
6
+ import { readTaskEvidenceRaw } from '../gate-evidence.js';
6
7
  import { tryAcquireLock } from '../parallel/file-locks.js';
7
8
  import { loadPlan, updateTaskStatus } from '../plan/manager';
9
+ import { hasActiveLeanTurbo, hasActiveTurboMode } from '../state';
10
+ import { type ReviewerGateEvidenceKind, type ReviewerGateReasonCode } from '../telemetry.js';
11
+ import { verifyLeanTurboTaskCompletion } from '../turbo/lean/task-completion';
8
12
  import { resolveWorkingDirectory } from './resolve-working-directory';
9
13
  /**
10
14
  * Internal seams for test injection.
@@ -12,10 +16,16 @@ import { resolveWorkingDirectory } from './resolve-working-directory';
12
16
  * module-scope vi.mock, which leaks across files in Bun's shared test runner.
13
17
  */
14
18
  export declare const _internals: {
15
- readonly tryAcquireLock: typeof tryAcquireLock;
16
- readonly updateTaskStatus: typeof updateTaskStatus;
17
- readonly resolveWorkingDirectory: typeof resolveWorkingDirectory;
18
- readonly loadPlan: typeof loadPlan;
19
+ tryAcquireLock: typeof tryAcquireLock;
20
+ updateTaskStatus: typeof updateTaskStatus;
21
+ resolveWorkingDirectory: typeof resolveWorkingDirectory;
22
+ loadPlan: typeof loadPlan;
23
+ readTaskEvidenceRaw: typeof readTaskEvidenceRaw;
24
+ hasActiveLeanTurbo: typeof hasActiveLeanTurbo;
25
+ hasActiveTurboMode: typeof hasActiveTurboMode;
26
+ verifyLeanTurboTaskCompletion: typeof verifyLeanTurboTaskCompletion;
27
+ hasPassedDurableGateEvidence: typeof hasPassedDurableGateEvidence;
28
+ emitReviewerGateDecision: (sessionId: string, taskId: string, blocked: boolean, reasonCode: ReviewerGateReasonCode, evidenceKind: ReviewerGateEvidenceKind) => void;
19
29
  };
20
30
  /**
21
31
  * Arguments for the update_task_status tool
@@ -58,6 +68,7 @@ export interface ReviewerGateResult {
58
68
  blocked: boolean;
59
69
  reason: string;
60
70
  }
71
+ declare function hasPassedDurableGateEvidence(workingDirectory: string, taskId: string): boolean;
61
72
  /**
62
73
  * Check if a task has passed required QA gates using the state machine.
63
74
  * Requires the task to be in 'tests_run' or 'complete' state, which means
@@ -138,3 +149,4 @@ export declare function executeUpdateTaskStatus(args: UpdateTaskStatusArgs, fall
138
149
  * Tool definition for update_task_status
139
150
  */
140
151
  export declare const update_task_status: ToolDefinition;
152
+ export {};
@@ -7,9 +7,10 @@ export interface ExternalToolRunOptions {
7
7
  maxStdoutBytes: number;
8
8
  maxStderrBytes: number;
9
9
  env?: Record<string, string | undefined>;
10
+ abortSignal?: AbortSignal;
10
11
  }
11
12
  export interface ExternalToolRunResult {
12
- status: 'completed' | 'timeout' | 'spawn-error';
13
+ status: 'completed' | 'timeout' | 'cancelled' | 'spawn-error';
13
14
  exitCode: number | null;
14
15
  stdout: string;
15
16
  stderr: string;
@@ -0,0 +1,3 @@
1
+ export function validPort(port: number): boolean {
2
+ return port >= 1 && port <= 65_535;
3
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { validPort } from './defect';
3
+ test('rejects the first invalid port', () => expect(validPort(65_536)).toBe(false));
@@ -0,0 +1,3 @@
1
+ export function validPort(port: number): boolean {
2
+ return port >= 1 && port <= 65_536;
3
+ }
@@ -0,0 +1 @@
1
+ Inspect the upper-bound validation in `environment/defect.ts` and identify the invalid value it permits.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"boundary-error","source":"curated","split":"train","category":"boundary-error","protected":true,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"ac9cd9f603d86640900fe3af16e7373a322eb5deff009b72bdf4239df13661b8"}
@@ -0,0 +1,3 @@
1
+ export function accessLabel(admin: boolean): string {
2
+ return admin ? 'admin' : 'user';
3
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { accessLabel } from './defect';
3
+ test('labels administrators', () => expect(accessLabel(true)).toBe('admin'));
@@ -0,0 +1,3 @@
1
+ export function accessLabel(admin: boolean): string {
2
+ return admin ? 'user' : 'admin';
3
+ }
@@ -0,0 +1 @@
1
+ Inspect `environment/defect.ts` for swapped conditional branches and report the incorrect results.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"branch-swap","source":"curated","split":"train","category":"branch-swap","protected":false,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"f9b09fb7fa980fd94e1603a0e26e1ef43cd30a1d91211a195933913847943f23"}
@@ -0,0 +1,3 @@
1
+ export function pageStart(page: number, size: number): number {
2
+ return page * size;
3
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { pageStart } from './defect';
3
+ test('first page begins at zero', () => expect(pageStart(0, 20)).toBe(0));
@@ -0,0 +1,3 @@
1
+ export function pageStart(page: number, size: number): number {
2
+ return page * size + 1;
3
+ }
@@ -0,0 +1 @@
1
+ Review the pagination boundary in `environment/defect.ts` and identify the page that is skipped.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"curated-off-by-one","source":"curated","split":"train","category":"curated-off-by-one","protected":true,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"2894129b530e0624dc1739ee7910839d261728a8655474b0103b8c98a7ea9f81"}
@@ -0,0 +1,3 @@
1
+ export function normalized(value: string | undefined): string {
2
+ return value?.trim().toLowerCase() ?? '';
3
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { normalized } from './defect';
3
+ test('handles missing input', () => expect(normalized(undefined)).toBe(''));
@@ -0,0 +1,3 @@
1
+ export function normalized(value: string | undefined): string {
2
+ return value!.trim().toLowerCase();
3
+ }
@@ -0,0 +1 @@
1
+ Find the removed input guard in `environment/defect.ts` and state which input now fails.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"guard-removal","source":"curated","split":"train","category":"guard-removal","protected":true,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"7943c549ab0c9ce6503ca8df45a9430ae0a431094b4e358be43da1cfb63a1f7d"}
@@ -0,0 +1,3 @@
1
+ export function shellCommand(filename: string): string {
2
+ return `cat -- ${filename.replace(/[^A-Za-z0-9._-]/g, '')}`;
3
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { shellCommand } from './defect';
3
+ test('does not interpolate shell syntax', () => expect(shellCommand('a; rm -rf x')).not.toContain(';'));
@@ -0,0 +1,3 @@
1
+ export function shellCommand(filename: string): string {
2
+ return `cat ${filename}`;
3
+ }
@@ -0,0 +1 @@
1
+ Find the injection-prone command construction in `environment/defect.ts` and identify the unsafe input boundary.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"injection-prone-string","source":"curated","split":"train","category":"injection-prone-string","protected":true,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"0f45604dbdd251aaec2af3f82afeec10b2242b16a88d86087994918796a657f4"}
@@ -0,0 +1,4 @@
1
+ export function deleteAccount(actorRole: string, accountId: string): string {
2
+ if (actorRole !== 'admin') throw new Error('forbidden');
3
+ return `deleted:${accountId}`;
4
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { deleteAccount } from './defect';
3
+ test('blocks ordinary users', () => expect(() => deleteAccount('user', '42')).toThrow());
@@ -0,0 +1,3 @@
1
+ export function deleteAccount(_actorRole: string, accountId: string): string {
2
+ return `deleted:${accountId}`;
3
+ }
@@ -0,0 +1 @@
1
+ Review `environment/defect.ts` for a missing authorization check and state who can perform the protected action.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"missing-auth-check","source":"curated","split":"train","category":"missing-auth-check","protected":true,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"9b6d8ff362df8aad25d3c579b10e0fa202e923a0565cf5d18d4c4d1da75af482"}
@@ -0,0 +1,7 @@
1
+ export async function saveThenRead(
2
+ save: () => Promise<void>,
3
+ read: () => string,
4
+ ): Promise<string> {
5
+ await save();
6
+ return read();
7
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { saveThenRead } from './defect';
3
+ test('waits for save', async () => { let value = ''; expect(await saveThenRead(async () => { await Promise.resolve(); value = 'saved'; }, () => value)).toBe('saved'); });
@@ -0,0 +1,4 @@
1
+ export async function saveThenRead(save: () => Promise<void>, read: () => string): Promise<string> {
2
+ save();
3
+ return read();
4
+ }
@@ -0,0 +1 @@
1
+ Find the missing await in `environment/defect.ts` and explain the ordering failure.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"missing-await","source":"curated","split":"train","category":"missing-await","protected":true,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"d444592ce7d955882de61601bfe414be54c616f6c441ea735450e6716bc837fd"}
@@ -0,0 +1,3 @@
1
+ export function last<T>(items: T[]): T | undefined {
2
+ return items[items.length - 1];
3
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { last } from './defect';
3
+ test('returns the final item', () => expect(last([1, 2])).toBe(2));
@@ -0,0 +1,3 @@
1
+ export function last<T>(items: T[]): T | undefined {
2
+ return items[items.length];
3
+ }
@@ -0,0 +1 @@
1
+ Find the boundary defect in `environment/defect.ts`. Report whether the implementation is safe and explain the exact failing case.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"mutation-off-by-one","source":"curated","split":"train","category":"mutation-off-by-one","protected":true,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"9cec6a89ff87b1b85691313a2430916e3ebf393d532644b3f82faa10fe0203cd"}
@@ -0,0 +1,3 @@
1
+ export function displayName(name: string | null): string {
2
+ return name === null ? '' : name;
3
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { displayName } from './defect';
3
+ test('preserves a real name', () => expect(displayName('Ada')).toBe('Ada'));
@@ -0,0 +1,3 @@
1
+ export function displayName(name: string | null): string {
2
+ return name === null ? '' : null as unknown as string;
3
+ }
@@ -0,0 +1 @@
1
+ Inspect `environment/defect.ts` for an incorrect null substitution and report the observable regression.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"null-substitution","source":"curated","split":"train","category":"null-substitution","protected":true,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"5a335a9750981580e3feb6449d348f5111ff84a77058b8b0a50b57caf8ba9a6c"}
@@ -0,0 +1,3 @@
1
+ export function canRetry(attempt: number, maximum: number): boolean {
2
+ return attempt < maximum;
3
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { canRetry } from './defect';
3
+ test('allows attempts below the maximum', () => expect(canRetry(1, 3)).toBe(true));
@@ -0,0 +1,3 @@
1
+ export function canRetry(attempt: number, maximum: number): boolean {
2
+ return attempt > maximum;
3
+ }
@@ -0,0 +1 @@
1
+ Review the comparison in `environment/defect.ts` and identify the incorrect operator.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"operator-swap","source":"curated","split":"train","category":"operator-swap","protected":false,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"613431a4462af61ac236985724be5879b8b1d713ea090f74a8713011378b781e"}
@@ -0,0 +1,4 @@
1
+ export function record(items: string[], value: string): number {
2
+ items.push(value);
3
+ return items.length;
4
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { record } from './defect';
3
+ test('records the value', () => { const items: string[] = []; record(items, 'x'); expect(items).toEqual(['x']); });
@@ -0,0 +1,3 @@
1
+ export function record(items: string[], value: string): number {
2
+ return items.length + 1;
3
+ }
@@ -0,0 +1 @@
1
+ Identify the missing side effect in `environment/defect.ts` and explain how callers observe it.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"side-effect-deletion","source":"curated","split":"train","category":"side-effect-deletion","protected":false,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"d86bd1df176087b1157480043098782ea671553a713015ec734cd573fa23be88"}
@@ -0,0 +1,3 @@
1
+ export async function required(work: () => Promise<void>): Promise<void> {
2
+ await work();
3
+ }
@@ -0,0 +1,3 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { required } from './defect';
3
+ test('propagates failures', async () => expect(required(async () => { throw new Error('boom'); })).rejects.toThrow('boom'));
@@ -0,0 +1,3 @@
1
+ export async function required(work: () => Promise<void>): Promise<void> {
2
+ try { await work(); } catch { return; }
3
+ }
@@ -0,0 +1 @@
1
+ Inspect the error handling in `environment/defect.ts` and report why failures become invisible.
@@ -0,0 +1 @@
1
+ {"v":1,"id":"swallowed-error","source":"curated","split":"train","category":"swallowed-error","protected":true,"instructionPath":"instruction.md","environment":{"kind":"fixture","path":"environment"},"scorer":{"kind":"builtin","argv":["tier1-defect"],"timeoutMs":30000,"scoreRange":[0,1]},"provenance":{"origin":"opencode-swarm#1820","license":"MIT"},"contentHash":"4889fcc71918cfc11aec97258b1be29158e3e353a029446aad848dce4cf5583f"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.115.0",
3
+ "version": "7.116.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",
@@ -41,6 +41,7 @@
41
41
  "dist",
42
42
  "dist/lang/grammars",
43
43
  "binaries",
44
+ "evaluation-fixtures",
44
45
  ".opencode/skills/brainstorm",
45
46
  ".opencode/skills/specify",
46
47
  ".opencode/skills/clarify-spec",