opencode-swarm 7.81.3 → 7.82.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.
@@ -92,7 +92,11 @@ RESEARCH CONTEXT
92
92
  continue only non-dependent architect work: prepare the synthesis outline,
93
93
  normalize the RESEARCH CONTEXT citations, and draft disagreement categories.
94
94
  Do not call `convene_general_council` or present conclusions from running
95
- lanes. Each dispatch message must
95
+ lanes. Dispatch promptly do not accumulate extensive planning prose before the
96
+ call, or output truncation may swallow the tool call itself. Keep each lane `prompt`
97
+ compact: send shared context ONCE via the `common_prompt` field, or have lanes read
98
+ it from a file by absolute path, instead of inlining the same large blob into every
99
+ lane prompt. Each dispatch message must
96
100
  include:
97
101
  - The question
98
102
  - Round number: 1
@@ -71,7 +71,7 @@ Each explorer mission receives:
71
71
  - The scope map context from Step 2
72
72
  - Instruction: "You are performing a [LANE] audit. Report findings as candidate observations with severity (INFO/LOW/MEDIUM/HIGH/CRITICAL), location, and evidence."
73
73
 
74
- Explorer missions are dispatched in parallel waves. Launch the wave, record the returned `batch_id`, then continue deterministic architect work that does not depend on lane output: refine the scope map, build the candidate ledger shell, inspect local evidence with read-only tools, and prepare reviewer shard structure. Do not synthesize findings from running lanes.
74
+ Explorer missions are dispatched in parallel waves. Launch the wave promptly — do not accumulate extensive planning prose before the call, or output truncation may swallow the tool call itself. Launch the wave, record the returned `batch_id`, then continue deterministic architect work that does not depend on lane output: refine the scope map, build the candidate ledger shell, inspect local evidence with read-only tools, and prepare reviewer shard structure. Do not synthesize findings from running lanes. Keep each lane `prompt` compact: send shared context ONCE via the `common_prompt` field, or have lanes read it from a file by absolute path, instead of inlining the same large blob into every lane prompt — oversized inline prompts produce malformed or truncated tool-call JSON.
75
75
 
76
76
  At the Step 4 boundary, call `collect_lane_results` with `wait: true` for every open wave batch. Treat missing, stale, cancelled, or failed lanes as explicit coverage gaps; do not silently proceed past a required lane. If `dispatch_lanes_async` is unavailable, use blocking `dispatch_lanes` or parallel Task calls and record that async advisory lanes were unavailable.
77
77
 
@@ -102,7 +102,12 @@ Dispatch up to `max_researchers` `the active swarm's sme agent` calls with
102
102
  `batch_id`, then continue architect-owned retrieval quality work that does not
103
103
  depend on worker output: tighten the evidence ledger, check source authority,
104
104
  prepare reviewer shard structure, and identify unresolved gaps. Do not write final
105
- claims from running lanes. Each sme dispatch must
105
+ claims from running lanes. Dispatch promptly do not accumulate extensive planning
106
+ prose before the call, or output truncation may swallow the tool call itself. Keep each
107
+ lane `prompt` compact: send shared context ONCE via the `common_prompt` field, or have
108
+ lanes read it from a file by absolute path, instead of inlining the same large blob into
109
+ every lane prompt — oversized inline prompts produce malformed or truncated tool-call
110
+ JSON. Each sme dispatch must
106
111
  include:
107
112
  - `DOMAIN`: the subtopic
108
113
  - `TASK`: "Synthesize an evidence-grounded answer for this subtopic. Cite each
@@ -491,7 +491,7 @@ Tool candidate rules:
491
491
 
492
492
  ## Phase 3: Parallel Base Explorer Lanes
493
493
 
494
- Launch all base lanes with `dispatch_lanes_async` when available. Pass the six lane specs together, set `max_concurrent` to `6`, record the returned `batch_id`, and continue only non-dependent architect work: refine the obligation ledger, inspect PR metadata, prepare micro-lane trigger checks, and run deterministic read-only local tools. Do not synthesize findings from running lanes.
494
+ Launch all base lanes with `dispatch_lanes_async` when available. Pass the six lane specs together, set `max_concurrent` to `6`, record the returned `batch_id`, and continue only non-dependent architect work: refine the obligation ledger, inspect PR metadata, prepare micro-lane trigger checks, and run deterministic read-only local tools. Do not synthesize findings from running lanes. Keep each lane `prompt` compact: send the shared review context (PR diff, obligation ledger, scope) ONCE via the `common_prompt` field, or have lanes read it from a file by absolute path, instead of inlining the same large blob into all six prompts — oversized inline prompts produce malformed or truncated tool-call JSON and force clumsy file workarounds.
495
495
 
496
496
  Before Phase 4 or synthesis, call `collect_lane_results` with `wait: true` for the base-lane batch and treat the collected `lane_results` as the join barrier. Missing, stale, cancelled, or failed base lanes are explicit review coverage gaps. If `dispatch_lanes_async` is unavailable, use blocking `dispatch_lanes`; if that is also unavailable, simulate isolated passes. Do not let one lane's conclusions bias another lane, and record unavailable deterministic dispatch in the validation gate.
497
497
 
@@ -1,27 +1,14 @@
1
1
  /**
2
2
  * Background subagent completion observer/ingester.
3
3
  *
4
- * Registers as a swarm `event` hook to watch for the upstream background-completion signal:
5
- * a message part with `synthetic === true` whose text is a task envelope with
6
- * `state="completed"` or `state="error"`. When such a part correlates to a durable pending
7
- * background-delegation record, it is logged (debug-gated) as the empirical confirmation
8
- * instrument operators use to verify the runtime signal in a real environment.
9
- *
10
- * PR1 async advisory lanes ingest trusted terminal completions into the durable
11
- * background-delegation ledger only. This still NEVER advances workflow gates or records
12
- * gate evidence; gate-bearing execution is intentionally outside this advisory path.
13
- *
14
- * The `synthetic` flag is the trust gate (set by OpenCode, not the model/user). Non-synthetic
15
- * text that merely looks like an envelope is ignored. The observer is fail-open: any error is
16
- * swallowed so it can never block event delivery or plugin load (Invariant 1/10).
4
+ * Trusted synthetic background completions always settle the durable
5
+ * background-delegation ledger. Correctness-critical Stage B completions then
6
+ * pass through workspace freshness validation before gate evidence, receipts, or
7
+ * task workflow state can advance.
17
8
  */
18
9
  interface ObserverConfig {
19
10
  enabled: boolean;
20
11
  }
21
- /**
22
- * Build the background completion observer. Returns an `event` handler suitable for the
23
- * OpenCode plugin `event` hook. No-op (cheap early return) when the feature is disabled.
24
- */
25
12
  export declare function createBackgroundCompletionObserver(opts: {
26
13
  config: ObserverConfig;
27
14
  directory: string;
@@ -12,8 +12,8 @@
12
12
  *
13
13
  * Scope: dispatch records `pending`/`running` snapshots, collection or trusted synthetic
14
14
  * completions record terminal snapshots, and the stale sweep records `stale` snapshots.
15
- * This store still has NO gate advancement and NO gate evidence side effect; it is an
16
- * advisory result ledger only.
15
+ * This store itself has no gate-advancement side effect. Stage B gate ingestion is a
16
+ * separate consumer of trusted terminal snapshots.
17
17
  *
18
18
  * Concurrency: all writes (append, sweep) run under a single project-scoped lock via
19
19
  * `withEvidenceLock`, so concurrent dispatches/sweeps cannot interleave appends. Reads are
@@ -23,7 +23,7 @@
23
23
  * `.swarm/` (Invariant 4).
24
24
  */
25
25
  export declare const BACKGROUND_DELEGATIONS_FILE = "background-delegations.jsonl";
26
- export type BackgroundDelegationStatus = 'pending' | 'running' | 'completed' | 'error' | 'cancelled' | 'stale' | 'consumed';
26
+ export type BackgroundDelegationStatus = 'pending' | 'running' | 'ingestion_error' | 'completed' | 'error' | 'cancelled' | 'stale' | 'consumed';
27
27
  export interface BackgroundDelegationRecord {
28
28
  schemaVersion: 1 | 2;
29
29
  /** Subagent session id from the dispatch envelope — the correlation key. */
@@ -56,6 +56,7 @@ export interface BackgroundDelegationRecord {
56
56
  promptHash?: string;
57
57
  /** Project/root provenance captured at dispatch time. */
58
58
  workspace?: BackgroundWorkspaceSnapshot;
59
+ prompt?: BackgroundPromptSnapshot;
59
60
  generation?: number;
60
61
  result?: BackgroundDelegationResult;
61
62
  completedAt?: number;
@@ -67,6 +68,12 @@ export interface BackgroundWorkspaceSnapshot {
67
68
  prHeadSha: string | null;
68
69
  scope: string | null;
69
70
  }
71
+ export interface BackgroundPromptSnapshot {
72
+ text: string;
73
+ chars: number;
74
+ truncated: boolean;
75
+ digest: string;
76
+ }
70
77
  export interface BackgroundDelegationResult {
71
78
  text?: string;
72
79
  error?: string;
@@ -101,6 +108,7 @@ export interface RecordPendingInput {
101
108
  mode?: string;
102
109
  promptHash?: string;
103
110
  workspace?: BackgroundWorkspaceSnapshot;
111
+ prompt?: BackgroundPromptSnapshot;
104
112
  generation?: number;
105
113
  }
106
114
  /**
@@ -113,6 +121,7 @@ export interface RecordPendingInput {
113
121
  export declare function recordPendingDelegation(directory: string, input: RecordPendingInput, options?: {
114
122
  staleTimeoutMs?: number;
115
123
  }): Promise<BackgroundDelegationRecord | null>;
124
+ export declare function buildPromptSnapshot(text: string, maxChars: number): BackgroundPromptSnapshot;
116
125
  export declare function appendDelegationTransition(directory: string, correlationId: string, transition: {
117
126
  status: BackgroundDelegationStatus;
118
127
  result?: BackgroundDelegationResult;
@@ -0,0 +1,18 @@
1
+ import type { BackgroundDelegationRecord, BackgroundDelegationResult } from './pending-delegations.js';
2
+ export interface StageBIngestionResult {
3
+ ok: boolean;
4
+ consumed: boolean;
5
+ stale?: boolean;
6
+ reason?: string;
7
+ }
8
+ export declare function isBackgroundGateBearingRecord(record: BackgroundDelegationRecord): boolean;
9
+ export declare function validateStageBWorkspace(directory: string, record: BackgroundDelegationRecord): {
10
+ ok: boolean;
11
+ stale: boolean;
12
+ reason?: string;
13
+ };
14
+ export declare function ingestBackgroundStageBCompletion(args: {
15
+ directory: string;
16
+ record: BackgroundDelegationRecord;
17
+ result: BackgroundDelegationResult;
18
+ }): Promise<StageBIngestionResult>;
@@ -0,0 +1,31 @@
1
+ import * as child_process from 'node:child_process';
2
+ import type { BackgroundWorkspaceSnapshot } from './pending-delegations.js';
3
+ type SpawnSync = typeof child_process.spawnSync;
4
+ interface CaptureWorkspaceSnapshotOptions {
5
+ scope?: string | null;
6
+ prHeadSha?: string | null;
7
+ /**
8
+ * Re-resolve the current upstream ref for freshness validation. When the
9
+ * dispatch captured an explicit PR head SHA, ingestion must compare against a
10
+ * live local ref, not replay the stored metadata back into the snapshot.
11
+ */
12
+ resolveCurrentPrHeadSha?: boolean;
13
+ }
14
+ export declare function captureWorkspaceSnapshot(directory: string, optionsOrScope?: string | null | CaptureWorkspaceSnapshotOptions, prHeadShaArg?: string | null): BackgroundWorkspaceSnapshot;
15
+ export declare function workspaceSnapshotMatches(expected: BackgroundWorkspaceSnapshot | undefined, current: BackgroundWorkspaceSnapshot): {
16
+ ok: true;
17
+ } | {
18
+ ok: false;
19
+ reason: string;
20
+ };
21
+ export type WorkspaceFreshness = ReturnType<typeof workspaceSnapshotMatches>;
22
+ export declare const compareWorkspaceSnapshot: typeof workspaceSnapshotMatches;
23
+ export declare function compareWorkspaceSnapshots(expected: BackgroundWorkspaceSnapshot | undefined, current: BackgroundWorkspaceSnapshot): {
24
+ stale: boolean;
25
+ reason?: string;
26
+ };
27
+ export declare function digest(text: string): string;
28
+ export declare const _internals: {
29
+ spawnSync: SpawnSync;
30
+ };
31
+ export {};
package/dist/cli/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "opencode-swarm",
55
- version: "7.81.3",
55
+ version: "7.82.0",
56
56
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
57
57
  main: "dist/index.js",
58
58
  types: "dist/index.d.ts",
@@ -17763,15 +17763,15 @@ var init_tool_metadata = __esm(() => {
17763
17763
  ]
17764
17764
  },
17765
17765
  dispatch_lanes: {
17766
- description: "dispatch multiple read-only exploration/review lanes concurrently and return a structured join result",
17766
+ description: "dispatch read-only exploration/review lanes concurrently and BLOCK until all finish; prefer dispatch_lanes_async for non-blocking dispatch, use this only when promptAsync is unavailable",
17767
17767
  agents: ["architect"]
17768
17768
  },
17769
17769
  dispatch_lanes_async: {
17770
- description: "launch multiple read-only advisory lanes asynchronously and return a batch id for later collection",
17770
+ description: "launch read-only advisory lanes non-blockingly and return a batch id immediately so you can keep working; join later with collect_lane_results",
17771
17771
  agents: ["architect"]
17772
17772
  },
17773
17773
  collect_lane_results: {
17774
- description: "collect or poll results for a dispatch_lanes_async advisory batch without advancing workflow gates",
17774
+ description: "collect or poll results for a dispatch_lanes_async batch; this is the required join barrier for advisory lane workflows and does not advance workflow gates",
17775
17775
  agents: ["architect"]
17776
17776
  },
17777
17777
  summarize_work: {
@@ -41475,6 +41475,14 @@ async function activateProposal(directory, slug, force = false, options = {}) {
41475
41475
  reason: `proposal not found or already activated: ${readErr instanceof Error ? readErr.message : String(readErr)}`
41476
41476
  };
41477
41477
  }
41478
+ if (await isRejectedSkillContent(directory, cleanSlug, proposalContent)) {
41479
+ return {
41480
+ activated: false,
41481
+ from,
41482
+ to,
41483
+ reason: "previously rejected equivalent content"
41484
+ };
41485
+ }
41478
41486
  const flipped = proposalContent.replace(/^status:\s*draft\s*$/m, "status: active");
41479
41487
  let evaluation;
41480
41488
  if (options.evaluate) {
@@ -41497,7 +41505,7 @@ async function activateProposal(directory, slug, force = false, options = {}) {
41497
41505
  await appendRejectedSkillEdit({
41498
41506
  directory,
41499
41507
  slug: cleanSlug,
41500
- candidateContent: flipped,
41508
+ candidateContent: proposalContent,
41501
41509
  incumbentContent,
41502
41510
  operation: options.operation ?? "skill_apply"
41503
41511
  }, evaluation);
@@ -48,6 +48,14 @@ export interface ReviewerReceiptInput {
48
48
  export interface ReviewerReceiptOutput {
49
49
  output?: unknown;
50
50
  }
51
+ export interface ReviewerReceiptTranscriptInput {
52
+ targetAgent?: string;
53
+ prompt: string;
54
+ transcript: string;
55
+ sessionID?: string;
56
+ sessionId?: string;
57
+ }
58
+ export declare function collectReviewerReceiptFromTranscript(directory: string, input: ReviewerReceiptTranscriptInput): Promise<string | null>;
51
59
  /**
52
60
  * `tool.execute.after` collector. When a reviewer Task returns, parse its
53
61
  * verdict block and persist a durable review receipt. No-op for non-reviewer