@aiwg/cli 2026.9.20 → 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
@@ -0,0 +1,152 @@
1
+ import { createCipheriv, createDecipheriv, randomBytes, randomUUID } from 'node:crypto';
2
+ import { validateDebugCapturePolicy } from './retention.js';
3
+ import { validateDecisionLifecyclePolicy } from '../lifecycle.js';
4
+ /** Opaque reference and ciphertext only; never serialize plaintext into a receipt or audit event. */
5
+ export class DecisionDebugSidecar {
6
+ policy;
7
+ backend;
8
+ resolveKey;
9
+ authorize;
10
+ clock;
11
+ constructor(policy, backend, resolveKey, authorize, lifecycle, clock = Date.now) {
12
+ this.policy = policy;
13
+ this.backend = backend;
14
+ this.resolveKey = resolveKey;
15
+ this.authorize = authorize;
16
+ this.clock = clock;
17
+ if (!validateDebugCapturePolicy(policy))
18
+ throw new Error('Debug capture authorization required');
19
+ validateDecisionLifecyclePolicy(lifecycle);
20
+ const rule = lifecycle.surfaces['debug-sidecar'];
21
+ if (rule.classification !== policy.classification || rule.retentionMs !== policy.ttlMs
22
+ || rule.deletion !== 'erase' || rule.export !== 'denied') {
23
+ throw new Error('Debug capture lifecycle policy mismatch');
24
+ }
25
+ }
26
+ async capture(scope, plaintext) {
27
+ if (!scope || !await this.authorize(scope, 'capture'))
28
+ throw new Error('Debug capture denied');
29
+ const now = this.clock();
30
+ if (!Number.isSafeInteger(now) || now < 0 || !Number.isSafeInteger(now + this.policy.ttlMs))
31
+ throw new Error('Debug capture clock invalid');
32
+ const id = randomUUID();
33
+ const nonce = randomBytes(12);
34
+ const key = await this.key();
35
+ let ciphertext;
36
+ let tag;
37
+ try {
38
+ const cipher = createCipheriv('aes-256-gcm', key, nonce);
39
+ cipher.setAAD(Buffer.from(`${id}:${scope}:${now + this.policy.ttlMs}`));
40
+ ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
41
+ tag = cipher.getAuthTag();
42
+ }
43
+ finally {
44
+ key.fill(0);
45
+ }
46
+ // Audit must succeed before content is persisted. An audit failure never opens capture.
47
+ await this.audit('capture', id, scope);
48
+ try {
49
+ await this.backend.put({ id, scope, expiresAt: now + this.policy.ttlMs, nonce, ciphertext, tag });
50
+ }
51
+ catch {
52
+ throw new Error('Debug sidecar storage failed');
53
+ }
54
+ return id;
55
+ }
56
+ async read(scope, id) {
57
+ if (!scope || !await this.authorize(scope, 'read'))
58
+ throw new Error('Debug read denied');
59
+ const record = await this.get(id);
60
+ if (!record || record.scope !== scope)
61
+ return null;
62
+ if (this.clock() >= record.expiresAt) {
63
+ await this.audit('expire', id, scope);
64
+ await this.erase(id);
65
+ return null;
66
+ }
67
+ await this.audit('read', id, scope);
68
+ const key = await this.key();
69
+ try {
70
+ const decipher = createDecipheriv('aes-256-gcm', key, record.nonce);
71
+ decipher.setAAD(Buffer.from(`${id}:${scope}:${record.expiresAt}`));
72
+ decipher.setAuthTag(record.tag);
73
+ return Buffer.concat([decipher.update(record.ciphertext), decipher.final()]);
74
+ }
75
+ catch {
76
+ throw new Error('Debug sidecar integrity check failed');
77
+ }
78
+ finally {
79
+ key.fill(0);
80
+ }
81
+ }
82
+ async delete(scope, id) {
83
+ if (!scope || !await this.authorize(scope, 'delete'))
84
+ throw new Error('Debug deletion denied');
85
+ const record = await this.get(id);
86
+ if (!record || record.scope !== scope)
87
+ return;
88
+ await this.audit('delete', id, scope);
89
+ await this.erase(id);
90
+ }
91
+ /** Evict expired ciphertext even when nobody reads it. The backend must return
92
+ * only scoped records; each candidate is checked again before erasure. */
93
+ async sweepExpired(scope) {
94
+ if (!scope || !await this.authorize(scope, 'delete'))
95
+ throw new Error('Debug expiry sweep denied');
96
+ const now = this.clock();
97
+ let records;
98
+ try {
99
+ records = await this.backend.listExpired(scope, now);
100
+ }
101
+ catch {
102
+ throw new Error('Debug sidecar storage failed');
103
+ }
104
+ let deleted = 0;
105
+ for (const candidate of records) {
106
+ const record = await this.get(candidate.id);
107
+ if (!record || record.scope !== scope || now < record.expiresAt)
108
+ continue;
109
+ await this.audit('expire', record.id, scope);
110
+ await this.erase(record.id);
111
+ deleted++;
112
+ }
113
+ return deleted;
114
+ }
115
+ async get(id) {
116
+ try {
117
+ return await this.backend.get(id);
118
+ }
119
+ catch {
120
+ throw new Error('Debug sidecar storage failed');
121
+ }
122
+ }
123
+ async erase(id) {
124
+ try {
125
+ await this.backend.delete(id);
126
+ }
127
+ catch {
128
+ throw new Error('Debug sidecar deletion failed');
129
+ }
130
+ }
131
+ async audit(operation, id, scope) {
132
+ try {
133
+ await this.backend.audit({ operation, id, scope });
134
+ }
135
+ catch {
136
+ throw new Error('Debug access audit failed');
137
+ }
138
+ }
139
+ async key() {
140
+ let resolved;
141
+ try {
142
+ resolved = await this.resolveKey(this.policy.encryption.keyReference);
143
+ }
144
+ catch {
145
+ throw new Error('Debug encryption key unavailable');
146
+ }
147
+ if (resolved.length !== 32)
148
+ throw new Error('Debug encryption key invalid');
149
+ return Buffer.from(resolved);
150
+ }
151
+ }
152
+ //# sourceMappingURL=debug-sidecar.js.map
@@ -0,0 +1,77 @@
1
+ import { sanitizedTelemetryExport } from './redaction.js';
2
+ export class BoundedDecisionTraceExporter {
3
+ sink;
4
+ options;
5
+ queue = [];
6
+ draining = null;
7
+ stopped = false;
8
+ diagnostics = [];
9
+ constructor(sink, options) {
10
+ this.sink = sink;
11
+ this.options = options;
12
+ if (!Number.isSafeInteger(options.capacity) || options.capacity < 1 || !Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1
13
+ || !Number.isSafeInteger(options.maximumTraceBytes ?? 65_536) || (options.maximumTraceBytes ?? 65_536) < 1
14
+ || !Number.isSafeInteger(options.maximumDiagnostics ?? 100) || (options.maximumDiagnostics ?? 100) < 1) {
15
+ throw new Error('Invalid exporter bounds');
16
+ }
17
+ }
18
+ /** Never awaits the sink and never changes a decision result. */
19
+ offer(trace) {
20
+ if (this.stopped || this.queue.length >= this.options.capacity) {
21
+ this.record('dropped', this.stopped ? 'exporter stopped' : 'queue capacity reached');
22
+ return false;
23
+ }
24
+ try {
25
+ const sanitized = sanitizedTelemetryExport(trace, { canaries: this.options.canaries });
26
+ const encoded = JSON.stringify(sanitized);
27
+ if (Buffer.byteLength(encoded, 'utf8') > (this.options.maximumTraceBytes ?? 65_536)) {
28
+ this.record('dropped', 'trace exceeds configured byte bound');
29
+ return false;
30
+ }
31
+ this.queue.push(sanitized);
32
+ this.drain();
33
+ return true;
34
+ }
35
+ catch {
36
+ this.record('dropped', 'invalid telemetry trace');
37
+ return false;
38
+ }
39
+ }
40
+ async shutdown() {
41
+ this.stopped = true;
42
+ await (this.drain() ?? this.draining);
43
+ }
44
+ record(type, detail) {
45
+ const containsCanary = this.options.canaries?.some(canary => canary && detail.toLowerCase().includes(canary.toLowerCase()));
46
+ this.diagnostics.push({ type, atUnixMs: Date.now(), detail: containsCanary ? 'redacted exporter diagnostic' : detail.slice(0, 256) });
47
+ const maximum = this.options.maximumDiagnostics ?? 100;
48
+ if (this.diagnostics.length > maximum)
49
+ this.diagnostics.splice(0, this.diagnostics.length - maximum);
50
+ }
51
+ drain() {
52
+ if (this.draining)
53
+ return null;
54
+ this.draining = (async () => {
55
+ while (this.queue.length > 0) {
56
+ const trace = this.queue.shift();
57
+ const controller = new AbortController();
58
+ let timeout;
59
+ const deadline = new Promise((_, reject) => {
60
+ timeout = setTimeout(() => { controller.abort(); reject(new Error('telemetry export timed out')); }, this.options.timeoutMs);
61
+ });
62
+ try {
63
+ await Promise.race([this.sink.export(trace, controller.signal), deadline]);
64
+ }
65
+ catch (error) {
66
+ this.record(controller.signal.aborted ? 'timeout' : 'failed', error instanceof Error ? error.message : 'export failed');
67
+ }
68
+ finally {
69
+ if (timeout)
70
+ clearTimeout(timeout);
71
+ }
72
+ }
73
+ })().finally(() => { this.draining = null; });
74
+ return this.draining;
75
+ }
76
+ }
77
+ //# sourceMappingURL=exporter.js.map
@@ -0,0 +1,112 @@
1
+ import { constants } from 'node:fs';
2
+ import { link, lstat, mkdir, open, readdir, rm } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { randomUUID } from 'node:crypto';
5
+ const ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
6
+ const SCOPE = /^[A-Za-z0-9][A-Za-z0-9_.-]*$/;
7
+ /** Local encrypted-content backend. The caller supplies key resolution and authorization separately. */
8
+ export class FileDebugSidecarBackend {
9
+ root;
10
+ constructor(root) {
11
+ this.root = root;
12
+ if (!root)
13
+ throw new Error('Debug storage root required');
14
+ }
15
+ path(id) {
16
+ if (!ID.test(id))
17
+ throw new Error('Debug reference invalid');
18
+ return join(this.root, `${id}.json`);
19
+ }
20
+ async prepare() {
21
+ await mkdir(this.root, { recursive: true, mode: 0o700 });
22
+ const stat = await lstat(this.root);
23
+ if (!stat.isDirectory() || stat.isSymbolicLink() || (stat.mode & 0o077) !== 0) {
24
+ throw new Error('Debug storage root must be a private directory');
25
+ }
26
+ }
27
+ async put(record) {
28
+ const target = this.path(record.id);
29
+ if (!SCOPE.test(record.scope))
30
+ throw new Error('Debug scope invalid');
31
+ await this.prepare();
32
+ const temp = join(this.root, `${randomUUID()}.tmp`);
33
+ const serialized = JSON.stringify({ id: record.id, scope: record.scope, expiresAt: record.expiresAt,
34
+ nonce: record.nonce.toString('base64'), tag: record.tag.toString('base64'), ciphertext: record.ciphertext.toString('base64') });
35
+ try {
36
+ const fd = await open(temp, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
37
+ try {
38
+ await fd.writeFile(serialized);
39
+ await fd.sync();
40
+ }
41
+ finally {
42
+ await fd.close();
43
+ }
44
+ // Atomic create without replacing a previous reference or following a symlink.
45
+ await link(temp, target);
46
+ }
47
+ finally {
48
+ await rm(temp, { force: true });
49
+ }
50
+ }
51
+ async get(id) {
52
+ const target = this.path(id);
53
+ let fd;
54
+ try {
55
+ fd = await open(target, constants.O_RDONLY | constants.O_NOFOLLOW);
56
+ }
57
+ catch (error) {
58
+ if (error.code === 'ENOENT')
59
+ return null;
60
+ throw new Error('Debug content unavailable');
61
+ }
62
+ try {
63
+ const value = JSON.parse(await fd.readFile({ encoding: 'utf8' }));
64
+ if (value.id !== id || typeof value.scope !== 'string' || !SCOPE.test(value.scope)
65
+ || !Number.isSafeInteger(value.expiresAt) || typeof value.nonce !== 'string'
66
+ || typeof value.tag !== 'string' || typeof value.ciphertext !== 'string')
67
+ throw new Error();
68
+ return { id, scope: value.scope, expiresAt: value.expiresAt,
69
+ nonce: Buffer.from(value.nonce, 'base64'), tag: Buffer.from(value.tag, 'base64'),
70
+ ciphertext: Buffer.from(value.ciphertext, 'base64') };
71
+ }
72
+ catch {
73
+ throw new Error('Debug content invalid');
74
+ }
75
+ finally {
76
+ await fd.close();
77
+ }
78
+ }
79
+ async delete(id) {
80
+ await rm(this.path(id), { force: true });
81
+ }
82
+ async listExpired(scope, before) {
83
+ if (!SCOPE.test(scope) || !Number.isSafeInteger(before))
84
+ throw new Error('Debug expiry query invalid');
85
+ await this.prepare();
86
+ const records = [];
87
+ for (const name of await readdir(this.root)) {
88
+ if (!name.endsWith('.json') || !ID.test(name.slice(0, -5)))
89
+ continue;
90
+ const record = await this.get(name.slice(0, -5));
91
+ if (record?.scope === scope && record.expiresAt <= before)
92
+ records.push(record);
93
+ }
94
+ return records;
95
+ }
96
+ async audit(event) {
97
+ this.path(event.id);
98
+ if (!SCOPE.test(event.scope) || !['capture', 'read', 'delete', 'expire'].includes(event.operation)) {
99
+ throw new Error('Debug audit event invalid');
100
+ }
101
+ await this.prepare();
102
+ const fd = await open(join(this.root, 'audit.jsonl'), constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW, 0o600);
103
+ try {
104
+ await fd.writeFile(`${JSON.stringify(event)}\n`);
105
+ await fd.sync();
106
+ }
107
+ finally {
108
+ await fd.close();
109
+ }
110
+ }
111
+ }
112
+ //# sourceMappingURL=file-debug-backend.js.map
@@ -0,0 +1,13 @@
1
+ export * from './context.js';
2
+ export * from './debug-sidecar.js';
3
+ export * from './file-debug-backend.js';
4
+ export * from './exporter.js';
5
+ export * from './otlp-http.js';
6
+ export * from './mapping.js';
7
+ export * from './metrics.js';
8
+ export * from './redaction.js';
9
+ export * from './retention.js';
10
+ export * from './runtime.js';
11
+ export * from './trace.js';
12
+ export * from './types.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,146 @@
1
+ import { sanitizeOpaqueValue } from './redaction.js';
2
+ function put(target, key, value, provenance) {
3
+ target.attributes[key] = value;
4
+ target.provenance[key] = value === null ? 'unknown' : provenance;
5
+ }
6
+ export function mapDecisionAttempt(attempt) {
7
+ const out = { attributes: {}, provenance: {} };
8
+ put(out, 'aiwg.attempt.ordinal', attempt.ordinal, 'client-derived');
9
+ put(out, 'aiwg.adapter.id', attempt.adapter, 'client-derived');
10
+ put(out, 'aiwg.adapter.version', attempt.adapterVersion, 'client-derived');
11
+ put(out, 'gen_ai.request.model', attempt.requestedModel, 'client-derived');
12
+ put(out, 'gen_ai.response.model', attempt.actualModel, 'provider-fact');
13
+ put(out, 'aiwg.decision.status', attempt.status, 'client-derived');
14
+ put(out, 'aiwg.decision.reason', attempt.reason, 'client-derived');
15
+ put(out, 'aiwg.attempt.duration_ms', attempt.durationMs, 'client-derived');
16
+ put(out, 'gen_ai.usage.input_tokens', attempt.usage.inputTokens, 'provider-fact');
17
+ put(out, 'gen_ai.usage.output_tokens', attempt.usage.outputTokens, 'provider-fact');
18
+ put(out, 'aiwg.usage.cost_usd', attempt.usage.costUsd, 'provider-fact');
19
+ put(out, 'aiwg.usage.cost_provenance', attempt.usage.costUsd === null ? 'unknown' : 'provider-fact', 'client-derived');
20
+ put(out, 'aiwg.provider.request_id', attempt.requestId === null ? null : sanitizeOpaqueValue(attempt.requestId, 128), 'provider-fact');
21
+ if (attempt.requestIdSource)
22
+ put(out, 'aiwg.provider.request_id_source', attempt.requestIdSource, 'client-derived');
23
+ if (attempt.httpStatus !== undefined)
24
+ put(out, 'http.response.status_code', attempt.httpStatus, 'provider-fact');
25
+ if (attempt.retryDelayMs !== undefined)
26
+ put(out, 'aiwg.retry.delay_ms', attempt.retryDelayMs, 'client-derived');
27
+ if (attempt.termination)
28
+ put(out, 'aiwg.attempt.termination', attempt.termination, 'client-derived');
29
+ if (attempt.remoteExecution)
30
+ put(out, 'aiwg.remote.execution', attempt.remoteExecution, 'unknown');
31
+ if (attempt.batch) {
32
+ put(out, 'aiwg.batch.id', attempt.batch.groupId, 'client-derived');
33
+ put(out, 'aiwg.batch.mode', attempt.batch.mode, 'client-derived');
34
+ }
35
+ if (attempt.providerPrefix) {
36
+ put(out, 'aiwg.cache.layer', 'provider-prefix', 'client-derived');
37
+ put(out, 'aiwg.cache.result', attempt.providerPrefix.status, 'provider-fact');
38
+ put(out, 'aiwg.cache.source', attempt.providerPrefix.source, 'client-derived');
39
+ put(out, 'aiwg.cache.version', attempt.providerPrefix.cacheVersion === null
40
+ ? null : sanitizeOpaqueValue(attempt.providerPrefix.cacheVersion, 64), 'provider-fact');
41
+ put(out, 'aiwg.cache.saved_tokens', attempt.providerPrefix.savedInputTokens, 'provider-fact');
42
+ put(out, 'aiwg.cache.expires_at_ms', attempt.providerPrefix.expiresAtEpochMs, 'provider-fact');
43
+ }
44
+ return out;
45
+ }
46
+ /**
47
+ * Maps any cache layer's metadata-only record. Every value is a fixed enum,
48
+ * a number or a bounded version string; keys, aliases and identities never appear.
49
+ */
50
+ export function mapCacheTelemetry(telemetry) {
51
+ const out = { attributes: {}, provenance: {} };
52
+ const reported = telemetry.layer === 'provider-prefix' && telemetry.reason === 'provider-report';
53
+ put(out, 'aiwg.cache.layer', telemetry.layer, 'client-derived');
54
+ put(out, 'aiwg.cache.result', telemetry.outcome, reported ? 'provider-fact' : 'client-derived');
55
+ put(out, 'aiwg.cache.reason', telemetry.reason, 'client-derived');
56
+ put(out, 'aiwg.cache.version', telemetry.version === null ? null : sanitizeOpaqueValue(telemetry.version, 64), reported ? 'provider-fact' : 'client-derived');
57
+ put(out, 'aiwg.cache.saved_tokens', telemetry.savedTokens, 'provider-fact');
58
+ put(out, 'aiwg.cache.preparation_ms', telemetry.preparationLatencyMs, 'client-derived');
59
+ put(out, 'aiwg.cache.expires_at_ms', telemetry.expiresAtEpochMs, reported ? 'provider-fact' : 'client-derived');
60
+ put(out, 'aiwg.cache.invalidation_reason', telemetry.invalidationReason, 'client-derived');
61
+ return out;
62
+ }
63
+ /** Admission evidence is metadata-only by contract; no principal or workspace ID reaches a span. */
64
+ export function mapAdmissionEvidence(evidence) {
65
+ const out = { attributes: {}, provenance: {} };
66
+ put(out, 'aiwg.admission.decision', evidence.decision, 'client-derived');
67
+ put(out, 'aiwg.admission.reason', evidence.reason, 'client-derived');
68
+ put(out, 'aiwg.queue.delay_ms', evidence.queueDelayMs, 'client-derived');
69
+ put(out, 'aiwg.queue.active', evidence.active, 'client-derived');
70
+ put(out, 'aiwg.queue.queued', evidence.queued, 'client-derived');
71
+ put(out, 'aiwg.admission.estimated_tokens', evidence.estimatedTokens, 'estimate');
72
+ put(out, 'aiwg.admission.estimated_cost_usd', evidence.estimatedCostUsd, 'estimate');
73
+ put(out, 'aiwg.retry.pressure', evidence.retryPressure, 'client-derived');
74
+ put(out, 'aiwg.breaker.status', evidence.breakerState, 'client-derived');
75
+ if (evidence.retryAfterMs !== undefined)
76
+ put(out, 'aiwg.admission.retry_after_ms', evidence.retryAfterMs, 'client-derived');
77
+ return out;
78
+ }
79
+ /** Maps lifecycle-only metadata not present on DecisionResult without opening a body. */
80
+ export function mapDecisionLifecycle(metadata) {
81
+ const out = { attributes: {}, provenance: {} };
82
+ const pin = (prefix, value) => {
83
+ put(out, `${prefix}.id`, value?.id ?? null, 'client-derived');
84
+ put(out, `${prefix}.version`, value?.version ?? null, 'client-derived');
85
+ put(out, `${prefix}.digest`, value?.digest ?? null, 'client-derived');
86
+ };
87
+ pin('aiwg.definition', metadata.definitionPin);
88
+ pin('aiwg.policy', metadata.policyPin);
89
+ pin('aiwg.calibration', metadata.calibrationPin);
90
+ put(out, 'aiwg.route.reason', metadata.routeReason ?? null, 'client-derived');
91
+ put(out, 'aiwg.route.fallback', metadata.fallback ?? false, 'client-derived');
92
+ put(out, 'aiwg.primitive.count', metadata.primitiveCount ?? null, 'client-derived');
93
+ put(out, 'aiwg.validation.outcome', metadata.validationOutcome ?? 'unknown', 'client-derived');
94
+ put(out, 'aiwg.persistence.result', metadata.persistenceResult ?? 'unknown', 'client-derived');
95
+ put(out, 'aiwg.cache.source', metadata.cacheSource ?? null, 'client-derived');
96
+ for (const [key, value] of Object.entries({
97
+ 'aiwg.batch.id': metadata.batchId, 'aiwg.job.id': metadata.jobId, 'aiwg.review.id': metadata.reviewId,
98
+ 'aiwg.effect_receipt.id': metadata.effectReceiptId,
99
+ }))
100
+ put(out, key, value ?? null, 'client-derived');
101
+ return out;
102
+ }
103
+ export function mapDecisionResult(result) {
104
+ const out = { attributes: {}, provenance: {} };
105
+ put(out, 'aiwg.run.id', result.spec.runId, 'client-derived');
106
+ put(out, 'aiwg.invocation.id', result.spec.invocationId, 'client-derived');
107
+ put(out, 'aiwg.decision.id', result.spec.decision.id, 'client-derived');
108
+ put(out, 'aiwg.decision.version', result.spec.decision.version, 'client-derived');
109
+ put(out, 'aiwg.ruleset.id', result.spec.ruleset.id, 'client-derived');
110
+ put(out, 'aiwg.ruleset.version', result.spec.ruleset.version, 'client-derived');
111
+ put(out, 'aiwg.binding.id', result.spec.binding.id, 'client-derived');
112
+ put(out, 'aiwg.binding.version', result.spec.binding.version, 'client-derived');
113
+ put(out, 'aiwg.decision.alias', result.spec.alias, 'client-derived');
114
+ put(out, 'aiwg.decision.status', result.spec.status, 'client-derived');
115
+ put(out, 'aiwg.decision.reason', result.spec.reason, 'client-derived');
116
+ put(out, 'aiwg.attempt.count', result.spec.attempts.length, 'client-derived');
117
+ if (result.spec.acceptance) {
118
+ put(out, 'aiwg.acceptance.policy_version', result.spec.acceptance.policyVersion, 'client-derived');
119
+ put(out, 'aiwg.acceptance.disposition', result.spec.acceptance.disposition, 'client-derived');
120
+ put(out, 'aiwg.acceptance.reason', result.spec.acceptance.reason, 'client-derived');
121
+ }
122
+ if (result.spec.calibrationCompatibility) {
123
+ const calibration = result.spec.calibrationCompatibility;
124
+ put(out, 'aiwg.calibration.compatibility_state', calibration.state, 'client-derived');
125
+ put(out, 'aiwg.calibration.compatibility_action', calibration.action, 'client-derived');
126
+ put(out, 'aiwg.calibration.artifact_id', calibration.artifactId, 'client-derived');
127
+ put(out, 'aiwg.calibration.artifact_digest', calibration.artifactDigest, 'client-derived');
128
+ put(out, 'aiwg.calibration.alias_revision', calibration.aliasRevision, 'client-derived');
129
+ put(out, 'aiwg.calibration.reason_count', calibration.reasons.length, 'client-derived');
130
+ }
131
+ return out;
132
+ }
133
+ export function mapRulesetResult(result) {
134
+ const out = { attributes: {}, provenance: {} };
135
+ put(out, 'aiwg.run.id', result.spec.runId, 'client-derived');
136
+ put(out, 'aiwg.invocation.id', result.spec.invocationId, 'client-derived');
137
+ put(out, 'aiwg.ruleset.id', result.spec.ruleset.id, 'client-derived');
138
+ put(out, 'aiwg.ruleset.version', result.spec.ruleset.version, 'client-derived');
139
+ put(out, 'aiwg.binding.id', result.spec.binding.id, 'client-derived');
140
+ put(out, 'aiwg.binding.version', result.spec.binding.version, 'client-derived');
141
+ put(out, 'aiwg.workflow.status', result.spec.status, 'client-derived');
142
+ put(out, 'aiwg.decision.reason', result.spec.reason, 'client-derived');
143
+ put(out, 'aiwg.evaluation.count', Object.keys(result.spec.evaluations).length, 'client-derived');
144
+ return out;
145
+ }
146
+ //# sourceMappingURL=mapping.js.map