opencode-swarm 6.64.0 → 6.66.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/architect.d.ts +18 -1
- package/dist/cli/index.js +21 -1
- package/dist/config/schema.d.ts +17 -0
- package/dist/council/council-advisory.d.ts +46 -0
- package/dist/council/council-evidence-writer.d.ts +18 -0
- package/dist/council/council-service.d.ts +12 -0
- package/dist/council/criteria-store.d.ts +9 -0
- package/dist/council/types.d.ts +77 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/repo-graph-builder.d.ts +24 -0
- package/dist/index.js +2694 -1308
- package/dist/tools/convene-council.d.ts +48 -0
- package/dist/tools/declare-council-criteria.d.ts +14 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/repo-graph.d.ts +226 -0
- package/dist/tools/tool-names.d.ts +1 -1
- package/dist/tools/update-task-status.d.ts +19 -0
- package/dist/utils/path-security.d.ts +10 -0
- package/package.json +1 -1
|
@@ -8,4 +8,21 @@ export interface AdversarialTestingConfig {
|
|
|
8
8
|
enabled: boolean;
|
|
9
9
|
scope: 'all' | 'security-only';
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Subset of PluginConfig.council needed to gate the Work Complete Council
|
|
13
|
+
* workflow block in the architect prompt. Only `enabled` is consumed here —
|
|
14
|
+
* runtime behavior (maxRounds, timeout, veto priority) is enforced elsewhere
|
|
15
|
+
* via the council tools and config. Keeping this shape narrow avoids pulling
|
|
16
|
+
* the full PluginConfig type into the agent-prompt layer.
|
|
17
|
+
*/
|
|
18
|
+
export interface CouncilWorkflowConfig {
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build the Work Complete Council four-phase workflow block. Returns the full
|
|
23
|
+
* block text when council.enabled === true, otherwise the empty string. The
|
|
24
|
+
* empty-string return path guarantees byte-for-byte non-regression when the
|
|
25
|
+
* council feature is off or the config key is absent.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildCouncilWorkflow(council?: CouncilWorkflowConfig): string;
|
|
28
|
+
export declare function createArchitectAgent(model: string, customPrompt?: string, customAppendPrompt?: string, adversarialTesting?: AdversarialTestingConfig, council?: CouncilWorkflowConfig): AgentDefinition;
|
package/dist/cli/index.js
CHANGED
|
@@ -14825,7 +14825,14 @@ async function savePlan(directory, plan, options) {
|
|
|
14825
14825
|
const planId = `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
14826
14826
|
const planHashForInit = computePlanHash(validated);
|
|
14827
14827
|
if (!await ledgerExists(directory)) {
|
|
14828
|
-
|
|
14828
|
+
try {
|
|
14829
|
+
await initLedger(directory, planId, planHashForInit, validated);
|
|
14830
|
+
} catch (initErr) {
|
|
14831
|
+
const msg = initErr instanceof Error ? initErr.message : String(initErr);
|
|
14832
|
+
if (!/already initialized/i.test(msg)) {
|
|
14833
|
+
throw initErr;
|
|
14834
|
+
}
|
|
14835
|
+
}
|
|
14829
14836
|
} else {
|
|
14830
14837
|
const existingEvents = await readLedgerEvents(directory);
|
|
14831
14838
|
if (existingEvents.length > 0 && existingEvents[0].plan_id !== planId) {
|
|
@@ -18470,6 +18477,8 @@ var TOOL_NAMES = [
|
|
|
18470
18477
|
"evidence_check",
|
|
18471
18478
|
"check_gate_status",
|
|
18472
18479
|
"completion_verify",
|
|
18480
|
+
"convene_council",
|
|
18481
|
+
"declare_council_criteria",
|
|
18473
18482
|
"sbom_generate",
|
|
18474
18483
|
"checkpoint",
|
|
18475
18484
|
"pkg_audit",
|
|
@@ -18526,6 +18535,8 @@ var AGENT_TOOL_MAP = {
|
|
|
18526
18535
|
"checkpoint",
|
|
18527
18536
|
"check_gate_status",
|
|
18528
18537
|
"completion_verify",
|
|
18538
|
+
"convene_council",
|
|
18539
|
+
"declare_council_criteria",
|
|
18529
18540
|
"complexity_hotspots",
|
|
18530
18541
|
"detect_domains",
|
|
18531
18542
|
"evidence_check",
|
|
@@ -19182,6 +19193,14 @@ var AuthorityConfigSchema = exports_external.object({
|
|
|
19182
19193
|
enabled: exports_external.boolean().default(true),
|
|
19183
19194
|
rules: exports_external.record(exports_external.string(), AgentAuthorityRuleSchema).default({})
|
|
19184
19195
|
});
|
|
19196
|
+
var CouncilConfigSchema = exports_external.object({
|
|
19197
|
+
enabled: exports_external.boolean().default(false),
|
|
19198
|
+
maxRounds: exports_external.number().int().min(1).max(10).default(3),
|
|
19199
|
+
parallelTimeoutMs: exports_external.number().int().min(5000).max(120000).default(30000),
|
|
19200
|
+
vetoPriority: exports_external.boolean().default(true),
|
|
19201
|
+
requireAllMembers: exports_external.boolean().default(false).describe("When true, convene_council rejects if fewer than 5 member verdicts are provided."),
|
|
19202
|
+
escalateOnMaxRounds: exports_external.string().optional().describe("Optional webhook URL or handler name invoked when maxRounds is reached without APPROVE. Declared for forward compatibility; no behavior is implemented yet.")
|
|
19203
|
+
}).strict();
|
|
19185
19204
|
var PluginConfigSchema = exports_external.object({
|
|
19186
19205
|
agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
|
|
19187
19206
|
swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
|
|
@@ -19229,6 +19248,7 @@ var PluginConfigSchema = exports_external.object({
|
|
|
19229
19248
|
}).optional(),
|
|
19230
19249
|
incremental_verify: IncrementalVerifyConfigSchema.optional(),
|
|
19231
19250
|
compaction_service: CompactionConfigSchema.optional(),
|
|
19251
|
+
council: CouncilConfigSchema.optional(),
|
|
19232
19252
|
turbo_mode: exports_external.boolean().default(false).optional(),
|
|
19233
19253
|
full_auto: exports_external.object({
|
|
19234
19254
|
enabled: exports_external.boolean().default(false),
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -511,6 +511,15 @@ export declare const AuthorityConfigSchema: z.ZodObject<{
|
|
|
511
511
|
}, z.core.$strip>>>;
|
|
512
512
|
}, z.core.$strip>;
|
|
513
513
|
export type AuthorityConfig = z.infer<typeof AuthorityConfigSchema>;
|
|
514
|
+
export declare const CouncilConfigSchema: z.ZodObject<{
|
|
515
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
516
|
+
maxRounds: z.ZodDefault<z.ZodNumber>;
|
|
517
|
+
parallelTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
518
|
+
vetoPriority: z.ZodDefault<z.ZodBoolean>;
|
|
519
|
+
requireAllMembers: z.ZodDefault<z.ZodBoolean>;
|
|
520
|
+
escalateOnMaxRounds: z.ZodOptional<z.ZodString>;
|
|
521
|
+
}, z.core.$strict>;
|
|
522
|
+
export type CouncilConfig = z.infer<typeof CouncilConfigSchema>;
|
|
514
523
|
export declare const PluginConfigSchema: z.ZodObject<{
|
|
515
524
|
agents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
516
525
|
model: z.ZodOptional<z.ZodString>;
|
|
@@ -854,6 +863,14 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
854
863
|
emergencyThreshold: z.ZodDefault<z.ZodNumber>;
|
|
855
864
|
preserveLastNTurns: z.ZodDefault<z.ZodNumber>;
|
|
856
865
|
}, z.core.$strip>>;
|
|
866
|
+
council: z.ZodOptional<z.ZodObject<{
|
|
867
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
868
|
+
maxRounds: z.ZodDefault<z.ZodNumber>;
|
|
869
|
+
parallelTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
870
|
+
vetoPriority: z.ZodDefault<z.ZodBoolean>;
|
|
871
|
+
requireAllMembers: z.ZodDefault<z.ZodBoolean>;
|
|
872
|
+
escalateOnMaxRounds: z.ZodOptional<z.ZodString>;
|
|
873
|
+
}, z.core.$strict>>;
|
|
857
874
|
turbo_mode: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
858
875
|
full_auto: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
859
876
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work Complete Council — advisory routing helper.
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* Routes a CouncilSynthesis (unifiedFeedbackMd + verdict metadata) into the
|
|
6
|
+
* architect's non-blocking advisory queue (`session.pendingAdvisoryMessages`).
|
|
7
|
+
* The guardrails `messagesTransform` hook drains that queue into an
|
|
8
|
+
* [ADVISORIES] block prepended to the architect's first SYSTEM message on
|
|
9
|
+
* the next turn.
|
|
10
|
+
*
|
|
11
|
+
* Runtime call site:
|
|
12
|
+
* `src/tools/convene-council.ts` invokes this helper after writing evidence,
|
|
13
|
+
* guarded by `ctx?.sessionID` and `getAgentSession`. Missing session, missing
|
|
14
|
+
* sessionID, or any thrown error silently skip — the advisory is never
|
|
15
|
+
* critical-path. The helper is also re-exported for direct use by any future
|
|
16
|
+
* caller that wants to push synthesis output into an advisory queue.
|
|
17
|
+
*
|
|
18
|
+
* Scope and known limitation:
|
|
19
|
+
* The advisory queue is READ by the architect session on its next turn (self
|
|
20
|
+
* echo). It is NOT a programmatic architect→coder delivery channel — the
|
|
21
|
+
* architect still has to render `unifiedFeedbackMd` into the coder's
|
|
22
|
+
* delegation payload manually, per the prompt's four-phase workflow. A
|
|
23
|
+
* dedicated architect→coder advisory primitive is future work.
|
|
24
|
+
*
|
|
25
|
+
* Dedup semantics:
|
|
26
|
+
* Dedup key is `council:${taskId}:${roundNumber}`. If the queue already
|
|
27
|
+
* contains a string whose content includes that key, the push is a no-op.
|
|
28
|
+
* Different rounds or tasks push distinct entries.
|
|
29
|
+
*
|
|
30
|
+
* Blocking signal (metadata only):
|
|
31
|
+
* - REJECT → header declares `blocking=true`. Council vetoed the candidate.
|
|
32
|
+
* - CONCERNS→ `blocking=false`. Architect should weigh fixes but is not vetoed.
|
|
33
|
+
* - APPROVE → `blocking=false`. Helper skips push entirely when there are no
|
|
34
|
+
* advisoryFindings (nothing useful to surface).
|
|
35
|
+
*/
|
|
36
|
+
import type { AgentSessionState } from '../state';
|
|
37
|
+
import type { CouncilSynthesis } from './types';
|
|
38
|
+
/**
|
|
39
|
+
* Push a CouncilSynthesis into the given session's advisory queue so the
|
|
40
|
+
* architect will see it as an [ADVISORIES] block on the next messagesTransform.
|
|
41
|
+
*
|
|
42
|
+
* Idempotent per (taskId, roundNumber): repeated calls with the same key
|
|
43
|
+
* leave the queue unchanged. Safe to call on APPROVE — it is a no-op when
|
|
44
|
+
* there are no advisoryFindings.
|
|
45
|
+
*/
|
|
46
|
+
export declare function pushCouncilAdvisory(session: Pick<AgentSessionState, 'pendingAdvisoryMessages'>, synthesis: CouncilSynthesis): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work Complete Council — evidence writer.
|
|
3
|
+
*
|
|
4
|
+
* Stamps the council synthesis result into `.swarm/evidence/{taskId}.json`
|
|
5
|
+
* under `gates.council`, matching the shape other gate writers use and the
|
|
6
|
+
* shape that `check_gate_status` and `update_task_status` consume (they read
|
|
7
|
+
* `evidence.gates[gateName]`). Council-specific fields (verdict, vetoedBy,
|
|
8
|
+
* roundNumber, allCriteriaMet) are stored alongside the standard GateInfo
|
|
9
|
+
* fields (sessionId, timestamp, agent); existing consumers only check
|
|
10
|
+
* `gates.council != null`, so the extras are compatible.
|
|
11
|
+
*
|
|
12
|
+
* Existing fields in the evidence file — top-level keys AND other `gates[*]`
|
|
13
|
+
* entries — are preserved across the write. The raw taskId is used as the
|
|
14
|
+
* filename; defense-in-depth regex validation rejects malformed IDs before
|
|
15
|
+
* any filesystem op.
|
|
16
|
+
*/
|
|
17
|
+
import type { CouncilSynthesis } from './types';
|
|
18
|
+
export declare function writeCouncilEvidence(workingDir: string, synthesis: CouncilSynthesis): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work Complete Council — pure synthesis service.
|
|
3
|
+
*
|
|
4
|
+
* Given the verdicts of council members (critic, reviewer, sme, test_engineer),
|
|
5
|
+
* compute the overall verdict, classify findings, detect conflicts, and build a
|
|
6
|
+
* single unified feedback document for the coder.
|
|
7
|
+
*
|
|
8
|
+
* No I/O — fully unit-testable with mock inputs. All file reads/writes happen in
|
|
9
|
+
* sibling modules (criteria-store, council-evidence-writer).
|
|
10
|
+
*/
|
|
11
|
+
import type { CouncilConfig, CouncilCriteria, CouncilMemberVerdict, CouncilSynthesis } from './types';
|
|
12
|
+
export declare function synthesizeCouncilVerdicts(taskId: string, swarmId: string, verdicts: CouncilMemberVerdict[], criteria: CouncilCriteria | null, roundNumber: number, config?: Partial<CouncilConfig>): CouncilSynthesis;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work Complete Council — pre-declaration criteria writer/reader.
|
|
3
|
+
*
|
|
4
|
+
* Stores acceptance criteria under .swarm/council/{safeId}.json so they can be
|
|
5
|
+
* read back during council evaluation.
|
|
6
|
+
*/
|
|
7
|
+
import type { CouncilCriteria, CouncilCriteriaItem } from './types';
|
|
8
|
+
export declare function writeCriteria(workingDir: string, taskId: string, criteria: CouncilCriteriaItem[]): void;
|
|
9
|
+
export declare function readCriteria(workingDir: string, taskId: string): CouncilCriteria | null;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work Complete Council — data contracts.
|
|
3
|
+
*
|
|
4
|
+
* Flat, stable schema — no nested generics. Designed for reliable LLM output.
|
|
5
|
+
* No business logic, no I/O. Only types, interfaces, and defaults.
|
|
6
|
+
*/
|
|
7
|
+
export type CouncilVerdict = 'APPROVE' | 'CONCERNS' | 'REJECT';
|
|
8
|
+
export type CouncilFindingSeverity = 'HIGH' | 'MEDIUM' | 'LOW';
|
|
9
|
+
export type CouncilFindingCategory = 'logic' | 'edge_case' | 'error_handling' | 'spec_compliance' | 'security' | 'maintainability' | 'naming' | 'domain' | 'test_gap' | 'test_quality' | 'mutation_gap' | 'adversarial_gap' | 'slop_pattern' | 'hallucinated_api' | 'lazy_abstraction' | 'cargo_cult' | 'spec_drift' | 'other';
|
|
10
|
+
export type CouncilAgent = 'critic' | 'reviewer' | 'sme' | 'test_engineer' | 'explorer';
|
|
11
|
+
export interface CouncilFinding {
|
|
12
|
+
severity: CouncilFindingSeverity;
|
|
13
|
+
category: CouncilFindingCategory;
|
|
14
|
+
/** e.g. "src/tools/convene-council.ts:42" */
|
|
15
|
+
location: string;
|
|
16
|
+
/** Human-readable explanation */
|
|
17
|
+
detail: string;
|
|
18
|
+
/** Concrete quote or line reference */
|
|
19
|
+
evidence: string;
|
|
20
|
+
}
|
|
21
|
+
export interface CouncilMemberVerdict {
|
|
22
|
+
agent: CouncilAgent;
|
|
23
|
+
verdict: CouncilVerdict;
|
|
24
|
+
/** Confidence 0.0–1.0 */
|
|
25
|
+
confidence: number;
|
|
26
|
+
findings: CouncilFinding[];
|
|
27
|
+
/** Criteria IDs from pre-declaration (e.g. ["C1","C3"]) */
|
|
28
|
+
criteriaAssessed: string[];
|
|
29
|
+
/** Criteria IDs that failed */
|
|
30
|
+
criteriaUnmet: string[];
|
|
31
|
+
durationMs: number;
|
|
32
|
+
}
|
|
33
|
+
export interface CouncilSynthesis {
|
|
34
|
+
taskId: string;
|
|
35
|
+
swarmId: string;
|
|
36
|
+
/** ISO 8601 */
|
|
37
|
+
timestamp: string;
|
|
38
|
+
overallVerdict: CouncilVerdict;
|
|
39
|
+
vetoedBy: CouncilAgent[] | null;
|
|
40
|
+
memberVerdicts: CouncilMemberVerdict[];
|
|
41
|
+
unresolvedConflicts: string[];
|
|
42
|
+
/** Severity HIGH + MEDIUM from veto members */
|
|
43
|
+
requiredFixes: CouncilFinding[];
|
|
44
|
+
/** Severity LOW or from non-veto members */
|
|
45
|
+
advisoryFindings: CouncilFinding[];
|
|
46
|
+
/** Single markdown document sent to coder */
|
|
47
|
+
unifiedFeedbackMd: string;
|
|
48
|
+
/** 1-indexed */
|
|
49
|
+
roundNumber: number;
|
|
50
|
+
allCriteriaMet: boolean;
|
|
51
|
+
}
|
|
52
|
+
export interface CouncilCriteriaItem {
|
|
53
|
+
id: string;
|
|
54
|
+
description: string;
|
|
55
|
+
mandatory: boolean;
|
|
56
|
+
}
|
|
57
|
+
export interface CouncilCriteria {
|
|
58
|
+
taskId: string;
|
|
59
|
+
criteria: CouncilCriteriaItem[];
|
|
60
|
+
/** ISO 8601 */
|
|
61
|
+
declaredAt: string;
|
|
62
|
+
}
|
|
63
|
+
/** Config shape — matched in schema.ts via CouncilConfigSchema. */
|
|
64
|
+
export interface CouncilConfig {
|
|
65
|
+
enabled: boolean;
|
|
66
|
+
/** Default 3 */
|
|
67
|
+
maxRounds: number;
|
|
68
|
+
/** Default 30_000 */
|
|
69
|
+
parallelTimeoutMs: number;
|
|
70
|
+
/** Default true — any REJECT blocks */
|
|
71
|
+
vetoPriority: boolean;
|
|
72
|
+
/** Default false — when true, convene_council rejects unless all 5 member verdicts are provided */
|
|
73
|
+
requireAllMembers: boolean;
|
|
74
|
+
/** Optional webhook URL or handler name invoked when maxRounds is reached without APPROVE. Declared for forward compatibility; no behavior is implemented yet. */
|
|
75
|
+
escalateOnMaxRounds?: string;
|
|
76
|
+
}
|
|
77
|
+
export declare const COUNCIL_DEFAULTS: CouncilConfig;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { consolidateSystemMessages } from './messages-transform';
|
|
|
13
13
|
export { extractModelInfo, NATIVE_MODEL_LIMITS, PROVIDER_CAPS, resolveModelLimit, } from './model-limits';
|
|
14
14
|
export { type CuratorDelegateFactory, createPhaseMonitorHook, } from './phase-monitor';
|
|
15
15
|
export { createPipelineTrackerHook } from './pipeline-tracker';
|
|
16
|
+
export { createRepoGraphBuilderHook, type RepoGraphBuilderHook, } from './repo-graph-builder';
|
|
16
17
|
export { buildApprovedReceipt, buildReceiptContextForDrift, buildRejectedReceipt, persistReviewReceipt, readAllReceipts, readReceiptsByScopeHash, } from './review-receipt';
|
|
17
18
|
export { createSystemEnhancerHook } from './system-enhancer';
|
|
18
19
|
export { createToolSummarizerHook, resetSummaryIdCounter, } from './tool-summarizer';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo Graph Builder Hook
|
|
3
|
+
*
|
|
4
|
+
* Startup hook that builds or refreshes the repo dependency graph when a session starts.
|
|
5
|
+
* Write-trigger hook that incrementally updates the graph when write tools are called.
|
|
6
|
+
* Wrapped in try/catch — failures are logged but never block plugin initialization.
|
|
7
|
+
*/
|
|
8
|
+
export interface RepoGraphBuilderHook {
|
|
9
|
+
init(): Promise<void>;
|
|
10
|
+
toolAfter(input: {
|
|
11
|
+
tool: string;
|
|
12
|
+
sessionID: string;
|
|
13
|
+
args?: unknown;
|
|
14
|
+
}, output: {
|
|
15
|
+
output?: unknown;
|
|
16
|
+
args?: unknown;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export interface RepoGraphDeps {
|
|
20
|
+
buildWorkspaceGraph: (workspace: string, options?: any) => any;
|
|
21
|
+
saveGraph: (workspace: string, graph: any) => Promise<void>;
|
|
22
|
+
updateGraphForFiles: (workspace: string, files: string[], options?: any) => Promise<any>;
|
|
23
|
+
}
|
|
24
|
+
export declare function createRepoGraphBuilderHook(workspaceRoot: string, deps?: Partial<RepoGraphDeps>): RepoGraphBuilderHook;
|