opencode-swarm 7.181.1 → 7.181.3
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/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
- package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
- package/dist/background/stage-b-gates.d.ts +4 -0
- package/dist/cli/{coder-settlement-ee8bmg83.js → coder-settlement-txte2m87.js} +11 -11
- package/dist/cli/{config-doctor-mnmxzg86.js → config-doctor-101n3c1r.js} +3 -3
- package/dist/cli/{core-m9yymv84.js → core-s0yzzpaj.js} +3 -3
- package/dist/cli/{curation-policy-m3x9mkj9.js → curation-policy-r4dkajw9.js} +4 -4
- package/dist/cli/{curator-7nmwpcxy.js → curator-dp49fr0p.js} +38 -38
- package/dist/cli/curator-drift-r7w3cg3m.js +37 -0
- package/dist/cli/curator-llm-factory-tycc9xkw.js +74 -0
- package/dist/cli/{evidence-summary-service-m2b0mxmr.js → evidence-summary-service-r648x5f2.js} +17 -17
- package/dist/cli/{gate-evidence-4y2x85g4.js → gate-evidence-8rh69tsh.js} +6 -6
- package/dist/cli/guardrail-explain-dfyj1g1c.js +75 -0
- package/dist/cli/{guardrail-log-202rfw7b.js → guardrail-log-yr60w7h6.js} +7 -7
- package/dist/cli/{guardrail-reset-7nt7z18b.js → guardrail-reset-eztc62va.js} +38 -38
- package/dist/cli/{hive-promoter-segsykns.js → hive-promoter-g56ba4a4.js} +38 -38
- package/dist/cli/{index-m65tnv4j.js → index-01r2wrwa.js} +1 -1
- package/dist/cli/{index-hxe22tx3.js → index-1ks0rnzn.js} +5 -5
- package/dist/cli/{index-ztph1v9m.js → index-1w1xrk5k.js} +1 -1
- package/dist/cli/{index-12ewkms0.js → index-23mdeh2a.js} +1 -1
- package/dist/cli/{index-a7z6jygf.js → index-2pt5g7zz.js} +3 -3
- package/dist/cli/{index-y4zjbrqs.js → index-2t21pv2v.js} +1 -1
- package/dist/cli/{index-38cfx8g8.js → index-427x3j6p.js} +2 -2
- package/dist/cli/{index-tczqm089.js → index-4ffryqb1.js} +1 -1
- package/dist/cli/{index-pee6ykkg.js → index-4jvt3r77.js} +5 -5
- package/dist/cli/{index-908yea8v.js → index-6ep83w7x.js} +1 -1
- package/dist/cli/{index-r6p6x0pb.js → index-789tdsfv.js} +4 -4
- package/dist/cli/{index-yhx94xpr.js → index-7s6ct0t2.js} +6 -6
- package/dist/cli/{index-9j5jjqks.js → index-8c37kzh6.js} +7 -7
- package/dist/cli/{index-gc6h1fmf.js → index-a2hvmc3a.js} +1 -1
- package/dist/cli/{index-ea9fk6v0.js → index-ap6hs8fj.js} +1 -1
- package/dist/cli/{index-92m05mew.js → index-by9wfeja.js} +1 -1
- package/dist/cli/{index-kjstkfgh.js → index-ckrm4784.js} +7 -7
- package/dist/cli/{index-rxs0rrv1.js → index-dy9mxh0z.js} +40 -40
- package/dist/cli/{index-b2zbak7v.js → index-ekwe81my.js} +2 -2
- package/dist/cli/{index-3qhx9dx0.js → index-h6gxh3an.js} +4946 -1965
- package/dist/cli/{index-basp4sxt.js → index-hcaspktr.js} +1 -1
- package/dist/cli/{index-bdpgfep1.js → index-jrxrjz89.js} +1 -1
- package/dist/cli/{index-q1prchye.js → index-k5rqe97g.js} +27 -13
- package/dist/cli/{index-4h54k8h3.js → index-kexzhwbq.js} +2 -2
- package/dist/cli/{index-516j9vsk.js → index-kkrbybgt.js} +27 -2
- package/dist/cli/{index-cyyvc1cd.js → index-m4e3p8na.js} +2 -2
- package/dist/cli/{index-jqjdejqe.js → index-mdqp0cq2.js} +4 -4
- package/dist/cli/{index-6mwha20t.js → index-mkpdcbye.js} +3 -3
- package/dist/cli/{index-y30y1rkg.js → index-nw3z614g.js} +6 -6
- package/dist/cli/{index-nhxykfyy.js → index-nw8pfcw1.js} +270 -10
- package/dist/cli/{index-na3br902.js → index-qdz43cne.js} +38 -38
- package/dist/cli/{index-g9ax7jyf.js → index-rchygh27.js} +57 -4
- package/dist/cli/{index-6gcxgx84.js → index-s34y6gbh.js} +1 -1
- package/dist/cli/{index-s0zgz4p1.js → index-sf51gh68.js} +1 -1
- package/dist/cli/{index-gydvqmtg.js → index-sr9k8sh7.js} +4 -4
- package/dist/cli/{index-edb3sgxg.js → index-ttgex8ky.js} +6 -6
- package/dist/cli/{index-91dhg3wr.js → index-ved1325w.js} +2 -2
- package/dist/cli/{index-rw0wy2y7.js → index-vgjmahnd.js} +3 -3
- package/dist/cli/{index-bv4b8tpa.js → index-vvgpgcyn.js} +10 -0
- package/dist/cli/{index-vmthakz0.js → index-w1ydvzef.js} +1 -1
- package/dist/cli/{index-gqe4sm73.js → index-xqr076aq.js} +4 -4
- package/dist/cli/{index-g5wjasjn.js → index-yv0q0hp9.js} +140 -9
- package/dist/cli/{index-vs83acgx.js → index-yzapt508.js} +3 -3
- package/dist/cli/index.js +39 -39
- package/dist/cli/{knowledge-escalator-r9chkas8.js → knowledge-escalator-0rcft6q4.js} +12 -12
- package/dist/cli/{knowledge-events-5j2n6age.js → knowledge-events-7jyz3qxs.js} +10 -10
- package/dist/cli/{knowledge-link-s2qs178z.js → knowledge-link-655xa3db.js} +3 -3
- package/dist/cli/{knowledge-store-mybx9bmx.js → knowledge-store-asa26g6p.js} +4 -4
- package/dist/cli/{knowledge-validator-v1sj9tv4.js → knowledge-validator-j3x9ezej.js} +6 -6
- package/dist/cli/{mcp-7yx5230p.js → mcp-70hefjk6.js} +1 -1
- package/dist/cli/model-preflight-szekh1dc.js +359 -0
- package/dist/cli/{pending-delegations-amjfmc7t.js → pending-delegations-rb6bhv5x.js} +10 -10
- package/dist/cli/{pr-subscriptions-rctqs0gk.js → pr-subscriptions-v4ms5pfb.js} +10 -10
- package/dist/cli/{pr-workflow-gate-9he8ys4e.js → pr-workflow-gate-qmfpz6wb.js} +38 -38
- package/dist/cli/{runner-tzgwvvn1.js → runner-b5vt1any.js} +4 -4
- package/dist/cli/{scan-cursor-pxqkphrh.js → scan-cursor-7zn4t1hw.js} +5 -5
- package/dist/cli/{schema-n8pk3f80.js → schema-tx62mfy8.js} +2 -2
- package/dist/cli/{scope-persistence-p992x2yd.js → scope-persistence-f8w12sns.js} +14 -14
- package/dist/cli/{server-ywrd2q6z.js → server-f2vrp2wc.js} +73 -603
- package/dist/cli/{skill-generator-cdppktqx.js → skill-generator-jme09w7n.js} +14 -14
- package/dist/cli/{snapshot-coordination-init-z42ev5g9.js → snapshot-coordination-init-ad83sq6c.js} +38 -38
- package/dist/cli/{speckit-checkoff-6ynv46bn.js → speckit-checkoff-98gfvn3r.js} +4 -4
- package/dist/cli/{telemetry-zhcgfe70.js → telemetry-6k8t2mrw.js} +1 -1
- package/dist/cli/{workspace-snapshot-4m2ex1ey.js → workspace-snapshot-hsssm50w.js} +2 -2
- package/dist/cli/{worktree-collision-ownership-65971p3m.js → worktree-collision-ownership-47kdjtqb.js} +11 -11
- package/dist/cli/{worktree-isolation-xf7dfc46.js → worktree-isolation-etaawcnt.js} +38 -38
- package/dist/commands/registry.d.ts +1 -1
- package/dist/config/agent-model.d.ts +14 -0
- package/dist/config/bundled-skill-dispositions.d.ts +29 -0
- package/dist/db/qa-gate-profile.d.ts +6 -3
- package/dist/db/qa-gate-session-override.d.ts +72 -0
- package/dist/index.js +404 -390
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/instruction-pairing.d.ts +112 -0
- package/dist/services/model-preflight.d.ts +103 -21
- package/dist/session/restart-reconciliation.d.ts +74 -0
- package/dist/state.d.ts +6 -3
- package/dist/tools/get-qa-gate-profile.d.ts +13 -6
- package/package.json +1 -1
- package/dist/cli/curator-drift-q42fr0c9.js +0 -297
- package/dist/cli/curator-llm-factory-s1b2p162.js +0 -74
- package/dist/cli/guardrail-explain-nvmf3y7j.js +0 -75
- package/dist/cli/model-preflight-ckvv1arg.js +0 -170
package/dist/memory/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type { MemoryGatewayOptions, ProposeMemoryInput, RecallMemoryInput, Recor
|
|
|
7
7
|
export { createConfiguredMemoryProvider, createConfiguredMemoryProviderForRoot, createMemoryGateway, MemoryGateway, } from './gateway';
|
|
8
8
|
export { type HeldoutRecallCorpusCase, type HeldoutRecallCorpusManifest, type LoadedHeldoutRecallScenario, loadHeldoutRecallEvaluationCorpus, loadHeldoutRecallEvaluationScenarios, validateHeldoutRecallCorpusManifest, } from './heldout-evaluation-corpus';
|
|
9
9
|
export { createMemoryLifecycleHooks, type MemoryLifecycleHookOptions, type MemoryLifecycleHooks, } from './injector';
|
|
10
|
+
export { DEFAULT_INSTRUCTION_PAIRING_TASKS, type InstructionPairingArmResult, type InstructionPairingDirectivePriority, type InstructionPairingOptions, type InstructionPairingPair, type InstructionPairingRecord, type InstructionPairingReport, type InstructionPairingTask, runInstructionSelectionPairing, } from './instruction-pairing';
|
|
10
11
|
export { backupLegacyJsonl, getLegacyJsonlFileStatus, getLegacyOutcomeJsonlSignature, type JsonlBackupResult, type JsonlImportPayload, type JsonlInvalidRow, type JsonlMigrationReport, LEGACY_JSONL_MIGRATION_NAME, LEGACY_JSONL_MIGRATION_VERSION, LEGACY_JSONL_OUTCOME_META_KEY, readLegacyJsonl, readMigrationReport, resolveMemoryStorageDir, resolveSqliteDatabasePath, writeJsonlExport, writeMigrationReport, } from './jsonl-migration';
|
|
11
12
|
export { LocalJsonlMemoryProvider } from './local-jsonl-provider';
|
|
12
13
|
export { buildMemoryMaintenanceReport, type MemoryMaintenanceReport, type MemoryMaintenanceReportOptions, type MemoryRecallUsageByMemory, type MemoryRecallUsageByRole, type MemorySupersededChain, shouldCompactMemory, } from './maintenance';
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paired cached-vs-uncached outcome evidence for instruction selection (#2672).
|
|
3
|
+
*
|
|
4
|
+
* Runs the REAL knowledge-injector hook (the plugin's instruction-selection and
|
|
5
|
+
* instruction-cache surface) over deterministic, offline fixture tasks and
|
|
6
|
+
* reports paired per-task outcomes: quality (which directive labels survive
|
|
7
|
+
* selection), latency per arm, cache reads, uncached cost, and the rendered
|
|
8
|
+
* prefix length at the host-renderable carrier boundary.
|
|
9
|
+
*
|
|
10
|
+
* Contract discipline (issue #2672):
|
|
11
|
+
* - Same task/model/budget on both arms; the uncached arm is the regeneration
|
|
12
|
+
* reference and the cached arm replays byte-identical context on a warm
|
|
13
|
+
* per-instance cache.
|
|
14
|
+
* - Negative results are RETAINED rows (`negative_result: true` when the
|
|
15
|
+
* cached arm did not improve the paired quality outcome). On the offline
|
|
16
|
+
* deterministic corpus both arms run the same selection algorithm over the
|
|
17
|
+
* same records, so `quality_outcome` is 'identical' by design — the honest
|
|
18
|
+
* "caching did not change instruction quality" negative result.
|
|
19
|
+
* - NO percentage or savings claim exists anywhere in the report: deltas are
|
|
20
|
+
* absolute numbers and every quantity names its denominator in `measurement`.
|
|
21
|
+
* - `identity.instruction_set_digest` is the evidence handle a HarnessOpt
|
|
22
|
+
* lineage record (#2503) can reference; this module never modifies the
|
|
23
|
+
* harness-optimizer — #2503 remains the broad held-out comparison owner.
|
|
24
|
+
*/
|
|
25
|
+
export type InstructionPairingDirectivePriority = 'critical' | 'high' | 'medium' | 'low';
|
|
26
|
+
export interface InstructionPairingRecord {
|
|
27
|
+
/**
|
|
28
|
+
* Stable identifier recovered from the rendered prefix. Constrained to
|
|
29
|
+
* `[A-Za-z0-9-]` (PRR-012): other characters still reach the fixture
|
|
30
|
+
* store verbatim but can never be matched back by the sentinel pattern,
|
|
31
|
+
* silently undercounting `quality.expected_hit_count` for that record.
|
|
32
|
+
*/
|
|
33
|
+
label: string;
|
|
34
|
+
lesson: string;
|
|
35
|
+
directivePriority?: InstructionPairingDirectivePriority;
|
|
36
|
+
tags?: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface InstructionPairingTask {
|
|
39
|
+
id: string;
|
|
40
|
+
lastUserMessage: string;
|
|
41
|
+
expectedLabels: string[];
|
|
42
|
+
records: InstructionPairingRecord[];
|
|
43
|
+
}
|
|
44
|
+
export interface InstructionPairingOptions {
|
|
45
|
+
/**
|
|
46
|
+
* Project directory context. Fixture stores live in disposable temp roots
|
|
47
|
+
* (never under the caller's `.swarm/`); when `writeReport` is set, the
|
|
48
|
+
* durable report artifact is written under this directory's
|
|
49
|
+
* `.swarm/memory/`.
|
|
50
|
+
*/
|
|
51
|
+
directory: string;
|
|
52
|
+
/** Omitted falls back to the deterministic DEFAULT_INSTRUCTION_PAIRING_TASKS. */
|
|
53
|
+
tasks?: InstructionPairingTask[];
|
|
54
|
+
modelId?: string;
|
|
55
|
+
injectCharBudget?: number;
|
|
56
|
+
/** Explicit report destination; overrides the `writeReport` default path. */
|
|
57
|
+
reportPath?: string;
|
|
58
|
+
/** Write the report to `<directory>/.swarm/memory/instruction-pairing-report.json`. */
|
|
59
|
+
writeReport?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export interface InstructionPairingArmResult {
|
|
62
|
+
latency_ms: number;
|
|
63
|
+
/** Injections served from the warm context cache in the measured invocation (0 or 1). */
|
|
64
|
+
cache_reads: number;
|
|
65
|
+
/** How cache_reads was determined ('events-file-delta' = observed, 'protocol-assumed' = identical-context replay). */
|
|
66
|
+
cache_reads_basis: string;
|
|
67
|
+
rendered_prefix_chars: number;
|
|
68
|
+
/** The paired uncached arm's regeneration latency, reported on both arms (paired attribution, absolute ms). */
|
|
69
|
+
uncached_cost: number;
|
|
70
|
+
quality: {
|
|
71
|
+
expected_hit_count: number;
|
|
72
|
+
expected_total: number;
|
|
73
|
+
selected_labels: string[];
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export interface InstructionPairingPair {
|
|
77
|
+
task: {
|
|
78
|
+
id: string;
|
|
79
|
+
};
|
|
80
|
+
arm_cached: InstructionPairingArmResult;
|
|
81
|
+
arm_uncached: InstructionPairingArmResult;
|
|
82
|
+
quality_outcome: 'identical' | 'improved' | 'degraded';
|
|
83
|
+
negative_result: boolean;
|
|
84
|
+
}
|
|
85
|
+
export interface InstructionPairingReport {
|
|
86
|
+
schema_version: 1;
|
|
87
|
+
generated_at: string;
|
|
88
|
+
identity: {
|
|
89
|
+
task_set_id: string;
|
|
90
|
+
model_id: string;
|
|
91
|
+
budget_chars: number;
|
|
92
|
+
instruction_set_digest: string;
|
|
93
|
+
};
|
|
94
|
+
pairs: InstructionPairingPair[];
|
|
95
|
+
measurement: {
|
|
96
|
+
latency_denominator: string;
|
|
97
|
+
cost_denominator: string;
|
|
98
|
+
prefix_denominator: string;
|
|
99
|
+
};
|
|
100
|
+
negative_results_retained: boolean;
|
|
101
|
+
cache_invalidation: {
|
|
102
|
+
verified: boolean;
|
|
103
|
+
detail: string;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/** Deterministic offline corpus used when `options.tasks` is omitted. */
|
|
107
|
+
export declare const DEFAULT_INSTRUCTION_PAIRING_TASKS: InstructionPairingTask[];
|
|
108
|
+
/**
|
|
109
|
+
* Runs the paired cached-vs-uncached control over the task set and returns the
|
|
110
|
+
* report. Deterministic and offline (lexical store, hive disabled, real hook).
|
|
111
|
+
*/
|
|
112
|
+
export declare function runInstructionSelectionPairing(options: InstructionPairingOptions): Promise<InstructionPairingReport>;
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent model-resolution preflight (issue #2271 bug 4).
|
|
2
|
+
* Agent model-resolution preflight (issue #2271 bug 4; issue #2680).
|
|
3
3
|
*
|
|
4
|
-
* Agent model strings (DEFAULT_MODELS plus user `agents.<role>.model`
|
|
5
|
-
* overrides) are handed to the OpenCode host
|
|
6
|
-
* resolve ("Model not found", "Forbidden"),
|
|
7
|
-
* failure as permanent, the affected agent never
|
|
8
|
-
* gate wedges into manual `approve_plan_critic`
|
|
9
|
-
* verdict is ever produced.
|
|
4
|
+
* Agent model strings (DEFAULT_MODELS plus user `agents.<role>.model` /
|
|
5
|
+
* `swarms.<id>.agents.<role>.model` overrides) are handed to the OpenCode host
|
|
6
|
+
* unvalidated. When one does not resolve ("Model not found", "Forbidden"),
|
|
7
|
+
* dispatch-lanes classifies the failure as permanent, the affected agent never
|
|
8
|
+
* runs, and the plan-critic gate wedges into manual `approve_plan_critic`
|
|
9
|
+
* overrides because no APPROVED verdict is ever produced.
|
|
10
10
|
*
|
|
11
|
-
* This module validates
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* This module validates the FINAL effective model selection for every ENABLED
|
|
12
|
+
* legacy and prefixed multi-swarm role (issue #2680) against the live provider
|
|
13
|
+
* catalog (`client.provider.list()`), reusing the exact-name resolution
|
|
14
|
+
* helpers from src/config/agent-model.ts. Every check is FAIL-OPEN: if the
|
|
15
|
+
* catalog is unreachable or malformed, results come back `unknown` and callers
|
|
16
|
+
* must proceed — the preflight only acts on a POSITIVE confirmation that a
|
|
17
|
+
* model does not resolve (or that no final selection exists at all, the
|
|
18
|
+
* catalog-independent `missing-selection` class).
|
|
16
19
|
*/
|
|
17
20
|
import type { OpencodeClient } from '@opencode-ai/sdk';
|
|
18
21
|
import type { PluginConfig } from '../config/schema.js';
|
|
@@ -21,12 +24,17 @@ export declare const PROVIDER_LIST_TIMEOUT_MS = 2000;
|
|
|
21
24
|
export interface ConfiguredAgentModel {
|
|
22
25
|
/** Agent role the model is configured for. */
|
|
23
26
|
agent: string;
|
|
24
|
-
/** Full model id in `provider/model` form. */
|
|
27
|
+
/** Full model id in `provider/model` form. Empty when no final selection exists. */
|
|
25
28
|
model: string;
|
|
26
29
|
/** Where the value came from. */
|
|
27
30
|
source: 'default' | 'override' | 'fallback';
|
|
31
|
+
/**
|
|
32
|
+
* Issue #2680: whether the entry's role is registered as a primary agent
|
|
33
|
+
* (OpenCode's UI owns its model selection) or a dispatchable subagent.
|
|
34
|
+
*/
|
|
35
|
+
mode?: 'primary' | 'subagent';
|
|
28
36
|
}
|
|
29
|
-
export type ModelResolutionStatus = 'ok' | 'unresolved' | 'unknown';
|
|
37
|
+
export type ModelResolutionStatus = 'ok' | 'unresolved' | 'unknown' | 'missing-selection' | 'host-controlled';
|
|
30
38
|
export interface ModelResolution {
|
|
31
39
|
agent: string;
|
|
32
40
|
model: string;
|
|
@@ -34,6 +42,7 @@ export interface ModelResolution {
|
|
|
34
42
|
status: ModelResolutionStatus;
|
|
35
43
|
/** Human-readable explanation for non-ok statuses. */
|
|
36
44
|
detail?: string;
|
|
45
|
+
mode?: ConfiguredAgentModel['mode'];
|
|
37
46
|
}
|
|
38
47
|
export interface ModelPreflightResult {
|
|
39
48
|
/** False when the catalog could not be fetched — every entry is `unknown`. */
|
|
@@ -53,29 +62,102 @@ export declare function splitModelId(model: string): {
|
|
|
53
62
|
* Collect every model id the swarm could dispatch with: DEFAULT_MODELS
|
|
54
63
|
* entries, user agent overrides, and declared fallback_models. Overriding one
|
|
55
64
|
* role replaces its default (mirrors getModelForAgent precedence).
|
|
65
|
+
*
|
|
66
|
+
* Superseded by collectEnabledAgentModels (issue #2680): this legacy view
|
|
67
|
+
* enumerates the top-level config plus a blanket DEFAULT_MODELS pass and
|
|
68
|
+
* cannot see multi-swarm per-swarm selections or enabled-role gating. Retained
|
|
69
|
+
* unchanged for API compatibility; runModelPreflight no longer consumes it.
|
|
56
70
|
*/
|
|
57
71
|
export declare function collectConfiguredAgentModels(config?: PluginConfig): ConfiguredAgentModel[];
|
|
72
|
+
/**
|
|
73
|
+
* Issue #2680: compute the generated agent names the plugin would register for
|
|
74
|
+
* this configuration — the "enabled role" domain the preflight must validate.
|
|
75
|
+
* Mirrors createAgents' generation rules (legacy single default swarm vs
|
|
76
|
+
* per-swarm prefixing; object-level top-level merge; disabled exclusion;
|
|
77
|
+
* feature-gated roles only while their flag is on). The live
|
|
78
|
+
* swarmState.generatedAgentNames registry stays authoritative when available;
|
|
79
|
+
* this computation is the config-only fallback (doctor, unit tests) and is
|
|
80
|
+
* drift-guarded by the parity test.
|
|
81
|
+
*/
|
|
82
|
+
export declare function enumerateEnabledAgentRoles(config?: PluginConfig): string[];
|
|
83
|
+
/** Options for the enabled-role preflight (issue #2680). */
|
|
84
|
+
export interface EnabledAgentPreflightOptions {
|
|
85
|
+
/**
|
|
86
|
+
* The live registry of generated agent names the host actually registered
|
|
87
|
+
* (swarmState.generatedAgentNames). Authoritative when provided; the
|
|
88
|
+
* config-only enumeration is the fallback.
|
|
89
|
+
*/
|
|
90
|
+
generatedAgentNames?: readonly string[];
|
|
91
|
+
/**
|
|
92
|
+
* The registered agents map (name → { model, mode }) as produced by
|
|
93
|
+
* createAgents/getAgentConfigs. When provided, `mode` comes from it;
|
|
94
|
+
* otherwise primaries are derived via resolvePrimaryAgentNames.
|
|
95
|
+
*/
|
|
96
|
+
registeredAgents?: Record<string, {
|
|
97
|
+
model?: unknown;
|
|
98
|
+
mode?: unknown;
|
|
99
|
+
}>;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Issue #2680: collect the FINAL effective model selection for every enabled
|
|
103
|
+
* legacy and prefixed multi-swarm role, plus each role's explicitly configured
|
|
104
|
+
* fallback entries. Final selections are computed with the shipped exact-name
|
|
105
|
+
* helpers (resolveRegisteredAgentModel / resolveConfiguredAgentModel) so
|
|
106
|
+
* defaults, swarm prefixes, and the object-level merge match dispatch reality.
|
|
107
|
+
*
|
|
108
|
+
* Outcome classes (see resolveAgainstCatalog):
|
|
109
|
+
* - an explicitly configured but blank model, or a registry name that resolves
|
|
110
|
+
* to no target at all, yields an EMPTY model — the distinct
|
|
111
|
+
* `missing-selection` class (never silently treated as a successful default);
|
|
112
|
+
* - primary roles are tagged `mode: 'primary'` → `host-controlled` (OpenCode's
|
|
113
|
+
* UI owns their selection);
|
|
114
|
+
* - fallback entries appear only when explicitly configured and recorded —
|
|
115
|
+
* never synthesized (curator roles inherit explorer's chain at runtime via
|
|
116
|
+
* resolveFallbackModel; that inheritance is documented, not duplicated here).
|
|
117
|
+
*/
|
|
118
|
+
export declare function collectEnabledAgentModels(config?: PluginConfig, opts?: EnabledAgentPreflightOptions): ConfiguredAgentModel[];
|
|
58
119
|
/** Provider catalog snapshot: provider id → set of model ids. */
|
|
59
120
|
export type ProviderCatalog = Map<string, Set<string>>;
|
|
60
121
|
/** Test/gate seam: drop the cached catalogs (used after config changes and denials). */
|
|
61
122
|
export declare function invalidateProviderCatalogCache(): void;
|
|
123
|
+
/**
|
|
124
|
+
* PR #2782 review PRR-001: neutralize control characters before interpolating
|
|
125
|
+
* config- or host-sourced strings (model ids, agent names, provider detail)
|
|
126
|
+
* into console.warn / thrown-Error text. Newlines forge multi-line
|
|
127
|
+
* plugin-looking output and ESC sequences drive the terminal; control runs
|
|
128
|
+
* collapse to a single space (same policy as the doctor's stripControlChars).
|
|
129
|
+
*/
|
|
130
|
+
export declare function sanitizePreflightText(value: string): string;
|
|
62
131
|
/**
|
|
63
132
|
* Fetch the provider catalog. Returns null when the catalog cannot be
|
|
64
133
|
* obtained or parsed — callers fail open on null.
|
|
65
134
|
*/
|
|
66
135
|
export declare function fetchProviderCatalog(client: OpencodeClient | null): Promise<ProviderCatalog | null>;
|
|
67
136
|
/**
|
|
68
|
-
* Validate collected models against a catalog.
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
137
|
+
* Validate collected models against a catalog. Classification order (issue
|
|
138
|
+
* #2680): an EMPTY model is the catalog-independent `missing-selection` class;
|
|
139
|
+
* a primary role is `host-controlled` (OpenCode's UI owns its selection —
|
|
140
|
+
* never a preflight failure and never a consumer-default warning); otherwise
|
|
141
|
+
* the catalog decides — a model whose provider is absent from the catalog, or
|
|
142
|
+
* whose provider exists but does not list the model, is `unresolved` — but
|
|
143
|
+
* only when the catalog itself was successfully fetched (callers must treat a
|
|
144
|
+
* null catalog as fail-open, never unresolved).
|
|
72
145
|
*/
|
|
73
146
|
export declare function resolveAgainstCatalog(models: ConfiguredAgentModel[], catalog: ProviderCatalog | null): ModelPreflightResult;
|
|
74
147
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
148
|
+
* Issue #2680: render the operator warning for a preflight result. Reports
|
|
149
|
+
* ONLY actionable classes (`unresolved`, `missing-selection`) — ok/unknown
|
|
150
|
+
* entries and host-controlled primaries stay silent, so disabled, optional,
|
|
151
|
+
* and merely-uninvoked roles never produce consumer-default noise. Returns
|
|
152
|
+
* null when there is nothing to report.
|
|
153
|
+
*/
|
|
154
|
+
export declare function formatModelPreflightWarning(result: ModelPreflightResult): string | null;
|
|
155
|
+
/**
|
|
156
|
+
* End-to-end preflight: collect the FINAL effective selection for every
|
|
157
|
+
* enabled role (issue #2680), fetch the catalog, and resolve. Fail-open on
|
|
158
|
+
* every catalog error.
|
|
77
159
|
*/
|
|
78
|
-
export declare function runModelPreflight(config: PluginConfig | undefined, client: OpencodeClient | null): Promise<ModelPreflightResult>;
|
|
160
|
+
export declare function runModelPreflight(config: PluginConfig | undefined, client: OpencodeClient | null, opts?: EnabledAgentPreflightOptions): Promise<ModelPreflightResult>;
|
|
79
161
|
/**
|
|
80
162
|
* Resolves a single model id against the live catalog for gate preflights.
|
|
81
163
|
* Returns 'unknown' whenever the catalog cannot be fetched — gates must only
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owner-named restart reconciliation (issue #2668).
|
|
3
|
+
*
|
|
4
|
+
* At the rehydrate boundary, ephemeral execution authority expires by design
|
|
5
|
+
* (`delegationActive` and friends are reset in
|
|
6
|
+
* `TRANSIENT_SESSION_FIELDS`) — but the expiry must not be silent. When a
|
|
7
|
+
* serialized session arrives with in-flight authority, the boundary records a
|
|
8
|
+
* bounded, owner-named reconciliation outcome so an operator (and the
|
|
9
|
+
* resumed session) can tell "interrupted mid-execution, outcome UNKNOWN"
|
|
10
|
+
* from "was idle": absence must never read as success.
|
|
11
|
+
*
|
|
12
|
+
* Two surfaces, written together inside the rehydrate populate loop (after
|
|
13
|
+
* the transient reset, before the caller proceeds to the projection write):
|
|
14
|
+
*
|
|
15
|
+
* 1. The durable artifact `.swarm/session/restart-reconciliation.json` — a
|
|
16
|
+
* bounded list (cap {@link MAX_RESTART_RECONCILIATION_ENTRIES}, FIFO
|
|
17
|
+
* overflow) deduped by `(sessionId, taskId)` so a repeated restart
|
|
18
|
+
* refreshes the entry instead of duplicating it.
|
|
19
|
+
* 2. A one-shot advisory string pushed into the rehydrated session's
|
|
20
|
+
* `pendingAdvisoryMessages` (per-restart; the next rehydrate re-derives
|
|
21
|
+
* it).
|
|
22
|
+
*
|
|
23
|
+
* The record deliberately COMPOSES the shipped recovery surfaces instead of
|
|
24
|
+
* duplicating them: guidance points operators at `/swarm recover` (stale
|
|
25
|
+
* coder-settlement WALs) and `/swarm status` (uncertain provider effects),
|
|
26
|
+
* and the #2665 `stale`/`ambiguous`/`live_wedge` classification for
|
|
27
|
+
* coder settlements remains owned by those stores.
|
|
28
|
+
*/
|
|
29
|
+
/** Relative to the project root's `.swarm/` directory. */
|
|
30
|
+
export declare const RESTART_RECONCILIATION_FILE = "session/restart-reconciliation.json";
|
|
31
|
+
export declare const MAX_RESTART_RECONCILIATION_ENTRIES = 50;
|
|
32
|
+
export type RestartReconciliationClassification = 'interrupted';
|
|
33
|
+
export interface RestartReconciliationEntry {
|
|
34
|
+
sessionId: string;
|
|
35
|
+
agentName: string;
|
|
36
|
+
/** The task the interrupted execution was driving ('(unknown)' when the snapshot carried none). */
|
|
37
|
+
taskId: string;
|
|
38
|
+
classification: RestartReconciliationClassification;
|
|
39
|
+
observedAt: string;
|
|
40
|
+
guidance: string;
|
|
41
|
+
}
|
|
42
|
+
export interface RestartReconciliationFile {
|
|
43
|
+
version: 1;
|
|
44
|
+
entries: RestartReconciliationEntry[];
|
|
45
|
+
}
|
|
46
|
+
export declare const RESTART_RECONCILIATION_GUIDANCE = "outcome UNKNOWN \u2014 do not assume success; inspect /swarm status for uncertain provider effects; /swarm recover settles stale coder-settlement WALs; a human must resolve external effects (pushed commits, published PRs) manually";
|
|
47
|
+
/**
|
|
48
|
+
* Read the reconciliation artifact fail-closed: absent, corrupt, partial, or
|
|
49
|
+
* oversized files read as an empty list — the boundary then re-records what
|
|
50
|
+
* it observes and the artifact heals on the next append.
|
|
51
|
+
*/
|
|
52
|
+
export declare function readRestartReconciliation(directory: string): RestartReconciliationFile;
|
|
53
|
+
/**
|
|
54
|
+
* Append (or refresh, keyed by `(sessionId, taskId)`) a reconciliation entry
|
|
55
|
+
* and persist the bounded list atomically. Fail-open: a write error is
|
|
56
|
+
* logged and swallowed — the reconciliation record must never fail the
|
|
57
|
+
* rehydrate that produces it.
|
|
58
|
+
*/
|
|
59
|
+
export declare function recordInterruptedExecution(directory: string, entry: {
|
|
60
|
+
sessionId: string;
|
|
61
|
+
agentName: string;
|
|
62
|
+
taskId: string;
|
|
63
|
+
observedAt?: string;
|
|
64
|
+
guidance?: string;
|
|
65
|
+
}): Promise<RestartReconciliationEntry>;
|
|
66
|
+
/**
|
|
67
|
+
* The one-shot session advisory naming the owner of the interrupted effect.
|
|
68
|
+
* Pushed into `pendingAdvisoryMessages` AFTER the transient-field reset so
|
|
69
|
+
* it survives the rehydrate that produced it.
|
|
70
|
+
*/
|
|
71
|
+
export declare function buildInterruptedAdvisoryDedupeKey(entry: Pick<RestartReconciliationEntry, 'sessionId' | 'taskId'>): string;
|
|
72
|
+
export declare function buildInterruptedAdvisoryMessage(entry: Pick<RestartReconciliationEntry, 'sessionId' | 'agentName' | 'taskId'> & {
|
|
73
|
+
guidance?: string;
|
|
74
|
+
}): string;
|
package/dist/state.d.ts
CHANGED
|
@@ -417,9 +417,12 @@ export interface AgentSessionState {
|
|
|
417
417
|
autoProceedNudgeDone?: boolean;
|
|
418
418
|
/** Session-level QA gate overrides layered on top of the spec-level profile.
|
|
419
419
|
* Overrides can only enable gates (true); false values are ignored by
|
|
420
|
-
* getEffectiveGates.
|
|
421
|
-
*
|
|
422
|
-
*
|
|
420
|
+
* getEffectiveGates. Durable runtime policy (#2668): the authoritative copy
|
|
421
|
+
* lives in the project DB (qa_gate_session_override), written durable-first
|
|
422
|
+
* by `/swarm qa-gates override`, restored by rehydrateState, and deleted in
|
|
423
|
+
* lockstep with the session (end/stale-eviction/reset). Optional for
|
|
424
|
+
* backwards compatibility with pre-existing session state fixtures;
|
|
425
|
+
* consumers should read via `session.qaGateSessionOverrides ?? {}`. */
|
|
423
426
|
qaGateSessionOverrides?: Partial<QaGates>;
|
|
424
427
|
/** Session-scoped Full Auto flag for autonomous multi-agent oversight */
|
|
425
428
|
fullAutoMode: boolean;
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Read-only: uses plan.json identity when available or an explicit exact
|
|
5
5
|
* swarm/title pair before plan creation, then looks up the profile in the
|
|
6
|
-
* per-project DB. Returns the spec-level profile gates, lock state, and
|
|
7
|
-
* hash
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* per-project DB. Returns the spec-level profile gates, lock state, and
|
|
7
|
+
* profile hash, plus — when the caller carries a session context (#2668) —
|
|
8
|
+
* the session's ratchet-tighter overrides and the EFFECTIVE gates (profile
|
|
9
|
+
* merged with those overrides) so an agent can inspect the effective
|
|
10
|
+
* runtime policy after a restart. The live session's override cache is
|
|
11
|
+
* authoritative when present; the durable `qa_gate_session_override` row is
|
|
12
|
+
* the restart authority consulted when the live session is absent.
|
|
10
13
|
*/
|
|
11
|
-
import type { tool } from '@opencode-ai/plugin';
|
|
14
|
+
import type { ToolContext, tool } from '@opencode-ai/plugin';
|
|
12
15
|
import { type QaGatePlanIdentityArgs } from './qa-gate-plan-identity.js';
|
|
13
16
|
export type GetQaGateProfileArgs = QaGatePlanIdentityArgs;
|
|
14
17
|
interface GetQaGateProfileResult {
|
|
@@ -25,7 +28,11 @@ interface GetQaGateProfileResult {
|
|
|
25
28
|
created_at: string;
|
|
26
29
|
profile_hash: string;
|
|
27
30
|
};
|
|
31
|
+
/** Calling session's ratchet-tighter overrides (empty when no session context or none set). */
|
|
32
|
+
session_overrides?: Record<string, boolean>;
|
|
33
|
+
/** Effective gates: profile merged with the calling session's overrides (#2668). */
|
|
34
|
+
effective_gates?: Record<string, boolean>;
|
|
28
35
|
}
|
|
29
|
-
export declare function executeGetQaGateProfile(args: GetQaGateProfileArgs, directory: string): Promise<GetQaGateProfileResult>;
|
|
36
|
+
export declare function executeGetQaGateProfile(args: GetQaGateProfileArgs, directory: string, ctx?: ToolContext): Promise<GetQaGateProfileResult>;
|
|
30
37
|
export declare const get_qa_gate_profile: ReturnType<typeof tool>;
|
|
31
38
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.181.
|
|
3
|
+
"version": "7.181.3",
|
|
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",
|