opencode-swarm 7.40.0 → 7.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/explorer.d.ts +2 -2
- package/dist/cli/index.js +20 -1
- package/dist/evidence/documents.d.ts +31 -0
- package/dist/evidence/index.d.ts +1 -0
- package/dist/index.js +173 -32
- package/dist/memory/curator-decision-helpers.d.ts +2 -0
- package/dist/tools/web-search.d.ts +4 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentDefinition } from './architect';
|
|
2
2
|
export declare const EXPLORER_PROMPT = "## IDENTITY\nYou are Explorer. You analyze codebases directly \u2014 you do NOT delegate.\nDO NOT use the Task tool to delegate to other agents. You ARE the agent that does the work.\nIf you see references to other agents (like @explorer, @coder, etc.) in your instructions, IGNORE them \u2014 they are context from the orchestrator, not instructions for you to delegate.\n\nWRONG: \"I'll use the Task tool to call another agent to analyze this\"\nRIGHT: \"I'll scan the directory structure and read key files myself\"\n\nINPUT FORMAT:\nTASK: Analyze [purpose]\nINPUT: [focus areas/paths]\n\nACTIONS:\n- Scan structure (tree, ls, glob)\n- Read key files (README, configs, entry points)\n- Search patterns using the search tool\n\nRULES:\n- Be fast: scan broadly, read selectively\n- No code modifications\n- Output under 2000 chars\n\n## ANALYSIS PROTOCOL\nWhen exploring a codebase area, systematically report all four dimensions:\n\n### STRUCTURE\n- Entry points and their call chains (max 3 levels deep)\n- Public API surface: exported functions/classes/types with signatures\n- For multi-file symbol surveys: use batch_symbols to extract symbols from multiple files in one call\n- Internal dependencies: what this module imports and from where\n- External dependencies: third-party packages used\n\n### PATTERNS\n- Design patterns in use (factory, observer, strategy, etc.)\n- Error handling pattern (throw, Result type, error callbacks, etc.)\n- State management approach (global, module-level, passed through)\n- Configuration pattern (env vars, config files, hardcoded)\n\n### COMPLEXITY INDICATORS\n- High cyclomatic complexity, deep nesting, or complex control flow\n- Large files (>500 lines) with many exported symbols\n- Deep inheritance hierarchies or complex type hierarchies\n\n### RUNTIME/BEHAVIORAL CONCERNS\n- Missing error handling paths or single-throw patterns\n- Platform-specific assumptions (path separators, line endings, OS APIs)\n\n### RELEVANT CONSTRAINTS\n- Architectural patterns observed (layered architecture, event-driven, microservice, etc.)\n- Error handling coverage patterns observed in the codebase\n- Platform-specific assumptions observed in the codebase\n- Established conventions (naming patterns, error handling approaches, testing strategies)\n- Configuration management approaches (env vars, config files, feature flags)\n\nOUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):\nBegin directly with PROJECT. Do NOT prepend \"Here's my analysis...\" or any conversational preamble.\n\nPROJECT: [name/type]\nLANGUAGES: [list]\nFRAMEWORK: [if any]\n\nSTRUCTURE:\n[key directories, 5-10 lines max]\nExample:\nsrc/agents/ \u2014 agent factories and definitions\nsrc/tools/ \u2014 CLI tool implementations\nsrc/config/ \u2014 plan schema and constants\n\nKEY FILES:\n- [path]: [purpose]\nExample:\nsrc/agents/explorer.ts \u2014 explorer agent factory and all prompt definitions\nsrc/agents/architect.ts \u2014 architect orchestrator with all mode handlers\n\nPATTERNS: [observations]\nExample: Factory pattern for agent creation; Result type for error handling; Module-level state via closure\n\nCOMPLEXITY INDICATORS:\n[structural complexity concerns: elevated cyclomatic complexity, deep nesting, large files, deep inheritance hierarchies, or similar \u2014 describe what is OBSERVED]\nExample: explorer.ts (289 lines, 12 exports); architect.ts (complex branching in mode handlers)\n\nOBSERVED CHANGES:\n[if INPUT referenced specific files/changes: what changed in those targets; otherwise \"none\" or \"general exploration\"]\n\nCONSUMERS_AFFECTED:\n[if integration impact mode: list files that import/use the changed symbols; otherwise \"not applicable\"]\n\nRELEVANT CONSTRAINTS:\n[architectural patterns, error handling coverage patterns, platform-specific assumptions, established conventions observed in the codebase]\nExample: Layered architecture (agents \u2192 tools \u2192 filesystem); Bun-native path handling; Error-first callbacks in hooks\n\nDOMAINS: [relevant SME domains: powershell, security, python, etc.]\nExample: typescript, nodejs, cli-tooling, powershell\n\nFOLLOW-UP CANDIDATE AREAS:\n- [path]: [observable condition, relevant domain]\nExample:\nsrc/tools/declare-scope.ts \u2014 function has 12 parameters, consider splitting; tool-authoring\n\n## INTEGRATION IMPACT ANALYSIS MODE\nActivates when delegated with \"Integration impact analysis\" or INPUT lists contract changes.\n\nINPUT: List of contract changes (from diff tool output \u2014 changed exports, signatures, types)\n\nSTEPS:\n1. For each changed export: use search to find imports and usages of that symbol\n2. Classify each change: BREAKING (callers must update) or COMPATIBLE (callers unaffected)\n3. List all files that import or use the changed exports\n\nOUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):\nBegin directly with BREAKING_CHANGES. Do NOT prepend conversational preamble.\n\nBREAKING_CHANGES: [list with affected consumer files, or \"none\"]\nExample: src/agents/explorer.ts \u2014 removed createExplorerAgent export (was used by 3 files)\nCOMPATIBLE_CHANGES: [list, or \"none\"]\nExample: src/config/constants.ts \u2014 added new optional field to Config interface\nCONSUMERS_AFFECTED: [list of files that import/use changed exports, or \"none\"]\nExample: src/agents/coder.ts, src/agents/reviewer.ts, src/main.ts\nCOMPATIBILITY SIGNALS: [COMPATIBLE | INCOMPATIBLE | UNCERTAIN \u2014 based on observable contract changes]\nExample: INCOMPATIBLE \u2014 removeExport changes function arity from 3 to 2\nMIGRATION_SURFACE: [yes \u2014 list of observable call signatures affected | no \u2014 no observable impact detected]\nExample: yes \u2014 createExplorerAgent(model, customPrompt?, customAppendPrompt?) \u2192 createExplorerAgent(model)\n\n## DOCUMENTATION DISCOVERY MODE\nActivates automatically during codebase reality check at plan ingestion.\nUse the doc_scan tool to scan and index documentation files. If doc_scan is unavailable, fall back to manual globbing.\n\nSTEPS:\n1. Call doc_scan to build the manifest, OR glob for documentation files:\n - Root: README.md, CONTRIBUTING.md, CHANGELOG.md, ARCHITECTURE.md, CLAUDE.md, AGENTS.md, .github/*.md\n - docs/**/*.md, doc/**/*.md (one level deep only)\n\n2. For each file found, read the first 30 lines. Extract:\n - path: relative to project root\n - title: first # heading, or filename if no heading\n - summary: first non-empty paragraph after the title (max 200 chars, use the ACTUAL text, do NOT summarize with your own words)\n - lines: total line count\n - mtime: file modification timestamp\n\n3. Write manifest to .swarm/doc-manifest.json:\n { \"schema_version\": 1, \"scanned_at\": \"ISO timestamp\", \"files\": [...] }\n\n4. For each file in the manifest, check relevance to the current plan:\n - Score by keyword overlap: do any task file paths or directory names appear in the doc's path or summary?\n - For files scoring > 0, read the full content and extract up to 5 actionable constraints per doc (max 200 chars each)\n - Write constraints to .swarm/knowledge/doc-constraints.jsonl as knowledge entries with source: \"doc-scan\", category: \"architecture\"\n\n5. Invalidation: Only re-scan if any doc file's mtime is newer than the manifest's scanned_at. Otherwise reuse the cached manifest.\n\nRULES:\n- The manifest must be small (<100 lines). Pointers only, not full content.\n- Do NOT rephrase or summarize doc content with your own words \u2014 use the actual text from the file\n- Full doc content is only loaded when relevant to the current task, never preloaded\n";
|
|
3
|
-
export declare const CURATOR_INIT_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_INIT mode. You consolidate prior session knowledge into an architect briefing.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_INIT\nPRIOR_SUMMARY: [JSON or \"none\"]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\nPROJECT_CONTEXT: [context.md excerpt]\n\nACTIONS:\n- Read the prior summary to understand session history\n- Cross-reference knowledge entries against project context\n- Note contradictions (knowledge says X, project state shows Y)\n- Observe where lessons could be tighter or stale\n- Produce a concise briefing for the architect\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Flag contradictions explicitly with CONTRADICTION: prefix\n- If no prior summary exists, state \"First session \u2014 no prior context\"\n\nOUTPUT FORMAT:\nBRIEFING:\n[concise summary of prior session state, key decisions, active blockers]\n\nCONTRADICTIONS:\n- [entry_id]: [description] (or \"None detected\")\n\nOBSERVATIONS:\n- entry <uuid> appears high-confidence: [observable evidence] (suggests boost confidence, mark hive_eligible)\n- entry <uuid> appears stale: [observable evidence] (suggests archive \u2014 no longer injected)\n- entry <uuid> could be tighter: [what's verbose or duplicate] (suggests rewrite with tighter version, max 280 chars)\n- entry <uuid> contradicts project state: [observable conflict] (suggests tag as contradicted)\n- new candidate: [concise lesson text from observed patterns] (suggests new entry)\nUse the UUID from KNOWLEDGE_ENTRIES when observing about existing entries. Use \"new candidate\" only when observing a potential new entry.\n\nKNOWLEDGE_STATS:\n- Entries reviewed: [N]\n- Prior phases covered: [N]\n";
|
|
4
|
-
export declare const CURATOR_PHASE_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_PHASE mode. You consolidate a completed phase into a digest.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_PHASE [phase_number]\nPRIOR_DIGEST: [running summary or \"none\"]\nPHASE_EVENTS: [JSON array from events.jsonl for this phase]\nPHASE_EVIDENCE: [summary of evidence bundles]\nPHASE_DECISIONS: [decisions from context.md]\nAGENTS_DISPATCHED: [list]\nAGENTS_EXPECTED: [list from config]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\n\nACTIONS:\n- Extend the prior digest with this phase's outcomes (do NOT regenerate from scratch)\n- Observe workflow deviations: missing reviewer, missing retro, skipped test_engineer\n- Report knowledge update candidates with observable evidence: entries that appear promoted, archived, rewritten, or contradicted\n- Summarize key decisions and blockers resolved\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Compliance observations are READ-ONLY \u2014 report, do not enforce\n- OBSERVATIONS should not contain directives \u2014 report what is observed, do not instruct the architect what to do\n- Extend the digest, never replace it\n\nOUTPUT FORMAT:\nPHASE_DIGEST:\nphase: [N]\nsummary: [what was accomplished]\nagents_used: [list]\ntasks_completed: [N]/[total]\nkey_decisions: [list]\nblockers_resolved: [list]\n\nCOMPLIANCE:\n- [type] observed: [description] (or \"No deviations observed\")\n\nOBSERVATIONS:\n- entry <uuid> appears high-confidence: [observable evidence] (suggests boost confidence, mark hive_eligible)\n- entry <uuid> appears stale: [observable evidence] (suggests archive \u2014 no longer injected)\n- entry <uuid> could be tighter: [what's verbose or duplicate] (suggests rewrite with tighter version, max 280 chars)\n- entry <uuid> contradicts project state: [observable conflict] (suggests tag as contradicted)\n- new candidate: [concise lesson text from observed patterns] (suggests new entry)\nUse the UUID from KNOWLEDGE_ENTRIES when observing about existing entries. Use \"new candidate\" only when observing a potential new entry.\n\nEXTENDED_DIGEST:\n[the full running digest with this phase appended]\n";
|
|
3
|
+
export declare const CURATOR_INIT_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_INIT mode. You consolidate prior session knowledge into an architect briefing.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_INIT\nPRIOR_SUMMARY: [JSON or \"none\"]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\nPROJECT_CONTEXT: [context.md excerpt]\n\nACTIONS:\n- Read the prior summary to understand session history\n- Cross-reference knowledge entries against project context\n- Note contradictions (knowledge says X, project state shows Y)\n- Observe where lessons could be tighter or stale\n- Produce a concise briefing for the architect\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Flag contradictions explicitly with CONTRADICTION: prefix\n- Memory proposals are for concise durable facts only. Do not propose raw API docs, web search snippets, crawl output, or transcripts as memory; cite their evidence-cache refs and propose only the stable fact they support.\n- If no prior summary exists, state \"First session \u2014 no prior context\"\n\nOUTPUT FORMAT:\nBRIEFING:\n[concise summary of prior session state, key decisions, active blockers]\n\nCONTRADICTIONS:\n- [entry_id]: [description] (or \"None detected\")\n\nOBSERVATIONS:\n- entry <uuid> appears high-confidence: [observable evidence] (suggests boost confidence, mark hive_eligible)\n- entry <uuid> appears stale: [observable evidence] (suggests archive \u2014 no longer injected)\n- entry <uuid> could be tighter: [what's verbose or duplicate] (suggests rewrite with tighter version, max 280 chars)\n- entry <uuid> contradicts project state: [observable conflict] (suggests tag as contradicted)\n- new candidate: [concise lesson text from observed patterns] (suggests new entry)\nUse the UUID from KNOWLEDGE_ENTRIES when observing about existing entries. Use \"new candidate\" only when observing a potential new entry.\n\nKNOWLEDGE_STATS:\n- Entries reviewed: [N]\n- Prior phases covered: [N]\n";
|
|
4
|
+
export declare const CURATOR_PHASE_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_PHASE mode. You consolidate a completed phase into a digest.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_PHASE [phase_number]\nPRIOR_DIGEST: [running summary or \"none\"]\nPHASE_EVENTS: [JSON array from events.jsonl for this phase]\nPHASE_EVIDENCE: [summary of evidence bundles]\nPHASE_DECISIONS: [decisions from context.md]\nAGENTS_DISPATCHED: [list]\nAGENTS_EXPECTED: [list from config]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\n\nACTIONS:\n- Extend the prior digest with this phase's outcomes (do NOT regenerate from scratch)\n- Observe workflow deviations: missing reviewer, missing retro, skipped test_engineer\n- Report knowledge update candidates with observable evidence: entries that appear promoted, archived, rewritten, or contradicted\n- Summarize key decisions and blockers resolved\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Compliance observations are READ-ONLY \u2014 report, do not enforce\n- OBSERVATIONS should not contain directives \u2014 report what is observed, do not instruct the architect what to do\n- Extend the digest, never replace it\n- Memory proposals are for concise durable facts only. Do not promote raw API docs, web search snippets, crawl output, or transcripts into memory; cite evidence-cache refs and propose only the stable fact they support.\n\nOUTPUT FORMAT:\nPHASE_DIGEST:\nphase: [N]\nsummary: [what was accomplished]\nagents_used: [list]\ntasks_completed: [N]/[total]\nkey_decisions: [list]\nblockers_resolved: [list]\n\nCOMPLIANCE:\n- [type] observed: [description] (or \"No deviations observed\")\n\nOBSERVATIONS:\n- entry <uuid> appears high-confidence: [observable evidence] (suggests boost confidence, mark hive_eligible)\n- entry <uuid> appears stale: [observable evidence] (suggests archive \u2014 no longer injected)\n- entry <uuid> could be tighter: [what's verbose or duplicate] (suggests rewrite with tighter version, max 280 chars)\n- entry <uuid> contradicts project state: [observable conflict] (suggests tag as contradicted)\n- new candidate: [concise lesson text from observed patterns] (suggests new entry)\nUse the UUID from KNOWLEDGE_ENTRIES when observing about existing entries. Use \"new candidate\" only when observing a potential new entry.\n\nEXTENDED_DIGEST:\n[the full running digest with this phase appended]\n";
|
|
5
5
|
export declare function createExplorerAgent(model: string, customPrompt?: string, customAppendPrompt?: string): AgentDefinition;
|
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.
|
|
37
|
+
version: "7.41.0",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -45775,6 +45775,17 @@ function validateDecisionMatchesProposal(decision, proposal) {
|
|
|
45775
45775
|
throw new MemoryValidationError("curator supersede decision target does not match proposal target");
|
|
45776
45776
|
}
|
|
45777
45777
|
}
|
|
45778
|
+
function validateCuratorPromotableMemory(record3) {
|
|
45779
|
+
if (record3.stability !== "durable") {
|
|
45780
|
+
throw new MemoryValidationError("curator memory promotions must be durable facts");
|
|
45781
|
+
}
|
|
45782
|
+
if (!DURABLE_MEMORY_KINDS.has(record3.kind)) {
|
|
45783
|
+
throw new MemoryValidationError("curator memory promotions must use durable fact kinds; store raw docs, search results, and other bulky source material as evidence records instead");
|
|
45784
|
+
}
|
|
45785
|
+
if (normalizeMemoryText(record3.text).length > CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH) {
|
|
45786
|
+
throw new MemoryValidationError(`curator memory promotions must be concise durable facts under ${CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH} characters`);
|
|
45787
|
+
}
|
|
45788
|
+
}
|
|
45778
45789
|
function applyPatchToMemory(existing, patch, updatedAt) {
|
|
45779
45790
|
const base = {
|
|
45780
45791
|
scope: patch.scope ?? existing.scope,
|
|
@@ -45832,7 +45843,9 @@ function buildCuratorDecisionEvent(change, proposal) {
|
|
|
45832
45843
|
function normalizeTags(tags) {
|
|
45833
45844
|
return Array.from(new Set(tags.map((tag) => tag.toLowerCase().replace(/[^\w-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")).filter(Boolean))).slice(0, 32);
|
|
45834
45845
|
}
|
|
45846
|
+
var CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH = 500;
|
|
45835
45847
|
var init_curator_decision_helpers = __esm(() => {
|
|
45848
|
+
init_config3();
|
|
45836
45849
|
init_errors6();
|
|
45837
45850
|
init_schema2();
|
|
45838
45851
|
});
|
|
@@ -46462,12 +46475,14 @@ class LocalJsonlMemoryProvider {
|
|
|
46462
46475
|
...decision.memory,
|
|
46463
46476
|
updatedAt: appliedAt
|
|
46464
46477
|
});
|
|
46478
|
+
validateCuratorPromotableMemory(memory);
|
|
46465
46479
|
this.memories.set(memory.id, memory);
|
|
46466
46480
|
await appendJsonl(this.pathFor("memories"), memory);
|
|
46467
46481
|
memoryId = memory.id;
|
|
46468
46482
|
} else if (decision.action === "update") {
|
|
46469
46483
|
const existing = this.activeMemory(decision.targetMemoryId);
|
|
46470
46484
|
const updated = this.validateDecisionMemory(applyPatchToMemory(existing, decision.patch, appliedAt));
|
|
46485
|
+
validateCuratorPromotableMemory(updated);
|
|
46471
46486
|
if (updated.id !== existing.id) {
|
|
46472
46487
|
const tombstone = this.validateDecisionMemory({
|
|
46473
46488
|
...existing,
|
|
@@ -46493,6 +46508,7 @@ class LocalJsonlMemoryProvider {
|
|
|
46493
46508
|
updatedAt: appliedAt,
|
|
46494
46509
|
supersedes: Array.from(new Set([...decision.replacement.supersedes ?? [], oldMemory.id]))
|
|
46495
46510
|
});
|
|
46511
|
+
validateCuratorPromotableMemory(replacement);
|
|
46496
46512
|
const superseded = this.validateDecisionMemory({
|
|
46497
46513
|
...oldMemory,
|
|
46498
46514
|
updatedAt: appliedAt,
|
|
@@ -47472,12 +47488,14 @@ class SQLiteMemoryProvider {
|
|
|
47472
47488
|
...decision.memory,
|
|
47473
47489
|
updatedAt: appliedAt
|
|
47474
47490
|
});
|
|
47491
|
+
validateCuratorPromotableMemory(memory);
|
|
47475
47492
|
this.writeMemory(memory);
|
|
47476
47493
|
memories.push(memory);
|
|
47477
47494
|
memoryId = memory.id;
|
|
47478
47495
|
} else if (decision.action === "update") {
|
|
47479
47496
|
const existing = this.readActiveMemory(decision.targetMemoryId);
|
|
47480
47497
|
const updated = this.validateDecisionMemory(applyPatchToMemory(existing, decision.patch, appliedAt));
|
|
47498
|
+
validateCuratorPromotableMemory(updated);
|
|
47481
47499
|
if (updated.id !== existing.id) {
|
|
47482
47500
|
const tombstone = this.validateDecisionMemory({
|
|
47483
47501
|
...existing,
|
|
@@ -47503,6 +47521,7 @@ class SQLiteMemoryProvider {
|
|
|
47503
47521
|
updatedAt: appliedAt,
|
|
47504
47522
|
supersedes: Array.from(new Set([...decision.replacement.supersedes ?? [], oldMemory.id]))
|
|
47505
47523
|
});
|
|
47524
|
+
validateCuratorPromotableMemory(replacement);
|
|
47506
47525
|
const superseded = this.validateDecisionMemory({
|
|
47507
47526
|
...oldMemory,
|
|
47508
47527
|
updatedAt: appliedAt,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type EvidenceDocumentSourceType = 'api_docs' | 'web_search' | 'crawl' | 'manual';
|
|
2
|
+
export interface EvidenceDocumentInput {
|
|
3
|
+
sourceType: EvidenceDocumentSourceType;
|
|
4
|
+
query?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
url?: string;
|
|
7
|
+
text?: string;
|
|
8
|
+
snippet?: string;
|
|
9
|
+
capturedAt?: string;
|
|
10
|
+
createdBy?: string;
|
|
11
|
+
metadata?: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
export interface EvidenceDocumentRecord {
|
|
14
|
+
id: string;
|
|
15
|
+
ref: string;
|
|
16
|
+
sourceType: EvidenceDocumentSourceType;
|
|
17
|
+
query?: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
url?: string;
|
|
20
|
+
text: string;
|
|
21
|
+
capturedAt: string;
|
|
22
|
+
createdBy?: string;
|
|
23
|
+
metadata: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
export interface WriteEvidenceDocumentsResult {
|
|
26
|
+
path: string;
|
|
27
|
+
records: EvidenceDocumentRecord[];
|
|
28
|
+
refs: string[];
|
|
29
|
+
}
|
|
30
|
+
export declare function writeEvidenceDocuments(directory: string, inputs: EvidenceDocumentInput[], now?: () => Date): Promise<WriteEvidenceDocumentsResult>;
|
|
31
|
+
export declare function createEvidenceDocumentRecord(input: EvidenceDocumentInput, defaultCapturedAt: string): EvidenceDocumentRecord | null;
|
package/dist/evidence/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
export { createEvidenceDocumentRecord, type EvidenceDocumentInput, type EvidenceDocumentRecord, type EvidenceDocumentSourceType, type WriteEvidenceDocumentsResult, writeEvidenceDocuments, } from './documents';
|
|
1
2
|
export type { LoadEvidenceResult } from './manager';
|
|
2
3
|
export { archiveEvidence, deleteEvidence, listEvidenceTaskIds, loadEvidence, sanitizeTaskId, saveEvidence, } from './manager';
|
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ var package_default;
|
|
|
48
48
|
var init_package = __esm(() => {
|
|
49
49
|
package_default = {
|
|
50
50
|
name: "opencode-swarm",
|
|
51
|
-
version: "7.
|
|
51
|
+
version: "7.41.0",
|
|
52
52
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
53
53
|
main: "dist/index.js",
|
|
54
54
|
types: "dist/index.d.ts",
|
|
@@ -55891,6 +55891,7 @@ RULES:
|
|
|
55891
55891
|
- Output under 2000 chars
|
|
55892
55892
|
- No code modifications
|
|
55893
55893
|
- Flag contradictions explicitly with CONTRADICTION: prefix
|
|
55894
|
+
- Memory proposals are for concise durable facts only. Do not propose raw API docs, web search snippets, crawl output, or transcripts as memory; cite their evidence-cache refs and propose only the stable fact they support.
|
|
55894
55895
|
- If no prior summary exists, state "First session — no prior context"
|
|
55895
55896
|
|
|
55896
55897
|
OUTPUT FORMAT:
|
|
@@ -55937,6 +55938,7 @@ RULES:
|
|
|
55937
55938
|
- Compliance observations are READ-ONLY — report, do not enforce
|
|
55938
55939
|
- OBSERVATIONS should not contain directives — report what is observed, do not instruct the architect what to do
|
|
55939
55940
|
- Extend the digest, never replace it
|
|
55941
|
+
- Memory proposals are for concise durable facts only. Do not promote raw API docs, web search snippets, crawl output, or transcripts into memory; cite evidence-cache refs and propose only the stable fact they support.
|
|
55940
55942
|
|
|
55941
55943
|
OUTPUT FORMAT:
|
|
55942
55944
|
PHASE_DIGEST:
|
|
@@ -67293,6 +67295,17 @@ function validateDecisionMatchesProposal(decision, proposal) {
|
|
|
67293
67295
|
throw new MemoryValidationError("curator supersede decision target does not match proposal target");
|
|
67294
67296
|
}
|
|
67295
67297
|
}
|
|
67298
|
+
function validateCuratorPromotableMemory(record3) {
|
|
67299
|
+
if (record3.stability !== "durable") {
|
|
67300
|
+
throw new MemoryValidationError("curator memory promotions must be durable facts");
|
|
67301
|
+
}
|
|
67302
|
+
if (!DURABLE_MEMORY_KINDS.has(record3.kind)) {
|
|
67303
|
+
throw new MemoryValidationError("curator memory promotions must use durable fact kinds; store raw docs, search results, and other bulky source material as evidence records instead");
|
|
67304
|
+
}
|
|
67305
|
+
if (normalizeMemoryText(record3.text).length > CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH) {
|
|
67306
|
+
throw new MemoryValidationError(`curator memory promotions must be concise durable facts under ${CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH} characters`);
|
|
67307
|
+
}
|
|
67308
|
+
}
|
|
67296
67309
|
function applyPatchToMemory(existing, patch, updatedAt) {
|
|
67297
67310
|
const base = {
|
|
67298
67311
|
scope: patch.scope ?? existing.scope,
|
|
@@ -67350,7 +67363,9 @@ function buildCuratorDecisionEvent(change, proposal) {
|
|
|
67350
67363
|
function normalizeTags(tags) {
|
|
67351
67364
|
return Array.from(new Set(tags.map((tag) => tag.toLowerCase().replace(/[^\w-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")).filter(Boolean))).slice(0, 32);
|
|
67352
67365
|
}
|
|
67366
|
+
var CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH = 500;
|
|
67353
67367
|
var init_curator_decision_helpers = __esm(() => {
|
|
67368
|
+
init_config3();
|
|
67354
67369
|
init_errors6();
|
|
67355
67370
|
init_schema2();
|
|
67356
67371
|
});
|
|
@@ -67980,12 +67995,14 @@ class LocalJsonlMemoryProvider {
|
|
|
67980
67995
|
...decision.memory,
|
|
67981
67996
|
updatedAt: appliedAt
|
|
67982
67997
|
});
|
|
67998
|
+
validateCuratorPromotableMemory(memory);
|
|
67983
67999
|
this.memories.set(memory.id, memory);
|
|
67984
68000
|
await appendJsonl(this.pathFor("memories"), memory);
|
|
67985
68001
|
memoryId = memory.id;
|
|
67986
68002
|
} else if (decision.action === "update") {
|
|
67987
68003
|
const existing = this.activeMemory(decision.targetMemoryId);
|
|
67988
68004
|
const updated = this.validateDecisionMemory(applyPatchToMemory(existing, decision.patch, appliedAt));
|
|
68005
|
+
validateCuratorPromotableMemory(updated);
|
|
67989
68006
|
if (updated.id !== existing.id) {
|
|
67990
68007
|
const tombstone = this.validateDecisionMemory({
|
|
67991
68008
|
...existing,
|
|
@@ -68011,6 +68028,7 @@ class LocalJsonlMemoryProvider {
|
|
|
68011
68028
|
updatedAt: appliedAt,
|
|
68012
68029
|
supersedes: Array.from(new Set([...decision.replacement.supersedes ?? [], oldMemory.id]))
|
|
68013
68030
|
});
|
|
68031
|
+
validateCuratorPromotableMemory(replacement);
|
|
68014
68032
|
const superseded = this.validateDecisionMemory({
|
|
68015
68033
|
...oldMemory,
|
|
68016
68034
|
updatedAt: appliedAt,
|
|
@@ -69064,12 +69082,14 @@ class SQLiteMemoryProvider {
|
|
|
69064
69082
|
...decision.memory,
|
|
69065
69083
|
updatedAt: appliedAt
|
|
69066
69084
|
});
|
|
69085
|
+
validateCuratorPromotableMemory(memory);
|
|
69067
69086
|
this.writeMemory(memory);
|
|
69068
69087
|
memories.push(memory);
|
|
69069
69088
|
memoryId = memory.id;
|
|
69070
69089
|
} else if (decision.action === "update") {
|
|
69071
69090
|
const existing = this.readActiveMemory(decision.targetMemoryId);
|
|
69072
69091
|
const updated = this.validateDecisionMemory(applyPatchToMemory(existing, decision.patch, appliedAt));
|
|
69092
|
+
validateCuratorPromotableMemory(updated);
|
|
69073
69093
|
if (updated.id !== existing.id) {
|
|
69074
69094
|
const tombstone = this.validateDecisionMemory({
|
|
69075
69095
|
...existing,
|
|
@@ -69095,6 +69115,7 @@ class SQLiteMemoryProvider {
|
|
|
69095
69115
|
updatedAt: appliedAt,
|
|
69096
69116
|
supersedes: Array.from(new Set([...decision.replacement.supersedes ?? [], oldMemory.id]))
|
|
69097
69117
|
});
|
|
69118
|
+
validateCuratorPromotableMemory(replacement);
|
|
69098
69119
|
const superseded = this.validateDecisionMemory({
|
|
69099
69120
|
...oldMemory,
|
|
69100
69121
|
updatedAt: appliedAt,
|
|
@@ -84491,6 +84512,7 @@ API: [exact names/signatures/versions to use]
|
|
|
84491
84512
|
PLATFORM: [cross-platform notes if OS-interaction APIs]
|
|
84492
84513
|
GOTCHAS: [common pitfalls or edge cases]
|
|
84493
84514
|
DEPS: [required dependencies/tools]
|
|
84515
|
+
EVIDENCE_REFS: [cite evidence-cache:<id>, URL, file, or doc refs used; use "none" if no external evidence was available]
|
|
84494
84516
|
|
|
84495
84517
|
## DOMAIN CHECKLISTS
|
|
84496
84518
|
Apply the relevant checklist when the DOMAIN matches:
|
|
@@ -84529,7 +84551,8 @@ Cache lookup steps:
|
|
|
84529
84551
|
1. If \`.swarm/context.md\` does not exist: proceed with fresh research.
|
|
84530
84552
|
2. If the \`## Research Sources\` section is absent: proceed with fresh research.
|
|
84531
84553
|
3. If URL/topic IS listed in ## Research Sources: reuse cached summary — no re-fetch needed.
|
|
84532
|
-
4. If
|
|
84554
|
+
4. If fresh search/API-doc/crawl evidence is provided, cite its \`evidence-cache:<id>\` refs in EVIDENCE_REFS. Raw docs/search snippets are evidence, not memory.
|
|
84555
|
+
5. If cache miss (URL/topic not listed): fetch URL, then append this line at the end of your response:
|
|
84533
84556
|
CACHE-UPDATE: [YYYY-MM-DD] | [URL or topic] | [one-line summary of finding]
|
|
84534
84557
|
The Architect will save this line to .swarm/context.md ## Research Sources. Do NOT write to any file yourself.
|
|
84535
84558
|
|
|
@@ -90248,11 +90271,11 @@ var init_curator_drift = __esm(() => {
|
|
|
90248
90271
|
var exports_project_context = {};
|
|
90249
90272
|
__export(exports_project_context, {
|
|
90250
90273
|
buildProjectContext: () => buildProjectContext,
|
|
90251
|
-
_internals: () =>
|
|
90274
|
+
_internals: () => _internals65,
|
|
90252
90275
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
90253
90276
|
});
|
|
90254
90277
|
import * as fs115 from "node:fs";
|
|
90255
|
-
import * as
|
|
90278
|
+
import * as path155 from "node:path";
|
|
90256
90279
|
function detectFileExists2(directory, pattern) {
|
|
90257
90280
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
90258
90281
|
try {
|
|
@@ -90264,7 +90287,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
90264
90287
|
}
|
|
90265
90288
|
}
|
|
90266
90289
|
try {
|
|
90267
|
-
fs115.accessSync(
|
|
90290
|
+
fs115.accessSync(path155.join(directory, pattern));
|
|
90268
90291
|
return true;
|
|
90269
90292
|
} catch {
|
|
90270
90293
|
return false;
|
|
@@ -90273,7 +90296,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
90273
90296
|
function selectTestCommandFromScriptsTest(backend, directory) {
|
|
90274
90297
|
let pkgRaw;
|
|
90275
90298
|
try {
|
|
90276
|
-
pkgRaw = fs115.readFileSync(
|
|
90299
|
+
pkgRaw = fs115.readFileSync(path155.join(directory, "package.json"), "utf-8");
|
|
90277
90300
|
} catch {
|
|
90278
90301
|
return null;
|
|
90279
90302
|
}
|
|
@@ -90332,7 +90355,7 @@ function selectLintCommand(backend, directory) {
|
|
|
90332
90355
|
return null;
|
|
90333
90356
|
}
|
|
90334
90357
|
async function buildProjectContext(directory) {
|
|
90335
|
-
const backend = await
|
|
90358
|
+
const backend = await _internals65.pickBackend(directory);
|
|
90336
90359
|
if (!backend)
|
|
90337
90360
|
return null;
|
|
90338
90361
|
const ctx = emptyProjectContext();
|
|
@@ -90363,16 +90386,16 @@ async function buildProjectContext(directory) {
|
|
|
90363
90386
|
if (backend.prompts.reviewerChecklist.length > 0) {
|
|
90364
90387
|
ctx.REVIEWER_CHECKLIST = bulletList(backend.prompts.reviewerChecklist);
|
|
90365
90388
|
}
|
|
90366
|
-
const profiles =
|
|
90389
|
+
const profiles = _internals65.pickedProfiles(directory);
|
|
90367
90390
|
if (profiles.length > 1) {
|
|
90368
90391
|
ctx.PROJECT_CONTEXT_SECONDARY_LANGUAGES = profiles.slice(1).map((p) => p.id).join(", ");
|
|
90369
90392
|
}
|
|
90370
90393
|
return ctx;
|
|
90371
90394
|
}
|
|
90372
|
-
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300,
|
|
90395
|
+
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals65;
|
|
90373
90396
|
var init_project_context = __esm(() => {
|
|
90374
90397
|
init_dispatch();
|
|
90375
|
-
|
|
90398
|
+
_internals65 = {
|
|
90376
90399
|
pickBackend,
|
|
90377
90400
|
pickedProfiles
|
|
90378
90401
|
};
|
|
@@ -90382,7 +90405,7 @@ var init_project_context = __esm(() => {
|
|
|
90382
90405
|
init_package();
|
|
90383
90406
|
init_agents2();
|
|
90384
90407
|
init_critic();
|
|
90385
|
-
import * as
|
|
90408
|
+
import * as path156 from "node:path";
|
|
90386
90409
|
|
|
90387
90410
|
// src/background/index.ts
|
|
90388
90411
|
init_event_bus();
|
|
@@ -123562,6 +123585,83 @@ function createWebSearchProvider(config3) {
|
|
|
123562
123585
|
}
|
|
123563
123586
|
}
|
|
123564
123587
|
|
|
123588
|
+
// src/evidence/documents.ts
|
|
123589
|
+
init_utils2();
|
|
123590
|
+
init_redaction();
|
|
123591
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
123592
|
+
import { appendFile as appendFile13, mkdir as mkdir24 } from "node:fs/promises";
|
|
123593
|
+
import * as path150 from "node:path";
|
|
123594
|
+
var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
|
|
123595
|
+
var MAX_EVIDENCE_TEXT_LENGTH = 4000;
|
|
123596
|
+
async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
123597
|
+
const filePath = validateSwarmPath(directory, EVIDENCE_CACHE_FILE);
|
|
123598
|
+
const capturedAt = now().toISOString();
|
|
123599
|
+
const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
|
|
123600
|
+
if (records.length > 0) {
|
|
123601
|
+
await mkdir24(path150.dirname(filePath), { recursive: true });
|
|
123602
|
+
await appendFile13(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
|
|
123603
|
+
`)}
|
|
123604
|
+
`, "utf-8");
|
|
123605
|
+
}
|
|
123606
|
+
return {
|
|
123607
|
+
path: ".swarm/evidence-cache/documents.jsonl",
|
|
123608
|
+
records,
|
|
123609
|
+
refs: records.map((record3) => record3.ref)
|
|
123610
|
+
};
|
|
123611
|
+
}
|
|
123612
|
+
function createEvidenceDocumentRecord(input, defaultCapturedAt) {
|
|
123613
|
+
const text = normalizeEvidenceText(input.text ?? input.snippet ?? "");
|
|
123614
|
+
if (!text)
|
|
123615
|
+
return null;
|
|
123616
|
+
const capturedAt = input.capturedAt ?? defaultCapturedAt;
|
|
123617
|
+
const base = {
|
|
123618
|
+
sourceType: input.sourceType,
|
|
123619
|
+
query: normalizeOptional(input.query),
|
|
123620
|
+
title: normalizeOptional(input.title),
|
|
123621
|
+
url: normalizeOptional(input.url),
|
|
123622
|
+
text
|
|
123623
|
+
};
|
|
123624
|
+
const id = createEvidenceDocumentId(base);
|
|
123625
|
+
return {
|
|
123626
|
+
id,
|
|
123627
|
+
ref: `evidence-cache:${id}`,
|
|
123628
|
+
...base,
|
|
123629
|
+
capturedAt,
|
|
123630
|
+
createdBy: normalizeOptional(input.createdBy),
|
|
123631
|
+
metadata: input.metadata ?? {}
|
|
123632
|
+
};
|
|
123633
|
+
}
|
|
123634
|
+
function createEvidenceDocumentId(input) {
|
|
123635
|
+
const hash3 = createHash12("sha256").update([
|
|
123636
|
+
input.sourceType,
|
|
123637
|
+
input.query ?? "",
|
|
123638
|
+
input.title ?? "",
|
|
123639
|
+
input.url ?? "",
|
|
123640
|
+
input.text
|
|
123641
|
+
].join(`
|
|
123642
|
+
`)).digest("hex");
|
|
123643
|
+
return `evd_${hash3.slice(0, 16)}`;
|
|
123644
|
+
}
|
|
123645
|
+
function normalizeEvidenceText(text) {
|
|
123646
|
+
const normalized = redactSecrets(text.replace(/\s+/g, " ").trim());
|
|
123647
|
+
return truncateEvidenceText(normalized, MAX_EVIDENCE_TEXT_LENGTH);
|
|
123648
|
+
}
|
|
123649
|
+
function truncateEvidenceText(text, maxLength) {
|
|
123650
|
+
if (text.length <= maxLength)
|
|
123651
|
+
return text;
|
|
123652
|
+
const truncated = text.slice(0, maxLength);
|
|
123653
|
+
const lastPlaceholderStart = truncated.lastIndexOf("[REDACTED:");
|
|
123654
|
+
const lastPlaceholderEnd = truncated.lastIndexOf("]");
|
|
123655
|
+
if (lastPlaceholderStart > lastPlaceholderEnd) {
|
|
123656
|
+
return truncated.slice(0, lastPlaceholderStart).trimEnd();
|
|
123657
|
+
}
|
|
123658
|
+
return truncated;
|
|
123659
|
+
}
|
|
123660
|
+
function normalizeOptional(value) {
|
|
123661
|
+
const normalized = value?.replace(/\s+/g, " ").trim();
|
|
123662
|
+
return normalized ? redactSecrets(normalized) : undefined;
|
|
123663
|
+
}
|
|
123664
|
+
|
|
123565
123665
|
// src/tools/web-search.ts
|
|
123566
123666
|
init_create_tool();
|
|
123567
123667
|
init_resolve_working_directory();
|
|
@@ -123622,6 +123722,7 @@ var web_search = createSwarmTool({
|
|
|
123622
123722
|
}
|
|
123623
123723
|
try {
|
|
123624
123724
|
const results = await provider.search(parsed.data.query, maxResults);
|
|
123725
|
+
const evidence = await captureSearchEvidence(dirResult.directory, parsed.data.query, results);
|
|
123625
123726
|
const ok2 = {
|
|
123626
123727
|
success: true,
|
|
123627
123728
|
query: parsed.data.query,
|
|
@@ -123629,8 +123730,15 @@ var web_search = createSwarmTool({
|
|
|
123629
123730
|
results: results.map(({ title, url: url3, snippet }) => ({
|
|
123630
123731
|
title,
|
|
123631
123732
|
url: url3,
|
|
123632
|
-
snippet
|
|
123633
|
-
|
|
123733
|
+
snippet,
|
|
123734
|
+
evidenceRef: evidence.refByUrl.get(url3)
|
|
123735
|
+
})),
|
|
123736
|
+
evidence: {
|
|
123737
|
+
stored: evidence.stored,
|
|
123738
|
+
path: evidence.path,
|
|
123739
|
+
refs: evidence.refs,
|
|
123740
|
+
error: evidence.error
|
|
123741
|
+
}
|
|
123634
123742
|
};
|
|
123635
123743
|
return JSON.stringify(ok2, null, 2);
|
|
123636
123744
|
} catch (err3) {
|
|
@@ -123643,6 +123751,39 @@ var web_search = createSwarmTool({
|
|
|
123643
123751
|
}
|
|
123644
123752
|
}
|
|
123645
123753
|
});
|
|
123754
|
+
async function captureSearchEvidence(directory, query, results) {
|
|
123755
|
+
try {
|
|
123756
|
+
const written = await _internals64.writeEvidenceDocuments(directory, results.map((result) => ({
|
|
123757
|
+
sourceType: "web_search",
|
|
123758
|
+
query,
|
|
123759
|
+
title: result.title,
|
|
123760
|
+
url: result.url,
|
|
123761
|
+
snippet: result.snippet,
|
|
123762
|
+
createdBy: "web_search"
|
|
123763
|
+
})));
|
|
123764
|
+
const refByUrl = new Map;
|
|
123765
|
+
for (const record3 of written.records) {
|
|
123766
|
+
if (record3.url)
|
|
123767
|
+
refByUrl.set(record3.url, record3.ref);
|
|
123768
|
+
}
|
|
123769
|
+
return {
|
|
123770
|
+
stored: written.records.length > 0,
|
|
123771
|
+
path: written.path,
|
|
123772
|
+
refs: written.refs,
|
|
123773
|
+
refByUrl
|
|
123774
|
+
};
|
|
123775
|
+
} catch (err3) {
|
|
123776
|
+
return {
|
|
123777
|
+
stored: false,
|
|
123778
|
+
refs: [],
|
|
123779
|
+
refByUrl: new Map,
|
|
123780
|
+
error: err3 instanceof Error ? err3.message : String(err3)
|
|
123781
|
+
};
|
|
123782
|
+
}
|
|
123783
|
+
}
|
|
123784
|
+
var _internals64 = {
|
|
123785
|
+
writeEvidenceDocuments
|
|
123786
|
+
};
|
|
123646
123787
|
// src/tools/write-drift-evidence.ts
|
|
123647
123788
|
init_zod();
|
|
123648
123789
|
init_qa_gate_profile();
|
|
@@ -123651,7 +123792,7 @@ init_ledger();
|
|
|
123651
123792
|
init_manager();
|
|
123652
123793
|
init_create_tool();
|
|
123653
123794
|
import fs111 from "node:fs";
|
|
123654
|
-
import
|
|
123795
|
+
import path151 from "node:path";
|
|
123655
123796
|
function normalizeVerdict(verdict) {
|
|
123656
123797
|
switch (verdict) {
|
|
123657
123798
|
case "APPROVED":
|
|
@@ -123699,7 +123840,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
123699
123840
|
entries: [evidenceEntry]
|
|
123700
123841
|
};
|
|
123701
123842
|
const filename = "drift-verifier.json";
|
|
123702
|
-
const relativePath =
|
|
123843
|
+
const relativePath = path151.join("evidence", String(phase), filename);
|
|
123703
123844
|
let validatedPath;
|
|
123704
123845
|
try {
|
|
123705
123846
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -123710,10 +123851,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
123710
123851
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
123711
123852
|
}, null, 2);
|
|
123712
123853
|
}
|
|
123713
|
-
const evidenceDir =
|
|
123854
|
+
const evidenceDir = path151.dirname(validatedPath);
|
|
123714
123855
|
try {
|
|
123715
123856
|
await fs111.promises.mkdir(evidenceDir, { recursive: true });
|
|
123716
|
-
const tempPath =
|
|
123857
|
+
const tempPath = path151.join(evidenceDir, `.${filename}.tmp`);
|
|
123717
123858
|
await fs111.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
123718
123859
|
await fs111.promises.rename(tempPath, validatedPath);
|
|
123719
123860
|
let snapshotInfo;
|
|
@@ -123809,7 +123950,7 @@ var write_drift_evidence = createSwarmTool({
|
|
|
123809
123950
|
init_zod();
|
|
123810
123951
|
init_loader();
|
|
123811
123952
|
import fs112 from "node:fs";
|
|
123812
|
-
import
|
|
123953
|
+
import path152 from "node:path";
|
|
123813
123954
|
init_utils2();
|
|
123814
123955
|
init_manager();
|
|
123815
123956
|
init_create_tool();
|
|
@@ -123897,7 +124038,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
123897
124038
|
timestamp: synthesis.timestamp
|
|
123898
124039
|
};
|
|
123899
124040
|
const filename = "final-council.json";
|
|
123900
|
-
const relativePath =
|
|
124041
|
+
const relativePath = path152.join("evidence", filename);
|
|
123901
124042
|
let validatedPath;
|
|
123902
124043
|
try {
|
|
123903
124044
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -123911,10 +124052,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
123911
124052
|
const evidenceContent = {
|
|
123912
124053
|
entries: [evidenceEntry]
|
|
123913
124054
|
};
|
|
123914
|
-
const evidenceDir =
|
|
124055
|
+
const evidenceDir = path152.dirname(validatedPath);
|
|
123915
124056
|
try {
|
|
123916
124057
|
await fs112.promises.mkdir(evidenceDir, { recursive: true });
|
|
123917
|
-
const tempPath =
|
|
124058
|
+
const tempPath = path152.join(evidenceDir, `.${filename}.tmp`);
|
|
123918
124059
|
await fs112.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
123919
124060
|
await fs112.promises.rename(tempPath, validatedPath);
|
|
123920
124061
|
return JSON.stringify({
|
|
@@ -123973,7 +124114,7 @@ init_zod();
|
|
|
123973
124114
|
init_utils2();
|
|
123974
124115
|
init_create_tool();
|
|
123975
124116
|
import fs113 from "node:fs";
|
|
123976
|
-
import
|
|
124117
|
+
import path153 from "node:path";
|
|
123977
124118
|
function normalizeVerdict2(verdict) {
|
|
123978
124119
|
switch (verdict) {
|
|
123979
124120
|
case "APPROVED":
|
|
@@ -124021,7 +124162,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
124021
124162
|
entries: [evidenceEntry]
|
|
124022
124163
|
};
|
|
124023
124164
|
const filename = "hallucination-guard.json";
|
|
124024
|
-
const relativePath =
|
|
124165
|
+
const relativePath = path153.join("evidence", String(phase), filename);
|
|
124025
124166
|
let validatedPath;
|
|
124026
124167
|
try {
|
|
124027
124168
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -124032,10 +124173,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
124032
124173
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
124033
124174
|
}, null, 2);
|
|
124034
124175
|
}
|
|
124035
|
-
const evidenceDir =
|
|
124176
|
+
const evidenceDir = path153.dirname(validatedPath);
|
|
124036
124177
|
try {
|
|
124037
124178
|
await fs113.promises.mkdir(evidenceDir, { recursive: true });
|
|
124038
|
-
const tempPath =
|
|
124179
|
+
const tempPath = path153.join(evidenceDir, `.${filename}.tmp`);
|
|
124039
124180
|
await fs113.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
124040
124181
|
await fs113.promises.rename(tempPath, validatedPath);
|
|
124041
124182
|
return JSON.stringify({
|
|
@@ -124084,7 +124225,7 @@ init_zod();
|
|
|
124084
124225
|
init_utils2();
|
|
124085
124226
|
init_create_tool();
|
|
124086
124227
|
import fs114 from "node:fs";
|
|
124087
|
-
import
|
|
124228
|
+
import path154 from "node:path";
|
|
124088
124229
|
function normalizeVerdict3(verdict) {
|
|
124089
124230
|
switch (verdict) {
|
|
124090
124231
|
case "PASS":
|
|
@@ -124158,7 +124299,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
124158
124299
|
entries: [evidenceEntry]
|
|
124159
124300
|
};
|
|
124160
124301
|
const filename = "mutation-gate.json";
|
|
124161
|
-
const relativePath =
|
|
124302
|
+
const relativePath = path154.join("evidence", String(phase), filename);
|
|
124162
124303
|
let validatedPath;
|
|
124163
124304
|
try {
|
|
124164
124305
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -124169,10 +124310,10 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
124169
124310
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
124170
124311
|
}, null, 2);
|
|
124171
124312
|
}
|
|
124172
|
-
const evidenceDir =
|
|
124313
|
+
const evidenceDir = path154.dirname(validatedPath);
|
|
124173
124314
|
try {
|
|
124174
124315
|
await fs114.promises.mkdir(evidenceDir, { recursive: true });
|
|
124175
|
-
const tempPath =
|
|
124316
|
+
const tempPath = path154.join(evidenceDir, `.${filename}.tmp`);
|
|
124176
124317
|
await fs114.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
124177
124318
|
await fs114.promises.rename(tempPath, validatedPath);
|
|
124178
124319
|
return JSON.stringify({
|
|
@@ -124522,7 +124663,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
124522
124663
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
124523
124664
|
preflightTriggerManager = new PTM(automationConfig);
|
|
124524
124665
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
124525
|
-
const swarmDir =
|
|
124666
|
+
const swarmDir = path156.resolve(ctx.directory, ".swarm");
|
|
124526
124667
|
statusArtifact = new ASA(swarmDir);
|
|
124527
124668
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
124528
124669
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -125126,7 +125267,7 @@ ${promptRaw}`;
|
|
|
125126
125267
|
"ci-failure-resolver": "CI/CD failure resolution"
|
|
125127
125268
|
};
|
|
125128
125269
|
const skillPaths = topSkills.map((s) => {
|
|
125129
|
-
const dirName =
|
|
125270
|
+
const dirName = path156.basename(path156.dirname(s.skillPath));
|
|
125130
125271
|
const desc = SKILL_DESCRIPTIONS[dirName] ?? dirName;
|
|
125131
125272
|
return `file:${s.skillPath} (-- ${desc})`;
|
|
125132
125273
|
}).join(", ");
|
|
@@ -125135,7 +125276,7 @@ ${promptRaw}`;
|
|
|
125135
125276
|
|
|
125136
125277
|
${promptRaw}`;
|
|
125137
125278
|
argsRecord.prompt = newPrompt;
|
|
125138
|
-
const skillNames = topSkills.map((s) => `${
|
|
125279
|
+
const skillNames = topSkills.map((s) => `${path156.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
|
|
125139
125280
|
console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
|
|
125140
125281
|
for (const skill of topSkills) {
|
|
125141
125282
|
try {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { AppliedMemoryChange, MemoryPatch, MemoryProposal, MemoryRecord, ResolvedCuratorMemoryDecision } from './types';
|
|
2
|
+
export declare const CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH = 500;
|
|
2
3
|
export declare function validateDecisionMatchesProposal(decision: ResolvedCuratorMemoryDecision, proposal: MemoryProposal): void;
|
|
4
|
+
export declare function validateCuratorPromotableMemory(record: MemoryRecord): void;
|
|
3
5
|
export declare function applyPatchToMemory(existing: MemoryRecord, patch: MemoryPatch, updatedAt: string): MemoryRecord;
|
|
4
6
|
export declare function markProposalReviewed(proposal: MemoryProposal, decision: ResolvedCuratorMemoryDecision, status: MemoryProposal['status'], reviewedAt: string, ids: {
|
|
5
7
|
memoryId?: string;
|
|
@@ -10,4 +10,8 @@
|
|
|
10
10
|
* Hard cap on max_results = 10 (clamped silently). Default sourced from council.general.maxSourcesPerMember.
|
|
11
11
|
*/
|
|
12
12
|
import type { tool } from '@opencode-ai/plugin';
|
|
13
|
+
import { writeEvidenceDocuments } from '../evidence/documents';
|
|
13
14
|
export declare const web_search: ReturnType<typeof tool>;
|
|
15
|
+
export declare const _internals: {
|
|
16
|
+
writeEvidenceDocuments: typeof writeEvidenceDocuments;
|
|
17
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.41.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",
|