@aiwg/cli 2026.9.19 → 2026.9.21

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 (272) hide show
  1. package/agentic/code/providers/capability-matrix.yaml +58 -6
  2. package/agentic/code/providers/model-capabilities.v1.json +34 -0
  3. package/agentic/code/providers/model-catalog.v1.json +55 -13
  4. package/bin/aiwg.mjs +2 -0
  5. package/dist/src/api/index.d.ts +1 -0
  6. package/dist/src/api/index.js +1 -0
  7. package/dist/src/artifacts/enrichment/cli.js +1 -1
  8. package/dist/src/artifacts/views/cli.js +1 -1
  9. package/dist/src/audit/operator-decision.js +10 -0
  10. package/dist/src/auth/credential-store.js +127 -27
  11. package/dist/src/catalog/builtin-models.json +272 -40
  12. package/dist/src/catalog/cli.js +1 -1
  13. package/dist/src/catalog/cli.mjs +1 -1
  14. package/dist/src/cli/handlers/effect.js +872 -0
  15. package/dist/src/cli/handlers/help.js +2 -0
  16. package/dist/src/cli/handlers/index.js +4 -2
  17. package/dist/src/cli/handlers/models.js +41 -10
  18. package/dist/src/cli/handlers/ralph.js +1 -1
  19. package/dist/src/cli/handlers/sessions.js +113 -37
  20. package/dist/src/cli/handlers/subcommands.js +31 -0
  21. package/dist/src/cli/handlers/use.js +46 -9
  22. package/dist/src/cli/handlers/utilities.js +10 -0
  23. package/dist/src/cli/handlers/workspace.js +3 -1
  24. package/dist/src/cli/scope-resolver.js +112 -9
  25. package/dist/src/cli/services/deployment-verification.js +5 -0
  26. package/dist/src/config/aiwg-config.js +3 -0
  27. package/dist/src/decision/acceptance-rollout.js +93 -0
  28. package/dist/src/decision/acceptance.js +175 -0
  29. package/dist/src/decision/adapters/jev.js +234 -13
  30. package/dist/src/decision/adapters/llm-subagent.js +60 -12
  31. package/dist/src/decision/admission.js +550 -0
  32. package/dist/src/decision/batch-benchmark.js +47 -0
  33. package/dist/src/decision/batch-receipts/accounting.js +75 -0
  34. package/dist/src/decision/batch-receipts/export.js +40 -0
  35. package/dist/src/decision/batch-receipts/index.js +9 -0
  36. package/dist/src/decision/batch-receipts/protection.js +40 -0
  37. package/dist/src/decision/batch-receipts/receipt.js +44 -0
  38. package/dist/src/decision/batch-receipts/result-store.js +341 -0
  39. package/dist/src/decision/batch-receipts/store.js +362 -0
  40. package/dist/src/decision/batch-receipts/types.js +2 -0
  41. package/dist/src/decision/batch-receipts/validate.js +127 -0
  42. package/dist/src/decision/batch.js +68 -0
  43. package/dist/src/decision/calibration/index.js +4 -0
  44. package/dist/src/decision/calibration/receipts.js +130 -0
  45. package/dist/src/decision/calibration/registry.js +258 -0
  46. package/dist/src/decision/calibration/types.js +2 -0
  47. package/dist/src/decision/compile-cache/benchmark.js +62 -0
  48. package/dist/src/decision/compile-cache/compatibility.js +65 -0
  49. package/dist/src/decision/compile-cache/file-store.js +280 -0
  50. package/dist/src/decision/compile-cache/identity.js +26 -0
  51. package/dist/src/decision/compile-cache/index.js +9 -0
  52. package/dist/src/decision/compile-cache/prefix.js +21 -0
  53. package/dist/src/decision/compile-cache/records.js +86 -0
  54. package/dist/src/decision/compile-cache/runtime.js +68 -0
  55. package/dist/src/decision/compile-cache/store.js +108 -0
  56. package/dist/src/decision/compile-cache/types.js +2 -0
  57. package/dist/src/decision/context-plan.js +234 -0
  58. package/dist/src/decision/context-qualification.js +60 -0
  59. package/dist/src/decision/ensemble/aggregate.js +215 -0
  60. package/dist/src/decision/ensemble/contract.js +316 -0
  61. package/dist/src/decision/ensemble/drift.js +51 -0
  62. package/dist/src/decision/ensemble/index.js +6 -0
  63. package/dist/src/decision/ensemble/report.js +71 -0
  64. package/dist/src/decision/ensemble/types.js +2 -0
  65. package/dist/src/decision/evaluate.js +1024 -78
  66. package/dist/src/decision/file-lifecycle-store.js +168 -0
  67. package/dist/src/decision/graph-beam.js +40 -0
  68. package/dist/src/decision/graph-budget.js +110 -0
  69. package/dist/src/decision/graph-decision-bridge.js +93 -0
  70. package/dist/src/decision/graph-evidence.js +123 -0
  71. package/dist/src/decision/graph-flow-adapter.js +56 -0
  72. package/dist/src/decision/graph-flow.js +105 -0
  73. package/dist/src/decision/graph-parallel.js +79 -0
  74. package/dist/src/decision/graph-patterns.js +20 -0
  75. package/dist/src/decision/graph-run-store.js +66 -0
  76. package/dist/src/decision/graph-run.js +166 -0
  77. package/dist/src/decision/graph-skill-bridge.js +91 -0
  78. package/dist/src/decision/graph-templates.js +56 -0
  79. package/dist/src/decision/graph.js +115 -0
  80. package/dist/src/decision/index.js +35 -0
  81. package/dist/src/decision/job-accounting.js +93 -0
  82. package/dist/src/decision/job-contract.js +186 -0
  83. package/dist/src/decision/job-effects.js +95 -0
  84. package/dist/src/decision/job-evaluate.js +80 -0
  85. package/dist/src/decision/job-gateway.js +121 -0
  86. package/dist/src/decision/job-http.js +194 -0
  87. package/dist/src/decision/job-payload-store.js +258 -0
  88. package/dist/src/decision/job-poll-limiter.js +92 -0
  89. package/dist/src/decision/job-quota.js +158 -0
  90. package/dist/src/decision/job-runtime.js +240 -0
  91. package/dist/src/decision/job-scheduler.js +26 -0
  92. package/dist/src/decision/job-service.js +117 -0
  93. package/dist/src/decision/job-store.js +264 -0
  94. package/dist/src/decision/job-worker.js +141 -0
  95. package/dist/src/decision/lifecycle.js +148 -0
  96. package/dist/src/decision/patterns/artifacts.js +173 -0
  97. package/dist/src/decision/patterns/catalog.js +108 -0
  98. package/dist/src/decision/patterns/durable-review.js +237 -0
  99. package/dist/src/decision/patterns/index.js +8 -0
  100. package/dist/src/decision/patterns/playground.js +401 -0
  101. package/dist/src/decision/patterns/recorded.js +43 -0
  102. package/dist/src/decision/patterns/specs.js +174 -0
  103. package/dist/src/decision/patterns/types.js +2 -0
  104. package/dist/src/decision/portable-secrets.js +53 -0
  105. package/dist/src/decision/projection.js +210 -0
  106. package/dist/src/decision/qualification/capture.js +67 -0
  107. package/dist/src/decision/qualification/drift.js +68 -0
  108. package/dist/src/decision/qualification/gate-evidence.js +172 -0
  109. package/dist/src/decision/qualification/gates.js +83 -0
  110. package/dist/src/decision/qualification/index.js +12 -0
  111. package/dist/src/decision/qualification/load.js +275 -0
  112. package/dist/src/decision/qualification/manifest.js +37 -0
  113. package/dist/src/decision/qualification/privacy.js +41 -0
  114. package/dist/src/decision/qualification/quality.js +213 -0
  115. package/dist/src/decision/qualification/release.js +116 -0
  116. package/dist/src/decision/qualification/runner.js +408 -0
  117. package/dist/src/decision/qualification/types.js +2 -0
  118. package/dist/src/decision/receipts.js +30 -7
  119. package/dist/src/decision/result-cache/index.js +6 -0
  120. package/dist/src/decision/result-cache/integrity.js +28 -0
  121. package/dist/src/decision/result-cache/key.js +28 -0
  122. package/dist/src/decision/result-cache/service.js +92 -0
  123. package/dist/src/decision/result-cache/store.js +327 -0
  124. package/dist/src/decision/result-cache/types.js +3 -0
  125. package/dist/src/decision/review/authorization.js +110 -0
  126. package/dist/src/decision/review/effect-ledger-adapter.js +321 -0
  127. package/dist/src/decision/review/index.js +12 -0
  128. package/dist/src/decision/review/migrate.js +34 -0
  129. package/dist/src/decision/review/operator-audit.js +59 -0
  130. package/dist/src/decision/review/recovery-adapters.js +252 -0
  131. package/dist/src/decision/review/recovery.js +33 -0
  132. package/dist/src/decision/review/service.js +498 -0
  133. package/dist/src/decision/review/store.js +219 -0
  134. package/dist/src/decision/review/types.js +2 -0
  135. package/dist/src/decision/review/validate.js +205 -0
  136. package/dist/src/decision/scheduler.js +115 -0
  137. package/dist/src/decision/telemetry/context.js +42 -0
  138. package/dist/src/decision/telemetry/debug-sidecar.js +152 -0
  139. package/dist/src/decision/telemetry/exporter.js +77 -0
  140. package/dist/src/decision/telemetry/file-debug-backend.js +112 -0
  141. package/dist/src/decision/telemetry/index.js +13 -0
  142. package/dist/src/decision/telemetry/mapping.js +146 -0
  143. package/dist/src/decision/telemetry/metrics.js +164 -0
  144. package/dist/src/decision/telemetry/otlp-http.js +183 -0
  145. package/dist/src/decision/telemetry/redaction.js +93 -0
  146. package/dist/src/decision/telemetry/retention.js +109 -0
  147. package/dist/src/decision/telemetry/runtime.js +310 -0
  148. package/dist/src/decision/telemetry/trace.js +158 -0
  149. package/dist/src/decision/telemetry/types.js +3 -0
  150. package/dist/src/decision/validate.js +135 -5
  151. package/dist/src/effects/checkpoint-sinks.js +94 -0
  152. package/dist/src/effects/checkpoint.js +76 -0
  153. package/dist/src/effects/decision-links.js +54 -0
  154. package/dist/src/effects/errors.js +48 -0
  155. package/dist/src/effects/identity.js +178 -0
  156. package/dist/src/effects/index.js +25 -0
  157. package/dist/src/effects/keyring.js +160 -0
  158. package/dist/src/effects/keys.js +130 -0
  159. package/dist/src/effects/ledger.js +435 -0
  160. package/dist/src/effects/lifecycle.js +110 -0
  161. package/dist/src/effects/lock-recovery.js +269 -0
  162. package/dist/src/effects/reader.js +103 -0
  163. package/dist/src/effects/records.js +114 -0
  164. package/dist/src/effects/redaction.js +51 -0
  165. package/dist/src/effects/schema.js +73 -0
  166. package/dist/src/effects/store.js +239 -0
  167. package/dist/src/effects/types.js +49 -0
  168. package/dist/src/effects/verifiers/decision.js +168 -0
  169. package/dist/src/effects/verifiers/file.js +106 -0
  170. package/dist/src/effects/verifiers/git.js +206 -0
  171. package/dist/src/effects/verifiers/index.js +90 -0
  172. package/dist/src/effects/verifiers/registry.js +148 -0
  173. package/dist/src/effects/verifiers/review.js +123 -0
  174. package/dist/src/effects/verifiers/tracker.js +299 -0
  175. package/dist/src/effects/verifiers/types.js +21 -0
  176. package/dist/src/effects/verify.js +295 -0
  177. package/dist/src/evidence/bundle.js +2 -0
  178. package/dist/src/extensions/commands/definitions.js +28 -0
  179. package/dist/src/extensions/manifest.js +1 -0
  180. package/dist/src/marketplace/provenance.js +25 -27
  181. package/dist/src/mcp/cli.mjs +11 -1
  182. package/dist/src/mcp/grok-build-config.mjs +189 -0
  183. package/dist/src/mcp/registry.js +21 -1
  184. package/dist/src/mcp/registry.mjs +20 -1
  185. package/dist/src/models/grok-build-models.js +356 -0
  186. package/dist/src/models/index.js +1 -0
  187. package/dist/src/models/model-capabilities.v1.json +34 -0
  188. package/dist/src/models/model-catalog.v1.json +55 -13
  189. package/dist/src/models/model-discovery.js +41 -5
  190. package/dist/src/models/provider-policy.js +3 -2
  191. package/dist/src/plugin/skill-command-translator.js +1 -0
  192. package/dist/src/providers/capability-matrix.yaml +58 -6
  193. package/dist/src/providers/grok-build-acp.js +192 -0
  194. package/dist/src/providers/grok-build-dispatch.js +251 -0
  195. package/dist/src/providers/grok-build-headless.js +170 -0
  196. package/dist/src/providers/muse-paths.js +105 -0
  197. package/dist/src/providers/provider-definitions.js +93 -7
  198. package/dist/src/providers/provider-definitions.mjs +21 -1
  199. package/dist/src/providers/provider-inventory.js +3 -0
  200. package/dist/src/security/artifact-attestation.js +4 -8
  201. package/dist/src/security/signing.js +119 -0
  202. package/dist/src/sessions/adapters/grok-build.js +187 -0
  203. package/dist/src/sessions/adapters/muse.js +412 -0
  204. package/dist/src/sessions/contracts.js +1 -1
  205. package/dist/src/sessions/grok-build-cli.js +196 -0
  206. package/dist/src/sessions/index.js +3 -0
  207. package/dist/src/sessions/workspace-discovery.js +9 -5
  208. package/dist/src/skills/deployer.js +33 -5
  209. package/dist/src/smiths/context-pipeline/claude-hook.js +2 -0
  210. package/dist/src/smiths/context-pipeline/context-file-safety.js +18 -0
  211. package/dist/src/smiths/context-pipeline/finalization.js +1 -32
  212. package/dist/src/smiths/context-pipeline/generator.js +12 -0
  213. package/dist/src/smiths/context-pipeline/index.js +1 -1
  214. package/dist/src/smiths/context-pipeline/managed-hook.js +2 -0
  215. package/dist/src/smiths/context-pipeline/muse-bridge.js +50 -0
  216. package/dist/src/smiths/context-pipeline/provider-policy.js +5 -0
  217. package/dist/src/smiths/context-pipeline/workspace-context.js +22 -16
  218. package/dist/src/smiths/hook-bridge/grok-build-translator.js +64 -0
  219. package/dist/src/smiths/hook-bridge/index.js +3 -0
  220. package/dist/src/smiths/hook-bridge/shim.js +2 -0
  221. package/dist/src/smiths/hook-bridge/types.js +5 -0
  222. package/dist/src/smiths/skillsmith/collision-detector.js +1 -0
  223. package/dist/src/storage/protected-files.js +102 -0
  224. package/dist/src/tracker/forge-http.js +371 -0
  225. package/dist/src/tracker/project-inputs.js +41 -0
  226. package/package.json +2 -1
  227. package/schemas/decision/BatchReceipt.v1.schema.json +50 -0
  228. package/schemas/decision/CalibrationArtifact.v1.schema.json +76 -0
  229. package/schemas/decision/CalibrationCompatibility.v1.schema.json +18 -0
  230. package/schemas/decision/CalibrationGovernanceReceipt.v1.schema.json +44 -0
  231. package/schemas/decision/DecisionAdmissionEvidence.v1.schema.json +43 -0
  232. package/schemas/decision/DecisionBinding.schema.json +309 -0
  233. package/schemas/decision/DecisionBinding.v1alpha2.schema.json +369 -0
  234. package/schemas/decision/DecisionCacheTelemetry.v1.schema.json +20 -0
  235. package/schemas/decision/DecisionChampionChallenger.v1.schema.json +100 -0
  236. package/schemas/decision/DecisionCompileCacheEntry.v1.schema.json +35 -0
  237. package/schemas/decision/DecisionCompileCacheIdentity.v1.schema.json +26 -0
  238. package/schemas/decision/DecisionCompileCacheTombstone.v1.schema.json +31 -0
  239. package/schemas/decision/DecisionContextEvidence.v1.schema.json +136 -0
  240. package/schemas/decision/DecisionDefinition.schema.json +159 -0
  241. package/schemas/decision/DecisionDefinition.v1alpha2.schema.json +203 -0
  242. package/schemas/decision/DecisionDriftResponse.v1.schema.json +55 -0
  243. package/schemas/decision/DecisionEnsembleAggregate.v1.schema.json +86 -0
  244. package/schemas/decision/DecisionEnsembleIntegrityReport.v1.schema.json +64 -0
  245. package/schemas/decision/DecisionEnsemblePolicy.v1.schema.json +130 -0
  246. package/schemas/decision/DecisionGraph.v1.schema.json +77 -0
  247. package/schemas/decision/DecisionJob.v1.schema.json +71 -0
  248. package/schemas/decision/DecisionLifecyclePolicy.v1.schema.json +52 -0
  249. package/schemas/decision/DecisionProjectionPolicy.v1.schema.json +65 -0
  250. package/schemas/decision/DecisionProviderPrefixCompatibility.v1.schema.json +45 -0
  251. package/schemas/decision/DecisionProviderPrefixEvidence.v1.schema.json +17 -0
  252. package/schemas/decision/DecisionProviderPrefixIdentity.v1.schema.json +36 -0
  253. package/schemas/decision/DecisionResult.schema.json +524 -0
  254. package/schemas/decision/DecisionResult.v1alpha2.schema.json +619 -0
  255. package/schemas/decision/DecisionResultCacheEntry.v1.schema.json +53 -0
  256. package/schemas/decision/DecisionReview.schema.json +29 -0
  257. package/schemas/decision/DecisionRuleset.schema.json +313 -0
  258. package/schemas/decision/DecisionRuleset.v1alpha2.schema.json +313 -0
  259. package/schemas/decision/DecisionTelemetryTrace.v1.schema.json +95 -0
  260. package/schemas/decision/RulesetResult.schema.json +721 -0
  261. package/schemas/decision/RulesetResult.v1alpha2.schema.json +891 -0
  262. package/schemas/security/pr-evidence-receipt.v1.schema.json +77 -0
  263. package/schemas/security/threat-assessment-report.v1.schema.json +71 -1
  264. package/tools/agents/deploy-agents.mjs +21 -6
  265. package/tools/agents/providers/base.mjs +7 -4
  266. package/tools/agents/providers/codex.mjs +1 -1
  267. package/tools/agents/providers/grok-build.d.mts +7 -0
  268. package/tools/agents/providers/grok-build.mjs +249 -9
  269. package/tools/agents/providers/model-role.mjs +6 -3
  270. package/tools/agents/providers/muse-hooks.mjs +785 -0
  271. package/tools/agents/providers/muse-paths.mjs +112 -0
  272. package/tools/agents/providers/muse.mjs +336 -0
@@ -3,29 +3,35 @@
3
3
  * Project skills under `.grok/skills`; user home via $GROK_HOME (default ~/.grok).
4
4
  * Distinct from grokbot. No bare `grok` alias.
5
5
  *
6
- * Wave 1: native kernel skills + AGENTS.md bridge. Agents and rules are
7
- * indexed/deferred until #2577 (Grok discovers `.grok/agents` and
8
- * `.grok/rules`, but AIWG does not yet emit qualified writers for them).
6
+ * Native agent compilation is deliberately limited to the three AIWG model
7
+ * workers until the wider corpus has a qualified Grok tool mapping (#2577).
8
+ * Rules remain indexed; Grok loads AGENTS.md and native .grok/rules itself.
9
9
  *
10
10
  * @issue #2575
11
11
  */
12
12
 
13
13
  import path from 'node:path';
14
14
  import os from 'node:os';
15
+ import fs from 'node:fs';
16
+ import { createHash, randomUUID } from 'node:crypto';
17
+ import yaml from 'js-yaml';
15
18
  import {
16
19
  createAgentsMdFromTemplate,
17
20
  deploySkillsWithKernelRouting,
18
21
  collectFrameworkArtifacts,
19
22
  getAddonSkillDirs,
23
+ injectPlatformInContent,
24
+ isKernelSkill,
20
25
  normalizeDeploymentMode,
21
26
  resolveAiwgRoot,
27
+ deployFiles,
28
+ ensureDir,
22
29
  } from './base.mjs';
23
30
 
24
31
  export const name = 'grok-build';
25
32
  export const aliases = [];
26
33
  export const paths = {
27
- // Agents/rules dirs exist in Grok Build, but Wave 1 does not write them.
28
- agents: '',
34
+ agents: '.grok/agents',
29
35
  skills: '.grok/skills',
30
36
  rules: '',
31
37
  hooks: '.grok/hooks',
@@ -36,7 +42,7 @@ export const kernelSkillsPath = '.grok/skills';
36
42
  export const standardSkillsPath = '.grok/.aiwg/skills';
37
43
 
38
44
  export const support = {
39
- agents: 'indexed', // deferred native writer until #2577
45
+ agents: 'native',
40
46
  commands: 'indexed', // discoverable through the AIWG index; no native command writer
41
47
  skills: 'native',
42
48
  rules: 'indexed', // deferred native writer until #2577; host still loads AGENTS.md + .grok/rules hierarchically
@@ -66,6 +72,7 @@ export function resolveGrokHome(env = process.env, userHome = os.homedir()) {
66
72
  }
67
73
 
68
74
  export function createAgentsMd(target, srcRoot, dryRun) {
75
+ assertSafeAgentsMd(target);
69
76
  createAgentsMdFromTemplate(
70
77
  target,
71
78
  resolveAiwgRoot(srcRoot) || srcRoot,
@@ -74,6 +81,35 @@ export function createAgentsMd(target, srcRoot, dryRun) {
74
81
  );
75
82
  }
76
83
 
84
+ function assertSafeAgentsMd(target) {
85
+ const dest = path.join(target, 'AGENTS.md');
86
+ const stat = existingStat(dest);
87
+ if (stat && (!stat.isFile() || stat.isSymbolicLink())) {
88
+ throw new Error(`Refusing unsafe Grok Build AGENTS.md target: ${dest}`);
89
+ }
90
+ }
91
+
92
+ function existingStat(target) {
93
+ try { return fs.lstatSync(target); }
94
+ catch (error) {
95
+ if (error?.code === 'ENOENT') return null;
96
+ throw error;
97
+ }
98
+ }
99
+
100
+ function assertSafeNativeDirectory(target, relative) {
101
+ let current = path.resolve(target);
102
+ for (const segment of relative.split(path.sep)) {
103
+ current = path.join(current, segment);
104
+ const stat = existingStat(current);
105
+ if (!stat) continue;
106
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
107
+ throw new Error(`Refusing unsafe Grok Build deployment directory: ${current}`);
108
+ }
109
+ }
110
+ return current;
111
+ }
112
+
77
113
  /**
78
114
  * Kernel skills → `.grok/skills` (always).
79
115
  * Standard skills → index-driven by default; `.grok/.aiwg/skills` with `--copy-all`.
@@ -81,20 +117,211 @@ export function createAgentsMd(target, srcRoot, dryRun) {
81
117
  export function deploySkills(skillDirs, targetDir, opts = {}) {
82
118
  const kernelDest = path.join(targetDir, kernelSkillsPath);
83
119
  const standardDest = path.join(targetDir, standardSkillsPath);
120
+ assertSafeNativeDirectory(targetDir, kernelSkillsPath);
121
+ assertSafeNativeDirectory(targetDir, standardSkillsPath);
122
+ for (const source of skillDirs) {
123
+ const relative = path.join(isKernelSkill(source) ? kernelSkillsPath : standardSkillsPath, path.basename(source));
124
+ const dest = assertSafeNativeDirectory(targetDir, relative);
125
+ if (fs.existsSync(dest)) regularFiles(dest);
126
+ }
84
127
  return deploySkillsWithKernelRouting(skillDirs, standardDest, kernelDest, {
85
128
  ...opts,
86
129
  copyStandardSkills: opts.copyStandardSkills === true,
87
130
  });
88
131
  }
89
132
 
90
- export function deployAgents() {
91
- return 0;
133
+ const WORKER_ROLES = new Set(['reasoning', 'coding', 'efficiency']);
134
+ const ROLE_FROM_ALIAS = { opus: 'reasoning', sonnet: 'coding', haiku: 'efficiency' };
135
+ const GROK_TOOLS = new Set(['Bash', 'Read', 'Write', 'Edit', 'Grep', 'Glob']);
136
+
137
+ /** Grok agent files accept a small YAML frontmatter subset, not AIWG metadata. */
138
+ export function compileGrokAgent(source, content, opts = {}) {
139
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
140
+ if (!match) throw new Error(`${source}: expected YAML agent frontmatter`);
141
+ const metadata = yaml.load(match[1]);
142
+ if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) {
143
+ throw new Error(`${source}: invalid agent frontmatter`);
144
+ }
145
+ const name = metadata.name;
146
+ const role = metadata['model-role'] || ROLE_FROM_ALIAS[metadata.model];
147
+ if (!/^aiwg-model-(reasoning|coding|efficiency)-worker$/.test(String(name)) || !WORKER_ROLES.has(role)) {
148
+ throw new Error(`${source}: Grok Build native compilation currently supports only the three AIWG model-worker roles; use aiwg show agent for other roles`);
149
+ }
150
+ if (typeof metadata.description !== 'string' || !metadata.description.trim()) {
151
+ throw new Error(`${source}: agent description is required`);
152
+ }
153
+ const tools = metadata.tools;
154
+ if (!Array.isArray(tools) || tools.some(tool => !GROK_TOOLS.has(tool))) {
155
+ throw new Error(`${source}: unsupported Grok Build tool mapping; supported tools: ${[...GROK_TOOLS].join(', ')}`);
156
+ }
157
+ const sourceModel = String(metadata.model || '').trim();
158
+ if (sourceModel && !ROLE_FROM_ALIAS[sourceModel] && sourceModel !== 'inherit') {
159
+ throw new Error(`${source}: exact model pin '${sourceModel}' is not a qualified Grok Build selector; configure --${role}-model with a discovered Grok model`);
160
+ }
161
+ const configuredModel = opts[`${role}Model`] || opts.modelsConfig?.['grok-build']?.[role]?.model;
162
+ if (configuredModel && (typeof configuredModel !== 'string' || /^(configured\/|inherit$)/.test(configuredModel))) {
163
+ throw new Error(`${source}: unresolved Grok Build ${role} model; configure --${role}-model with a discovered selector`);
164
+ }
165
+ const header = [
166
+ '---',
167
+ `name: ${name}`,
168
+ `description: ${JSON.stringify(metadata.description)}`,
169
+ `tools: ${tools.join(', ')}`,
170
+ ...(configuredModel ? [`model: ${JSON.stringify(configuredModel)}`] : []),
171
+ '---',
172
+ ];
173
+ const intent = configuredModel
174
+ ? `AIWG model role: ${role}; exact Grok Build selector: ${configuredModel}.`
175
+ : `AIWG model role: ${role}; no exact Grok Build model is configured. This agent inherits the parent model. Configure --${role}-model after native model discovery to pin this role.`;
176
+ return `${header.join('\n')}\n\n${intent}\n\n${match[2].trim()}\n`;
177
+ }
178
+
179
+ export function deployAgents(agentFiles, targetDir, opts = {}) {
180
+ const selected = agentFiles.filter(file => /^aiwg-model-(reasoning|coding|efficiency)-worker\.md$/.test(path.basename(file)));
181
+ const dir = assertSafeNativeDirectory(targetDir, paths.agents);
182
+ for (const source of selected) {
183
+ const dest = path.join(dir, path.basename(source));
184
+ const stat = existingStat(dest);
185
+ if (!stat) continue;
186
+ if (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`Refusing unsafe Grok Build agent target: ${dest}`);
187
+ }
188
+ const manifest = path.join(dir, '.aiwg-manifest.json');
189
+ const manifestStat = existingStat(manifest);
190
+ if (manifestStat && (!manifestStat.isFile() || manifestStat.isSymbolicLink())) {
191
+ throw new Error(`Refusing unsafe Grok Build agent manifest: ${manifest}`);
192
+ }
193
+ ensureDir(dir, opts.dryRun);
194
+ return deployFiles(selected, dir, { ...opts, provider: 'grok-build' }, compileGrokAgent);
92
195
  }
93
196
 
94
197
  export function deployRules() {
95
198
  return 0;
96
199
  }
97
200
 
201
+ function regularFiles(dir, prefix = '') {
202
+ const files = [];
203
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
204
+ if (entry.isSymbolicLink()) throw new Error('symlink in managed Grok Build artifact');
205
+ const relative = path.join(prefix, entry.name);
206
+ if (entry.isDirectory()) {
207
+ files.push(`${relative}${path.sep}`);
208
+ files.push(...regularFiles(path.join(dir, entry.name), relative));
209
+ }
210
+ else if (entry.isFile()) files.push(relative);
211
+ else throw new Error('special file in managed Grok Build artifact');
212
+ }
213
+ return files.sort();
214
+ }
215
+
216
+ function matchesSkillSource(source, target) {
217
+ try {
218
+ const expected = regularFiles(source);
219
+ const actual = regularFiles(target).filter(name => name !== '.aiwg-managed');
220
+ if (JSON.stringify(expected) !== JSON.stringify(actual)) return false;
221
+ return expected.every(relative => {
222
+ if (relative.endsWith(path.sep)) return true;
223
+ let content = fs.readFileSync(path.join(source, relative), 'utf8');
224
+ if (relative === 'SKILL.md') content = injectPlatformInContent(content, 'grok-build');
225
+ return content === fs.readFileSync(path.join(target, relative), 'utf8');
226
+ });
227
+ } catch { return false; }
228
+ }
229
+
230
+ /** Remove only unchanged AIWG Grok artifacts; shared context files stay intact. */
231
+ export function uninstall(target, opts = {}) {
232
+ const root = path.resolve(target);
233
+ const native = path.join(root, '.grok');
234
+ if (!fs.existsSync(native)) return { planned: [], removed: [], skipped: [] };
235
+ if (fs.lstatSync(native).isSymbolicLink()) throw new Error('Refusing symlinked Grok Build root');
236
+ const internal = path.join(native, '.aiwg');
237
+ if (fs.existsSync(internal) && fs.lstatSync(internal).isSymbolicLink()) throw new Error('Refusing symlinked Grok Build AIWG mirror');
238
+ const sourceRoot = resolveAiwgRoot(opts.srcRoot) || opts.srcRoot;
239
+ if (!sourceRoot) throw new Error('AIWG source is required for safe Grok Build removal');
240
+ const sources = [
241
+ ...getAddonSkillDirs(sourceRoot),
242
+ ...collectFrameworkArtifacts(sourceRoot, 'all', {
243
+ includeAgents: false, includeCommands: false, includeSkills: true, includeRules: false,
244
+ }).skills,
245
+ ];
246
+ const byName = new Map();
247
+ for (const source of sources) {
248
+ const name = path.basename(source);
249
+ if (!byName.has(name)) byName.set(name, []);
250
+ byName.get(name).push(source);
251
+ }
252
+ const planned = [];
253
+ const skipped = [];
254
+ for (const skillRoot of [path.join(native, 'skills'), path.join(native, '.aiwg', 'skills')]) {
255
+ if (!fs.existsSync(skillRoot)) continue;
256
+ if (fs.lstatSync(skillRoot).isSymbolicLink()) throw new Error('Refusing symlinked Grok Build skill root');
257
+ for (const entry of fs.readdirSync(skillRoot, { withFileTypes: true })) {
258
+ if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
259
+ const skill = path.join(skillRoot, entry.name);
260
+ const marker = path.join(skill, '.aiwg-managed');
261
+ if (!fs.existsSync(marker)) continue;
262
+ const relative = path.relative(root, skill);
263
+ if (fs.lstatSync(marker).isSymbolicLink() || fs.readFileSync(marker, 'utf8') !== 'aiwg\n') {
264
+ skipped.push(relative); continue;
265
+ }
266
+ if ((byName.get(entry.name) ?? []).some(source => matchesSkillSource(source, skill))) {
267
+ planned.push(relative);
268
+ } else skipped.push(relative);
269
+ }
270
+ }
271
+ const agentsDir = path.join(native, 'agents');
272
+ const manifestPath = path.join(agentsDir, '.aiwg-manifest.json');
273
+ let manifest;
274
+ if (fs.existsSync(manifestPath)) {
275
+ if (fs.lstatSync(agentsDir).isSymbolicLink() || fs.lstatSync(manifestPath).isSymbolicLink()) {
276
+ throw new Error('Refusing symlinked Grok Build agent manifest');
277
+ }
278
+ manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
279
+ for (const [name, record] of Object.entries(manifest.managed ?? {})) {
280
+ if (path.basename(name) !== name || !/^aiwg-model-(reasoning|coding|efficiency)-worker\.md$/.test(name)) continue;
281
+ const file = path.join(agentsDir, name);
282
+ const relative = path.relative(root, file);
283
+ if (!fs.existsSync(file) || fs.lstatSync(file).isSymbolicLink() || !fs.lstatSync(file).isFile()) {
284
+ skipped.push(relative); continue;
285
+ }
286
+ const digest = `sha256:${createHash('sha256').update(fs.readFileSync(file)).digest('hex')}`;
287
+ if (record?.source === 'bundled' && record.hash === digest) planned.push(relative);
288
+ else skipped.push(relative);
289
+ }
290
+ }
291
+ const removed = [];
292
+ if (!opts.dryRun) {
293
+ for (const relative of planned) {
294
+ const file = path.join(root, relative);
295
+ if (relative.includes(`${path.sep}skills${path.sep}`)) {
296
+ const marker = path.join(file, '.aiwg-managed');
297
+ if (!fs.existsSync(marker) || fs.readFileSync(marker, 'utf8') !== 'aiwg\n'
298
+ || !(byName.get(path.basename(file)) ?? []).some(source => matchesSkillSource(source, file))) {
299
+ skipped.push(relative); continue;
300
+ }
301
+ fs.rmSync(file, { recursive: true });
302
+ } else {
303
+ const name = path.basename(file);
304
+ const record = manifest?.managed?.[name];
305
+ const digest = fs.existsSync(file) && !fs.lstatSync(file).isSymbolicLink()
306
+ ? `sha256:${createHash('sha256').update(fs.readFileSync(file)).digest('hex')}` : '';
307
+ if (!record || digest !== record.hash) { skipped.push(relative); continue; }
308
+ fs.unlinkSync(file);
309
+ delete manifest.managed[name];
310
+ }
311
+ removed.push(relative);
312
+ }
313
+ if (manifest && removed.some(relative => relative.startsWith(`.grok${path.sep}agents${path.sep}`))) {
314
+ if (Object.keys(manifest.managed).length === 0) fs.unlinkSync(manifestPath);
315
+ else {
316
+ const temporary = `${manifestPath}.${randomUUID()}.tmp`;
317
+ fs.writeFileSync(temporary, `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600, flag: 'wx' });
318
+ fs.renameSync(temporary, manifestPath);
319
+ }
320
+ }
321
+ }
322
+ return { planned, removed, skipped: [...new Set(skipped)] };
323
+ }
324
+
98
325
  export async function postDeploy(target, opts = {}) {
99
326
  if (opts.createAgentsMd || (!opts.commandsOnly && !opts.skillsOnly && !opts.rulesOnly)) {
100
327
  createAgentsMd(target, opts.srcRoot, opts.dryRun);
@@ -104,7 +331,7 @@ export async function postDeploy(target, opts = {}) {
104
331
  console.log(
105
332
  `Grok Build (experimental): kernel skills → ${kernelSkillsPath}; ` +
106
333
  `standard skills index-driven (opt-in mirror → ${standardSkillsPath} with --copy-all); ` +
107
- `agents/rules indexed until #2577; user home → ${home || '(unresolved GROK_HOME)'}. ` +
334
+ `model-worker agents → ${paths.agents}; rules indexed; user home → ${home || '(unresolved GROK_HOME)'}. ` +
108
335
  'Distinct from grokbot.',
109
336
  );
110
337
  }
@@ -116,6 +343,10 @@ export function getFileExtension() {
116
343
 
117
344
  export async function deploy(opts) {
118
345
  const mode = normalizeDeploymentMode(opts.mode);
346
+ if (opts.createAgentsMd || (!opts.commandsOnly && !opts.skillsOnly && !opts.rulesOnly)) {
347
+ assertSafeAgentsMd(opts.target);
348
+ }
349
+ const aiwgRoot = resolveAiwgRoot(opts.srcRoot) || opts.srcRoot;
119
350
  const skillDirs = [...getAddonSkillDirs(opts.srcRoot)];
120
351
  skillDirs.push(
121
352
  ...collectFrameworkArtifacts(opts.srcRoot, mode, {
@@ -126,6 +357,13 @@ export async function deploy(opts) {
126
357
  }).skills,
127
358
  );
128
359
  let count = 0;
360
+ if (!opts.commandsOnly && !opts.skillsOnly && !opts.rulesOnly) {
361
+ const workerDir = path.join(aiwgRoot, 'agentic', 'code', 'addons', 'aiwg-utils', 'agents');
362
+ const workers = ['reasoning', 'coding', 'efficiency']
363
+ .map(role => path.join(workerDir, `aiwg-model-${role}-worker.md`))
364
+ .filter(file => fs.existsSync(file));
365
+ count += deployAgents(workers, opts.target, opts).filter(action => action.type === 'deploy').length;
366
+ }
129
367
  if (!opts.commandsOnly && !opts.rulesOnly) {
130
368
  const result = deploySkills(skillDirs, opts.target, opts);
131
369
  count += (result?.kernel ?? 0) + (result?.standardCopied ?? 0);
@@ -146,8 +384,10 @@ export default {
146
384
  createAgentsMd,
147
385
  deploySkills,
148
386
  deployAgents,
387
+ compileGrokAgent,
149
388
  deployRules,
150
389
  postDeploy,
151
390
  getFileExtension,
152
391
  deploy,
392
+ uninstall,
153
393
  };
@@ -9,10 +9,13 @@
9
9
  * @implements #1801
10
10
  */
11
11
 
12
+ // Families by provider tier. Flagship families (Claude Fable, OpenAI GPT-6
13
+ // Astra) classify as reasoning: deployment never selects a flagship for a
14
+ // role, but an explicitly elected flagship pin must still classify.
12
15
  const ROLE_PATTERNS = [
13
- ['reasoning', /(?:^|[/:._-])opus(?:$|[/:._-]|\d)/i],
14
- ['coding', /(?:^|[/:._-])sonnet(?:$|[/:._-]|\d)/i],
15
- ['efficiency', /(?:^|[/:._-])haiku(?:$|[/:._-]|\d)/i],
16
+ ['reasoning', /(?:^|[/:._-])(?:opus|fable|sol|astra)(?:$|[/:._\[-]|\d)/i],
17
+ ['coding', /(?:^|[/:._-])(?:sonnet|terra)(?:$|[/:._\[-]|\d)/i],
18
+ ['efficiency', /(?:^|[/:._-])(?:haiku|luna)(?:$|[/:._\[-]|\d)/i],
16
19
  ];
17
20
 
18
21
  /**