@kontextmind/kxm 0.6.0

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 (227) hide show
  1. package/.claude-plugin/marketplace.json +19 -0
  2. package/.kxm/README.md +14 -0
  3. package/.kxm/assets/README.md +5 -0
  4. package/.kxm/assets/retrospectives/README.md +5 -0
  5. package/.kxm/config/README.md +5 -0
  6. package/.kxm/config/agents.json +43 -0
  7. package/.kxm/config/env.example +56 -0
  8. package/.kxm/config/update.example.yaml +9 -0
  9. package/.kxm/config/workflows/fix.json +160 -0
  10. package/.kxm/config/workflows/jira-development.json +116 -0
  11. package/.kxm/config/workflows/provenance-quorum.json +150 -0
  12. package/.kxm/config/workflows/v04-dogfood.json +72 -0
  13. package/CHANGELOG.md +465 -0
  14. package/LICENSE +21 -0
  15. package/README.md +306 -0
  16. package/SECURITY.md +72 -0
  17. package/docs/README.md +48 -0
  18. package/docs/agent-communication-envelopes-and-gates.md +553 -0
  19. package/docs/architecture.md +242 -0
  20. package/docs/assignment-runner.md +241 -0
  21. package/docs/configuration.md +361 -0
  22. package/docs/continuous-improvement.md +114 -0
  23. package/docs/getting-started.md +253 -0
  24. package/docs/kxm-handbook.md +1090 -0
  25. package/docs/operations.md +205 -0
  26. package/docs/provenance-gates.md +291 -0
  27. package/docs/skills.md +45 -0
  28. package/docs/templates/README.md +95 -0
  29. package/docs/templates/adr.md +88 -0
  30. package/docs/templates/architecture.md +120 -0
  31. package/docs/templates/bug-fix.md +109 -0
  32. package/docs/templates/feature.md +108 -0
  33. package/docs/templates/handoff.md +72 -0
  34. package/docs/templates/postmortem.md +77 -0
  35. package/docs/templates/research.md +100 -0
  36. package/docs/templates/review.md +85 -0
  37. package/docs/templates/runbook.md +73 -0
  38. package/docs/templates/test-plan.md +87 -0
  39. package/docs/templates/test-report.md +72 -0
  40. package/docs/test-matrix.md +121 -0
  41. package/docs/troubleshooting.md +249 -0
  42. package/docs/vnext/README.md +62 -0
  43. package/docs/vnext/architecture.md +185 -0
  44. package/docs/vnext/effects-and-recovery.md +172 -0
  45. package/docs/vnext/lifecycles.md +235 -0
  46. package/docs/vnext/migration.md +220 -0
  47. package/docs/vnext/routing.md +184 -0
  48. package/docs/vnext/synchronization.md +172 -0
  49. package/docs/vnext/terminology.md +240 -0
  50. package/docs/vnext/validation.md +335 -0
  51. package/docs/webhook-workflows.md +240 -0
  52. package/docs/workflow-guide.md +1150 -0
  53. package/examples/README.md +102 -0
  54. package/examples/provenance-workflow.json +40 -0
  55. package/examples/requester.ts +30 -0
  56. package/examples/reviewer-agent.ts +29 -0
  57. package/examples/roundtrip.ts +46 -0
  58. package/examples/vnext/.kxm/agents/coordinator.yaml +16 -0
  59. package/examples/vnext/.kxm/agents/critic-1.yaml +16 -0
  60. package/examples/vnext/.kxm/agents/critic-2.yaml +15 -0
  61. package/examples/vnext/.kxm/agents/critic-3.yaml +15 -0
  62. package/examples/vnext/.kxm/agents/implementer.yaml +15 -0
  63. package/examples/vnext/.kxm/agents/planner.yaml +13 -0
  64. package/examples/vnext/.kxm/agents/reproducer.yaml +15 -0
  65. package/examples/vnext/.kxm/agents/reviewer.yaml +15 -0
  66. package/examples/vnext/.kxm/gates.yaml +8 -0
  67. package/examples/vnext/.kxm/models/critic-claude.yaml +11 -0
  68. package/examples/vnext/.kxm/models/critic-gemini.yaml +11 -0
  69. package/examples/vnext/.kxm/models/critic-grok.yaml +12 -0
  70. package/examples/vnext/.kxm/models/implementation.yaml +14 -0
  71. package/examples/vnext/.kxm/models/primary.yaml +17 -0
  72. package/examples/vnext/.kxm/prices.yaml +111 -0
  73. package/examples/vnext/.kxm/project/env.yaml +7 -0
  74. package/examples/vnext/.kxm/project.yaml +32 -0
  75. package/examples/vnext/.kxm/repo/repo.yaml +8 -0
  76. package/examples/vnext/.kxm/workflows/default.yaml +92 -0
  77. package/examples/vnext/.kxm/workflows/fix.yaml +376 -0
  78. package/examples/vnext/.kxm/workflows/improve.yaml +57 -0
  79. package/examples/vnext/README.md +53 -0
  80. package/examples/vnext/records/assignment-result-recorded.json +63 -0
  81. package/examples/vnext/records/assignment-result.json +46 -0
  82. package/examples/vnext/records/context-candidate.json +42 -0
  83. package/examples/vnext/records/delivery-manifest.json +66 -0
  84. package/examples/vnext/records/effect-uncertainty-resolved-sync.json +67 -0
  85. package/examples/vnext/records/effect-uncertainty-resolved.json +62 -0
  86. package/examples/vnext/records/run-created.json +54 -0
  87. package/examples/vnext/records/sync-event.json +65 -0
  88. package/examples/vnext/repositories/api/.kxm/repo/env.yaml +7 -0
  89. package/examples/vnext/repositories/api/.kxm/repo/repo.yaml +8 -0
  90. package/examples/vnext/repositories/web/.kxm/repo/repo.yaml +8 -0
  91. package/examples/workflow-signal.ts +63 -0
  92. package/package.json +129 -0
  93. package/plugins/kxm/.claude-plugin/plugin.json +73 -0
  94. package/plugins/kxm/.mcp.json +19 -0
  95. package/plugins/kxm/README.md +93 -0
  96. package/plugins/kxm/dist/cli.js +42853 -0
  97. package/plugins/kxm/dist/client.js +416 -0
  98. package/plugins/kxm/dist/core.js +1823 -0
  99. package/plugins/kxm/dist/extension.js +3797 -0
  100. package/plugins/kxm/dist/mcp-server.js +17104 -0
  101. package/plugins/kxm/dist/runtime.js +23361 -0
  102. package/plugins/kxm/dist/server.js +13640 -0
  103. package/plugins/kxm/dist/vnext-runtime-supervisor.js +21109 -0
  104. package/plugins/kxm/package.json +12 -0
  105. package/plugins/kxm/skills/kxm/SKILL.md +97 -0
  106. package/plugins/kxm/skills/kxm/references/protocol.md +103 -0
  107. package/plugins/kxm/skills/kxm-session/SKILL.md +53 -0
  108. package/plugins/kxm/src/arbiter.ts +355 -0
  109. package/plugins/kxm/src/artifacts-exist.ts +62 -0
  110. package/plugins/kxm/src/autocomplete.ts +236 -0
  111. package/plugins/kxm/src/cli.ts +3707 -0
  112. package/plugins/kxm/src/client.ts +614 -0
  113. package/plugins/kxm/src/commands.ts +1063 -0
  114. package/plugins/kxm/src/config.ts +290 -0
  115. package/plugins/kxm/src/context/providers.ts +101 -0
  116. package/plugins/kxm/src/context-packet.ts +332 -0
  117. package/plugins/kxm/src/context.ts +499 -0
  118. package/plugins/kxm/src/core.ts +6 -0
  119. package/plugins/kxm/src/database.ts +563 -0
  120. package/plugins/kxm/src/diagnostics.ts +184 -0
  121. package/plugins/kxm/src/envelope.ts +118 -0
  122. package/plugins/kxm/src/extension.ts +895 -0
  123. package/plugins/kxm/src/external-effects.ts +299 -0
  124. package/plugins/kxm/src/github-watch.ts +255 -0
  125. package/plugins/kxm/src/hub-binding.ts +160 -0
  126. package/plugins/kxm/src/hub.ts +2502 -0
  127. package/plugins/kxm/src/improve.ts +383 -0
  128. package/plugins/kxm/src/inbox.ts +10 -0
  129. package/plugins/kxm/src/kxm-install-kind.ts +113 -0
  130. package/plugins/kxm/src/kxm-update-config.ts +39 -0
  131. package/plugins/kxm/src/kxm-update.ts +238 -0
  132. package/plugins/kxm/src/local-snapshot.ts +406 -0
  133. package/plugins/kxm/src/logger.ts +198 -0
  134. package/plugins/kxm/src/mcp-server.ts +143 -0
  135. package/plugins/kxm/src/memory.ts +385 -0
  136. package/plugins/kxm/src/nous-pi.ts +287 -0
  137. package/plugins/kxm/src/nous-provider.ts +729 -0
  138. package/plugins/kxm/src/price-calc.ts +87 -0
  139. package/plugins/kxm/src/prices.ts +121 -0
  140. package/plugins/kxm/src/protocol.ts +172 -0
  141. package/plugins/kxm/src/recovery.ts +211 -0
  142. package/plugins/kxm/src/redact.ts +26 -0
  143. package/plugins/kxm/src/retrospective.ts +400 -0
  144. package/plugins/kxm/src/routing.ts +830 -0
  145. package/plugins/kxm/src/runtime.ts +9 -0
  146. package/plugins/kxm/src/server.ts +117 -0
  147. package/plugins/kxm/src/session-work.ts +571 -0
  148. package/plugins/kxm/src/session.ts +184 -0
  149. package/plugins/kxm/src/skills.ts +535 -0
  150. package/plugins/kxm/src/state.ts +326 -0
  151. package/plugins/kxm/src/store.ts +637 -0
  152. package/plugins/kxm/src/studio-layout.ts +268 -0
  153. package/plugins/kxm/src/suggest.ts +162 -0
  154. package/plugins/kxm/src/task-manager.ts +244 -0
  155. package/plugins/kxm/src/telemetry.ts +116 -0
  156. package/plugins/kxm/src/tui.ts +1046 -0
  157. package/plugins/kxm/src/vnext-bindings.ts +403 -0
  158. package/plugins/kxm/src/vnext-config.ts +1646 -0
  159. package/plugins/kxm/src/vnext-engine-artifacts.ts +86 -0
  160. package/plugins/kxm/src/vnext-engine-command.ts +533 -0
  161. package/plugins/kxm/src/vnext-engine-compile.ts +722 -0
  162. package/plugins/kxm/src/vnext-engine-evidence.ts +273 -0
  163. package/plugins/kxm/src/vnext-engine-fold.ts +1400 -0
  164. package/plugins/kxm/src/vnext-engine-gate-records.ts +583 -0
  165. package/plugins/kxm/src/vnext-engine-plan.ts +717 -0
  166. package/plugins/kxm/src/vnext-engine.ts +2458 -0
  167. package/plugins/kxm/src/vnext-gate-hash.ts +10 -0
  168. package/plugins/kxm/src/vnext-harness.ts +1142 -0
  169. package/plugins/kxm/src/vnext-init.ts +430 -0
  170. package/plugins/kxm/src/vnext-migrate.ts +1848 -0
  171. package/plugins/kxm/src/vnext-oneshot-producer.ts +424 -0
  172. package/plugins/kxm/src/vnext-permission.ts +936 -0
  173. package/plugins/kxm/src/vnext-pi-producer.ts +628 -0
  174. package/plugins/kxm/src/vnext-repair.ts +1094 -0
  175. package/plugins/kxm/src/vnext-runtime-owner.ts +320 -0
  176. package/plugins/kxm/src/vnext-runtime-store.ts +1560 -0
  177. package/plugins/kxm/src/vnext-runtime-supervisor.ts +586 -0
  178. package/plugins/kxm/src/vnext-runtime.ts +663 -0
  179. package/plugins/kxm/src/vnext-template.ts +247 -0
  180. package/plugins/kxm/src/wiki.ts +313 -0
  181. package/plugins/kxm/src/workflow.ts +1548 -0
  182. package/schemas/vnext/README.md +46 -0
  183. package/schemas/vnext/agent.schema.json +40 -0
  184. package/schemas/vnext/assignment-result.schema.json +66 -0
  185. package/schemas/vnext/backup-manifest.schema.json +89 -0
  186. package/schemas/vnext/candidate.schema.json +109 -0
  187. package/schemas/vnext/common.schema.json +422 -0
  188. package/schemas/vnext/context-candidate.schema.json +76 -0
  189. package/schemas/vnext/context-packet.schema.json +192 -0
  190. package/schemas/vnext/delivery-manifest.schema.json +159 -0
  191. package/schemas/vnext/environment.schema.json +66 -0
  192. package/schemas/vnext/gate-registry.schema.json +109 -0
  193. package/schemas/vnext/handoff-manifest.schema.json +146 -0
  194. package/schemas/vnext/init-operation.schema.json +61 -0
  195. package/schemas/vnext/local-repository-bindings.schema.json +30 -0
  196. package/schemas/vnext/memory-record.schema.json +45 -0
  197. package/schemas/vnext/migration-decision.schema.json +26 -0
  198. package/schemas/vnext/migration-plan.schema.json +123 -0
  199. package/schemas/vnext/migration-receipt.schema.json +52 -0
  200. package/schemas/vnext/model.schema.json +42 -0
  201. package/schemas/vnext/permission-diff.schema.json +57 -0
  202. package/schemas/vnext/prices.schema.json +115 -0
  203. package/schemas/vnext/project.schema.json +85 -0
  204. package/schemas/vnext/repository.schema.json +24 -0
  205. package/schemas/vnext/run-event.schema.json +460 -0
  206. package/schemas/vnext/session-brief.schema.json +153 -0
  207. package/schemas/vnext/sync-event.schema.json +234 -0
  208. package/schemas/vnext/template-provenance.schema.json +38 -0
  209. package/schemas/vnext/workflow.schema.json +248 -0
  210. package/scripts/assignment-run.d.mts +354 -0
  211. package/scripts/assignment-run.mjs +4451 -0
  212. package/scripts/build-runtime.mjs +56 -0
  213. package/scripts/check-generated.mjs +77 -0
  214. package/scripts/check-versions.mjs +34 -0
  215. package/scripts/emit-codex-artifacts.d.mts +9 -0
  216. package/scripts/emit-codex-artifacts.mjs +91 -0
  217. package/scripts/harness-run.d.mts +83 -0
  218. package/scripts/harness-run.mjs +2095 -0
  219. package/scripts/kxm-hub.mjs +105 -0
  220. package/scripts/kxm-publish-npm.mjs +327 -0
  221. package/scripts/kxm-release-github.mjs +472 -0
  222. package/scripts/kxm-runtime-supervisor.mjs +7 -0
  223. package/scripts/kxm-worker.mjs +1127 -0
  224. package/scripts/kxm.mjs +27 -0
  225. package/scripts/roster-policy.d.mts +20 -0
  226. package/scripts/roster-policy.mjs +161 -0
  227. package/scripts/smoke-multi-pi.mjs +479 -0
@@ -0,0 +1,235 @@
1
+ # Durable lifecycles
2
+
3
+ All transitions are append-only events. A projection may materialize the
4
+ current state, but it cannot create a transition absent from the home Runtime's
5
+ event sequence.
6
+
7
+ ## Event ordering
8
+
9
+ Each run has a strictly increasing 1-based `sequence` assigned by its home
10
+ Runtime. Repeating an idempotent command returns the prior result and does not
11
+ append a duplicate semantic event. The hub deduplicates synchronized events by
12
+ `{projectId, runId, sequence}`.
13
+
14
+ UTC timestamps are audit/display data. Durations and timeouts use the Runtime's
15
+ monotonic clock and persisted duration samples.
16
+
17
+ ## Run request
18
+
19
+ A hub run request is coordination state, not execution state.
20
+
21
+ ```text
22
+ queued → offered → accepted
23
+ │ │ └── creates one home-owned run
24
+ │ ├── declined
25
+ │ └── expired
26
+ └── cancelled
27
+ ```
28
+
29
+ Acceptance is atomic with reserving a unique run ID and immutable
30
+ `homeRuntimeId`. A repeated request key returns the existing acceptance.
31
+
32
+ ## Run
33
+
34
+ ```text
35
+ created → preparing → running ↔ waiting
36
+ │ │
37
+ ├── blocked_uncertain
38
+ ├── cancelling → cancelled
39
+ ├── completed
40
+ └── failed
41
+ ```
42
+
43
+ | State | Meaning | Allowed exits |
44
+ |---|---|---|
45
+ | `created` | Identity, owner, and pinned revisions recorded | `preparing`, `cancelled`, `failed` |
46
+ | `preparing` | Inputs, capabilities, workspaces, secrets, and models are being verified; the run plan pin is recorded here | `running`, `cancelled`, `failed` |
47
+ | `running` | One top-level step is active | `waiting`, `blocked_uncertain`, `cancelling`, `completed`, `failed` |
48
+ | `waiting` | No model/process compute is required; a declared signal, lease, or approval is pending | `running`, `blocked_uncertain`, `cancelling`, `completed`, `failed`, `cancelled` |
49
+ | `blocked_uncertain` | An effect outcome cannot be proven | `running`, `cancelling`, `failed` |
50
+ | `cancelling` | Cancellation has been durably requested and child processes are draining | `cancelled`, `blocked_uncertain`, `failed` |
51
+ | `completed` | Declared success terminal reached | None |
52
+ | `failed` | Declared failure or exhausted budget reached | None |
53
+ | `cancelled` | Cancellation completed without unresolved owned effects | None |
54
+
55
+ Operator `cancelled` from `created` or `preparing` requires a recorded
56
+ `run.cancel_requested`. A compiled selected `terminalStatus=cancelled` may
57
+ still complete from `running` without that operator event.
58
+
59
+ A run cannot move to another Runtime by editing a projection or hub record.
60
+
61
+ ## Step and step attempt
62
+
63
+ Only one top-level step is active. Entering a step creates a new positive
64
+ `stepAttempt` number.
65
+
66
+ ```text
67
+ pending → preparing → running ↔ waiting
68
+ │ │
69
+ ├── blocked_uncertain
70
+ ├── passed
71
+ ├── failed
72
+ ├── skipped
73
+ └── cancelled
74
+ ```
75
+
76
+ A typed transition from a terminal step attempt selects the next step or a run
77
+ terminal. A back-edge creates a fresh step attempt and fresh assignment set.
78
+ `step.maxAttempts` bounds all entries/retries of that step for the run in
79
+ addition to global and per-edge transition budgets. Evidence is attempt-bound
80
+ unless its declaration explicitly allows reuse.
81
+
82
+ `skipped` is legal only when a validated workflow declares the skip outcome and
83
+ proves that no required approval or gate is bypassed.
84
+
85
+ ## Assignment
86
+
87
+ An assignment is logical work and may have more than one physical attempt.
88
+
89
+ ```text
90
+ created → accepted → dispatched → executing → result_recorded → terminal
91
+ ▲ │ │
92
+ │ ├── reattaching
93
+ └── retry_pending─┘ └── blocked_uncertain
94
+ ```
95
+
96
+ | State | Durable condition |
97
+ |---|---|
98
+ | `created` | Assignment identity, purpose, bounds, and requested evidence recorded |
99
+ | `accepted` | Runtime has resolved policy, agent, model, repository, tools, secrets, and executor |
100
+ | `dispatched` | Attempt identity and dispatch intent persisted before process start |
101
+ | `executing` | Invocation admitted and the attempt capability is usable. This slice is in-process (no OS process identity yet); later recovery still requires exact process/session proof |
102
+ | `reattaching` | Runtime is verifying the same process/session and event cursor |
103
+ | `result_recorded` | Structured attempt result and referenced receipts are durably stored |
104
+ | `retry_pending` | Policy permits another physical attempt after the prior attempt became terminal |
105
+ | `blocked_uncertain` | A dependent effect cannot be reconciled safely |
106
+ | `terminal` | The logical assignment outcome is final and immutable: passed, failed, or cancelled |
107
+
108
+ `assignmentId` remains stable. A retry moves the nonterminal assignment through
109
+ `retry_pending` to `accepted`, creates a new `attemptId`, and never rewrites or
110
+ exits the previous attempt's terminal state. The effective
111
+ `assignments.maxAttemptsPerAssignment` bounds physical attempts; the Runtime
112
+ may retry only outcomes and effect classes declared safe by trusted policy.
113
+
114
+ ## Assignment attempt
115
+
116
+ ```text
117
+ created → starting → executing → settling → terminal
118
+ │ │
119
+ │ ├── reattaching → executing
120
+ │ └── blocked_uncertain
121
+ └── connection_lost
122
+ ```
123
+
124
+ Reattachment to the same attempt requires all of:
125
+
126
+ - exact Runtime, run, assignment, and attempt identity;
127
+ - exact physical process or harness session identity;
128
+ - compatible executor/helper generation;
129
+ - valid last durable event cursor;
130
+ - no replacement process or attempt;
131
+ - unchanged scope epoch and grants.
132
+
133
+ If those facts cannot be proven, the Runtime either creates a new attempt after
134
+ safe reconciliation or enters `blocked_uncertain`.
135
+
136
+ ## Dynamic assignment panel
137
+
138
+ Every step has effective bounds:
139
+
140
+ ```text
141
+ minimum ≤ target ≤ maximum
142
+ maxParallel ≤ maximum
143
+ ```
144
+
145
+ The coordinator may create assignments only until `maximum`. Every assignment,
146
+ including one whose provider work began but failed to start fully, counts
147
+ against the step attempt's maximum. Each assignment also has a compiled physical
148
+ attempt ceiling; omitting a project override uses the step-kind default rather
149
+ than an unbounded retry policy.
150
+
151
+ Fail-closed compiled defaults:
152
+
153
+ | Step kind | Step attempts | Assignments | Physical attempts per assignment | Join |
154
+ |---|---:|---:|---:|---|
155
+ | Single agent | 1 | Exactly 1 | 1 | `all` |
156
+ | Deterministic gate | 1 | Exactly 1 | 1 | `all` |
157
+ | Human approval | 1 | Exactly 1 authorized decision | 1 | `all` |
158
+ | Wait | 1 | Exactly 1 signal | 1 | `all` |
159
+ | MOA | 1 | Exactly 1 unless the step declares a panel | 1 | `all` |
160
+
161
+ Current contract (`kxm.workflow.v1`): an omitted `assignments` block resolves for every kind to minimum 1, target = minimum, maximum = target, maxParallel = maximum, one physical attempt per assignment; an omitted `join` resolves to `all`. The loader checks these numbers and the compiler mirrors them exactly; the compiler never resolves a larger ceiling than the loader validated. A MOA step must declare its panel explicitly (see `fix.yaml`). The kind-level MOA default of target 3, minimum 2, maximum 3, all-settled with two valid completions is a Phase 7 change made to schema, loader, compiler, and this table in one change.
162
+
163
+ Templates may materialize larger reviewed attempt ceilings. No omitted field ever
164
+ means unlimited retries.
165
+ `first-success` is valid only for an explicitly speculative, safely cancellable
166
+ step. It is invalid for independent review.
167
+
168
+ ## Effect
169
+
170
+ ```text
171
+ intent_recorded → dispatched → observed → receipt_recorded → settled
172
+ │ │
173
+ └──────────┴── blocked_uncertain
174
+ ```
175
+
176
+ The intent, effect class, idempotency key, and expected receipt query are
177
+ recorded before dispatch. See [Effects and recovery](effects-and-recovery.md).
178
+
179
+ ## Delivery
180
+
181
+ A multi-repository delivery is explicitly non-atomic.
182
+
183
+ ```text
184
+ planned → preparing → delivering → completed
185
+ │ │
186
+ │ ├── partial
187
+ │ ├── blocked_uncertain
188
+ │ └── failed
189
+ └── cancelled
190
+ ```
191
+
192
+ Each repository has its own result and receipt. `partial` is a delivery-panel
193
+ state, not an individual assignment-result status. It never projects as
194
+ `completed`; remediation or compensation is explicit. Conversely, a manifest
195
+ with any `delivered` repository cannot project as `failed`, `cancelled`, or
196
+ `blocked_uncertain`: it is `partial` until the delivered work is explicitly
197
+ accounted for. Every `delivered` repository has at least one receipt.
198
+
199
+ ## Synchronization
200
+
201
+ ```text
202
+ local_event → sync_transform → outbox_pending → acknowledged
203
+ │ │
204
+ └── omitted ├── retry_pending
205
+ └── rejected
206
+ ```
207
+
208
+ `omitted` means the event contains no sync-worthy fields under policy. A
209
+ schema-invalid or unsafe transformation never enters the outbox. `rejected`
210
+ requires operator-visible diagnostics; the local run remains authoritative.
211
+
212
+ ## Session lifecycle
213
+
214
+ A physical agent session is reusable only within one exact run and compatible
215
+ scope epoch.
216
+
217
+ ```text
218
+ created → active ↔ idle → closed
219
+ │ │
220
+ └── rotate_scope → closed + new scope epoch
221
+ ```
222
+
223
+ Scope rotation occurs before an assignment with narrower or incompatible
224
+ repository, secret, tool, model, executor, or disclosure scope is dispatched.
225
+
226
+ ## Recovery invariants
227
+
228
+ 1. No terminal state exits.
229
+ 2. No sequence number is reused.
230
+ 3. No new process inherits an old `attemptId`.
231
+ 4. No prior step-attempt evidence silently satisfies a later attempt.
232
+ 5. No coordinator command expands a compiled policy ceiling.
233
+ 6. No unknown effect is replayed automatically.
234
+ 7. No session crosses a run or incompatible scope epoch.
235
+ 8. No hub projection changes home-owned run state.
@@ -0,0 +1,220 @@
1
+ # Migration and compatibility matrix
2
+
3
+ KXM vNext is introduced beside the current v0.5 transport/workflow surfaces.
4
+ Presence of vNext documents does not activate new behavior.
5
+
6
+ ## Surface matrix
7
+
8
+ | Current surface | vNext target | Migration rule |
9
+ |---|---|---|
10
+ | `.kxm/config/agents.json` aggregate roster | `.kxm/agents/<id>.yaml` individual definitions | Split records, infer ID from filename, preserve unrecognized fields in a migration report rather than silently dropping them |
11
+ | `gates.json` descriptive records | Workflow step/gate references plus registered deterministic adapters | Map only implemented gates; report names with no runner |
12
+ | `KXM_WEBHOOK_WORKFLOWS` inline JSON | `.kxm/workflows/<id>.yaml` | Materialize secret-free behavior; convert secret fields to references |
13
+ | `KXM_WEBHOOK_WORKFLOWS_FILE` JSON array | Individual workflow YAML files | Split definitions and validate typed transitions |
14
+ | `.kxm/config/workflows/*.json` including `/fix` | `.kxm/workflows/<id>.yaml` | Preserve typed transitions, immutable reproduction oracle, approved-plan hash, plan-hash requirements, producer policies, and attempt/transition budgets |
15
+ | Hub-selected project from environment | Git project identity plus Runtime-local binding | Detect and ask on ambiguity; do not derive durable identity from directory basename |
16
+ | Long-lived manually started Pi workers | Runtime-managed run-scoped sessions | Existing worker mode remains available during compatibility release |
17
+ | Shared/off workflow Pi history | `{run, agent, instance, scopeEpoch}` sessions | Never import shared conversation history into a narrower run scope |
18
+ | Hub-owned workflow state | Home Runtime event log with hub projection | Import completed history as legacy records; active-run cutover requires quiescence |
19
+ | SQLite schema v3 `kxm.db` | Runtime registry, per-project event stores, hub registry/project stores | Copy through versioned migration; never mutate the only database in place |
20
+ | Full peer message bodies in hub DB | Summary-first sync events | Existing bodies remain protected legacy data and are not re-emitted automatically |
21
+ | Project tokens/manual environment auth | Runtime enrollment and scoped credentials | Preserve current mode until enrollment is confirmed; never copy tokens into Git |
22
+ | `.kxm/config/env.example` | Built-in defaults plus optional scoped env YAML | Import only explicit portable differences; secrets become references |
23
+ | Retired product-prefixed init (empty directories) | Unified `kxm init` create/join/migrate/repair | Removed; `kxm init` is the only entry and the old init command fails closed |
24
+ | `kxm session start` manifest only | `kxm run` executable run | Do not reinterpret old session manifests as completed or active runs |
25
+ | Existing context items and journal | Pinned memory revisions and candidates | Preserve provenance/authority floors; no automatic executable promotion |
26
+
27
+ ## Compatibility releases and activation
28
+
29
+ Local Runtime support may ship publicly before hub vNext, but it remains beside
30
+ existing hub contracts and stores. Old command names are not preserved. A project
31
+ activates `kxm.*.v1` only by an explicit successful `kxm init`/migration receipt;
32
+ file presence alone never activates it. Legacy hub runs continue on the legacy
33
+ engine.
34
+
35
+ When Phase 8 activates hub vNext, at least one hub transition release provides:
36
+
37
+ - current `mesh_*` peer tools;
38
+ - current hub APIs behind a compatibility adapter;
39
+ - legacy JSON configuration read support while vNext writes only YAML;
40
+ - current completed workflow history read/export support;
41
+ - Runtime-managed vNext runs in new event stores with new identities;
42
+ - CLI labels for legacy versus vNext state;
43
+ - no implicit movement of active runs between engines.
44
+
45
+ Before activation, a repository MUST NOT use legacy and vNext definitions with
46
+ the same normalized identity. Validation reports the conflict and requires an
47
+ explicit migration choice. After a migration receipt activates the vNext copy,
48
+ the matching legacy definition is read-only compatibility input and cannot be
49
+ selected for a new vNext run.
50
+
51
+ ## Migration commands
52
+
53
+ ```text
54
+ kxm migrate plan
55
+ kxm migrate apply [--decisions <file>] [--project-id <id>] [--name <name>]
56
+ kxm migrate verify
57
+ ```
58
+
59
+ `kxm init` invokes the planning flow when it detects legacy state.
60
+
61
+ **Implementation status (Phase 1 slice):** the commands above are implemented
62
+ for **configuration migration only** — legacy `agents.json`, `gates.json`, and
63
+ workflow-definition JSON under `.kxm/config/`. Database/WAL migration,
64
+ active-run cutover, session migration, and rollback orchestration remain
65
+ later-phase work and are not performed by these commands.
66
+
67
+ ### Plan
68
+
69
+ Produces a secret-free `kxm.migration-plan.v1` report containing:
70
+
71
+ - detected source files with sha256 and byte counts plus a combined
72
+ `sourceDigest`;
73
+ - target resource paths with their rendered content hashes;
74
+ - deterministic ambiguities, each with a stable decision key and the allowed
75
+ values: terminal status for legacy `$terminal` edges, per-edge budgets for
76
+ unbounded back-edges, missing global transition budgets, evidence-policy
77
+ strengthening (`replied` → `passed`), foreign producer identities, secret
78
+ field drops, narrowed permission ceilings, and identity normalization;
79
+ - unrecognized or unmappable fields preserved as hashed `unmapped` entries
80
+ (sensitive values are hashed, never copied);
81
+ - old-to-new identity renames;
82
+ - the resulting permission changes tied to their decision keys.
83
+
84
+ It changes nothing: no writes, no locks, no staging, no local state.
85
+
86
+ ### Decisions
87
+
88
+ `kxm migrate apply` requires every ambiguity to be resolved. Decisions are
89
+ supplied either as a reviewed `kxm.migration-decision.v1` YAML file
90
+ (`--decisions <file>`) binding the exact `projectId`, `projectName`, and
91
+ `sourceDigest` of the plan, or programmatically. Unknown decision keys and
92
+ values outside the plan's allowed set fail closed before any write.
93
+
94
+ ### Apply
95
+
96
+ 1. Acquire the project mutation lock.
97
+ 2. Recompute the plan and re-check the decision binding (project, source
98
+ digest, key set, allowed values).
99
+ 3. Validate every converted resource against its exact schema and the whole
100
+ bundle against semantic rules.
101
+ 4. Refuse to overwrite any existing target path.
102
+ 5. Install resources with durable writes (fsync + rename).
103
+ 6. Load and validate the complete installed bundle.
104
+ 7. Write a hash-linked `kxm.migration-receipt.v1` binding source hashes,
105
+ decision digest, target configuration revision, and installed resource
106
+ hashes; the receipt is self-hashed.
107
+ 8. Re-load the mixed tree: legacy inputs remain intact but receipt-pinned
108
+ read-only; `loadVnextProject` accepts coexistence only through the
109
+ verified receipt.
110
+
111
+ Re-applying with the receipt present is an idempotent no-op
112
+ (`already-migrated`). Editing a legacy source after the receipt makes both
113
+ `loadVnextProject` and `kxm migrate verify` fail closed.
114
+
115
+ ### Verify
116
+
117
+ `kxm migrate verify` reopens the target, re-checks the receipt self-hash,
118
+ re-hashes legacy sources, and compares the target configuration revision and
119
+ installed resource bytes against the receipt. It performs no writes.
120
+
121
+ ## Database migration
122
+
123
+ Before any database operation:
124
+
125
+ - verify SQLite `user_version`;
126
+ - refuse a newer unknown version;
127
+ - checkpoint WAL or copy using the SQLite backup API;
128
+ - include `-wal` state correctly rather than copying only the main file;
129
+ - verify backup integrity;
130
+ - record source and target hashes.
131
+
132
+ Current agents, messages, workflow runs, journal entries, and context items are
133
+ imported as typed **legacy records**. They are not fabricated into fine-grained
134
+ vNext run events whose original ordering was never observed.
135
+
136
+ Completed legacy runs remain queryable. A legacy active run must either finish
137
+ on the old engine or be explicitly cancelled/exported; it is not resumed as a
138
+ vNext run.
139
+
140
+ ## Configuration migration
141
+
142
+ The implemented converter:
143
+
144
+ - reads legacy JSON with byte/depth/node bounds and token-level duplicate-key
145
+ rejection; linked files and linked `workflows/` directories are never
146
+ traversed for authoritative bytes;
147
+ - normalizes case-insensitive identities, records explicit old-to-new renames,
148
+ and rejects case-fold collisions and destination-invalid names;
149
+ - splits `agents.json` into `.kxm/agents/<id>.yaml` resources and emits one
150
+ `.kxm/models/<id>-primary.yaml` profile per agent whose legacy record pinned
151
+ a provider/model pair with a thinking level;
152
+ - maps roster-only concepts (`ownership`, `host`, top-level `project`) into
153
+ hashed `unmapped` report entries rather than dropping them silently;
154
+ - maps workflow stages to agent steps, preserves `reproOracle`, `planHash`,
155
+ `requirePlanHash`, typed transitions, immutable oracles, and global
156
+ transition budgets, and widens evidence-carrying steps into an explicit
157
+ assignment pool containing their producers;
158
+ - converts legacy peer-reply evidence policies (`acceptedStatuses:
159
+ ["replied"]`) into vNext producer policies requiring `passed` only through
160
+ an explicit operator decision;
161
+ - requires decisions for: every legacy `$terminal` edge's terminal status
162
+ (legacy completed the run even on failure outcomes), every unbounded
163
+ back-edge's per-edge budget, missing global budgets, foreign producer
164
+ identities, secret-field drops, unimplemented gates, and each narrowed
165
+ permission ceiling;
166
+ - never copies secret values or environment indirections; webhook secret
167
+ fields are hashed into the report and dropped by explicit decision;
168
+ - records template provenance only for files whose exact generated baseline is
169
+ known; migrated files carry no template provenance and are never
170
+ retroactively adopted;
171
+ - validates the entire target project (exact schemas plus semantic rules)
172
+ before installation and shows the Git diff through normal review.
173
+
174
+ Unknown data is preserved in the migration report, not placed into a generic
175
+ runtime extension map.
176
+
177
+ Legacy typed workflows have a global transition budget but may lack vNext
178
+ per-back-edge caps. The migrator MUST NOT invent those caps silently. `migrate
179
+ plan` lists every affected edge and a proposed bounded value; `migrate apply`
180
+ requires the values in an operator-approved migration decision. The committed
181
+ vNext `/fix` fixture is one reviewed resolution, not a generic automatic rule.
182
+
183
+ Stage IDs, outcome keys, evidence keys, oracle references, plan-hash references,
184
+ and eligible producer identities are preserved by default. Any unavoidable
185
+ normalization appears as an explicit old-to-new mapping and rewrites all bound
186
+ references atomically.
187
+
188
+ ## Session migration
189
+
190
+ Old shared Pi histories may contain content from broader scopes. They remain
191
+ archived under the old worker binding and are never selected for a vNext run.
192
+ The first vNext physical session starts clean. Durable facts must come from Git,
193
+ workflow evidence, artifacts, or promoted context rather than conversation
194
+ history.
195
+
196
+ ## Rollback
197
+
198
+ Rollback is supported until the operator accepts the migration receipt and
199
+ starts a permission-expanding vNext-only run.
200
+
201
+ Rollback:
202
+
203
+ 1. stop vNext writers;
204
+ 2. preserve vNext stores as diagnostic artifacts;
205
+ 3. restore the recorded legacy configuration selection and database path;
206
+ 4. restart only compatible legacy processes;
207
+ 5. verify legacy health and record rollback evidence.
208
+
209
+ Events created only by vNext are not reverse-translated into fabricated legacy
210
+ workflow history.
211
+
212
+ ## Removal gate
213
+
214
+ Legacy readers and command aliases are removed only after:
215
+
216
+ - at least one compatibility release;
217
+ - migration telemetry shows no material unmapped cases;
218
+ - package/install/Windows tests cover vNext;
219
+ - operator documentation and rollback paths are proven;
220
+ - removal is announced in the changelog.
@@ -0,0 +1,184 @@
1
+ # Routing and cost telemetry
2
+
3
+ > **Status.** `kxm.routing-record.v1` is parse-only for legacy records.
4
+ > `kxm.routing-record.v2` is **implemented and active**: emitted at engine
5
+ > attempt settlement (`routing.attempt.recorded` event in `plugins/kxm/src/vnext-engine.ts`),
6
+ > enforced with fail-closed `costBasis` requirement. Price catalog `.kxm/prices.yaml`
7
+ > (`kxm.prices.v1`) is implemented, dated, and hashed. `kxm routing report`
8
+ > is implemented (`plugins/kxm/src/routing.ts`) and ranks routes quality-first,
9
+ > then cost per accepted attempt, never ranking unknown cost cheapest and
10
+ > reporting metered, unmetered, and unknown populations separately. Dev-helper
11
+ > telemetry (`scripts/harness-run.mjs`) and the issue 127 assignment runner
12
+ > (`scripts/assignment-run.mjs`, `just assign`) are implemented developer tools.
13
+
14
+ This document describes what the tree does today versus what Tracking still
15
+ plans. It does not invent prices or close product enums.
16
+
17
+ ## Implemented: v1 record
18
+
19
+ Schema id: `kxm.routing-record.v1` (`plugins/kxm/src/routing.ts`).
20
+
21
+ Always present or defaulted by `parseRoutingRecord`: `schema`,
22
+ `behavioralHashVersion`, `behavioralSha256`, `skills` (default `[]`),
23
+ `contextItemIds` (default `[]`), `retries` / `transitions` /
24
+ `humanInterventions` (default `0`).
25
+
26
+ Optional when present and valid: `workflowRunId`, `stageId`, `attempt`,
27
+ `requestedModel`, `effectiveModel`, `reasoningEffort`, `agentRole`,
28
+ `rolePromptSha256`, `contextPolicyVersion`, `toolPolicyVersion`,
29
+ `workflowDefinitionSha256`, `verifierConfigSha256`, `tokensIn`, `tokensOut`,
30
+ `cacheReadTokens`, `costUsd`, `verifierOutcome`, `finalOutcome`, bounded
31
+ `providerMetadata`.
32
+
33
+ The behavioral hash covers the configuration tuple (normalized models, role,
34
+ prompt/skill/tool/workflow/verifier hashes). Outcome telemetry (tokens, cost,
35
+ retries, outcomes) is outside the hash.
36
+
37
+ **No built-in product producer.** The worker envelope validates a `routing`
38
+ field when present. Nothing in `plugins/kxm/src` or `scripts/kxm-worker.mjs`
39
+ writes a record. Repo records are test-built. External JSONL can be ingested.
40
+
41
+ v1 has **no dedicated fields** for harness, provider, latency, cost basis,
42
+ cache-write tokens, or context occupancy. Bounded `providerMetadata` may
43
+ carry extra keys (at most 32; values are strings, numbers, or booleans;
44
+ `prompt`/`body`/`content`/`message` keys are rejected), but those keys are
45
+ **not standardized** and `kxm routing report` does not read them.
46
+
47
+ `kxm routing report` reads `telemetry.jsonl`, groups by behavioral hash, sorts
48
+ by run count (then hash), and sums missing `costUsd` as **zero**. That silent
49
+ underquote is why the report is **not** a ranking source.
50
+
51
+ ## Implemented: dev helper telemetry
52
+
53
+ `scripts/harness-run.mjs` emits `kxm.harness-result.v2` after a
54
+ `kxm.harness-request.v1`. It is not a Phase 11 adapter and is not persisted as
55
+ a routing record. Helper `status` is transport-only (`completed`, `failed`,
56
+ `interrupted`) and must not be read as product `routing-record.v1`
57
+ `finalOutcome`. Obsolete `kxm.harness-result.v1` files are diagnosed (file,
58
+ observed known schema or `unrecognized`, obsolete schema id) and left
59
+ untouched; there is no v1 parser or upgrade lane. Public result fields are
60
+ a closed allowlist with type checks (no arbitrary objects in scalar
61
+ positions); raw model/stdio text is not copied into metadata.
62
+
63
+ Observed normalization (not an invoice; none of these paths reconcile
64
+ against an invoice or usage API):
65
+
66
+ - Token basis is `cumulative`. Context occupancy is always `unknown`.
67
+ Values above the routing v1 int cap stay in metadata and are not clamped.
68
+ - Helper cost-basis labels are `provider-reported`, `list`, `unmetered`, and
69
+ `unknown`. `billed` is reserved for invoice provenance and is **not**
70
+ emitted here. `just runs` can still print a `billed` label if a v2 file
71
+ already has that string.
72
+ - Claude/Grok (`normalizeClaudeOrGrok`): when the payload has a provider
73
+ cost, that number is copied into **both** `costUsd` and
74
+ `providerReportedCostUsd`. Explicit `modelUsage` `costBasis: "list"` stays
75
+ `list`. Grok `total_cost_usd` without that list basis is
76
+ `provider-reported`. After parse, subscription Claude
77
+ (`authStatus.method === "claude.ai"`) sets `costBasis` to `unmetered` and
78
+ **clears `costUsd`**, leaving `providerReportedCostUsd` when it was present.
79
+ - Pi (`normalizePi`): sums `usage.cost.total` from assistant
80
+ `message_end` events into `costUsd` only. Basis is `list` when that
81
+ aggregate exists, otherwise `unknown`. There is **no**
82
+ `providerReportedCostUsd` field on this path.
83
+ - Codex (`normalizeCodex`): emits `costBasis: "unmetered"` (empty payload
84
+ is `unknown`). Root-verified helper auth preflight permits Codex
85
+ **ChatGPT only** (`scripts/harness-run.mjs` ChatGPT login parse). The
86
+ post-normalize ChatGPT branch also clears `costUsd`. Do not invent an
87
+ API-key billing path here; B3 inventory of other Codex surfaces is a
88
+ **separate** product/inventory question, not this helper.
89
+ - Formatter `formatRunCost` still prints `billed $…` when a listing file
90
+ already has `costBasis: "billed"`. The helper itself does not emit that
91
+ label. That is display of a supplied label, not invoice reconciliation.
92
+
93
+ Do not relabel provider-reported or list-basis amounts as billed. Partial
94
+ usage after failure or interruption is kept and marked `usagePartial`;
95
+ missing counters stay absent, not zero.
96
+
97
+ ## Implemented/unreleased: assignment runner (issue 127)
98
+
99
+ `scripts/assignment-run.mjs` is the normal **dev** entry. It is not `kxm run`
100
+ and does not replace Phase 3/4 gates.
101
+
102
+ Working commands (absolute paths; flags from the script, not invented):
103
+
104
+ ```text
105
+ just assign /abs/manifest.json
106
+ # node scripts/assignment-run.mjs run --manifest /abs/manifest.json
107
+
108
+ just witness /abs/record-dir
109
+ # witness --record-dir /abs/record-dir
110
+
111
+ just attribute /abs/task-dir /abs/record-dir orchestration /abs/note.txt
112
+ # attribute --task-dir --record-dir --class --explanation-file
113
+
114
+ just observe-cost /abs/task-dir /abs/observation.json
115
+ # observe-cost --task-dir --input
116
+
117
+ just accept /abs/task-dir <commit> /abs/writer-record /abs/arch-review /abs/cli-review
118
+ # accept --task-dir --commit --record-dir --critic --critic
119
+ # optional observed PR/CI (direct script; the five-argument just recipe cannot forward them):
120
+ # node scripts/assignment-run.mjs accept --task-dir /abs/task --commit <sha> --record-dir /abs/writer --critic /abs/arch --critic /abs/cli [--observed-pr <id>] [--observed-ci <id>]
121
+
122
+ just plan-current /abs/task-dir /abs/plan.md <sha256> <base-commit> <expected-generation>
123
+ just change-report /abs/task-dir
124
+ ```
125
+
126
+ `just impl|plan|review-arch|review-cli` remain harness transport. They do not
127
+ create assignment identity, witness receipts, or `accepted.json`.
128
+
129
+ Distinctions the report and docs must keep:
130
+
131
+ - **Manifest / current plan / gate / acceptance / cost** are different
132
+ records. Completions are not acceptance. Witness receipts are not critic
133
+ PASS. `attribute` history does not edit `completion.json`. Cost-only
134
+ imports never gain witness or acceptance eligibility.
135
+ - `change-report` separates provider-reported sums, list estimates,
136
+ unmetered, unknown, not-dispatched (`provider_calls` 0), and partial
137
+ markers. Missing is not `0`. Unmetered is not free. Cumulative tokens are
138
+ not context occupancy. True elapsed time is separate from summed latency
139
+ and summed witness duration. The effort table is descriptive, not a
140
+ ranking. Orchestration/root usage is unavailable unless imported.
141
+ - Observed PR/CI identifiers are unvalidated observations.
142
+ - Private handoff notes live in `attribute` explanations and private model
143
+ summaries; the report references them and does not print the prose.
144
+
145
+ Evidence-informed **effort defaults** for transport recipes and operator
146
+ manifests: medium implementation/planning/architecture, low CLI review. Not a
147
+ learned policy and not a catalog feed. Phase 9 may use this report to
148
+ **propose** harness or model changes; activation still requires Git review.
149
+
150
+ Per-candidate acceptance requires an actual native writer, the fixed witness,
151
+ and both designated native reviews. PR/CI/merge complete issue 127. This
152
+ document does not assert those gates have passed. Low-level
153
+ `just impl|plan|review-arch|review-cli` recipes remain harness transport.
154
+
155
+ ## Implemented: v2 record
156
+
157
+ Schema id: `kxm.routing-record.v2` (`plugins/kxm/src/routing.ts`).
158
+
159
+ Fields carried on `RoutingRecordV2`:
160
+
161
+ - Identity & scoping: `schema`, `recordedAt`, `project`, `runId`, `stepId`, `assignmentId`, `attemptId`.
162
+ - Routing configuration: `harness`, `provider`, `requestedModel`, `effectiveModel`, optional `thinking`, optional `agentRole`, `behavioralSha256`.
163
+ - Execution metrics: `latencyMs`, `contextTokens`, `tokensIn`, `tokensOut`, `cacheReadTokens`, `cacheWriteTokens`.
164
+ - Outcomes: `verifierOutcome` (`passed` | `warning` | `failed`), `finalOutcome` (`accepted` | `blocked` | `failed` | `pending`), `retries`, optional `transitions`, optional `humanInterventions`, optional `providerMetadata`.
165
+ - Cost accounting: `costBasis` (`"metered" | "unmetered" | "unknown"`), `costUsd` (required when metered), optional `priceRef`.
166
+
167
+ The vNext engine settle transaction appends a `routing.attempt.recorded` event carrying the v2 record and refuses to settle without a valid `costBasis`. Attempt dispatch enforces `limits.maxModelCost` against metered cost before invocation (`budget_model_cost`).
168
+
169
+ ## Implemented: report and price catalog
170
+
171
+ - **Price catalog:** `.kxm/prices.yaml` (`kxm.prices.v1`, dated and hashed) defines input, output, cache-read, cache-write rates, and context tiers for active models. Missing rows or uncataloged models evaluate to `costBasis: "unknown"`.
172
+ - **Ranked report:** `kxm routing report` (`plugins/kxm/src/routing.ts`, CLI command `kxm routing report`) groups records by `(harness, model, thinking, role)`.
173
+ - **Ranking order:** Quality first (`verifyPassRate` descending, then `reworkRate` ascending where rework measures back-edge re-entries `transitions > 0`), followed by `costPerAcceptedUsd` ascending.
174
+ - **Underquote prevention:** Routes with unknown cost are flagged (`*`) and **never ranked cheapest**, eliminating silent underquoting.
175
+ - **Population separation:** Reports metered cost, unmetered attempt counts, unknown-cost attempt counts, and quota-exhausted attempt counts as separate metrics rather than a single misleading total.
176
+ - **List prices flag:** Supports `--equivalent-list-cost` / `--list-prices` to display estimated list rates for comparison alongside actual recorded spend.
177
+ - **Post-MVP:** Dynamic catalog price feeds (`kxm update --models`), budget roll-over, and automated promotion of repeat successes into workflow gates.
178
+
179
+ ## Precedence
180
+
181
+ [AGENTS.md](../../AGENTS.md) and
182
+ [Tracking](../../plans/implementation-plan.md#tracking-working-tree-not-a-release)
183
+ win where they differ from historical 2026-09-04 reviews.
184
+ Issue 86 stays open for later-phase remainder (see Tracking).