@kontextmind/kxm 0.7.39 → 0.7.43
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +41 -7
- package/docs/README.md +5 -3
- package/docs/agent-skills.md +1 -1
- package/docs/architecture.md +1 -1
- package/docs/configuration.md +28 -5
- package/docs/{vnext → contracts}/README.md +7 -7
- package/docs/{vnext → contracts}/architecture.md +2 -2
- package/docs/{vnext → contracts}/migration.md +25 -25
- package/docs/{vnext → contracts}/routing.md +2 -2
- package/docs/{vnext → contracts}/synchronization.md +1 -1
- package/docs/{vnext → contracts}/validation.md +7 -7
- package/docs/getting-started.md +1 -1
- package/docs/kb/qa-authentik-authentication.md +47 -0
- package/docs/kb/qa-extension-install-and-hub-bootstrap.md +68 -0
- package/docs/kb/qa-hub-on-a-public-host.md +31 -0
- package/docs/kb/qa-sqlite-vs-duckdb.md +18 -0
- package/docs/kb/qa-what-the-hub-stores.md +47 -0
- package/docs/packages.md +91 -0
- package/docs/templates/architecture.md +1 -1
- package/docs/test-matrix.md +6 -6
- package/docs/tui-components.md +131 -0
- package/examples/README.md +2 -2
- package/examples/{vnext → project}/.kxm/agents/critic-3.yaml +1 -1
- package/examples/{vnext → project}/README.md +4 -4
- package/package.json +18 -8
- package/packages/core/tui/CHANGELOG.md +19 -0
- package/packages/core/tui/LICENSE +21 -0
- package/packages/core/tui/README.md +45 -0
- package/packages/core/tui/dist/index.js +1439 -0
- package/packages/core/tui/src/adapters/pi.ts +73 -0
- package/packages/core/tui/src/adapters/terminal.ts +106 -0
- package/packages/core/tui/src/exports/index.ts +30 -0
- package/packages/core/tui/src/services/registry.ts +274 -0
- package/packages/core/tui/src/tui/keys.ts +130 -0
- package/packages/core/tui/src/tui/layout.ts +117 -0
- package/packages/core/tui/src/tui/panel.ts +435 -0
- package/packages/core/tui/src/tui/panelComponent.ts +208 -0
- package/packages/core/tui/src/tui/render.ts +309 -0
- package/packages/core/tui/src/tui/theme.ts +145 -0
- package/packages/core/tui/src/types/surface.ts +407 -0
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +681 -553
- package/plugins/kxm/dist/extension.js +18 -18
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/{vnext-runtime-supervisor.js → runtime-supervisor.js} +553 -553
- package/plugins/kxm/dist/runtime.js +608 -608
- package/plugins/kxm/dist/server.js +13 -13
- package/plugins/kxm/package.json +2 -2
- package/plugins/kxm/skills/kxm-project-setup/SKILL.md +2 -2
- package/plugins/kxm/skills/kxm-runs/SKILL.md +3 -3
- package/plugins/kxm/skills/kxm-session/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-workflow/SKILL.md +1 -1
- package/plugins/kxm/src/autocomplete.ts +4 -4
- package/plugins/kxm/src/{vnext-bindings.ts → bindings.ts} +48 -48
- package/plugins/kxm/src/cli/hub.ts +3 -3
- package/plugins/kxm/src/cli/{vnext.ts → project.ts} +106 -106
- package/plugins/kxm/src/cli/roles.ts +9 -9
- package/plugins/kxm/src/cli/system.ts +2 -2
- package/plugins/kxm/src/cli/tasks.ts +8 -8
- package/plugins/kxm/src/cli/workflows.ts +8 -8
- package/plugins/kxm/src/cli.ts +47 -47
- package/plugins/kxm/src/config.ts +69 -14
- package/plugins/kxm/src/database.ts +4 -4
- package/plugins/kxm/src/{vnext-engine-artifacts.ts → engine-artifacts.ts} +7 -7
- package/plugins/kxm/src/{vnext-engine-command.ts → engine-command.ts} +40 -40
- package/plugins/kxm/src/{vnext-engine-compile.ts → engine-compile.ts} +64 -64
- package/plugins/kxm/src/{vnext-engine-evidence.ts → engine-evidence.ts} +26 -26
- package/plugins/kxm/src/{vnext-engine-fold.ts → engine-fold.ts} +99 -99
- package/plugins/kxm/src/{vnext-engine-gate-records.ts → engine-gate-records.ts} +105 -105
- package/plugins/kxm/src/{vnext-engine-plan.ts → engine-plan.ts} +69 -69
- package/plugins/kxm/src/{vnext-engine.ts → engine.ts} +502 -502
- package/plugins/kxm/src/gate-hash.ts +10 -0
- package/plugins/kxm/src/{vnext-harness.ts → harness.ts} +1 -1
- package/plugins/kxm/src/hub.ts +1 -1
- package/plugins/kxm/src/init-guide-setup.ts +3 -3
- package/plugins/kxm/src/{vnext-init.ts → init.ts} +93 -93
- package/plugins/kxm/src/kxm-install-kind.ts +1 -1
- package/plugins/kxm/src/kxm-update-config.ts +2 -2
- package/plugins/kxm/src/local-snapshot.ts +23 -23
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/{vnext-migrate.ts → migrate.ts} +123 -123
- package/plugins/kxm/src/model-inventory.ts +1 -1
- package/plugins/kxm/src/{vnext-oneshot-evidence.ts → oneshot-evidence.ts} +2 -2
- package/plugins/kxm/src/{vnext-oneshot-process.ts → oneshot-process.ts} +4 -4
- package/plugins/kxm/src/{vnext-oneshot-producer.ts → oneshot-producer.ts} +24 -24
- package/plugins/kxm/src/{vnext-permission.ts → permission.ts} +86 -86
- package/plugins/kxm/src/{vnext-pi-producer.ts → pi-producer.ts} +13 -13
- package/plugins/kxm/src/{vnext-config.ts → project-config.ts} +177 -177
- package/plugins/kxm/src/{vnext-repair.ts → repair.ts} +159 -159
- package/plugins/kxm/src/restricted-yaml.d.mts +3 -3
- package/plugins/kxm/src/restricted-yaml.mjs +4 -4
- package/plugins/kxm/src/{vnext-runtime-owner.ts → runtime-owner.ts} +35 -35
- package/plugins/kxm/src/{vnext-runtime.ts → runtime-service.ts} +136 -136
- package/plugins/kxm/src/{vnext-runtime-store.ts → runtime-store.ts} +145 -145
- package/plugins/kxm/src/{vnext-runtime-supervisor.ts → runtime-supervisor.ts} +80 -80
- package/plugins/kxm/src/runtime.ts +6 -6
- package/plugins/kxm/src/session-work.ts +3 -3
- package/plugins/kxm/src/studio-layout.ts +6 -6
- package/plugins/kxm/src/{vnext-template.ts → template.ts} +33 -33
- package/plugins/kxm/src/tui.ts +10 -24
- package/schemas/{vnext/README.md → README.md} +3 -3
- package/schemas/{vnext/agent.schema.json → agent.schema.json} +1 -1
- package/schemas/{vnext/assignment-result.schema.json → assignment-result.schema.json} +1 -1
- package/schemas/{vnext/backup-manifest.schema.json → backup-manifest.schema.json} +1 -1
- package/schemas/{vnext/candidate.schema.json → candidate.schema.json} +1 -1
- package/schemas/{vnext/common.schema.json → common.schema.json} +2 -2
- package/schemas/{vnext/context-candidate.schema.json → context-candidate.schema.json} +1 -1
- package/schemas/{vnext/context-packet.schema.json → context-packet.schema.json} +1 -1
- package/schemas/{vnext/delivery-manifest.schema.json → delivery-manifest.schema.json} +1 -1
- package/schemas/{vnext/drive-receipt.schema.json → drive-receipt.schema.json} +2 -2
- package/schemas/{vnext/environment.schema.json → environment.schema.json} +1 -1
- package/schemas/{vnext/gate-registry.schema.json → gate-registry.schema.json} +1 -1
- package/schemas/{vnext/handoff-manifest.schema.json → handoff-manifest.schema.json} +1 -1
- package/schemas/{vnext/init-operation.schema.json → init-operation.schema.json} +1 -1
- package/schemas/{vnext/local-repository-bindings.schema.json → local-repository-bindings.schema.json} +1 -1
- package/schemas/{vnext/memory-record.schema.json → memory-record.schema.json} +1 -1
- package/schemas/{vnext/migration-decision.schema.json → migration-decision.schema.json} +1 -1
- package/schemas/{vnext/migration-plan.schema.json → migration-plan.schema.json} +1 -1
- package/schemas/{vnext/migration-receipt.schema.json → migration-receipt.schema.json} +1 -1
- package/schemas/{vnext/model.schema.json → model.schema.json} +1 -1
- package/schemas/{vnext/modes.schema.json → modes.schema.json} +1 -1
- package/schemas/{vnext/permission-diff.schema.json → permission-diff.schema.json} +1 -1
- package/schemas/policy-draft/README.md +2 -2
- package/schemas/{vnext/prices.schema.json → prices.schema.json} +1 -1
- package/schemas/{vnext/project.schema.json → project.schema.json} +1 -1
- package/schemas/{vnext/repository.schema.json → repository.schema.json} +1 -1
- package/schemas/{vnext/role.schema.json → role.schema.json} +1 -1
- package/schemas/{vnext/run-event.schema.json → run-event.schema.json} +1 -1
- package/schemas/{vnext/session-brief.schema.json → session-brief.schema.json} +2 -2
- package/schemas/{vnext/sync-event.schema.json → sync-event.schema.json} +1 -1
- package/schemas/{vnext/template-provenance.schema.json → template-provenance.schema.json} +1 -1
- package/schemas/{vnext/workflow.schema.json → workflow.schema.json} +1 -1
- package/scripts/build-package.mjs +59 -0
- package/scripts/build-runtime.mjs +3 -2
- package/scripts/check-generated.mjs +2 -1
- package/scripts/check-versions.mjs +12 -1
- package/scripts/docker-install-smoke.mjs +268 -0
- package/scripts/emit-codex-artifacts.mjs +1 -1
- package/scripts/kxm-bump-version.mjs +53 -3
- package/scripts/kxm-runtime-supervisor.mjs +3 -3
- package/scripts/package-surfaces.mjs +39 -0
- package/scripts/roster-policy.mjs +1 -1
- package/plugins/kxm/src/vnext-gate-hash.ts +0 -10
- /package/docs/{vnext → contracts}/effects-and-recovery.md +0 -0
- /package/docs/{vnext → contracts}/lifecycles.md +0 -0
- /package/docs/{vnext → contracts}/terminology.md +0 -0
- /package/examples/{vnext → project}/.kxm/agents/coordinator.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/critic-1.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/critic-2.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/implementer.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/planner.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/reproducer.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/reviewer.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/gates.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/critic-claude.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/critic-gemini.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/critic-grok.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/implementation.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/primary.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/prices.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/project/env.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/project.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/repo/repo.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/workflows/default.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/workflows/fix.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/workflows/improve.yaml +0 -0
- /package/examples/{vnext → project}/records/assignment-result-recorded.json +0 -0
- /package/examples/{vnext → project}/records/assignment-result.json +0 -0
- /package/examples/{vnext → project}/records/context-candidate.json +0 -0
- /package/examples/{vnext → project}/records/delivery-manifest.json +0 -0
- /package/examples/{vnext → project}/records/effect-uncertainty-resolved-sync.json +0 -0
- /package/examples/{vnext → project}/records/effect-uncertainty-resolved.json +0 -0
- /package/examples/{vnext → project}/records/run-created.json +0 -0
- /package/examples/{vnext → project}/records/sync-event.json +0 -0
- /package/examples/{vnext → project}/repositories/api/.kxm/repo/env.yaml +0 -0
- /package/examples/{vnext → project}/repositories/api/.kxm/repo/repo.yaml +0 -0
- /package/examples/{vnext → project}/repositories/web/.kxm/repo/repo.yaml +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,11 +4,45 @@ All notable user-facing changes are documented here. The project follows [Semant
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Terminal component kit package:** `@kontextmind/tui` (`packages/core/tui`, also
|
|
10
|
+
exposed as the `@kontextmind/kxm/tui` export) ships the reusable Pi-renderer-based
|
|
11
|
+
terminal components in the package layer shape (`src/{types,tui,services,adapters,exports}`,
|
|
12
|
+
`tests/{unit,helpers}`), enforced by `test/core/package-layers.test.ts`.
|
|
13
|
+
- **Per-package workspace tooling:** nx + Bun workspace wiring (`nx.json`,
|
|
14
|
+
`bunfig.toml`, `packages/*/project.json`, `scripts/build-package.mjs`) with
|
|
15
|
+
`npm run build:packages|test:packages|check:packages`. Bun is installer and task
|
|
16
|
+
runner only; tests, the hub, and the CLI remain on Node.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **Naming sweep:** the retired `vnext` naming is gone from file and folder names,
|
|
21
|
+
symbols, constants, schema `$id` segments, and error codes (`vnext_*` is now
|
|
22
|
+
`initialization_failed`, `initialization_io_failed`, `wait_failed`); package and
|
|
23
|
+
folder names dropped the `kxm-` prefix. `docs/vnext/` is `docs/contracts/`,
|
|
24
|
+
`examples/vnext/` is `examples/project/`. Dated evidence under `plans/` and
|
|
25
|
+
`.kxm/logs/` keeps its original wording.
|
|
26
|
+
- **Read-only run projection:** `GET /v1/runs/:id` folds the event log without
|
|
27
|
+
persisting a projection write, so a read cannot mutate run state or surface a
|
|
28
|
+
false `run_projection_divergent`.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **Release version surfaces cover workspace packages:** a merged PR no longer
|
|
33
|
+
breaks the release pipeline. `scripts/kxm-bump-version.mjs` now writes the
|
|
34
|
+
version into every package manifest under `packages/`, using the same package
|
|
35
|
+
scan that `scripts/check-versions.mjs` enforces (both import
|
|
36
|
+
`scripts/package-surfaces.mjs`), and patches `package-lock.json` by key rather
|
|
37
|
+
than by searching for the old version string — a third-party dependency that
|
|
38
|
+
happens to share the product's version is left alone, and a workspace package
|
|
39
|
+
with no lock entry fails loudly instead of releasing half-bumped.
|
|
40
|
+
|
|
7
41
|
## 0.7.0 - 2026-09-11
|
|
8
42
|
|
|
9
43
|
### Added
|
|
10
44
|
|
|
11
|
-
- **
|
|
45
|
+
- **KXM Architecture Engine and Multi-Phase Isolation (Phases 0–4):**
|
|
12
46
|
- **Dead Route Brake (Phase 0):** Fails closed and asserts 404 on obsolete `/dispatch`
|
|
13
47
|
endpoint in supervisor API to eliminate legacy unmonitored dispatch routes.
|
|
14
48
|
- **Objective Propagation (Phase 1):** Propagates accepted run objectives into the producer
|
|
@@ -20,7 +54,7 @@ All notable user-facing changes are documented here. The project follows [Semant
|
|
|
20
54
|
resolution (`step.model -> agent.model -> refuse`), enforcing model admission policies and role
|
|
21
55
|
roster alignment before birth.
|
|
22
56
|
- **Asynchronous Scheduler & Graceful Lifecycle (Phase 4):** Asynchronous `/drive` execution via
|
|
23
|
-
`
|
|
57
|
+
`KxmRunScheduler` returning `202 Accepted` with `/v1/runs/:id` poll endpoints, duplicate run
|
|
24
58
|
rejection (`409 Conflict`), and supervisor graceful shutdown that awaits active drives.
|
|
25
59
|
- **Oneshot Harness Isolation, Pricing Safety & Async Probes:**
|
|
26
60
|
- Standardized one-shot harness execution across Anthropic Claude, OpenAI Codex, Kimi, and Google AGY
|
|
@@ -48,7 +82,7 @@ All notable user-facing changes are documented here. The project follows [Semant
|
|
|
48
82
|
baseline metrics, declared outcome, measure, and proposed diff patch. Skills carry
|
|
49
83
|
standard YAML frontmatter (`name`, `description`). `skills promote` emits a unified diff
|
|
50
84
|
patch (`.patch`) instead of moving a directory. Added `improve.yaml` workflow in
|
|
51
|
-
`examples/
|
|
85
|
+
`examples/project/.kxm/workflows/` completing on the driver. Un-gitignored retrospective exports.
|
|
52
86
|
- **Database backup, restore, and migrations (E6, issue #102):** Unified SQLite
|
|
53
87
|
lifecycle via `openDatabase` with fail-closed schema checks, WAL journal mode with
|
|
54
88
|
retry loop, busy timeout, and transaction helper with a nesting guard. Stepwise
|
|
@@ -71,7 +105,7 @@ All notable user-facing changes are documented here. The project follows [Semant
|
|
|
71
105
|
creation. Reorganized tests into `test/core/` (PR gate) and `test/simulations/`
|
|
72
106
|
(heavy simulations) with parallel `--test-concurrency=4` and scheduled nightly
|
|
73
107
|
coverage.
|
|
74
|
-
- Agent-only
|
|
108
|
+
- Agent-only KXM run loop (`engine.ts`): pins a D1 compiled plan in an
|
|
75
109
|
immutable hashed envelope, folds schema-valid `kxm.run-event.v1` events with
|
|
76
110
|
a run_state projection, and drives a model-free simulated producer under
|
|
77
111
|
transition/step budgets. Public drive, step, and scheduler share one
|
|
@@ -84,10 +118,10 @@ All notable user-facing changes are documented here. The project follows [Semant
|
|
|
84
118
|
refused (E6). Gate dispatch stays S3/S4. Evaluated gate settlement applies
|
|
85
119
|
transition-budget failure, and complete/no-start observation facts are
|
|
86
120
|
closed on both insert and replay.
|
|
87
|
-
- Pure
|
|
121
|
+
- Pure KXM workflow compile (`engine-compile.ts`) turns a validated
|
|
88
122
|
`kxm.workflow.v1` into a frozen JSON plan. Compile is not execution; D3/D4
|
|
89
123
|
remain open.
|
|
90
|
-
- Routing contract doc (`docs/
|
|
124
|
+
- Routing contract doc (`docs/contracts/routing.md`) and synchronization status
|
|
91
125
|
(schema-tested; Phase 8 implementation).
|
|
92
126
|
- Tag-triggered `release.yml` packs `kxm-<v>.tgz`, creates or reuses only a
|
|
93
127
|
**draft** GitHub release, and fails unless the REST asset digest equals the
|
|
@@ -99,7 +133,7 @@ All notable user-facing changes are documented here. The project follows [Semant
|
|
|
99
133
|
`--ignore-scripts` install, the job runs that package's `install.cjs` so
|
|
100
134
|
the native binary is present.
|
|
101
135
|
- Session brief `AGENTS.md` / `CLAUDE.md` and Tracking in
|
|
102
|
-
`docs/
|
|
136
|
+
`docs/contracts/implementation-plan.md` (roles, provider-native harness routing,
|
|
103
137
|
cost/insights, plan hygiene).
|
|
104
138
|
- Hub-local session chrome: `kxm session brief [--status]`, Pi TUI picker and
|
|
105
139
|
status line on new/fork sessions, `/kxm` (`status`/`hub`/`help`), skill
|
package/docs/README.md
CHANGED
|
@@ -8,6 +8,8 @@ This documentation is organized by task. Start with the guide that matches what
|
|
|
8
8
|
| [Getting started](getting-started.md) | Pi and Claude Code users | Complete the first successful multi-agent exchange |
|
|
9
9
|
| [Configuration](configuration.md) | Users and operators | Understand every supported setting and default |
|
|
10
10
|
| [Architecture](architecture.md) | Maintainers and integrators | Learn the component boundaries and message lifecycle |
|
|
11
|
+
| [Terminal components](tui-components.md) | Maintainers and integrators | The reusable panel kit behind `kxm dash` and every configuration surface |
|
|
12
|
+
| [Packages and workspaces](packages.md) | Maintainers | Workspace layout, Nx targets, Bun task running, and the layer gate |
|
|
11
13
|
| [Agent Skills](agent-skills.md) | Users and integrators | Comprehensive skill suite covering all KXM commands with progressive disclosure |
|
|
12
14
|
| [Browser automation](browser-automation.md) | Developers and operators | Self-hosted Steel on DOKS, agent-browser, Playwright, pass-cli, and human takeover. See the [knowledge base](browser-automation.md#knowledge-base) and [prompt templates](browser-automation.md#prompt-templates) |
|
|
13
15
|
| [Skills](skills.md) | Operators and skill authors | Governed candidate lifecycle; also the [repository work delivery](skills/repo-work-delivery.md) skill |
|
|
@@ -22,7 +24,7 @@ This documentation is organized by task. Start with the guide that matches what
|
|
|
22
24
|
| [Agent Envelopes & Quality Gates](agent-communication-envelopes-and-gates.md) | Multi-agent workflow engineers | Production communication envelopes, quality gates, and work loops |
|
|
23
25
|
| [Assignment runner](assignment-runner.md) | Maintainers and developers | Native developer assignments, deterministic witness verification, and multi-vendor dual-critic acceptance |
|
|
24
26
|
| [This host's Pi packages](operator-pi-packages.md) | Maintainers on this development host | Snapshot of operator `pi list` packages and file extensions; not a KXM install requirement |
|
|
25
|
-
| [
|
|
27
|
+
| [KXM contract package](contracts/README.md) | Maintainers and reviewers | Review the accepted local-first target architecture and implementation contracts |
|
|
26
28
|
|
|
27
29
|
Project-level policies live at the repository root:
|
|
28
30
|
|
|
@@ -34,7 +36,7 @@ Project-level policies live at the repository root:
|
|
|
34
36
|
|
|
35
37
|
- Put the shortest successful path before optional details.
|
|
36
38
|
- Use the product terms **hub**, **agent**, **peer**, **project**, **request**, and **reply** consistently.
|
|
37
|
-
- Distinguish verified behavior from planned behavior; `docs/
|
|
39
|
+
- Distinguish verified behavior from planned behavior; `docs/contracts` is a planned normative target until activation.
|
|
38
40
|
- Distinguish durable single-node delivery from clustering and exactly-once execution.
|
|
39
41
|
- Update the relevant guide in the same change that modifies user-visible behavior.
|
|
40
42
|
|
|
@@ -48,6 +50,6 @@ CLI behavior.
|
|
|
48
50
|
| `build-feature` | [Getting started](getting-started.md), [Configuration](configuration.md), [Architecture](architecture.md), [Test matrix](test-matrix.md) |
|
|
49
51
|
| `refactor-repair-regressions` | [Architecture](architecture.md), [Test matrix](test-matrix.md), [Troubleshooting](troubleshooting.md), [Provenance gates](provenance-gates.md) |
|
|
50
52
|
| `stabilize-flaky-tests` | [Test matrix](test-matrix.md), [Operations](operations.md), [Troubleshooting](troubleshooting.md) |
|
|
51
|
-
| `design-software-system` | [Architecture](architecture.md), [Configuration](configuration.md), [
|
|
53
|
+
| `design-software-system` | [Architecture](architecture.md), [Configuration](configuration.md), [KXM contracts](contracts/README.md) |
|
|
52
54
|
| `investigate-incident` | [Operations](operations.md), [Troubleshooting](troubleshooting.md), [Webhook workflows](webhook-workflows.md) |
|
|
53
55
|
| `patch-vulnerability` | [Provenance gates](provenance-gates.md), [Operations](operations.md), [Configuration](configuration.md) |
|
package/docs/agent-skills.md
CHANGED
|
@@ -17,7 +17,7 @@ authority, admit new writers, or replace trusted `.kxm/roster.yaml` policy.
|
|
|
17
17
|
| Peer Communication | `kxm-peer` | `peer` | Discover, send, poll/await, cancel, fan out, inbox, and reply safely |
|
|
18
18
|
| Workflow Management | `kxm-workflow` | `workflow`, `gate` | Operate webhook workflows, waits/signals, evidence checkpoints, provenance |
|
|
19
19
|
| Definitions | `kxm-definitions` | `role` | Manage role YAML through configuration commands; role edits do not grant trusted writer admission |
|
|
20
|
-
| Run Management | `kxm-runs` | `run`, `runs` | Create and inspect local
|
|
20
|
+
| Run Management | `kxm-runs` | `run`, `runs` | Create and inspect local KXM runs while preserving execution boundaries |
|
|
21
21
|
| Context & Memory | `kxm-context-memory` | `context`, `memory` | Query role-aware context and manage Git-authored memory proposals |
|
|
22
22
|
| Skill Lifecycle | `kxm-skill-lifecycle` | `skills` | Govern candidate/evaluate/promote/reject/verify lifecycle |
|
|
23
23
|
| Routing & Improve | `kxm-routing-improve` | `routing`, `improve` | Inspect real route quality/cost and propose reviewed improvements |
|
package/docs/architecture.md
CHANGED
|
@@ -28,7 +28,7 @@ Envelope parity is a **shape** guarantee, not a **trust** guarantee. An agent-au
|
|
|
28
28
|
|---|---|---|
|
|
29
29
|
| `kxm session start --id <id> (--mix a,b \| --workflow <definitionId>)` | Resolves names against the workspace `agents.json` / `gates.json`, writes `.kxm/assets/sessions/<id>/session.json` (`kxm.session.v1`), creates `inputs/` and `outputs/` (plus `assets/workflows/<definitionId>/{inputs,outputs,generated}` in workflow mode), and exits. | Start any process, dispatch a workflow, run a gate, or set `KXM_SESSION_ID`. In `--workflow` mode it lists the **entire roster**, not the definition's participants, and does not read the definition. |
|
|
30
30
|
| `kxm session status` | Lists PID claim files and worker-recovery envelopes under `.kxm/state`. | Read `session.json` or report anything `session start` created. |
|
|
31
|
-
| `kxm session brief [--status]` | Read-only hub snapshot of recent workflow runs (tasks) and journal `plan` rows. `--status` prints the status line. No message bodies. | Start a hub, dispatch a workflow, or read
|
|
31
|
+
| `kxm session brief [--status]` | Read-only hub snapshot of recent workflow runs (tasks) and journal `plan` rows. `--status` prints the status line. No message bodies. | Start a hub, dispatch a workflow, or read KXM Runtime runs |
|
|
32
32
|
| `kxm session stop` | Requests shutdown of the hub **and every worker** with a PID file in the workspace. It takes no session ID and is the same operation as `kxm hub stop`. | Stop one session. **Treat it as a global stop.** |
|
|
33
33
|
|
|
34
34
|
Treat `session.json` as a manifest for humans and dashboards. The effective execution primitives are `kxm hub start` (one hub process), `kxm agent worker` (one worker process), and `kxm workflow start` (one signed run).
|
package/docs/configuration.md
CHANGED
|
@@ -2,7 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
KXM uses environment variables for the hub and Pi extension. The Claude Code plugin maps its settings to the same client values.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Personalization and workflow settings (`kxm.config.v1`)
|
|
6
|
+
|
|
7
|
+
`kxm config list|get|set` reads one merged view of three layers, in this order:
|
|
8
|
+
|
|
9
|
+
1. built-in defaults in `plugins/kxm/src/config.ts`;
|
|
10
|
+
2. user scope at `~/.config/kxm/config.yaml` (override the directory with
|
|
11
|
+
`KXM_USER_CONFIG_DIR`);
|
|
12
|
+
3. project scope at `<repo>/.kxm/config.yaml`.
|
|
13
|
+
|
|
14
|
+
`kxm config set <key> <value> --scope user|project` writes exactly one of those
|
|
15
|
+
files, defaulting to project scope. `kxm config list --json` reports which file
|
|
16
|
+
supplied what under `loadedFrom`; an empty `loadedFrom` means nothing is stored
|
|
17
|
+
yet and every value shown is a built-in default. A stored value is not trusted
|
|
18
|
+
because it is in the file: an unknown `hub.autoStart` fails closed to the
|
|
19
|
+
default, and an unset `defaults.harness` means Pi rather than the first harness
|
|
20
|
+
in the catalog.
|
|
21
|
+
|
|
22
|
+
Project identity and repository bindings are separate, Git-tracked files under
|
|
23
|
+
`.kxm/` (`project.yaml`, `roster.yaml`, `routes.yaml`, `gates.yaml`, `prices.yaml`,
|
|
24
|
+
`roles/`, `workflows/`). They are configuration reviewed in a PR, not personal
|
|
25
|
+
settings, and no panel or editor grants writer admission by editing them. See
|
|
26
|
+
[Terminal components](tui-components.md) for the surface that renders them.
|
|
27
|
+
|
|
28
|
+
## KXM local project settings
|
|
6
29
|
|
|
7
30
|
Root `kxm init` discovers the control Git worktree and does not use legacy
|
|
8
31
|
`KXM_*` workspace overrides. A cloned multi-repository project can bind a
|
|
@@ -245,21 +268,21 @@ The tool allowlist is a capability boundary inside Pi, not a prompt suggestion
|
|
|
245
268
|
|
|
246
269
|
## Operator CLI
|
|
247
270
|
|
|
248
|
-
The current hub command groups are `agent`, `session`, `workflow`, `gate`, `hub`, `dash`, `improve`, `context`, and `skills`; the root `init` command is the first configuration-only
|
|
271
|
+
The current hub command groups are `agent`, `session`, `workflow`, `gate`, `hub`, `dash`, `improve`, `context`, and `skills`; the root `init` command is the first configuration-only KXM slice. The CLI is an operator **client**: the hub's durable state, the protocol and schema types, and reviewed Git configuration define behaviour; where the CLI diverges from them, the CLI is the defect.
|
|
249
272
|
|
|
250
273
|
| Command | Purpose |
|
|
251
274
|
|---|---|
|
|
252
|
-
| `kxm init` | Atomically create a provenance-tracked minimal
|
|
275
|
+
| `kxm init` | Atomically create a provenance-tracked minimal KXM project, validate it without rewriting, resume a pinned interrupted create/repair, apply conflict-free non-authority template updates, or join an existing clone with repeatable `--repository <id=absolute-path>` member bindings stored outside Git. `--dry-run` performs no writes. Provenance-free/ambiguous repair and permission-expanding changes remain planning-only. These configuration slices do **not** activate a KXM Runtime. `kxm init` is project-only; bind a running hub with `kxm hub bind <url>` |
|
|
253
276
|
| `kxm migrate plan` | Convert legacy `.kxm/config` JSON (agents, gates, workflow definitions) into a deterministic, secret-free `kxm.migration-plan.v1` report: source/target hashes, decision-requiring ambiguities (terminal status, transition budgets, evidence-policy strengthening, secret drops, narrowed ceilings, foreign producers), hashed unmapped fields, and explicit identity renames. Performs no writes, locks, or staging |
|
|
254
277
|
| `kxm migrate apply [--decisions <file>]` | Install a reviewed migration: re-checks the decision binding against current sources, validates the complete target bundle, refuses to overwrite existing paths, installs durably, and writes a self-hashed `kxm.migration-receipt.v1` that keeps legacy inputs read-only. Re-applying is an idempotent no-op. `--dry-run` performs no writes |
|
|
255
278
|
| `kxm migrate verify` | Re-check the migration receipt against current legacy sources and the target bundle (self-hash, source hashes, configuration revision, resource bytes). Performs no writes |
|
|
256
279
|
| `kxm trust diff [--base <rev>]` | Print the structured `kxm.permission-diff.v1` report between a base Git revision (default `HEAD`, materialized into a temporary shadow with a sanitized environment) and the working tree: every authority-bearing field change classified as expansion, narrowing, or neutral with per-field hashes. Performs no project writes |
|
|
257
280
|
| `kxm trust check [--base <rev>]` | Exit non-zero when any expansion exists, so an authority-bearing change cannot merge without a reviewed Git change. Formatting/description-only changes never require review |
|
|
258
|
-
| `kxm run <workflow> [prompt]` | Auto-start the
|
|
281
|
+
| `kxm run <workflow> [prompt]` | Auto-start the KXM Runtime supervisor if needed, then create an immutable run offline: pins `homeRuntimeId` plus config/executor/tool policy revisions and stores only the prompt hash. `--dry-run` prints the plan without creating anything |
|
|
259
282
|
| `kxm runs status <runId>` | Show the projected status of a run from its event sequence |
|
|
260
283
|
| `kxm runs cancel <runId>` | Durably request cancellation (ordered `run.cancel_requested` then `run.status_changed` events; idempotent, terminal runs are no-ops). `--dry-run` writes nothing |
|
|
261
284
|
| `kxm runs list` | List recent runs for the current project |
|
|
262
|
-
| `kxm runtime start \| status \| stop` | Manage the detached
|
|
285
|
+
| `kxm runtime start \| status \| stop` | Manage the detached KXM Runtime supervisor: auto-start with liveness probe, token-authenticated 127.0.0.1 API, crash recovery with a stable logical runtime identity |
|
|
263
286
|
| `kxm agent worker` | Start a long-lived Pi worker. Use `--session-isolation workflow` to enable per-workflow Pi contexts; the upgrade-compatible default is `off`. Does not read a workspace `agents.json`; pass `--model`, `--tools`, and related flags explicitly |
|
|
264
287
|
| `kxm session start --id <id> (--mix a,b \| --workflow <definitionId>)` | Write a `kxm.session.v1` manifest under `.kxm/assets/sessions/<id>/` and create asset directories. **Does not start any process.** `--workflow` records the whole roster, not the definition's participants |
|
|
265
288
|
| `kxm session brief [--status]` | Read-only local hub snapshot of recent tasks (workflow runs) and plans (journal). `--status` prints the status line for harness chrome. No message bodies. Does not start a hub |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# KXM
|
|
1
|
+
# KXM contract package
|
|
2
2
|
|
|
3
3
|
> **Status: planned normative contract.** This directory describes the target
|
|
4
|
-
> architecture accepted for KXM
|
|
4
|
+
> architecture accepted for KXM. Not all commands are implemented.
|
|
5
5
|
> Phase 1 (init/migrate/trust) and Phase 2 (Runtime create/recover) have landed
|
|
6
6
|
> slices. Phase 3 has D3 S1–S4 and D4 U2a-2 implemented (unreleased); it is not
|
|
7
7
|
> only an agent-only simulated loop, and the default/fix driver gate remains
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
> For current hub execution behavior, use [Architecture](../architecture.md) and
|
|
12
12
|
> [Configuration](../configuration.md).
|
|
13
13
|
|
|
14
|
-
KXM
|
|
14
|
+
KXM is a convention-over-configuration, local-first orchestration and
|
|
15
15
|
context platform. One local Runtime owns execution; an optional multi-project
|
|
16
16
|
hub coordinates requests, synchronized facts, and aggregate views.
|
|
17
17
|
|
|
@@ -30,9 +30,9 @@ The words **MUST**, **MUST NOT**, **SHOULD**, and **MAY** are normative.
|
|
|
30
30
|
| [Validation](validation.md) | Parse, schema, reference, semantic, permission, and snapshot validation |
|
|
31
31
|
| [Migration](migration.md) | Compatibility from the current environment/JSON/SQLite surfaces |
|
|
32
32
|
| [Implementation plan](../../plans/implementation-plan.md) | Ordered implementation and release gates |
|
|
33
|
-
| [Examples](../../examples/
|
|
33
|
+
| [Examples](../../examples/project/README.md) | Complete project and workflow fixture |
|
|
34
34
|
|
|
35
|
-
Machine-readable schemas live under [`schemas
|
|
35
|
+
Machine-readable schemas live under [`schemas`](../../schemas).
|
|
36
36
|
JSON Schema validates the data model after a YAML document has been parsed with
|
|
37
37
|
custom tags disabled and bounded aliases, depth, scalar size, and document size.
|
|
38
38
|
|
|
@@ -54,9 +54,9 @@ custom tags disabled and bounded aliases, depth, scalar size, and document size.
|
|
|
54
54
|
## Compatibility rule
|
|
55
55
|
|
|
56
56
|
The current v0.5 contracts remain authoritative until a release explicitly
|
|
57
|
-
activates a
|
|
57
|
+
activates a KXM schema. Implementations MUST NOT infer KXM behavior merely
|
|
58
58
|
because these documents or examples are present.
|
|
59
59
|
|
|
60
|
-
Every persisted
|
|
60
|
+
Every persisted KXM resource carries an exact schema identity. Additive
|
|
61
61
|
changes require a new compatible schema revision; a semantic breaking change
|
|
62
62
|
requires a new major schema identity and an explicit migration.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# ADR-001: Local Runtime, project authority, and aggregate hub
|
|
2
2
|
|
|
3
3
|
- **Status:** accepted target
|
|
4
|
-
- **Scope:** KXM
|
|
4
|
+
- **Scope:** KXM
|
|
5
5
|
- **Supersedes:** no current contract until migration activation
|
|
6
6
|
|
|
7
7
|
## Context
|
|
8
8
|
|
|
9
9
|
The current implementation combines durable peer transport, workflow state,
|
|
10
|
-
and context in one hub-oriented process. KXM
|
|
10
|
+
and context in one hub-oriented process. KXM must support multiple
|
|
11
11
|
projects and repositories while continuing useful work when a shared hub is
|
|
12
12
|
unavailable. It must also prevent a hub, model, or learned record from silently
|
|
13
13
|
becoming an execution or policy authority.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Migration and compatibility matrix
|
|
2
2
|
|
|
3
|
-
KXM
|
|
4
|
-
Presence of
|
|
3
|
+
KXM is introduced beside the current v0.5 transport/workflow surfaces.
|
|
4
|
+
Presence of KXM documents does not activate new behavior.
|
|
5
5
|
|
|
6
6
|
## Surface matrix
|
|
7
7
|
|
|
8
|
-
| Current surface |
|
|
8
|
+
| Current surface | KXM target | Migration rule |
|
|
9
9
|
|---|---|---|
|
|
10
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
11
|
| `gates.json` descriptive records | Workflow step/gate references plus registered deterministic adapters | Map only implemented gates; report names with no runner |
|
|
@@ -26,27 +26,27 @@ Presence of vNext documents does not activate new behavior.
|
|
|
26
26
|
|
|
27
27
|
## Compatibility releases and activation
|
|
28
28
|
|
|
29
|
-
Local Runtime support may ship publicly before hub
|
|
29
|
+
Local Runtime support may ship publicly before hub KXM, but it remains beside
|
|
30
30
|
existing hub contracts and stores. Old command names are not preserved. A project
|
|
31
31
|
activates `kxm.*.v1` only by an explicit successful `kxm init`/migration receipt;
|
|
32
32
|
file presence alone never activates it. Legacy hub runs continue on the legacy
|
|
33
33
|
engine.
|
|
34
34
|
|
|
35
|
-
When Phase 8 activates hub
|
|
35
|
+
When Phase 8 activates hub KXM, at least one hub transition release provides:
|
|
36
36
|
|
|
37
37
|
- current `mesh_*` peer tools;
|
|
38
38
|
- current hub APIs behind a compatibility adapter;
|
|
39
|
-
- legacy JSON configuration read support while
|
|
39
|
+
- legacy JSON configuration read support while KXM writes only YAML;
|
|
40
40
|
- current completed workflow history read/export support;
|
|
41
|
-
- Runtime-managed
|
|
42
|
-
- CLI labels for legacy versus
|
|
41
|
+
- Runtime-managed KXM runs in new event stores with new identities;
|
|
42
|
+
- CLI labels for legacy versus KXM state;
|
|
43
43
|
- no implicit movement of active runs between engines.
|
|
44
44
|
|
|
45
|
-
Before activation, a repository MUST NOT use legacy and
|
|
45
|
+
Before activation, a repository MUST NOT use legacy and KXM definitions with
|
|
46
46
|
the same normalized identity. Validation reports the conflict and requires an
|
|
47
|
-
explicit migration choice. After a migration receipt activates the
|
|
47
|
+
explicit migration choice. After a migration receipt activates the KXM copy,
|
|
48
48
|
the matching legacy definition is read-only compatibility input and cannot be
|
|
49
|
-
selected for a new
|
|
49
|
+
selected for a new KXM run.
|
|
50
50
|
|
|
51
51
|
## Migration commands
|
|
52
52
|
|
|
@@ -105,12 +105,12 @@ values outside the plan's allowed set fail closed before any write.
|
|
|
105
105
|
decision digest, target configuration revision, and installed resource
|
|
106
106
|
hashes; the receipt is self-hashed.
|
|
107
107
|
8. Re-load the mixed tree: legacy inputs remain intact but receipt-pinned
|
|
108
|
-
read-only; `
|
|
108
|
+
read-only; `loadKxmProject` accepts coexistence only through the
|
|
109
109
|
verified receipt.
|
|
110
110
|
|
|
111
111
|
Re-applying with the receipt present is an idempotent no-op
|
|
112
112
|
(`already-migrated`). Editing a legacy source after the receipt makes both
|
|
113
|
-
`
|
|
113
|
+
`loadKxmProject` and `kxm migrate verify` fail closed.
|
|
114
114
|
|
|
115
115
|
### Verify
|
|
116
116
|
|
|
@@ -131,11 +131,11 @@ Before any database operation:
|
|
|
131
131
|
|
|
132
132
|
Current agents, messages, workflow runs, journal entries, and context items are
|
|
133
133
|
imported as typed **legacy records**. They are not fabricated into fine-grained
|
|
134
|
-
|
|
134
|
+
KXM run events whose original ordering was never observed.
|
|
135
135
|
|
|
136
136
|
Completed legacy runs remain queryable. A legacy active run must either finish
|
|
137
137
|
on the old engine or be explicitly cancelled/exported; it is not resumed as a
|
|
138
|
-
|
|
138
|
+
KXM run.
|
|
139
139
|
|
|
140
140
|
## Configuration migration
|
|
141
141
|
|
|
@@ -156,7 +156,7 @@ The implemented converter:
|
|
|
156
156
|
transition budgets, and widens evidence-carrying steps into an explicit
|
|
157
157
|
assignment pool containing their producers;
|
|
158
158
|
- converts legacy peer-reply evidence policies (`acceptedStatuses:
|
|
159
|
-
["replied"]`) into
|
|
159
|
+
["replied"]`) into KXM producer policies requiring `passed` only through
|
|
160
160
|
an explicit operator decision;
|
|
161
161
|
- requires decisions for: every legacy `$terminal` edge's terminal status
|
|
162
162
|
(legacy completed the run even on failure outcomes), every unbounded
|
|
@@ -174,11 +174,11 @@ The implemented converter:
|
|
|
174
174
|
Unknown data is preserved in the migration report, not placed into a generic
|
|
175
175
|
runtime extension map.
|
|
176
176
|
|
|
177
|
-
Legacy typed workflows have a global transition budget but may lack
|
|
177
|
+
Legacy typed workflows have a global transition budget but may lack KXM
|
|
178
178
|
per-back-edge caps. The migrator MUST NOT invent those caps silently. `migrate
|
|
179
179
|
plan` lists every affected edge and a proposed bounded value; `migrate apply`
|
|
180
180
|
requires the values in an operator-approved migration decision. The committed
|
|
181
|
-
|
|
181
|
+
KXM `/fix` fixture is one reviewed resolution, not a generic automatic rule.
|
|
182
182
|
|
|
183
183
|
Stage IDs, outcome keys, evidence keys, oracle references, plan-hash references,
|
|
184
184
|
and eligible producer identities are preserved by default. Any unavoidable
|
|
@@ -188,25 +188,25 @@ references atomically.
|
|
|
188
188
|
## Session migration
|
|
189
189
|
|
|
190
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
|
|
192
|
-
The first
|
|
191
|
+
archived under the old worker binding and are never selected for a KXM run.
|
|
192
|
+
The first KXM physical session starts clean. Durable facts must come from Git,
|
|
193
193
|
workflow evidence, artifacts, or promoted context rather than conversation
|
|
194
194
|
history.
|
|
195
195
|
|
|
196
196
|
## Rollback
|
|
197
197
|
|
|
198
198
|
Rollback is supported until the operator accepts the migration receipt and
|
|
199
|
-
starts a permission-expanding
|
|
199
|
+
starts a permission-expanding KXM-only run.
|
|
200
200
|
|
|
201
201
|
Rollback:
|
|
202
202
|
|
|
203
|
-
1. stop
|
|
204
|
-
2. preserve
|
|
203
|
+
1. stop KXM writers;
|
|
204
|
+
2. preserve KXM stores as diagnostic artifacts;
|
|
205
205
|
3. restore the recorded legacy configuration selection and database path;
|
|
206
206
|
4. restart only compatible legacy processes;
|
|
207
207
|
5. verify legacy health and record rollback evidence.
|
|
208
208
|
|
|
209
|
-
Events created only by
|
|
209
|
+
Events created only by KXM are not reverse-translated into fabricated legacy
|
|
210
210
|
workflow history.
|
|
211
211
|
|
|
212
212
|
## Removal gate
|
|
@@ -215,6 +215,6 @@ Legacy readers and command aliases are removed only after:
|
|
|
215
215
|
|
|
216
216
|
- at least one compatibility release;
|
|
217
217
|
- migration telemetry shows no material unmapped cases;
|
|
218
|
-
- package/install/Windows tests cover
|
|
218
|
+
- package/install/Windows tests cover KXM;
|
|
219
219
|
- operator documentation and rollback paths are proven;
|
|
220
220
|
- removal is announced in the changelog.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **Status.** `kxm.routing-record.v1` is parse-only for legacy records.
|
|
4
4
|
> `kxm.routing-record.v2` is **implemented and active**: emitted at engine
|
|
5
|
-
> attempt settlement (`routing.attempt.recorded` event in `plugins/kxm/src/
|
|
5
|
+
> attempt settlement (`routing.attempt.recorded` event in `plugins/kxm/src/engine.ts`),
|
|
6
6
|
> enforced with fail-closed `costBasis` requirement. Price catalog `.kxm/prices.yaml`
|
|
7
7
|
> (`kxm.prices.v1`) is implemented, dated, and hashed. `kxm routing report`
|
|
8
8
|
> is implemented (`plugins/kxm/src/routing.ts`) and ranks routes quality-first,
|
|
@@ -164,7 +164,7 @@ Fields carried on `RoutingRecordV2`:
|
|
|
164
164
|
- Outcomes: `verifierOutcome` (`passed` | `warning` | `failed`), `finalOutcome` (`accepted` | `blocked` | `failed` | `pending`), `retries`, optional `transitions`, optional `humanInterventions`, optional `providerMetadata`.
|
|
165
165
|
- Cost accounting: `costBasis` (`"metered" | "unmetered" | "unknown"`), `costUsd` (required when metered), optional `priceRef`.
|
|
166
166
|
|
|
167
|
-
The
|
|
167
|
+
The KXM 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
168
|
|
|
169
169
|
## Implemented: report and price catalog
|
|
170
170
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **Status.** `kxm.sync-event.v1` is a **schema-tested contract**. There is no
|
|
4
4
|
> outbox table, sync transform, or hub ingestion in source. Implementation
|
|
5
|
-
> begins in [Phase 8](../../plans/implementation-plan.md#phase-8-multi-project-hub-
|
|
5
|
+
> begins in [Phase 8](../../plans/implementation-plan.md#phase-8-multi-project-hub-kxm).
|
|
6
6
|
|
|
7
7
|
Synchronization is summary-first, project-scoped, at-least-once, and
|
|
8
8
|
allowlist-based. The full local event is never placed directly in the outbox.
|
|
@@ -23,13 +23,13 @@ the normalized filename without `.yaml`; an in-document identity field is
|
|
|
23
23
|
forbidden.
|
|
24
24
|
|
|
25
25
|
The shared implementation is `plugins/kxm/src/restricted-yaml.mjs`. Public
|
|
26
|
-
`
|
|
26
|
+
`project-config` callers still receive `KxmConfigError` issue codes, paths, and
|
|
27
27
|
messages.
|
|
28
28
|
|
|
29
29
|
`schemas/policy-draft` (`kxm.model.v2`, `kxm.role.v2`) and
|
|
30
30
|
`validatePolicyDraft` are non-authoritative scaffolding. They are not live
|
|
31
31
|
registry identities, operator settings, or admission. Live model files remain
|
|
32
|
-
`kxm.model.v1` under `schemas
|
|
32
|
+
`kxm.model.v1` under `schemas`.
|
|
33
33
|
|
|
34
34
|
## Validation pipeline
|
|
35
35
|
|
|
@@ -40,7 +40,7 @@ UTF-8, and resource-limit violations.
|
|
|
40
40
|
|
|
41
41
|
### 2. JSON Schema validation
|
|
42
42
|
|
|
43
|
-
Validate against the exact schema identity under `schemas
|
|
43
|
+
Validate against the exact schema identity under `schemas`. Unknown fields
|
|
44
44
|
are rejected unless a schema explicitly defines an extension map.
|
|
45
45
|
|
|
46
46
|
### 3. Path and identity validation
|
|
@@ -110,7 +110,7 @@ template revision.
|
|
|
110
110
|
#### Legacy configuration migration
|
|
111
111
|
|
|
112
112
|
`kxm migrate plan|apply|verify` converts legacy `.kxm/config` JSON into
|
|
113
|
-
validated
|
|
113
|
+
validated KXM resources with an exact receipt:
|
|
114
114
|
|
|
115
115
|
- Legacy files are read with byte/depth/node bounds and token-level
|
|
116
116
|
duplicate-key rejection. Symbolic links and linked `workflows/` directories
|
|
@@ -135,7 +135,7 @@ validated vNext resources with an exact receipt:
|
|
|
135
135
|
- Installation uses durable writes under the project mutation lock and finishes
|
|
136
136
|
with a self-hashed `kxm.migration-receipt.v1` binding source hashes, decision
|
|
137
137
|
digest, target configuration revision, and installed resource hashes. The
|
|
138
|
-
receipt keeps the legacy inputs read-only: `
|
|
138
|
+
receipt keeps the legacy inputs read-only: `loadKxmProject` accepts mixed
|
|
139
139
|
trees only through a verified receipt, and any later legacy-source edit makes
|
|
140
140
|
loading and `migrate verify` fail closed. Re-apply is an idempotent no-op.
|
|
141
141
|
- `plan`, `verify`, and every `--dry-run` path perform no writes, locks,
|
|
@@ -222,7 +222,7 @@ description-only changes do not.
|
|
|
222
222
|
#### Structured projections and the `kxm trust` gate
|
|
223
223
|
|
|
224
224
|
The implemented workflow projects every resource into deterministic,
|
|
225
|
-
field-addressed authority entries (`
|
|
225
|
+
field-addressed authority entries (`kxmAuthorityEntries`) covering the
|
|
226
226
|
categories above, then diffs two complete bundles into a
|
|
227
227
|
`kxm.permission-diff.v1` report. Every change is classified conservatively:
|
|
228
228
|
|
|
@@ -296,7 +296,7 @@ revision.
|
|
|
296
296
|
|
|
297
297
|
## Machine-verifiable fixture
|
|
298
298
|
|
|
299
|
-
[`test/core/contracts
|
|
299
|
+
[`test/core/contracts.test.ts`](../../test/core/contracts.test.ts) parses the
|
|
300
300
|
committed YAML example with the restricted parser profile and validates each
|
|
301
301
|
resource plus representative event/result/delivery/candidate records against
|
|
302
302
|
the committed JSON Schemas.
|
package/docs/getting-started.md
CHANGED
|
@@ -74,7 +74,7 @@ workflow-guide agents and workflows for the harnesses you have installed and
|
|
|
74
74
|
authenticated. Accepting lists the software-engineering workflows from
|
|
75
75
|
[`workflow-guide.md`](workflow-guide.md); pick by number or slug (`all` works
|
|
76
76
|
too). kxm resolves each role's first guide candidate whose harness is
|
|
77
|
-
authenticated and writes only current
|
|
77
|
+
authenticated and writes only current KXM project resources —
|
|
78
78
|
`.kxm/agents/<role>.yaml` (`kxm.agent.v1`) and `.kxm/workflows/<slug>.yaml`
|
|
79
79
|
(`kxm.workflow.v1`). It never writes retired legacy authority (`.kxm/config`,
|
|
80
80
|
retired `.kxm/roster.json`) or the trusted `.kxm/roster.yaml` policy. Roles whose candidates have no authenticated harness are
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Q&A: Authentik (OIDC) for user/role/agent authentication
|
|
2
|
+
|
|
3
|
+
> Researched by `claude --model fable` (planner, read-only) · 2026-09-17 · task_c0bb05339e15 · root review: pending
|
|
4
|
+
|
|
5
|
+
**Short answer:** Yes, but not by swapping the hub's checks for OIDC. The hub has one shared-secret model, and the safest hook is a token broker that exchanges Authentik identity for the kxm tokens the hub already understands. Proxy forward-auth is the zero-code first step for humans; hub-side JWT validation is a later, additive gate.
|
|
6
|
+
|
|
7
|
+
## What exists today
|
|
8
|
+
|
|
9
|
+
The hub knows about three credentials. None of them carries a user identity, a role, or a group.
|
|
10
|
+
|
|
11
|
+
1. **Static admin token.** `MeshHubOptions.authToken` (`plugins/kxm/src/hub.ts:77`) is compared with `safeTokenEqual` (`hub.ts:126`, delegating to the SHA-256 `timingSafeEqual` in `commands.ts:937`) against the `Authorization: Bearer` header parsed by `bearerToken` (`hub.ts:130`). `requireAdminAuth` (`hub.ts:533`) gates `/metrics` (`hub.ts:1390`) and admin-scoped context calls (`hub.ts:525`). `requireConfiguredAdminAuth` (`hub.ts:543`) returns 503 `admin_auth_not_configured` when no token is set, gating `/v1/ops/snapshot` and `/v1/ops/events` (`hub.ts:1396`, `1406`) and workflow degradation. The token is sourced from `KXM_AUTH_TOKEN` (`server.ts:15`) or resolved via `resolveHubCredentials` (`hub-env.ts:140`), which generates `kxm_admin_<24 random bytes>` (`hub-env.ts:44`) and persists it to `hub-env.json` with mode 0600 (`hub-env.ts:86`). Auto-start injects it into the hub child's env (`hub-autostart.ts:175`).
|
|
12
|
+
2. **Per-project tokens.** `KXM_PROJECT_TOKENS` is a JSON map of project name to bearer string (`server.ts:45`, `hub-env.ts:120`). `expectedProjectToken` falls back to the admin token when no project token exists (`hub.ts:495`). `requireProjectAuth` (`hub.ts:499`) throws 401 `invalid_auth` on mismatch. Every agent-facing route calls `requireAgent` then `requireProjectAuth(request, agent.project)` (e.g. `hub.ts:1432`, `2133`, `2200`).
|
|
13
|
+
3. **Agent identity (name + key).** `POST /v1/agents/register` (`hub.ts:2091`) accepts a free-form `name`, `purpose`, `project`, `model`, requires only the project token, and mints a fresh `key` via `newId("key")` on every registration or resume (`hub.ts:2107`, `2115`). Name uniqueness is enforced only against currently online agents in the same project (`hub.ts:2098`). The record is stored as opaque JSON in the `agents` table (`store.ts:26`); `AgentRecord` (`protocol.ts:19`) has no role, owner, or principal field. Clients send `x-kxm-agent-id` and `x-kxm-agent-key` headers (`client.ts:540`), which `requireAgent` checks with `safeTokenEqual` (`hub.ts:554`).
|
|
14
|
+
|
|
15
|
+
**Fail-open edges to preserve or close.** With no admin token on a loopback bind, `requireAdminAuth` returns without checking (`hub.ts:534`) and `requireProjectAuth` skips when no expected token exists (`hub.ts:501`); `server.ts:92` warns `auth=none`. A non-loopback bind without a token refuses to start (`hub.ts:468`). Repo rule: "Bypass fail-closed identity checks" is on the do-not list (`AGENTS.md:224`).
|
|
16
|
+
|
|
17
|
+
**Roles and permissions today are not hub-authenticated.** Role definitions map to a `tools` allow/deny/preset block (`role.ts:63`-`137`), and the `role` on `/v1/context/get` is a caller-asserted string used only to pick a context budget and journal categories (`hub.ts:1578`, `arbiter.ts:81`). Tool policy is enforced client-side by `enforceToolPolicy` (`commands.ts:1125`), called from the MCP server (`mcp-server.ts:115`), the Pi extension (`extension.ts:892`), and the CLI (`cli.ts:220`). It reads `KXM_ATTEMPT_TOKEN`, then `KXM_SESSION_TOKEN`, then the on-disk `session.token` (`commands.ts:1130`, `1166`, `1182`), and returns `tool_policy_denied` when `isToolAllowed` (`commands.ts:1086`) rejects. Both token formats are unsigned base64url JSON (`mintAttemptToken` `commands.ts:916`, `mintSessionToken` `commands.ts:977`); `parseSessionToken` checks only schema and expiry (`commands.ts:998`). `kxm auth token --issue` mints an `operator` preset locally with no external identity (`cli/hub.ts:500`). The Studio mutate endpoint compares its session token with plain `!==` rather than the timing-safe helper (`studio-layout.ts:350`). No OIDC, JWT, or JWKS code exists in the repo; the only hits are prose in a role description (`init-guide-setup.ts:136`). The plugin has no JWT dependency (`plugins/kxm/package.json:9`).
|
|
18
|
+
|
|
19
|
+
## Integration options
|
|
20
|
+
|
|
21
|
+
### 1. Reverse-proxy forward-auth (Authentik outpost at the proxy; hub unchanged)
|
|
22
|
+
|
|
23
|
+
Authentik's proxy outpost authenticates browser sessions and passes headers upstream. The hub ignores those headers today, so the proxy must still inject the hub bearer token, or clients must still send it. Covers: Studio, `/v1/ops/*` dashboards, human CLI users via a browser-capable flow. Does not cover: agents (they present `x-kxm-agent-*` headers plus a bearer, not a cookie), and it gives the hub no per-user identity for logging. Effort: low, config only. Risk: low if the hub keeps its token check; medium if someone sets the proxy to add the admin token for every authenticated user, which flattens all Authentik users to admin. Non-loopback bind already requires a token (`hub.ts:468`), so the proxy cannot make the hub anonymous.
|
|
24
|
+
|
|
25
|
+
### 2. Hub validates Authentik-issued JWTs (OIDC discovery + JWKS)
|
|
26
|
+
|
|
27
|
+
Add a second accepted credential in `bearerToken`'s callers: if the bearer parses as a JWT, verify `iss`, `aud`, `exp`, and signature against a cached JWKS from `<issuer>/.well-known/openid-configuration`; else fall through to the existing `safeTokenEqual` path. Code changes: a new `oidc.ts` (discovery, JWKS cache, verify via `node:crypto` `createPublicKey` from JWK, or add `jose`), new `MeshHubOptions.oidc` and `KXM_OIDC_ISSUER` / `KXM_OIDC_AUDIENCE` env in `server.ts` and `hub-env.ts`, and changes to `requireAdminAuth` and `requireProjectAuth` to accept a verified claim set. Mapping: `groups` claim to admin (e.g. `kxm-admin`) and to project scope (e.g. `kxm-project:<name>`). Client side: `HubClient.authToken` (`client.ts:539`) already sends any string as bearer, so a client can pass an Authentik access token unchanged. Effort: medium, roughly 300 to 500 lines plus tests. Risk: medium. New network dependency at auth time (JWKS fetch must fail closed, never skip), clock skew, and the hub must reject `alg: none` and HS256. Agent registration would gain a real principal to store on the agent record (`sub`, `preferred_username`), which the schema can absorb since records are opaque JSON (`store.ts:26`).
|
|
28
|
+
|
|
29
|
+
### 3. Token-broker mapping (Authentik users/groups mint per-user or per-agent kxm tokens)
|
|
30
|
+
|
|
31
|
+
A small broker (could be a new hub route or a sidecar) accepts an Authentik ID token, verifies it as in option 2, then issues the tokens the runtime already consumes: a project token entry for `requireProjectAuth`, and a `kxm.session-token.v1` with a `toolPolicy` derived from the user's group (`mintSessionToken`, `commands.ts:944`). Mapping table: Authentik group to kxm role id (`role.ts:63` ids `writer`, `planner`, `critic-*`, `verifier`), role `tools` block to `ToolPolicy`, and group to project list to `projectTokens`. Today project tokens are a static map read at startup (`hub.ts:385`), so per-user project tokens need either a dynamic token store in `MeshStore` or short-lived tokens the hub can look up. Session tokens are unsigned (`commands.ts:977`), so a broker-issued one only means something if `parseSessionToken` gains signature verification; otherwise any local process can forge the same payload. Effort: medium to high, because it touches token storage, signing, and revocation. Risk: medium. Benefit: agents and humans converge on one identity source without changing every hub route.
|
|
32
|
+
|
|
33
|
+
## Recommendation
|
|
34
|
+
|
|
35
|
+
Phased, honoring the fail-closed rules:
|
|
36
|
+
|
|
37
|
+
1. **Phase 1, now: forward-auth for human surfaces only.** Put Authentik in front of Studio and `/v1/ops/*` on any non-loopback deployment. Keep `KXM_AUTH_TOKEN` mandatory; the proxy never substitutes for it. This adds SSO without touching `hub.ts`. Fix the plain-string compare in `studio-layout.ts:350` to use `timingSafeStringCompare` while there.
|
|
38
|
+
2. **Phase 2: hub-side JWT verification as an additive gate.** Implement option 2 with a hard rule: if `KXM_OIDC_ISSUER` is set and discovery or JWKS fetch fails, the JWT path returns 401, and the static-token path still works. Never let loopback plus OIDC config produce anonymous admin. Record the verified `sub` on the agent record at registration for provenance.
|
|
39
|
+
3. **Phase 3 (defer): broker-issued signed session and attempt tokens.** Sign `kxm.session-token.v1` and `kxm.attempt-token.v1` payloads and verify in `enforceToolPolicy` before mapping Authentik groups to `ToolPolicy`. Until tokens are signed, group-to-policy mapping is advisory, not enforcement, because the check is client-side and forgeable.
|
|
40
|
+
|
|
41
|
+
Defer any attempt to remove the static token entirely; it is the only credential the auto-start path (`hub-autostart.ts:175`) and the persisted client resolver (`hub-env.ts:203`) know how to pass.
|
|
42
|
+
|
|
43
|
+
## Agent auth specifically
|
|
44
|
+
|
|
45
|
+
Running agents today authenticate non-interactively with whatever string lands in `HubClient.authToken`, resolved by `resolveClientHubAuthToken` (`hub-env.ts:203`): `KXM_AUTH_TOKEN` env, else the persisted project token, else the persisted admin token. The MCP server (`mcp-server.ts:84`) and the Pi extension (`extension.ts:709`) both use this. Pi worker children inherit `process.env` unchanged (`pi-producer.ts:504`), so they get the same token as the supervisor. Tool policy for workers comes from `KXM_ATTEMPT_TOKEN`, which is minted only in tests today (`test/core/commands-policy.test.ts:60`); no runtime path in `plugins/kxm/src` calls `mintAttemptToken`, so engine issuance is planned but not wired.
|
|
46
|
+
|
|
47
|
+
With Authentik, agents should use the OAuth2 client-credentials grant (one Authentik application per agent class, or per role such as `writer` and `verifier`), obtain an access token at spawn, and pass it as `KXM_AUTH_TOKEN` to the child. This needs option 2 in the hub so the token verifies, and a refresh hook in `HubClient` since `headers()` reads a fixed string (`client.ts:539`) and access tokens expire. Device-code flow is the fallback for Claude Code sessions that start from a human terminal. Whether Authentik's client-credentials tokens carry `groups` claims by default is unknown from this repo; it must be confirmed against the Authentik provider config before mapping roles from claims.
|