@aiwg/cli 2026.10.4 → 2026.10.6

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 (220) hide show
  1. package/agentic/code/addons/composition-engine/lib/runtime.mjs +1401 -0
  2. package/agentic/code/addons/composition-engine/lib/validator.mjs +513 -0
  3. package/agentic/code/addons/composition-engine/schemas/flow-graph.schema.json +372 -0
  4. package/agentic/code/providers/model-capabilities.v1.json +74 -50
  5. package/bin/aiwg.mjs +3 -1
  6. package/dist/src/artifacts/browser-export.js +1 -0
  7. package/dist/src/artifacts/citation-parser.js +8 -1
  8. package/dist/src/artifacts/cli.js +72 -9
  9. package/dist/src/artifacts/fortemi-core-query-adapter.js +2 -0
  10. package/dist/src/artifacts/fortemi-core-sync.js +26 -8
  11. package/dist/src/artifacts/graph-query.js +18 -8
  12. package/dist/src/artifacts/index-adapters.js +339 -0
  13. package/dist/src/artifacts/index-builder.js +146 -16
  14. package/dist/src/artifacts/index-files.js +15 -4
  15. package/dist/src/artifacts/index-preparation.js +91 -26
  16. package/dist/src/artifacts/index-reader.js +44 -0
  17. package/dist/src/artifacts/index-refresh.js +130 -56
  18. package/dist/src/artifacts/index-status.js +20 -5
  19. package/dist/src/artifacts/index-worker.mjs +9 -7
  20. package/dist/src/artifacts/memory-maintenance.js +503 -0
  21. package/dist/src/artifacts/prebuilt-relations.js +3 -1
  22. package/dist/src/artifacts/query-engine.js +263 -108
  23. package/dist/src/artifacts/relations-builder.js +2 -2
  24. package/dist/src/artifacts/source-graph.js +2 -2
  25. package/dist/src/artifacts/types.js +9 -1
  26. package/dist/src/cli/handlers/decision.js +19 -1
  27. package/dist/src/cli/handlers/guided-setup.js +470 -0
  28. package/dist/src/cli/handlers/help.js +2 -2
  29. package/dist/src/cli/handlers/housekeeper.js +1110 -0
  30. package/dist/src/cli/handlers/index.js +4 -2
  31. package/dist/src/cli/handlers/init.js +41 -6
  32. package/dist/src/cli/handlers/local-executor.js +5 -3
  33. package/dist/src/cli/handlers/mc.js +509 -53
  34. package/dist/src/cli/handlers/models.js +32 -2
  35. package/dist/src/cli/handlers/ralph-launcher.js +76 -4
  36. package/dist/src/cli/handlers/rules.js +1 -1
  37. package/dist/src/cli/handlers/script-runner.js +73 -2
  38. package/dist/src/cli/handlers/serve.js +5 -3
  39. package/dist/src/cli/handlers/sessions.js +40 -6
  40. package/dist/src/cli/handlers/setup.js +428 -1
  41. package/dist/src/cli/handlers/skill-lint.js +1 -1
  42. package/dist/src/cli/handlers/subcommands.js +118 -8
  43. package/dist/src/cli/handlers/use.js +279 -93
  44. package/dist/src/cli/handlers/workspace.js +3 -1
  45. package/dist/src/cli/prompt-utils.js +8 -0
  46. package/dist/src/cli/router.js +16 -1
  47. package/dist/src/config/aiwg-config.js +42 -0
  48. package/dist/src/config/cli.js +7 -3
  49. package/dist/src/config/decision-config.js +14 -1
  50. package/dist/src/config/native-sandbox-warnings.js +25 -0
  51. package/dist/src/contributors/validation.js +6 -5
  52. package/dist/src/decision/admission.js +7 -3
  53. package/dist/src/decision/benchmark.js +469 -0
  54. package/dist/src/decision/ledger.js +22 -3
  55. package/dist/src/decision/pricing.js +147 -0
  56. package/dist/src/decision/qualification/gate-evidence.js +18 -15
  57. package/dist/src/decision/qualification/load-staged.js +539 -0
  58. package/dist/src/decision/qualification/load.js +109 -33
  59. package/dist/src/decision/qualification/runner.js +5 -2
  60. package/dist/src/decision/review/service.js +6 -4
  61. package/dist/src/decision/review/validate.js +23 -2
  62. package/dist/src/decision/savings.js +8 -3
  63. package/dist/src/discovery/index.js +492 -0
  64. package/dist/src/discovery/interview.js +233 -0
  65. package/dist/src/discovery/plan-apply.js +571 -0
  66. package/dist/src/discovery/plan-store.js +171 -0
  67. package/dist/src/discovery/plan-types.js +2 -0
  68. package/dist/src/discovery/plan-validation.js +139 -0
  69. package/dist/src/discovery/types.js +2 -0
  70. package/dist/src/extensions/commands/definitions.js +49 -9
  71. package/dist/src/extensions/manifest.js +71 -44
  72. package/dist/src/extensions/project-local-discovery.js +1 -1
  73. package/dist/src/extensions/project-quickref.js +18 -17
  74. package/dist/src/extensions/validation.js +32 -29
  75. package/dist/src/housekeeper/daemon-config.js +148 -0
  76. package/dist/src/housekeeper/ipc.js +84 -0
  77. package/dist/src/housekeeper/lifecycle.js +148 -0
  78. package/dist/src/housekeeper/platform.js +35 -0
  79. package/dist/src/housekeeper/status.js +70 -0
  80. package/dist/src/housekeeper/units.js +114 -0
  81. package/dist/src/jobs/flow.js +22 -21
  82. package/dist/src/lint/rule-activation.js +20 -5
  83. package/dist/src/lint/runner.js +1 -1
  84. package/dist/src/mcp/cli.mjs +5 -6
  85. package/dist/src/mcp/config-file.mjs +6 -2
  86. package/dist/src/mcp/config-layers.mjs +23 -7
  87. package/dist/src/mcp/profiles.js +18 -31
  88. package/dist/src/mcp/profiles.mjs +18 -32
  89. package/dist/src/mcp/registry.js +7 -27
  90. package/dist/src/mcp/registry.mjs +7 -28
  91. package/dist/src/mcp/server.mjs +34 -1
  92. package/dist/src/mcp/tools/agentic-sandbox.mjs +8 -7
  93. package/dist/src/mcp/tools/command-run.mjs +3 -2
  94. package/dist/src/mcp/tools/decision.mjs +49 -48
  95. package/dist/src/mcp/tools/discovery.mjs +46 -21
  96. package/dist/src/mcp/tools/orchestration.mjs +22 -22
  97. package/dist/src/mcp/tools/subsystems.mjs +9 -8
  98. package/dist/src/mcp/tools/worker-invoke.mjs +17 -4
  99. package/dist/src/mcp/tools/writer-profiles.mjs +1 -1
  100. package/dist/src/memory/audit.js +719 -0
  101. package/dist/src/memory/canonical-context.js +392 -13
  102. package/dist/src/memory/canonical-maintenance.js +95 -0
  103. package/dist/src/memory/cli-result.js +22 -0
  104. package/dist/src/memory/cli.js +176 -0
  105. package/dist/src/memory/context-pack.js +57 -6
  106. package/dist/src/memory/cost.js +512 -0
  107. package/dist/src/memory/firewall-classification.d.mts +7 -0
  108. package/dist/src/memory/firewall-classification.mjs +32 -0
  109. package/dist/src/memory/index.js +8 -0
  110. package/dist/src/memory/line-maintenance.js +68 -0
  111. package/dist/src/memory/maintenance-cli.js +286 -0
  112. package/dist/src/memory/maintenance-contract.js +136 -0
  113. package/dist/src/memory/maintenance-index.js +18 -0
  114. package/dist/src/memory/maintenance-owner.js +2 -0
  115. package/dist/src/memory/maintenance-record.js +138 -0
  116. package/dist/src/memory/maintenance.js +254 -0
  117. package/dist/src/memory/provider-memory-adapter.js +154 -0
  118. package/dist/src/memory/recommend-cli.js +83 -0
  119. package/dist/src/memory/recommend.js +269 -0
  120. package/dist/src/memory/scheduled.js +81 -0
  121. package/dist/src/memory/taxonomy.js +44 -0
  122. package/dist/src/mission-protocol/codecs.js +19 -9
  123. package/dist/src/models/config-loader.js +11 -1
  124. package/dist/src/models/model-capabilities.v1.json +74 -50
  125. package/dist/src/models/provider-policy.js +125 -62
  126. package/dist/src/models/resolver.js +45 -8
  127. package/dist/src/models/worker-installation.d.mts +7 -0
  128. package/dist/src/models/worker-installation.mjs +169 -37
  129. package/dist/src/models/wrapper-route.js +1 -1
  130. package/dist/src/output-modes/registry.js +8 -7
  131. package/dist/src/plugin/metadata-validator.js +1 -1
  132. package/dist/src/providers/deploy-version.d.mts +1 -0
  133. package/dist/src/providers/deploy-version.mjs +17 -0
  134. package/dist/src/providers/provider-definitions.js +19 -16
  135. package/dist/src/providers/skill-ownership.d.mts +11 -2
  136. package/dist/src/providers/skill-ownership.mjs +35 -17
  137. package/dist/src/rules/activation.d.mts +11 -2
  138. package/dist/src/rules/activation.mjs +82 -6
  139. package/dist/src/rules/inventory.js +1 -1
  140. package/dist/src/rules/rule-frontmatter.schema.json +2 -0
  141. package/dist/src/schema/zod-validation.d.mts +6 -0
  142. package/dist/src/schema/zod-validation.mjs +50 -0
  143. package/dist/src/serve/executor-registry.js +297 -20
  144. package/dist/src/serve/executor-token.d.mts +1 -0
  145. package/dist/src/serve/executor-token.mjs +8 -0
  146. package/dist/src/serve/shared-host-scheduler.js +1102 -31
  147. package/dist/src/serve/worker-invocation.js +114 -15
  148. package/dist/src/sessions/adapters/claude.js +19 -18
  149. package/dist/src/sessions/adapters/codex.js +33 -19
  150. package/dist/src/sessions/adapters/copilot.js +14 -13
  151. package/dist/src/sessions/adapters/cursor.js +19 -18
  152. package/dist/src/sessions/adapters/deepseek-harness.js +9 -8
  153. package/dist/src/sessions/adapters/factory.js +11 -10
  154. package/dist/src/sessions/adapters/generic.js +32 -23
  155. package/dist/src/sessions/adapters/grokbot.js +35 -35
  156. package/dist/src/sessions/adapters/hermes.js +20 -19
  157. package/dist/src/sessions/adapters/muse.js +50 -49
  158. package/dist/src/sessions/adapters/omp.js +5 -4
  159. package/dist/src/sessions/adapters/openclaw.js +30 -29
  160. package/dist/src/sessions/adapters/opencode.js +26 -26
  161. package/dist/src/sessions/adapters/openhuman.js +24 -23
  162. package/dist/src/sessions/adapters/pi.js +5 -4
  163. package/dist/src/sessions/adapters/windsurf.js +8 -8
  164. package/dist/src/sessions/analytics.js +10 -9
  165. package/dist/src/sessions/batch-contracts.js +1 -1
  166. package/dist/src/sessions/batch-import.js +202 -2
  167. package/dist/src/sessions/candidates.js +7 -6
  168. package/dist/src/sessions/contracts.js +73 -54
  169. package/dist/src/sessions/coverage-preflight.js +26 -1
  170. package/dist/src/sessions/output-registration.js +11 -10
  171. package/dist/src/sessions/policy.js +18 -7
  172. package/dist/src/sessions/refresh.js +2 -3
  173. package/dist/src/sessions/repository.js +4 -2
  174. package/dist/src/sessions/workspace-discovery.js +92 -26
  175. package/dist/src/smiths/context-pipeline/aiwg-md.js +18 -1
  176. package/dist/src/smiths/context-pipeline/claude-hook.js +42 -6
  177. package/dist/src/smiths/context-pipeline/parallelism-section.js +72 -5
  178. package/dist/src/smiths/context-pipeline/workspace-context.js +106 -10
  179. package/dist/src/update/checker.d.mts +4 -0
  180. package/dist/src/update/checker.mjs +14 -0
  181. package/dist/src/writing/exemplar-selection.js +6 -6
  182. package/dist/src/writing/voice-evaluation.js +24 -23
  183. package/dist/src/writing/writer-migration.js +14 -13
  184. package/dist/src/writing/writer-profile.js +19 -18
  185. package/dist/src/writing/writing-brief.js +18 -17
  186. package/dist/src/writing/writing-receipt.js +47 -46
  187. package/package.json +5 -2
  188. package/schemas/decision/DecisionReview.schema.json +78 -1
  189. package/schemas/mission-v1.schema.json +3 -0
  190. package/tools/agents/deploy-agents.mjs +67 -39
  191. package/tools/agents/providers/antigravity.mjs +6 -1
  192. package/tools/agents/providers/base.mjs +19 -13
  193. package/tools/agents/providers/claude.mjs +1 -1
  194. package/tools/agents/providers/codex.mjs +50 -56
  195. package/tools/agents/providers/copilot.mjs +8 -2
  196. package/tools/agents/providers/cursor.mjs +1 -1
  197. package/tools/agents/providers/deepseek-harness.mjs +1 -1
  198. package/tools/agents/providers/factory.mjs +7 -1
  199. package/tools/agents/providers/grok-build.mjs +18 -2
  200. package/tools/agents/providers/grokbot.mjs +1 -1
  201. package/tools/agents/providers/hermes.mjs +7 -13
  202. package/tools/agents/providers/muse-hooks.mjs +21 -14
  203. package/tools/agents/providers/muse.mjs +7 -2
  204. package/tools/agents/providers/omp.mjs +28 -4
  205. package/tools/agents/providers/opencode.mjs +14 -5
  206. package/tools/agents/providers/openhuman.mjs +1 -1
  207. package/tools/agents/providers/pi.mjs +1 -1
  208. package/tools/agents/providers/provider-prepare-coordinator.mjs +29 -9
  209. package/tools/agents/providers/rule-delivery.mjs +263 -71
  210. package/tools/agents/providers/windsurf.mjs +7 -0
  211. package/tools/cli/workspace-status.mjs +5 -0
  212. package/tools/commands/deploy-prompts-codex.mjs +11 -8
  213. package/tools/ralph-external/lib/codex-adapter.mjs +6 -2
  214. package/tools/ralph-external/lib/muse-adapter.mjs +12 -2
  215. package/tools/ralph-external/lib/worker-health.mjs +1 -1
  216. package/tools/ralph-external/lib/worker-isolation.mjs +65 -9
  217. package/tools/ralph-external/process-monitor.mjs +7 -4
  218. package/tools/ralph-external/session-launcher.mjs +280 -32
  219. package/tools/skills/deploy-skills-codex.mjs +11 -7
  220. package/vscode-extension/schemas/aiwg.config.v1.json +11 -1
@@ -0,0 +1,512 @@
1
+ import { z } from 'zod';
2
+ import { dateTime, number } from '../schema/zod-validation.mjs';
3
+ import { guardRulesInlineBudget, resolveRulesInlineBudget } from '../rules/inline-budget.mjs';
4
+ /**
5
+ * Resident context cost and memory utility (#3281).
6
+ *
7
+ * Read-only attribution over a `MemoryAudit` report. This module never reads
8
+ * session telemetry, never contacts a provider and never writes anything:
9
+ * every value that cannot be derived from local static evidence stays
10
+ * `unknown` (null tokens, 'unknown' confidence) rather than a guessed number.
11
+ *
12
+ * Token estimation reuses the repository's existing estimators and adds no
13
+ * tokenizer:
14
+ * - per-file `ceil(UTF-8 bytes / 4)` from `tools/rules/measure-startup-context.mjs` (#2936);
15
+ * - the `UTF-8 bytes / 4` guard report from `src/rules/inline-budget.mjs` (#2938),
16
+ * embedded untouched via `guardRulesInlineBudget`.
17
+ */
18
+ export const TOKEN_ESTIMATOR_2936 = 'sum(ceil(UTF-8 bytes per file / 4)); not a tokenizer';
19
+ export const TOKEN_ESTIMATOR_2938 = 'UTF-8 bytes / 4';
20
+ export const STARTUP_MEASURE_TOOL = 'startup context measurement (#2936)';
21
+ /** Existing persistent ledger an operator may reuse; the cost view never writes to it. */
22
+ export const USAGE_LEDGER_NOTE = 'No new persistent telemetry is written. Caller-supplied usage evidence is held in memory only; to persist utility observations reuse the existing memory log via `aiwg memory append-log`.';
23
+ export const CostConfidenceSchema = z.enum(['measured', 'inferred', 'unknown']);
24
+ export const CostClassSchema = z.enum([
25
+ 'instruction', 'role', 'rule', 'skill', 'tool-schema', 'native-memory', 'stored', 'imported', 'other',
26
+ ]);
27
+ export const CostItemLayerSchema = z.enum(['startup', 'per-task', 'overhead', 'stored', 'unknown']);
28
+ const LayerCostSchema = z.strictObject({
29
+ bytes: number().nullable(),
30
+ tokens: number().nullable(),
31
+ estimator: z.string().min(1),
32
+ confidence: CostConfidenceSchema,
33
+ basis: z.string().min(1),
34
+ });
35
+ const UtilitySchema = z.strictObject({
36
+ exposures: number(),
37
+ exposureKinds: z.array(z.string()),
38
+ retrieved: z.boolean().nullable(),
39
+ used: z.boolean().nullable(),
40
+ rejected: z.boolean().nullable(),
41
+ outcome: z.enum(['unknown', 'retrieved-unused', 'used', 'rejected']),
42
+ evidence: z.string().nullable(),
43
+ });
44
+ export const CostAttributionSchema = z.strictObject({
45
+ id: z.string().min(1),
46
+ sourcePath: z.string().min(1),
47
+ costClass: CostClassSchema,
48
+ bytes: number().nullable(),
49
+ tokens: number().nullable(),
50
+ estimator: z.string().min(1),
51
+ confidence: CostConfidenceSchema,
52
+ layer: CostItemLayerSchema,
53
+ imported: z.boolean(),
54
+ duplicateGroup: z.string().nullable(),
55
+ utility: UtilitySchema,
56
+ });
57
+ const ClassTotalSchema = z.strictObject({
58
+ items: number(),
59
+ bytes: number().nullable(),
60
+ tokens: number().nullable(),
61
+ estimator: z.string().min(1),
62
+ confidence: CostConfidenceSchema,
63
+ });
64
+ const DemotionAnchorSchema = z.strictObject({
65
+ kind: z.enum(['indexed-record', 'include-stub', 'discovery-query']),
66
+ locator: z.string().min(1),
67
+ bytes: number(),
68
+ tokens: number(),
69
+ estimator: z.string().min(1),
70
+ confidence: CostConfidenceSchema,
71
+ note: z.string().min(1),
72
+ });
73
+ const DemotionTargetSchema = z.strictObject({
74
+ id: z.string().min(1),
75
+ sourcePath: z.string().min(1),
76
+ reachable: z.boolean(),
77
+ before: z.strictObject({ bytes: number().nullable(), tokens: number().nullable() }),
78
+ after: z.strictObject({ residentBytes: number(), residentTokens: number(), anchorBytes: number(), anchorTokens: number() }),
79
+ anchors: z.array(DemotionAnchorSchema),
80
+ warnings: z.array(z.string().min(1)),
81
+ });
82
+ const StartupMeasurementSchema = z.object({
83
+ version: number().optional(),
84
+ token_estimate: z.string().optional(),
85
+ providers: z.record(z.string(), z.object({ startup: z.object({ bytes: number(), estimated_tokens: number() }).catchall(z.unknown()) }).catchall(z.unknown())),
86
+ }).catchall(z.unknown());
87
+ export const MemoryCostSchema = z.strictObject({
88
+ schemaVersion: z.literal('aiwg.memory-cost.v1'),
89
+ at: dateTime(),
90
+ workspace: z.string().min(1),
91
+ scope: z.string().min(1),
92
+ estimator: z.string().min(1),
93
+ summary: z.strictObject({
94
+ byClass: z.partialRecord(CostClassSchema, ClassTotalSchema),
95
+ imported: ClassTotalSchema,
96
+ duplicated: ClassTotalSchema,
97
+ layers: z.strictObject({
98
+ startup: LayerCostSchema,
99
+ perTask: LayerCostSchema,
100
+ overhead: LayerCostSchema,
101
+ usageBilling: LayerCostSchema,
102
+ cacheDiscounts: LayerCostSchema,
103
+ }),
104
+ }),
105
+ items: z.array(CostAttributionSchema),
106
+ inlineBudget: z.strictObject({
107
+ estimator: z.string().min(1),
108
+ limit: number(),
109
+ configSource: z.string().min(1),
110
+ providers: z.array(z.strictObject({
111
+ provider: z.string().min(1),
112
+ selected_bytes: number(),
113
+ selected_tokens: number(),
114
+ exceeded: z.boolean(),
115
+ contributors: z.array(z.strictObject({ path: z.string().min(1), bytes: number(), estimated_tokens: number() })),
116
+ scopeNote: z.string().min(1),
117
+ })),
118
+ }),
119
+ startupMeasurement: z.strictObject({
120
+ status: z.enum(['matched', 'unknown']),
121
+ estimator: z.string().min(1),
122
+ providers: z.array(z.strictObject({
123
+ provider: z.string().min(1),
124
+ measuredStartupBytes: number().nullable(),
125
+ measuredStartupTokens: number().nullable(),
126
+ staticResidentBytes: number().nullable(),
127
+ note: z.string().min(1),
128
+ })),
129
+ note: z.string().min(1),
130
+ }),
131
+ telemetry: z.strictObject({
132
+ store: z.string().nullable(),
133
+ writesNewTelemetry: z.boolean(),
134
+ retention: z.string().min(1),
135
+ auditComplete: z.boolean(),
136
+ exclusions: z.array(z.string()),
137
+ }),
138
+ demotionPreview: z.strictObject({
139
+ targets: z.array(DemotionTargetSchema),
140
+ totals: z.strictObject({
141
+ beforeTokens: number().nullable(),
142
+ afterAnchorTokens: number(),
143
+ residentTokensRemoved: number().nullable(),
144
+ }),
145
+ }).nullable(),
146
+ });
147
+ function categoryClass(category) {
148
+ switch (category) {
149
+ case 'instruction':
150
+ case 'prompt':
151
+ return 'instruction';
152
+ case 'role':
153
+ return 'role';
154
+ case 'rule':
155
+ return 'rule';
156
+ case 'skill':
157
+ return 'skill';
158
+ case 'tool-description':
159
+ return 'tool-schema';
160
+ case 'native-memory':
161
+ return 'native-memory';
162
+ case 'memory-store':
163
+ case 'compound-memory':
164
+ case 'registry':
165
+ case 'tool-config':
166
+ return 'stored';
167
+ case 'transitive-context':
168
+ return 'imported';
169
+ default:
170
+ return 'other';
171
+ }
172
+ }
173
+ function itemLayer(item) {
174
+ if (item.record?.placement === 'resident')
175
+ return 'startup';
176
+ if (item.record?.placement === 'task-context' || item.category === 'prompt')
177
+ return 'per-task';
178
+ if (item.category === 'tool-description')
179
+ return 'overhead';
180
+ if (item.record)
181
+ return 'stored';
182
+ return 'unknown';
183
+ }
184
+ /** Static inventory is never live telemetry: on-disk evidence only supports inference. */
185
+ function confidenceFor(item) {
186
+ if (item.bytes === null || item.bytes === undefined)
187
+ return 'unknown';
188
+ if (item.observation.status === 'observed')
189
+ return 'measured';
190
+ return 'inferred';
191
+ }
192
+ export function estimateTokens(bytes) {
193
+ if (bytes === null || bytes === undefined)
194
+ return null;
195
+ return Math.ceil(bytes / 4);
196
+ }
197
+ /** Read-only attribution. Never touches a filesystem, session or network. */
198
+ export function costMemory(report, options = {}) {
199
+ const at = options.at ?? new Date().toISOString();
200
+ const digestCounts = new Map();
201
+ for (const item of report.items) {
202
+ if (item.digest)
203
+ digestCounts.set(item.digest, (digestCounts.get(item.digest) ?? 0) + 1);
204
+ }
205
+ const usage = options.usage ?? {};
206
+ const items = report.items.map(item => {
207
+ const costClass = categoryClass(item.category);
208
+ const layer = itemLayer(item);
209
+ const confidence = confidenceFor(item);
210
+ const tokens = estimateTokens(item.bytes);
211
+ const imported = costClass === 'imported' || item.exposures.some(e => e.kind === 'include');
212
+ const duplicateGroup = item.digest && (digestCounts.get(item.digest) ?? 0) > 1 ? item.digest : null;
213
+ const evidence = usage[item.id];
214
+ const retrieved = evidence?.retrieved ?? null;
215
+ const used = evidence?.used ?? null;
216
+ const rejected = evidence?.rejected ?? null;
217
+ return {
218
+ id: item.id,
219
+ sourcePath: item.sourcePath,
220
+ costClass,
221
+ bytes: item.bytes,
222
+ tokens,
223
+ estimator: TOKEN_ESTIMATOR_2936,
224
+ confidence,
225
+ layer,
226
+ imported,
227
+ duplicateGroup,
228
+ utility: {
229
+ exposures: item.exposures.length,
230
+ exposureKinds: [...new Set(item.exposures.map(e => e.kind))],
231
+ retrieved,
232
+ used,
233
+ rejected,
234
+ outcome: used === true ? 'used' : rejected === true ? 'rejected' : retrieved === true ? 'retrieved-unused' : 'unknown',
235
+ evidence: evidence?.evidence ?? null,
236
+ },
237
+ };
238
+ });
239
+ const classes = CostClassSchema.options;
240
+ const byClass = Object.fromEntries(classes.map(name => {
241
+ const group = items.filter(i => i.costClass === name);
242
+ const bytes = group.every(i => i.bytes === null) ? null : group.reduce((sum, i) => sum + (i.bytes ?? 0), 0);
243
+ const tokens = group.every(i => i.tokens === null) ? null : group.reduce((sum, i) => sum + (i.tokens ?? 0), 0);
244
+ return [name, {
245
+ items: group.length,
246
+ bytes,
247
+ tokens,
248
+ estimator: TOKEN_ESTIMATOR_2936,
249
+ confidence: group.length === 0 || group.every(i => i.confidence === 'unknown')
250
+ ? 'unknown'
251
+ : group.every(i => i.confidence === 'measured') ? 'measured' : 'inferred',
252
+ }];
253
+ }));
254
+ const overlapping = (selected) => ({
255
+ items: selected.length,
256
+ bytes: selected.every(i => i.bytes === null) ? null : selected.reduce((sum, i) => sum + (i.bytes ?? 0), 0),
257
+ tokens: selected.every(i => i.tokens === null) ? null : selected.reduce((sum, i) => sum + (i.tokens ?? 0), 0),
258
+ estimator: TOKEN_ESTIMATOR_2936,
259
+ confidence: selected.length === 0 || selected.every(i => i.confidence === 'unknown') ? 'unknown' : 'inferred',
260
+ });
261
+ const startupGroup = items.filter(i => i.layer === 'startup');
262
+ const perTaskGroup = items.filter(i => i.layer === 'per-task');
263
+ const overheadGroup = items.filter(i => i.layer === 'overhead');
264
+ const layers = {
265
+ startup: {
266
+ bytes: startupGroup.every(i => i.bytes === null) ? null : startupGroup.reduce((s, i) => s + (i.bytes ?? 0), 0),
267
+ tokens: startupGroup.every(i => i.tokens === null) ? null : startupGroup.reduce((s, i) => s + (i.tokens ?? 0), 0),
268
+ estimator: TOKEN_ESTIMATOR_2936,
269
+ confidence: startupGroup.length === 0 || startupGroup.every(i => i.confidence === 'unknown') ? 'unknown' : 'inferred',
270
+ basis: 'Static resident inventory; live activation and enabled state unverified',
271
+ },
272
+ perTask: {
273
+ bytes: perTaskGroup.every(i => i.bytes === null) ? null : perTaskGroup.reduce((s, i) => s + (i.bytes ?? 0), 0),
274
+ tokens: null,
275
+ estimator: TOKEN_ESTIMATOR_2936,
276
+ confidence: 'unknown',
277
+ basis: 'Eligible per-task surfaces only; injected bytes per task are unobserved statically',
278
+ },
279
+ overhead: {
280
+ bytes: overheadGroup.every(i => i.bytes === null) ? null : overheadGroup.reduce((s, i) => s + (i.bytes ?? 0), 0),
281
+ tokens: null,
282
+ estimator: TOKEN_ESTIMATOR_2936,
283
+ confidence: 'unknown',
284
+ basis: 'Declared tool/context description bytes; repetition per call requires runtime telemetry',
285
+ },
286
+ usageBilling: {
287
+ bytes: null,
288
+ tokens: null,
289
+ estimator: TOKEN_ESTIMATOR_2936,
290
+ confidence: 'unknown',
291
+ basis: 'Actual usage and billing have no local evidence surface',
292
+ },
293
+ cacheDiscounts: {
294
+ bytes: null,
295
+ tokens: null,
296
+ estimator: TOKEN_ESTIMATOR_2936,
297
+ confidence: 'unknown',
298
+ basis: 'Provider cache discounts have no local evidence surface',
299
+ },
300
+ };
301
+ // #2938: reuse the inline-budget guard over static resident rule candidates.
302
+ // Live rule activation (isAlwaysOnRule) is owned by rule-binding; the guard
303
+ // input here is static eligibility, never a live selection claim.
304
+ const env = options.env ?? process.env;
305
+ const limit = resolveRulesInlineBudget(options.inlineBudgetConfig ?? {}, env);
306
+ const inlineBudgetProviders = report.providers.map(p => {
307
+ const candidates = items.filter(i => i.costClass === 'rule'
308
+ && i.layer === 'startup'
309
+ && i.bytes !== null
310
+ && report.items.find(a => a.id === i.id)?.exposures.some(e => e.provider === p.id));
311
+ const guarded = guardRulesInlineBudget({
312
+ provider: p.id,
313
+ files: candidates.map(i => ({ path: i.sourcePath, bytes: i.bytes })),
314
+ config: options.inlineBudgetConfig ?? {},
315
+ env,
316
+ reportOnly: true,
317
+ });
318
+ return {
319
+ provider: guarded.report.provider,
320
+ selected_bytes: guarded.report.selected_bytes,
321
+ selected_tokens: guarded.report.selected_tokens,
322
+ exceeded: guarded.report.exceeded,
323
+ contributors: guarded.report.contributors,
324
+ scopeNote: 'Static resident rule candidates; live activation-selected content may differ',
325
+ };
326
+ });
327
+ // #2936: cross-reference a startup-measurement report when supplied; the
328
+ // measured surface and this static inventory are reported side by side.
329
+ let startupMeasurement;
330
+ if (options.startupMeasurement === undefined) {
331
+ startupMeasurement = {
332
+ status: 'unknown',
333
+ estimator: TOKEN_ESTIMATOR_2936,
334
+ providers: report.providers.map(p => ({
335
+ provider: p.id,
336
+ measuredStartupBytes: null,
337
+ measuredStartupTokens: null,
338
+ staticResidentBytes: startupGroup.some(i => report.items.find(a => a.id === i.id)?.exposures.some(e => e.provider === p.id))
339
+ ? startupGroup.filter(i => report.items.find(a => a.id === i.id)?.exposures.some(e => e.provider === p.id))
340
+ .reduce((s, i) => s + (i.bytes ?? 0), 0)
341
+ : null,
342
+ note: `No ${STARTUP_MEASURE_TOOL} report was supplied with --startup-measurement; measured startup bytes are unknown`,
343
+ })),
344
+ note: `Supply a ${STARTUP_MEASURE_TOOL} report with --startup-measurement to compare measured deployment bytes against this static inventory`,
345
+ };
346
+ }
347
+ else {
348
+ const parsed = StartupMeasurementSchema.parse(options.startupMeasurement);
349
+ startupMeasurement = {
350
+ status: 'matched',
351
+ estimator: parsed.token_estimate ?? TOKEN_ESTIMATOR_2936,
352
+ providers: report.providers.map(p => {
353
+ const measured = parsed.providers[p.id]?.startup;
354
+ const resident = startupGroup.filter(i => report.items.find(a => a.id === i.id)?.exposures.some(e => e.provider === p.id));
355
+ return {
356
+ provider: p.id,
357
+ measuredStartupBytes: measured?.bytes ?? null,
358
+ measuredStartupTokens: measured?.estimated_tokens ?? null,
359
+ staticResidentBytes: resident.length ? resident.reduce((s, i) => s + (i.bytes ?? 0), 0) : null,
360
+ note: 'Measured deployment surface beside static resident inventory; neither establishes live injection',
361
+ };
362
+ }),
363
+ note: 'Measured surface includes emitted indexes and behavior bodies; static inventory includes linked context candidates',
364
+ };
365
+ }
366
+ const demotionPreview = options.demote?.length
367
+ ? previewDemotion(report, items, options.demote)
368
+ : null;
369
+ return MemoryCostSchema.parse({
370
+ schemaVersion: 'aiwg.memory-cost.v1',
371
+ at,
372
+ workspace: report.workspace,
373
+ scope: report.scope,
374
+ estimator: TOKEN_ESTIMATOR_2936,
375
+ summary: {
376
+ byClass,
377
+ imported: overlapping(items.filter(i => i.imported)),
378
+ duplicated: overlapping(items.filter(i => i.duplicateGroup !== null)),
379
+ layers,
380
+ },
381
+ items: items.sort((a, b) => a.sourcePath.localeCompare(b.sourcePath)),
382
+ inlineBudget: {
383
+ estimator: TOKEN_ESTIMATOR_2938,
384
+ limit,
385
+ configSource: env.AIWG_RULES_INLINE_BUDGET_TOKENS !== undefined
386
+ ? 'AIWG_RULES_INLINE_BUDGET_TOKENS'
387
+ : options.inlineBudgetConfig?.rules?.inline_budget_tokens !== undefined ? 'aiwg.config rules.inline_budget_tokens' : 'default',
388
+ providers: inlineBudgetProviders,
389
+ },
390
+ startupMeasurement,
391
+ telemetry: {
392
+ store: Object.keys(usage).length ? 'caller-supplied usage evidence (in-memory only)' : null,
393
+ writesNewTelemetry: false,
394
+ retention: USAGE_LEDGER_NOTE,
395
+ auditComplete: report.coverage.complete,
396
+ exclusions: report.coverage.exclusions,
397
+ },
398
+ demotionPreview,
399
+ });
400
+ }
401
+ function previewDemotion(report, items, selectors) {
402
+ const byId = new Map(items.map(i => [i.id, i]));
403
+ const byPath = new Map(items.map(i => [i.sourcePath, i]));
404
+ const targets = [];
405
+ let beforeTokens = 0;
406
+ let removed = 0;
407
+ let anchorTokens = 0;
408
+ for (const selector of selectors) {
409
+ const item = byId.get(selector) ?? byPath.get(selector);
410
+ if (!item)
411
+ throw new Error(`Demotion preview target is not a costed audit item: ${selector}`);
412
+ const auditItem = report.items.find(a => a.id === item.id);
413
+ const warnings = [];
414
+ if (item.layer !== 'startup')
415
+ warnings.push('Target is not startup-resident; demotion preview assumes a resident to indexed move');
416
+ if (item.imported) {
417
+ warnings.push('Native `@` imports still consume startup context at load; splitting files is not demotion');
418
+ }
419
+ // Anchors keep the demoted body reachable: the indexed record identity,
420
+ // every static include/reference path, and the discovery query surface.
421
+ // A loaded body linked by import or reference never anchors at zero cost.
422
+ const anchors = [];
423
+ if (auditItem.record) {
424
+ const locator = `indexed:${auditItem.record.id}`;
425
+ const bytes = Buffer.byteLength(locator, 'utf8');
426
+ anchors.push({
427
+ kind: 'indexed-record',
428
+ locator,
429
+ bytes,
430
+ tokens: Math.max(1, Math.ceil(bytes / 4)),
431
+ estimator: TOKEN_ESTIMATOR_2936,
432
+ confidence: 'inferred',
433
+ note: 'Indexed record identity retained for retrieval after demotion',
434
+ });
435
+ }
436
+ for (const exposure of auditItem.exposures) {
437
+ if (exposure.kind !== 'include' && exposure.kind !== 'reference')
438
+ continue;
439
+ const locator = `stub:${exposure.path}`;
440
+ const bytes = Buffer.byteLength(locator, 'utf8');
441
+ anchors.push({
442
+ kind: exposure.kind === 'include' ? 'include-stub' : 'discovery-query',
443
+ locator,
444
+ bytes,
445
+ tokens: Math.max(1, Math.ceil(bytes / 4)),
446
+ estimator: TOKEN_ESTIMATOR_2936,
447
+ confidence: 'inferred',
448
+ note: exposure.kind === 'include'
449
+ ? 'Import stub remains loadable on demand; loading it consumes context'
450
+ : 'Discovery anchor for on-demand retrieval; loading it consumes context',
451
+ });
452
+ }
453
+ const reachable = anchors.length > 0;
454
+ if (!reachable)
455
+ warnings.push('No indexed path or exposure anchor exists; demotion would make this content unreachable');
456
+ const anchorBytes = anchors.reduce((s, a) => s + a.bytes, 0);
457
+ const anchorTokenSum = anchors.reduce((s, a) => s + a.tokens, 0);
458
+ anchorTokens += anchorTokenSum;
459
+ if (item.tokens === null)
460
+ beforeTokens = null;
461
+ else if (beforeTokens !== null)
462
+ beforeTokens += item.tokens;
463
+ if (item.layer === 'startup' && item.tokens !== null && removed !== null)
464
+ removed += item.tokens;
465
+ else if (item.layer === 'startup')
466
+ removed = null;
467
+ targets.push({
468
+ id: item.id,
469
+ sourcePath: item.sourcePath,
470
+ reachable,
471
+ before: { bytes: item.bytes, tokens: item.tokens },
472
+ after: { residentBytes: 0, residentTokens: 0, anchorBytes, anchorTokens: anchorTokenSum },
473
+ anchors,
474
+ warnings,
475
+ });
476
+ }
477
+ return { targets, totals: { beforeTokens, afterAnchorTokens: anchorTokens, residentTokensRemoved: removed } };
478
+ }
479
+ export function formatMemoryCost(report) {
480
+ const lines = [
481
+ `Memory cost (${report.scope}): ${report.workspace}`,
482
+ `Estimator: ${report.estimator}; unmeasurable layers stay unknown, never guessed`,
483
+ ...Object.entries(report.summary.byClass)
484
+ .filter(([, total]) => total.items > 0)
485
+ .map(([name, total]) => ` ${name}: ${total.items} item(s), ${total.bytes ?? 'unknown'} bytes, ${total.tokens ?? 'unknown'} tokens (${total.confidence})`),
486
+ ` imported (overlapping): ${report.summary.imported.items} item(s), ${report.summary.imported.tokens ?? 'unknown'} tokens`,
487
+ ` duplicated (overlapping): ${report.summary.duplicated.items} item(s), ${report.summary.duplicated.tokens ?? 'unknown'} tokens`,
488
+ `Layers: startup ${report.summary.layers.startup.tokens ?? 'unknown'} tokens (${report.summary.layers.startup.confidence}); `
489
+ + `per-task ${report.summary.layers.perTask.tokens ?? 'unknown'}; overhead ${report.summary.layers.overhead.tokens ?? 'unknown'}; `
490
+ + `usage/billing ${report.summary.layers.usageBilling.tokens ?? 'unknown'}; cache discounts ${report.summary.layers.cacheDiscounts.tokens ?? 'unknown'}`,
491
+ `Inline budget (#2938, ${report.inlineBudget.estimator}, limit ${report.inlineBudget.limit} via ${report.inlineBudget.configSource}): `
492
+ + report.inlineBudget.providers.map(p => `${p.provider} ${p.selected_tokens} tokens${p.exceeded ? ' EXCEEDED' : ''}`).join('; '),
493
+ `Startup measurement (#2936): ${report.startupMeasurement.status}`
494
+ + (report.startupMeasurement.status === 'matched'
495
+ ? ` (${report.startupMeasurement.providers.map(p => `${p.provider} measured ${p.measuredStartupBytes ?? 'unknown'} bytes vs static ${p.staticResidentBytes ?? 'unknown'} bytes`).join('; ')})`
496
+ : '; supply a measure-startup-context report to compare'),
497
+ `Telemetry: ${report.telemetry.store ?? 'none'}; writes new telemetry: ${report.telemetry.writesNewTelemetry}`,
498
+ ];
499
+ if (report.demotionPreview) {
500
+ lines.push(`Demotion preview: before ${report.demotionPreview.totals.beforeTokens ?? 'unknown'} tokens, `
501
+ + `anchors ${report.demotionPreview.totals.afterAnchorTokens} tokens, `
502
+ + `resident removed ${report.demotionPreview.totals.residentTokensRemoved ?? 'unknown'} tokens`);
503
+ for (const target of report.demotionPreview.targets) {
504
+ lines.push(` ${target.reachable ? 'reachable' : 'UNREACHABLE'} ${target.sourcePath}: `
505
+ + `${target.before.tokens ?? 'unknown'} -> ${target.after.anchorTokens} anchor token(s) `
506
+ + `[${target.anchors.map(a => a.locator).join(', ') || 'no anchor'}]`
507
+ + (target.warnings.length ? ` (${target.warnings.join('; ')})` : ''));
508
+ }
509
+ }
510
+ return lines.join('\n');
511
+ }
512
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1,7 @@
1
+ export interface ContextMemoryMetadata { digest?: string; hash?: string; trust?: string }
2
+ export function classifyContextMemory(input: {
3
+ digest: string; managed: boolean;
4
+ manifest?: ContextMemoryMetadata | null;
5
+ baselineEntry?: ContextMemoryMetadata | null;
6
+ threat?: { poisoning: boolean; signals: string[] };
7
+ }): { trust: string; reviewStatus: string; findings: string[]; manifestDrift: boolean };
@@ -0,0 +1,32 @@
1
+ /** Shared, body-free trust classification for static context inventories. */
2
+ export function classifyContextMemory({ digest, managed, manifest, baselineEntry, threat }) {
3
+ const manifestDrift = Boolean(manifest?.hash && manifest.hash !== digest);
4
+ const baselineChanged = Boolean(baselineEntry?.digest && baselineEntry.digest !== digest);
5
+ const findings = [];
6
+ let trust;
7
+ let reviewStatus;
8
+ if (baselineEntry?.trust === 'superseded') {
9
+ trust = 'superseded';
10
+ reviewStatus = 'superseded';
11
+ } else if (threat?.poisoning && !managed) {
12
+ trust = 'quarantined';
13
+ reviewStatus = 'quarantine-review-required';
14
+ findings.push('poisoning-signal');
15
+ } else if (manifestDrift) {
16
+ trust = 'stale';
17
+ reviewStatus = 'deployed-drift';
18
+ findings.push('stale-deployed-bytes');
19
+ } else if (baselineChanged) {
20
+ trust = 'quarantined';
21
+ reviewStatus = 'changed-review-required';
22
+ findings.push('changed-since-review');
23
+ } else if (['user-authored', 'generated', 'external', 'stale', 'quarantined', 'superseded'].includes(baselineEntry?.trust)) {
24
+ trust = baselineEntry.trust;
25
+ reviewStatus = 'reviewed';
26
+ } else {
27
+ trust = managed ? 'generated' : 'user-authored';
28
+ reviewStatus = 'unreviewed';
29
+ }
30
+ if (threat?.signals.length > 0 && (!threat.poisoning || managed)) findings.push('content-review-signal');
31
+ return { trust, reviewStatus, findings, manifestDrift };
32
+ }
@@ -1,4 +1,12 @@
1
1
  export * from './context-pack.js';
2
2
  export * from './canonical-context.js';
3
3
  export * from './intake.js';
4
+ export * from './taxonomy.js';
5
+ export * from './maintenance-record.js';
6
+ export * from './maintenance-contract.js';
7
+ export * from './provider-memory-adapter.js';
8
+ export * from './audit.js';
9
+ export * from './maintenance-owner.js';
10
+ export * from './maintenance.js';
11
+ export * from './recommend.js';
4
12
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,68 @@
1
+ import { refreshMaintenanceIndexes } from './maintenance-index.js';
2
+ import path from 'node:path';
3
+ import { existsSync } from 'node:fs';
4
+ import { fileURLToPath, pathToFileURL } from 'node:url';
5
+ import { MaintenanceOperationSchema } from './maintenance-contract.js';
6
+ import { loadMemoryRecord } from './maintenance-record.js';
7
+ /** Resolve the shipped lifecycle owner from source or compiled CLI installations. */
8
+ async function lineOwner() {
9
+ let directory = path.dirname(fileURLToPath(import.meta.url));
10
+ while (true) {
11
+ const candidate = path.join(directory, 'agentic/code/addons/line-memory/commands/line-memory.mjs');
12
+ if (existsSync(candidate))
13
+ return import(pathToFileURL(candidate).href);
14
+ const parent = path.dirname(directory);
15
+ if (parent === directory)
16
+ throw new Error('The line-memory lifecycle owner is unavailable');
17
+ directory = parent;
18
+ }
19
+ }
20
+ /** Adapter only: all durable mutations remain in line-memory's locked sidecar transaction. */
21
+ export class LineMaintenanceOwner {
22
+ name = 'line-memory';
23
+ projectRoot;
24
+ options;
25
+ constructor(projectRoot, options = {}) {
26
+ this.projectRoot = projectRoot;
27
+ this.options = options;
28
+ }
29
+ async records() {
30
+ return (await (await lineOwner()).readLineMaintenanceState(this.projectRoot)).records.map(loadMemoryRecord);
31
+ }
32
+ async snapshot() {
33
+ return (await (await lineOwner()).readLineMaintenanceState(this.projectRoot)).snapshot;
34
+ }
35
+ async validate(operation) {
36
+ MaintenanceOperationSchema.parse(operation);
37
+ await (await lineOwner()).validateLineMaintenance(this.projectRoot, operation);
38
+ }
39
+ async apply(operation, key) {
40
+ MaintenanceOperationSchema.parse(operation);
41
+ const receipt = await (await lineOwner()).applyLineMaintenance(this.projectRoot, operation, key, { verifyRetrieval: operation => this.verifyRetrieval(operation) });
42
+ await this.refreshIndex();
43
+ return receipt;
44
+ }
45
+ async receipt(key, options = {}) {
46
+ const receipt = await (await lineOwner()).readLineMaintenanceReceipt(this.projectRoot, key);
47
+ if (receipt !== undefined && !options.readOnly)
48
+ await this.refreshIndex();
49
+ return receipt;
50
+ }
51
+ async verifyEndState(operation, key) {
52
+ return (await lineOwner()).verifyLineMaintenanceEndState(this.projectRoot, operation, key);
53
+ }
54
+ async refreshIndex() {
55
+ await refreshMaintenanceIndexes(this.projectRoot);
56
+ }
57
+ async pending(operation) {
58
+ return (await lineOwner()).pendingLineMaintenance(this.projectRoot, operation);
59
+ }
60
+ async verifyRetrieval(operation) {
61
+ if (operation.owner?.name !== this.name)
62
+ return false;
63
+ if (this.options.verifyRetrieval)
64
+ return this.options.verifyRetrieval(operation);
65
+ throw new Error('line-memory resident removal is unsupported: no owner-native indexed retrieval projection is available');
66
+ }
67
+ }
68
+ //# sourceMappingURL=line-maintenance.js.map