@kontextmind/kxm 0.7.95 → 0.7.97
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/.kxm/README.md +39 -9
- package/CHANGELOG.md +23 -1
- package/README.md +147 -257
- package/SECURITY.md +21 -12
- package/docs/README.md +133 -54
- package/docs/adr/ADR-0002-browser-automation-steel-doks.md +24 -18
- package/docs/adr/ADR-0003-sqlite-only-store.md +100 -0
- package/docs/adr/ADR-0004-edge-identity-authentik.md +99 -0
- package/docs/adr/README.md +33 -0
- package/docs/concepts/architecture.md +262 -0
- package/docs/concepts/data-and-storage.md +194 -0
- package/docs/concepts/trust-model.md +153 -0
- package/docs/contracts/README.md +22 -14
- package/docs/contracts/effects-and-recovery.md +3 -0
- package/docs/contracts/migration.md +2 -2
- package/docs/contracts/routing.md +6 -5
- package/docs/contributing/assignment-runner.md +388 -0
- package/docs/contributing/ci-and-release.md +231 -0
- package/docs/contributing/development.md +362 -0
- package/docs/contributing/harness-routing-internals.md +192 -0
- package/docs/{packages.md → contributing/packages.md} +13 -15
- package/docs/{skills → contributing}/repo-work-delivery.md +20 -21
- package/docs/contributing/test-matrix.md +208 -0
- package/docs/{tui-components.md → contributing/tui-components.md} +30 -22
- package/docs/contributing/writing-docs.md +340 -0
- package/docs/glossary.md +471 -0
- package/docs/guides/agent-skills.md +137 -0
- package/docs/guides/browser-automation.md +160 -0
- package/docs/guides/context-and-memory.md +352 -0
- package/docs/guides/continuous-improvement.md +228 -0
- package/docs/guides/governed-skills.md +173 -0
- package/docs/guides/nous-providers.md +186 -0
- package/docs/guides/peer-messaging.md +304 -0
- package/docs/guides/pi-workers.md +219 -0
- package/docs/guides/provenance-gates.md +313 -0
- package/docs/guides/webhook-workflows.md +399 -0
- package/docs/kb/how-credentials-retrieved-safely.md +38 -12
- package/docs/kb/how-to-capture-and-annotate-section.md +15 -13
- package/docs/kb/how-to-connect-playwright-to-steel.md +16 -11
- package/docs/kb/how-to-recover-expired-session-or-orphan.md +26 -16
- package/docs/kb/how-to-resume-after-mfa.md +19 -11
- package/docs/kb/how-to-take-over-session.md +17 -13
- package/docs/kb/why-authentication-disappeared.md +22 -14
- package/docs/kb/why-automation-opened-different-browser.md +23 -14
- package/docs/kb/why-session-viewer-cannot-control.md +13 -12
- package/docs/operations/backup-and-restore.md +248 -0
- package/docs/operations/deploy.md +307 -0
- package/docs/operations/monitoring.md +209 -0
- package/docs/operations/runtime-sync.md +192 -0
- package/docs/operations/troubleshooting.md +266 -0
- package/docs/operations/upgrade.md +124 -0
- package/docs/prompts/browser-annotate-feedback.md +7 -7
- package/docs/prompts/browser-diagnose-recover.md +11 -10
- package/docs/prompts/browser-explore.md +7 -7
- package/docs/prompts/browser-repro-fix.md +7 -7
- package/docs/prompts/browser-start.md +12 -11
- package/docs/prompts/browser-takeover.md +8 -8
- package/docs/{cli-reference.md → reference/cli-reference.md} +88 -46
- package/docs/{config-reference.md → reference/config-reference.md} +159 -148
- package/docs/reference/configuration.md +299 -0
- package/docs/reference/harness-routing.md +508 -0
- package/docs/reference/http-api.md +203 -0
- package/docs/reference/tools.md +370 -0
- package/docs/{workflow-guide.md → reference/workflow-catalog.md} +92 -153
- package/docs/reference/workflow-definitions.md +286 -0
- package/docs/start/first-workflow.md +287 -0
- package/docs/start/install.md +146 -0
- package/docs/start/quickstart-claude-code.md +405 -0
- package/docs/start/quickstart-pi.md +213 -0
- package/docs/templates/README.md +78 -73
- package/docs/templates/adr.md +13 -13
- package/docs/templates/architecture.md +55 -71
- package/docs/templates/bug-fix.md +13 -16
- package/docs/templates/feature.md +14 -19
- package/docs/templates/handoff.md +44 -46
- package/docs/templates/postmortem.md +30 -43
- package/docs/templates/research.md +15 -20
- package/docs/templates/review.md +49 -50
- package/docs/templates/runbook.md +38 -30
- package/docs/templates/test-plan.md +16 -23
- package/docs/templates/test-report.md +14 -17
- package/examples/README.md +9 -5
- package/examples/provenance-workflow.json +1 -1
- package/examples/webhook-workflows/jira-development.json +59 -0
- package/examples/webhook-workflows/jira-issue-updated.json +12 -0
- package/examples/workflow-signal.ts +4 -5
- package/package.json +1 -1
- package/packages/core/tui/README.md +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/README.md +31 -32
- package/plugins/kxm/dist/claude-hook.js +11 -1
- package/plugins/kxm/dist/cli.js +164 -79
- package/plugins/kxm/dist/client.js +3 -1
- package/plugins/kxm/dist/core.js +11 -1
- package/plugins/kxm/dist/extension.js +45 -13
- package/plugins/kxm/dist/mcp-server.js +20 -4
- package/plugins/kxm/dist/runtime-supervisor.js +1 -3
- package/plugins/kxm/dist/runtime.js +18 -4
- package/plugins/kxm/dist/server.js +115 -20
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm/references/protocol.md +3 -1
- package/plugins/kxm/skills/kxm-browser-auth/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-browser-diagnostics/SKILL.md +5 -5
- package/plugins/kxm/skills/kxm-browser-explore/SKILL.md +2 -2
- package/plugins/kxm/skills/kxm-browser-session/SKILL.md +10 -13
- package/plugins/kxm/skills/kxm-browser-takeover/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-browser-verify/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-context-memory/SKILL.md +13 -4
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +3 -1
- package/plugins/kxm/skills/kxm-mind-setup/SKILL.md +2 -1
- package/plugins/kxm/skills/kxm-project-setup/SKILL.md +31 -54
- package/plugins/kxm/skills/kxm-projects/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-protocol/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-routing-improve/SKILL.md +15 -7
- package/plugins/kxm/skills/kxm-runs/SKILL.md +11 -5
- package/plugins/kxm/skills/kxm-session/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-tasks/SKILL.md +9 -7
- package/plugins/kxm/skills/kxm-workflow/SKILL.md +10 -2
- package/plugins/kxm/src/cli/system.ts +1 -1
- package/plugins/kxm/src/cli/workflows.ts +12 -7
- package/plugins/kxm/src/cli.ts +22 -8
- package/plugins/kxm/src/client.ts +4 -0
- package/plugins/kxm/src/commands.ts +23 -1
- package/plugins/kxm/src/extension.ts +20 -14
- package/plugins/kxm/src/github-watch.ts +8 -5
- package/plugins/kxm/src/hub-env.ts +19 -1
- package/plugins/kxm/src/hub.ts +105 -21
- package/plugins/kxm/src/improve-sources.ts +2 -7
- package/plugins/kxm/src/init-guide-setup.ts +1 -1
- package/plugins/kxm/src/mcp-server.ts +9 -2
- package/plugins/kxm/src/modes.ts +1 -1
- package/plugins/kxm/src/runtime-store.ts +23 -0
- package/plugins/kxm/src/workflow.ts +70 -1
- package/schemas/README.md +1 -1
- package/scripts/smoke-multi-pi.mjs +5 -1
- package/docs/agent-communication-envelopes-and-gates.md +0 -553
- package/docs/agent-skills.md +0 -198
- package/docs/architecture.md +0 -245
- package/docs/assignment-runner.md +0 -264
- package/docs/browser-automation.md +0 -139
- package/docs/configuration.md +0 -437
- package/docs/continuous-improvement.md +0 -226
- package/docs/getting-started.md +0 -277
- package/docs/harness-routing.md +0 -616
- package/docs/kb/qa-authentik-authentication.md +0 -97
- package/docs/kb/qa-extension-install-and-hub-bootstrap.md +0 -85
- package/docs/kb/qa-hub-on-a-public-host.md +0 -48
- package/docs/kb/qa-sqlite-vs-duckdb.md +0 -35
- package/docs/kb/qa-what-the-hub-stores.md +0 -64
- package/docs/kxm-handbook.md +0 -1181
- package/docs/operations.md +0 -510
- package/docs/operator-pi-packages.md +0 -67
- package/docs/provenance-gates.md +0 -295
- package/docs/skills.md +0 -47
- package/docs/test-matrix.md +0 -132
- package/docs/troubleshooting.md +0 -322
- package/docs/webhook-workflows.md +0 -240
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# CI and release
|
|
2
|
+
|
|
3
|
+
Every pull request and every push to `main` that changes code runs a
|
|
4
|
+
three-minute merge-safety gate, the complete suite with coverage floors runs
|
|
5
|
+
nightly, every merge to `main` cuts a patch release, and every release is
|
|
6
|
+
verified before it reaches npm. This
|
|
7
|
+
page explains which checks run where, how a merge becomes a published version,
|
|
8
|
+
and which smoke tests stay manual. It is for contributors and maintainers.
|
|
9
|
+
|
|
10
|
+
## The pipeline at a glance
|
|
11
|
+
|
|
12
|
+
A merged pull request flows through CI, an automatic tag, a verified GitHub
|
|
13
|
+
release and an npm publish; the nightly job adds the slower suites.
|
|
14
|
+
|
|
15
|
+
```mermaid
|
|
16
|
+
flowchart LR
|
|
17
|
+
PR[Pull request] -->|"validate:pr, docs lint, plugin validation"| MERGE{Merged?}
|
|
18
|
+
MERGE -->|yes| MAIN[main]
|
|
19
|
+
MAIN -->|"same three-minute validate:pr"| PUSH[Push CI]
|
|
20
|
+
MAIN -->|"Auto-Release: next patch tag"| TAG[Tag vX.Y.Z]
|
|
21
|
+
TAG -->|dispatch| REL[Release workflow]
|
|
22
|
+
REL -->|"verify, stamp version, pack"| GH[GitHub release<br/>kxm-X.Y.Z.tgz]
|
|
23
|
+
GH -->|"sha256 verified"| NPM[npm publish]
|
|
24
|
+
MAIN -->|"daily 04:00 UTC"| NIGHT[Nightly<br/>complete suite]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
All workflows live in `.github/workflows/`. Every job runs on the organization's
|
|
28
|
+
ARC runner scale set, and `test/core/ci-contract.test.ts` pins the
|
|
29
|
+
runner selector, job names, coverage floors and release triggers. Change a
|
|
30
|
+
workflow and that test together.
|
|
31
|
+
|
|
32
|
+
## What runs where
|
|
33
|
+
|
|
34
|
+
| Trigger | Workflow (job) | What it runs |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| Before you push | Local | `npm run verify` |
|
|
37
|
+
| Pull request and push to `main` | `ci.yml` (Validate, two Node legs) | `validate:pr`, the three-minute gate; skipped for documentation-only changes |
|
|
38
|
+
| Pull request and push | `ci.yml` (Docs lint) | `lint:docs` and `check:versions`, always |
|
|
39
|
+
| Pull request and push | `ci.yml` (Plugin validation) | `claude plugin validate --strict` on the marketplace and the plugin; skipped for documentation-only changes |
|
|
40
|
+
| Daily at 04:00 UTC, or manual | `nightly.yml` | `test:coverage:complete`, `check`, `check:generated`, `npm pack --dry-run` |
|
|
41
|
+
| Merged pull request | `auto-release.yml` | Tags the merge commit and dispatches `release.yml` |
|
|
42
|
+
| Tag push or dispatch | `release.yml` | Verifies, packs and publishes (see [Release flow](#release-flow)) |
|
|
43
|
+
| Manual only | `smoke.yml` | Real Pi smoke, currently disabled (see [Smoke tests](#smoke-tests)) |
|
|
44
|
+
|
|
45
|
+
The npm scripts behind those rows:
|
|
46
|
+
|
|
47
|
+
| Script | Composition |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `verify` | `npm test` (core and package unit tests), `check`, `check:generated` |
|
|
50
|
+
| `validate:pr` | `build`, `typecheck`, a compact contract and smoke set of nine `test/core` files, `check:versions`, and the generated-`dist` check |
|
|
51
|
+
| `validate:ci` | `test:coverage` (core and package tests, 91/80/92 floors), `check`, `npm pack --dry-run`; not run by CI today, available locally |
|
|
52
|
+
| `test:coverage:complete` | Core, simulation and package tests with 93/80/93 floors |
|
|
53
|
+
| `check` | `typecheck`, `lint:docs`, `check:versions` |
|
|
54
|
+
|
|
55
|
+
Three differences matter when a check fails on one side only:
|
|
56
|
+
|
|
57
|
+
- CI runs a compact contract and smoke set, not the core suite. The full core
|
|
58
|
+
suite and the package unit tests under `packages/core/*/tests` run in your
|
|
59
|
+
local `npm run verify`; run it before every push.
|
|
60
|
+
- Coverage and `test/simulations` run only in the nightly complete suite, never
|
|
61
|
+
on a pull request or a push to `main`.
|
|
62
|
+
- A regression the compact set misses can reach `main` and show up in the
|
|
63
|
+
nightly run, so treat a nightly failure as a release blocker.
|
|
64
|
+
|
|
65
|
+
### Validate matrix and required checks
|
|
66
|
+
|
|
67
|
+
The Validate job runs on Node 22.19.0 and Node 24, on Linux, with a
|
|
68
|
+
three-minute job timeout. The branch ruleset
|
|
69
|
+
requires the job names `Validate (linux, Node 22.19.0)` and
|
|
70
|
+
`Validate (linux, Node 24)`, so renaming the job or the matrix means updating
|
|
71
|
+
the ruleset in the same change. A newer push cancels an older pull request run;
|
|
72
|
+
runs on `main` are never cancelled.
|
|
73
|
+
|
|
74
|
+
### CI jobs stay queued while a runner is online
|
|
75
|
+
|
|
76
|
+
Every Linux workflow targets the ARC runner scale set `kontextmind-doks`. That
|
|
77
|
+
name is the scale set, not a custom label on a repository runner. The scale set
|
|
78
|
+
belongs to the selected-repository runner group `KontextMind DOKS ARC`, which
|
|
79
|
+
must allow this public repository. The legacy repository runner `km-gh-rn01`
|
|
80
|
+
must not carry the `kontextmind-doks` label; adding it bypasses ARC and
|
|
81
|
+
serializes the build queue.
|
|
82
|
+
|
|
83
|
+
Check GitHub routing first:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
gh api repos/kontextmind/kxm/actions/runners \
|
|
87
|
+
--jq '.runners[] | {name, status, busy, labels: [.labels[].name]}'
|
|
88
|
+
gh api orgs/kontextmind/actions/runner-groups \
|
|
89
|
+
--jq '.runner_groups[] | select(.name == "KontextMind DOKS ARC") |
|
|
90
|
+
{name, visibility, allows_public_repositories}'
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Then check ARC in the cluster:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
kubectl -n arc-runners get autoscalingrunnerset kontextmind-doks
|
|
97
|
+
kubectl -n arc-runners get ephemeralrunners,pods
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The capacity policy keeps one warm runner, bursts to four, and requests three
|
|
101
|
+
CPUs per runner so the node-pool autoscaler adds capacity instead of packing
|
|
102
|
+
CPU-bound jobs onto busy nodes. If jobs stay queued while the listener is
|
|
103
|
+
assigned zero jobs, check the runner group's selected repository and public
|
|
104
|
+
repository access. If ARC has pending pods, check node capacity and the cluster
|
|
105
|
+
autoscaler. Do not relabel `km-gh-rn01` or push an empty commit as a routing
|
|
106
|
+
workaround.
|
|
107
|
+
|
|
108
|
+
> [!NOTE]
|
|
109
|
+
> Windows legs are paused, not removed. Windows stays a supported target, and
|
|
110
|
+
> Windows-specific fixtures (for example the `pi.cmd` worker launch in
|
|
111
|
+
> `test/core/worker.test.ts`) run when you test on Windows locally.
|
|
112
|
+
|
|
113
|
+
### The docs-only classifier
|
|
114
|
+
|
|
115
|
+
The first job, Classify changes, lists the changed paths and sets `code=false`
|
|
116
|
+
when every path matches `*.md`, `docs/*`, `.kxm/assets/*`, `LICENSE`, the issue
|
|
117
|
+
and PR templates, or `dependabot.yml`. Validate and Plugin validation read it:
|
|
118
|
+
for a documentation-only change they report success without checking out the
|
|
119
|
+
code, so the required job names still pass. Docs lint always runs.
|
|
120
|
+
`ci-contract.test.ts` pins this behavior.
|
|
121
|
+
|
|
122
|
+
> [!WARNING]
|
|
123
|
+
> Several tests and code paths read documentation files by path. A pull request
|
|
124
|
+
> that only moves or renames a pinned doc is classified documentation-only, so
|
|
125
|
+
> CI does not run the tests that would catch the broken path; the next code
|
|
126
|
+
> change fails instead. For any docs move, update the pinned readers in the same
|
|
127
|
+
> pull request (see [Pinned paths](writing-docs.md#pinned-paths)) and run
|
|
128
|
+
> `npm run verify` locally before you push.
|
|
129
|
+
|
|
130
|
+
## Release flow
|
|
131
|
+
|
|
132
|
+
KXM releases a patch version for every merged pull request. No one bumps
|
|
133
|
+
versions by hand.
|
|
134
|
+
|
|
135
|
+
1. **Auto-Release** (`auto-release.yml`) runs when a pull request to `main` is
|
|
136
|
+
merged. It finds the newest `vX.Y.Z` tag, adds one to the patch number, tags
|
|
137
|
+
the merge commit, and dispatches the Release workflow for that tag.
|
|
138
|
+
2. **Release** (`release.yml`) checks out the tag, and takes its release helper
|
|
139
|
+
scripts from `main`. It runs `npm run check:generated` against the tagged
|
|
140
|
+
tree, stamps the tag's version into every version surface, runs
|
|
141
|
+
`npm run validate:ci`, and packs `kxm-<version>.tgz`. The step summary records
|
|
142
|
+
the tarball's sha256.
|
|
143
|
+
3. `scripts/kxm-release-github.mjs` creates a draft GitHub release, uploads the
|
|
144
|
+
tarball, and checks the digest GitHub reports against the local one. The
|
|
145
|
+
workflow then publishes the draft.
|
|
146
|
+
4. **Publish npm** runs in the protected `npm-publish` environment. It skips a
|
|
147
|
+
version already on npm. Otherwise `scripts/kxm-publish-npm.mjs` confirms the
|
|
148
|
+
GitHub release is published, downloads the asset, verifies its sha256
|
|
149
|
+
against the release digest, and runs `npm publish` on that exact file.
|
|
150
|
+
|
|
151
|
+
Every step is idempotent. Rerunning the Release workflow for a tag that is
|
|
152
|
+
already published or already on npm reports it and changes nothing.
|
|
153
|
+
|
|
154
|
+
### Skip a release
|
|
155
|
+
|
|
156
|
+
Auto-Release skips a merge when the pull request has the `no-release` label, or
|
|
157
|
+
when its head branch starts with `chore/release-`.
|
|
158
|
+
|
|
159
|
+
### Versions
|
|
160
|
+
|
|
161
|
+
The version in the repository's `package.json` stays at its base value. The
|
|
162
|
+
release job stamps the tag's version into the package, the lockfile, the plugin
|
|
163
|
+
package and manifest, the marketplace entry, the MCP server constant, and every
|
|
164
|
+
workspace package, in the runner's workspace only. The stamp is never committed
|
|
165
|
+
back.
|
|
166
|
+
|
|
167
|
+
- Do not edit version fields in a pull request. `npm run check:versions` fails
|
|
168
|
+
when any surface differs from the root `package.json`.
|
|
169
|
+
- Auto-Release only increments the patch number. For a minor or major release,
|
|
170
|
+
push a `vX.Y.0` tag yourself; `release.yml` also runs on tag pushes, and
|
|
171
|
+
later merges continue from that tag.
|
|
172
|
+
- `scripts/kxm-bump-version.mjs` and `scripts/check-versions.mjs` read the same
|
|
173
|
+
package list from `scripts/package-surfaces.mjs`, so the gate and the writer
|
|
174
|
+
cannot disagree.
|
|
175
|
+
|
|
176
|
+
### Changelog
|
|
177
|
+
|
|
178
|
+
Add user-visible changes to `CHANGELOG.md` under `## Unreleased`, in the same
|
|
179
|
+
pull request. Keep an entry to a few lines and link the doc page that explains
|
|
180
|
+
the behavior. Add an `### Upgrade note` when an operator must act.
|
|
181
|
+
|
|
182
|
+
No release step moves those entries into a dated section. Auto-Release tags a
|
|
183
|
+
patch for each merged pull request, but nothing cuts the changelog, so
|
|
184
|
+
everything released since its newest dated section is still listed under
|
|
185
|
+
`## Unreleased`.
|
|
186
|
+
|
|
187
|
+
## Smoke tests
|
|
188
|
+
|
|
189
|
+
Smoke tests prove what unit tests cannot: that the packed artifact installs,
|
|
190
|
+
and that real harnesses complete a turn.
|
|
191
|
+
|
|
192
|
+
| Smoke | How to run | What it proves |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| Packed install | Part of the core suite: `test/core/package-install.test.ts` | The packed CLI and hub run from a clean local and global install |
|
|
195
|
+
| Real Pi smoke | `KXM_SMOKE=1 KXM_SMOKE_MODELS=<model-a>,<model-b> node scripts/smoke-multi-pi.mjs` | Two supervised Pi workers discover each other, exchange requests and replies, and recover across a restart |
|
|
196
|
+
| Container install | `just docker-install-smoke` | The tarball installs into a fresh container with a fresh Pi, and two providers complete a live turn |
|
|
197
|
+
|
|
198
|
+
The real Pi smoke calls paid models, so it never runs by default. Its workflow,
|
|
199
|
+
`smoke.yml`, is manual and stays skipped until the repository variable
|
|
200
|
+
`KXM_SMOKE_RUNNER` names a runner with Pi credentials. Both smoke models run as
|
|
201
|
+
long-lived Pi workers, so each must pass the Pi native-vendor brake: pick two
|
|
202
|
+
non-native routes such as
|
|
203
|
+
`openrouter/qwen/qwen3-coder-plus,openrouter/z-ai/glm-5.3-flash`, never `xai/…`
|
|
204
|
+
or `anthropic/…`. The container smoke needs
|
|
205
|
+
Docker, a `pass-cli` session and a local Pi model store. It keeps secrets in a
|
|
206
|
+
mode-600 file inside a temporary directory; set `KXM_SMOKE_VAULT` to read keys
|
|
207
|
+
from your own vault.
|
|
208
|
+
|
|
209
|
+
### Manual checks before announcing a release
|
|
210
|
+
|
|
211
|
+
Automation cannot prove that a harness UI renders correctly. Before you
|
|
212
|
+
announce a release:
|
|
213
|
+
|
|
214
|
+
1. Install the published version:
|
|
215
|
+
`npm install --global --omit=peer @kontextmind/kxm@<version>`.
|
|
216
|
+
2. Connect two current Pi sessions, run `/kxm hub`, and complete one inbound
|
|
217
|
+
round trip.
|
|
218
|
+
3. Install the marketplace plugin in a clean Claude Code profile and confirm
|
|
219
|
+
that `kxm_list` answers.
|
|
220
|
+
4. Check pushed channel delivery only when the target Claude Code version
|
|
221
|
+
supports channels.
|
|
222
|
+
|
|
223
|
+
If a behavior can only be checked by hand, add it to this list rather than
|
|
224
|
+
implying automated coverage.
|
|
225
|
+
|
|
226
|
+
## Related
|
|
227
|
+
|
|
228
|
+
- [Develop KXM](development.md): the local gate and generated artifacts
|
|
229
|
+
- [Test matrix](test-matrix.md): which test proves which behavior
|
|
230
|
+
- [Write KXM documentation](writing-docs.md): doc gates and pinned paths
|
|
231
|
+
- [Upgrade KXM](../operations/upgrade.md): the operator side of a new version
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
# Develop KXM
|
|
2
|
+
|
|
3
|
+
Set up a source checkout, learn where each part of KXM lives, and run the same
|
|
4
|
+
gate CI runs before you push. This page is for contributors who change the CLI,
|
|
5
|
+
the [hub](../glossary.md#hub), the [Runtime](../glossary.md#runtime), the Pi
|
|
6
|
+
extension, the Claude Code plugin, or the bundled skills.
|
|
7
|
+
|
|
8
|
+
## Before you begin
|
|
9
|
+
|
|
10
|
+
- Node.js 22.19 or newer on the 22 line, or Node.js 24 or newer. The
|
|
11
|
+
`engines` field in `package.json` is the authority.
|
|
12
|
+
- npm and Git.
|
|
13
|
+
- Optional tools, needed only for the matching task:
|
|
14
|
+
- [Pi](https://pi.dev) to load the extension from source.
|
|
15
|
+
- The Claude Code CLI to validate the plugin manifests locally.
|
|
16
|
+
- [`just`](https://github.com/casey/just) for the
|
|
17
|
+
[assignment runner](assignment-runner.md).
|
|
18
|
+
- Docker for the clean-container install smoke.
|
|
19
|
+
|
|
20
|
+
## Set up a checkout
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/kontextmind/kxm.git
|
|
24
|
+
cd kxm
|
|
25
|
+
npm ci
|
|
26
|
+
node scripts/kxm.mjs --help
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`node scripts/kxm.mjs` is the `kxm` binary from `package.json` `bin`. It runs the
|
|
30
|
+
committed bundle `plugins/kxm/dist/cli.js`, not the TypeScript source. A source
|
|
31
|
+
change is invisible until you rebuild:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm run build
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Use `node scripts/kxm.mjs` wherever the user docs show `kxm`.
|
|
38
|
+
|
|
39
|
+
### Keep experiments away from real state
|
|
40
|
+
|
|
41
|
+
A source build uses the same default hub (`http://127.0.0.1:7331`), user state
|
|
42
|
+
root, configuration and telemetry directories as an installed `kxm`. Point every
|
|
43
|
+
experiment at throwaway directories and a hub you start yourself on another
|
|
44
|
+
port:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Run in a scratch Git repository, not in your KXM checkout.
|
|
48
|
+
export KXM_STATE_HOME="$(mktemp -d)"
|
|
49
|
+
export KXM_USER_CONFIG_DIR="$(mktemp -d)"
|
|
50
|
+
export KXM_USER_TELEMETRY_DIR="$(mktemp -d)"
|
|
51
|
+
export KXM_PORT=47331
|
|
52
|
+
export KXM_SERVER_URL="http://127.0.0.1:$KXM_PORT"
|
|
53
|
+
node /path/to/kxm/scripts/kxm.mjs hub start
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
In a second terminal with the same variables:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
node /path/to/kxm/scripts/kxm.mjs hub view
|
|
60
|
+
node /path/to/kxm/scripts/kxm.mjs hub stop
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Expected output of `hub view`:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
hub health=true ready=true · loopback hub
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`KXM_STATE_HOME` must be an absolute path. The hub writes its database and logs
|
|
70
|
+
under `.kxm/` in the directory where you start it.
|
|
71
|
+
|
|
72
|
+
### Load the Pi extension from source
|
|
73
|
+
|
|
74
|
+
Pi loads the TypeScript extension directly, so it needs no build step:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pi --no-extensions -e ./plugins/kxm/src/extension.ts
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`--no-extensions` turns off Pi's package discovery, so only the listed extensions
|
|
81
|
+
load. Add another `-e` for each provider extension your models need.
|
|
82
|
+
|
|
83
|
+
### Validate the Claude Code plugin
|
|
84
|
+
|
|
85
|
+
With the Claude Code CLI installed, run the same strict manifest validation as
|
|
86
|
+
CI. Validation reads the manifests only; the plugin itself runs the committed
|
|
87
|
+
`plugins/kxm/dist/mcp-server.js`, so rebuild before you try it in Claude Code.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm run validate:claude
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Repository layout
|
|
94
|
+
|
|
95
|
+
The tree below lists what is tracked in Git. Directories marked "not shipped" are
|
|
96
|
+
excluded from the npm package.
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
.
|
|
100
|
+
├── plugins/kxm/ The product: CLI, hub, Runtime, Pi extension, MCP server
|
|
101
|
+
│ ├── src/ TypeScript source (cli/, context/, providers/ inside)
|
|
102
|
+
│ ├── dist/ Generated, committed bundles (see Generated artifacts)
|
|
103
|
+
│ ├── skills/ Bundled Agent Skills, one <name>/SKILL.md each
|
|
104
|
+
│ ├── skill-suite.json Skill manifest: names, paths, owned commands
|
|
105
|
+
│ ├── .claude-plugin/ Claude Code plugin manifest (plugin.json)
|
|
106
|
+
│ └── .mcp.json MCP server launch for the plugin
|
|
107
|
+
├── .claude-plugin/ Claude marketplace catalog (marketplace.json)
|
|
108
|
+
├── packages/core/tui/ @kontextmind/tui workspace package
|
|
109
|
+
├── scripts/ kxm.mjs, hub and worker wrappers, build, release, runners
|
|
110
|
+
├── schemas/ JSON Schemas for YAML resources, events and records
|
|
111
|
+
├── docs/ User, operator and contributor documentation
|
|
112
|
+
├── examples/ Runnable transport examples and project fixtures
|
|
113
|
+
├── test/ core/, simulations/, fixtures/, helpers/ (not shipped)
|
|
114
|
+
├── .kxm/ This repository's own KXM project definition
|
|
115
|
+
├── .agents/skills/ Generated mirror of the bundled skills (not shipped)
|
|
116
|
+
├── .github/ CI, release, issue and PR templates (not shipped)
|
|
117
|
+
├── .claude/ Developer harness notes and commands (not shipped)
|
|
118
|
+
├── plans/ Internal planning and tracking (not shipped)
|
|
119
|
+
├── justfile Developer recipes for the assignment runner
|
|
120
|
+
└── AGENTS.md, CLAUDE.md, GEMINI.md Agent instructions with generated blocks
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The workspace layout for `packages/` is described in
|
|
124
|
+
[Packages and workspaces](packages.md). The `.kxm/` layout is described in
|
|
125
|
+
[`.kxm/README.md`](../../.kxm/README.md).
|
|
126
|
+
|
|
127
|
+
## Packaging standards
|
|
128
|
+
|
|
129
|
+
KXM ships one product through four native package formats. Each format reads
|
|
130
|
+
its own manifest, and `npm run check:versions` keeps every version field equal.
|
|
131
|
+
|
|
132
|
+
### npm package
|
|
133
|
+
|
|
134
|
+
`@kontextmind/kxm` is published publicly.
|
|
135
|
+
|
|
136
|
+
| Field | What it declares |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `bin` | `kxm` → `scripts/kxm.mjs` |
|
|
139
|
+
| `exports` | `./core`, `./runtime`, `./client`, `./extension`, `./mcp` from `plugins/kxm/dist`, and `./tui` |
|
|
140
|
+
| `files` | `plugins/kxm/{dist,src,skills}`, `scripts`, `docs`, `examples`, `schemas`, the plugin manifests, and selected `.kxm` files |
|
|
141
|
+
| `engines` | Node `^22.19.0 \|\| >=24.0.0` |
|
|
142
|
+
| `peerDependencies` | Pi and `typebox`, both optional |
|
|
143
|
+
|
|
144
|
+
Everything under `docs/` ships in the tarball, so a link from `docs/` into
|
|
145
|
+
`plans/` is dead for npm readers. `.npmignore` drops logs, state and generated
|
|
146
|
+
assets even inside listed directories. Inspect the result with
|
|
147
|
+
`npm pack --dry-run`.
|
|
148
|
+
|
|
149
|
+
### Claude Code plugin and marketplace
|
|
150
|
+
|
|
151
|
+
| File | Role |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `.claude-plugin/marketplace.json` | Marketplace catalog; its `kxm` entry points at `./plugins/kxm` |
|
|
154
|
+
| `plugins/kxm/.claude-plugin/plugin.json` | Plugin manifest: `userConfig`, the `SessionStart` hook, the channel, and `mcpServers` |
|
|
155
|
+
| `plugins/kxm/.mcp.json` | Launches `dist/mcp-server.js` over stdio and maps `userConfig` to `KXM_*` variables |
|
|
156
|
+
| `plugins/kxm/dist/claude-hook.js` | The bundled, read-only `SessionStart` hook script |
|
|
157
|
+
|
|
158
|
+
A marketplace install clones the repository, so the plugin can use only committed
|
|
159
|
+
files. That is why the bundles in `dist/` are tracked. For what the plugin does,
|
|
160
|
+
see the [plugin README](../../plugins/kxm/README.md).
|
|
161
|
+
|
|
162
|
+
### Pi package
|
|
163
|
+
|
|
164
|
+
The root `package.json` carries the `pi-package` keyword and a `pi` block:
|
|
165
|
+
`pi.extensions` lists `./plugins/kxm/src/extension.ts` and `pi.skills` lists
|
|
166
|
+
`./plugins/kxm/skills`. Pi loads the TypeScript source itself.
|
|
167
|
+
|
|
168
|
+
### Agent Skills
|
|
169
|
+
|
|
170
|
+
Each bundled skill is a directory `plugins/kxm/skills/<name>/` with a `SKILL.md`.
|
|
171
|
+
`plugins/kxm/skill-suite.json` declares every skill and the top-level `kxm`
|
|
172
|
+
commands it owns. `test/core/skill-suite.test.ts` enforces the rules:
|
|
173
|
+
|
|
174
|
+
- The directory name equals the frontmatter `name` and the manifest `name`.
|
|
175
|
+
- The frontmatter parses as strict YAML. Quote any value that contains a colon followed by a space.
|
|
176
|
+
- The `description` is at most 1,024 characters.
|
|
177
|
+
- Every top-level `kxm` command is owned by exactly one skill.
|
|
178
|
+
- `.agents/skills/` matches the authored skills byte for byte.
|
|
179
|
+
|
|
180
|
+
For what each skill covers, see [Agent skills](../guides/agent-skills.md).
|
|
181
|
+
|
|
182
|
+
## The development loop
|
|
183
|
+
|
|
184
|
+
1. Branch from `main`. Keep one concern per branch and one clear concern per
|
|
185
|
+
commit.
|
|
186
|
+
2. Change the source and the test that proves the change. Update
|
|
187
|
+
[the test matrix](test-matrix.md) when you add a behavior.
|
|
188
|
+
3. Rebuild with `npm run build` when you touched anything that is bundled.
|
|
189
|
+
4. Run the focused test file while you iterate (see
|
|
190
|
+
[Test conventions](#test-conventions)).
|
|
191
|
+
5. Update the user docs and `CHANGELOG.md` (under `## Unreleased`) for any
|
|
192
|
+
user-visible change.
|
|
193
|
+
6. Stage the source change together with the regenerated files. The commit gate
|
|
194
|
+
compares generated files with the staged copy.
|
|
195
|
+
7. Run the commit gate, `npm run verify`, fix what it reports, then commit.
|
|
196
|
+
8. Push and open a pull request. The template asks for the slice issue and the
|
|
197
|
+
`npm run verify` result.
|
|
198
|
+
|
|
199
|
+
Maintainers who delegate work to coding agents use the
|
|
200
|
+
[assignment runner](assignment-runner.md) for steps 2 to 7.
|
|
201
|
+
|
|
202
|
+
## Generated artifacts
|
|
203
|
+
|
|
204
|
+
`npm run build` regenerates the files below. They are committed because the
|
|
205
|
+
Claude marketplace installs from Git and npm consumers install without dev
|
|
206
|
+
dependencies. Neither can run a build or strip TypeScript at install time.
|
|
207
|
+
|
|
208
|
+
| Artifact | Produced by | Consumers |
|
|
209
|
+
|---|---|---|
|
|
210
|
+
| `plugins/kxm/dist/cli.js`, `server.js`, `runtime-supervisor.js`, `claude-hook.js` | `scripts/build-runtime.mjs` | `kxm`, the hub, the Runtime supervisor, the plugin hook |
|
|
211
|
+
| `plugins/kxm/dist/core.js`, `runtime.js`, `client.js`, `extension.js` | `scripts/build-runtime.mjs` | The package `exports` |
|
|
212
|
+
| `plugins/kxm/dist/mcp-server.js` | `npm run build:mcp` | The Claude plugin and `@kontextmind/kxm/mcp` |
|
|
213
|
+
| `packages/core/tui/dist/index.js` | `npm run build:packages` | `@kontextmind/kxm/tui` |
|
|
214
|
+
| `.agents/skills/<name>/…` | `scripts/emit-codex-artifacts.mjs` | Harnesses that read `.agents/skills` |
|
|
215
|
+
| `AGENTS.md` block between the `kxm:codex:commands` markers | `scripts/emit-codex-artifacts.mjs` | Codex and other `AGENTS.md` readers |
|
|
216
|
+
| `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` blocks between the `kxm:memory` markers | `syncHarnessMemory` (same as `kxm memory sync`) | Every harness, from `.kxm/memory/*.md` |
|
|
217
|
+
|
|
218
|
+
Never edit a generated file by hand. Edit its source and rebuild.
|
|
219
|
+
|
|
220
|
+
`npm run check:generated` rebuilds, then fails if any artifact is missing, not
|
|
221
|
+
tracked, or different from the staged copy. Stage the rebuilt files
|
|
222
|
+
(`git add plugins/kxm/dist packages/core/tui/dist .agents AGENTS.md CLAUDE.md GEMINI.md`)
|
|
223
|
+
before you run it.
|
|
224
|
+
|
|
225
|
+
## The commit gate
|
|
226
|
+
|
|
227
|
+
Run `npm run verify` before every commit you push. It is the same gate for
|
|
228
|
+
people and for agents.
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm run verify
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
It runs three scripts in order:
|
|
235
|
+
|
|
236
|
+
| Step | Script | What it checks |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| 1 | `npm test` | Build, then `test/core/*.test.ts` and `packages/core/*/tests/unit/*.test.ts` |
|
|
239
|
+
| 2 | `npm run check` | `tsc --noEmit`, `markdownlint-cli2`, and version surfaces |
|
|
240
|
+
| 3 | `npm run check:generated` | Generated artifacts are tracked and match the staged copy |
|
|
241
|
+
|
|
242
|
+
Other scripts you will use:
|
|
243
|
+
|
|
244
|
+
| Script | Use it for |
|
|
245
|
+
|---|---|
|
|
246
|
+
| `npm run test:core` | The core suite only (CI runs a smaller contract set; see [CI and release](ci-and-release.md)) |
|
|
247
|
+
| `npm run test:simulations` | `test/simulations/*.test.ts` |
|
|
248
|
+
| `npm run test:coverage` | Core suite with coverage floors |
|
|
249
|
+
| `npm run test:coverage:complete` | Core plus simulations with the higher nightly floors |
|
|
250
|
+
| `npm run lint:docs` | Markdown lint only |
|
|
251
|
+
| `npm run validate:pr` | The three-minute CI gate; see [CI and release](ci-and-release.md) |
|
|
252
|
+
| `npm run validate:ci` | Coverage suite, `check` and a package dry run (not run by CI today) |
|
|
253
|
+
| `npm run validate:claude` | Strict Claude plugin and marketplace validation |
|
|
254
|
+
|
|
255
|
+
Plugin validation needs the Claude Code CLI, so it is a CI job rather than part
|
|
256
|
+
of `verify`. Do not add a third gate script: `test/core/ci-contract.test.ts`
|
|
257
|
+
refuses one.
|
|
258
|
+
|
|
259
|
+
### Coverage floors
|
|
260
|
+
|
|
261
|
+
| Run | Lines | Branches | Functions |
|
|
262
|
+
|---|---:|---:|---:|
|
|
263
|
+
| `test:coverage:core` (pushes to `main`, releases) | 91% | 80% | 92% |
|
|
264
|
+
| `test:coverage:complete` (nightly) | 93% | 80% | 93% |
|
|
265
|
+
|
|
266
|
+
Coverage measures `plugins/kxm/src/**/*.ts` and `packages/core/*/src/**/*.ts`.
|
|
267
|
+
The floors only move up. A pull request may raise a floor. No pull request may
|
|
268
|
+
lower one: when coverage drops, add tests.
|
|
269
|
+
|
|
270
|
+
Three files are excluded because they run only as spawned bundles, so coverage
|
|
271
|
+
would attribute their lines to `dist`, never to the source. Each is exercised
|
|
272
|
+
as a child process instead:
|
|
273
|
+
|
|
274
|
+
- `plugins/kxm/src/server.ts`, the hub entry;
|
|
275
|
+
- `plugins/kxm/src/mcp-server.ts`, the MCP stdio entry;
|
|
276
|
+
- `plugins/kxm/src/runtime-supervisor.ts`, the Runtime supervisor entry.
|
|
277
|
+
|
|
278
|
+
An exclusion needs a reason other than "hard to test".
|
|
279
|
+
|
|
280
|
+
## Test conventions
|
|
281
|
+
|
|
282
|
+
Tests use the built-in `node:test` runner and run TypeScript through
|
|
283
|
+
`--experimental-strip-types`. There is no Jest or Vitest.
|
|
284
|
+
|
|
285
|
+
### Write one focused test per behavior
|
|
286
|
+
|
|
287
|
+
- Name each test after the behavior it proves, as a sentence. For example,
|
|
288
|
+
`"MCP server never registers with the persisted admin token"`.
|
|
289
|
+
- Assert the observable contract: an exit code, a JSON field, an error code, a
|
|
290
|
+
file on disk. Do not assert log wording unless the wording is the contract.
|
|
291
|
+
- Prove the refusal as well as the success. Fail-closed paths need their own test.
|
|
292
|
+
- Put the test next to its peers in `test/core/<area>.test.ts`, and add a row to
|
|
293
|
+
[the test matrix](test-matrix.md).
|
|
294
|
+
|
|
295
|
+
### Run one file or one test
|
|
296
|
+
|
|
297
|
+
Build once, then run the file directly:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
npm run build
|
|
301
|
+
node --disable-warning=ExperimentalWarning --experimental-strip-types \
|
|
302
|
+
--test test/core/improve.test.ts
|
|
303
|
+
# Narrow to tests whose names match a pattern.
|
|
304
|
+
node --disable-warning=ExperimentalWarning --experimental-strip-types \
|
|
305
|
+
--test --test-name-pattern="same-ask" test/core/improve.test.ts
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Several suites spawn the built bundles, so a stale `dist` fails them. Rebuild
|
|
309
|
+
before you trust a failure.
|
|
310
|
+
|
|
311
|
+
### Isolate all state
|
|
312
|
+
|
|
313
|
+
A test must never read or write the operator's hub, state root, configuration or
|
|
314
|
+
credentials. Use the shared helpers:
|
|
315
|
+
|
|
316
|
+
| Helper | What it isolates |
|
|
317
|
+
|---|---|
|
|
318
|
+
| `isolateSessionEnvironment()` in `test/helpers/session-env.ts` | Points `KXM_STATE_HOME` and `KXM_USER_CONFIG_DIR` at a temp directory and clears session tokens |
|
|
319
|
+
| `createTestMesh(context)` in `test/helpers.ts` | Starts an in-memory hub on port `0` with a test token, closed when the test ends |
|
|
320
|
+
| `committedKxmProject(prefix, …)` in `test/helpers/project.ts` | Creates a committed KXM project and a separate state root in temp directories |
|
|
321
|
+
| `test/helpers/harness-fake.ts` | Fake spawns and auth fixtures for `scripts/harness-run.mjs`, so no real harness or login is needed |
|
|
322
|
+
|
|
323
|
+
Other rules:
|
|
324
|
+
|
|
325
|
+
- Create files only under `mkdtempSync(join(tmpdir(), …))` and remove them when
|
|
326
|
+
the test ends.
|
|
327
|
+
- Bind servers to port `0`. Never assume `7331` is free.
|
|
328
|
+
- Make no network calls outside loopback, and never call a paid model. Real-model
|
|
329
|
+
checks are opt-in smoke tests (see [CI and release](ci-and-release.md#smoke-tests)).
|
|
330
|
+
- Tests must pass on Node 22.19 and Node 24.
|
|
331
|
+
|
|
332
|
+
## Change the protocol
|
|
333
|
+
|
|
334
|
+
Routes, request fields, status transitions, delivery modes, limits and
|
|
335
|
+
authentication are the protocol. A change to any of them needs:
|
|
336
|
+
|
|
337
|
+
- integration tests;
|
|
338
|
+
- an update to `plugins/kxm/skills/kxm/references/protocol.md`;
|
|
339
|
+
- an update to the matching page in `docs/`;
|
|
340
|
+
- a `CHANGELOG.md` entry;
|
|
341
|
+
- a compatibility note when existing clients could break.
|
|
342
|
+
|
|
343
|
+
Prefer additive changes. KXM does not keep backward-compatible aliases for
|
|
344
|
+
retired names: an old name fails closed instead.
|
|
345
|
+
|
|
346
|
+
## Troubleshooting
|
|
347
|
+
|
|
348
|
+
| Symptom | Cause | Fix |
|
|
349
|
+
|---|---|---|
|
|
350
|
+
| `generated artifacts changed after build` | `dist`, a skill mirror or a generated block differs from the index | Run `npm run build`, stage the listed files, rerun |
|
|
351
|
+
| `generated artifacts are not tracked by git` | A new bundle or skill file was never added | `git add` the listed paths |
|
|
352
|
+
| `… version … does not match …` from `check:versions` | A version surface was edited by hand | Revert it; releases stamp versions (see [CI and release](ci-and-release.md#versions)) |
|
|
353
|
+
| A doc test fails after a docs move | A test or code path reads that doc | See [pinned paths](writing-docs.md#pinned-paths) |
|
|
354
|
+
| A CLI change has no effect | `node scripts/kxm.mjs` runs the old bundle | `npm run build` |
|
|
355
|
+
|
|
356
|
+
## Next steps
|
|
357
|
+
|
|
358
|
+
- Understand what CI runs on your pull request: [CI and release](ci-and-release.md)
|
|
359
|
+
- Write or update a docs page: [Write KXM documentation](writing-docs.md)
|
|
360
|
+
- Find the test that proves a behavior: [Test matrix](test-matrix.md)
|
|
361
|
+
- Add a workspace package: [Packages and workspaces](packages.md)
|
|
362
|
+
- Look up a command: [CLI reference](../reference/cli-reference.md)
|