@aiwg/cli 2026.10.11 → 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 (132) hide show
  1. package/agentic/code/providers/model-catalog.v1.json +62 -12
  2. package/dist/src/artifacts/binding-target-identity.js +51 -0
  3. package/dist/src/artifacts/checksum-manifest.js +12 -0
  4. package/dist/src/artifacts/index-builder.js +11 -13
  5. package/dist/src/artifacts/query-engine.js +5 -11
  6. package/dist/src/cli/handlers/doctor-help.js +32 -0
  7. package/dist/src/cli/handlers/gates.js +19 -18
  8. package/dist/src/cli/handlers/models-help.js +7 -1
  9. package/dist/src/cli/handlers/models.js +3 -3
  10. package/dist/src/cli/handlers/script-runner.js +8 -5
  11. package/dist/src/cli/handlers/sessions-intake.js +104 -0
  12. package/dist/src/cli/handlers/sessions-tail.js +172 -0
  13. package/dist/src/cli/handlers/sessions.js +90 -17
  14. package/dist/src/cli/handlers/skill-lint.js +10 -3
  15. package/dist/src/cli/handlers/steward-format.js +100 -0
  16. package/dist/src/cli/handlers/steward-models.js +167 -0
  17. package/dist/src/cli/handlers/steward.js +14 -248
  18. package/dist/src/cli/handlers/use-bundle-counts.js +61 -0
  19. package/dist/src/cli/handlers/use.js +6 -24
  20. package/dist/src/cli/handlers/utilities.js +1 -24
  21. package/dist/src/config/aiwg-config.js +7 -0
  22. package/dist/src/config/authorization-cli.js +89 -0
  23. package/dist/src/config/cli-help.js +1 -0
  24. package/dist/src/config/cli.js +10 -1
  25. package/dist/src/decision/context-pruning.js +3 -2
  26. package/dist/src/decision/ensemble/contract.js +15 -4
  27. package/dist/src/decision/ensemble-study/artifacts.js +5 -0
  28. package/dist/src/decision/ensemble-study/score.js +4 -3
  29. package/dist/src/decision/feature-export.js +3 -9
  30. package/dist/src/decision/heldout/collector.js +2 -2
  31. package/dist/src/decision/issue-triage/runtime.js +3 -9
  32. package/dist/src/decision/qualification/gates.js +2 -1
  33. package/dist/src/decision/qualification/release.js +2 -3
  34. package/dist/src/decision/routing/report.js +2 -0
  35. package/dist/src/decision/sdlc-screening.js +3 -5
  36. package/dist/src/decision/sensitivity/comparative.js +5 -3
  37. package/dist/src/gates/driver.js +6 -77
  38. package/dist/src/gates/evaluate.js +4 -11
  39. package/dist/src/gates/floors.js +4 -4
  40. package/dist/src/gates/index.js +3 -3
  41. package/dist/src/gates/lattice.js +26 -0
  42. package/dist/src/gates/registry.js +2 -1
  43. package/dist/src/gates/report.js +19 -7
  44. package/dist/src/issues/audit-cli.js +120 -0
  45. package/dist/src/issues/audit-contract.js +64 -0
  46. package/dist/src/issues/audit-local.js +82 -0
  47. package/dist/src/issues/audit.js +220 -0
  48. package/dist/src/lint/rule-activation.js +15 -1
  49. package/dist/src/mission-protocol/canonical-codecs.js +270 -0
  50. package/dist/src/mission-protocol/codecs.js +22 -550
  51. package/dist/src/mission-protocol/health-trace-codecs.js +281 -0
  52. package/dist/src/mission-protocol/health-trace-types.js +43 -0
  53. package/dist/src/mission-protocol/types.js +2 -42
  54. package/dist/src/mission-protocol/worker-contract-json.js +10 -0
  55. package/dist/src/mission-protocol/worker-review-gate.js +100 -0
  56. package/dist/src/mission-protocol/worker-review-types.js +2 -0
  57. package/dist/src/models/catalog-policy.js +280 -0
  58. package/dist/src/models/index.js +1 -1
  59. package/dist/src/models/model-catalog.v1.json +62 -12
  60. package/dist/src/models/policy-resources.js +28 -0
  61. package/dist/src/models/provider-policy.js +10 -546
  62. package/dist/src/models/resolver.js +26 -8
  63. package/dist/src/models/router.js +15 -2
  64. package/dist/src/models/tiers.js +13 -0
  65. package/dist/src/models/types.js +0 -6
  66. package/dist/src/models/worker-ceilings.js +59 -0
  67. package/dist/src/models/worker-invocation-policy.js +243 -0
  68. package/dist/src/models/worker-plan.js +16 -20
  69. package/dist/src/models/worker-review-lineage.js +55 -0
  70. package/dist/src/models/worker-selection-policy.js +1 -1
  71. package/dist/src/models/wrapper-route.js +6 -3
  72. package/dist/src/policy/authorization.js +1 -0
  73. package/dist/src/policy/hitl-config.js +63 -0
  74. package/dist/src/policy/hitl-receipt.js +57 -0
  75. package/dist/src/policy/hitl-types.js +4 -0
  76. package/dist/src/policy/hitl-validation.js +39 -0
  77. package/dist/src/policy/hitl.js +117 -0
  78. package/dist/src/rules/activation.d.mts +1 -1
  79. package/dist/src/rules/activation.mjs +0 -2
  80. package/dist/src/rules/gate-coverage.js +51 -0
  81. package/dist/src/rules/gate-references.js +16 -0
  82. package/dist/src/rules/rule-frontmatter.schema.json +7 -1
  83. package/dist/src/serve/worker-command-request.js +21 -4
  84. package/dist/src/serve/worker-invocation-preparation.js +3 -1
  85. package/dist/src/serve/worker-invocation.js +21 -10
  86. package/dist/src/sessions/adapters/deepseek-harness.js +1 -0
  87. package/dist/src/sessions/adapters/grok-build-native.js +269 -0
  88. package/dist/src/sessions/adapters/grok-build.js +57 -15
  89. package/dist/src/sessions/adapters/hermes-state-db.js +252 -0
  90. package/dist/src/sessions/adapters/hermes.js +42 -3
  91. package/dist/src/sessions/adapters/warp.js +1 -1
  92. package/dist/src/sessions/batch-import.js +10 -0
  93. package/dist/src/sessions/contracts.js +1 -1
  94. package/dist/src/sessions/discovery-capability.js +38 -0
  95. package/dist/src/sessions/importer.js +8 -251
  96. package/dist/src/sessions/index.js +4 -0
  97. package/dist/src/sessions/intake-dir.js +71 -0
  98. package/dist/src/sessions/normalization.js +251 -0
  99. package/dist/src/sessions/tail.js +91 -0
  100. package/dist/src/sessions/workspace-discovery.js +83 -7
  101. package/dist/src/skills/agent-skill-sidecar.js +28 -0
  102. package/dist/src/skills/agent-skills.js +4 -23
  103. package/dist/src/skills/claude-surface-projection.js +25 -0
  104. package/dist/src/skills/deployer.js +8 -288
  105. package/dist/src/skills/deployment-policy.js +114 -0
  106. package/dist/src/skills/deployment-projection.js +152 -0
  107. package/dist/src/skills/deployment-types.js +20 -0
  108. package/dist/src/skills/exporter.js +8 -31
  109. package/dist/src/skills/provider-extensions.js +41 -0
  110. package/dist/src/skills/run.js +6 -0
  111. package/dist/src/skills/types.js +0 -8
  112. package/dist/src/skills/validator-resources.js +68 -0
  113. package/dist/src/skills/validator.js +6 -55
  114. package/dist/src/storage/cli-migrate-options.js +125 -0
  115. package/dist/src/storage/cli-migrate.js +111 -0
  116. package/dist/src/storage/cli.js +4 -279
  117. package/dist/src/storage/migration-adapter.js +79 -0
  118. package/dist/src/storage/migration-copy.js +108 -0
  119. package/dist/src/storage/migration-protocol.js +14 -197
  120. package/dist/src/storage/migration-records.js +186 -0
  121. package/dist/src/storage/migration-types.js +12 -0
  122. package/dist/src/tracker/forge-http.js +2 -1
  123. package/dist/src/tracker/issue-pages.js +110 -0
  124. package/package.json +1 -1
  125. package/schemas/mission-v1.schema.json +335 -0
  126. package/schemas/models/model-catalog.v1.schema.json +19 -1
  127. package/schemas/models/model-config-compatibility.v1.schema.json +3 -2
  128. package/schemas/models/model-policy.v1.schema.json +1 -1
  129. package/tools/agents/providers/provider-paths-staging.mjs +35 -0
  130. package/tools/agents/providers/rule-binding-targets.mjs +146 -0
  131. package/tools/agents/providers/rule-delivery.mjs +7 -126
  132. package/vscode-extension/schemas/aiwg.config.v1.json +177 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "../../../schemas/models/model-catalog.v1.schema.json",
3
3
  "version": "1.0.0",
4
- "refreshedAt": "2026-09-21",
4
+ "refreshedAt": "2026-10-27",
5
5
  "staleAfterDays": 90,
6
6
  "providers": {
7
7
  "antigravity": {
@@ -28,44 +28,94 @@
28
28
  "claude": {
29
29
  "roles": {
30
30
  "reasoning": {
31
- "id": "claude-opus-5",
31
+ "id": "claude-opus-5-5",
32
32
  "status": "active",
33
- "observed": false
33
+ "observed": true
34
34
  },
35
35
  "coding": {
36
- "id": "claude-sonnet-5",
36
+ "id": "claude-sonnet-5-5",
37
37
  "status": "active",
38
- "observed": false
38
+ "observed": true
39
39
  },
40
40
  "efficiency": {
41
- "id": "claude-haiku-4-5",
41
+ "id": "claude-haiku-5-5",
42
42
  "status": "active",
43
- "observed": false
43
+ "observed": true
44
44
  }
45
45
  },
46
46
  "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview",
47
- "verifiedAt": "2026-09-21"
47
+ "verifiedAt": "2026-10-27",
48
+ "tiers": {
49
+ "flagship": {
50
+ "id": "claude-fable-5-1",
51
+ "status": "active",
52
+ "observed": true,
53
+ "selection": "user-elected"
54
+ },
55
+ "premium": {
56
+ "id": "claude-opus-5-5",
57
+ "status": "active",
58
+ "observed": true
59
+ },
60
+ "standard": {
61
+ "id": "claude-sonnet-5-5",
62
+ "status": "active",
63
+ "observed": true
64
+ },
65
+ "economy": {
66
+ "id": "claude-haiku-5-5",
67
+ "status": "active",
68
+ "observed": true
69
+ }
70
+ },
71
+ "verified_at": "2026-10-27",
72
+ "evidence": "Conductor-verified Claude Code harness current model list, 2026-10-27."
48
73
  },
49
74
  "codex": {
50
75
  "roles": {
51
76
  "reasoning": {
52
- "id": "gpt-5.6-sol",
77
+ "id": "gpt-6.1-sol",
53
78
  "status": "active",
54
79
  "observed": true
55
80
  },
56
81
  "coding": {
57
- "id": "gpt-5.6-terra",
82
+ "id": "gpt-6.1-terra",
58
83
  "status": "active",
59
84
  "observed": true
60
85
  },
61
86
  "efficiency": {
62
- "id": "gpt-5.6-luna",
87
+ "id": "gpt-6-luna",
63
88
  "status": "active",
64
89
  "observed": true
65
90
  }
66
91
  },
67
92
  "sourceUrl": "https://learn.chatgpt.com/docs/models",
68
- "verifiedAt": "2026-09-21"
93
+ "verifiedAt": "2026-10-27",
94
+ "tiers": {
95
+ "flagship": {
96
+ "id": "gpt-6-astra",
97
+ "status": "active",
98
+ "observed": true,
99
+ "selection": "user-elected"
100
+ },
101
+ "premium": {
102
+ "id": "gpt-6.1-sol",
103
+ "status": "active",
104
+ "observed": true
105
+ },
106
+ "standard": {
107
+ "id": "gpt-6.1-terra",
108
+ "status": "active",
109
+ "observed": true
110
+ },
111
+ "economy": {
112
+ "id": "gpt-6-luna",
113
+ "status": "active",
114
+ "observed": true
115
+ }
116
+ },
117
+ "verified_at": "2026-10-27",
118
+ "evidence": "Conductor-verified Codex CLI local model cache on titan (codex-cli 0.165.0), plus ~/.cache/aiwg/model-catalog.v1.json, 2026-10-27; no network verification by this worker."
69
119
  },
70
120
  "copilot": {
71
121
  "roles": {
@@ -0,0 +1,51 @@
1
+ /** Resolve source aliases and bundle ownership before rule-target precedence. */
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ function realpath(file) {
5
+ try {
6
+ return fs.realpathSync(file);
7
+ }
8
+ catch {
9
+ return path.resolve(file);
10
+ }
11
+ }
12
+ function sourcePath(file, options) {
13
+ const normalized = file.replace(/\\/g, '/');
14
+ const anchor = normalized.startsWith('agentic/code/') ? options.packageRoot : options.cwd;
15
+ return path.resolve(anchor ?? process.cwd(), normalized);
16
+ }
17
+ function identity(file, options) {
18
+ const absolute = sourcePath(file, options);
19
+ // Realpath handles symlinks; the supplied mapping handles materialized copies.
20
+ return realpath(options.logicalPath?.(realpath(absolute)) ?? absolute);
21
+ }
22
+ function inside(root, file) {
23
+ const relative = path.relative(root, file);
24
+ return relative === '' || (!path.isAbsolute(relative) && relative !== '..' && !relative.startsWith(`..${path.sep}`));
25
+ }
26
+ export function selectBindingTargetIdentities(entries, options = {}) {
27
+ const bundle = options.bundleRoot && identity(options.bundleRoot, options);
28
+ const snapshot = options.bundleRoot && sourcePath(options.bundleRoot, options);
29
+ const preferred = bundle && snapshot ? entries.filter(entry => inside(snapshot, sourcePath(entry.path, options)) || inside(bundle, identity(entry.path, options))) : [];
30
+ const candidates = preferred.length ? preferred : entries;
31
+ const unique = new Map();
32
+ for (const entry of candidates) {
33
+ const key = `${entry.type}:${identity(entry.path, options)}`;
34
+ const previous = unique.get(key);
35
+ // The projector must receive the entry in the bundle's current snapshot.
36
+ const inSnapshot = snapshot && inside(snapshot, sourcePath(entry.path, options));
37
+ if (!previous || inSnapshot)
38
+ unique.set(key, entry);
39
+ }
40
+ return [...unique.values()];
41
+ }
42
+ /** Retain the existing preference for canonical sources over packaged mirrors. */
43
+ export function preferCanonicalBindingTargets(matches) {
44
+ if (matches.length > 1) {
45
+ const canonical = matches.filter(entry => !/(^|\/)agentic\/code\/plugins\//.test(entry.path.replace(/\\/g, '/')));
46
+ if (canonical.length === 1)
47
+ return canonical;
48
+ }
49
+ return matches;
50
+ }
51
+ //# sourceMappingURL=binding-target-identity.js.map
@@ -89,4 +89,16 @@ export function pruneManifest(manifest, cwd) {
89
89
  }
90
90
  return removed;
91
91
  }
92
+ /** Format change-detection diagnostics from the same counters returned to callers. */
93
+ export function formatManifestStats(stats) {
94
+ if (stats.checked === 0)
95
+ return [];
96
+ const messages = [
97
+ ` Change detection: ${stats.checked} checked, ${stats.statSkipped} skipped via stat, ${stats.checked - stats.statSkipped} content-read, ${stats.reindexed} re-indexed`,
98
+ ];
99
+ if (stats.pruned > 0) {
100
+ messages.push(` Pruned ${stats.pruned} stale manifest entries (files no longer on disk)`);
101
+ }
102
+ return messages;
103
+ }
92
104
  //# sourceMappingURL=checksum-manifest.js.map
@@ -19,7 +19,7 @@ import { validateGateDocument } from '../gates/schema.js';
19
19
  import { INDEX_EXTRACTOR_VERSION, INDEX_VERSION, INDEX_DIR, OPERATIONAL_DISCOVERY_TYPES, PHASE_DIRECTORIES, GRAPH_CONFIGS, TEMPLATE_INDEX_EXTENSIONS, resolveGraphScanDir, loadUserGraphConfigs, loadGlobalGraphConfigs, resolveGraphBackendType, } from './types.js';
20
20
  import { parseCitationSidecar, citationResultToEdges, buildRefToPathMap } from './citation-parser.js';
21
21
  import { writeIndexFile, resolveIndexDir, loadGraphIndexFile, publishIndexFiles } from './index-reader.js';
22
- import { loadManifest, writeManifest, statMatches, makeEntry } from './checksum-manifest.js';
22
+ import { loadManifest, writeManifest, statMatches, makeEntry, formatManifestStats } from './checksum-manifest.js';
23
23
  import { FRAMEWORK_RELATIONS_REVISION } from './framework-source-digest.js';
24
24
  import { normalizeOperationalState } from './operational-state.js';
25
25
  import { DEFAULT_PROJECT_AIWG_DIR, resolveProjectAiwgDir, } from '../config/project-artifacts.js';
@@ -963,6 +963,7 @@ function extractIndexArtifact(job, bindingOnly, warnings = []) {
963
963
  };
964
964
  return { checksum, entry };
965
965
  }
966
+ /** Return change-detection counts for artifact builds; skipped/source builds return void. */
966
967
  export async function buildIndex(cwd, options = {}) {
967
968
  loadUserGraphConfigs(cwd);
968
969
  loadGlobalGraphConfigs();
@@ -993,7 +994,7 @@ export async function buildIndex(cwd, options = {}) {
993
994
  fs.mkdirSync(directory, { recursive: true });
994
995
  return staging ??= fs.mkdtempSync(path.join(directory, '.build-'));
995
996
  };
996
- await buildIndexSnapshot(cwd, options, preparePublication, owned ? observation : undefined);
997
+ const stats = await buildIndexSnapshot(cwd, options, preparePublication, owned ? observation : undefined);
997
998
  // A receipt hit verifies the existing snapshot directly against the scan's
998
999
  // stats. There is no extraction interval to recheck. Real builds still probe
999
1000
  // again after preparation so concurrent source changes remain pending.
@@ -1004,6 +1005,7 @@ export async function buildIndex(cwd, options = {}) {
1004
1005
  recordIndexVerification(owned, cwd, { before: observation.before, after, wallMs: Date.now() - start }, staging);
1005
1006
  if (staging)
1006
1007
  publishIndexFiles(staging, directory);
1008
+ return stats;
1007
1009
  }
1008
1010
  catch (error) {
1009
1011
  if (owned) {
@@ -1141,14 +1143,9 @@ async function buildIndexSnapshot(cwd, options, preparePublication, observation)
1141
1143
  log(`Artifact index built in ${buildTimeMs}ms`);
1142
1144
  log(` Indexed ${newCount} new, updated ${updatedCount}, unchanged ${unchangedCount}`);
1143
1145
  log(` Total: ${total} artifacts`);
1144
- if (!force && manifestStats.checked > 0) {
1145
- const fastPath = manifestStats.statSkipped;
1146
- const slowPath = manifestStats.checked - manifestStats.statSkipped;
1147
- log(` Change detection: ${manifestStats.checked} checked, ${fastPath} skipped via stat, ${slowPath} content-read, ${manifestStats.reindexed} re-indexed`);
1148
- if (manifestStats.pruned > 0) {
1149
- log(` Pruned ${manifestStats.pruned} stale manifest entries (files no longer on disk)`);
1150
- }
1151
- }
1146
+ if (!force)
1147
+ for (const message of formatManifestStats(manifestStats))
1148
+ log(message);
1152
1149
  const displayDir = graph ? indexOutputDir : `${INDEX_DIR}/`;
1153
1150
  log(` Output: ${displayDir}`);
1154
1151
  };
@@ -1211,7 +1208,7 @@ async function buildIndexSnapshot(cwd, options, preparePublication, observation)
1211
1208
  if (observation)
1212
1209
  observation.unchanged = true;
1213
1210
  reportBuild(buildTimeMs, files.length);
1214
- return;
1211
+ return manifestStats;
1215
1212
  }
1216
1213
  }
1217
1214
  const publicationDir = preparePublication();
@@ -1245,6 +1242,7 @@ async function buildIndexSnapshot(cwd, options, preparePublication, observation)
1245
1242
  ...(!force && existingEntries[relativePath] ? { existingChecksum: existingEntries[relativePath].checksum } : {}) });
1246
1243
  }
1247
1244
  const preparation = await runIndexPreparation(jobs, prepareIndexArtifact, import.meta.url, workers, options.onDiagnostic ?? (message => console.warn(`Index preparation: ${message}`)));
1245
+ manifestStats.reindexed = preparation.results.filter(result => result.entry !== undefined).length;
1248
1246
  for (const result of preparation.results)
1249
1247
  for (const warning of result.warnings ?? []) {
1250
1248
  (options.onDiagnostic ?? (message => console.warn(`Index preparation: ${message}`)))(warning);
@@ -1313,7 +1311,6 @@ async function buildIndexSnapshot(cwd, options, preparePublication, observation)
1313
1311
  log(` unchanged (checksum): ${relativePath}`);
1314
1312
  continue;
1315
1313
  }
1316
- manifestStats.reindexed++;
1317
1314
  nextManifestEntries[relativePath] = makeEntry(checksum, stat);
1318
1315
  entry = prepared.entry;
1319
1316
  }
@@ -1363,7 +1360,7 @@ async function buildIndexSnapshot(cwd, options, preparePublication, observation)
1363
1360
  if (manifestStats.checksumSkipped > 0 || projectionNeedsRepair)
1364
1361
  writeBuildManifest(nextManifestEntries);
1365
1362
  reportBuild(buildTimeMs, total);
1366
- return;
1363
+ return manifestStats;
1367
1364
  }
1368
1365
  }
1369
1366
  // Apply metadata supplements if configured (enriches filename-metadata nodes from sidecars)
@@ -1563,5 +1560,6 @@ async function buildIndexSnapshot(cwd, options, preparePublication, observation)
1563
1560
  writeBuildManifest(nextManifestEntries);
1564
1561
  // Report
1565
1562
  reportBuild(buildTimeMs, total);
1563
+ return manifestStats;
1566
1564
  }
1567
1565
  //# sourceMappingURL=index-builder.js.map
@@ -12,6 +12,7 @@ import { refreshFrameworkCapabilities, resolveFrameworkCorpusRoot, isCorpusBundl
12
12
  import { resolveFrameworkIndexRoot } from './framework-index-paths.js';
13
13
  import { ensureRelations, selectPrebuiltRelations, emptyRuleStats } from './relations.js';
14
14
  import { minimatch } from 'minimatch';
15
+ import { selectBindingTargetIdentities, preferCanonicalBindingTargets } from './binding-target-identity.js';
15
16
  import { inferRuleActivation } from '../rules/activation.mjs';
16
17
  import * as fs from 'node:fs';
17
18
  import * as path from 'node:path';
@@ -1624,7 +1625,7 @@ function findShowMatches(entries, types, needle) {
1624
1625
  return matches;
1625
1626
  }
1626
1627
  /** Preselect exact candidates once; the canonical resolver still owns precedence and ambiguity. */
1627
- export function createRuleBindingTargetResolver(entries) {
1628
+ export function createRuleBindingTargetResolver(entries, options = {}) {
1628
1629
  const candidates = new Map();
1629
1630
  for (const entry of entries) {
1630
1631
  if (!['skill', 'agent', 'flow'].includes(entry.type))
@@ -1643,13 +1644,13 @@ export function createRuleBindingTargetResolver(entries) {
1643
1644
  candidates.set(key, selected);
1644
1645
  }
1645
1646
  }
1646
- return (type, id) => resolveRuleBindingTarget(candidates.get(`${type}\0${id}`) ?? [], type, id);
1647
+ return (type, id, bundleRoot = options.bundleRoot) => resolveRuleBindingTarget(candidates.get(`${type}\0${id}`) ?? [], type, id, { ...options, bundleRoot });
1647
1648
  }
1648
1649
  /** Resolve exact rule binding IDs using the same precedence and ambiguity as show.
1649
1650
  * Canonical layout slugs remain valid when frontmatter names are display names.
1650
1651
  * Titles and filesystem paths are deliberately excluded (#2938).
1651
1652
  */
1652
- export function resolveRuleBindingTarget(entries, type, id) {
1653
+ export function resolveRuleBindingTarget(entries, type, id, options = {}) {
1653
1654
  const exact = entries.filter(entry => {
1654
1655
  if (entry.type !== type)
1655
1656
  return false;
@@ -1660,14 +1661,7 @@ export function resolveRuleBindingTarget(entries, type, id) {
1660
1661
  : basename.replace(/\.[^.]+$/, '');
1661
1662
  return entry.name === id || discoveryIdForEntry(entry) === id || slug === id;
1662
1663
  });
1663
- let matches = findShowMatches(exact, [type], id);
1664
- // Generated plugin copies (agentic/code/plugins/*) mirror canonical framework
1665
- // and addon artifacts. Prefer the canonical source when it is unambiguous.
1666
- if (matches.length > 1) {
1667
- const canonical = matches.filter(entry => !/(^|\/)agentic\/code\/plugins\//.test(normalizeIndexedPath(entry.path)));
1668
- if (canonical.length === 1)
1669
- matches = canonical;
1670
- }
1664
+ const matches = preferCanonicalBindingTargets(findShowMatches(selectBindingTargetIdentities(exact, options), [type], id));
1671
1665
  if (matches.length === 0)
1672
1666
  throw new Error(`Missing ${type} binding target: ${id}`);
1673
1667
  if (matches.length > 1)
@@ -0,0 +1,32 @@
1
+ // Public doctor options and exit-status contract.
2
+ export const DOCTOR_HELP = `aiwg doctor — check AIWG installation health
3
+
4
+ Usage:
5
+ aiwg doctor [options]
6
+ aiwg -doctor [options]
7
+ aiwg --doctor [options]
8
+
9
+ Options:
10
+ --deployment Verify configured provider deployments
11
+ --provider <name> Limit deployment verification to one provider
12
+ --bundle <name> Limit deployment verification to one bundle
13
+ --scope <scope> Verification scope: project or user
14
+ --user Alias for --scope user
15
+ --qualify With --probe-workers, record installation and configured model/role approval
16
+ --yes Confirm worker qualification without a terminal
17
+ --dry-run With --probe-workers, preview qualification without writes
18
+ --cli NAME Limit worker probes/qualification to one configured CLI
19
+ --decision-offload Show offline advisory decision readiness and adoption report
20
+ --probe-workers Run bounded worker CLI version probes (default: config-only, no subprocess)
21
+ --project-local Include project-local artifact diagnostics
22
+ --json Emit machine-readable output (with --probe-workers: one worker-probe record per CLI; with --deployment: deployment verification; with --decision-offload: offline snapshot)
23
+ --verbose, -v Include verbose diagnostics
24
+ --help, -h Show this help
25
+
26
+ Exit status:
27
+ 0 Checks completed; ordinary doctor warnings are advisory.
28
+ 1 Diagnostic errors, failed or partial explicit worker qualification, or blocked recorded invocations.
29
+ 2 Invalid usage.
30
+ --qualify uses the same exit status in text and JSON output.
31
+ `;
32
+ //# sourceMappingURL=doctor-help.js.map
@@ -3,13 +3,14 @@ function jsonResult(value, exitCode = 0) {
3
3
  }
4
4
  function usage() {
5
5
  return [
6
- 'Usage: aiwg gates <validate|evaluate|show|list> [options]',
6
+ 'Usage: aiwg gates <validate|evaluate|show|list|coverage> [options]',
7
7
  '',
8
8
  'Commands:',
9
9
  ' validate <pack|binding|report> <path> [--pack-dir <dir>] [--aiwg-root <dir>]',
10
10
  ' evaluate --binding <file> --metrics <file> --holdout <file> [--upstream <file>] --now <iso> --trusted-binding-digest <sha256> [--pack-dir <dir>] [--aiwg-root <dir>]',
11
11
  ' show <id> [--pack-dir <dir>] [--aiwg-root <dir>]',
12
12
  ' list [--namespace <ns>] [--rule [<rule-id>]] [--pack-dir <dir>] [--aiwg-root <dir>]',
13
+ ' coverage [--rule <rule-id>] [--json] [--pack-dir <dir>] [--aiwg-root <dir>]',
13
14
  '',
14
15
  'Packs live in <bundle>/gate-packs/*.gatepack.yaml|json and register as',
15
16
  'aiwg:<bundle>/<name> (shipped).',
@@ -77,7 +78,7 @@ async function executeGates(ctx) {
77
78
  try {
78
79
  if (!command || command === '--help' || command === '-h')
79
80
  return { exitCode: 0, message: usage(), rawOutput: true };
80
- const { validateGateFile, evaluateGatesFromFiles, showGatePack, listGatePacks, packsReferencedByRule, } = await import('../../gates/driver.js');
81
+ const { validateGateFile, evaluateGatesFromFiles, showGatePack, listGatePacks, } = await import('../../gates/driver.js');
81
82
  const options = driverOptions(ctx);
82
83
  if (command === 'validate') {
83
84
  const args = positionals(ctx.args, 'validate');
@@ -115,27 +116,27 @@ async function executeGates(ctx) {
115
116
  return { exitCode: 2, message: `gates show requires <id>\n\n${usage()}`, rawOutput: true };
116
117
  return jsonResult(showGatePack(id, options), 0);
117
118
  }
118
- if (command === 'list') {
119
+ if (command === 'coverage' || command === 'list' && ctx.args.includes('--rule')) {
120
+ const { listRuleGateCoverage, formatRuleGateCoverage } = await import('../../rules/gate-coverage.js');
121
+ const value = takeOption(ctx.args, '--rule');
122
+ const rule = value && !value.startsWith('-') ? value : undefined;
123
+ const rules = listRuleGateCoverage(options, rule);
124
+ if (command === 'coverage') {
125
+ return ctx.args.includes('--json') ? jsonResult({ schema: 'aiwg-gates-coverage/v1', rules })
126
+ : { exitCode: 0, message: formatRuleGateCoverage(rules), rawOutput: true };
127
+ }
119
128
  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
129
  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));
130
+ const referenced = new Set(rules.flatMap(item => item.enforcedBy.map(reference => reference.split('#')[0])));
133
131
  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.' },
132
+ schema: 'aiwg-gates-list/v1', ...(rule ? { rule } : {}), rules,
133
+ packs: rule ? packs.filter(pack => referenced.has(pack.id)) : packs,
137
134
  }, 0);
138
135
  }
136
+ if (command === 'list') {
137
+ const namespace = takeOption(ctx.args, '--namespace');
138
+ return jsonResult({ schema: 'aiwg-gates-list/v1', packs: listGatePacks({ ...options, ...(namespace ? { namespace } : {}) }) });
139
+ }
139
140
  return { exitCode: 2, message: usage(), rawOutput: true };
140
141
  }
141
142
  catch (error) {
@@ -27,7 +27,7 @@ Artifact selectors and options:
27
27
  --drift Include catalog drift for sources/refresh
28
28
  --url <url> Remote catalog URL for refresh
29
29
  --help, -h Show this reference
30
- TIER: economy | standard | premium | max-quality
30
+ TIER: economy | standard | premium | flagship (alias: max-quality)
31
31
 
32
32
  Direct worker resolution (plans an invocation; does not launch it):
33
33
  aiwg models resolve --role <role> --task <class> --group <group>
@@ -43,6 +43,12 @@ Direct worker resolution (plans an invocation; does not launch it):
43
43
  --transport Must match group execution transport (default: shell)
44
44
  --format JSON plan or POSIX shell command (default: json)
45
45
  --json Alias for --format json
46
+ --max-attempts <count> Tighten total attempts, including the initial attempt
47
+ --timeout-ms <ms> Tighten the hard stop; positive multiple of 1000 (whole seconds)
48
+ --max-output-tokens <count> Tighten the existing task token budget (tokens)
49
+ --max-usd <amount> Tighten the task cost ceiling (costUsd)
50
+ Limits may only tighten resolved policy; larger values fail
51
+ JSON includes ceilings and their origins
46
52
  --authorize-premium Authorize premium for this resolution only
47
53
  Agents require explicit human confirmation of escalation
48
54
 
@@ -144,7 +144,7 @@ async function resolveDirect(ctx, services) {
144
144
  return { exitCode: 2 };
145
145
  }
146
146
  }
147
- const TIERS = new Set(['economy', 'standard', 'premium', 'max-quality']);
147
+ const TIERS = new Set(['economy', 'standard', 'premium', 'flagship', 'max-quality']);
148
148
  const PROVIDERS = new Set(Object.keys(loadProviderModelCapabilities().providers));
149
149
  function parseArgs(args) {
150
150
  const [subcommand = 'help', ...rest] = args;
@@ -241,7 +241,7 @@ function select(artifacts, parsed, useTierSelector = true) {
241
241
  && (!framework || item.framework === framework)));
242
242
  }
243
243
  function normalizedTier(tier) {
244
- return tier === 'max-quality' ? 'premium' : tier ?? 'standard';
244
+ return tier === 'max-quality' ? 'flagship' : tier ?? 'standard';
245
245
  }
246
246
  function resolved(item, provider, catalog) {
247
247
  const policy = {
@@ -331,7 +331,7 @@ async function execute(ctx, services = { load: loadWorkerInputs }) {
331
331
  return { exitCode: 0 };
332
332
  }
333
333
  // Preserve artifact/native resolve when direct-only flags are absent.
334
- if (ctx.args[0] === 'resolve' && ctx.args.slice(1).some(arg => /^--(?:task|group|brief|workdir|final-output|transport|format|authorize-premium)(?:=|$)/.test(arg))) {
334
+ if (ctx.args[0] === 'resolve' && ctx.args.slice(1).some(arg => /^--(?:task|group|brief|workdir|final-output|transport|format|authorize-premium|max-attempts|timeout-ms|max-output-tokens|max-usd)(?:=|$)/.test(arg))) {
335
335
  return resolveDirect(ctx, services);
336
336
  }
337
337
  if (await handleWorkerAdoptionArgs(ctx.args, ctx.cwd, 'models', ctx.signal, ctx.dryRun))
@@ -120,11 +120,13 @@ export class DefaultScriptRunner {
120
120
  clearTimeout(timeoutId);
121
121
  if (killEscalationId)
122
122
  clearTimeout(killEscalationId);
123
- // On failure in capture mode, surface the captured stderr
124
- if (options.capture && code !== 0 && capturedStderrBytes > 0) {
123
+ // On failure in capture mode, surface the captured stderr. Every
124
+ // failure carries a message so callers never print an empty ERROR.
125
+ if (options.capture && code !== 0) {
126
+ const stderr = Buffer.concat(capturedStderr).toString().trim();
125
127
  resolve({
126
128
  exitCode: code ?? 1,
127
- message: Buffer.concat(capturedStderr).toString().trim(),
129
+ message: stderr || `Script exited with code ${code ?? 1}: ${path.basename(fullPath)}`,
128
130
  });
129
131
  }
130
132
  else {
@@ -183,8 +185,9 @@ export class DefaultScriptRunner {
183
185
  // the runner still supports arbitrary scripts via its subprocess path.
184
186
  const deployer = await import(pathToFileURL(fullPath).href);
185
187
  const exitCode = (await deployer.main(args, { capture: options.capture === true })) ?? 0;
186
- const message = Buffer.concat(diagnostics).toString().trim();
187
- return exitCode && message ? { exitCode, message } : { exitCode };
188
+ const message = Buffer.concat(diagnostics).toString().trim()
189
+ || (exitCode ? `Deployment script exited with code ${exitCode}: ${path.basename(fullPath)}` : '');
190
+ return exitCode || message ? { exitCode, message } : { exitCode };
188
191
  }
189
192
  catch (error) {
190
193
  const message = Buffer.concat(diagnostics).toString().trim()
@@ -0,0 +1,104 @@
1
+ // `aiwg sessions import --from-dir`: idempotent intake-directory batch import (#3168).
2
+ import { join } from 'node:path';
3
+ import { fingerprintSourceFile, intakeSourceId, isRecognisedIntakeFile, listIntakeDirFiles, summarizeIntakeReceipts, INTAKE_DIR_SCHEMA_VERSION, } from '../../sessions/index.js';
4
+ export async function importFromDir(ctx, args, dir, deps) {
5
+ const { assertSupportedImportProvider, normalizeWorkspaceId, isDryRun, preview, ok, openRepository, adapterVersionFor, importSource, importFailureReason, } = deps;
6
+ const provider = assertSupportedImportProvider(args.values.get('--provider') ?? 'generic');
7
+ const workspaceId = args.values.has('--workspace')
8
+ ? normalizeWorkspaceId(ctx.cwd, args.values.get('--workspace'))
9
+ : 'default';
10
+ const prefix = args.values.get('--source-id');
11
+ const files = await listIntakeDirFiles(dir);
12
+ if (isDryRun(ctx, args)) {
13
+ return preview('import', {
14
+ fromDir: dir,
15
+ provider,
16
+ workspaceId,
17
+ sourceIdPrefix: prefix ?? null,
18
+ files: files.map((file) => {
19
+ const recognition = isRecognisedIntakeFile(provider, file);
20
+ return {
21
+ file,
22
+ sourceId: recognition.recognised ? intakeSourceId(prefix, file) : null,
23
+ recognised: recognition.recognised,
24
+ reason: recognition.reason ?? null,
25
+ };
26
+ }),
27
+ wouldPersist: false,
28
+ });
29
+ }
30
+ const repository = openRepository(ctx, args);
31
+ try {
32
+ const interrupted = new Map();
33
+ const receipts = [];
34
+ for (const file of files) {
35
+ const recognition = isRecognisedIntakeFile(provider, file);
36
+ const input = join(dir, file);
37
+ if (!recognition.recognised) {
38
+ receipts.push({
39
+ file, sourceId: null, digest: null, status: 'skipped',
40
+ reason: recognition.reason ?? 'unrecognised file', sessionsInserted: 0, eventsInserted: 0,
41
+ });
42
+ continue;
43
+ }
44
+ const sourceId = intakeSourceId(prefix, file);
45
+ let digest = null;
46
+ try {
47
+ const fingerprint = await fingerprintSourceFile({ selectedPath: input, allowedRoots: [dir] });
48
+ digest = fingerprint.digest;
49
+ const checkpoint = repository.getCheckpoint(sourceId, adapterVersionFor(provider));
50
+ if (checkpoint?.prefixDigest === digest && checkpoint.sourceSize === fingerprint.size) {
51
+ receipts.push({
52
+ file, sourceId, digest, status: 'already-imported',
53
+ reason: 'content digest already imported', sessionsInserted: 0, eventsInserted: 0,
54
+ });
55
+ continue;
56
+ }
57
+ }
58
+ catch (error) {
59
+ receipts.push({
60
+ file, sourceId, digest, status: 'rejected',
61
+ reason: importFailureReason(error), sessionsInserted: 0, eventsInserted: 0,
62
+ });
63
+ continue;
64
+ }
65
+ const fileValues = new Map(args.values);
66
+ fileValues.delete('--from-dir');
67
+ fileValues.set('--source-id', sourceId);
68
+ try {
69
+ const result = await importSource(ctx, {
70
+ command: 'import', positionals: [input], flags: new Set(args.flags),
71
+ values: fileValues, codexRoots: args.codexRoots, exclude: args.exclude,
72
+ });
73
+ const data = result.envelope.data;
74
+ for (const run of data.interruptedRuns ?? [])
75
+ interrupted.set(run.runId, run);
76
+ receipts.push({
77
+ file, sourceId, digest, status: 'imported', reason: null,
78
+ sessionsInserted: data.totals?.sessionsInserted ?? 0,
79
+ eventsInserted: data.totals?.eventsInserted ?? 0,
80
+ });
81
+ }
82
+ catch (error) {
83
+ receipts.push({
84
+ file, sourceId, digest, status: 'rejected',
85
+ reason: importFailureReason(error), sessionsInserted: 0, eventsInserted: 0,
86
+ });
87
+ }
88
+ }
89
+ return ok('import', {
90
+ fromDir: dir,
91
+ provider,
92
+ workspaceId,
93
+ sourceIdPrefix: prefix ?? null,
94
+ schemaVersion: INTAKE_DIR_SCHEMA_VERSION,
95
+ files: receipts,
96
+ summary: summarizeIntakeReceipts(receipts),
97
+ interruptedRuns: [...interrupted.values()],
98
+ });
99
+ }
100
+ finally {
101
+ repository.close();
102
+ }
103
+ }
104
+ //# sourceMappingURL=sessions-intake.js.map