Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,6 @@ jobs:
- name: Build and test
run: bun run release:build

# Platform probing only checks that a transport is theoretically
# supported. It cannot prove that this hosted runner has the required
# kernel capability, helper, and mount privileges. Keep the real mount
# test opt-in for a runner explicitly configured for Mountx; otherwise
# the regular scenario test still covers the probe and skip behavior.
- name: Run Mountx integration on an explicitly configured runner
if: ${{ vars.ZCODE_TEST_MOUNTX == '1' }}
timeout-minutes: 3
run: timeout --foreground 120s env ZCODE_TEST_MOUNTX=1 bun test test/tui/scenario-mountx.test.ts

- name: Pack and install-test
run: bun run release:pack

Expand Down Expand Up @@ -125,7 +115,7 @@ jobs:

# Business-logic regressions run once in validate. Exercise the boundaries
# affected by Node/OS differences here: launch, HTTP streaming, app-server
# auth, both terminal modes, and the real SQLite driver below.
# auth and the real SQLite driver below; terminal wiring runs in validate.
- name: Run Node and OS compatibility tests
run: bun run test:runtime:compat

Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -586,11 +586,14 @@ Run all validation layers:

```bash
bun run typecheck
bun test
bun run test
bun run check
bun run check:tui
```

The required contracts and the reason for every retained test file are listed in
[`test/README.md`](./test/README.md). `bun run test:unit` runs only the fast subset.

For the OAuth path, release workflow details, CI, and the full development
guide, see [Development](./docs/DEVELOPMENT.md). For maintainer-only release
and publishing workflows, see [Releasing](./docs/RELEASING.md).
Expand Down
62 changes: 28 additions & 34 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ to these functions. Recovery reads optional metadata asynchronously and shares
one in-flight restoration per app, so a concurrent send waits for registration.
The runtime continues to own task lifecycle, registry state and message routing;
the helper merges read models and preserves the existing restore/stop/send order.
`test/runtime-tui-bridge.test.ts` tests these operations directly, while
`test/sync-runtime.test.ts` exercises the injected calls and patch idempotency.
Required runtime patches are verified during synchronization and by `check`.
The minimal behavioral test inventory is documented in
[`test/README.md`](../test/README.md); implementation-string and patch-fixture
matrices are not part of the default gate.

Run all validation layers:

Expand All @@ -56,18 +58,15 @@ See [TUI scenario testing](./TUI_SCENARIO_TESTING.md) for fixture and PTY
guidance, and [SQLite concurrency](./SQLITE_CONCURRENCY.md) for storage retry
boundaries and real Node regression coverage.

`check:tui` runs real-PTY scenarios. The official runtime scenario completes
`check:tui` runs one real-PTY official runtime scenario. It completes
masked Coding Plan API-key setup in a temporary home, verifies the official
config output, executes `/help`, switches to plan mode, exits, and checks that
the launcher forwards terminal SIGHUP shutdown. The offline
feature scenario also covers suspended login restoration, selectors, image
attachments, nested Agent tools, Markdown, Mermaid, diffs, transcript
navigation, context/status details, MCP actions, task-scoped background output,
terminal-agent recovery and the
workflow panel. A pressure scenario verifies that steering, UTF-8 input and
Ctrl+C cancellation remain responsive during rapid Bash progress output. The
scenarios advance from observed terminal output instead of fixed timers and do
not make model API calls.
the launcher forwards terminal SIGHUP shutdown. The separate `test:tui` suite
covers queue/image ownership, permission ordering, startup cancellation, shell
cleanup in both terminal modes, and tool writes with Git diff inspection.
Tests advance from observed output rather than fixed sleeps and do not make
external model API calls. Visual matrices and output-pressure benchmarks are
not release requirements.

Dependency security fixes and their regression commands are documented in
[`patches/README.md`](../patches/README.md). Source installs must use Bun so
Expand All @@ -83,9 +82,9 @@ the hardware cursor remains the only caret on the focused input. The
PTY trace checks share `scripts/terminal-output.ts`, which handles both BEL
and ST control-string terminators without consuming subsequent visible text.

After changing pi-tui, `bun run check:tui` verifies regular/fullscreen input,
focus, search, selection, images and overlays. `bun run verify:tui-perf` runs
the complete quality and performance gate, including those smoke checks.
After changing pi-tui, run `bun run test:tui` and `bun run check:tui` for the
required terminal contracts. Inspect focus, selection and overlays manually
when relevant. `bun run verify:tui-perf` adds optional performance measurements.
The three runtime patches
`http-no-content`, `bigmodel-oauth` and `cli-help-contract` also remain in the
patch plan as required verification points: Desktop 3.16.3 already supplies
Expand All @@ -103,8 +102,7 @@ Only the best requested number of matches are retained, with exact names before
prefix and substring matches. Hidden entries require a query beginning with `.`;
this preserves the runtime's existing rules rather than adding `.gitignore` parsing.

`bun test test/runtime-workspace-paths.test.ts test/runtime-workspace-path-patches.test.ts`
covers real file trees and patch compatibility. After syncing the built runtime,
After syncing the built runtime,
`bun test test/runtime/workspace-paths.test.ts` checks the actual native provider
and filesystem adapter in Node, including the nested file case from #240.

Expand All @@ -125,7 +123,7 @@ bun run sync:local # macOS with /Applications/ZCode.app; otherwise use bun run s
bun scripts/smoke-tui.ts
```

The tests cover lazy and legacy command lists, custom commands, MCP picker
The tests cover lazy command lists, custom commands, MCP picker
dispatch, cancellation, late rejection, and raw-mode restoration on failure. The
runtime smoke test also checks `/mc` suggestions from the real upstream loader.
For manual verification, launch `zcode`, type `/mc` without submitting, and check
Expand Down Expand Up @@ -164,23 +162,23 @@ bun test test/runtime/session-model-recovery.test.ts

Headless recovery exits with the invalid provider/model and instructions to
resume interactively; it sends no model request. The regression tests also
cover `/resume` inside the TUI and restarting after a repair.
cover repairing a saved model and restarting after the repair.

## Runtime refresh regression

`bun test test/runtime-context-cache.test.ts test/tui/runtime-refresh.test.ts`
verifies that text/reasoning deltas do not schedule runtime queries and that
tool activity polling reuses a compact, session-scoped token summary. Completed
Runtime refresh behavior is not exhaustively tested by the minimal suite.
When changing it, verify that text/reasoning deltas do not schedule runtime
queries and that tool activity polling reuses a compact, session-scoped token summary. Completed
requests, history changes and changed projection usage invalidate the summary.
In-flight reads from a previous session or revision cannot overwrite newer
statistics. Full message bodies are read for statistics only after invalidation
or when the user opens `/context`; they are not retained in the cache.

## Context window projection (#212)

`bun test test/runtime-context-window-patches.test.ts test/runtime/context-window-projection.test.ts`
covers the patch that makes the product-state projection report the model's resolved
context window. The runtime assigns `contextWindow` from a `session_created` event
The required patch makes the product-state projection report the model's resolved
context window; synchronization and `check` verify it on the locked runtime.
The runtime assigned `contextWindow` from a `session_created` event
that current runtimes no longer append for new sessions, so `/context`, the runtime
state and the headless `--json` projection kept the 200000 default while compaction
and the request budget used the configured window.
Expand Down Expand Up @@ -267,8 +265,7 @@ and injects registry options plus the registry's auth port. Unrelated functions,
partial patches, mismatched registries and ambiguous anchors cannot satisfy its
verification. Acorn is a synchronization-time development dependency.

Run `bun test test/app-server-auth.test.ts test/runtime-app-server-patches.test.ts`
for mode selection and patch regression tests. After synchronization, run
Run `bun test test/app-server-auth.test.ts` for mode selection. After synchronization, run
`bun test test/runtime/app-server-auth.test.ts` for real protocol turns against
a local HTTPS model server: local login, credential rotation, host account
updates and auth callbacks, missing credentials and invalid modes. Tests use
Expand Down Expand Up @@ -331,13 +328,10 @@ the reviewed npm tarball and an isolated installed-package smoke test.
The complete runtime suite runs once in that job. Additional Node 24/26 Linux
and Node 24 macOS jobs reuse the same tarball and run `test:runtime:compat`,
the installed-package checks and the real Node SQLite suite. The compatibility
subset covers launch, HTTP streaming/retry, app-server authentication and both
TUI modes; it does not repeat the entire model/configuration/workflow matrix.

`check:tui:focus` uses three representative configurations: regular with
notifications off, fullscreen with unfocused BEL notifications, and the built
fullscreen adapter with notifications off. Backend selection is also covered
by the notification unit tests.
subset covers launch, HTTP streaming/retry and app-server authentication;
terminal modes run in the primary validation job. It does not repeat the whole
suite. Focus-dependent cursors and notification combinations are manual checks,
not a separate automatic matrix.

A newer commit to the same pull request or branch automatically cancels its
superseded CI run; unrelated pull requests continue independently.
15 changes: 7 additions & 8 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,17 +201,16 @@ both credential owners against a local HTTPS model fixture.

`bigmodel-oauth` is required. It replaces the runtime's direct exchange requiring
an app secret with Desktop's official ZCode token service, and persists the
ZCode JWT alongside the BigModel tokens. Runtime tests use the native localhost
callback, stub token/API-key endpoints and the native encrypted credential store
to cover browser login, failure cleanup and manual Coding Plan setup.
ZCode JWT alongside the BigModel tokens. The minimal OAuth tests exercise native
token storage, account changes and HTTP failure handling through local fixtures.
They are not an exhaustive BigModel login matrix; inspect platform-specific
callbacks and manual Coding Plan setup when changing those paths.

`browser-url-opening` is required. Windows browser launches use an encoded
PowerShell command that decodes the URL as data, preserving OAuth query separators,
percent encoding and state. On Windows, run `bun test test/browser-open.test.ts`
locally to exercise PowerShell itself with the browser-launch action stubbed.
The cross-platform tests remain in the unit suite. Runtime login tests also
verify that the native browser opener invokes this command before completing
the callback.
percent encoding and state. Inspect PowerShell/browser opening on Windows when
changing this path; it is not a separate test in the minimal baseline.
The real-runtime smoke still exercises masked key setup and normal launcher exit.

If a required compatibility check fails, synchronization writes JSON and
Markdown reports under `.release/`. The scheduled workflow uploads both files
Expand Down
18 changes: 8 additions & 10 deletions docs/SQLITE_CONCURRENCY.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,28 +102,26 @@ and independent Node processes. They do not use account credentials or send mode
requests. They cover:

- the effective `PRAGMA busy_timeout` after sync open, async startup, and reopen;
- a native session write blocked by another process for 6.5 seconds, longer than
the previous 5-second timeout, then succeeding exactly once;
- recovery after a 10.5-second lock, with timers progressing during backoff;
- a native session write recovering from a process-held lock while timers
progress during backoff;
- a deliberately shortened recovery budget that reports `SQLITE_BUSY`, writes
no session, and permits a later write after the lock is released;
- four independent processes migrating the same fresh database and persisting
distinct sessions without duplicate migrations or integrity errors;
- killing a writer with uncommitted changes, then reopening without those changes
and successfully writing another session;
- same-process connections completing an asynchronous native transaction without
starving its commit, plus caller-owned transactions retaining rollback ownership;
- caller-owned transactions retaining rollback ownership and never being replayed;
- a failure after message/part insertion that rolls back before input promotion
retries, and an idempotent partial part write that cannot overtake a newer update;
- a partial message bundle rolling back before replay, without duplicate messages
or parts, and rejection of stores missing the native bundle transaction;
- non-BUSY errors and partially committed goal counters never being replayed;
- closing a store cancelling both backoff and pending writes;
- 100 usage facts requiring one cleanup transaction when expired rows exist,
with recent records retained and explicit cleanup still honored;
- retrying usage writes yielding priority to conversation writes;
- twelve independent processes persisting 300 input promotions and matching
messages, parts and usage records, followed by integrity and foreign-key checks.
- integrity and foreign-key checks after migration and killed-writer recovery.

The minimal suite does not retain long held-lock delays, maintenance-priority
matrices or large multi-process stress runs. Its boundary inventory is in
[`test/README.md`](../test/README.md).

Lock holders use independent processes. One test schedules their release from
the writer's event loop to verify that the new recovery yields instead of
Expand Down
29 changes: 6 additions & 23 deletions docs/TUI_SCENARIO_TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,7 @@ Tests are grouped by execution cost and environment:
# In-process application and pure unit tests.
bun run test:unit

# In-process scenario harness components (no PTY or child TUI).
bun run test:tui:component

# Hermetic PTY scenarios with a fixture runtime.
bun run test:tui:e2e

# Tests requiring a host kernel transport and mount privileges.
ZCODE_TEST_MOUNTX=1 bun run test:tui:host

# Run component and PTY TUI layers (the default portable TUI suite).
bun run test:tui

# Tests that require vendor/zcode.cjs, Node, sockets, or local networking.
Expand All @@ -37,7 +28,7 @@ bun run test:node
bun run test:all
```

`bun run test` intentionally aliases the unit group for normal development.
`bun run test` runs the complete required suite; `test:unit` is the fast subset.
The built-in `bun test` command also discovers the Node-only `.test.cjs` files
and runs them with the wrong SQLite implementation. Use `bun run test:all`
for the complete suite; runtime and Node tests require a synchronized runtime.
Expand All @@ -54,15 +45,6 @@ bun run test:tui-scenario --list
# Run all portable TUI scenarios automatically.
bun run test:tui

# Run only the in-process scenario harness tests.
bun run test:tui:component

# Run only the real PTY TUI scenarios.
bun run test:tui:e2e

# Run Mountx only on a runner with a configured transport.
ZCODE_TEST_MOUNTX=1 bun run test:tui:host

# Run one scenario automatically.
bun run test:tui-scenario permission-request-queue

Expand Down Expand Up @@ -205,10 +187,11 @@ host's selected transport. `MountxWorkspaceBackend` also accepts a custom
Mountx driver for operation journaling or deterministic fault injection. The
backend is opt-in because Mountx is alpha, requires OS mount support, and
exposes the mount to other host processes. It is not a sandbox.
The gated integration check can be run explicitly:
There is no automatic Mountx gate in the minimal suite. Inspect a mounted
workspace explicitly on a host with the required transport:

```bash
ZCODE_TEST_MOUNTX=1 bun test test/tui/scenario-mountx.test.ts
bun run test:tui:manual allowlisted-shell --workspace-backend=mountx
```

The completed backend boundary is:
Expand All @@ -233,6 +216,6 @@ container/VM runtime test instead of weakening the hermetic TUI suite.
2. Add a declaration under `test/tui/scenarios/` with optional baseline files
and the automatic interaction.
3. Register it in `test/tui/scenarios/index.ts`.
4. Add a `bun:test` entry and register it in the matching `test:tui` package script
when the scenario should run in the automated suite.
4. Add a `bun:test` entry only when it prevents a distinct product failure not
already covered by the inventory in [`test/README.md`](../test/README.md).
5. Verify both automatic and `--manual` modes before enabling it in CI.
12 changes: 4 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,15 @@
"sync:local": "bun run build && bun scripts/sync-runtime.ts --app /Applications/ZCode.app",
"check": "bun run build && bun scripts/check-runtime.ts",
"check:oauth-callback": "bun scripts/smoke-oauth-callback.ts",
"check:tui": "bun scripts/smoke-tui.ts && bun scripts/smoke-tui-features.ts && bun scripts/smoke-tui-clear.ts && bun scripts/smoke-tui-session-title.ts && bun scripts/smoke-tui-pressure.ts && bun scripts/smoke-tui-widths.ts && bun scripts/smoke-tui-fullscreen.ts && bun scripts/smoke-tui-fullscreen-switch.ts && bun scripts/smoke-tui-fullscreen-layout.ts && bun run check:tui:focus",
"check:tui:focus": "bun scripts/smoke-tui-focus.ts regular off always && bun scripts/smoke-tui-focus.ts fullscreen bel unfocused && bun scripts/smoke-tui-focus.ts fullscreen off always built",
"check:tui": "bun scripts/smoke-tui.ts",
"check:tui:focus:manual": "bun scripts/manual-tui-focus.ts",
"test": "bun run test:unit",
"test": "bun run test:all",
"test:all": "bun run test:unit && bun run test:tui && bun run test:runtime && bun run test:node",
"test:unit": "bun test test/*.test.ts",
"test:runtime": "bun test test/runtime/*.test.ts",
"test:runtime:compat": "bun test test/runtime/launcher.test.ts test/runtime/network-retry.test.ts test/runtime/app-server-auth.test.ts test/runtime/execution-state-tui.test.ts",
"test:runtime:compat": "bun test test/runtime/launcher.test.ts test/runtime/network-retry.test.ts test/runtime/app-server-auth.test.ts",
"test:node": "node --test test/node/*.test.cjs",
"test:tui": "bun run test:tui:component && bun run test:tui:e2e",
"test:tui:component": "bun test test/tui/scenario-http.test.ts test/tui/scenario-runtime.test.ts test/tui/scenario-shell.test.ts test/tui/scenario-workspace.test.ts test/tui/terminal-screen.test.ts",
"test:tui:e2e": "bun test test/tui/allowlisted-shell.test.ts test/tui/dynamic-workflows.test.ts test/tui/http-mock.test.ts test/tui/input-actions.test.ts test/tui/model-resume.test.ts test/tui/model-status.test.ts test/tui/permission-request-queue.test.ts test/tui/run-scenario.test.ts test/tui/runtime-refresh.test.ts test/tui/session-lifecycle.test.ts test/tui/session-rename.test.ts test/tui/startup.test.ts test/tui/terminal-exit.test.ts test/tui/terminal-session.test.ts test/tui/write-and-diff.test.ts",
"test:tui:host": "bun test test/tui/scenario-mountx.test.ts",
"test:tui": "bun test test/tui/*.test.ts",
"test:tui:manual": "bun scripts/tui-scenario.ts --manual",
"test:tui-scenario": "bun scripts/tui-scenario.ts",
"typecheck": "tsc --noEmit",
Expand Down
Loading
Loading