@kontextmind/kxm 0.7.165 → 0.7.167

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 (41) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +16 -0
  3. package/docs/README.md +1 -0
  4. package/docs/architecture/hosted-direction.md +9 -4
  5. package/docs/architecture/inventory.md +1 -0
  6. package/docs/concepts/trust-model.md +1 -1
  7. package/docs/contributing/decisions.md +153 -0
  8. package/docs/contributing/learnings.md +54 -53
  9. package/docs/contributing/operating-rules.md +19 -6
  10. package/docs/glossary.md +2 -2
  11. package/docs/operations/troubleshooting.md +2 -2
  12. package/docs/operations.md +62 -8
  13. package/docs/reference/cli-reference.md +11 -11
  14. package/docs/reference/config-reference.md +36 -11
  15. package/docs/reference/configuration.md +2 -2
  16. package/docs/reference/tools.md +1 -1
  17. package/docs/start/quickstart-claude-code.md +2 -2
  18. package/package.json +1 -1
  19. package/plugins/kxm/.claude-plugin/plugin.json +1 -1
  20. package/plugins/kxm/README.md +3 -3
  21. package/plugins/kxm/dist/claude-hook.js +417 -66
  22. package/plugins/kxm/dist/cli.js +1399 -900
  23. package/plugins/kxm/dist/extension.js +399 -64
  24. package/plugins/kxm/dist/mcp-server.js +622 -135
  25. package/plugins/kxm/dist/runtime-supervisor.js +668 -166
  26. package/plugins/kxm/dist/runtime.js +713 -211
  27. package/plugins/kxm/dist/server.js +466 -58
  28. package/plugins/kxm/package.json +1 -1
  29. package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +15 -7
  30. package/plugins/kxm/src/cli/hub.ts +80 -21
  31. package/plugins/kxm/src/cli/types.ts +8 -1
  32. package/plugins/kxm/src/cli.ts +41 -7
  33. package/plugins/kxm/src/config.ts +246 -3
  34. package/plugins/kxm/src/extension.ts +8 -7
  35. package/plugins/kxm/src/hub-autostart.ts +20 -0
  36. package/plugins/kxm/src/hub-env.ts +83 -31
  37. package/plugins/kxm/src/hub-identity.ts +337 -0
  38. package/plugins/kxm/src/mcp-server.ts +17 -15
  39. package/plugins/kxm/src/project-name.ts +6 -47
  40. package/plugins/kxm/src/server.ts +22 -4
  41. package/scripts/kxm-hub.mjs +5 -0
@@ -11,7 +11,7 @@
11
11
  "name": "kxm",
12
12
  "source": "./plugins/kxm",
13
13
  "description": "Durable workflows, peer agents, and kxm tui",
14
- "version": "0.7.165",
14
+ "version": "0.7.167",
15
15
  "category": "development",
16
16
  "tags": ["kxm", "multi-agent", "workflows", "mcp"]
17
17
  }
package/CHANGELOG.md CHANGED
@@ -6,6 +6,22 @@ All notable user-facing changes are documented here. The project follows [Semant
6
6
 
7
7
  ### Added
8
8
 
9
+ - **Hub project identity and its access key live in `.kxm/config.yaml`.**
10
+ `hub.local` and `hub.cloud` hold the URL, the project id to present, and a
11
+ key reference (`key.op` is an `op://` reference, `key.env` is an environment
12
+ variable name). A literal token is refused. `op read` runs at use time and
13
+ the resolved value is not saved. The same order is used everywhere: flag,
14
+ `KXM_PROJECT`, the active mode's config project, `.kxm/project.yaml`, the
15
+ package name, then the directory name. `kxm hub bind` and
16
+ `kxm hub bind --cloud` write the non-secret fields, and `kxm hub view`
17
+ prints the mode, URL, project id, and key source. The hub's
18
+ `hub.projects` map uses the same references. `KXM_PROJECT_TOKENS` still
19
+ replaces that map. Setups whose hub map is keyed by the package name should
20
+ set `hub.local.project` or `hub.cloud.project` to that name, or keep passing
21
+ `KXM_PROJECT`: a checkout with `.kxm/project.yaml` otherwise sends that id
22
+ and gets `project_token_missing`. See
23
+ [Operate a KXM hub](docs/operations.md#hub-identity-in-config).
24
+
9
25
  - **`kxm hub bind --cloud` attaches a client to a remote hub reached through a loopback forward.**
10
26
  The binding records `--token-env` and/or `--token-command` and never the token.
11
27
  Later commands, including the environment for a Pi worker, use that source and
package/docs/README.md CHANGED
@@ -117,6 +117,7 @@ KXM connects coding agents through a durable, authenticated [hub](glossary.md#hu
117
117
  | [KXM terminal components](contributing/tui-components.md) | Maintainers, integrators | The panel kit behind `kxm dash` |
118
118
  | [Repository work delivery skill](contributing/repo-work-delivery.md) | Contributors | The repository-local skill for delivering a change |
119
119
  | [Operating rules](contributing/operating-rules.md) | Agents, maintainers | The operator's standing instructions, dated, and where each is enforced |
120
+ | [Decisions](contributing/decisions.md) | Agents, maintainers | Medium-or-higher decisions from automated work, with weights and evidence |
120
121
  | [Learnings](contributing/learnings.md) | Agents, maintainers | Durable lessons from running the writer, landing, and docs loops |
121
122
  | [Artifact templates](templates/README.md) | Workflow authors | Document templates and where workflows use them |
122
123
 
@@ -2,8 +2,11 @@
2
2
 
3
3
  Target. This page is a direction, not a live deployment.
4
4
 
5
- Read from `plans/plan-per-tenant-hosting.md`. `plans/plan-greenfield-infra.md`
6
- is not in this checkout.
5
+ Read from `plans/plan-per-tenant-hosting.md`.
6
+ `plans/plan-greenfield-infra.md` is in this checkout as a `kxm.doc.v1`
7
+ stub (status draft, authority instruction): the long-form proposal was
8
+ never committed, and the canonical facts below come from the
9
+ implementation-plan greenfield bullets.
7
10
 
8
11
  ```mermaid
9
12
  flowchart LR
@@ -44,8 +47,10 @@ roadmap question. The tracker wins.
44
47
 
45
48
  ## Greenfield infra plan
46
49
 
47
- `plans/plan-greenfield-infra.md` is not observed from this checkout. Its
48
- `status` and `blocked_by` are not observed from this checkout.
50
+ `plans/plan-greenfield-infra.md` is observed from this checkout as a
51
+ `kxm.doc.v1` stub (status draft, authority instruction, updated
52
+ 2026-09-28). Its delivery position is unchanged: none of the delivery is
53
+ scheduled there.
49
54
 
50
55
  The tracker names that file. The sentences that can be repeated without a
51
56
  hostname, an account name, or a secret are: a first move is recorded as
@@ -12,6 +12,7 @@ Read from `plugins/kxm/src/cli.ts`, `scripts/kxm-hub.mjs`, `plugins/kxm/src/hub.
12
12
  | `kxm` CLI | `node scripts/kxm.mjs` or the installed bin | no listener | none | `plugins/kxm/src/cli.ts` |
13
13
  | Hub | `kxm hub start` via `scripts/kxm-hub.mjs` | `127.0.0.1:7331` | `.kxm/state/kxm.db` under the workspace state dir | `plugins/kxm/src/hub.ts` |
14
14
  | Hub credentials | written when the hub starts | `hub-env.json` under the user state root | that JSON file, not SQLite | `plugins/kxm/src/hub-env.ts` |
15
+ | Hub cloud binding | `kxm hub bind <url> --cloud --token-env/--token-command` | no listener; writes the binding record and never stores the token | binding record; token stays in the named env or command | `plugins/kxm/src/cli/hub.ts` |
15
16
  | Runtime supervisor | `kxm runtime` / `scripts/kxm-runtime-supervisor.mjs` | `127.0.0.1` and the requested port, or ephemeral | registry and event stores below | `plugins/kxm/src/runtime-supervisor.ts` |
16
17
  | Runtime registry | opened by the supervisor | `runtime/registry.db` under the user state root | `registry.db`. A lane worktree registers under its project: same project id, its own control root, `lane_of` set. A registering root is the primary worktree when its git common dir is `<root>/.git`; if that primary registers while the live home row is not primary, the primary becomes the home row and every other live row of that repository becomes its lane. | `plugins/kxm/src/runtime-paths.ts` |
17
18
  | Runtime event store | opened by the supervisor | `runtime/projects/<key>/run-events.db` | `run-events.db` | `plugins/kxm/src/runtime-paths.ts` |
@@ -56,7 +56,7 @@ flowchart LR
56
56
  - **Claude Code plugin.** The MCP server uses the plugin's `auth_token` setting, else the project token the hub saved for this project. It never falls back to the saved admin token; without a project token, its tools report that and do nothing.
57
57
  - **SessionStart hook.** It reads local state read-only. It mints no token, writes no file, and never prints a token.
58
58
  - **Pi extension.** It uses `KXM_AUTH_TOKEN`, else the project token the hub saved for this project. It never uses the saved admin token, nor the one a hub it auto-started generated; without a project token it reports the fix and stays offline.
59
- - **`kxm peer` and `kxm workflow` agent commands.** They act as a peer agent, so they choose a token as the Pi extension does, and exit 2 with `project_token_missing` when none resolves.
59
+ - **`kxm peer` and `kxm workflow` agent commands.** They act as a peer agent, so they choose a token as the Pi extension does, and exit 2 with `project_token_missing` when none resolves. The message names the project id that was sent and where it came from.
60
60
  - **Dashboard and Runtime supervisor.** Operator tools use `KXM_AUTH_TOKEN`, else the saved project token, else the saved admin token.
61
61
 
62
62
  ## Project isolation
@@ -0,0 +1,153 @@
1
+ ---
2
+ title: "Decisions"
3
+ description: "Decisions of medium significance or higher made by automated KXM work in this repository. One entry per decision: the options evaluated with their weights, and why the selected option won. Recorded the turn the decision is taken."
4
+ audience: "agents and maintainers"
5
+ updated: "2026-09-27"
6
+ ---
7
+
8
+ # Decisions
9
+
10
+ Automated work records here every decision of medium significance or
11
+ higher: the options it evaluated, the weight each option scored against
12
+ the criteria that mattered, and why the selected option won. Weights are
13
+ the session's own 0-to-1 scores, not measurements. A decision that was
14
+ made directly by the operator is recorded only when executing it required
15
+ a choice.
16
+
17
+ Entries run oldest first. Retention: this file keeps the last 50 entries. When one more would exceed
18
+ the cap, the oldest entries rotate to
19
+ `docs/contributing/decisions-archive.jsonl` as `kxm.decision-archive.v1`
20
+ lines (date, title, area, options with weights, selected, why, evidence),
21
+ oldest first. The archive is append-only cold storage; the md stays the
22
+ working set.
23
+
24
+ ## 2026-09-26 — P2 critic transport while the engine was schema-blocked (dispatch)
25
+
26
+ - Context: installed 0.7.130 refused the P2 lane's new agent schemas, so
27
+ `kxm run`, drive, cancel, and receipt all answered 400. Both critics
28
+ still had to review the unit, and loop-dispatch wanted engine attempts.
29
+ - Options:
30
+ - Wait until #343 ships, then run critics through the engine — weight
31
+ 0.2. Highest purity, but it stalls the unit for a release cycle and
32
+ the reviewers' context goes cold.
33
+ - Run a second runtime supervisor from the branch code — weight 0.1. It
34
+ would load the lane, but it mutates machine-global runtime state with
35
+ unreleased code and risks the exact registry corruption S24 just
36
+ fixed.
37
+ - Dispatch both critics through the harness runner with briefs copied
38
+ into the lane sandbox — weight 0.9. The documented relief for schema
39
+ cutover lanes, proven twice the same morning by the writer repairs;
40
+ costs only the improve-report attempt rows.
41
+ - Selected: harness runner. Fastest safe path; the engine-attempt proof
42
+ was deliberately deferred to the next unit rather than falsified.
43
+ Evidence: Evidence: the P2 lane store (bae17379) held the settled attempts while the control-root report read zero, and the 0.7.131 update plus runtime restart left the lane loadable with a verified simulated receipt.
44
+
45
+ ## 2026-09-26 — Supervisor cadence interpretation (operations)
46
+
47
+ - Context: the operator ordered the schedule task changed to 30 minutes.
48
+ The improvement loop was anchored to wall-clock ("every sixth tick,
49
+ about 30 minutes"), which a longer tick would silently stretch to three
50
+ hours.
51
+ - Options:
52
+ - Keep "every sixth tick" literally — weight 0.3. Preserves the prompt's
53
+ letter, breaks the documented ~30-minute wall-clock cadence the
54
+ parenthetical pins.
55
+ - Improvement loop every tick — weight 0.8. Preserves both documented
56
+ wall-clock behaviours; the tick count stops appearing anywhere.
57
+ - Selected: every tick. The operator's order named the tick cadence; the
58
+ improvement loop's anchor was always the half hour. Stated in the report
59
+ so it can be flipped back with one word.
60
+ Evidence: Evidence: plans/kxm-roadmap/supervisor-prompt.md and the operator order of 2026-09-26.
61
+
62
+ ## 2026-09-27 — Authoring witness misses committed work (engine)
63
+
64
+ - Context: the engine failed two writer runs (P2 morning, vision port)
65
+ with `authoringWitness: unchanged` while both lanes held the writer's
66
+ commit. `captureWorktreeWitness` fingerprints porcelain, unstaged, and
67
+ staged diffs but not HEAD, so a writer that fully commits reads as
68
+ unchanged and a `passed` write step is flipped to `failed`.
69
+ - Options:
70
+ - Add `git rev-parse HEAD` to the fingerprint — weight 0.9. One term in
71
+ one string; catches commits, resets, and branch switches, which are
72
+ all authoring-relevant moves of a lone-writer checkout.
73
+ - A separate commit-witness field with its own failure class — weight
74
+ 0.6. Finer attribution (commit versus dirty edit) but a larger
75
+ surface for a distinction nothing consumes today.
76
+ - Trust the producer's `authored` metadata — weight 0.1. The module
77
+ documents that metadata is set here, not trusted from the producer.
78
+ - Selected: HEAD in the fingerprint, one named test (committed-only
79
+ change keeps `passed` with `authored: true`), shipped before any more
80
+ engine-driven write steps.
81
+ Evidence: Evidence: test/core/worktree-witness.test.ts (real temp git repositories), and the two failed lane runs run_fe3061b3 (vision) and run_f7a21c84 (P2) whose lanes held the writer commits.
82
+
83
+ ## 2026-09-27 — Open PR queue: draft handling and landing order (landing)
84
+
85
+ - Context: six open PRs after #343. Two were drafts, one conflicted
86
+ against the restructured CLI, three were clean and non-draft. The
87
+ standing rule says every PR is landed without asking.
88
+ - Options:
89
+ - Land everything including drafts — weight 0.2. A draft is the
90
+ author's own hold signal; overriding it defeats the state and risks
91
+ landing half-work.
92
+ - Land only clean non-drafts now, defer the conflicted one to a port,
93
+ leave drafts — weight 0.9. Honours both the autonomy rule and the
94
+ draft semantics; the queue drains in one session.
95
+ - Ask the operator per PR — weight 0.1. The standing rule explicitly
96
+ removes this ask for open PRs.
97
+ - Selected: land non-drafts oldest-first (#341, #344, #346), leave
98
+ #325 and #342 as drafts, dispatch #345 as a port.
99
+ Evidence: Evidence: gh pr list on 2026-09-27 (six open: two drafts, one conflicting, three clean).
100
+
101
+ ## 2026-09-27 — Outcome parser rejects real model output (engine)
102
+
103
+ - Context: the one-shot producer appends a "return a final JSON object
104
+ with an outcome field" contract to every prompt, and `determineOutcome`
105
+ requires the model's entire output to parse as that bare JSON. Both real
106
+ writers and critics answer with the brief's own review format instead
107
+ (grok prose, fable markdown), so every substantive engine-driven step
108
+ settles `failed` even when the transport and witness are clean.
109
+ - Options:
110
+ - Extract the last balanced JSON object in the text and apply the same
111
+ strict checks (object, string `outcome`, member of allowed outcomes;
112
+ anything else stays `failed`) — weight 0.9. Tolerates the prose
113
+ models actually produce; no path to success without a truthful
114
+ outcome token.
115
+ - Repeat the JSON contract as the first and last line of the prompt —
116
+ weight 0.3. Prompt engineering against measured behaviour; the brief's
117
+ own output section still wins.
118
+ - Per-harness structured output modes — weight 0.5. The durable fix but
119
+ a per-adapter surface change; too broad for the ship cycle this needs
120
+ to ride.
121
+ - Selected: last-JSON-object extraction, same strict checks, same
122
+ fail-closed default. Shipped with the witness fix in one release so the
123
+ engine can drive real steps at all.
124
+ - Addendum (2026-09-27, after two more real failures): the shipped rule
125
+ required the object alone on the final line; real critics write the
126
+ object inline after their summary prose and fail anyway. The rule is
127
+ now "the last top-level object of the reply, extending to the end of
128
+ the trimmed text": forward scan, depth- and string-aware, so trailing
129
+ prose, mid-text objects, and inner objects of a truncated outer object
130
+ all still fail, while the real inline-at-end shape passes.
131
+ Evidence: Evidence: test/core/oneshot-producer.test.ts (real reviewer shapes), runs run_79bd2d13 and run_041dfb8e on the vision lane, and the shipped forward pass in #368.
132
+
133
+ ## 2026-09-27 — PR #345: rebase, close, or port (dispatch)
134
+
135
+ - Context: #345 adds `kxm vision assert`, but its base predates the CLI
136
+ restructure that deleted `plugins/kxm/src/cli/vnext.ts`; GitHub reports
137
+ DIRTY/CONFLICTING. The gate module `vision-gate.ts` already exists on
138
+ main; only the command surface is missing.
139
+ - Options:
140
+ - Force the rebase and hand-resolve inside the land pipeline — weight
141
+ 0.3. The land rebase stage resolves only three union classes; a
142
+ deleted-file port is none of them, so it fails mid-pipeline anyway.
143
+ - Close #345 as superseded — weight 0.2. Discards reviewed intent
144
+ (skill gate-step wording, fail-closed exit contract) that is still
145
+ wanted.
146
+ - Port the four pieces (handler, registration, test, skill wording)
147
+ onto the current CLI structure through a writer lane — weight 0.9.
148
+ Small surface, the PR stays open until the port lands, and the
149
+ dispatch is the first engine-driven unit on 0.7.131, feeding
150
+ loop-dispatch.
151
+ - Selected: port through the engine lane `vision-assert-port`; the PR is
152
+ closed by its replacement landing, not by hand.
153
+ Evidence: Evidence: merge-base 77beda4 predates the CLI restructure; merge-tree showed cli/vnext.ts deleted on main; vision-gate.ts already on main.
@@ -13,6 +13,16 @@ entry whose fix has landed is deleted, not archived.
13
13
 
14
14
  ## Dispatch and lanes
15
15
 
16
+ - **A "no retired names anywhere" rule must exclude the history pages.**
17
+ The P2 brief asked that retired recipe names appear nowhere in docs; the
18
+ writer then rewrote dated lessons and rules on this page and on
19
+ `operating-rules.md` into nonsense ("applies to `kxm lane run` and
20
+ `kxm lane run`") and hand-edited generated roadmap pages. Sweeps like
21
+ that exclude `docs/contributing/learnings.md`, `operating-rules.md`,
22
+ `plans/`, and `CHANGELOG.md`, and the planner reverts any edit to them.
23
+ Evidence: omp-align-p2, 2026-09-26. Applies to: every brief with a
24
+ "returns nothing" grep.
25
+
16
26
  - **Branch every lane from the current `origin/main`, and rebase before
17
27
  review, not after.** Three branches cut before #330 and #331 landed each
18
28
  needed a hand rebase with the same additive conflicts (`cli.ts`
@@ -31,11 +41,14 @@ entry whose fix has landed is deleted, not archived.
31
41
  supervisor tick and any batch of writers finishing together.
32
42
  - **The transport's stdin read can fail with `EAGAIN` under concurrent
33
43
  detached dispatch.** Retry once; the request itself is fine. Evidence:
34
- two occurrences on 2026-09-26 (backlog S18). Applies to: `just impl-bg`
35
- and `just review-cli` until they retire.
44
+ two occurrences on 2026-09-26 (backlog S18). Applies to:
45
+ `scripts/harness-run.mjs` dispatches, which outlive the retired just
46
+ recipes.
36
47
  - **Do not launch a writer under the Bash tool's ten-minute background
37
- cap.** It kills the harness mid-run. Use the detached recipe or
38
- `kxm lane run`. Evidence: the first lane-cli dispatch, 2026-09-26.
48
+ cap.** It kills the harness mid-run. Give the dispatch call an unbounded
49
+ timeout, use the detached runner, or `kxm lane run`. Evidence: the first
50
+ lane-cli dispatch, 2026-09-26; omp-align-p2 repairs ran 15 to 36 minutes
51
+ in 2026-09-26 background jobs with an unbounded timeout and survived.
39
52
  - **Do not run a standalone `npm run verify` on a branch that `kxm land`
40
53
  will land.** The `verify` stage runs it again, so the standalone run
41
54
  only spends one of the two verify slots twice. Run the critics on the
@@ -44,63 +57,47 @@ entry whose fix has landed is deleted, not archived.
44
57
 
45
58
  ## Engine and runtime
46
59
 
47
- - **A lane that changes `.kxm` schemas cannot be observed or re-driven by
48
- the installed runtime until that change ships.** The runtime revalidates
49
- the lane's project config on every request with the installed code, so
50
- once the P1 writer rewrote the role files to v2, `kxm runs status`,
51
- `cancel`, and a second `kxm lane run` all refused with
52
- `schema_identity_mismatch`. Watch such a writer by process and tree, and
53
- dispatch its repair through the harness runner. Evidence: omp-align-p1,
54
- 2026-09-26. Applies to: any schema or config-identity cutover.
55
-
56
- - **One control root per project id in the Runtime registry.** A lane
57
- worktree carries the same `.kxm/project.yaml` id as the main checkout, so
58
- the second root that posts a run is refused with `project_home_conflict`,
59
- and a lane that was removed leaves a dead row behind. Until backlog S24
60
- lands: stop the runtime, delete the dead row from `registry.db` under the
61
- user state root, restart, redispatch. Never delete a row whose root still
62
- exists. Evidence: omp-align-p1 dispatch, 2026-09-26. Applies to:
63
- `kxm lane run` and `kxm run --lane`.
60
+ - **A lane whose `.kxm` schemas are ahead of the installed runtime cannot
61
+ be driven, observed, or cancelled by the engine.** Every run-scoped
62
+ request (status, drive, cancel, receipt) answers 400
63
+ `schema_additionalProperties`, because `loadKxmProject` validates the
64
+ project before the route: installed 0.7.130 refuses the P2 lane's
65
+ `role:` on `.kxm/agents/*.yaml` while the branch's own loader validates
66
+ clean. The morning `implement-only` run executed before the writer
67
+ rewrote the agent files (c352285 landed mid-run), then settled `failed`
68
+ with `authored: false` and witness unchanged, and the lane now refuses
69
+ new runs with `lane_run_open` because that run cannot be cancelled.
70
+ Until the branch ships, `kxm update --kxm` runs, and the runtime
71
+ supervisor restarts, dispatch repairs and critics through the harness
72
+ transport. Resolved for this lane by 0.7.131: after the update and a
73
+ runtime restart, the lane loads clean, the stuck run cancelled
74
+ idempotently, and a simulated drive returned a verified receipt.
75
+ Evidence: omp-align-p2 lane, 2026-09-26. Applies to: every
76
+ dispatch whose lane changes schemas.
64
77
 
65
- - **The improvement loop is blind while writers bypass `kxm run`.** Every
66
- writer this week ran through the harness runner (`just impl-bg` and the
67
- critic recipes), which records no engine events, so `kxm improve report`
68
- and `kxm routing report` both return zero records and no candidates.
69
- Evidence: both reports on 2026-09-26 at 08:14 UTC list the engine store as
70
- absent and telemetry as empty. Applies to: dispatch. Once the one-step
71
- workflows land, dispatch through `kxm lane run --workflow implement-only`
72
- so attempts land in the run-events store; until then the sixth-tick
73
- improvement loop reports nothing by design.
74
- The reports read the store of the control root they run in, so a lane's
75
- attempts show up only when the report runs inside that lane, or once the
76
- lane is registered under the project (backlog S24).
78
+ - **The improvement reports read only the control root's own store.**
79
+ `kxm improve report` and `kxm routing report` read the run-events store
80
+ of the checkout they run in, so a registered lane's attempts are
81
+ invisible from the parent (backlog S30): on 2026-09-26 the control-root
82
+ report read 0 records while the lane store held the settled attempts.
83
+ Run the reports inside the lane, or dispatch through the engine from the
84
+ root you report on. Evidence: both reports on the P2 control root
85
+ (0 records) versus the same reports inside the omp-align-p2 and
86
+ docs-cadence lanes (settled attempts). Applies to: the supervisor's
87
+ improvement loop and any report run from a parent checkout.
77
88
 
78
- - **A live agent step had a hard 120 second timeout with no configuration
79
- path.** The supervisor built the one-shot producer without a timeout.
80
- Fixed on the run-driver-timeouts branch (step `timeoutMs`, project
81
- `limits.agentStepTimeoutMs`, default one hour). Delete this entry when
82
- that lands.
83
- - **A run with an unreconciled executing attempt could not be cancelled or
84
- driven again**, and that survived a supervisor restart; deleting the
85
- lane's Runtime project store was the only recovery. Fixed on the same
86
- branch (`executing_unrecorded`, admission released on a handoff receipt).
87
- Delete when it lands.
88
- - **The engine sends `--reasoning-effort low` on a first attempt regardless
89
- of the role's effort.** `engine.ts` hard-codes it. Open; covered by the
90
- role alignment plan P2 and P6.
91
89
  - **Template provenance is refused when the installed kxm moves ahead of
92
90
  the stamped revision, and a project without the file validates as
93
91
  ready.** Deleting the file is the sanctioned state until `kxm init` can
94
- re-stamp. Evidence: every fresh lane on 2026-09-26 until #330 removed it.
92
+ re-stamp. Evidence: backlog S3 (still open; the re-stamp decision is
93
+ unmade) and the live check at `plugins/kxm/src/project-config.ts`.
94
+ Applies to: every fresh lane.
95
95
 
96
96
  ## `kxm land`
97
97
 
98
98
  - **Auto-merge cannot be enabled on a PR that is already `CLEAN`**; the
99
99
  mutation answers "clean status" and the REST squash merge is the path.
100
100
  While CI is paused every PR is clean, so this is the normal path.
101
- - **The Release workflow's run is titled `Release`, never the PR title.**
102
- Match it by time after the Auto-Release run. Fixed on kxm-land-followup;
103
- delete when it lands.
104
101
  - **A verify failure inside `kxm land` shows only the child's last output
105
102
  line.** Re-run verify by hand to see the cause until backlog S19 lands.
106
103
 
@@ -110,9 +107,13 @@ entry whose fix has landed is deleted, not archived.
110
107
  main's later additions as deletions.** Say the base commit in the brief
111
108
  and tell the critic to review against it. Evidence: docs-site review,
112
109
  two of five findings were base artifacts.
113
- - **Usage errors are Commander prose even under `--json` in every group.**
114
- Repo-wide, one fix in `mapCommanderError`; on kxm-land-followup. Delete
115
- when it lands.
110
+ - **Read-only critics cannot leave their lane sandbox.** The architecture
111
+ critic three times could not read a brief under the main checkout's
112
+ `.kxm/briefs/` and reviewed against the question list alone, once
113
+ re-flagging a decision the brief had already settled. Copy the brief
114
+ into the lane's gitignored `.kxm/logs/` and dispatch from that path.
115
+ Evidence: omp-align-p2 passes 1 to 3, 2026-09-26. Applies to: every
116
+ read-only critic dispatch.
116
117
 
117
118
  ## omp research, kept for the alignment plan
118
119
 
@@ -30,7 +30,8 @@ replacement.
30
30
  merge, and follow through to the auto-release tag and the npm publish.
31
31
  Report the outcome; do not stop to ask for the merge. Enforced by
32
32
  `kxm land` (verify, docs, push, pr, rebase, unblock, merge, release,
33
- milestone) and, until every stage is proven, by hand. (2026-09-26.)
33
+ milestone); every stage ran green end to end on #338 with kxm 0.7.126,
34
+ so hand landing is the exception, not the rule. (2026-09-26.)
34
35
  - **Documentation is regenerated after a green pipeline and before the
35
36
  merge.** The `docs` stage of `kxm land` runs the roadmap generator and
36
37
  commits the regenerated pages on the branch. (2026-09-26.)
@@ -54,9 +55,14 @@ replacement.
54
55
  entry point is a `kxm` command: a group under `plugins/kxm/src/cli/`,
55
56
  registered in `cli.ts`, owned by a bundled skill so `check:generated`
56
57
  passes, documented in the CLI reference. Existing recipes retire as their
57
- `kxm` verbs land; the transport recipes (`impl`, `plan`, `review-*`,
58
- `impl-bg`) retire last, after one real unit has run through the one-step
59
- workflows. (2026-09-26.)
58
+ `kxm` verbs land; the transport recipes (`impl`, `plan`, `review-arch`,
59
+ `review-cli`, `impl-bg`, `dispatch`) retired in #343, so units dispatch
60
+ through `kxm lane run <unit> --brief <file> --workflow implement-only`
61
+ and the read-only critic workflows `review-arch-only` and
62
+ `review-cli-only`. `just` keeps only the assignment-runner recipes
63
+ (`assign`, `witness`, `accept`, `observe-cost`, `attribute`,
64
+ `change-report`, `plan-current`), which are harness transport for the
65
+ issue 127 runner. (2026-09-26.)
60
66
 
61
67
  ## Accounts
62
68
 
@@ -72,6 +78,13 @@ replacement.
72
78
 
73
79
  ## Decisions and debt
74
80
 
81
+ - **Automated KXM work records every medium-or-higher decision it makes in
82
+ `docs/contributing/decisions.md`** for its working project: the options
83
+ evaluated, the weight each option scored and against what, and why the
84
+ selected option won. Recorded the turn the decision is taken, not at
85
+ session end. The doc keeps the last 50 entries; older ones rotate to
86
+ `docs/contributing/decisions-archive.jsonl` as `kxm.decision-archive.v1`
87
+ lines. (2026-09-27.)
75
88
  - **Every option comes with pros and cons and two recommendations**, the
76
89
  solid-product answer and the interim answer. (2026-09-26.)
77
90
  - **Every shortcut goes on the backlog the same turn it is taken**, as an
@@ -102,10 +115,10 @@ refusals, and the two roadmap skills. (2026-09-26.)
102
115
  form: `[{lane}/{agent}]: {phrase}. {No action|Review needed}. -
103
116
  {E}e|{D}d ({M}m{S}s)`. Routine lines are not echoed back in chat.
104
117
  (2026-09-26, formatter at `~/.claude/scripts/evt-monitor.sh`.)
105
- - **A supervisor tick runs every five minutes** while a session is open:
118
+ - **A supervisor tick runs every thirty minutes** while a session is open:
106
119
  sweep the lanes, act on "Review needed", cap concurrent verifies at two,
107
120
  regenerate the roadmap after a merge, and run the improvement loop every
108
- sixth tick. Its prompt is checked in at
121
+ tick. Its prompt is checked in at
109
122
  `plans/kxm-roadmap/supervisor-prompt.md`; a tick that finds the schedule
110
123
  missing or expiring recreates it from that file in the same chat session,
111
124
  never a new one, so the loop continues under the same task. (2026-09-26.)
package/docs/glossary.md CHANGED
@@ -104,7 +104,7 @@ Another [agent](#agent) in the same [project](#project). `kxm_list` and `kxm pee
104
104
 
105
105
  ### Project
106
106
 
107
- The authentication and discovery namespace on the hub. Every command resolves it the same way: `--project` or `KXM_PROJECT`, then the [project ID](#project-id) in `.kxm/project.yaml`, then the `package.json` name, then the directory name. Its key in the hub's `KXM_PROJECT_TOKENS` holds its token. Agents see only peers in the same project.
107
+ The authentication and discovery namespace on the hub. Every command resolves it the same way: `--project` or `KXM_PROJECT`, then the active mode's `project` in `.kxm/config.yaml`, then the [project ID](#project-id) in `.kxm/project.yaml`, then the `package.json` name, then the directory name. Its token is a key reference in that config, or the matching key in the hub's `KXM_PROJECT_TOKENS`. Agents see only peers in the same project.
108
108
 
109
109
  ### Project ID
110
110
 
@@ -112,7 +112,7 @@ The stable `prj_` identifier in `.kxm/project.yaml`. It is the hub [project](#pr
112
112
 
113
113
  ### Project token
114
114
 
115
- The credential that the agents of one [project](#project) use. The operator sets it in the hub's `KXM_PROJECT_TOKENS` JSON map, and agents receive it as `KXM_AUTH_TOKEN` or the plugin's `auth_token`. Setting `KXM_PROJECT_TOKENS` replaces the hub's saved map, so list every project each time.
115
+ The credential that the agents of one [project](#project) use. The operator points config at it with `key.op` (`op://vault/item/field`) or `key.env` (an environment variable name), or sets the hub's `KXM_PROJECT_TOKENS` JSON map. The config file never holds the token. Agents receive the resolved value as `KXM_AUTH_TOKEN` or the plugin's `auth_token`. Setting `KXM_PROJECT_TOKENS` replaces the hub's saved map, so list every project each time. A config `hub.projects` map is resolved in memory and is not saved.
116
116
 
117
117
  ### Session token
118
118
 
@@ -88,7 +88,7 @@ If a malformed claim remains, read the exact `.pid` JSON in the state directory
88
88
  | `hub_bind_unauthenticated` | The URL is remote and this machine has no token for the project; export it and bind again |
89
89
  | `hub_credential_unreadable` | Repair or remove `hub-env.json` under the user state root |
90
90
  | `cloud_token_missing` | A `--cloud` binding's variable is empty and it has no working command. Export the variable or fix `--token-command`. This machine's hub-env token is not sent |
91
- | `cloud_flag_required` | `--token-env` or `--token-command` was passed without `--cloud` |
91
+ | `cloud_flag_required` | `--token-command` was passed without `--cloud`. `--token-env` and `--key-op` are key references and are valid on a local bind |
92
92
  | 401 after binding a loopback forward | The bind was not `--cloud`, so the client sent the local hub-env token. See [Cross-box peer attach](../operations.md#cross-box-peer-attach) |
93
93
 
94
94
  ## Claude Code plugin and MCP
@@ -99,7 +99,7 @@ The [plugin troubleshooting guide](../../plugins/kxm/README.md#troubleshooting)
99
99
  |---|---|
100
100
  | `kxm_*` tools do not appear | Check `/mcp` for the `kxm` server, check `node --version`, run `/reload-plugins`, and confirm `claude plugin list` shows `kxm@kxm` enabled |
101
101
  | `KXM hub unreachable at <url>` | Start the hub, or correct `server_url` with `/plugin configure kxm@kxm` |
102
- | `no project token for project <p>` | Enter the project token at `/plugin configure kxm@kxm`, or add `<p>` to the hub's full `KXM_PROJECT_TOKENS` map and restart the hub |
102
+ | `kxm has no project token for project <p>` | The message names where `<p>` came from. Set `hub.local.project` or `hub.cloud.project` and a key reference in `.kxm/config.yaml`, or add `<p>` to the hub's full `KXM_PROJECT_TOKENS` map and restart the hub. Never paste the token into the file |
103
103
  | `KXM hub rejected the project token for project <p>` | Enter the token the hub holds for `<p>` |
104
104
  | `tool_policy_denied: Session token on disk is malformed or expired` | Run `kxm session token --clear` |
105
105
  | Pushed requests never arrive | Start Claude Code with `claude --dangerously-load-development-channels plugin:kxm@kxm` and accept the trust prompt, or use `kxm_inbox` and `kxm_reply` |
@@ -92,7 +92,7 @@ Expected output:
92
92
 
93
93
  ```text
94
94
  bound hub http://127.0.0.1:17331 · remote · health=on · token is not stored
95
- hub health=true ready=true · remote hub
95
+ hub health=true ready=true · remote hub · mode=cloud project=prj_example (.kxm/config.yaml hub.cloud.project) key=env:KXMD_HUB_TOKEN
96
96
  ```
97
97
 
98
98
  `--token-env` and `--token-command` can be combined. A non-empty variable wins.
@@ -115,8 +115,8 @@ kxm hub view
115
115
  |---|---|---|
116
116
  | Loopback URL | Scope `loopback`. No credential required | Scope `remote`, including an SSH forward |
117
117
  | Token stored in `hub-binding.json` | No | No. The file names `tokenEnv` and/or `tokenCommand` |
118
- | Credential later commands send | `KXM_AUTH_TOKEN`, then this machine's hub-env | The named source only. Hub-env is not a fallback |
119
- | Missing source | Agent commands report `project_token_missing` | `cloud_token_missing` or `cloud_token_command_failed`. The local admin token is not sent |
118
+ | Credential later commands send | `KXM_AUTH_TOKEN`, then the active mode's key reference in `.kxm/config.yaml`, then this machine's hub-env | The active mode's key reference, then the binding's named source. Hub-env is not a fallback |
119
+ | Missing source | Agent commands report `project_token_missing` and name the project id that was sent | `cloud_token_missing` or `cloud_token_command_failed`. The local admin token is not sent |
120
120
  | `kxm hub start` from an extension | May start a local hub | Does not start a local hub when the forward is down (`cloud_hub_unreachable`) |
121
121
 
122
122
  `kxm hub view`, `kxm tenant status`, `kxm peer`, `kxm workflow` agent commands,
@@ -124,9 +124,60 @@ kxm hub view
124
124
  all use that source. `kxm agent worker` puts `KXM_AUTH_TOKEN` in the child
125
125
  process environment only. It does not write the token to disk.
126
126
 
127
- The hub project id is the same value for peer commands and `kxm tenant status`:
128
- `--project` or `KXM_PROJECT`, then the `id` in `.kxm/project.yaml`, then
129
- `package.json` `name`, then the directory name.
127
+ The hub project id is the same value everywhere: `--project` or `KXM_PROJECT`,
128
+ then the active mode's `project` in `.kxm/config.yaml`, then the `id` in
129
+ `.kxm/project.yaml`, then `package.json` `name`, then the directory name.
130
+
131
+ ### Hub identity in config
132
+
133
+ Hub URL, mode, project id, and key reference live in `.kxm/config.yaml`
134
+ (`kxm.config.v1`), the same file as `hub.autoStart`. `.kxm/project.yaml` stays
135
+ the stable project id. The project file wins over
136
+ `~/.config/kxm/config.yaml`. `KXM_PROJECT` and `KXM_SERVER_URL` select the
137
+ live connection for one process. They do not rewrite the file.
138
+
139
+ ```yaml
140
+ hub:
141
+ autoStart: background
142
+ mode: local # local | cloud
143
+ local:
144
+ url: http://127.0.0.1:7331
145
+ project: prj_example # optional; defaults to the project.yaml id
146
+ key:
147
+ op: op://Private/kxm/local-project-token
148
+ env: KXM_LOCAL_PROJECT_TOKEN
149
+ cloud:
150
+ url: https://hub.kxmd.dev
151
+ project: prj_example
152
+ key:
153
+ op: op://Private/kxmd/project-token
154
+ env: KXMD_HUB_TOKEN
155
+ projects: # hub process map; references only
156
+ prj_example:
157
+ op: op://Private/kxm/local-project-token
158
+ env: KXM_LOCAL_PROJECT_TOKEN
159
+ ```
160
+
161
+ `key.op` is an `op://vault/item/field` reference. `key.env` is an environment
162
+ variable name. A non-empty variable wins; otherwise `op read` runs when the
163
+ client or the hub needs the token. The resolved value is not written to
164
+ config, `hub-binding.json`, or `hub-env.json`. A literal token is refused
165
+ with `hub_config_invalid`.
166
+
167
+ `kxm hub bind` and `kxm hub bind --cloud` write the mode, URL, project id, and
168
+ key reference. `--key-op` is the `op://` reference for either mode.
169
+ `--token-env` names the variable for either mode. `--token-command` stays
170
+ cloud-only. `kxm hub view` prints the mode, URL, project id, and key source.
171
+ It does not print the token. `kxm hub unbind` removes the binding and
172
+ `hub.mode`, and leaves the `local` and `cloud` blocks in place.
173
+
174
+ On the hub, `hub.projects` is that same kind of map. `KXM_PROJECT_TOKENS`
175
+ still replaces the map and is saved. A config map is resolved in memory and
176
+ does not replace the saved file.
177
+
178
+ A setup whose hub map is still keyed by the package name should set
179
+ `hub.local.project` or `hub.cloud.project` to that name. Otherwise clients
180
+ send the `.kxm/project.yaml` id and the hub has no token for it.
130
181
 
131
182
  ### Remove the binding
132
183
 
@@ -134,8 +185,10 @@ The hub project id is the same value for peer commands and `kxm tenant status`:
134
185
  kxm hub unbind
135
186
  ```
136
187
 
137
- Unbind deletes `hub-binding.json`. It does not delete hub-env, and it does not
138
- close the SSH forward. Stop the forward by ending the `ssh -N` session.
188
+ Unbind deletes `hub-binding.json` and clears `hub.mode` in `.kxm/config.yaml`.
189
+ The `local` and `cloud` blocks stay, so the next bind can switch mode again.
190
+ It does not delete hub-env, and it does not close the SSH forward. Stop the
191
+ forward by ending the `ssh -N` session.
139
192
 
140
193
  ## Troubleshooting
141
194
 
@@ -143,6 +196,7 @@ close the SSH forward. Stop the forward by ending the `ssh -N` session.
143
196
  |---|---|---|
144
197
  | 401 `invalid_auth` after binding `127.0.0.1:17331` | The bind was not `--cloud`, so the client sent this machine's hub-env admin token | Bind again with `--cloud` and a token source that holds the remote hub's token. Unset a stale `KXM_AUTH_TOKEN` that points at the local hub |
145
198
  | `cloud_token_missing` | `KXMD_HUB_TOKEN` (or the variable you named) is unset or empty, and no command is configured | Export the variable or pass `--token-command`. The local hub-env token is intentionally unused |
199
+ | `project_token_missing` | The project id sent to the hub has no agent token. The message names that id and where it came from | Set `hub.local.project` or `hub.cloud.project` in `.kxm/config.yaml` to the id the hub already knows, and point `key.op` or `key.env` at the token. `KXM_PROJECT` or `--project` overrides the id for one command. Do not paste the token into the file |
146
200
  | `cloud_token_command_failed` | `op` exited non-zero, timed out, or printed more than one line | Run the same command in a terminal and sign in to 1Password. Do not paste the token into the binding |
147
201
  | Clients through one SSH host get locked out together | The hub rate-limits by agent id, otherwise by source address. Every forward from one SSH session shares `127.0.0.1` on the hub. `sshd` `MaxStartups` and `MaxSessions` can refuse new forwards first | Give each long-lived agent its own name. Raise the SSH limits on that host if many people share one jump host. Do not point two tenants at one hub |
148
202
  | `kxm hub view` says `loopback` for the forward | `--cloud` was omitted | Bind again with `--cloud`. `KXM_SERVER_URL` overrides the binding URL and is labeled on its own |