@aiwg/cli 2026.10.10 → 2026.10.12

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.
Files changed (156) hide show
  1. package/agentic/code/providers/model-capabilities.v1.json +78 -14
  2. package/agentic/code/providers/model-catalog.v1.json +62 -12
  3. package/dist/src/artifacts/binding-target-identity.js +51 -0
  4. package/dist/src/artifacts/checksum-manifest.js +12 -0
  5. package/dist/src/artifacts/index-builder.js +11 -13
  6. package/dist/src/artifacts/query-engine.js +5 -11
  7. package/dist/src/cli/handlers/doctor-help.js +32 -0
  8. package/dist/src/cli/handlers/gates.js +19 -18
  9. package/dist/src/cli/handlers/models-help.js +7 -1
  10. package/dist/src/cli/handlers/models.js +3 -3
  11. package/dist/src/cli/handlers/script-runner.js +8 -5
  12. package/dist/src/cli/handlers/sessions-intake.js +104 -0
  13. package/dist/src/cli/handlers/sessions-tail.js +172 -0
  14. package/dist/src/cli/handlers/sessions.js +287 -31
  15. package/dist/src/cli/handlers/skill-lint.js +10 -3
  16. package/dist/src/cli/handlers/steward-format.js +100 -0
  17. package/dist/src/cli/handlers/steward-models.js +167 -0
  18. package/dist/src/cli/handlers/steward.js +14 -248
  19. package/dist/src/cli/handlers/use-bundle-counts.js +61 -0
  20. package/dist/src/cli/handlers/use.js +18 -28
  21. package/dist/src/cli/handlers/utilities.js +1 -24
  22. package/dist/src/config/aiwg-config.js +7 -0
  23. package/dist/src/config/authorization-cli.js +89 -0
  24. package/dist/src/config/cli-help.js +1 -0
  25. package/dist/src/config/cli.js +10 -1
  26. package/dist/src/config/worker-context.js +337 -0
  27. package/dist/src/decision/context-pruning.js +3 -2
  28. package/dist/src/decision/ensemble/contract.js +15 -4
  29. package/dist/src/decision/ensemble-study/artifacts.js +5 -0
  30. package/dist/src/decision/ensemble-study/score.js +4 -3
  31. package/dist/src/decision/feature-export.js +3 -9
  32. package/dist/src/decision/heldout/collector.js +2 -2
  33. package/dist/src/decision/issue-triage/runtime.js +3 -9
  34. package/dist/src/decision/qualification/gates.js +2 -1
  35. package/dist/src/decision/qualification/release.js +2 -3
  36. package/dist/src/decision/routing/report.js +2 -0
  37. package/dist/src/decision/sdlc-screening.js +3 -5
  38. package/dist/src/decision/sensitivity/comparative.js +5 -3
  39. package/dist/src/gates/driver.js +6 -77
  40. package/dist/src/gates/evaluate.js +4 -11
  41. package/dist/src/gates/floors.js +4 -4
  42. package/dist/src/gates/index.js +3 -3
  43. package/dist/src/gates/lattice.js +26 -0
  44. package/dist/src/gates/registry.js +2 -1
  45. package/dist/src/gates/report.js +19 -7
  46. package/dist/src/issues/audit-cli.js +120 -0
  47. package/dist/src/issues/audit-contract.js +64 -0
  48. package/dist/src/issues/audit-local.js +82 -0
  49. package/dist/src/issues/audit.js +220 -0
  50. package/dist/src/lint/rule-activation.js +15 -1
  51. package/dist/src/mcp/tools/worker-invoke.mjs +108 -10
  52. package/dist/src/mission-protocol/canonical-codecs.js +270 -0
  53. package/dist/src/mission-protocol/codecs.js +22 -550
  54. package/dist/src/mission-protocol/health-trace-codecs.js +281 -0
  55. package/dist/src/mission-protocol/health-trace-types.js +43 -0
  56. package/dist/src/mission-protocol/types.js +2 -42
  57. package/dist/src/mission-protocol/worker-contract-json.js +10 -0
  58. package/dist/src/mission-protocol/worker-review-gate.js +100 -0
  59. package/dist/src/mission-protocol/worker-review-types.js +2 -0
  60. package/dist/src/models/catalog-policy.js +280 -0
  61. package/dist/src/models/index.js +1 -1
  62. package/dist/src/models/model-capabilities.v1.json +78 -14
  63. package/dist/src/models/model-catalog.v1.json +62 -12
  64. package/dist/src/models/policy-resources.js +28 -0
  65. package/dist/src/models/provider-policy.js +10 -539
  66. package/dist/src/models/resolver.js +26 -8
  67. package/dist/src/models/router.js +15 -2
  68. package/dist/src/models/tiers.js +13 -0
  69. package/dist/src/models/types.js +0 -6
  70. package/dist/src/models/worker-ceilings.js +59 -0
  71. package/dist/src/models/worker-invocation-policy.js +243 -0
  72. package/dist/src/models/worker-plan.js +16 -20
  73. package/dist/src/models/worker-review-lineage.js +55 -0
  74. package/dist/src/models/worker-selection-policy.js +1 -1
  75. package/dist/src/models/wrapper-route.js +6 -3
  76. package/dist/src/policy/authorization.js +30 -1
  77. package/dist/src/policy/hitl-config.js +63 -0
  78. package/dist/src/policy/hitl-receipt.js +57 -0
  79. package/dist/src/policy/hitl-types.js +4 -0
  80. package/dist/src/policy/hitl-validation.js +39 -0
  81. package/dist/src/policy/hitl.js +117 -0
  82. package/dist/src/process/aiwg-probe-command.d.mts +15 -0
  83. package/dist/src/process/aiwg-probe-command.mjs +37 -0
  84. package/dist/src/rules/activation.d.mts +1 -1
  85. package/dist/src/rules/activation.mjs +0 -2
  86. package/dist/src/rules/gate-coverage.js +51 -0
  87. package/dist/src/rules/gate-references.js +16 -0
  88. package/dist/src/rules/rule-frontmatter.schema.json +7 -1
  89. package/dist/src/serve/worker-command-request.js +21 -4
  90. package/dist/src/serve/worker-invocation-preparation.js +3 -1
  91. package/dist/src/serve/worker-invocation.js +21 -10
  92. package/dist/src/sessions/adapters/deepseek-harness.js +1 -0
  93. package/dist/src/sessions/adapters/grok-build-native.js +269 -0
  94. package/dist/src/sessions/adapters/grok-build.js +57 -15
  95. package/dist/src/sessions/adapters/grokbot.js +7 -0
  96. package/dist/src/sessions/adapters/hermes-state-db.js +252 -0
  97. package/dist/src/sessions/adapters/hermes.js +42 -3
  98. package/dist/src/sessions/adapters/warp.js +1 -1
  99. package/dist/src/sessions/batch-import.js +44 -6
  100. package/dist/src/sessions/contracts.js +20 -1
  101. package/dist/src/sessions/coverage-preflight.js +7 -1
  102. package/dist/src/sessions/discovery-capability.js +38 -0
  103. package/dist/src/sessions/fortemi-export-mapping.js +33 -3
  104. package/dist/src/sessions/host-catalog.js +157 -0
  105. package/dist/src/sessions/image-blobs.js +141 -0
  106. package/dist/src/sessions/importer.js +9 -232
  107. package/dist/src/sessions/index.js +6 -0
  108. package/dist/src/sessions/intake-dir.js +71 -0
  109. package/dist/src/sessions/normalization.js +251 -0
  110. package/dist/src/sessions/refresh.js +25 -2
  111. package/dist/src/sessions/repository.js +164 -22
  112. package/dist/src/sessions/tail.js +91 -0
  113. package/dist/src/sessions/workspace-discovery.js +88 -9
  114. package/dist/src/skills/agent-skill-sidecar.js +28 -0
  115. package/dist/src/skills/agent-skills.js +4 -23
  116. package/dist/src/skills/claude-surface-projection.js +25 -0
  117. package/dist/src/skills/deployer.js +8 -288
  118. package/dist/src/skills/deployment-policy.js +114 -0
  119. package/dist/src/skills/deployment-projection.js +152 -0
  120. package/dist/src/skills/deployment-types.js +20 -0
  121. package/dist/src/skills/exporter.js +8 -31
  122. package/dist/src/skills/provider-extensions.js +41 -0
  123. package/dist/src/skills/run.js +6 -0
  124. package/dist/src/skills/types.js +0 -8
  125. package/dist/src/skills/validator-resources.js +68 -0
  126. package/dist/src/skills/validator.js +6 -55
  127. package/dist/src/storage/cli-migrate-options.js +125 -0
  128. package/dist/src/storage/cli-migrate.js +111 -0
  129. package/dist/src/storage/cli.js +4 -279
  130. package/dist/src/storage/migration-adapter.js +79 -0
  131. package/dist/src/storage/migration-copy.js +108 -0
  132. package/dist/src/storage/migration-protocol.js +14 -197
  133. package/dist/src/storage/migration-records.js +186 -0
  134. package/dist/src/storage/migration-types.js +12 -0
  135. package/dist/src/tracker/forge-http.js +2 -1
  136. package/dist/src/tracker/issue-pages.js +110 -0
  137. package/package.json +7 -1
  138. package/schemas/mission-v1.schema.json +335 -0
  139. package/schemas/models/model-catalog.v1.schema.json +19 -1
  140. package/schemas/models/model-config-compatibility.v1.schema.json +3 -2
  141. package/schemas/models/model-policy.v1.schema.json +1 -1
  142. package/tools/agents/providers/provider-paths-staging.mjs +35 -0
  143. package/tools/agents/providers/rule-binding-targets.mjs +146 -0
  144. package/tools/agents/providers/rule-delivery.mjs +7 -126
  145. package/tools/ralph-external/lib/muse-adapter.mjs +10 -0
  146. package/tools/ralph-external/lib/worker-context.mjs +237 -0
  147. package/tools/ralph-external/lib/worker-invocation-ancestry.mjs +132 -0
  148. package/tools/ralph-external/lib/worker-invocation-processes.mjs +123 -0
  149. package/tools/ralph-external/lib/worker-isolation-status.mjs +48 -0
  150. package/tools/ralph-external/lib/worker-isolation.mjs +17 -29
  151. package/tools/ralph-external/lib/worker-launch-cli.mjs +3 -1
  152. package/tools/ralph-external/lib/worker-overflow.mjs +48 -13
  153. package/tools/ralph-external/lib/worker-retry-evidence.mjs +103 -0
  154. package/tools/ralph-external/lib/worker-termination.mjs +82 -0
  155. package/tools/ralph-external/session-launcher.mjs +51 -96
  156. package/vscode-extension/schemas/aiwg.config.v1.json +177 -0
@@ -0,0 +1,100 @@
1
+ // Formats the steward capability matrix and permission command usage.
2
+ import { isExternalStrategy } from '../../providers/capability-matrix.js';
3
+ export function printFullMatrix(matrix) {
4
+ const { providers, features } = matrix;
5
+ const providerIds = Object.keys(providers);
6
+ const featureIds = Object.keys(features);
7
+ console.log(`\n Provider Capability Matrix (v${matrix.version})`);
8
+ console.log(` ✓ = native ~ = AIWG emulation - = not supported\n`);
9
+ const featureColW = 20;
10
+ const provColW = 14;
11
+ const header = ' ' + 'Feature'.padEnd(featureColW) + providerIds.map(p => p.padEnd(provColW)).join('');
12
+ console.log(header);
13
+ console.log(' ' + '─'.repeat(featureColW + providerIds.length * provColW));
14
+ for (const featureId of featureIds) {
15
+ const feat = features[featureId];
16
+ let row = ' ' + featureId.padEnd(featureColW);
17
+ for (const providerId of providerIds) {
18
+ const provider = providers[providerId];
19
+ const isNative = provider?.native_features?.[featureId] === true;
20
+ const emulation = provider?.emulation?.[featureId] ?? null;
21
+ const mark = isNative ? '✓' : (emulation ? '~' : '-');
22
+ row += mark.padEnd(provColW);
23
+ }
24
+ console.log(row);
25
+ if (feat?.description) {
26
+ console.log(' ' + ' '.repeat(featureColW) + feat.description);
27
+ }
28
+ console.log('');
29
+ }
30
+ }
31
+ // ── Main execution ─────────────────────────────────────────────────────────────
32
+ export function permissionsUsage() {
33
+ return `
34
+ aiwg steward permissions — authorization model audit and normalization
35
+
36
+ Usage:
37
+ aiwg steward permissions audit Find normalized-model errors and legacy grants
38
+ aiwg steward permissions migrate --dry-run Preview legacy permission normalization
39
+ aiwg steward permissions migrate --apply Back up and atomically normalize config
40
+
41
+ Reads .aiwg/aiwg.config authorization block. Migration backs up before writing.
42
+ `;
43
+ }
44
+ const NATIVE_MARK = '✓ native';
45
+ const EMULATED_MARK = '~ emulated';
46
+ const EXTERNAL_MARK = '↗ external';
47
+ const UNSUPPORTED_MARK = '- not supported';
48
+ export function emulationLabel(strategy) {
49
+ if (!strategy)
50
+ return 'none';
51
+ if (strategy === 'native')
52
+ return 'native (no fallback needed)';
53
+ return strategy;
54
+ }
55
+ export function formatProvider(id, provider, matrix, meta) {
56
+ const lines = [];
57
+ lines.push(`\n Provider: ${provider.display_name} (${id})`);
58
+ if (meta) {
59
+ lines.push(` Project-local: yes`);
60
+ lines.push(` Base adapter: ${meta.baseAdapter}`);
61
+ }
62
+ lines.push(` Status: ${provider.status}`);
63
+ lines.push(` Daemon: ${provider.daemon_tier}${provider.daemon_pty_adapter ? ' (+ pty-adapter)' : ''}`);
64
+ lines.push(` ${'─'.repeat(60)}`);
65
+ const featureKeys = Object.keys(matrix.features);
66
+ for (const featureId of featureKeys) {
67
+ const isNative = provider.native_features?.[featureId] === true;
68
+ const emulation = provider.emulation?.[featureId] ?? null;
69
+ const status = isNative
70
+ ? NATIVE_MARK
71
+ : isExternalStrategy(emulation) ? EXTERNAL_MARK : (emulation ? EMULATED_MARK : UNSUPPORTED_MARK);
72
+ const feat = matrix.features[featureId];
73
+ lines.push(`\n ${featureId} — ${status}`);
74
+ if (feat?.description)
75
+ lines.push(` ${feat.description}`);
76
+ if (isNative) {
77
+ if (id === 'omp' && featureId === 'mcp') {
78
+ lines.push(' OMP supplies the native client. AIWG persistent injection/removal is available for project and profile scope; ephemeral injection is unsupported.');
79
+ lines.push(' example: aiwg mcp inject --provider omp --servers local-tools');
80
+ }
81
+ else if (id === 'omp' && featureId === 'behaviors') {
82
+ lines.push(' AIWG bridges selected handlers through an OMP extension; no default policy is installed. Permission-request and pre-compaction enforcement are unsupported.');
83
+ }
84
+ else if (id === 'omp' && (featureId === 'tasks' || featureId === 'agent_teams')) {
85
+ lines.push(' OMP native leaf tasks use AIWG workspace admission limits and verified child results; nested requests share the same scheduler.');
86
+ lines.push(' example: aiwg team run --provider omp --body-file tasks.json');
87
+ }
88
+ else if (feat?.native_example)
89
+ lines.push(` example: ${feat.native_example}`);
90
+ }
91
+ else if (isExternalStrategy(emulation)) {
92
+ lines.push(` trigger: system cron, systemd timer, or CI; AIWG does not own the clock`);
93
+ }
94
+ else if (emulation) {
95
+ lines.push(` fallback: ${emulationLabel(emulation)}`);
96
+ }
97
+ }
98
+ return lines.join('\n');
99
+ }
100
+ //# sourceMappingURL=steward-format.js.map
@@ -0,0 +1,167 @@
1
+ import { access } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { AiwgError, EXIT_CODES } from '../errors.js';
4
+ import { getProjectDir } from '../../config/aiwg-config.js';
5
+ import { capabilityProviderId, normalizeProviderId, resolveActiveProvider } from '../provider-resolution.js';
6
+ import { routeModelTier } from '../../models/router.js';
7
+ import { buildWrapperRouteEnvelope } from '../../models/wrapper-route.js';
8
+ import { loadProviderModelCatalog } from '../../models/provider-policy.js';
9
+ import { CapabilityResolutionError, resolveRoutableCapability } from '../../artifacts/capability-resolver.js';
10
+ function isModelPolicyProvider(provider) {
11
+ return Object.hasOwn(loadProviderModelCatalog().providers, provider);
12
+ }
13
+ export async function handleStewardModels(args, matrix, ctx) {
14
+ const flagValue = (name) => {
15
+ const index = args.indexOf(name);
16
+ if (index < 0)
17
+ return undefined;
18
+ const value = args[index + 1];
19
+ if (!value || value.startsWith('--'))
20
+ throw new AiwgError({
21
+ code: 'ERR_USAGE_MISSING_VALUE',
22
+ message: `${name} requires a value.`,
23
+ exitCode: EXIT_CODES.USAGE,
24
+ });
25
+ return value;
26
+ };
27
+ if (args.includes('--route')) {
28
+ const rawProvider = flagValue('--provider') ?? await resolveActiveProvider({
29
+ cwd: ctx ? getProjectDir(ctx, ctx.args) : process.cwd(),
30
+ detectProcess: true,
31
+ }).then(result => result.provider ?? undefined);
32
+ const provider = normalizeProviderId(rawProvider);
33
+ if (!provider || provider === 'generic')
34
+ throw new AiwgError({
35
+ code: 'ERR_USAGE_UNKNOWN_PROVIDER',
36
+ message: `Cannot compile a wrapper route for provider: ${rawProvider ?? '(undetected)'}`,
37
+ hint: 'Pass --provider with a supported provider id.',
38
+ exitCode: EXIT_CODES.USAGE,
39
+ });
40
+ if (!isModelPolicyProvider(provider))
41
+ throw new AiwgError({
42
+ code: 'ERR_USAGE_UNSUPPORTED_PROVIDER',
43
+ message: `Model wrapper routing is not implemented for provider: ${provider}`,
44
+ hint: 'Use `aiwg steward capabilities --provider pi` for current Pi capability routing; model routing is tracked separately.',
45
+ exitCode: EXIT_CODES.USAGE,
46
+ });
47
+ const capabilityType = flagValue('--capability-type');
48
+ const capability = flagValue('--capability');
49
+ const assignment = flagValue('--assignment');
50
+ if (!capabilityType || !['agent', 'skill', 'rule', 'workflow'].includes(capabilityType))
51
+ throw new AiwgError({
52
+ code: 'ERR_USAGE_MISSING_VALUE',
53
+ message: '--capability-type requires agent, skill, rule, or workflow.',
54
+ exitCode: EXIT_CODES.USAGE,
55
+ });
56
+ if (!capability || !assignment)
57
+ throw new AiwgError({
58
+ code: 'ERR_USAGE_MISSING_VALUE',
59
+ message: '--route requires both --capability <id> and --assignment <bounded text>.',
60
+ exitCode: EXIT_CODES.USAGE,
61
+ });
62
+ const capabilityProvider = capabilityProviderId(provider);
63
+ const providerCapabilities = capabilityProvider ? matrix.providers[capabilityProvider] : undefined;
64
+ const launchMechanism = providerCapabilities?.native_features.tasks
65
+ ? 'native-subagent'
66
+ : providerCapabilities?.emulation.tasks === 'aiwg-mc' ? 'aiwg-mc' : 'manual';
67
+ const premiumAuthorized = args.includes('--allow-premium');
68
+ const { collectProviderInventory } = await import('../../providers/provider-inventory.js');
69
+ const { resolveDynamicModelCatalog } = await import('../../models/model-discovery.js');
70
+ const projectDir = ctx ? getProjectDir(ctx, ctx.args) : process.cwd();
71
+ const requestedAiwgRoot = ctx?.frameworkRoot ?? process.cwd();
72
+ const aiwgRoot = await access(join(requestedAiwgRoot, 'agentic/code/providers/model-catalog.v1.json')).then(() => requestedAiwgRoot).catch(() => process.cwd());
73
+ const resolvedCapability = await resolveRoutableCapability(aiwgRoot, capabilityType, capability).catch(error => {
74
+ if (!(error instanceof CapabilityResolutionError))
75
+ throw error;
76
+ throw new AiwgError({
77
+ code: error.kind === 'ambiguous'
78
+ ? 'ERR_USAGE_AMBIGUOUS_CAPABILITY'
79
+ : 'ERR_USAGE_UNKNOWN_CAPABILITY',
80
+ message: error.message,
81
+ hint: 'Run aiwg discover "<capability>" --json and pass an exact name or stable id.',
82
+ exitCode: EXIT_CODES.USAGE,
83
+ });
84
+ });
85
+ const catalog = await resolveDynamicModelCatalog({
86
+ aiwgRoot,
87
+ inventory: await collectProviderInventory(projectDir),
88
+ allowNetwork: false,
89
+ });
90
+ const baselineCatalog = loadProviderModelCatalog();
91
+ const effectiveCatalog = {
92
+ ...baselineCatalog,
93
+ ...catalog,
94
+ refreshedAt: catalog.refreshedAt ?? baselineCatalog.refreshedAt,
95
+ staleAfterDays: baselineCatalog.staleAfterDays,
96
+ providers: { ...baselineCatalog.providers, ...catalog.providers },
97
+ };
98
+ const envelope = buildWrapperRouteEnvelope({
99
+ provider,
100
+ capability: resolvedCapability,
101
+ assignment,
102
+ launchMechanism,
103
+ deterministic: args.includes('--deterministic'),
104
+ routine: args.includes('--routine'),
105
+ complex: args.includes('--complex'),
106
+ highImpact: args.includes('--high-impact'),
107
+ requestedPremium: args.includes('--premium'),
108
+ unattended: args.includes('--unattended'),
109
+ premiumAuthorized,
110
+ maxAutoTier: premiumAuthorized ? 3 : undefined,
111
+ catalog: effectiveCatalog,
112
+ });
113
+ if (args.includes('--json'))
114
+ console.log(JSON.stringify(envelope, null, 2));
115
+ else {
116
+ console.log('\n Model wrapper route');
117
+ console.log(` Provider: ${envelope.provider}`);
118
+ console.log(` Capability: ${envelope.capability.type} ${envelope.capability.name} (${envelope.capability.id})`);
119
+ console.log(` Tier/role: ${envelope.tier ?? 'deterministic'}/${envelope.role ?? 'none'}`);
120
+ console.log(` Wrapper: ${envelope.wrapper ?? 'none'}`);
121
+ console.log(` Model: ${envelope.model?.effectiveModel ?? 'inherited or no model call'} (${envelope.model?.outcome ?? 'deterministic'})`);
122
+ console.log(` Launch: ${envelope.launch.mechanism}`);
123
+ console.log(` Confirmation: ${envelope.decision.requiresConfirmation ? 'required' : 'not required'}`);
124
+ console.log('\n Wrapper prompt:\n');
125
+ console.log(envelope.launch.prompt);
126
+ }
127
+ return;
128
+ }
129
+ const tiers = Object.fromEntries(Object.entries(loadProviderModelCatalog().providers)
130
+ .filter(([, entry]) => entry.tiers)
131
+ .map(([provider, entry]) => [provider, Object.fromEntries(Object.entries(entry.tiers)
132
+ .map(([tier, model]) => [tier, { ...model, label: model.selection === 'user-elected' ? 'user-elected only' : tier }]))]));
133
+ const decision = routeModelTier({
134
+ deterministic: args.includes('--deterministic'),
135
+ routine: args.includes('--routine'),
136
+ complex: args.includes('--complex'),
137
+ highImpact: args.includes('--high-impact'),
138
+ requestedPremium: args.includes('--premium'),
139
+ unattended: args.includes('--unattended'),
140
+ premiumAuthorized: args.includes('--allow-premium'),
141
+ maxAutoTier: args.includes('--allow-premium') ? 3 : undefined,
142
+ });
143
+ if (args.includes('--json')) {
144
+ console.log(JSON.stringify({ decision, tiers }, null, 2));
145
+ return;
146
+ }
147
+ for (const [provider, ladder] of Object.entries(tiers)) {
148
+ for (const [tier, entry] of Object.entries(ladder))
149
+ console.log(` ${provider} ${tier}: ${entry.id} (${entry.label})`);
150
+ }
151
+ console.log('\n Model policy routing');
152
+ console.log(` Default stance: cheap-first role/tier intent, compiled per provider from the effective catalog.`);
153
+ console.log(` Suggested tier: ${decision.tier}${decision.modelTier ? ` (${decision.modelTier})` : ' (no model call)'}`);
154
+ console.log(` Confirmation: ${decision.requiresConfirmation ? 'required' : 'not required'}`);
155
+ console.log(` Summary before escalation: ${decision.summaryRequired ? 'required' : 'not required'}`);
156
+ console.log(` Rationale: ${decision.rationale.join('; ')}`);
157
+ console.log('\n Commands:');
158
+ console.log(' aiwg models sources --json # inspect effective cache/static/remote catalog provenance');
159
+ console.log(' aiwg models refresh --json # refresh dynamic provider catalog where supported');
160
+ console.log(' aiwg models audit --provider P # compile artifact policy and diagnostics');
161
+ console.log(' aiwg models resolve --provider P # show selected provider model for matching artifacts');
162
+ console.log('\n Authoring:');
163
+ console.log(' Agents: use model-role/model-tier; avoid exact provider IDs in source scaffolds.');
164
+ console.log(' Skills/commands: use commandHint.modelRole and commandHint.modelTier.');
165
+ return;
166
+ }
167
+ //# sourceMappingURL=steward-models.js.map
@@ -16,22 +16,15 @@
16
16
  * @source @src/cli/router.ts
17
17
  * @issue #599 #1261 #1262
18
18
  */
19
- import { access } from 'node:fs/promises';
20
- import { join } from 'node:path';
21
19
  import { AiwgError, EXIT_CODES, handlerResultFromError } from '../errors.js';
22
20
  import { loadCapabilityMatrix, isExternalStrategy, } from '../../providers/capability-matrix.js';
23
21
  import { getProjectDir, readAiwgConfig, writeAiwgConfig } from '../../config/aiwg-config.js';
24
22
  import { auditLegacyPermissions, archiveLegacyPermissionManifests, backupConfig, normalizeProjectPermissions, } from '../../policy/authorization.js';
25
23
  import { capabilityProviderId, normalizeProviderId, resolveActiveProvider } from '../provider-resolution.js';
26
24
  import { discoverProjectLocalBundles, } from '../../extensions/project-local-discovery.js';
27
- import { routeModelTier } from '../../models/router.js';
28
- import { buildWrapperRouteEnvelope } from '../../models/wrapper-route.js';
29
- import { loadProviderModelCatalog, } from '../../models/provider-policy.js';
30
- import { CapabilityResolutionError, resolveRoutableCapability, } from '../../artifacts/capability-resolver.js';
25
+ import { printFullMatrix, permissionsUsage, formatProvider, emulationLabel } from './steward-format.js';
26
+ import { handleStewardModels } from './steward-models.js';
31
27
  const BASELINE_PROVIDER = 'claude-code';
32
- function isModelPolicyProvider(provider) {
33
- return Object.hasOwn(loadProviderModelCatalog().providers, provider);
34
- }
35
28
  // ── Feature name normalization ────────────────────────────────────────────────
36
29
  /**
37
30
  * Accept both hyphenated (agent-teams) and underscored (agent_teams) feature
@@ -49,62 +42,6 @@ async function detectProvider(ctx) {
49
42
  return capabilityProviderId(resolution.provider);
50
43
  }
51
44
  // ── Formatters ────────────────────────────────────────────────────────────────
52
- const NATIVE_MARK = '✓ native';
53
- const EMULATED_MARK = '~ emulated';
54
- const EXTERNAL_MARK = '↗ external';
55
- const UNSUPPORTED_MARK = '- not supported';
56
- function emulationLabel(strategy) {
57
- if (!strategy)
58
- return 'none';
59
- if (strategy === 'native')
60
- return 'native (no fallback needed)';
61
- return strategy;
62
- }
63
- function formatProvider(id, provider, matrix, meta) {
64
- const lines = [];
65
- lines.push(`\n Provider: ${provider.display_name} (${id})`);
66
- if (meta) {
67
- lines.push(` Project-local: yes`);
68
- lines.push(` Base adapter: ${meta.baseAdapter}`);
69
- }
70
- lines.push(` Status: ${provider.status}`);
71
- lines.push(` Daemon: ${provider.daemon_tier}${provider.daemon_pty_adapter ? ' (+ pty-adapter)' : ''}`);
72
- lines.push(` ${'─'.repeat(60)}`);
73
- const featureKeys = Object.keys(matrix.features);
74
- for (const featureId of featureKeys) {
75
- const isNative = provider.native_features?.[featureId] === true;
76
- const emulation = provider.emulation?.[featureId] ?? null;
77
- const status = isNative
78
- ? NATIVE_MARK
79
- : isExternalStrategy(emulation) ? EXTERNAL_MARK : (emulation ? EMULATED_MARK : UNSUPPORTED_MARK);
80
- const feat = matrix.features[featureId];
81
- lines.push(`\n ${featureId} — ${status}`);
82
- if (feat?.description)
83
- lines.push(` ${feat.description}`);
84
- if (isNative) {
85
- if (id === 'omp' && featureId === 'mcp') {
86
- lines.push(' OMP supplies the native client. AIWG persistent injection/removal is available for project and profile scope; ephemeral injection is unsupported.');
87
- lines.push(' example: aiwg mcp inject --provider omp --servers local-tools');
88
- }
89
- else if (id === 'omp' && featureId === 'behaviors') {
90
- lines.push(' AIWG bridges selected handlers through an OMP extension; no default policy is installed. Permission-request and pre-compaction enforcement are unsupported.');
91
- }
92
- else if (id === 'omp' && (featureId === 'tasks' || featureId === 'agent_teams')) {
93
- lines.push(' OMP native leaf tasks use AIWG workspace admission limits and verified child results; nested requests share the same scheduler.');
94
- lines.push(' example: aiwg team run --provider omp --body-file tasks.json');
95
- }
96
- else if (feat?.native_example)
97
- lines.push(` example: ${feat.native_example}`);
98
- }
99
- else if (isExternalStrategy(emulation)) {
100
- lines.push(` trigger: system cron, systemd timer, or CI; AIWG does not own the clock`);
101
- }
102
- else if (emulation) {
103
- lines.push(` fallback: ${emulationLabel(emulation)}`);
104
- }
105
- }
106
- return lines.join('\n');
107
- }
108
45
  async function findProjectLocalProvider(projectDir, requestedProvider) {
109
46
  const discovery = await discoverProjectLocalBundles(projectDir);
110
47
  const requested = requestedProvider.trim().toLowerCase();
@@ -156,47 +93,6 @@ async function resolveStewardProvider(matrix, requestedProvider, ctx) {
156
93
  },
157
94
  };
158
95
  }
159
- function printFullMatrix(matrix) {
160
- const { providers, features } = matrix;
161
- const providerIds = Object.keys(providers);
162
- const featureIds = Object.keys(features);
163
- console.log(`\n Provider Capability Matrix (v${matrix.version})`);
164
- console.log(` ✓ = native ~ = AIWG emulation - = not supported\n`);
165
- const featureColW = 20;
166
- const provColW = 14;
167
- const header = ' ' + 'Feature'.padEnd(featureColW) + providerIds.map(p => p.padEnd(provColW)).join('');
168
- console.log(header);
169
- console.log(' ' + '─'.repeat(featureColW + providerIds.length * provColW));
170
- for (const featureId of featureIds) {
171
- const feat = features[featureId];
172
- let row = ' ' + featureId.padEnd(featureColW);
173
- for (const providerId of providerIds) {
174
- const provider = providers[providerId];
175
- const isNative = provider?.native_features?.[featureId] === true;
176
- const emulation = provider?.emulation?.[featureId] ?? null;
177
- const mark = isNative ? '✓' : (emulation ? '~' : '-');
178
- row += mark.padEnd(provColW);
179
- }
180
- console.log(row);
181
- if (feat?.description) {
182
- console.log(' ' + ' '.repeat(featureColW) + feat.description);
183
- }
184
- console.log('');
185
- }
186
- }
187
- // ── Main execution ─────────────────────────────────────────────────────────────
188
- function permissionsUsage() {
189
- return `
190
- aiwg steward permissions — authorization model audit and normalization
191
-
192
- Usage:
193
- aiwg steward permissions audit Find normalized-model errors and legacy grants
194
- aiwg steward permissions migrate --dry-run Preview legacy permission normalization
195
- aiwg steward permissions migrate --apply Back up and atomically normalize config
196
-
197
- Reads .aiwg/aiwg.config authorization block. Migration backs up before writing.
198
- `;
199
- }
200
96
  async function handleSteward(args, ctx) {
201
97
  const subcommand = args[0];
202
98
  if (!subcommand || subcommand === '--help' || subcommand === 'help') {
@@ -214,6 +110,7 @@ async function handleSteward(args, ctx) {
214
110
  aiwg steward models --route --capability-type <agent|skill|rule|workflow>
215
111
  --capability <id> --assignment <text> [--provider <name>] [--json]
216
112
  Emit a capability-bound wrapper launch envelope
113
+ aiwg steward authorization Bounded HITL policy: inspect/validate/preview/enable/revoke
217
114
  aiwg steward permissions audit Find normalized-model errors and legacy grants
218
115
  aiwg steward permissions migrate --dry-run Preview legacy permission normalization
219
116
  aiwg steward permissions migrate --apply Back up and atomically normalize config
@@ -242,6 +139,11 @@ async function handleSteward(args, ctx) {
242
139
  console.log(JSON.stringify(args.includes('--json') ? { decisionOffload } : decisionOffload, null, 2));
243
140
  return;
244
141
  }
142
+ if (subcommand === 'authorization') {
143
+ const { authorizationCli } = await import('../../config/authorization-cli.js');
144
+ await authorizationCli(args.slice(1), ctx?.cwd);
145
+ return;
146
+ }
245
147
  if (subcommand === 'permissions') {
246
148
  const operation = args[1];
247
149
  // `<namespace> --help` must reach the same usage block bare invocation prints (#2533).
@@ -478,148 +380,8 @@ async function handleSteward(args, ctx) {
478
380
  }
479
381
  return;
480
382
  }
481
- if (subcommand === 'models' || subcommand === 'model-routing') {
482
- const flagValue = (name) => {
483
- const index = args.indexOf(name);
484
- if (index < 0)
485
- return undefined;
486
- const value = args[index + 1];
487
- if (!value || value.startsWith('--'))
488
- throw new AiwgError({
489
- code: 'ERR_USAGE_MISSING_VALUE',
490
- message: `${name} requires a value.`,
491
- exitCode: EXIT_CODES.USAGE,
492
- });
493
- return value;
494
- };
495
- if (args.includes('--route')) {
496
- const rawProvider = flagValue('--provider') ?? await resolveActiveProvider({
497
- cwd: ctx ? getProjectDir(ctx, ctx.args) : process.cwd(),
498
- detectProcess: true,
499
- }).then(result => result.provider ?? undefined);
500
- const provider = normalizeProviderId(rawProvider);
501
- if (!provider || provider === 'generic')
502
- throw new AiwgError({
503
- code: 'ERR_USAGE_UNKNOWN_PROVIDER',
504
- message: `Cannot compile a wrapper route for provider: ${rawProvider ?? '(undetected)'}`,
505
- hint: 'Pass --provider with a supported provider id.',
506
- exitCode: EXIT_CODES.USAGE,
507
- });
508
- if (!isModelPolicyProvider(provider))
509
- throw new AiwgError({
510
- code: 'ERR_USAGE_UNSUPPORTED_PROVIDER',
511
- message: `Model wrapper routing is not implemented for provider: ${provider}`,
512
- hint: 'Use `aiwg steward capabilities --provider pi` for current Pi capability routing; model routing is tracked separately.',
513
- exitCode: EXIT_CODES.USAGE,
514
- });
515
- const capabilityType = flagValue('--capability-type');
516
- const capability = flagValue('--capability');
517
- const assignment = flagValue('--assignment');
518
- if (!capabilityType || !['agent', 'skill', 'rule', 'workflow'].includes(capabilityType))
519
- throw new AiwgError({
520
- code: 'ERR_USAGE_MISSING_VALUE',
521
- message: '--capability-type requires agent, skill, rule, or workflow.',
522
- exitCode: EXIT_CODES.USAGE,
523
- });
524
- if (!capability || !assignment)
525
- throw new AiwgError({
526
- code: 'ERR_USAGE_MISSING_VALUE',
527
- message: '--route requires both --capability <id> and --assignment <bounded text>.',
528
- exitCode: EXIT_CODES.USAGE,
529
- });
530
- const capabilityProvider = capabilityProviderId(provider);
531
- const providerCapabilities = capabilityProvider ? matrix.providers[capabilityProvider] : undefined;
532
- const launchMechanism = providerCapabilities?.native_features.tasks
533
- ? 'native-subagent'
534
- : providerCapabilities?.emulation.tasks === 'aiwg-mc' ? 'aiwg-mc' : 'manual';
535
- const premiumAuthorized = args.includes('--allow-premium');
536
- const { collectProviderInventory } = await import('../../providers/provider-inventory.js');
537
- const { resolveDynamicModelCatalog } = await import('../../models/model-discovery.js');
538
- const projectDir = ctx ? getProjectDir(ctx, ctx.args) : process.cwd();
539
- const requestedAiwgRoot = ctx?.frameworkRoot ?? process.cwd();
540
- const aiwgRoot = await access(join(requestedAiwgRoot, 'agentic/code/providers/model-catalog.v1.json')).then(() => requestedAiwgRoot).catch(() => process.cwd());
541
- const resolvedCapability = await resolveRoutableCapability(aiwgRoot, capabilityType, capability).catch(error => {
542
- if (!(error instanceof CapabilityResolutionError))
543
- throw error;
544
- throw new AiwgError({
545
- code: error.kind === 'ambiguous'
546
- ? 'ERR_USAGE_AMBIGUOUS_CAPABILITY'
547
- : 'ERR_USAGE_UNKNOWN_CAPABILITY',
548
- message: error.message,
549
- hint: 'Run aiwg discover "<capability>" --json and pass an exact name or stable id.',
550
- exitCode: EXIT_CODES.USAGE,
551
- });
552
- });
553
- const catalog = await resolveDynamicModelCatalog({
554
- aiwgRoot,
555
- inventory: await collectProviderInventory(projectDir),
556
- allowNetwork: false,
557
- });
558
- const baselineCatalog = loadProviderModelCatalog();
559
- const effectiveCatalog = {
560
- ...baselineCatalog,
561
- ...catalog,
562
- refreshedAt: catalog.refreshedAt ?? baselineCatalog.refreshedAt,
563
- staleAfterDays: baselineCatalog.staleAfterDays,
564
- providers: { ...baselineCatalog.providers, ...catalog.providers },
565
- };
566
- const envelope = buildWrapperRouteEnvelope({
567
- provider,
568
- capability: resolvedCapability,
569
- assignment,
570
- launchMechanism,
571
- deterministic: args.includes('--deterministic'),
572
- routine: args.includes('--routine'),
573
- complex: args.includes('--complex'),
574
- highImpact: args.includes('--high-impact'),
575
- requestedPremium: args.includes('--premium'),
576
- unattended: args.includes('--unattended'),
577
- premiumAuthorized,
578
- maxAutoTier: premiumAuthorized ? 3 : undefined,
579
- catalog: effectiveCatalog,
580
- });
581
- if (args.includes('--json'))
582
- console.log(JSON.stringify(envelope, null, 2));
583
- else {
584
- console.log('\n Model wrapper route');
585
- console.log(` Provider: ${envelope.provider}`);
586
- console.log(` Capability: ${envelope.capability.type} ${envelope.capability.name} (${envelope.capability.id})`);
587
- console.log(` Tier/role: ${envelope.tier ?? 'deterministic'}/${envelope.role ?? 'none'}`);
588
- console.log(` Wrapper: ${envelope.wrapper ?? 'none'}`);
589
- console.log(` Model: ${envelope.model?.effectiveModel ?? 'inherited or no model call'} (${envelope.model?.outcome ?? 'deterministic'})`);
590
- console.log(` Launch: ${envelope.launch.mechanism}`);
591
- console.log(` Confirmation: ${envelope.decision.requiresConfirmation ? 'required' : 'not required'}`);
592
- console.log('\n Wrapper prompt:\n');
593
- console.log(envelope.launch.prompt);
594
- }
595
- return;
596
- }
597
- const decision = routeModelTier({
598
- deterministic: args.includes('--deterministic'),
599
- routine: args.includes('--routine'),
600
- complex: args.includes('--complex'),
601
- highImpact: args.includes('--high-impact'),
602
- requestedPremium: args.includes('--premium'),
603
- unattended: args.includes('--unattended'),
604
- premiumAuthorized: args.includes('--allow-premium'),
605
- maxAutoTier: args.includes('--allow-premium') ? 3 : undefined,
606
- });
607
- console.log('\n Model policy routing');
608
- console.log(` Default stance: cheap-first role/tier intent, compiled per provider from the effective catalog.`);
609
- console.log(` Suggested tier: ${decision.tier}${decision.modelTier ? ` (${decision.modelTier})` : ' (no model call)'}`);
610
- console.log(` Confirmation: ${decision.requiresConfirmation ? 'required' : 'not required'}`);
611
- console.log(` Summary before escalation: ${decision.summaryRequired ? 'required' : 'not required'}`);
612
- console.log(` Rationale: ${decision.rationale.join('; ')}`);
613
- console.log('\n Commands:');
614
- console.log(' aiwg models sources --json # inspect effective cache/static/remote catalog provenance');
615
- console.log(' aiwg models refresh --json # refresh dynamic provider catalog where supported');
616
- console.log(' aiwg models audit --provider P # compile artifact policy and diagnostics');
617
- console.log(' aiwg models resolve --provider P # show selected provider model for matching artifacts');
618
- console.log('\n Authoring:');
619
- console.log(' Agents: use model-role/model-tier; avoid exact provider IDs in source scaffolds.');
620
- console.log(' Skills/commands: use commandHint.modelRole and commandHint.modelTier.');
621
- return;
622
- }
383
+ if (subcommand === 'models' || subcommand === 'model-routing')
384
+ return handleStewardModels(args, matrix, ctx);
623
385
  throw new AiwgError({
624
386
  code: 'ERR_USAGE_UNKNOWN_SUBCOMMAND',
625
387
  message: `Unknown steward subcommand: ${subcommand}`,
@@ -640,6 +402,10 @@ export const stewardHandler = {
640
402
  // sub-namespace help reachable, without executing anything (#2533).
641
403
  async help(ctx) {
642
404
  const positional = ctx.args.filter((arg) => !arg.startsWith('-'));
405
+ if (positional[0] === 'authorization') {
406
+ const { authorizationUsage } = await import('../../config/authorization-cli.js');
407
+ return { exitCode: 0, message: authorizationUsage, rawOutput: true };
408
+ }
643
409
  if (positional[0] === 'permissions') {
644
410
  return { exitCode: 0, message: permissionsUsage(), rawOutput: true };
645
411
  }
@@ -0,0 +1,61 @@
1
+ // Count bundle artifacts from native files and activation-selected rule receipts.
2
+ import { promises as fs } from 'node:fs';
3
+ import path from 'node:path';
4
+ export async function countDeployedBundleRules(bundlePath, target, deployPath) {
5
+ if (!deployPath)
6
+ return 0;
7
+ const destination = path.resolve(target, deployPath);
8
+ let selected = [];
9
+ try {
10
+ const receipt = JSON.parse(await fs.readFile(path.join(destination, '.aiwg-manifest.json'), 'utf8'));
11
+ selected = Array.isArray(receipt.ruleSources) ? receipt.ruleSources : [];
12
+ }
13
+ catch { /* Legacy deployments have only native files. */ }
14
+ let sources;
15
+ try {
16
+ sources = (await fs.readdir(path.join(bundlePath, 'rules'))).filter(name => name.endsWith('.md'));
17
+ }
18
+ catch {
19
+ return 0;
20
+ }
21
+ let count = 0;
22
+ for (const name of sources) {
23
+ if (selected.includes(path.resolve(bundlePath, 'rules', name))) {
24
+ count++;
25
+ continue;
26
+ }
27
+ for (const extension of ['.md', '.mdc']) {
28
+ try {
29
+ await fs.access(path.join(destination, path.basename(name, '.md') + extension));
30
+ count++;
31
+ break;
32
+ }
33
+ catch { /* A catalog-only, unselected rule is not deployed. */ }
34
+ }
35
+ }
36
+ return count;
37
+ }
38
+ export async function countDeployedBundleFiles(bundlePath, subdir, target, deployPath, extensions) {
39
+ if (!deployPath)
40
+ return 0;
41
+ let names;
42
+ try {
43
+ names = (await fs.readdir(path.join(bundlePath, subdir))).filter(name => name.endsWith('.md'));
44
+ }
45
+ catch {
46
+ return 0;
47
+ }
48
+ let count = 0;
49
+ for (const name of names) {
50
+ for (const extension of extensions) {
51
+ try {
52
+ await fs.access(path.join(path.resolve(target, deployPath), path.basename(name, '.md') + extension));
53
+ count++;
54
+ break;
55
+ }
56
+ catch { /* Only count artifacts actually written by this bundle. */ }
57
+ }
58
+ }
59
+ return count;
60
+ }
61
+ //# sourceMappingURL=use-bundle-counts.js.map