@aiwg/cli 2026.9.21 → 2026.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agentic/code/providers/capability-matrix.yaml +2 -1
- package/dist/src/artifacts/cli.js +23 -18
- package/dist/src/artifacts/discovery-shadow-evaluator.js +177 -0
- package/dist/src/artifacts/discovery-shadow.js +195 -0
- package/dist/src/artifacts/fortemi-core-query-adapter.js +6 -2
- package/dist/src/artifacts/index-builder.js +47 -9
- package/dist/src/artifacts/query-engine.js +108 -5
- package/dist/src/artifacts/types.js +1 -0
- package/dist/src/cli/handlers/decision.js +88 -0
- package/dist/src/cli/handlers/gates.js +154 -0
- package/dist/src/cli/handlers/index.js +5 -1
- package/dist/src/cli/handlers/sessions.js +10 -7
- package/dist/src/cli/handlers/utilities.js +20 -0
- package/dist/src/config/aiwg-config.js +15 -2
- package/dist/src/decision/acceptance.js +25 -0
- package/dist/src/decision/adapters/jev.js +24 -2
- package/dist/src/decision/calibration/registry.js +9 -0
- package/dist/src/decision/compose.js +74 -15
- package/dist/src/decision/context-live-promotion.js +344 -0
- package/dist/src/decision/context-live-qualification.js +591 -0
- package/dist/src/decision/context-pruning.js +847 -0
- package/dist/src/decision/driver.js +430 -0
- package/dist/src/decision/egress-live-qualification.js +874 -0
- package/dist/src/decision/ensemble/contract.js +64 -1
- package/dist/src/decision/ensemble/index.js +1 -0
- package/dist/src/decision/ensemble/report.js +8 -42
- package/dist/src/decision/ensemble/runtime.js +571 -0
- package/dist/src/decision/ensemble-study/artifacts.js +85 -0
- package/dist/src/decision/ensemble-study/calibration.js +443 -0
- package/dist/src/decision/ensemble-study/corpus.js +229 -0
- package/dist/src/decision/ensemble-study/multifact-artifacts.js +23 -0
- package/dist/src/decision/ensemble-study/multifact-study.js +596 -0
- package/dist/src/decision/ensemble-study/multifact.js +241 -0
- package/dist/src/decision/ensemble-study/protocol.js +77 -0
- package/dist/src/decision/ensemble-study/score.js +462 -0
- package/dist/src/decision/ensemble-study/staged.js +87 -0
- package/dist/src/decision/ensemble-study/statistics.js +84 -0
- package/dist/src/decision/evaluate.js +227 -14
- package/dist/src/decision/export.js +4 -0
- package/dist/src/decision/feature-export.js +1074 -0
- package/dist/src/decision/graph-index.js +16 -0
- package/dist/src/decision/graph-live-qualification.js +1041 -0
- package/dist/src/decision/graph-live-workload.js +245 -0
- package/dist/src/decision/graph-skill-bridge.js +21 -3
- package/dist/src/decision/heldout/calibration.js +140 -0
- package/dist/src/decision/heldout/collector.js +430 -0
- package/dist/src/decision/heldout/contract.js +309 -0
- package/dist/src/decision/heldout/d29-generator-ids.js +12 -0
- package/dist/src/decision/heldout/d29-passage-baseline-v2.js +93 -0
- package/dist/src/decision/heldout/d29-passage-baseline-v3.js +100 -0
- package/dist/src/decision/heldout/d29-passage-baseline.js +66 -0
- package/dist/src/decision/heldout/d29-pools-v8.js +575 -0
- package/dist/src/decision/heldout/d29-pools.js +288 -0
- package/dist/src/decision/heldout/d29-v6.js +169 -0
- package/dist/src/decision/heldout/d29-v7.js +202 -0
- package/dist/src/decision/heldout/d29-v8.js +586 -0
- package/dist/src/decision/heldout/generator-registry.js +67 -0
- package/dist/src/decision/heldout/generators.js +696 -0
- package/dist/src/decision/heldout/index.js +8 -0
- package/dist/src/decision/heldout/journal.js +346 -0
- package/dist/src/decision/heldout/study-generators.js +64 -0
- package/dist/src/decision/heldout/types.js +2 -0
- package/dist/src/decision/host-policy.js +61 -0
- package/dist/src/decision/index.js +11 -0
- package/dist/src/decision/interop-profile.v1.json +112 -0
- package/dist/src/decision/interop.js +653 -0
- package/dist/src/decision/issue-triage/index.js +3 -0
- package/dist/src/decision/issue-triage/runtime.js +1069 -0
- package/dist/src/decision/issue-triage/types.js +2 -0
- package/dist/src/decision/patterns/catalog.js +28 -8
- package/dist/src/decision/patterns/playground.js +28 -11
- package/dist/src/decision/patterns/specs.js +19 -10
- package/dist/src/decision/preprocessed-evidence.js +724 -0
- package/dist/src/decision/qualification/capture.js +8 -2
- package/dist/src/decision/qualification/gate-evidence.js +19 -4
- package/dist/src/decision/qualification/load.js +8 -1
- package/dist/src/decision/qualification/quality.js +57 -49
- package/dist/src/decision/qualification/release.js +76 -3
- package/dist/src/decision/qualification/runner.js +5 -2
- package/dist/src/decision/routing/contract.js +175 -0
- package/dist/src/decision/routing/index.js +5 -0
- package/dist/src/decision/routing/report.js +216 -0
- package/dist/src/decision/routing/runtime.js +685 -0
- package/dist/src/decision/routing/types.js +2 -0
- package/dist/src/decision/sdlc-screening.js +1157 -0
- package/dist/src/decision/sensitivity/comparative.js +154 -0
- package/dist/src/decision/sensitivity/contract.js +218 -0
- package/dist/src/decision/sensitivity/index.js +5 -0
- package/dist/src/decision/sensitivity/runtime.js +912 -0
- package/dist/src/decision/sensitivity/types.js +2 -0
- package/dist/src/decision/validate.js +26 -0
- package/dist/src/extensions/commands/definitions.js +38 -0
- package/dist/src/extensions/manifest.js +44 -0
- package/dist/src/gates/discovery.js +315 -0
- package/dist/src/gates/driver.js +388 -0
- package/dist/src/gates/evaluate.js +719 -0
- package/dist/src/gates/floors.js +255 -0
- package/dist/src/gates/index.js +17 -0
- package/dist/src/gates/providers/evidence.js +38 -0
- package/dist/src/gates/providers/index.js +21 -0
- package/dist/src/gates/providers/isolated-child-source.js +446 -0
- package/dist/src/gates/providers/loader.js +1069 -0
- package/dist/src/gates/providers/paired.js +52 -0
- package/dist/src/gates/providers/proportion.js +60 -0
- package/dist/src/gates/providers/registry.js +40 -0
- package/dist/src/gates/providers/scalar.js +41 -0
- package/dist/src/gates/providers/screening.js +53 -0
- package/dist/src/gates/providers/types.js +25 -0
- package/dist/src/gates/registry.js +1003 -0
- package/dist/src/gates/report.js +102 -0
- package/dist/src/gates/schema.js +56 -0
- package/dist/src/gates/stats/binomial.js +26 -0
- package/dist/src/gates/stats/bootstrap.js +62 -0
- package/dist/src/gates/stats/clopper-pearson.js +95 -0
- package/dist/src/gates/stats/digest.js +26 -0
- package/dist/src/gates/stats/error.js +5 -0
- package/dist/src/gates/stats/index.js +9 -0
- package/dist/src/gates/stats/normal.js +35 -0
- package/dist/src/gates/stats/paired.js +120 -0
- package/dist/src/gates/stats/splits.js +30 -0
- package/dist/src/gates/types.js +8 -0
- package/dist/src/governance/redaction.js +14 -4
- package/dist/src/mcp/muse-native-config.mjs +123 -0
- package/dist/src/mcp/tools/decision.mjs +188 -0
- package/dist/src/mcp/tools/subsystems.mjs +2 -0
- package/dist/src/providers/capability-matrix.yaml +2 -1
- package/dist/src/providers/provider-definitions.js +2 -1
- package/dist/src/sessions/adapters/muse.js +336 -39
- package/dist/src/sessions/batch-import.js +7 -0
- package/dist/src/sessions/workspace-discovery.js +13 -2
- package/package.json +1 -1
- package/schemas/decision/ConformalFrozenOpenData.v2.schema.json +371 -0
- package/schemas/decision/ConformalOpenDataReport.v2.schema.json +421 -0
- package/schemas/decision/ConformalPreregistration.v2.schema.json +529 -0
- package/schemas/decision/ContextPruningCandidate.v1.schema.json +47 -0
- package/schemas/decision/ContextPruningEvaluationReport.v1.schema.json +758 -0
- package/schemas/decision/ContextPruningPreregistration.v1.schema.json +175 -0
- package/schemas/decision/ContextPruningReceipt.v1.schema.json +72 -0
- package/schemas/decision/D17Multifact.v1.schema.json +1851 -0
- package/schemas/decision/D17StudyAnalysis.v1.schema.json +42 -0
- package/schemas/decision/D17StudyAnalysis.v2.schema.json +51 -0
- package/schemas/decision/D17StudyCalibration.v1.schema.json +819 -0
- package/schemas/decision/D17StudyDryRun.v1.schema.json +169 -0
- package/schemas/decision/D17StudyDryRun.v2.schema.json +239 -0
- package/schemas/decision/D17StudyGold.v1.schema.json +108 -0
- package/schemas/decision/D17StudyGuide.v1.schema.json +63 -0
- package/schemas/decision/D17StudyNativeTemplates.v1.schema.json +619 -0
- package/schemas/decision/D17StudyProtocol.v1.schema.json +241 -0
- package/schemas/decision/D17StudyReport.v1.schema.json +902 -0
- package/schemas/decision/D17StudyReport.v2.schema.json +1319 -0
- package/schemas/decision/D17StudyReview.v1.schema.json +175 -0
- package/schemas/decision/D17StudySplits.v1.schema.json +217 -0
- package/schemas/decision/D29Study.v1.schema.json +1903 -0
- package/schemas/decision/D29Study.v2.schema.json +1344 -0
- package/schemas/decision/D29Study.v3.schema.json +609 -0
- package/schemas/decision/D29Study.v4.schema.json +1133 -0
- package/schemas/decision/D29Study.v6.schema.json +1205 -0
- package/schemas/decision/D29Study.v7.schema.json +1471 -0
- package/schemas/decision/D29Study.v8.schema.json +671 -0
- package/schemas/decision/D29Study.v9.schema.json +778 -0
- package/schemas/decision/DecisionComparativeReplayAuditSample.v1.schema.json +137 -0
- package/schemas/decision/DecisionComparativeReplayCorpus.v1.schema.json +258 -0
- package/schemas/decision/DecisionComparativeReplayFreeze.v1.schema.json +74 -0
- package/schemas/decision/DecisionComparativeReplayGold.v1.schema.json +50 -0
- package/schemas/decision/DecisionComparativeReplayGoldAsset.v1.schema.json +37 -0
- package/schemas/decision/DecisionComparativeReplayIntegrity.v1.schema.json +81 -0
- package/schemas/decision/DecisionComparativeReplayMembers.v1.schema.json +52 -0
- package/schemas/decision/DecisionComparativeReplayPreregistration.v1.schema.json +113 -0
- package/schemas/decision/DecisionComparativeReplayReport.v1.schema.json +407 -0
- package/schemas/decision/DecisionComparativeReplayReviewPackets.v1.schema.json +260 -0
- package/schemas/decision/DecisionComparativeReplaySplit.v1.schema.json +84 -0
- package/schemas/decision/DecisionFeatureObservation.v1.schema.json +564 -0
- package/schemas/decision/DecisionFeatureSet.v1.schema.json +155 -0
- package/schemas/decision/DecisionInteropMapping.v1.schema.json +85 -0
- package/schemas/decision/DecisionIssueTriageEvaluationManifest.v1.schema.json +174 -0
- package/schemas/decision/DecisionIssueTriageEvaluationReport.v1.schema.json +280 -0
- package/schemas/decision/DecisionIssueTriagePilotPack.v1.schema.json +114 -0
- package/schemas/decision/DecisionRouteReceipt.v1.schema.json +155 -0
- package/schemas/decision/DecisionRoutingPolicy.v1.schema.json +132 -0
- package/schemas/decision/DecisionRoutingShadowReport.v1.schema.json +170 -0
- package/schemas/decision/DecisionRoutingTask.v1.schema.json +49 -0
- package/schemas/decision/DecisionRuleset.schema.json +8 -2
- package/schemas/decision/DecisionRuleset.v1alpha2.schema.json +8 -2
- package/schemas/decision/DecisionSensitivityPlan.v1.schema.json +191 -0
- package/schemas/decision/DecisionSensitivityReport.v1.schema.json +163 -0
- package/schemas/decision/HeldoutApproval.v1.schema.json +312 -0
- package/schemas/decision/HeldoutAttempt.v1.schema.json +211 -0
- package/schemas/decision/HeldoutBaseline.v1.schema.json +90 -0
- package/schemas/decision/HeldoutCalibrationPhase.v1.schema.json +87 -0
- package/schemas/decision/HeldoutCorpus.v1.schema.json +167 -0
- package/schemas/decision/HeldoutEvent.v1.schema.json +41 -0
- package/schemas/decision/HeldoutFrozen.v1.schema.json +142 -0
- package/schemas/decision/HeldoutPreregistration.v1.schema.json +222 -0
- package/schemas/decision/HeldoutSpendEvent.v1.schema.json +122 -0
- package/schemas/decision/HeldoutSpendHead.v1.schema.json +25 -0
- package/schemas/decision/HeldoutSpendHead.v2.schema.json +46 -0
- package/schemas/decision/HeldoutSummary.v1.schema.json +101 -0
- package/schemas/decision/OpaDecisionLogExport.v1.schema.json +65 -0
- package/schemas/decision/PreprocessedEvidence.v1.schema.json +306 -0
- package/schemas/decision/RulesetResult.v1alpha2.schema.json +175 -0
- package/schemas/decision/SdlcEvidenceScreening.v1.schema.json +499 -0
- package/schemas/decision/SdlcScreeningPreregistration.v1.schema.json +132 -0
- package/schemas/decision/SdlcScreeningPreregistration.v2.schema.json +138 -0
- package/schemas/decision/SdlcScreeningRelease.v1.schema.json +654 -0
- package/schemas/decision/SdlcScreeningRelease.v2.schema.json +654 -0
- package/tools/agents/deploy-agents.mjs +1 -1
- package/tools/agents/providers/base.mjs +26 -7
- package/tools/agents/providers/factory.mjs +10 -2
- package/tools/agents/providers/muse-hooks.mjs +1 -29
- package/tools/agents/providers/muse.mjs +6 -3
|
@@ -949,8 +949,12 @@ export async function discoverCapability(cwd, params) {
|
|
|
949
949
|
continue;
|
|
950
950
|
}
|
|
951
951
|
}
|
|
952
|
-
if (loaded.reason)
|
|
952
|
+
if (loaded.reason) {
|
|
953
953
|
unavailableReason ??= loaded.reason;
|
|
954
|
+
if (graph === 'framework' && !params.graph) {
|
|
955
|
+
console.error(`Warning: framework capabilities are unavailable: ${loaded.reason}`);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
954
958
|
entries.push(...loaded.entries.map((entry) => withIndexProvenance(entry, graph)));
|
|
955
959
|
const discovered = await queryFortemiCoreAiwgDiscovery(cwd, {
|
|
956
960
|
graph,
|
|
@@ -1138,6 +1142,19 @@ export async function discoverCapability(cwd, params) {
|
|
|
1138
1142
|
}
|
|
1139
1143
|
const scored = dedupeDiscoverResults(await applyFacetFusion(Array.from(combinedByPath.values()).sort(compareDiscoverResults), candidates, params.phrase)).slice(0, limit);
|
|
1140
1144
|
const relaxed = scored.some(result => !strictPaths.has(result.entry.path));
|
|
1145
|
+
if (params.shadowRoute) {
|
|
1146
|
+
try {
|
|
1147
|
+
await params.shadowRoute.observe(params.phrase, scored.map(result => ({
|
|
1148
|
+
id: discoveryIdForEntry(result.entry), name: result.entry.name ?? result.entry.title,
|
|
1149
|
+
type: result.entry.type, capability: result.entry.capability ?? result.entry.summary,
|
|
1150
|
+
score: result.score,
|
|
1151
|
+
})));
|
|
1152
|
+
}
|
|
1153
|
+
catch {
|
|
1154
|
+
// An optional observation failure must never replace deterministic discovery.
|
|
1155
|
+
params.shadowRoute.disable();
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1141
1158
|
const queryTimeMs = Date.now() - startTime;
|
|
1142
1159
|
/**
|
|
1143
1160
|
* Resolve a stored framework-graph path to an absolute AIWG_ROOT
|
|
@@ -1171,7 +1188,7 @@ export async function discoverCapability(cwd, params) {
|
|
|
1171
1188
|
// broader phrase / type filter, and a capability refresh via `aiwg use`.
|
|
1172
1189
|
const emptyResultHint = scored.length === 0
|
|
1173
1190
|
? backend === 'fortemi-core'
|
|
1174
|
-
? `No capability matched "${params.phrase}" among ${entries.length} Fortemi Core static-cache capabilities. Try a broader phrase or a \`--type\` filter. If the local index changed, refresh the cache with \`aiwg index sync\`, or pass \`--backend local\` to use the legacy local index.`
|
|
1191
|
+
? `No capability matched "${params.phrase}" among ${entries.length} Fortemi Core static-cache capabilities. Try a broader phrase or a \`--type\` filter. If the local index changed, refresh the cache with \`aiwg index sync ${params.graph ? `--graph ${params.graph}` : '--all'}\`, or pass \`--backend local\` to use the legacy local index.`
|
|
1175
1192
|
: `No capability matched "${params.phrase}" among ${entries.length} indexed capabilities. Try a broader phrase or a \`--type\` filter. If you just installed or authored capabilities, refresh discovery with \`aiwg use <framework>\` (or \`aiwg index build\`).`
|
|
1176
1193
|
: null;
|
|
1177
1194
|
const includePaths = params.includePaths ?? true;
|
|
@@ -1272,7 +1289,9 @@ export async function discoverCapability(cwd, params) {
|
|
|
1272
1289
|
}
|
|
1273
1290
|
if (scored.length === 0) {
|
|
1274
1291
|
console.log(`No discovery matches for "${params.phrase}" in types: ${types.join(',')}.`);
|
|
1275
|
-
console.log(
|
|
1292
|
+
console.log(backend === 'fortemi-core'
|
|
1293
|
+
? emptyResultHint
|
|
1294
|
+
: 'Try a broader phrase or a `--type` filter. If capabilities were just added, refresh with `aiwg use <framework>` (or `aiwg index build`).');
|
|
1276
1295
|
return;
|
|
1277
1296
|
}
|
|
1278
1297
|
const relaxedNote = relaxed ? ' — relaxed match (verbose query)' : '';
|
|
@@ -1410,8 +1429,12 @@ async function loadShowEntries(cwd, params) {
|
|
|
1410
1429
|
continue;
|
|
1411
1430
|
}
|
|
1412
1431
|
}
|
|
1413
|
-
if (loaded.reason)
|
|
1432
|
+
if (loaded.reason) {
|
|
1414
1433
|
unavailableReason ??= loaded.reason;
|
|
1434
|
+
if (graph === 'framework' && !params.graph) {
|
|
1435
|
+
console.error(`Warning: framework capabilities are unavailable: ${loaded.reason}`);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1415
1438
|
entries.push(...loaded.entries.map((entry) => withIndexProvenance(entry, graph)));
|
|
1416
1439
|
}
|
|
1417
1440
|
if (entries.length === 0 && unavailableReason) {
|
|
@@ -1464,7 +1487,15 @@ function findShowMatches(entries, types, needle) {
|
|
|
1464
1487
|
const slugLayoutMatch = ((basename === 'SKILL.md' && e.type === 'skill') ||
|
|
1465
1488
|
(basename === 'BEHAVIOR.md' && e.type === 'behavior')) &&
|
|
1466
1489
|
dirStem === needle;
|
|
1467
|
-
|
|
1490
|
+
if (slugLayoutMatch || fileStem === needle || e.name === needle)
|
|
1491
|
+
return true;
|
|
1492
|
+
if (e.type === 'gate-pack' && typeof e.name === 'string') {
|
|
1493
|
+
const gateStem = fileStem.replace(/\.gatepack$/i, '');
|
|
1494
|
+
const rest = e.name.includes(':') ? e.name.slice(e.name.indexOf(':') + 1) : e.name;
|
|
1495
|
+
const short = rest.includes('/') ? rest.slice(rest.indexOf('/') + 1) : rest;
|
|
1496
|
+
return gateStem === needle || rest === needle || short === needle;
|
|
1497
|
+
}
|
|
1498
|
+
return false;
|
|
1468
1499
|
});
|
|
1469
1500
|
}
|
|
1470
1501
|
if (matches.length === 0) {
|
|
@@ -1516,6 +1547,68 @@ async function fortemiRecordForEntry(cwd, entry, sourcePaths) {
|
|
|
1516
1547
|
const id = discoveryIdForEntry(entry);
|
|
1517
1548
|
return loaded.exported.items.find((record) => record.id === id || record.source.path === entry.path) ?? null;
|
|
1518
1549
|
}
|
|
1550
|
+
/**
|
|
1551
|
+
* Scan bundle `gate-packs/` directories for a pack matching `needle` (#2830).
|
|
1552
|
+
*
|
|
1553
|
+
* Accepts the full namespaced id, the rest-path or the short pack name and
|
|
1554
|
+
* probes `<bundle>/gate-packs/<pack>.gatepack.{yaml,yml,json}`. Never looks
|
|
1555
|
+
* under `gates/`, which agent-persistence HITL owns.
|
|
1556
|
+
*/
|
|
1557
|
+
async function findGatePackInCorpus(groups, needle) {
|
|
1558
|
+
const path = await import('node:path');
|
|
1559
|
+
const fsp = (await import('node:fs')).promises;
|
|
1560
|
+
const trimmed = needle.trim();
|
|
1561
|
+
const rest = trimmed.includes(':') ? trimmed.slice(trimmed.indexOf(':') + 1) : trimmed;
|
|
1562
|
+
const slash = rest.indexOf('/');
|
|
1563
|
+
const wantedBundle = slash >= 0 ? rest.slice(0, slash) : null;
|
|
1564
|
+
const wantedPack = slash >= 0 ? rest.slice(slash + 1) : rest;
|
|
1565
|
+
if (!wantedPack || /\s/.test(wantedPack) || wantedPack.includes(':') || wantedPack.includes('/'))
|
|
1566
|
+
return null;
|
|
1567
|
+
const extensions = ['.gatepack.yaml', '.gatepack.yml', '.gatepack.json'];
|
|
1568
|
+
const ordered = wantedBundle
|
|
1569
|
+
? groups.flatMap(group => [{ group, bundle: wantedBundle }])
|
|
1570
|
+
: null;
|
|
1571
|
+
const probe = async (group, bundle) => {
|
|
1572
|
+
for (const extension of extensions) {
|
|
1573
|
+
const candidate = path.join(group.dir, bundle, 'gate-packs', `${wantedPack}${extension}`);
|
|
1574
|
+
try {
|
|
1575
|
+
const stat = await fsp.stat(candidate);
|
|
1576
|
+
if (stat.isFile())
|
|
1577
|
+
return { path: candidate, bundleKind: group.kind, bundleId: bundle };
|
|
1578
|
+
}
|
|
1579
|
+
catch {
|
|
1580
|
+
// not present — continue
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return null;
|
|
1584
|
+
};
|
|
1585
|
+
if (ordered) {
|
|
1586
|
+
for (const { group, bundle } of ordered) {
|
|
1587
|
+
const found = await probe(group, bundle);
|
|
1588
|
+
if (found)
|
|
1589
|
+
return found;
|
|
1590
|
+
}
|
|
1591
|
+
return null;
|
|
1592
|
+
}
|
|
1593
|
+
for (const group of groups) {
|
|
1594
|
+
let bundles;
|
|
1595
|
+
try {
|
|
1596
|
+
bundles = (await fsp.readdir(group.dir, { withFileTypes: true }))
|
|
1597
|
+
.filter(d => d.isDirectory())
|
|
1598
|
+
.map(d => d.name)
|
|
1599
|
+
.sort();
|
|
1600
|
+
}
|
|
1601
|
+
catch {
|
|
1602
|
+
continue;
|
|
1603
|
+
}
|
|
1604
|
+
for (const bundle of bundles) {
|
|
1605
|
+
const found = await probe(group, bundle);
|
|
1606
|
+
if (found)
|
|
1607
|
+
return found;
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
return null;
|
|
1611
|
+
}
|
|
1519
1612
|
/**
|
|
1520
1613
|
* Scan the AIWG_ROOT corpus for an artifact matching `name` (#1221).
|
|
1521
1614
|
*
|
|
@@ -1582,6 +1675,16 @@ async function findCorpusArtifact(aiwgRoot, name, typeFilter) {
|
|
|
1582
1675
|
}
|
|
1583
1676
|
}
|
|
1584
1677
|
}
|
|
1678
|
+
// Gate packs live in `<bundle>/gate-packs/*.gatepack.yaml|json` (never
|
|
1679
|
+
// `gates/`, which agent-persistence HITL uses). The needle may be the full
|
|
1680
|
+
// namespaced id (`aiwg:decision-engine/integrity-ceiling`), the rest-path
|
|
1681
|
+
// (`decision-engine/integrity-ceiling`) or the short pack name
|
|
1682
|
+
// (`integrity-ceiling`). (#2830)
|
|
1683
|
+
if (typeFilter.length === 0 || typeFilter.includes('gate-pack')) {
|
|
1684
|
+
const gateMatch = await findGatePackInCorpus(groups, name);
|
|
1685
|
+
if (gateMatch)
|
|
1686
|
+
return { ...gateMatch, type: 'gate-pack' };
|
|
1687
|
+
}
|
|
1585
1688
|
// Top-level agents live at `agentic/code/agents/<category>/<name>.md`
|
|
1586
1689
|
// (e.g. `personas/aiwg-writer.md`) — a flat-under-category layout the
|
|
1587
1690
|
// bundle groups above do not cover. Scan it directly so persona/agent
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { decisionCapabilities, evaluateRequestPath, listPatterns, livePlan, materializeSyntheticClassificationSetup, runOfflinePattern, showPattern, syntheticClassificationSetup, validateDecisionInput, } from '../../decision/driver.js';
|
|
2
|
+
function jsonResult(value, exitCode = 0) {
|
|
3
|
+
return { exitCode, message: JSON.stringify(value, null, 2), rawOutput: true };
|
|
4
|
+
}
|
|
5
|
+
function usage() {
|
|
6
|
+
return [
|
|
7
|
+
'Usage: aiwg decision <capabilities|status|patterns|validate|evaluate|setup> [options]',
|
|
8
|
+
'',
|
|
9
|
+
'Commands:',
|
|
10
|
+
' capabilities|status Show offline readiness, primitives, config and feature availability',
|
|
11
|
+
' patterns list List governed decision pattern packs',
|
|
12
|
+
' patterns show <id> Show one pattern pack and schemas',
|
|
13
|
+
' patterns offline-run <id> [fixture] Run a recorded offline fixture through the decision runtime',
|
|
14
|
+
' patterns live-plan <id> [--opt-in] [--credential-resolved] [--egress-approved]',
|
|
15
|
+
' validate <request|definition|ruleset|binding> <path>',
|
|
16
|
+
' evaluate --request <path> [--host-policy-module <path>]',
|
|
17
|
+
' setup synthetic-classification [--output-dir <dir>]',
|
|
18
|
+
].join('\n');
|
|
19
|
+
}
|
|
20
|
+
function takeOption(args, name) {
|
|
21
|
+
const index = args.indexOf(name);
|
|
22
|
+
if (index < 0)
|
|
23
|
+
return undefined;
|
|
24
|
+
return args[index + 1];
|
|
25
|
+
}
|
|
26
|
+
function patternId(value) {
|
|
27
|
+
if (!value)
|
|
28
|
+
throw new Error('Pattern id is required');
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
async function executeDecision(ctx) {
|
|
32
|
+
const [command, subcommand, ...rest] = ctx.args;
|
|
33
|
+
const options = { cwd: ctx.cwd, frameworkRoot: ctx.frameworkRoot, env: process.env };
|
|
34
|
+
try {
|
|
35
|
+
if (!command || command === '--help' || command === '-h')
|
|
36
|
+
return { exitCode: 0, message: usage(), rawOutput: true };
|
|
37
|
+
if (command === 'capabilities' || command === 'status')
|
|
38
|
+
return jsonResult(decisionCapabilities(options));
|
|
39
|
+
if (command === 'patterns') {
|
|
40
|
+
if (subcommand === 'list')
|
|
41
|
+
return jsonResult(listPatterns());
|
|
42
|
+
if (subcommand === 'show')
|
|
43
|
+
return jsonResult(showPattern(patternId(rest[0])));
|
|
44
|
+
if (subcommand === 'offline-run')
|
|
45
|
+
return jsonResult(await runOfflinePattern(patternId(rest[0]), rest[1]));
|
|
46
|
+
if (subcommand === 'live-plan')
|
|
47
|
+
return jsonResult(livePlan(patternId(rest[0]), {
|
|
48
|
+
explicitOptIn: rest.includes('--opt-in'),
|
|
49
|
+
credentialResolved: rest.includes('--credential-resolved'),
|
|
50
|
+
egressApproved: rest.includes('--egress-approved'),
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
if (command === 'validate') {
|
|
54
|
+
const target = subcommand;
|
|
55
|
+
const result = await validateDecisionInput(target, rest[0] ?? '', options);
|
|
56
|
+
return jsonResult(result, result.valid ? 0 : 2);
|
|
57
|
+
}
|
|
58
|
+
if (command === 'evaluate') {
|
|
59
|
+
const request = takeOption(ctx.args, '--request');
|
|
60
|
+
if (!request)
|
|
61
|
+
return { exitCode: 2, message: 'decision evaluate requires --request <path>' };
|
|
62
|
+
const result = await evaluateRequestPath(request, options, {
|
|
63
|
+
hostPolicyModulePath: takeOption(ctx.args, '--host-policy-module'),
|
|
64
|
+
});
|
|
65
|
+
return jsonResult(result, result.exitCode);
|
|
66
|
+
}
|
|
67
|
+
if (command === 'setup' && subcommand === 'synthetic-classification') {
|
|
68
|
+
const outputDir = takeOption(ctx.args, '--output-dir');
|
|
69
|
+
if (outputDir)
|
|
70
|
+
return jsonResult(await materializeSyntheticClassificationSetup(outputDir, {}, options));
|
|
71
|
+
return jsonResult(syntheticClassificationSetup({}, options));
|
|
72
|
+
}
|
|
73
|
+
return { exitCode: 2, message: usage(), rawOutput: true };
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
return { exitCode: 1, message: error instanceof Error ? error.message : String(error) };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export const decisionHandler = {
|
|
80
|
+
id: 'decision',
|
|
81
|
+
name: 'Decision Driver',
|
|
82
|
+
description: 'Inspect, validate and run governed decision classification workflows',
|
|
83
|
+
category: 'utility',
|
|
84
|
+
aliases: [],
|
|
85
|
+
help: async () => ({ exitCode: 0, message: usage(), rawOutput: true }),
|
|
86
|
+
execute: executeDecision,
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=decision.js.map
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
function jsonResult(value, exitCode = 0) {
|
|
2
|
+
return { exitCode, message: JSON.stringify(value, null, 2), rawOutput: true };
|
|
3
|
+
}
|
|
4
|
+
function usage() {
|
|
5
|
+
return [
|
|
6
|
+
'Usage: aiwg gates <validate|evaluate|show|list> [options]',
|
|
7
|
+
'',
|
|
8
|
+
'Commands:',
|
|
9
|
+
' validate <pack|binding|report> <path> [--pack-dir <dir>] [--aiwg-root <dir>]',
|
|
10
|
+
' evaluate --binding <file> --metrics <file> --holdout <file> [--upstream <file>] --now <iso> --trusted-binding-digest <sha256> [--pack-dir <dir>] [--aiwg-root <dir>]',
|
|
11
|
+
' show <id> [--pack-dir <dir>] [--aiwg-root <dir>]',
|
|
12
|
+
' list [--namespace <ns>] [--rule [<rule-id>]] [--pack-dir <dir>] [--aiwg-root <dir>]',
|
|
13
|
+
'',
|
|
14
|
+
'Packs live in <bundle>/gate-packs/*.gatepack.yaml|json and register as',
|
|
15
|
+
'aiwg:<bundle>/<name> (shipped).',
|
|
16
|
+
'Single files and bundle directories passed via --pack-dir are always',
|
|
17
|
+
'project: packs; aiwg: is reserved for the installed tree, and a --pack-dir',
|
|
18
|
+
'manifest claiming a shipped or installed bundle id refuses. An --aiwg-root',
|
|
19
|
+
'override is untrusted:',
|
|
20
|
+
'list/show/validate still inspect it, but evaluate refuses it.',
|
|
21
|
+
'Evaluation is pure and offline: pass --now <iso> for the fake clock.',
|
|
22
|
+
'The holdout and upstream files must already carry their sealed digests,',
|
|
23
|
+
'and --upstream is required whenever the binding observes an',
|
|
24
|
+
'upstream-ceiling gate. Project floors load from .aiwg/aiwg.config in the',
|
|
25
|
+
'cwd (unreadable or invalid config refuses evaluation). Reports printed',
|
|
26
|
+
"here carry attestation: 'offline-cli'.",
|
|
27
|
+
].join('\n');
|
|
28
|
+
}
|
|
29
|
+
function takeOption(args, name) {
|
|
30
|
+
const index = args.indexOf(name);
|
|
31
|
+
if (index < 0)
|
|
32
|
+
return undefined;
|
|
33
|
+
return args[index + 1];
|
|
34
|
+
}
|
|
35
|
+
function takeAllOptions(args, name) {
|
|
36
|
+
const values = [];
|
|
37
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
38
|
+
if (args[index] === name && index + 1 < args.length)
|
|
39
|
+
values.push(args[index + 1]);
|
|
40
|
+
}
|
|
41
|
+
return values;
|
|
42
|
+
}
|
|
43
|
+
function driverOptions(ctx) {
|
|
44
|
+
// The shipped root resolves from the installed framework location, never
|
|
45
|
+
// from the cwd: any checkout could otherwise impersonate the aiwg:
|
|
46
|
+
// namespace. An explicit --aiwg-root is kept for inspection only; packs
|
|
47
|
+
// loaded from it are marked untrusted and refused by evaluate.
|
|
48
|
+
const aiwgRoot = takeOption(ctx.args, '--aiwg-root') ?? ctx.frameworkRoot;
|
|
49
|
+
const packDirs = takeAllOptions(ctx.args, '--pack-dir');
|
|
50
|
+
return { cwd: ctx.cwd, aiwgRoot, ...(packDirs.length ? { packDirs } : {}) };
|
|
51
|
+
}
|
|
52
|
+
/** Positional args with each known value-flag and its value skipped in order. */
|
|
53
|
+
function positionals(args, skipCommand) {
|
|
54
|
+
const valueFlags = new Set(['--pack-dir', '--aiwg-root', '--binding', '--metrics', '--holdout', '--upstream', '--now', '--namespace', '--rule', '--trusted-binding-digest']);
|
|
55
|
+
const found = [];
|
|
56
|
+
let skipNext = false;
|
|
57
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
58
|
+
const arg = args[index];
|
|
59
|
+
if (skipNext) {
|
|
60
|
+
skipNext = false;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (valueFlags.has(arg)) {
|
|
64
|
+
skipNext = true;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (arg.startsWith('-'))
|
|
68
|
+
continue;
|
|
69
|
+
if (arg === skipCommand && index === 0)
|
|
70
|
+
continue;
|
|
71
|
+
found.push(arg);
|
|
72
|
+
}
|
|
73
|
+
return found;
|
|
74
|
+
}
|
|
75
|
+
async function executeGates(ctx) {
|
|
76
|
+
const [command] = ctx.args;
|
|
77
|
+
try {
|
|
78
|
+
if (!command || command === '--help' || command === '-h')
|
|
79
|
+
return { exitCode: 0, message: usage(), rawOutput: true };
|
|
80
|
+
const { validateGateFile, evaluateGatesFromFiles, showGatePack, listGatePacks, packsReferencedByRule, } = await import('../../gates/driver.js');
|
|
81
|
+
const options = driverOptions(ctx);
|
|
82
|
+
if (command === 'validate') {
|
|
83
|
+
const args = positionals(ctx.args, 'validate');
|
|
84
|
+
const target = (args[0] ?? '');
|
|
85
|
+
const targetPath = args[1] ?? '';
|
|
86
|
+
if (!['pack', 'binding', 'report', 'auto'].includes(target) || !targetPath) {
|
|
87
|
+
return { exitCode: 2, message: `gates validate requires <pack|binding|report|auto> <path>\n\n${usage()}`, rawOutput: true };
|
|
88
|
+
}
|
|
89
|
+
const result = await validateGateFile(target === 'auto' ? 'auto' : target, targetPath, options);
|
|
90
|
+
return jsonResult(result, result.valid ? 0 : 2);
|
|
91
|
+
}
|
|
92
|
+
if (command === 'evaluate') {
|
|
93
|
+
const binding = takeOption(ctx.args, '--binding');
|
|
94
|
+
const metrics = takeOption(ctx.args, '--metrics');
|
|
95
|
+
const holdout = takeOption(ctx.args, '--holdout');
|
|
96
|
+
const upstream = takeOption(ctx.args, '--upstream');
|
|
97
|
+
const now = takeOption(ctx.args, '--now');
|
|
98
|
+
const trustedBindingDigest = takeOption(ctx.args, '--trusted-binding-digest');
|
|
99
|
+
if (!binding || !metrics || !holdout || !now || !trustedBindingDigest) {
|
|
100
|
+
return { exitCode: 2, message: `gates evaluate requires --binding <file> --metrics <file> --holdout <file> --now <iso> --trusted-binding-digest <sha256:..>\n\n${usage()}`, rawOutput: true };
|
|
101
|
+
}
|
|
102
|
+
if (!/^sha256:[0-9a-f]{64}$/.test(trustedBindingDigest)) {
|
|
103
|
+
return { exitCode: 2, message: `gates evaluate requires --trusted-binding-digest <sha256:..> (64 hex chars)\n\n${usage()}`, rawOutput: true };
|
|
104
|
+
}
|
|
105
|
+
const report = await evaluateGatesFromFiles({
|
|
106
|
+
bindingPath: binding, metricsPath: metrics, holdoutPath: holdout,
|
|
107
|
+
...(upstream ? { upstreamPath: upstream } : {}), now,
|
|
108
|
+
trustedBindingDigest: trustedBindingDigest,
|
|
109
|
+
}, options);
|
|
110
|
+
return jsonResult(report, 0);
|
|
111
|
+
}
|
|
112
|
+
if (command === 'show') {
|
|
113
|
+
const id = positionals(ctx.args, 'show')[0];
|
|
114
|
+
if (!id)
|
|
115
|
+
return { exitCode: 2, message: `gates show requires <id>\n\n${usage()}`, rawOutput: true };
|
|
116
|
+
return jsonResult(showGatePack(id, options), 0);
|
|
117
|
+
}
|
|
118
|
+
if (command === 'list') {
|
|
119
|
+
const namespace = takeOption(ctx.args, '--namespace');
|
|
120
|
+
const ruleIndex = ctx.args.indexOf('--rule');
|
|
121
|
+
const ruleValue = ruleIndex >= 0 ? ctx.args[ruleIndex + 1] : undefined;
|
|
122
|
+
const rule = ruleIndex >= 0 ? (ruleValue && !ruleValue.startsWith('-') ? ruleValue : null) : undefined;
|
|
123
|
+
const packs = listGatePacks({ ...options, ...(namespace ? { namespace } : {}) });
|
|
124
|
+
if (rule === undefined)
|
|
125
|
+
return jsonResult({ schema: 'aiwg-gates-list/v1', packs }, 0);
|
|
126
|
+
if (rule === null) {
|
|
127
|
+
return jsonResult({
|
|
128
|
+
schema: 'aiwg-gates-list/v1', packs,
|
|
129
|
+
enforcedBy: { status: 'stub', note: 'Rule enforcedBy coverage is tracked in #2839; rules without enforcedBy remain guidance.' },
|
|
130
|
+
}, 0);
|
|
131
|
+
}
|
|
132
|
+
const referenced = new Set(await packsReferencedByRule(rule, options));
|
|
133
|
+
return jsonResult({
|
|
134
|
+
schema: 'aiwg-gates-list/v1', rule,
|
|
135
|
+
packs: packs.filter(pack => referenced.has(pack.id)),
|
|
136
|
+
enforcedBy: { status: 'stub', note: 'Rule enforcedBy coverage is tracked in #2839.' },
|
|
137
|
+
}, 0);
|
|
138
|
+
}
|
|
139
|
+
return { exitCode: 2, message: usage(), rawOutput: true };
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
return { exitCode: 1, message: error instanceof Error ? error.message : String(error) };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export const gatesHandler = {
|
|
146
|
+
id: 'gates',
|
|
147
|
+
name: 'Gates',
|
|
148
|
+
description: 'Validate, evaluate and inspect declarative gate packs offline',
|
|
149
|
+
category: 'utility',
|
|
150
|
+
aliases: [],
|
|
151
|
+
help: async () => ({ exitCode: 0, message: usage(), rawOutput: true }),
|
|
152
|
+
execute: executeGates,
|
|
153
|
+
};
|
|
154
|
+
//# sourceMappingURL=gates.js.map
|
|
@@ -73,12 +73,14 @@ import { installationHandler } from './installation.js';
|
|
|
73
73
|
import { uhpHandler } from './uhp.js';
|
|
74
74
|
import { schemaHandler } from './schema.js';
|
|
75
75
|
import { datasetHandler } from './dataset.js';
|
|
76
|
+
import { decisionHandler } from './decision.js';
|
|
77
|
+
import { gatesHandler } from './gates.js';
|
|
76
78
|
// Re-export individual handlers
|
|
77
79
|
export {
|
|
78
80
|
// Maintenance
|
|
79
81
|
helpHandler, versionHandler, authHandler, doctorHandler, contextFirewallHandler, updateHandler, refreshHandler, regenerateHandler, workspaceContextHandler,
|
|
80
82
|
// Framework management
|
|
81
|
-
useHandler, listHandler, removeHandler, promoteHandler, installHandler, packagesHandler, marketplaceHandler, initHandler, setupHandler, setupGenerateHandler, setupRunHandler, setupValidateHandler, issueHandler, issueAuditHandler, runHandler, jobHandler, costReportHandler, evidenceHandler, artifactVerifyHandler, outputModeHandler, writerProfileHandler, botHandoffHandler, buildVerifyHandler, writingHandler, schemaHandler, datasetHandler, installationHandler,
|
|
83
|
+
useHandler, listHandler, removeHandler, promoteHandler, installHandler, packagesHandler, marketplaceHandler, initHandler, setupHandler, setupGenerateHandler, setupRunHandler, setupValidateHandler, issueHandler, issueAuditHandler, runHandler, jobHandler, costReportHandler, evidenceHandler, artifactVerifyHandler, outputModeHandler, writerProfileHandler, botHandoffHandler, buildVerifyHandler, writingHandler, schemaHandler, datasetHandler, decisionHandler, gatesHandler, installationHandler,
|
|
82
84
|
// Project
|
|
83
85
|
newBundleHandler, quickrefHandler, newProjectHandler, sessionHandler, sessionsHandler,
|
|
84
86
|
// Workspace
|
|
@@ -169,6 +171,8 @@ export const allHandlers = [
|
|
|
169
171
|
writingHandler,
|
|
170
172
|
schemaHandler,
|
|
171
173
|
datasetHandler,
|
|
174
|
+
decisionHandler,
|
|
175
|
+
gatesHandler,
|
|
172
176
|
// Workspace management
|
|
173
177
|
...workspaceHandlers,
|
|
174
178
|
// Subcommand handlers (MCP, catalog, index, skills)
|
|
@@ -64,6 +64,7 @@ Options:
|
|
|
64
64
|
--provider-home <path> Override the provider home root (testing/portable homes)
|
|
65
65
|
--codex-root <path> Explicitly authorize a shared Codex sessions/export root
|
|
66
66
|
--omp-root <path> Explicitly authorize an OMP profile sessions root
|
|
67
|
+
--muse-root <path> Explicitly authorize a Muse Code sessions root
|
|
67
68
|
--dsh-root <path> Explicitly authorize a DeepSeek Harness sessions root
|
|
68
69
|
--confirm, --yes Confirm a persistent discovered batch import
|
|
69
70
|
--lock-wait-ms <n> Maximum import-lease wait (default 5000)
|
|
@@ -1172,6 +1173,8 @@ async function discoverWorkspace(ctx, args) {
|
|
|
1172
1173
|
: undefined,
|
|
1173
1174
|
ompRoot: args.values.has('--omp-root')
|
|
1174
1175
|
? resolve(ctx.cwd, args.values.get('--omp-root')) : undefined,
|
|
1176
|
+
museRoot: args.values.has('--muse-root')
|
|
1177
|
+
? resolve(ctx.cwd, args.values.get('--muse-root')) : undefined,
|
|
1175
1178
|
dshRoot: args.values.has('--dsh-root')
|
|
1176
1179
|
? resolve(ctx.cwd, args.values.get('--dsh-root')) : undefined,
|
|
1177
1180
|
codexRoot: args.values.has('--codex-root')
|
|
@@ -1439,14 +1442,14 @@ function providerDisposition(provider) {
|
|
|
1439
1442
|
}
|
|
1440
1443
|
if (provider === 'muse') {
|
|
1441
1444
|
return {
|
|
1442
|
-
provider, disposition: '
|
|
1443
|
-
supportedOperations: ['inspect', 'stream'],
|
|
1444
|
-
acquisitionModes: ['manual-export'],
|
|
1445
|
-
reasonCode:
|
|
1446
|
-
remediation: '
|
|
1445
|
+
provider, disposition: 'implemented', operationalState: 'available',
|
|
1446
|
+
supportedOperations: ['discover', 'inspect', 'stream'],
|
|
1447
|
+
acquisitionModes: ['manual-export', 'jsonl'],
|
|
1448
|
+
reasonCode: null,
|
|
1449
|
+
remediation: 'Import an explicit `muse export` trajectory JSON, or pass `--muse-root` with an explicitly authorized $XDG_DATA_HOME/muse/sessions root for evidence-gated native discovery.',
|
|
1447
1450
|
evidence: {
|
|
1448
1451
|
adapterVersion: MUSE_ADAPTER_VERSION,
|
|
1449
|
-
verifiedAt: '2026-
|
|
1452
|
+
verifiedAt: '2026-10-02',
|
|
1450
1453
|
documentation: 'docs/providers/muse-sessions.md',
|
|
1451
1454
|
},
|
|
1452
1455
|
};
|
|
@@ -1559,7 +1562,7 @@ function parseArgs(argv) {
|
|
|
1559
1562
|
'--entity', '--sensitivity', '--extraction-state', '--page-size', '--max-documents',
|
|
1560
1563
|
'--state', '--reviewer', '--reason', '--policy-version', '--min-confidence',
|
|
1561
1564
|
'--consumer', '--actor-class', '--reason-code', '--dependent-action', '--basis',
|
|
1562
|
-
'--manifest', '--provider-home', '--codex-root', '--omp-root', '--dsh-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
1565
|
+
'--manifest', '--provider-home', '--codex-root', '--omp-root', '--muse-root', '--dsh-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
1563
1566
|
'--inactivity-threshold',
|
|
1564
1567
|
'--control-events',
|
|
1565
1568
|
'--session', '--status', '--actor', '--group-by',
|
|
@@ -29,6 +29,13 @@ const REGISTRY_ID_TO_USE_NAME = {
|
|
|
29
29
|
'research-complete': 'research',
|
|
30
30
|
'forensics-complete': 'forensics',
|
|
31
31
|
};
|
|
32
|
+
function flagValue(args, flag) {
|
|
33
|
+
const index = args.indexOf(flag);
|
|
34
|
+
if (index >= 0)
|
|
35
|
+
return args[index + 1];
|
|
36
|
+
const prefix = `${flag}=`;
|
|
37
|
+
return args.find((arg) => arg.startsWith(prefix))?.slice(prefix.length);
|
|
38
|
+
}
|
|
32
39
|
/**
|
|
33
40
|
* Read the installed frameworks from the on-disk registry.
|
|
34
41
|
*/
|
|
@@ -519,6 +526,19 @@ export const doctorHandler = {
|
|
|
519
526
|
catch (error) {
|
|
520
527
|
console.log(`\n── Grok Build native extensions ──\n ⚠ unable to audit: ${error instanceof Error ? error.message : String(error)}`);
|
|
521
528
|
}
|
|
529
|
+
try {
|
|
530
|
+
const projectDir = ctx.cwd || process.cwd();
|
|
531
|
+
const provider = flagValue(ctx.args, '--provider');
|
|
532
|
+
const requested = provider === 'muse' || ctx.args.includes('--all-providers');
|
|
533
|
+
const { inspectMuseNative, isMuseDeployedProject } = await import('../../mcp/muse-native-config.mjs');
|
|
534
|
+
if (requested || await isMuseDeployedProject(projectDir)) {
|
|
535
|
+
const native = await inspectMuseNative({ projectDir });
|
|
536
|
+
console.log(`\n── Muse Code native extensions ──\n CLI: ${native.cli}\n Hooks: ${native.hooks}\n MCP: ${native.mcp}`);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
catch (error) {
|
|
540
|
+
console.log(`\n── Muse Code native extensions ──\n ⚠ unable to audit: ${error instanceof Error ? error.message : String(error)}`);
|
|
541
|
+
}
|
|
522
542
|
try {
|
|
523
543
|
const { buildAgentSkillsDoctorSection } = await import('../../skills/doctor.js');
|
|
524
544
|
const section = buildAgentSkillsDoctorSection(ctx.cwd || process.cwd());
|
|
@@ -17,6 +17,7 @@ import { validateAuthorization, } from '../policy/authorization.js';
|
|
|
17
17
|
import { projectAiwgPath, projectControlPath, resolveProjectAiwgDir, } from './project-artifacts.js';
|
|
18
18
|
import { defaultThreatAssessmentConfig, validateThreatAssessmentConfig, } from '../security/threat-assessment-config.js';
|
|
19
19
|
import { defaultArtifactOutputs, validateArtifactOutputs } from '../artifacts/output-policy.js';
|
|
20
|
+
import { validateGatesConfig } from '../gates/floors.js';
|
|
20
21
|
import { validateUhpConfig } from '../uhp/config.js';
|
|
21
22
|
const CONFIG_FILENAME = 'aiwg.config';
|
|
22
23
|
/**
|
|
@@ -174,7 +175,7 @@ export function resolveDelivery(delivery) {
|
|
|
174
175
|
* should tune. Conservative 10 default.
|
|
175
176
|
* - grokbot: desktop multi-agent; conservative 4 until native evidence.
|
|
176
177
|
* - grok-build: experimental; conservative 4 until Wave 2/3 evidence.
|
|
177
|
-
* - muse:
|
|
178
|
+
* - muse: stable; conservative 4 until native concurrency evidence.
|
|
178
179
|
* - unknown: conservative 4 default.
|
|
179
180
|
*/
|
|
180
181
|
export const PROVIDER_PARALLELISM_DEFAULTS = {
|
|
@@ -192,7 +193,7 @@ export const PROVIDER_PARALLELISM_DEFAULTS = {
|
|
|
192
193
|
// Desktop multi-agent; conservative until native concurrency evidence exists.
|
|
193
194
|
grokbot: { max_parallel_subagents: 4, max_parallel_ralph_loops: 2, max_parallel_mc_missions: 4 },
|
|
194
195
|
'grok-build': { max_parallel_subagents: 4, max_parallel_ralph_loops: 2, max_parallel_mc_missions: 4 },
|
|
195
|
-
// Muse Code is
|
|
196
|
+
// Muse Code is stable; keep conservative defaults until native concurrency evidence (#235).
|
|
196
197
|
muse: { max_parallel_subagents: 4, max_parallel_ralph_loops: 2, max_parallel_mc_missions: 4 },
|
|
197
198
|
// Conservative defaults for remaining stable/experimental harnesses (#249).
|
|
198
199
|
openhuman: { max_parallel_subagents: 4, max_parallel_ralph_loops: 2, max_parallel_mc_missions: 4 },
|
|
@@ -882,6 +883,15 @@ export async function readAiwgConfig(projectDir) {
|
|
|
882
883
|
const uhpErrors = validateUhpConfig(parsed.uhp);
|
|
883
884
|
if (uhpErrors.length > 0)
|
|
884
885
|
throw new Error(`Invalid .aiwg/aiwg.config:\n${uhpErrors.join('\n')}`);
|
|
886
|
+
// Gates errors warn (non-fatal): an invalid `gates` section must not brick
|
|
887
|
+
// every command that reads the config. Gates entry points (`aiwg gates
|
|
888
|
+
// evaluate`, binding resolution with floors) re-validate strictly via
|
|
889
|
+
// `validateGatesConfig` and fail closed there; `writeAiwgConfig` below
|
|
890
|
+
// stays strict so bad policy is never persisted.
|
|
891
|
+
const gatesErrors = validateGatesConfig(parsed.gates);
|
|
892
|
+
if (gatesErrors.length > 0) {
|
|
893
|
+
console.warn(`Invalid gates section in .aiwg/aiwg.config (ignored):\n${gatesErrors.join('\n')}`);
|
|
894
|
+
}
|
|
885
895
|
return parsed;
|
|
886
896
|
}
|
|
887
897
|
/**
|
|
@@ -903,6 +913,9 @@ export async function writeAiwgConfig(projectDir, config) {
|
|
|
903
913
|
const uhpErrors = validateUhpConfig(config.uhp);
|
|
904
914
|
if (uhpErrors.length > 0)
|
|
905
915
|
throw new Error(`Invalid .aiwg/aiwg.config:\n${uhpErrors.join('\n')}`);
|
|
916
|
+
const gatesErrors = validateGatesConfig(config.gates);
|
|
917
|
+
if (gatesErrors.length > 0)
|
|
918
|
+
throw new Error(`Invalid .aiwg/aiwg.config:\n${gatesErrors.join('\n')}`);
|
|
906
919
|
const localPath = getConfigPath(projectDir);
|
|
907
920
|
const artifactDir = resolveProjectAiwgDir(projectDir);
|
|
908
921
|
const artifactPath = join(artifactDir, CONFIG_FILENAME);
|
|
@@ -76,6 +76,31 @@ export function applyPrimitiveAcceptance(definition, policy, observation) {
|
|
|
76
76
|
}
|
|
77
77
|
return routed(observation, policy, policy.defaultRoute, 'default', evidence);
|
|
78
78
|
}
|
|
79
|
+
export function applyTargetAcceptance(definition, target, observation) {
|
|
80
|
+
if (observation.status !== 'success')
|
|
81
|
+
return observation;
|
|
82
|
+
if (target.acceptance.mode === 'typed-value')
|
|
83
|
+
return observation;
|
|
84
|
+
if (target.acceptance.mode === 'primitive-policy')
|
|
85
|
+
return applyPrimitiveAcceptance(definition, target.acceptance, observation);
|
|
86
|
+
if (!observation.uncertainty || observation.uncertainty.confidence === null)
|
|
87
|
+
return abstained('missing-confidence', observation);
|
|
88
|
+
if (observation.uncertainty.profile !== target.acceptance.profile)
|
|
89
|
+
return abstained('confidence-profile-mismatch', observation);
|
|
90
|
+
// Compare on the probability scale: minimumBps / 10_000 is the exact double for the decimal threshold,
|
|
91
|
+
// whereas confidence * 10_000 can round below it (0.7 * 10_000 === 6999.999999999999).
|
|
92
|
+
return observation.uncertainty.confidence < target.acceptance.minimumBps / 10_000
|
|
93
|
+
? abstained('low-confidence', observation) : observation;
|
|
94
|
+
}
|
|
95
|
+
// Mirrors the evaluator's failure observation: an abstention keeps provenance but drops the value.
|
|
96
|
+
function abstained(reason, observation) {
|
|
97
|
+
return {
|
|
98
|
+
status: 'abstained', reason, uncertainty: observation.uncertainty ?? null,
|
|
99
|
+
actualModel: observation.actualModel ?? null,
|
|
100
|
+
usage: observation.usage ?? { inputTokens: null, outputTokens: null, costUsd: null },
|
|
101
|
+
requestId: observation.requestId ?? null,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
79
104
|
function deriveEvidence(definition, observation) {
|
|
80
105
|
const values = {};
|
|
81
106
|
const add = (metric, value, normalized, provenance, calibrationRef = null) => {
|