@aiwg/cli 2026.10.4 → 2026.10.6
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/agentic/code/addons/composition-engine/lib/runtime.mjs +1401 -0
- package/agentic/code/addons/composition-engine/lib/validator.mjs +513 -0
- package/agentic/code/addons/composition-engine/schemas/flow-graph.schema.json +372 -0
- package/agentic/code/providers/model-capabilities.v1.json +74 -50
- package/bin/aiwg.mjs +3 -1
- package/dist/src/artifacts/browser-export.js +1 -0
- package/dist/src/artifacts/citation-parser.js +8 -1
- package/dist/src/artifacts/cli.js +72 -9
- package/dist/src/artifacts/fortemi-core-query-adapter.js +2 -0
- package/dist/src/artifacts/fortemi-core-sync.js +26 -8
- package/dist/src/artifacts/graph-query.js +18 -8
- package/dist/src/artifacts/index-adapters.js +339 -0
- package/dist/src/artifacts/index-builder.js +146 -16
- package/dist/src/artifacts/index-files.js +15 -4
- package/dist/src/artifacts/index-preparation.js +91 -26
- package/dist/src/artifacts/index-reader.js +44 -0
- package/dist/src/artifacts/index-refresh.js +130 -56
- package/dist/src/artifacts/index-status.js +20 -5
- package/dist/src/artifacts/index-worker.mjs +9 -7
- package/dist/src/artifacts/memory-maintenance.js +503 -0
- package/dist/src/artifacts/prebuilt-relations.js +3 -1
- package/dist/src/artifacts/query-engine.js +263 -108
- package/dist/src/artifacts/relations-builder.js +2 -2
- package/dist/src/artifacts/source-graph.js +2 -2
- package/dist/src/artifacts/types.js +9 -1
- package/dist/src/cli/handlers/decision.js +19 -1
- package/dist/src/cli/handlers/guided-setup.js +470 -0
- package/dist/src/cli/handlers/help.js +2 -2
- package/dist/src/cli/handlers/housekeeper.js +1110 -0
- package/dist/src/cli/handlers/index.js +4 -2
- package/dist/src/cli/handlers/init.js +41 -6
- package/dist/src/cli/handlers/local-executor.js +5 -3
- package/dist/src/cli/handlers/mc.js +509 -53
- package/dist/src/cli/handlers/models.js +32 -2
- package/dist/src/cli/handlers/ralph-launcher.js +76 -4
- package/dist/src/cli/handlers/rules.js +1 -1
- package/dist/src/cli/handlers/script-runner.js +73 -2
- package/dist/src/cli/handlers/serve.js +5 -3
- package/dist/src/cli/handlers/sessions.js +40 -6
- package/dist/src/cli/handlers/setup.js +428 -1
- package/dist/src/cli/handlers/skill-lint.js +1 -1
- package/dist/src/cli/handlers/subcommands.js +118 -8
- package/dist/src/cli/handlers/use.js +279 -93
- package/dist/src/cli/handlers/workspace.js +3 -1
- package/dist/src/cli/prompt-utils.js +8 -0
- package/dist/src/cli/router.js +16 -1
- package/dist/src/config/aiwg-config.js +42 -0
- package/dist/src/config/cli.js +7 -3
- package/dist/src/config/decision-config.js +14 -1
- package/dist/src/config/native-sandbox-warnings.js +25 -0
- package/dist/src/contributors/validation.js +6 -5
- package/dist/src/decision/admission.js +7 -3
- package/dist/src/decision/benchmark.js +469 -0
- package/dist/src/decision/ledger.js +22 -3
- package/dist/src/decision/pricing.js +147 -0
- package/dist/src/decision/qualification/gate-evidence.js +18 -15
- package/dist/src/decision/qualification/load-staged.js +539 -0
- package/dist/src/decision/qualification/load.js +109 -33
- package/dist/src/decision/qualification/runner.js +5 -2
- package/dist/src/decision/review/service.js +6 -4
- package/dist/src/decision/review/validate.js +23 -2
- package/dist/src/decision/savings.js +8 -3
- package/dist/src/discovery/index.js +492 -0
- package/dist/src/discovery/interview.js +233 -0
- package/dist/src/discovery/plan-apply.js +571 -0
- package/dist/src/discovery/plan-store.js +171 -0
- package/dist/src/discovery/plan-types.js +2 -0
- package/dist/src/discovery/plan-validation.js +139 -0
- package/dist/src/discovery/types.js +2 -0
- package/dist/src/extensions/commands/definitions.js +49 -9
- package/dist/src/extensions/manifest.js +71 -44
- package/dist/src/extensions/project-local-discovery.js +1 -1
- package/dist/src/extensions/project-quickref.js +18 -17
- package/dist/src/extensions/validation.js +32 -29
- package/dist/src/housekeeper/daemon-config.js +148 -0
- package/dist/src/housekeeper/ipc.js +84 -0
- package/dist/src/housekeeper/lifecycle.js +148 -0
- package/dist/src/housekeeper/platform.js +35 -0
- package/dist/src/housekeeper/status.js +70 -0
- package/dist/src/housekeeper/units.js +114 -0
- package/dist/src/jobs/flow.js +22 -21
- package/dist/src/lint/rule-activation.js +20 -5
- package/dist/src/lint/runner.js +1 -1
- package/dist/src/mcp/cli.mjs +5 -6
- package/dist/src/mcp/config-file.mjs +6 -2
- package/dist/src/mcp/config-layers.mjs +23 -7
- package/dist/src/mcp/profiles.js +18 -31
- package/dist/src/mcp/profiles.mjs +18 -32
- package/dist/src/mcp/registry.js +7 -27
- package/dist/src/mcp/registry.mjs +7 -28
- package/dist/src/mcp/server.mjs +34 -1
- package/dist/src/mcp/tools/agentic-sandbox.mjs +8 -7
- package/dist/src/mcp/tools/command-run.mjs +3 -2
- package/dist/src/mcp/tools/decision.mjs +49 -48
- package/dist/src/mcp/tools/discovery.mjs +46 -21
- package/dist/src/mcp/tools/orchestration.mjs +22 -22
- package/dist/src/mcp/tools/subsystems.mjs +9 -8
- package/dist/src/mcp/tools/worker-invoke.mjs +17 -4
- package/dist/src/mcp/tools/writer-profiles.mjs +1 -1
- package/dist/src/memory/audit.js +719 -0
- package/dist/src/memory/canonical-context.js +392 -13
- package/dist/src/memory/canonical-maintenance.js +95 -0
- package/dist/src/memory/cli-result.js +22 -0
- package/dist/src/memory/cli.js +176 -0
- package/dist/src/memory/context-pack.js +57 -6
- package/dist/src/memory/cost.js +512 -0
- package/dist/src/memory/firewall-classification.d.mts +7 -0
- package/dist/src/memory/firewall-classification.mjs +32 -0
- package/dist/src/memory/index.js +8 -0
- package/dist/src/memory/line-maintenance.js +68 -0
- package/dist/src/memory/maintenance-cli.js +286 -0
- package/dist/src/memory/maintenance-contract.js +136 -0
- package/dist/src/memory/maintenance-index.js +18 -0
- package/dist/src/memory/maintenance-owner.js +2 -0
- package/dist/src/memory/maintenance-record.js +138 -0
- package/dist/src/memory/maintenance.js +254 -0
- package/dist/src/memory/provider-memory-adapter.js +154 -0
- package/dist/src/memory/recommend-cli.js +83 -0
- package/dist/src/memory/recommend.js +269 -0
- package/dist/src/memory/scheduled.js +81 -0
- package/dist/src/memory/taxonomy.js +44 -0
- package/dist/src/mission-protocol/codecs.js +19 -9
- package/dist/src/models/config-loader.js +11 -1
- package/dist/src/models/model-capabilities.v1.json +74 -50
- package/dist/src/models/provider-policy.js +125 -62
- package/dist/src/models/resolver.js +45 -8
- package/dist/src/models/worker-installation.d.mts +7 -0
- package/dist/src/models/worker-installation.mjs +169 -37
- package/dist/src/models/wrapper-route.js +1 -1
- package/dist/src/output-modes/registry.js +8 -7
- package/dist/src/plugin/metadata-validator.js +1 -1
- package/dist/src/providers/deploy-version.d.mts +1 -0
- package/dist/src/providers/deploy-version.mjs +17 -0
- package/dist/src/providers/provider-definitions.js +19 -16
- package/dist/src/providers/skill-ownership.d.mts +11 -2
- package/dist/src/providers/skill-ownership.mjs +35 -17
- package/dist/src/rules/activation.d.mts +11 -2
- package/dist/src/rules/activation.mjs +82 -6
- package/dist/src/rules/inventory.js +1 -1
- package/dist/src/rules/rule-frontmatter.schema.json +2 -0
- package/dist/src/schema/zod-validation.d.mts +6 -0
- package/dist/src/schema/zod-validation.mjs +50 -0
- package/dist/src/serve/executor-registry.js +297 -20
- package/dist/src/serve/executor-token.d.mts +1 -0
- package/dist/src/serve/executor-token.mjs +8 -0
- package/dist/src/serve/shared-host-scheduler.js +1102 -31
- package/dist/src/serve/worker-invocation.js +114 -15
- package/dist/src/sessions/adapters/claude.js +19 -18
- package/dist/src/sessions/adapters/codex.js +33 -19
- package/dist/src/sessions/adapters/copilot.js +14 -13
- package/dist/src/sessions/adapters/cursor.js +19 -18
- package/dist/src/sessions/adapters/deepseek-harness.js +9 -8
- package/dist/src/sessions/adapters/factory.js +11 -10
- package/dist/src/sessions/adapters/generic.js +32 -23
- package/dist/src/sessions/adapters/grokbot.js +35 -35
- package/dist/src/sessions/adapters/hermes.js +20 -19
- package/dist/src/sessions/adapters/muse.js +50 -49
- package/dist/src/sessions/adapters/omp.js +5 -4
- package/dist/src/sessions/adapters/openclaw.js +30 -29
- package/dist/src/sessions/adapters/opencode.js +26 -26
- package/dist/src/sessions/adapters/openhuman.js +24 -23
- package/dist/src/sessions/adapters/pi.js +5 -4
- package/dist/src/sessions/adapters/windsurf.js +8 -8
- package/dist/src/sessions/analytics.js +10 -9
- package/dist/src/sessions/batch-contracts.js +1 -1
- package/dist/src/sessions/batch-import.js +202 -2
- package/dist/src/sessions/candidates.js +7 -6
- package/dist/src/sessions/contracts.js +73 -54
- package/dist/src/sessions/coverage-preflight.js +26 -1
- package/dist/src/sessions/output-registration.js +11 -10
- package/dist/src/sessions/policy.js +18 -7
- package/dist/src/sessions/refresh.js +2 -3
- package/dist/src/sessions/repository.js +4 -2
- package/dist/src/sessions/workspace-discovery.js +92 -26
- package/dist/src/smiths/context-pipeline/aiwg-md.js +18 -1
- package/dist/src/smiths/context-pipeline/claude-hook.js +42 -6
- package/dist/src/smiths/context-pipeline/parallelism-section.js +72 -5
- package/dist/src/smiths/context-pipeline/workspace-context.js +106 -10
- package/dist/src/update/checker.d.mts +4 -0
- package/dist/src/update/checker.mjs +14 -0
- package/dist/src/writing/exemplar-selection.js +6 -6
- package/dist/src/writing/voice-evaluation.js +24 -23
- package/dist/src/writing/writer-migration.js +14 -13
- package/dist/src/writing/writer-profile.js +19 -18
- package/dist/src/writing/writing-brief.js +18 -17
- package/dist/src/writing/writing-receipt.js +47 -46
- package/package.json +5 -2
- package/schemas/decision/DecisionReview.schema.json +78 -1
- package/schemas/mission-v1.schema.json +3 -0
- package/tools/agents/deploy-agents.mjs +67 -39
- package/tools/agents/providers/antigravity.mjs +6 -1
- package/tools/agents/providers/base.mjs +19 -13
- package/tools/agents/providers/claude.mjs +1 -1
- package/tools/agents/providers/codex.mjs +50 -56
- package/tools/agents/providers/copilot.mjs +8 -2
- package/tools/agents/providers/cursor.mjs +1 -1
- package/tools/agents/providers/deepseek-harness.mjs +1 -1
- package/tools/agents/providers/factory.mjs +7 -1
- package/tools/agents/providers/grok-build.mjs +18 -2
- package/tools/agents/providers/grokbot.mjs +1 -1
- package/tools/agents/providers/hermes.mjs +7 -13
- package/tools/agents/providers/muse-hooks.mjs +21 -14
- package/tools/agents/providers/muse.mjs +7 -2
- package/tools/agents/providers/omp.mjs +28 -4
- package/tools/agents/providers/opencode.mjs +14 -5
- package/tools/agents/providers/openhuman.mjs +1 -1
- package/tools/agents/providers/pi.mjs +1 -1
- package/tools/agents/providers/provider-prepare-coordinator.mjs +29 -9
- package/tools/agents/providers/rule-delivery.mjs +263 -71
- package/tools/agents/providers/windsurf.mjs +7 -0
- package/tools/cli/workspace-status.mjs +5 -0
- package/tools/commands/deploy-prompts-codex.mjs +11 -8
- package/tools/ralph-external/lib/codex-adapter.mjs +6 -2
- package/tools/ralph-external/lib/muse-adapter.mjs +12 -2
- package/tools/ralph-external/lib/worker-health.mjs +1 -1
- package/tools/ralph-external/lib/worker-isolation.mjs +65 -9
- package/tools/ralph-external/process-monitor.mjs +7 -4
- package/tools/ralph-external/session-launcher.mjs +280 -32
- package/tools/skills/deploy-skills-codex.mjs +11 -7
- package/vscode-extension/schemas/aiwg.config.v1.json +11 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { canonicalJson } from '../../security/artifact-trust.js';
|
|
3
3
|
import { AdmissionError, DecisionAdmissionRegistry } from '../admission.js';
|
|
4
|
+
import { verifyDecisionStagedLoadRecord } from './load-staged.js';
|
|
5
|
+
export * from './load-staged.js';
|
|
4
6
|
export function decisionLoadManifestDigest(bytes) {
|
|
5
7
|
return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;
|
|
6
8
|
}
|
|
@@ -56,7 +58,7 @@ export function decisionLoadPolicy(manifest, workspaceId, principalId) {
|
|
|
56
58
|
};
|
|
57
59
|
}
|
|
58
60
|
/** Drives each arrival straight through a registry-owned `DecisionAdmissionController`. */
|
|
59
|
-
export function admissionControllerLoadDriver(manifest, clock, registry = new DecisionAdmissionRegistry()) {
|
|
61
|
+
export function admissionControllerLoadDriver(manifest, clock, registry = new DecisionAdmissionRegistry(), hooks = {}) {
|
|
60
62
|
const workspaceId = 'load-harness';
|
|
61
63
|
for (const principal of manifest.principals)
|
|
62
64
|
registry.register(decisionLoadPolicy(manifest, workspaceId, principal.id), clock.now);
|
|
@@ -68,32 +70,81 @@ export function admissionControllerLoadDriver(manifest, clock, registry = new De
|
|
|
68
70
|
attempts += 1;
|
|
69
71
|
let lease;
|
|
70
72
|
try {
|
|
71
|
-
|
|
73
|
+
const pendingLease = controller.acquire({ budgetId: `load-${arrival.ordinal}`, principalId: arrival.principalId,
|
|
72
74
|
workspaceId, providerId: arrival.providerId, signal,
|
|
73
|
-
estimate: { tokens: arrival.tokens, attempts: 1, batchSize: 1, items: 1, costUsd: 0, retainedWork: 1 },
|
|
75
|
+
estimate: { tokens: arrival.tokens, attempts: 1, batchSize: 1, items: 1, costUsd: hooks.estimateCost?.(arrival) ?? 0, retainedWork: 1 },
|
|
74
76
|
deadlineEpochMs: clock.now() + manifest.workspace.maxQueueWaitMs + arrival.serviceMs });
|
|
77
|
+
hooks.onStateChange?.();
|
|
78
|
+
lease = await pendingLease;
|
|
75
79
|
}
|
|
76
80
|
catch (error) {
|
|
77
|
-
if (!(error instanceof AdmissionError))
|
|
81
|
+
if (!(error instanceof AdmissionError)) {
|
|
82
|
+
hooks.onDriverError?.();
|
|
83
|
+
controller.releaseBudget(`load-${arrival.ordinal}`);
|
|
78
84
|
throw error;
|
|
85
|
+
}
|
|
79
86
|
controller.releaseBudget(`load-${arrival.ordinal}`);
|
|
80
87
|
return { attempts, outcome: error.evidence.reason === 'cancelled' ? 'cancelled' : 'shed',
|
|
81
88
|
admissionReason: error.evidence.reason, queueDelaysMs, settledAtMs: clock.now() };
|
|
82
89
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
try {
|
|
91
|
+
queueDelaysMs.push(lease.evidence.queueDelayMs);
|
|
92
|
+
if (signal.aborted || hooks.beforeDispatch?.(arrival, retry + 1) === false) {
|
|
93
|
+
lease.release();
|
|
94
|
+
controller.releaseBudget(`load-${arrival.ordinal}`);
|
|
95
|
+
return { attempts: retry, outcome: 'cancelled', queueDelaysMs, settledAtMs: clock.now() };
|
|
96
|
+
}
|
|
97
|
+
hooks.onAdmission?.(arrival, retry + 1, lease.evidence);
|
|
98
|
+
let observation;
|
|
99
|
+
let dispatched;
|
|
100
|
+
try {
|
|
101
|
+
if (hooks.backend) {
|
|
102
|
+
observation = await hooks.backend(arrival, signal, context, retry + 1);
|
|
103
|
+
dispatched = signal.aborted ? 'aborted' : 'completed';
|
|
104
|
+
}
|
|
105
|
+
else
|
|
106
|
+
dispatched = await context.dispatch(arrival.serviceMs, signal);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
observation = { status: 'error', reason: 'executor-unavailable', actualModel: null, uncertainty: null,
|
|
110
|
+
requestId: null, usage: { inputTokens: null, outputTokens: null, costUsd: null } };
|
|
111
|
+
dispatched = signal.aborted ? 'aborted' : 'completed';
|
|
112
|
+
}
|
|
113
|
+
const failed = observation ? observation.status !== 'success' : arrival.failsFirstAttempt && retry === 0;
|
|
114
|
+
lease.release({ success: dispatched === 'completed' && !failed, ...(observation?.retryAfterMs === undefined ? {} : { retryAfterMs: observation.retryAfterMs }) });
|
|
115
|
+
if (observation)
|
|
116
|
+
hooks.onObservation?.(arrival, retry + 1, lease.evidence, observation);
|
|
117
|
+
if (dispatched === 'aborted') {
|
|
118
|
+
controller.releaseBudget(`load-${arrival.ordinal}`);
|
|
119
|
+
return { attempts, outcome: 'cancelled', queueDelaysMs, settledAtMs: clock.now() };
|
|
120
|
+
}
|
|
121
|
+
if (!failed) {
|
|
122
|
+
controller.releaseBudget(`load-${arrival.ordinal}`);
|
|
123
|
+
return { attempts, outcome: 'completed', queueDelaysMs, settledAtMs: clock.now() };
|
|
124
|
+
}
|
|
125
|
+
if (observation && !['service-error', 'rate-limited', 'network-transient', 'timeout'].includes(observation.reason))
|
|
126
|
+
break;
|
|
127
|
+
if (signal.aborted)
|
|
128
|
+
break;
|
|
129
|
+
if (retry < manifest.arrivalModel.maxRetries) {
|
|
130
|
+
await new Promise(done => {
|
|
131
|
+
const finish = () => { clearTimeout(timer); signal.removeEventListener('abort', finish); done(); };
|
|
132
|
+
const timer = setTimeout(finish, manifest.arrivalModel.retryBackoffMs);
|
|
133
|
+
if (signal.aborted)
|
|
134
|
+
finish();
|
|
135
|
+
else
|
|
136
|
+
signal.addEventListener('abort', finish, { once: true });
|
|
137
|
+
});
|
|
138
|
+
}
|
|
90
139
|
}
|
|
91
|
-
|
|
140
|
+
catch (error) {
|
|
141
|
+
hooks.onDriverError?.();
|
|
92
142
|
controller.releaseBudget(`load-${arrival.ordinal}`);
|
|
93
|
-
|
|
143
|
+
throw error;
|
|
94
144
|
}
|
|
95
|
-
|
|
96
|
-
|
|
145
|
+
finally {
|
|
146
|
+
lease.release();
|
|
147
|
+
hooks.onStateChange?.();
|
|
97
148
|
}
|
|
98
149
|
}
|
|
99
150
|
controller.releaseBudget(`load-${arrival.ordinal}`);
|
|
@@ -145,28 +196,56 @@ export async function runDecisionLoadHarness(options) {
|
|
|
145
196
|
signal.addEventListener('abort', aborted, { once: true });
|
|
146
197
|
}),
|
|
147
198
|
};
|
|
199
|
+
const advance = async (ms) => {
|
|
200
|
+
if (!options.signal) {
|
|
201
|
+
await clock.advance(ms);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const end = clock.now() + ms;
|
|
205
|
+
while (clock.now() < end && !options.signal.aborted)
|
|
206
|
+
await clock.advance(Math.min(1000, end - clock.now()));
|
|
207
|
+
};
|
|
148
208
|
const outcomes = [];
|
|
149
209
|
for (const arrival of arrivals) {
|
|
210
|
+
if (options.signal?.aborted)
|
|
211
|
+
break;
|
|
150
212
|
const due = start + arrival.atMs - clock.now();
|
|
151
213
|
if (due > 0)
|
|
152
|
-
await
|
|
214
|
+
await advance(due);
|
|
215
|
+
if (options.signal?.aborted)
|
|
216
|
+
break;
|
|
153
217
|
const controller = new AbortController();
|
|
154
218
|
const cancellation = { abortedAtMs: null };
|
|
219
|
+
let cancellationTimer;
|
|
155
220
|
if (arrival.cancelAtMs !== null) {
|
|
156
|
-
setTimeout(() => { cancellation.abortedAtMs = clock.now(); controller.abort(); }, arrival.cancelAtMs - arrival.atMs);
|
|
221
|
+
cancellationTimer = setTimeout(() => { cancellation.abortedAtMs = clock.now(); controller.abort(); }, arrival.cancelAtMs - arrival.atMs);
|
|
157
222
|
}
|
|
158
|
-
|
|
159
|
-
|
|
223
|
+
const combined = options.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal;
|
|
224
|
+
const pending = driver(arrival, combined, context)
|
|
225
|
+
.then(result => ({ arrival, result, abortedAtMs: cancellation.abortedAtMs }))
|
|
226
|
+
.finally(() => clearTimeout(cancellationTimer));
|
|
227
|
+
// Observe rejection immediately; allSettled below retains it for the caller.
|
|
228
|
+
void pending.catch(() => { });
|
|
229
|
+
outcomes.push(pending);
|
|
160
230
|
observe();
|
|
161
231
|
if (arrival.ordinal % 500 === 0)
|
|
162
232
|
sampleMemory();
|
|
163
233
|
}
|
|
164
234
|
let settled = false;
|
|
165
|
-
const all = Promise.
|
|
235
|
+
const all = Promise.allSettled(outcomes).then(values => { settled = true; return values; });
|
|
166
236
|
const drainStep = manifest.arrivalModel.serviceTimeMs.maximum + manifest.arrivalModel.retryBackoffMs;
|
|
167
237
|
while (!settled)
|
|
168
238
|
await clock.advance(drainStep);
|
|
169
|
-
const
|
|
239
|
+
const settledResults = await all;
|
|
240
|
+
const failure = settledResults.find(result => result.status === 'rejected');
|
|
241
|
+
if (failure?.status === 'rejected')
|
|
242
|
+
throw failure.reason;
|
|
243
|
+
const results = settledResults.map(result => result.value);
|
|
244
|
+
if (options.fullWindow && !options.signal?.aborted) {
|
|
245
|
+
const windowMs = (options.windowSeconds ?? manifest.duration.loadSeconds + manifest.duration.spikeSeconds + manifest.duration.soakSeconds) * 1000;
|
|
246
|
+
if (start + windowMs > clock.now())
|
|
247
|
+
await advance(start + windowMs - clock.now());
|
|
248
|
+
}
|
|
170
249
|
sampleMemory();
|
|
171
250
|
const threadUsage = process.threadCpuUsage(cpuStart);
|
|
172
251
|
const cpuMicros = threadUsage.user + threadUsage.system;
|
|
@@ -205,10 +284,10 @@ export async function runDecisionLoadHarness(options) {
|
|
|
205
284
|
const ratio = (value, total) => total ? Number((value / total).toFixed(6)) : 1;
|
|
206
285
|
return {
|
|
207
286
|
observations: {
|
|
208
|
-
arrivals:
|
|
287
|
+
arrivals: results.length, attempts, completed, failed, shed, cancelled,
|
|
209
288
|
shedReasons: Object.fromEntries(Object.entries(shedReasons).sort(([left], [right]) => left.localeCompare(right))),
|
|
210
289
|
maximumActiveCalls: maximumActive, maximumQueuedCalls: maximumQueued, maximumEligibleLaneWaitMs: laneWait,
|
|
211
|
-
retryAmplificationRatio: ratio(attempts,
|
|
290
|
+
retryAmplificationRatio: ratio(attempts, results.length), maximumCancellationLatencyMs: cancellationLatency,
|
|
212
291
|
quietPrincipalAdmissionRatio: ratio(admitted.quiet, submitted.quiet),
|
|
213
292
|
noisyPrincipalAdmissionRatio: ratio(admitted.noisy, submitted.noisy),
|
|
214
293
|
virtualDurationMs,
|
|
@@ -262,19 +341,16 @@ export function verifyDecisionLoadResultRecord(record, manifestDigest) {
|
|
|
262
341
|
return record.schema === 'decision-load-result/v1' && record.manifest.digest === manifestDigest
|
|
263
342
|
&& digest === decisionLoadManifestDigest(canonicalJson(body));
|
|
264
343
|
}
|
|
265
|
-
/**
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
*/
|
|
270
|
-
export function decisionLoadEvidenceFlags(records, manifestDigest) {
|
|
271
|
-
const bound = records.filter(record => verifyDecisionLoadResultRecord(record, manifestDigest));
|
|
344
|
+
/** Historical offline evidence stays separate from verified, exact-commit v3 G5 artifacts. */
|
|
345
|
+
export function decisionLoadEvidenceFlags(records, manifestDigest, sourceCommit) {
|
|
346
|
+
const legacy = records.filter((record) => 'schema' in record);
|
|
347
|
+
const bound = legacy.filter(record => verifyDecisionLoadResultRecord(record, manifestDigest));
|
|
272
348
|
const offline = bound.filter(record => record.mode === 'offline-fake-provider');
|
|
273
349
|
return {
|
|
274
|
-
'load-manifest-offline-passed': offline.length > 0 && offline.length ===
|
|
350
|
+
'load-manifest-offline-passed': offline.length > 0 && offline.length === legacy.filter(record => record.mode === 'offline-fake-provider').length
|
|
275
351
|
&& offline.every(record => record.passed),
|
|
276
|
-
'load-manifest-qualified':
|
|
277
|
-
&&
|
|
352
|
+
'load-manifest-qualified': records.length > 0 && records.every(record => 'schemaVersion' in record
|
|
353
|
+
&& record.manifestDigest === manifestDigest && verifyDecisionStagedLoadRecord(record, sourceCommit)),
|
|
278
354
|
};
|
|
279
355
|
}
|
|
280
356
|
//# sourceMappingURL=load.js.map
|
|
@@ -7,7 +7,8 @@ import { scanQualificationPrivacy } from './privacy.js';
|
|
|
7
7
|
/** Named master-test-plan suites plus the M01-M11 amendment IDs. */
|
|
8
8
|
export const QUALIFICATION_EVIDENCE_ID = /^(?:CON|POL|BCH|CTX|CNC|CAN|RTY|REC|SEC|PRV|CAL|DRF|CCP|M(?:0[1-9]|1[01]))-[A-Z0-9][A-Z0-9._-]*$/;
|
|
9
9
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
10
|
-
|
|
10
|
+
// Full staged-load receipt history and fixed-interval samples exceed 256 KiB.
|
|
11
|
+
const DEFAULT_MAX_ARTIFACT_BYTES = 1024 * 1024;
|
|
11
12
|
const DEFAULT_CONCURRENCY = 4;
|
|
12
13
|
function boundedInteger(value, fallback, minimum, maximum) {
|
|
13
14
|
if (value === undefined)
|
|
@@ -401,7 +402,9 @@ export async function evaluateExecutedQualification(manifest, artifactRoot, maxA
|
|
|
401
402
|
&& verification.every(item => item.verified && caseIds.has(item.caseId))
|
|
402
403
|
&& gateVerification.every(item => item.verified);
|
|
403
404
|
return { manifest, verification, gateVerification,
|
|
404
|
-
report: evaluateQualification(hardened, undefined, {
|
|
405
|
+
report: evaluateQualification(hardened, undefined, {
|
|
406
|
+
artifactsVerified, loadArtifactVerified: gateVerified.has('load-manifest-qualified'),
|
|
407
|
+
}) };
|
|
405
408
|
}
|
|
406
409
|
/** Executes, persists, verifies, and evaluates in one promotion-capable pipeline. */
|
|
407
410
|
export async function executeAndEvaluateQualification(plan) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assertReviewProjection, currentProposal, ReviewAccessError, ReviewConflictError, reviewDigest, reviewOperatorEventId } from './validate.js';
|
|
1
|
+
import { assertReviewProjection, currentProposal, ReviewAccessError, ReviewConflictError, reviewDigest, reviewOperatorEventId, validateReviewEvaluation } from './validate.js';
|
|
2
2
|
import { validateDecisionLifecyclePolicy } from '../lifecycle.js';
|
|
3
3
|
/** Only an executor that can attest zero external effect may report definitive failure. */
|
|
4
4
|
export class ReviewDefinitiveExecutionError extends Error {
|
|
@@ -233,7 +233,8 @@ export class DecisionReviewService {
|
|
|
233
233
|
return this.append(review, 'claimed', scope.actor, rationale, 'claimed');
|
|
234
234
|
}, true);
|
|
235
235
|
}
|
|
236
|
-
async decide(scope, id, decision, rationale) {
|
|
236
|
+
async decide(scope, id, decision, rationale, evaluation) {
|
|
237
|
+
const recordedEvaluation = evaluation === undefined ? {} : { evaluation: structuredClone(evaluation) };
|
|
237
238
|
return this.mutate(scope, id, 'decide', async (review) => {
|
|
238
239
|
this.requireActive(review);
|
|
239
240
|
const proposal = currentProposal(review);
|
|
@@ -243,10 +244,11 @@ export class DecisionReviewService {
|
|
|
243
244
|
throw new ReviewAccessError('Self-approval is denied');
|
|
244
245
|
if (review.decisions.some(item => item.reviewer.id === scope.actor.id && item.proposalVersion === proposal.version))
|
|
245
246
|
throw new ReviewConflictError('Reviewer already decided this proposal');
|
|
246
|
-
|
|
247
|
+
validateReviewEvaluation(recordedEvaluation.evaluation);
|
|
248
|
+
const decisions = [...review.decisions, { reviewer: scope.actor, proposalVersion: proposal.version, decision, rationale, atEpochMs: this.now(), ...recordedEvaluation }];
|
|
247
249
|
const approvals = decisions.filter(item => item.proposalVersion === proposal.version && item.decision === 'approve').length;
|
|
248
250
|
const status = decision === 'reject' ? 'rejected' : approvals >= review.quorum ? 'approved' : 'claimed';
|
|
249
|
-
return this.append({ ...review, decisions }, decision === 'approve' ? 'approved' : 'rejected', scope.actor, rationale, status, { quorumSatisfied: approvals >= review.quorum });
|
|
251
|
+
return this.append({ ...review, decisions }, decision === 'approve' ? 'approved' : 'rejected', scope.actor, rationale, status, { quorumSatisfied: approvals >= review.quorum, ...recordedEvaluation });
|
|
250
252
|
});
|
|
251
253
|
}
|
|
252
254
|
edit(scope, id, action, rationale, newResumeToken) {
|
|
@@ -15,6 +15,22 @@ export function reviewOperatorEventId(reviewId, sequence) {
|
|
|
15
15
|
const digestPattern = /^sha256:[a-f0-9]{64}$/;
|
|
16
16
|
const restrictedKey = /(?:password|credential|api.?key|secret|private.?reasoning|provider.?body|raw.?state|vault.?locator)/i;
|
|
17
17
|
const restrictedValue = /(?:vault:\/\/|\b(?:sk-(?:test-)?[a-z0-9_-]{12,}|ghp_[a-z0-9]{12,})\b)/i;
|
|
18
|
+
/** Optional review evidence remains strict when present, including imported records. */
|
|
19
|
+
export function validateReviewEvaluation(value) {
|
|
20
|
+
if (value === undefined)
|
|
21
|
+
return;
|
|
22
|
+
const object = (item) => typeof item === 'object' && item !== null && !Array.isArray(item);
|
|
23
|
+
const text = (item) => typeof item === 'string' && item.trim().length > 0 && item.length <= 8192;
|
|
24
|
+
const fields = ['evaluatorModel', 'evaluatorVendor', 'evaluatorFamily', 'acceptanceCriteriaRef', 'reReviewOf'];
|
|
25
|
+
if (!object(value) || Object.keys(value).some(key => key !== 'disagreements' && !fields.includes(key))
|
|
26
|
+
|| fields.some(key => value[key] !== undefined && !text(value[key])))
|
|
27
|
+
throw new ReviewIntegrityError('Invalid review evaluation');
|
|
28
|
+
if (value.disagreements !== undefined && (!Array.isArray(value.disagreements) || value.disagreements.some(item => !object(item) || Object.keys(item).some(key => !['claimRef', 'generatorPosition', 'evaluatorPosition', 'resolutionRef'].includes(key))
|
|
29
|
+
|| !text(item.claimRef) || !text(item.generatorPosition) || !text(item.evaluatorPosition)
|
|
30
|
+
|| (item.resolutionRef !== undefined && !text(item.resolutionRef)))))
|
|
31
|
+
throw new ReviewIntegrityError('Invalid review disagreements');
|
|
32
|
+
assertReviewProjection(value);
|
|
33
|
+
}
|
|
18
34
|
/** Enforce reference-only default review payloads; do not echo rejected material. */
|
|
19
35
|
export function assertReviewProjection(value) {
|
|
20
36
|
if (typeof value === 'string') {
|
|
@@ -67,7 +83,11 @@ export function validateReview(review) {
|
|
|
67
83
|
if (proposal.version !== index + 1 || proposal.actionDigest !== reviewDigest(proposal.action))
|
|
68
84
|
throw new ReviewIntegrityError('Invalid proposal lineage');
|
|
69
85
|
});
|
|
70
|
-
review.decisions.forEach(decision => {
|
|
86
|
+
review.decisions.forEach(decision => {
|
|
87
|
+
assertReviewProjection(decision.reviewer);
|
|
88
|
+
assertReviewProjection(decision.rationale);
|
|
89
|
+
validateReviewEvaluation(decision.evaluation);
|
|
90
|
+
});
|
|
71
91
|
review.events.forEach(event => { assertReviewProjection(event.actor); assertReviewProjection(event.rationale); });
|
|
72
92
|
if (review.effectReceipt)
|
|
73
93
|
assertReviewProjection(review.effectReceipt.result);
|
|
@@ -108,7 +128,8 @@ export function validateReview(review) {
|
|
|
108
128
|
throw new ReviewIntegrityError('Illegal decision');
|
|
109
129
|
const decision = review.decisions[decisionIndex++];
|
|
110
130
|
if (!decision || decision.proposalVersion !== version || decision.decision !== (event.type === 'approved' ? 'approve' : 'reject') ||
|
|
111
|
-
canonicalJson(decision.reviewer) !== canonicalJson(event.actor) || decision.rationale !== event.rationale || decision.atEpochMs !== event.atEpochMs
|
|
131
|
+
canonicalJson(decision.reviewer) !== canonicalJson(event.actor) || decision.rationale !== event.rationale || decision.atEpochMs !== event.atEpochMs ||
|
|
132
|
+
canonicalJson(decision.evaluation ?? null) !== canonicalJson(event.data?.evaluation ?? null)) {
|
|
112
133
|
throw new ReviewIntegrityError('Decision event mismatch');
|
|
113
134
|
}
|
|
114
135
|
if (event.type === 'rejected')
|
|
@@ -16,13 +16,18 @@ export function decisionSavingsWeights(ask) {
|
|
|
16
16
|
output_tokens: ask?.savings?.output_tokens ?? 128,
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
-
export function estimateDecisionSavings(inputTokens, answered, jevTokens, weights) {
|
|
19
|
+
export function estimateDecisionSavings(inputTokens, answered, jevTokens, weights, usage) {
|
|
20
20
|
const llmTokens = answered ? inputTokens + weights.reasoning_tokens + weights.output_tokens : 0;
|
|
21
|
+
const split = weights.jev_input_per_mtok !== undefined && weights.jev_output_per_mtok !== undefined
|
|
22
|
+
&& usage?.inputTokens != null && (usage.outputTokens != null || weights.jev_output_per_mtok === 0);
|
|
23
|
+
const jevCost = split
|
|
24
|
+
? (usage.inputTokens * weights.jev_input_per_mtok + (usage.outputTokens ?? 0) * weights.jev_output_per_mtok) / 1_000_000
|
|
25
|
+
: jevTokens * weights.jev_per_mtok / 1_000_000;
|
|
21
26
|
return {
|
|
22
27
|
llm_tokens_avoided: llmTokens,
|
|
23
28
|
jev_tokens: jevTokens,
|
|
24
|
-
cost_weighted_net_usd:
|
|
25
|
-
estimationMethod: { version: 'aiwg-decision-savings/v2', input_tokens: inputTokens, ...weights },
|
|
29
|
+
cost_weighted_net_usd: llmTokens * weights.llm_per_mtok / 1_000_000 - jevCost,
|
|
30
|
+
estimationMethod: { version: 'aiwg-decision-savings/v2', input_tokens: inputTokens, ...weights, source: weights.source ?? 'manual', jev_rate_basis: split ? 'split' : 'blended' },
|
|
26
31
|
};
|
|
27
32
|
}
|
|
28
33
|
//# sourceMappingURL=savings.js.map
|