opencode-swarm 7.181.2 → 7.181.4
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/cli/{coder-settlement-993vdsd2.js → coder-settlement-vbs5rj3z.js} +10 -10
- package/dist/cli/{config-doctor-nr27vfv6.js → config-doctor-3cb51z08.js} +2 -2
- package/dist/cli/{core-t3tg4397.js → core-0h7y8z0s.js} +2 -2
- package/dist/cli/{curation-policy-m3x9mkj9.js → curation-policy-r4dkajw9.js} +4 -4
- package/dist/cli/{curator-gk392717.js → curator-9sn55eyk.js} +34 -34
- package/dist/cli/curator-drift-d4jkgrba.js +37 -0
- package/dist/cli/{curator-llm-factory-n01we8pa.js → curator-llm-factory-zwc2gpe7.js} +34 -34
- package/dist/cli/{evidence-summary-service-fkvj8ct1.js → evidence-summary-service-sb5seqs3.js} +14 -14
- package/dist/cli/{gate-evidence-1n6zffzb.js → gate-evidence-emq2y7kz.js} +5 -5
- package/dist/cli/{guardrail-explain-81jvm99e.js → guardrail-explain-a3hcrpwv.js} +35 -35
- package/dist/cli/{guardrail-log-mw9x5j8g.js → guardrail-log-ftv03v4x.js} +6 -6
- package/dist/cli/{guardrail-reset-6thsn6ad.js → guardrail-reset-d6qmnvff.js} +34 -34
- package/dist/cli/{hive-promoter-pym6se37.js → hive-promoter-pktjn46n.js} +34 -34
- package/dist/cli/{index-m65tnv4j.js → index-01r2wrwa.js} +1 -1
- package/dist/cli/{index-txx2mrsk.js → index-0ea0c676.js} +25 -11
- package/dist/cli/{index-gmqf6bjj.js → index-12fxtcce.js} +36 -36
- package/dist/cli/{index-cr61qv27.js → index-1epynxc4.js} +2 -2
- package/dist/cli/{index-1wpnt86a.js → index-1msszzg2.js} +5 -5
- package/dist/cli/{index-12ewkms0.js → index-23mdeh2a.js} +1 -1
- package/dist/cli/{index-5hxv1er2.js → index-3ga3ts3h.js} +56 -3
- package/dist/cli/{index-38cfx8g8.js → index-427x3j6p.js} +2 -2
- package/dist/cli/{index-wph45kyb.js → index-4qpz7mpn.js} +4 -4
- package/dist/cli/{index-7nr9p5bd.js → index-54sd9bbn.js} +5 -5
- package/dist/cli/{index-fmhd3zc8.js → index-68ben2q8.js} +2 -2
- package/dist/cli/{index-n5a9dq5s.js → index-6jrn46zy.js} +1 -1
- package/dist/cli/{index-ernt0wrg.js → index-9eg8f4zm.js} +4306 -1504
- package/dist/cli/{index-hbe56wtn.js → index-9s2rp2j5.js} +2 -2
- 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-et28q7cp.js → index-dkprb20b.js} +1 -1
- package/dist/cli/{index-qw9aqays.js → index-dwc1wztn.js} +6 -6
- package/dist/cli/{index-0h39trak.js → index-enmvd9ap.js} +1 -1
- package/dist/cli/{index-kzmd4gs7.js → index-epq8am78.js} +1 -1
- package/dist/cli/{index-pqtmzee6.js → index-fsye9ygy.js} +4 -4
- package/dist/cli/{index-5q3xsqwm.js → index-gtpq64q7.js} +3 -3
- package/dist/cli/{index-5v8zws0s.js → index-hqa71xfm.js} +140 -9
- package/dist/cli/{index-5zy5k5w0.js → index-j97nc02q.js} +4 -4
- package/dist/cli/{index-bdpgfep1.js → index-jrxrjz89.js} +1 -1
- package/dist/cli/{index-516j9vsk.js → index-kkrbybgt.js} +27 -2
- package/dist/cli/{index-6mwha20t.js → index-mkpdcbye.js} +3 -3
- package/dist/cli/{index-6x36hhd3.js → index-myacmqmf.js} +34 -34
- package/dist/cli/{index-t93cp2tz.js → index-nw3z614g.js} +4 -4
- package/dist/cli/{index-ehvkz2zv.js → index-r4vve32m.js} +7 -7
- package/dist/cli/{index-m779twtf.js → index-rgfz80gt.js} +1 -1
- 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-2sqfrvxj.js → index-v4h99xhr.js} +2 -2
- package/dist/cli/{index-vmwmwahh.js → index-x4am0jxt.js} +3 -3
- package/dist/cli/{index-et7tg13p.js → index-y03jadcy.js} +269 -9
- package/dist/cli/{index-dpxg347z.js → index-y28np6j9.js} +3 -3
- package/dist/cli/{index-xz4q5vcg.js → index-zp6fss8c.js} +3 -3
- package/dist/cli/index.js +35 -35
- package/dist/cli/{knowledge-escalator-jmqbmfbf.js → knowledge-escalator-5q4y97e4.js} +11 -11
- package/dist/cli/{knowledge-events-5ksqpf4g.js → knowledge-events-x7q8yepd.js} +9 -9
- package/dist/cli/{knowledge-link-s2qs178z.js → knowledge-link-655xa3db.js} +3 -3
- package/dist/cli/{knowledge-store-q3yy56sc.js → knowledge-store-r7ng2nf8.js} +4 -4
- package/dist/cli/{knowledge-validator-r5kaz53f.js → knowledge-validator-e78m6cqe.js} +6 -6
- package/dist/cli/{mcp-h82hxnxr.js → mcp-208jwxps.js} +1 -1
- package/dist/cli/model-preflight-xakn1356.js +359 -0
- package/dist/cli/{pending-delegations-e4h6vjeb.js → pending-delegations-w4a5tg11.js} +7 -7
- package/dist/cli/{pr-subscriptions-j7hw3k6x.js → pr-subscriptions-8289esc9.js} +7 -7
- package/dist/cli/{pr-workflow-gate-js8dcry2.js → pr-workflow-gate-b7yx0x21.js} +34 -34
- package/dist/cli/{runner-tzgwvvn1.js → runner-b5vt1any.js} +4 -4
- package/dist/cli/{scan-cursor-yhf58mq2.js → scan-cursor-edpbzp72.js} +5 -5
- package/dist/cli/{schema-0k4st1qt.js → schema-dnsxhyr3.js} +1 -1
- package/dist/cli/{scope-persistence-bpptmh1e.js → scope-persistence-z1f7d4tw.js} +10 -10
- package/dist/cli/{server-axnran6h.js → server-t2edntv4.js} +69 -599
- package/dist/cli/{skill-generator-n2w032d1.js → skill-generator-5n7vf0s3.js} +13 -13
- package/dist/cli/{snapshot-coordination-init-kyf50x12.js → snapshot-coordination-init-t14dk9je.js} +34 -34
- package/dist/cli/{speckit-checkoff-m4184e1x.js → speckit-checkoff-4ws84g13.js} +3 -3
- 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-1g2414pf.js → worktree-collision-ownership-wj6337ec.js} +8 -8
- package/dist/cli/{worktree-isolation-x07f7cfp.js → worktree-isolation-9fyj85tc.js} +34 -34
- 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/hooks/delegation-gate.d.ts +10 -8
- package/dist/hooks/task-id-resolver.d.ts +7 -0
- package/dist/index.js +285 -269
- 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/package.json +1 -1
- package/dist/cli/curator-drift-hz3j3fad.js +0 -297
- package/dist/cli/model-preflight-5b81adsj.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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.181.
|
|
3
|
+
"version": "7.181.4",
|
|
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",
|
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
canonicalProjectKey,
|
|
4
|
-
getGlobalEventBus,
|
|
5
|
-
getGroupCommitWriter,
|
|
6
|
-
importLegacyJsonFiles
|
|
7
|
-
} from "./index-et7tg13p.js";
|
|
8
|
-
import {
|
|
9
|
-
readEffectiveSpecSync
|
|
10
|
-
} from "./index-m779twtf.js";
|
|
11
|
-
import"./index-kzmd4gs7.js";
|
|
12
|
-
import {
|
|
13
|
-
readSwarmFileAsync
|
|
14
|
-
} from "./index-gc6h1fmf.js";
|
|
15
|
-
import"./index-2s7dvzff.js";
|
|
16
|
-
import"./index-0725jpp7.js";
|
|
17
|
-
import {
|
|
18
|
-
DURABILITY_CLASSES,
|
|
19
|
-
getProjectDb,
|
|
20
|
-
projectDbExists
|
|
21
|
-
} from "./index-vvgpgcyn.js";
|
|
22
|
-
import"./index-rdm3px0g.js";
|
|
23
|
-
import"./index-ry16d01s.js";
|
|
24
|
-
import"./index-1xnse449.js";
|
|
25
|
-
import"./index-c1ggtmpm.js";
|
|
26
|
-
import"./index-ejhxgyvm.js";
|
|
27
|
-
import"./index-7g4c7s5r.js";
|
|
28
|
-
import"./index-989v83pb.js";
|
|
29
|
-
import"./index-n5a9dq5s.js";
|
|
30
|
-
import"./index-zxdawwc7.js";
|
|
31
|
-
import"./index-5hxv1er2.js";
|
|
32
|
-
import"./index-2t21pv2v.js";
|
|
33
|
-
import"./index-bk5tah7q.js";
|
|
34
|
-
import"./index-gknz3bv1.js";
|
|
35
|
-
import"./index-zpsr8rpc.js";
|
|
36
|
-
import {
|
|
37
|
-
init_logger,
|
|
38
|
-
warn
|
|
39
|
-
} from "./index-zgwm4ryv.js";
|
|
40
|
-
import"./index-a76rekgs.js";
|
|
41
|
-
|
|
42
|
-
// src/db/phase-report-store.ts
|
|
43
|
-
import { readdirSync } from "fs";
|
|
44
|
-
import { join } from "path";
|
|
45
|
-
var PHASE_REPORT_LEGACY_PREFIXES = {
|
|
46
|
-
curator_drift: "drift-report-phase-",
|
|
47
|
-
design_doc_drift: "doc-drift-phase-"
|
|
48
|
-
};
|
|
49
|
-
var importedRoots = new Set;
|
|
50
|
-
function hasAnyPhaseReportState(directory) {
|
|
51
|
-
if (projectDbExists(directory))
|
|
52
|
-
return true;
|
|
53
|
-
const root = canonicalProjectKey(directory);
|
|
54
|
-
let entries;
|
|
55
|
-
try {
|
|
56
|
-
entries = readdirSync(join(root, ".swarm"));
|
|
57
|
-
} catch {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
for (const prefix of Object.values(PHASE_REPORT_LEGACY_PREFIXES)) {
|
|
61
|
-
if (entries.some((name) => name.startsWith(prefix) && name.endsWith(".json") && !name.includes(".imported"))) {
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
function kindCount(db, kind) {
|
|
68
|
-
return db.query("SELECT COUNT(*) as count FROM phase_report WHERE kind = ?").get(kind)?.count ?? 0;
|
|
69
|
-
}
|
|
70
|
-
function ensurePhaseReportsImported(directory) {
|
|
71
|
-
const root = canonicalProjectKey(directory);
|
|
72
|
-
if (importedRoots.has(root))
|
|
73
|
-
return;
|
|
74
|
-
for (const kind of Object.keys(PHASE_REPORT_LEGACY_PREFIXES)) {
|
|
75
|
-
importLegacyJsonFiles(directory, {
|
|
76
|
-
filePrefix: PHASE_REPORT_LEGACY_PREFIXES[kind],
|
|
77
|
-
kind,
|
|
78
|
-
kindCount: (db) => kindCount(db, kind),
|
|
79
|
-
upsertRow: (db, phase, payload) => {
|
|
80
|
-
db.run(`INSERT INTO phase_report (kind, phase, payload, updated_at)
|
|
81
|
-
VALUES (?, ?, ?, datetime('now'))
|
|
82
|
-
ON CONFLICT(kind, phase) DO UPDATE SET
|
|
83
|
-
payload = excluded.payload,
|
|
84
|
-
updated_at = datetime('now')`, [kind, phase, payload]);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
importedRoots.add(root);
|
|
89
|
-
}
|
|
90
|
-
async function upsertPhaseReportDb(directory, kind, phase, payload) {
|
|
91
|
-
ensurePhaseReportsImported(directory);
|
|
92
|
-
const writer = getGroupCommitWriter(directory);
|
|
93
|
-
writer.enqueue({
|
|
94
|
-
durability: DURABILITY_CLASSES.phase_report,
|
|
95
|
-
run: (db) => {
|
|
96
|
-
db.run(`INSERT INTO phase_report (kind, phase, payload, updated_at)
|
|
97
|
-
VALUES (?, ?, ?, datetime('now'))
|
|
98
|
-
ON CONFLICT(kind, phase) DO UPDATE SET
|
|
99
|
-
payload = excluded.payload,
|
|
100
|
-
updated_at = datetime('now')`, [kind, phase, payload]);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
await writer.flush();
|
|
104
|
-
}
|
|
105
|
-
function readPhaseReportsDb(directory, kind) {
|
|
106
|
-
if (!hasAnyPhaseReportState(directory))
|
|
107
|
-
return [];
|
|
108
|
-
ensurePhaseReportsImported(directory);
|
|
109
|
-
const db = getProjectDb(directory);
|
|
110
|
-
return db.query("SELECT phase, payload FROM phase_report WHERE kind = ? ORDER BY phase").all(kind).map((row) => ({ phase: row.phase, payload: row.payload }));
|
|
111
|
-
}
|
|
112
|
-
function phaseReportLocator(kind, phase) {
|
|
113
|
-
return `swarm.db:phase_report(${kind},${phase})`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// src/hooks/curator-drift.ts
|
|
117
|
-
init_logger();
|
|
118
|
-
async function readPriorDriftReports(directory) {
|
|
119
|
-
const reports = [];
|
|
120
|
-
try {
|
|
121
|
-
for (const row of readPhaseReportsDb(directory, "curator_drift")) {
|
|
122
|
-
try {
|
|
123
|
-
const report = JSON.parse(row.payload);
|
|
124
|
-
if (typeof report.phase !== "number" || typeof report.alignment !== "string" || typeof report.timestamp !== "string" || typeof report.drift_score !== "number" || typeof report.schema_version !== "number" || !Array.isArray(report.compounding_effects)) {
|
|
125
|
-
warn(`[curator-drift] Skipping corrupt drift report: phase ${row.phase}`);
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
reports.push(report);
|
|
129
|
-
} catch {
|
|
130
|
-
warn(`[curator-drift] Skipping unreadable drift report: phase ${row.phase}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
} catch {
|
|
134
|
-
return [];
|
|
135
|
-
}
|
|
136
|
-
reports.sort((a, b) => a.phase - b.phase);
|
|
137
|
-
return reports;
|
|
138
|
-
}
|
|
139
|
-
async function writeDriftReport(directory, report) {
|
|
140
|
-
const locator = phaseReportLocator("curator_drift", report.phase);
|
|
141
|
-
try {
|
|
142
|
-
await upsertPhaseReportDb(directory, "curator_drift", report.phase, JSON.stringify(report, null, 2));
|
|
143
|
-
} catch (err) {
|
|
144
|
-
throw new Error(`[curator-drift] Failed to write drift report to ${locator}: ${String(err)}`);
|
|
145
|
-
}
|
|
146
|
-
return locator;
|
|
147
|
-
}
|
|
148
|
-
var _internals = {
|
|
149
|
-
readPriorDriftReports,
|
|
150
|
-
writeDriftReport,
|
|
151
|
-
runDeterministicDriftCheck,
|
|
152
|
-
buildDriftInjectionText
|
|
153
|
-
};
|
|
154
|
-
function extractRequirementIds(text) {
|
|
155
|
-
const matches = text.match(/(?:[A-Za-z0-9][A-Za-z0-9._-]*\/)?FR-\d{3}/g);
|
|
156
|
-
return matches ? [...new Set(matches)] : [];
|
|
157
|
-
}
|
|
158
|
-
function bareSuffixCovers(specId, refId) {
|
|
159
|
-
return refId === specId || !refId.includes("/") && specId.endsWith(`/${refId}`);
|
|
160
|
-
}
|
|
161
|
-
async function runDeterministicDriftCheck(directory, phase, curatorResult, config, injectAdvisory) {
|
|
162
|
-
try {
|
|
163
|
-
const planMd = await readSwarmFileAsync(directory, "plan.md");
|
|
164
|
-
const specMd = readEffectiveSpecSync(directory)?.content ?? null;
|
|
165
|
-
const priorReports = await _internals.readPriorDriftReports(directory);
|
|
166
|
-
const complianceCount = curatorResult.compliance.length;
|
|
167
|
-
const warningCompliance = curatorResult.compliance.filter((obs) => obs.severity === "warning");
|
|
168
|
-
let alignment = "ALIGNED";
|
|
169
|
-
let driftScore = 0;
|
|
170
|
-
const specRequirements = specMd ? extractRequirementIds(specMd) : [];
|
|
171
|
-
const planRequirements = planMd ? extractRequirementIds(planMd) : [];
|
|
172
|
-
const digestRequirements = extractRequirementIds(JSON.stringify(curatorResult.digest) + JSON.stringify(curatorResult.compliance) + JSON.stringify(curatorResult.knowledge_recommendations ?? []));
|
|
173
|
-
if (!planMd) {
|
|
174
|
-
alignment = "MINOR_DRIFT";
|
|
175
|
-
driftScore = 0.3;
|
|
176
|
-
} else if (specRequirements.length > 0) {
|
|
177
|
-
const coveredInPlan = specRequirements.filter((fr) => planRequirements.some((ref) => bareSuffixCovers(fr, ref)));
|
|
178
|
-
const coveredInDigest = specRequirements.filter((fr) => digestRequirements.some((ref) => bareSuffixCovers(fr, ref)));
|
|
179
|
-
const specCoverageRatio = coveredInPlan.length / specRequirements.length;
|
|
180
|
-
const implementationRatio = coveredInDigest.length / specRequirements.length;
|
|
181
|
-
if (specCoverageRatio < 0.5) {
|
|
182
|
-
alignment = "MAJOR_DRIFT";
|
|
183
|
-
driftScore = Math.min(0.9, 0.6 + (1 - specCoverageRatio) * 0.3);
|
|
184
|
-
} else if (warningCompliance.length >= 3) {
|
|
185
|
-
alignment = "MAJOR_DRIFT";
|
|
186
|
-
driftScore = Math.min(0.9, 0.5 + warningCompliance.length * 0.1);
|
|
187
|
-
} else if (warningCompliance.length >= 1 || complianceCount >= 3) {
|
|
188
|
-
alignment = "MINOR_DRIFT";
|
|
189
|
-
driftScore = Math.min(0.49, 0.2 + complianceCount * 0.05);
|
|
190
|
-
} else if (implementationRatio < 0.5) {
|
|
191
|
-
alignment = "MINOR_DRIFT";
|
|
192
|
-
driftScore = Math.min(0.6, 0.2 + (1 - implementationRatio) * 0.3);
|
|
193
|
-
}
|
|
194
|
-
} else {
|
|
195
|
-
if (warningCompliance.length >= 3) {
|
|
196
|
-
alignment = "MAJOR_DRIFT";
|
|
197
|
-
driftScore = Math.min(0.9, 0.5 + warningCompliance.length * 0.1);
|
|
198
|
-
} else if (warningCompliance.length >= 1 || complianceCount >= 3) {
|
|
199
|
-
alignment = "MINOR_DRIFT";
|
|
200
|
-
driftScore = Math.min(0.49, 0.2 + complianceCount * 0.05);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
const keyCorrections = warningCompliance.map((obs) => obs.description);
|
|
204
|
-
const firstDeviation = warningCompliance.length > 0 ? {
|
|
205
|
-
phase,
|
|
206
|
-
task: "unknown",
|
|
207
|
-
description: warningCompliance[0]?.description ?? ""
|
|
208
|
-
} : null;
|
|
209
|
-
const requirementsChecked = curatorResult.digest.tasks_total;
|
|
210
|
-
const requirementsSatisfied = curatorResult.digest.tasks_completed;
|
|
211
|
-
const coverageNote = specRequirements.length > 0 ? ` [${digestRequirements.filter((ref) => specRequirements.some((fr) => bareSuffixCovers(fr, ref))).length}/${specRequirements.length} FRs covered]` : "";
|
|
212
|
-
const injectionSummaryRaw = `Phase ${phase}: ${alignment} (${driftScore.toFixed(2)})${coverageNote} \u2014 ${firstDeviation ? firstDeviation.description : "all requirements on track"}.${keyCorrections.length > 0 ? `Correction: ${keyCorrections[0] ?? ""}.` : ""}`;
|
|
213
|
-
const injectionSummary = injectionSummaryRaw.slice(0, config.drift_inject_max_chars);
|
|
214
|
-
const report = {
|
|
215
|
-
schema_version: 1,
|
|
216
|
-
phase,
|
|
217
|
-
timestamp: new Date().toISOString(),
|
|
218
|
-
alignment,
|
|
219
|
-
drift_score: driftScore,
|
|
220
|
-
first_deviation: firstDeviation,
|
|
221
|
-
compounding_effects: priorReports.filter((r) => r.alignment !== "ALIGNED").map((r) => `Phase ${r.phase}: ${r.alignment}`).slice(0, 5),
|
|
222
|
-
corrections: keyCorrections.slice(0, 5),
|
|
223
|
-
requirements_checked: requirementsChecked,
|
|
224
|
-
requirements_satisfied: requirementsSatisfied,
|
|
225
|
-
scope_additions: [],
|
|
226
|
-
injection_summary: injectionSummary
|
|
227
|
-
};
|
|
228
|
-
const reportPath = await _internals.writeDriftReport(directory, report);
|
|
229
|
-
getGlobalEventBus().publish("curator.drift.completed", {
|
|
230
|
-
phase,
|
|
231
|
-
alignment,
|
|
232
|
-
drift_score: driftScore,
|
|
233
|
-
report_path: reportPath
|
|
234
|
-
});
|
|
235
|
-
if (injectAdvisory && alignment !== "ALIGNED" && driftScore > 0) {
|
|
236
|
-
try {
|
|
237
|
-
const advisoryText = `CURATOR DRIFT DETECTED (phase ${phase}, score ${driftScore.toFixed(2)}): ${injectionSummary.slice(0, 300)}. Review the phase-${phase} drift report stored in .swarm/swarm.db (${phaseReportLocator("curator_drift", phase)}) and address spec alignment before proceeding. Consider running critic_drift_verifier before phase completion to get a proper drift review.`;
|
|
238
|
-
injectAdvisory(advisoryText);
|
|
239
|
-
} catch {}
|
|
240
|
-
}
|
|
241
|
-
const injectionText = injectionSummary;
|
|
242
|
-
return {
|
|
243
|
-
phase,
|
|
244
|
-
report,
|
|
245
|
-
report_path: reportPath,
|
|
246
|
-
injection_text: injectionText
|
|
247
|
-
};
|
|
248
|
-
} catch (err) {
|
|
249
|
-
getGlobalEventBus().publish("curator.error", {
|
|
250
|
-
operation: "drift",
|
|
251
|
-
phase,
|
|
252
|
-
error: String(err)
|
|
253
|
-
});
|
|
254
|
-
const defaultReport = {
|
|
255
|
-
schema_version: 1,
|
|
256
|
-
phase,
|
|
257
|
-
timestamp: new Date().toISOString(),
|
|
258
|
-
alignment: "ALIGNED",
|
|
259
|
-
drift_score: 0,
|
|
260
|
-
first_deviation: null,
|
|
261
|
-
compounding_effects: [],
|
|
262
|
-
corrections: [],
|
|
263
|
-
requirements_checked: 0,
|
|
264
|
-
requirements_satisfied: 0,
|
|
265
|
-
scope_additions: [],
|
|
266
|
-
injection_summary: `Phase ${phase}: drift analysis unavailable (${String(err)})`
|
|
267
|
-
};
|
|
268
|
-
return {
|
|
269
|
-
phase,
|
|
270
|
-
report: defaultReport,
|
|
271
|
-
report_path: "",
|
|
272
|
-
injection_text: ""
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
function buildDriftInjectionText(report, maxChars) {
|
|
277
|
-
if (maxChars <= 0) {
|
|
278
|
-
return "";
|
|
279
|
-
}
|
|
280
|
-
let text;
|
|
281
|
-
if (report.alignment === "ALIGNED" && report.drift_score < 0.1) {
|
|
282
|
-
text = `<drift_report>Phase ${report.phase}: ALIGNED, all requirements on track.</drift_report>`;
|
|
283
|
-
} else {
|
|
284
|
-
const keyFinding = report.first_deviation?.description ?? "no deviation recorded";
|
|
285
|
-
const score = report.drift_score ?? 0;
|
|
286
|
-
const correctionClause = report.corrections?.[0] ? `Correction: ${report.corrections[0]}.` : "";
|
|
287
|
-
text = `<drift_report>Phase ${report.phase}: ${report.alignment} (${score.toFixed(2)}) \u2014 ${keyFinding}. ${correctionClause}</drift_report>`;
|
|
288
|
-
}
|
|
289
|
-
return text.slice(0, maxChars);
|
|
290
|
-
}
|
|
291
|
-
export {
|
|
292
|
-
writeDriftReport,
|
|
293
|
-
runDeterministicDriftCheck,
|
|
294
|
-
readPriorDriftReports,
|
|
295
|
-
buildDriftInjectionText,
|
|
296
|
-
_internals
|
|
297
|
-
};
|