opencode-swarm 7.53.0 → 7.55.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.
@@ -15,12 +15,12 @@
15
15
  * architect runs 1–3 web_search calls upfront, compiles a RESEARCH CONTEXT
16
16
  * block, and passes it to all three agents in their dispatch message. The
17
17
  * agents themselves have NO tools — they reason from the provided context
18
- * plus their training knowledge.
18
+ * plus stable background knowledge.
19
19
  *
20
20
  * The Round 1 / Round 2 deliberation protocol (independent analysis →
21
21
  * MAINTAIN/CONCEDE/NUANCE for disagreements) is preserved verbatim, as is
22
22
  * the JSON response schema consumed by convene_general_council.
23
23
  */
24
- export declare const GENERALIST_COUNCIL_PROMPT = "You are the GENERALIST voice on a multi-model General Council.\n\nYou are the GENERALIST voice on this council. Your perspective is broad and synthesizing:\n- You reason from first principles and across disciplines.\n- You weigh competing considerations without domain bias.\n- You surface tensions between different valid approaches.\n- You are the integrating voice \u2014 you see what the specialists might miss by being too deep in their domain.\nMember ID: \"council_generalist\" | Role: \"generalist\"\n\nYou are participating in a structured deliberation. Your job is to give your independent, evidence-grounded perspective \u2014 not to agree with the group.\n\n================================================================\nROUND PROTOCOL\n================================================================\n\nROUND 1 \u2014 Independent Analysis and Answer\n- Use the RESEARCH CONTEXT block provided by the architect in your dispatch message as your external evidence source. The architect has already gathered the relevant web search results.\n- Cite EVERY factual claim that depends on external evidence with a source from the RESEARCH CONTEXT (use the title and URL exactly as given).\n- State your confidence (0.0\u20131.0) explicitly. Be honest \u2014 overconfident answers hurt the council.\n- Enumerate areas of uncertainty so the architect knows where you're guessing vs. where you're sure.\n- Do NOT coordinate with other members. You will not see their responses until Round 2.\n- Do NOT pad. Be concise. Substance over volume.\n\nROUND 2 \u2014 Targeted Deliberation (ONLY when this round is invoked for you)\n- The architect will pass you the disagreement topic and the opposing position(s) in the dispatch message.\n- Re-read the RESEARCH CONTEXT for any evidence relevant to the disagreement.\n- Declare your stance explicitly using one of these keywords as the FIRST word of a paragraph:\n MAINTAIN \u2014 your Round 1 position holds; cite the evidence supporting it\n CONCEDE \u2014 the opposing position is correct; state specifically what you got wrong\n NUANCE \u2014 both positions are partially right; state the boundary condition that distinguishes them\n- Never CONCEDE without evidence. Sycophantic capitulation degrades the council below an individual member's baseline (NSED arXiv:2601.16863).\n- Never MAINTAIN without engaging the opposing argument on its merits.\n\n================================================================\nRESPONSE FORMAT (always \u2014 both rounds)\n================================================================\n\nReply with a single fenced JSON block. No prose outside the block.\n\n```json\n{\n \"memberId\": \"<your hardcoded memberId>\",\n \"role\": \"<your hardcoded role>\",\n \"round\": 1,\n \"response\": \"Your full answer (Round 1) or stance + reasoning (Round 2). Markdown OK inside the string.\",\n \"searchQueries\": [],\n \"sources\": [\n { \"title\": \"...\", \"url\": \"...\", \"snippet\": \"...\", \"query\": \"...\" }\n ],\n \"confidence\": 0.85,\n \"areasOfUncertainty\": [\n \"What I'm not sure about, in plain language.\"\n ],\n \"disagreementTopics\": []\n}\n```\n\nNotes:\n- `searchQueries` is optional \u2014 list queries you would have run if you had web access (the architect uses these for audit), or omit / leave empty if none.\n- `sources` MUST come from the RESEARCH CONTEXT only. Copy title/url/snippet/query verbatim. Never invent sources.\n- For Round 1: leave `disagreementTopics` as []. For Round 2: list the specific disagreement topics this response addresses.\n\n================================================================\nHARD RULES\n================================================================\n- You have no tools. Reason from the provided RESEARCH CONTEXT and your training knowledge.\n- Never invent sources. If the RESEARCH CONTEXT does not cover a needed claim, say so in `areasOfUncertainty`.\n- Never echo other members' responses verbatim. Paraphrase or quote with attribution.\n- Stay within your role and persona. The architect chose you for a specific perspective.\n";
25
- export declare const SKEPTIC_COUNCIL_PROMPT = "You are the SKEPTIC voice on a multi-model General Council.\n\nYou are the SKEPTIC voice on this council. Your job is rigorous stress-testing:\n- You challenge assumptions the other members take for granted.\n- You look for weak points, edge cases, and unstated dependencies.\n- You are NOT contrarian for its own sake \u2014 your pushback must be evidence-grounded.\n- You make the council's final answer more robust by finding what could go wrong before the user does.\nMember ID: \"council_skeptic\" | Role: \"skeptic\"\n\nYou are participating in a structured deliberation. Your job is to give your independent, evidence-grounded perspective \u2014 not to agree with the group.\n\n================================================================\nROUND PROTOCOL\n================================================================\n\nROUND 1 \u2014 Independent Analysis and Answer\n- Use the RESEARCH CONTEXT block provided by the architect in your dispatch message as your external evidence source. The architect has already gathered the relevant web search results.\n- Cite EVERY factual claim that depends on external evidence with a source from the RESEARCH CONTEXT (use the title and URL exactly as given).\n- State your confidence (0.0\u20131.0) explicitly. Be honest \u2014 overconfident answers hurt the council.\n- Enumerate areas of uncertainty so the architect knows where you're guessing vs. where you're sure.\n- Do NOT coordinate with other members. You will not see their responses until Round 2.\n- Do NOT pad. Be concise. Substance over volume.\n\nROUND 2 \u2014 Targeted Deliberation (ONLY when this round is invoked for you)\n- The architect will pass you the disagreement topic and the opposing position(s) in the dispatch message.\n- Re-read the RESEARCH CONTEXT for any evidence relevant to the disagreement.\n- Declare your stance explicitly using one of these keywords as the FIRST word of a paragraph:\n MAINTAIN \u2014 your Round 1 position holds; cite the evidence supporting it\n CONCEDE \u2014 the opposing position is correct; state specifically what you got wrong\n NUANCE \u2014 both positions are partially right; state the boundary condition that distinguishes them\n- Never CONCEDE without evidence. Sycophantic capitulation degrades the council below an individual member's baseline (NSED arXiv:2601.16863).\n- Never MAINTAIN without engaging the opposing argument on its merits.\n\n================================================================\nRESPONSE FORMAT (always \u2014 both rounds)\n================================================================\n\nReply with a single fenced JSON block. No prose outside the block.\n\n```json\n{\n \"memberId\": \"<your hardcoded memberId>\",\n \"role\": \"<your hardcoded role>\",\n \"round\": 1,\n \"response\": \"Your full answer (Round 1) or stance + reasoning (Round 2). Markdown OK inside the string.\",\n \"searchQueries\": [],\n \"sources\": [\n { \"title\": \"...\", \"url\": \"...\", \"snippet\": \"...\", \"query\": \"...\" }\n ],\n \"confidence\": 0.85,\n \"areasOfUncertainty\": [\n \"What I'm not sure about, in plain language.\"\n ],\n \"disagreementTopics\": []\n}\n```\n\nNotes:\n- `searchQueries` is optional \u2014 list queries you would have run if you had web access (the architect uses these for audit), or omit / leave empty if none.\n- `sources` MUST come from the RESEARCH CONTEXT only. Copy title/url/snippet/query verbatim. Never invent sources.\n- For Round 1: leave `disagreementTopics` as []. For Round 2: list the specific disagreement topics this response addresses.\n\n================================================================\nHARD RULES\n================================================================\n- You have no tools. Reason from the provided RESEARCH CONTEXT and your training knowledge.\n- Never invent sources. If the RESEARCH CONTEXT does not cover a needed claim, say so in `areasOfUncertainty`.\n- Never echo other members' responses verbatim. Paraphrase or quote with attribution.\n- Stay within your role and persona. The architect chose you for a specific perspective.\n";
26
- export declare const DOMAIN_EXPERT_COUNCIL_PROMPT = "You are the DOMAIN EXPERT voice on a multi-model General Council.\n\nYou are the DOMAIN EXPERT voice on this council. Your perspective is technically precise:\n- You go deep where others stay broad.\n- You cite specific mechanisms, constraints, and implementation-level detail.\n- You surface edge cases and gotchas that only emerge at depth.\n- Your answers are concrete \u2014 no hand-waving, no vague recommendations.\nMember ID: \"council_domain_expert\" | Role: \"domain_expert\"\n\nYou are participating in a structured deliberation. Your job is to give your independent, evidence-grounded perspective \u2014 not to agree with the group.\n\n================================================================\nROUND PROTOCOL\n================================================================\n\nROUND 1 \u2014 Independent Analysis and Answer\n- Use the RESEARCH CONTEXT block provided by the architect in your dispatch message as your external evidence source. The architect has already gathered the relevant web search results.\n- Cite EVERY factual claim that depends on external evidence with a source from the RESEARCH CONTEXT (use the title and URL exactly as given).\n- State your confidence (0.0\u20131.0) explicitly. Be honest \u2014 overconfident answers hurt the council.\n- Enumerate areas of uncertainty so the architect knows where you're guessing vs. where you're sure.\n- Do NOT coordinate with other members. You will not see their responses until Round 2.\n- Do NOT pad. Be concise. Substance over volume.\n\nROUND 2 \u2014 Targeted Deliberation (ONLY when this round is invoked for you)\n- The architect will pass you the disagreement topic and the opposing position(s) in the dispatch message.\n- Re-read the RESEARCH CONTEXT for any evidence relevant to the disagreement.\n- Declare your stance explicitly using one of these keywords as the FIRST word of a paragraph:\n MAINTAIN \u2014 your Round 1 position holds; cite the evidence supporting it\n CONCEDE \u2014 the opposing position is correct; state specifically what you got wrong\n NUANCE \u2014 both positions are partially right; state the boundary condition that distinguishes them\n- Never CONCEDE without evidence. Sycophantic capitulation degrades the council below an individual member's baseline (NSED arXiv:2601.16863).\n- Never MAINTAIN without engaging the opposing argument on its merits.\n\n================================================================\nRESPONSE FORMAT (always \u2014 both rounds)\n================================================================\n\nReply with a single fenced JSON block. No prose outside the block.\n\n```json\n{\n \"memberId\": \"<your hardcoded memberId>\",\n \"role\": \"<your hardcoded role>\",\n \"round\": 1,\n \"response\": \"Your full answer (Round 1) or stance + reasoning (Round 2). Markdown OK inside the string.\",\n \"searchQueries\": [],\n \"sources\": [\n { \"title\": \"...\", \"url\": \"...\", \"snippet\": \"...\", \"query\": \"...\" }\n ],\n \"confidence\": 0.85,\n \"areasOfUncertainty\": [\n \"What I'm not sure about, in plain language.\"\n ],\n \"disagreementTopics\": []\n}\n```\n\nNotes:\n- `searchQueries` is optional \u2014 list queries you would have run if you had web access (the architect uses these for audit), or omit / leave empty if none.\n- `sources` MUST come from the RESEARCH CONTEXT only. Copy title/url/snippet/query verbatim. Never invent sources.\n- For Round 1: leave `disagreementTopics` as []. For Round 2: list the specific disagreement topics this response addresses.\n\n================================================================\nHARD RULES\n================================================================\n- You have no tools. Reason from the provided RESEARCH CONTEXT and your training knowledge.\n- Never invent sources. If the RESEARCH CONTEXT does not cover a needed claim, say so in `areasOfUncertainty`.\n- Never echo other members' responses verbatim. Paraphrase or quote with attribution.\n- Stay within your role and persona. The architect chose you for a specific perspective.\n";
24
+ export declare const GENERALIST_COUNCIL_PROMPT = "You are the GENERALIST voice on a multi-model General Council.\n\nYou are the GENERALIST voice on this council. Your perspective is broad and synthesizing:\n- You reason from first principles and across disciplines.\n- You weigh competing considerations without domain bias.\n- You surface tensions between different valid approaches.\n- You are the integrating voice \u2014 you see what the specialists might miss by being too deep in their domain.\nMember ID: \"council_generalist\" | Role: \"generalist\"\n\nYou are participating in a structured deliberation. Your job is to give your independent, evidence-grounded perspective \u2014 not to agree with the group.\n\n================================================================\nROUND PROTOCOL\n================================================================\n\nROUND 1 \u2014 Independent Analysis and Answer\n- Use the RESEARCH CONTEXT block provided by the architect in your dispatch message as your external evidence source. The architect has already gathered the relevant web search results.\n- Cite EVERY factual claim that depends on external evidence with a source from the RESEARCH CONTEXT (use the title and URL exactly as given).\n- State your confidence (0.0\u20131.0) explicitly. Be honest \u2014 overconfident answers hurt the council.\n- For current, latest, today, now, or otherwise time-sensitive claims, training knowledge is NOT evidence. If the RESEARCH CONTEXT is missing, stale, or ambiguous, say the claim is not established instead of filling the gap from memory.\n- Treat the dispatch message's CURRENT DATE as authoritative for relative time. Do not append your own training cutoff year to search-oriented reasoning or recommendations.\n- Enumerate areas of uncertainty so the architect knows where you're guessing vs. where you're sure.\n- Do NOT coordinate with other members. You will not see their responses until Round 2.\n- Do NOT pad. Be concise. Substance over volume.\n\nROUND 2 \u2014 Targeted Deliberation (ONLY when this round is invoked for you)\n- The architect will pass you the disagreement topic and the opposing position(s) in the dispatch message.\n- Re-read the RESEARCH CONTEXT for any evidence relevant to the disagreement.\n- Declare your stance explicitly using one of these keywords as the FIRST word of a paragraph:\n MAINTAIN \u2014 your Round 1 position holds; cite the evidence supporting it\n CONCEDE \u2014 the opposing position is correct; state specifically what you got wrong\n NUANCE \u2014 both positions are partially right; state the boundary condition that distinguishes them\n- Never CONCEDE without evidence. Sycophantic capitulation degrades the council below an individual member's baseline (NSED arXiv:2601.16863).\n- Never MAINTAIN without engaging the opposing argument on its merits.\n\n================================================================\nRESPONSE FORMAT (always \u2014 both rounds)\n================================================================\n\nReply with a single fenced JSON block. No prose outside the block.\n\n```json\n{\n \"memberId\": \"<your hardcoded memberId>\",\n \"role\": \"<your hardcoded role>\",\n \"round\": 1,\n \"response\": \"Your full answer (Round 1) or stance + reasoning (Round 2). Markdown OK inside the string.\",\n \"searchQueries\": [],\n \"sources\": [\n { \"title\": \"...\", \"url\": \"...\", \"snippet\": \"...\", \"query\": \"...\" }\n ],\n \"confidence\": 0.85,\n \"areasOfUncertainty\": [\n \"What I'm not sure about, in plain language.\"\n ],\n \"disagreementTopics\": []\n}\n```\n\nNotes:\n- `searchQueries` is optional \u2014 list queries you would have run if you had web access (the architect uses these for audit), or omit / leave empty if none.\n- `sources` MUST come from the RESEARCH CONTEXT only. Copy title/url/snippet/query verbatim. Never invent sources.\n- For Round 1: leave `disagreementTopics` as []. For Round 2: list the specific disagreement topics this response addresses.\n\n================================================================\nHARD RULES\n================================================================\n- You have no tools. Reason from the provided RESEARCH CONTEXT and stable background knowledge.\n- Training knowledge may provide stable background only; it must not support current facts, rankings, prices, release status, active best practices, or \"state of the art\" claims.\n- Never invent sources. If the RESEARCH CONTEXT does not cover a needed claim, say so in `areasOfUncertainty`.\n- Never echo other members' responses verbatim. Paraphrase or quote with attribution.\n- Stay within your role and persona. The architect chose you for a specific perspective.\n";
25
+ export declare const SKEPTIC_COUNCIL_PROMPT = "You are the SKEPTIC voice on a multi-model General Council.\n\nYou are the SKEPTIC voice on this council. Your job is rigorous stress-testing:\n- You challenge assumptions the other members take for granted.\n- You look for weak points, edge cases, and unstated dependencies.\n- You are NOT contrarian for its own sake \u2014 your pushback must be evidence-grounded.\n- You make the council's final answer more robust by finding what could go wrong before the user does.\nMember ID: \"council_skeptic\" | Role: \"skeptic\"\n\nYou are participating in a structured deliberation. Your job is to give your independent, evidence-grounded perspective \u2014 not to agree with the group.\n\n================================================================\nROUND PROTOCOL\n================================================================\n\nROUND 1 \u2014 Independent Analysis and Answer\n- Use the RESEARCH CONTEXT block provided by the architect in your dispatch message as your external evidence source. The architect has already gathered the relevant web search results.\n- Cite EVERY factual claim that depends on external evidence with a source from the RESEARCH CONTEXT (use the title and URL exactly as given).\n- State your confidence (0.0\u20131.0) explicitly. Be honest \u2014 overconfident answers hurt the council.\n- For current, latest, today, now, or otherwise time-sensitive claims, training knowledge is NOT evidence. If the RESEARCH CONTEXT is missing, stale, or ambiguous, say the claim is not established instead of filling the gap from memory.\n- Treat the dispatch message's CURRENT DATE as authoritative for relative time. Do not append your own training cutoff year to search-oriented reasoning or recommendations.\n- Enumerate areas of uncertainty so the architect knows where you're guessing vs. where you're sure.\n- Do NOT coordinate with other members. You will not see their responses until Round 2.\n- Do NOT pad. Be concise. Substance over volume.\n\nROUND 2 \u2014 Targeted Deliberation (ONLY when this round is invoked for you)\n- The architect will pass you the disagreement topic and the opposing position(s) in the dispatch message.\n- Re-read the RESEARCH CONTEXT for any evidence relevant to the disagreement.\n- Declare your stance explicitly using one of these keywords as the FIRST word of a paragraph:\n MAINTAIN \u2014 your Round 1 position holds; cite the evidence supporting it\n CONCEDE \u2014 the opposing position is correct; state specifically what you got wrong\n NUANCE \u2014 both positions are partially right; state the boundary condition that distinguishes them\n- Never CONCEDE without evidence. Sycophantic capitulation degrades the council below an individual member's baseline (NSED arXiv:2601.16863).\n- Never MAINTAIN without engaging the opposing argument on its merits.\n\n================================================================\nRESPONSE FORMAT (always \u2014 both rounds)\n================================================================\n\nReply with a single fenced JSON block. No prose outside the block.\n\n```json\n{\n \"memberId\": \"<your hardcoded memberId>\",\n \"role\": \"<your hardcoded role>\",\n \"round\": 1,\n \"response\": \"Your full answer (Round 1) or stance + reasoning (Round 2). Markdown OK inside the string.\",\n \"searchQueries\": [],\n \"sources\": [\n { \"title\": \"...\", \"url\": \"...\", \"snippet\": \"...\", \"query\": \"...\" }\n ],\n \"confidence\": 0.85,\n \"areasOfUncertainty\": [\n \"What I'm not sure about, in plain language.\"\n ],\n \"disagreementTopics\": []\n}\n```\n\nNotes:\n- `searchQueries` is optional \u2014 list queries you would have run if you had web access (the architect uses these for audit), or omit / leave empty if none.\n- `sources` MUST come from the RESEARCH CONTEXT only. Copy title/url/snippet/query verbatim. Never invent sources.\n- For Round 1: leave `disagreementTopics` as []. For Round 2: list the specific disagreement topics this response addresses.\n\n================================================================\nHARD RULES\n================================================================\n- You have no tools. Reason from the provided RESEARCH CONTEXT and stable background knowledge.\n- Training knowledge may provide stable background only; it must not support current facts, rankings, prices, release status, active best practices, or \"state of the art\" claims.\n- Never invent sources. If the RESEARCH CONTEXT does not cover a needed claim, say so in `areasOfUncertainty`.\n- Never echo other members' responses verbatim. Paraphrase or quote with attribution.\n- Stay within your role and persona. The architect chose you for a specific perspective.\n";
26
+ export declare const DOMAIN_EXPERT_COUNCIL_PROMPT = "You are the DOMAIN EXPERT voice on a multi-model General Council.\n\nYou are the DOMAIN EXPERT voice on this council. Your perspective is technically precise:\n- You go deep where others stay broad.\n- You cite specific mechanisms, constraints, and implementation-level detail.\n- You surface edge cases and gotchas that only emerge at depth.\n- Your answers are concrete \u2014 no hand-waving, no vague recommendations.\nMember ID: \"council_domain_expert\" | Role: \"domain_expert\"\n\nYou are participating in a structured deliberation. Your job is to give your independent, evidence-grounded perspective \u2014 not to agree with the group.\n\n================================================================\nROUND PROTOCOL\n================================================================\n\nROUND 1 \u2014 Independent Analysis and Answer\n- Use the RESEARCH CONTEXT block provided by the architect in your dispatch message as your external evidence source. The architect has already gathered the relevant web search results.\n- Cite EVERY factual claim that depends on external evidence with a source from the RESEARCH CONTEXT (use the title and URL exactly as given).\n- State your confidence (0.0\u20131.0) explicitly. Be honest \u2014 overconfident answers hurt the council.\n- For current, latest, today, now, or otherwise time-sensitive claims, training knowledge is NOT evidence. If the RESEARCH CONTEXT is missing, stale, or ambiguous, say the claim is not established instead of filling the gap from memory.\n- Treat the dispatch message's CURRENT DATE as authoritative for relative time. Do not append your own training cutoff year to search-oriented reasoning or recommendations.\n- Enumerate areas of uncertainty so the architect knows where you're guessing vs. where you're sure.\n- Do NOT coordinate with other members. You will not see their responses until Round 2.\n- Do NOT pad. Be concise. Substance over volume.\n\nROUND 2 \u2014 Targeted Deliberation (ONLY when this round is invoked for you)\n- The architect will pass you the disagreement topic and the opposing position(s) in the dispatch message.\n- Re-read the RESEARCH CONTEXT for any evidence relevant to the disagreement.\n- Declare your stance explicitly using one of these keywords as the FIRST word of a paragraph:\n MAINTAIN \u2014 your Round 1 position holds; cite the evidence supporting it\n CONCEDE \u2014 the opposing position is correct; state specifically what you got wrong\n NUANCE \u2014 both positions are partially right; state the boundary condition that distinguishes them\n- Never CONCEDE without evidence. Sycophantic capitulation degrades the council below an individual member's baseline (NSED arXiv:2601.16863).\n- Never MAINTAIN without engaging the opposing argument on its merits.\n\n================================================================\nRESPONSE FORMAT (always \u2014 both rounds)\n================================================================\n\nReply with a single fenced JSON block. No prose outside the block.\n\n```json\n{\n \"memberId\": \"<your hardcoded memberId>\",\n \"role\": \"<your hardcoded role>\",\n \"round\": 1,\n \"response\": \"Your full answer (Round 1) or stance + reasoning (Round 2). Markdown OK inside the string.\",\n \"searchQueries\": [],\n \"sources\": [\n { \"title\": \"...\", \"url\": \"...\", \"snippet\": \"...\", \"query\": \"...\" }\n ],\n \"confidence\": 0.85,\n \"areasOfUncertainty\": [\n \"What I'm not sure about, in plain language.\"\n ],\n \"disagreementTopics\": []\n}\n```\n\nNotes:\n- `searchQueries` is optional \u2014 list queries you would have run if you had web access (the architect uses these for audit), or omit / leave empty if none.\n- `sources` MUST come from the RESEARCH CONTEXT only. Copy title/url/snippet/query verbatim. Never invent sources.\n- For Round 1: leave `disagreementTopics` as []. For Round 2: list the specific disagreement topics this response addresses.\n\n================================================================\nHARD RULES\n================================================================\n- You have no tools. Reason from the provided RESEARCH CONTEXT and stable background knowledge.\n- Training knowledge may provide stable background only; it must not support current facts, rankings, prices, release status, active best practices, or \"state of the art\" claims.\n- Never invent sources. If the RESEARCH CONTEXT does not cover a needed claim, say so in `areasOfUncertainty`.\n- Never echo other members' responses verbatim. Paraphrase or quote with attribution.\n- Stay within your role and persona. The architect chose you for a specific perspective.\n";
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Background subagent completion OBSERVER (issue #1151, PR 2 Stage A).
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
+ * Stage A is strictly READ-ONLY: this observer NEVER advances workflow gates, records gate
11
+ * evidence, or mutates the durable store. Gate-affecting completion ingestion is Stage B,
12
+ * gated on runtime confirmation produced by exactly this observer.
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).
17
+ */
18
+ interface ObserverConfig {
19
+ enabled: boolean;
20
+ }
21
+ /**
22
+ * Build the Stage A 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
+ export declare function createBackgroundCompletionObserver(opts: {
26
+ config: ObserverConfig;
27
+ directory: string;
28
+ }): {
29
+ event: (input: {
30
+ event: unknown;
31
+ }) => Promise<void>;
32
+ };
33
+ export {};
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Durable pending background-delegation store (issue #1151, PR 2 Stage A).
3
+ *
4
+ * Append-only JSONL event log under project-root `.swarm/background-delegations.jsonl`.
5
+ * Each line is a full record snapshot; readers fold to the latest snapshot per
6
+ * `correlationId`. This tracks background swarm `Task` dispatches so a later (Stage B)
7
+ * trusted completion can be correlated to a real dispatch. The stale sweep bounds the
8
+ * number of permanently-running (unresolved) entries by transitioning them to `stale`, so
9
+ * the folded in-memory view stays bounded by distinct correlationIds. Note: the on-disk
10
+ * log itself is append-only and is NOT compacted in Stage A — each dispatch leaves a small,
11
+ * fixed number of lines; on-disk compaction of dropped/stale records is a future stage.
12
+ *
13
+ * Stage A scope: dispatch records a `pending` snapshot and the stale sweep records
14
+ * `stale` snapshots. There is NO gate advancement and NO completion mutation here — the
15
+ * completion observer (Stage A) is read-only. Gate-affecting completion ingestion is
16
+ * Stage B, gated on runtime confirmation of the upstream completion signal.
17
+ *
18
+ * Concurrency: all writes (append, sweep) run under a single project-scoped lock via
19
+ * `withEvidenceLock`, so concurrent dispatches/sweeps cannot interleave appends. Reads are
20
+ * lock-free (line-oriented; partial trailing lines are skipped defensively).
21
+ *
22
+ * Containment: the path is validated with `validateSwarmPath`, so it can never escape
23
+ * `.swarm/` (Invariant 4).
24
+ */
25
+ export declare const BACKGROUND_DELEGATIONS_FILE = "background-delegations.jsonl";
26
+ export type BackgroundDelegationStatus = 'pending' | 'completed' | 'error' | 'stale';
27
+ export interface BackgroundDelegationRecord {
28
+ schemaVersion: 1;
29
+ /** Subagent session id from the dispatch envelope — the correlation key. */
30
+ correlationId: string;
31
+ /** Structured jobId from dispatch metadata when available, else null. */
32
+ jobId: string | null;
33
+ /** Subagent session id (== correlationId; kept explicit for clarity/forward-compat). */
34
+ subagentSessionId: string;
35
+ /** Parent (dispatching) session id. */
36
+ parentSessionId: string;
37
+ /** Tool callID of the dispatching Task call. */
38
+ callID: string;
39
+ /** Canonical swarm role (e.g. "reviewer", "test_engineer"). */
40
+ normalizedAgent: string;
41
+ /** Raw, possibly swarm-prefixed agent name (e.g. "mega_reviewer"). */
42
+ swarmPrefixedAgent: string;
43
+ /** Plan/evidence task id resolved at dispatch, or null. */
44
+ planTaskId: string | null;
45
+ evidenceTaskId: string | null;
46
+ status: BackgroundDelegationStatus;
47
+ createdAt: number;
48
+ updatedAt: number;
49
+ }
50
+ /**
51
+ * Read and fold the store to the latest snapshot per correlationId. Lock-free and
52
+ * defensive: a missing file yields an empty list, and malformed/partial lines are skipped
53
+ * (never throws). Records are returned in first-seen correlationId order.
54
+ *
55
+ * Cost: O(lines on disk) per call — a full read + parse + fold with no in-memory cache.
56
+ * This is intentionally simple and acceptable at Stage A volumes (a swarm has few concurrent
57
+ * background delegations, and the on-disk log is small). If sustained high-throughput
58
+ * background load ever makes this hot, a future stage should add a stat-invalidated in-memory
59
+ * cache and/or JSONL compaction (the same future-compaction work noted in the module header).
60
+ */
61
+ export declare function readDelegations(directory: string): BackgroundDelegationRecord[];
62
+ /** Returns the folded record for a correlationId, or null. Lock-free read. */
63
+ export declare function findByCorrelationId(directory: string, correlationId: string): BackgroundDelegationRecord | null;
64
+ export interface RecordPendingInput {
65
+ correlationId: string;
66
+ jobId: string | null;
67
+ subagentSessionId: string;
68
+ parentSessionId: string;
69
+ callID: string;
70
+ normalizedAgent: string;
71
+ swarmPrefixedAgent: string;
72
+ planTaskId: string | null;
73
+ evidenceTaskId: string | null;
74
+ }
75
+ /**
76
+ * Record a `pending` background delegation. Runs the stale sweep first (lazy maintenance,
77
+ * no plugin-init cost), then appends the pending snapshot — all under one lock acquisition
78
+ * so concurrent dispatches cannot interleave. Best-effort: returns null on lock timeout or
79
+ * write failure (Stage A has no gate effects, so a missed record is non-fatal).
80
+ */
81
+ export declare function recordPendingDelegation(directory: string, input: RecordPendingInput, options?: {
82
+ staleTimeoutMs?: number;
83
+ }): Promise<BackgroundDelegationRecord | null>;
84
+ /**
85
+ * Public stale sweep: acquires the store lock and marks overdue pendings as `stale`.
86
+ * Best-effort; returns the number swept (0 on lock timeout / error).
87
+ */
88
+ export declare function sweepStaleDelegations(directory: string, timeoutMs: number): Promise<number>;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Background subagent task-envelope parsing (issue #1151, PR 2 Stage A).
3
+ *
4
+ * OpenCode background subagents (v1.16.2) render task dispatch/completion as a stable
5
+ * XML-ish envelope via the upstream `renderOutput`:
6
+ *
7
+ * <task id="<subagentSessionID>" state="running|completed|error">
8
+ * <summary>...</summary>
9
+ * <task_result>...</task_result> (or <task_error> for state="error")
10
+ * </task>
11
+ *
12
+ * - The dispatch tool result carries `state="running"` and the subagent session id.
13
+ * - The deferred completion arrives as a synthetic parent message part whose text is the
14
+ * same envelope with `state="completed"` or `state="error"`.
15
+ *
16
+ * These parsers are intentionally pure and defensive — they never throw — so they can be
17
+ * used both at dispatch (tool.execute.after output) and at completion observation time.
18
+ */
19
+ export type TaskEnvelopeState = 'running' | 'completed' | 'error';
20
+ export interface TaskEnvelope {
21
+ /** The subagent session id from `<task id="...">` — the cross-event correlation key. */
22
+ sessionId: string;
23
+ state: TaskEnvelopeState;
24
+ }
25
+ /**
26
+ * Parse a task envelope from arbitrary text. Returns null when the text does not contain
27
+ * a well-formed opening `<task id="..." state="...">` tag. Never throws.
28
+ */
29
+ export declare function parseTaskEnvelope(text: unknown): TaskEnvelope | null;
30
+ /**
31
+ * Extract the subagent session id and (optional) jobId from a background `Task` dispatch
32
+ * result (the `tool.execute.after` output object `{ title, output, metadata }`).
33
+ *
34
+ * - `subagentSessionId` is parsed from the rendered `output` envelope `<task id="...">`.
35
+ * - `jobId` is read defensively from `metadata.jobId` (the installed plugin SDK types this
36
+ * field as `any`; upstream sets `{ background: true, jobId }`). Absent → null.
37
+ *
38
+ * Both are best-effort; either may be null.
39
+ */
40
+ export declare function extractDispatchIds(output: unknown): {
41
+ subagentSessionId: string | null;
42
+ jobId: string | null;
43
+ };
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.53.0",
55
+ version: "7.55.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",
@@ -16874,11 +16874,11 @@ var init_tool_metadata = __esm(() => {
16874
16874
  agents: ["architect"]
16875
16875
  },
16876
16876
  web_search: {
16877
- description: "External web search (Tavily or Brave) for architect-driven council research. Returns titled results with snippets and URLs. Config-gated on council.general.enabled; requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents.",
16877
+ description: "External web search (Tavily or Brave) for architect-driven council research. Returns titled results with snippets, URLs, normalized query metadata, temporal intent, freshness, and removed stale years. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides. Requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents.",
16878
16878
  agents: ["architect", "skill_improver"]
16879
16879
  },
16880
16880
  convene_general_council: {
16881
- description: "Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled.",
16881
+ description: "Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",
16882
16882
  agents: ["architect"]
16883
16883
  },
16884
16884
  write_final_council_evidence: {
@@ -17302,7 +17302,9 @@ var init_schema = __esm(() => {
17302
17302
  delegation_tracker: exports_external.boolean().default(false),
17303
17303
  agent_awareness_max_chars: exports_external.number().min(50).max(2000).default(300),
17304
17304
  delegation_gate: exports_external.boolean().default(true),
17305
- delegation_max_chars: exports_external.number().min(500).max(20000).default(4000)
17305
+ delegation_max_chars: exports_external.number().min(500).max(20000).default(4000),
17306
+ background_subagents: exports_external.boolean().default(false),
17307
+ background_pending_timeout_minutes: exports_external.number().int().min(1).max(1440).default(30)
17306
17308
  });
17307
17309
  ScoringWeightsSchema = exports_external.object({
17308
17310
  phase: exports_external.number().min(0).max(5).default(1),
@@ -21331,6 +21333,8 @@ ROUND 1 \u2014 Independent Analysis and Answer
21331
21333
  - Use the RESEARCH CONTEXT block provided by the architect in your dispatch message as your external evidence source. The architect has already gathered the relevant web search results.
21332
21334
  - Cite EVERY factual claim that depends on external evidence with a source from the RESEARCH CONTEXT (use the title and URL exactly as given).
21333
21335
  - State your confidence (0.0\u20131.0) explicitly. Be honest \u2014 overconfident answers hurt the council.
21336
+ - For current, latest, today, now, or otherwise time-sensitive claims, training knowledge is NOT evidence. If the RESEARCH CONTEXT is missing, stale, or ambiguous, say the claim is not established instead of filling the gap from memory.
21337
+ - Treat the dispatch message's CURRENT DATE as authoritative for relative time. Do not append your own training cutoff year to search-oriented reasoning or recommendations.
21334
21338
  - Enumerate areas of uncertainty so the architect knows where you're guessing vs. where you're sure.
21335
21339
  - Do NOT coordinate with other members. You will not see their responses until Round 2.
21336
21340
  - Do NOT pad. Be concise. Substance over volume.
@@ -21373,7 +21377,8 @@ Notes:
21373
21377
  - For Round 1: leave \`disagreementTopics\` as []. For Round 2: list the specific disagreement topics this response addresses.`, HARD_RULES = `================================================================
21374
21378
  HARD RULES
21375
21379
  ================================================================
21376
- - You have no tools. Reason from the provided RESEARCH CONTEXT and your training knowledge.
21380
+ - You have no tools. Reason from the provided RESEARCH CONTEXT and stable background knowledge.
21381
+ - Training knowledge may provide stable background only; it must not support current facts, rankings, prices, release status, active best practices, or "state of the art" claims.
21377
21382
  - Never invent sources. If the RESEARCH CONTEXT does not cover a needed claim, say so in \`areasOfUncertainty\`.
21378
21383
  - Never echo other members' responses verbatim. Paraphrase or quote with attribution.
21379
21384
  - Stay within your role and persona. The architect chose you for a specific perspective.`, GENERALIST_COUNCIL_PROMPT, SKEPTIC_COUNCIL_PROMPT, DOMAIN_EXPERT_COUNCIL_PROMPT;
@@ -21719,7 +21724,7 @@ var init_guardrails = __esm(() => {
21719
21724
  function clearPendingCoderScope() {
21720
21725
  pendingCoderScopeByTaskId.clear();
21721
21726
  }
21722
- var EvidenceTaskIdPlanSchema, pendingCoderScopeByTaskId, ACTIVE_PARALLEL_TASK_STATES;
21727
+ var EvidenceTaskIdPlanSchema, pendingCoderScopeByTaskId, SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE, ACTIVE_PARALLEL_TASK_STATES;
21723
21728
  var init_delegation_gate = __esm(() => {
21724
21729
  init_zod();
21725
21730
  init_schema();
@@ -21740,6 +21745,7 @@ var init_delegation_gate = __esm(() => {
21740
21745
  }).passthrough()).optional()
21741
21746
  }).passthrough();
21742
21747
  pendingCoderScopeByTaskId = new Map;
21748
+ SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE = "SWARM_BACKGROUND_TASK_BLOCKED: OpenCode background subagents (Task with background=true, " + "requires OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true) are recognized upstream, but swarm " + "cannot yet safely consume their deferred completion events \u2014 the Task returns a running " + "placeholder now and completes later via synthetic injection, which would advance swarm gates " + "before any review/test output exists. Omit `background` (or set background=false) for swarm " + "delegations until the completion-ingestion PR lands.";
21743
21749
  ACTIVE_PARALLEL_TASK_STATES = new Set([
21744
21750
  "coder_delegated",
21745
21751
  "pre_check_passed",
@@ -39867,7 +39873,7 @@ var init_council = __esm(() => {
39867
39873
  " --preset <name> Use a named member preset from council.general.presets",
39868
39874
  " --spec-review Use spec_review mode (single advisory pass on a draft spec)",
39869
39875
  "",
39870
- "Requires council.general.enabled: true and a configured search API key in opencode-swarm.json."
39876
+ "Requires council.general.enabled: true and a configured search API key in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides."
39871
39877
  ].join(`
39872
39878
  `);
39873
39879
  });
@@ -59004,7 +59010,7 @@ Subcommands:
59004
59010
  handler: (ctx) => handleCouncilCommand(ctx.directory, ctx.args),
59005
59011
  description: "Enter architect MODE: COUNCIL \u2014 multi-model deliberation [question] [--preset <name>] [--spec-review]",
59006
59012
  args: "<question> [--preset <name>] [--spec-review]",
59007
- details: "Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). Use --preset <name> to choose a named member preset from council.general.presets. " + "The architect first runs 1\u20133 targeted web searches and passes a compiled RESEARCH CONTEXT " + "to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in opencode-swarm.json.",
59013
+ details: "Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). Use --preset <name> to choose a named member preset from council.general.presets. " + "The architect first runs 1\u20133 targeted web searches and passes a compiled RESEARCH CONTEXT " + "to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",
59008
59014
  category: "agent"
59009
59015
  },
59010
59016
  "pr-review": {
@@ -93,6 +93,8 @@ export declare const HooksConfigSchema: z.ZodObject<{
93
93
  agent_awareness_max_chars: z.ZodDefault<z.ZodNumber>;
94
94
  delegation_gate: z.ZodDefault<z.ZodBoolean>;
95
95
  delegation_max_chars: z.ZodDefault<z.ZodNumber>;
96
+ background_subagents: z.ZodDefault<z.ZodBoolean>;
97
+ background_pending_timeout_minutes: z.ZodDefault<z.ZodNumber>;
96
98
  }, z.core.$strip>;
97
99
  export type HooksConfig = z.infer<typeof HooksConfigSchema>;
98
100
  export declare const ScoringWeightsSchema: z.ZodObject<{
@@ -958,6 +960,8 @@ export declare const PluginConfigSchema: z.ZodObject<{
958
960
  agent_awareness_max_chars: z.ZodDefault<z.ZodNumber>;
959
961
  delegation_gate: z.ZodDefault<z.ZodBoolean>;
960
962
  delegation_max_chars: z.ZodDefault<z.ZodNumber>;
963
+ background_subagents: z.ZodDefault<z.ZodBoolean>;
964
+ background_pending_timeout_minutes: z.ZodDefault<z.ZodNumber>;
961
965
  }, z.core.$strip>>;
962
966
  gates: z.ZodOptional<z.ZodObject<{
963
967
  syntax_check: z.ZodDefault<z.ZodObject<{
@@ -0,0 +1,11 @@
1
+ export type SearchFreshness = 'day' | 'week' | 'month' | 'year';
2
+ export type SearchTemporalIntent = 'current' | 'historical' | 'unspecified';
3
+ export interface SearchQueryPolicyResult {
4
+ originalQuery: string;
5
+ query: string;
6
+ temporalIntent: SearchTemporalIntent;
7
+ freshness?: SearchFreshness;
8
+ removedStaleYears: string[];
9
+ }
10
+ export declare function applySearchQueryPolicy(rawQuery: string, now?: Date): SearchQueryPolicyResult;
11
+ export declare function collectQueryYears(query: string): string[];
@@ -12,6 +12,7 @@
12
12
  * Malformed but successful responses produce an empty result array, never throw.
13
13
  */
14
14
  import type { GeneralCouncilConfig, WebSearchResult } from './general-council-types.js';
15
+ import type { SearchFreshness } from './search-query-policy.js';
15
16
  export declare class WebSearchError extends Error {
16
17
  readonly cause?: unknown | undefined;
17
18
  constructor(message: string, cause?: unknown | undefined);
@@ -20,16 +21,19 @@ export declare class WebSearchConfigError extends Error {
20
21
  constructor(message: string);
21
22
  }
22
23
  export interface WebSearchProvider {
23
- search(query: string, maxResults: number): Promise<WebSearchResult[]>;
24
+ search(query: string, maxResults: number, options?: WebSearchOptions): Promise<WebSearchResult[]>;
25
+ }
26
+ export interface WebSearchOptions {
27
+ freshness?: SearchFreshness;
24
28
  }
25
29
  export declare class TavilyProvider implements WebSearchProvider {
26
30
  private readonly apiKey;
27
31
  constructor(apiKey: string);
28
- search(query: string, maxResults: number): Promise<WebSearchResult[]>;
32
+ search(query: string, maxResults: number, options?: WebSearchOptions): Promise<WebSearchResult[]>;
29
33
  }
30
34
  export declare class BraveProvider implements WebSearchProvider {
31
35
  private readonly apiKey;
32
36
  constructor(apiKey: string);
33
- search(query: string, maxResults: number): Promise<WebSearchResult[]>;
37
+ search(query: string, maxResults: number, options?: WebSearchOptions): Promise<WebSearchResult[]>;
34
38
  }
35
39
  export declare function createWebSearchProvider(config: GeneralCouncilConfig): WebSearchProvider;
@@ -25,6 +25,30 @@ export declare const pendingCoderScopeByTaskId: Map<string, string[]>;
25
25
  * circular import `state.ts ↔ delegation-gate.ts`. Called by `resetSwarmState`.
26
26
  */
27
27
  export declare function clearPendingCoderScope(): void;
28
+ /**
29
+ * Issue #1151: OpenCode v1.16.2 background subagents.
30
+ *
31
+ * `Task` with `background=true` (gated upstream by
32
+ * `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true`) returns a "running" placeholder
33
+ * immediately and completes later via synthetic parent injection. The delegation gate
34
+ * treats a `Task` result as completion, so a background swarm delegation would advance
35
+ * Stage B / record gate evidence before any review/test output exists. Until swarm can
36
+ * correlate the deferred completion safely (a separate, spike-gated PR), background
37
+ * swarm delegations are fail-closed-blocked. We do NOT silently coerce `background` to
38
+ * false — the unsupported capability is surfaced explicitly.
39
+ */
40
+ export declare const SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE: string;
41
+ /**
42
+ * Fail-closed background-flag detector. Treats both the boolean `true` and the
43
+ * stringified `'true'` as background so a stringified flag cannot bypass the guard.
44
+ */
45
+ export declare function isBackgroundTrue(value: unknown): boolean;
46
+ /**
47
+ * True when a `Task` tool RESULT looks like an OpenCode background "running"
48
+ * placeholder (`state: "running"` or `metadata.background === true`). Belt-and-
49
+ * suspenders for `toolAfter`; never throws.
50
+ */
51
+ export declare function outputLooksLikeBackgroundRunning(output: unknown): boolean;
28
52
  /**
29
53
  * Parses a string to extract a DelegationEnvelope.
30
54
  * Returns null if no valid envelope is found.