Skip to content

feat: validate flow definitions and require defineFlow#219

Merged
osolmaz merged 13 commits intomainfrom
codex/flow-doc-design
Apr 5, 2026
Merged

feat: validate flow definitions and require defineFlow#219
osolmaz merged 13 commits intomainfrom
codex/flow-doc-design

Conversation

@osolmaz
Copy link
Copy Markdown
Contributor

@osolmaz osolmaz commented Apr 5, 2026

Summary

This PR tightens flow definition validation and standardizes flow authoring around the public acpx/flows surface.

It does five things:

  • adds zod-backed shape validation for flow definitions and node helpers while keeping the existing public flow shape (name / startAt / nodes / edges)
  • requires CLI-loaded flow modules to export defineFlow(...) from acpx/flows instead of arbitrary plain-object defaults
  • switches repo examples and test fixtures from relative src/flows... imports to acpx/flows
  • converts the pr-triage example to the same defineFlow(...) authoring pattern as the other flow examples
  • keeps FlowRunner validation structural so programmatic callers can still pass copied/composed flow objects

Why

The goal is to make one authoring path explicit for flow files without turning flows into a new DSL or changing the graph model.

The intended split is:

  • flow files: normal TypeScript modules importing from acpx/flows and exporting defineFlow(...)
  • loader: enforces that authoring contract for CLI-loaded modules
  • runtime API: still accepts structurally valid FlowDefinition objects for programmatic FlowRunner use

That preserves the existing graph surface while making the file-based authoring story consistent and easier to document.

Validation

  • pnpm run check:docs
  • pnpm run build:test && node --test --test-name-pattern='defineFlow allows staged assembly before full graph validation|validateFlowDefinition accepts structural copies of defined flows|repo flow modules use defineFlow\(\.\.\.\) and import from "acpx/flows"|integration: flow run requires defineFlow before permission gating|integration: flow run resolves "acpx/flows" imports for external flow files|integration: flow run supports staged defineFlow assembly in external modules' dist-test/test/flows.test.js dist-test/test/integration.test.js
  • pnpm run test ✅ (478 passed, 0 failed)
  • pnpm run check ❌ local-only coverage gate on Node 24: 82.26% line coverage vs configured 83%; format, typecheck, lint, build, viewer, and all tests passed

GitHub CI on the PR head is the source of truth for merge readiness.

@osolmaz osolmaz changed the title [codex] Clarify structured flow design docs docs: clarify structured flow design and PR title rules Apr 5, 2026
@osolmaz osolmaz changed the title docs: clarify structured flow design and PR title rules feat: validate flow definitions with zod Apr 5, 2026
Copy link
Copy Markdown
Contributor Author

osolmaz commented Apr 5, 2026

Final report for 62de479:

Implemented the follow-up flow authoring cleanup on top of the zod validation work.

Key points:

  • flow modules are now required to export default defineFlow({...})
  • plain exported flow objects are no longer accepted as a supported authoring form
  • repo examples and fixtures now import flow helpers from "acpx/flows" instead of relative src/flows... paths
  • examples/flows/pr-triage/pr-triage.flow.ts now uses defineFlow(...)
  • tsconfig.test.json now maps acpx/flows to ./src/flows.ts so clean test builds resolve the package self-import the same way CI/runtime do

Validation run on this branch:

  • pnpm run check:docs
  • pnpm run build:test
  • pnpm run test:coverage ❌ local-only Node 24 coverage threshold (82.12% line coverage vs configured 83%); all 478 tests passed and the previous CI acpx/flows resolution failure is fixed
  • pnpm run check ❌ same local-only Node 24 coverage threshold (82.31% line coverage vs configured 83%); format, typecheck, lint, build, viewer, and tests passed before the threshold failure

Review / comments:

  • earlier in this PR, I ran codex review --base main and fixed the one valid P2 about keeping runtime graph validation structural
  • per instruction, I did not rerun codex review after that single addressed P2
  • checked PR issue comments and PR comments on the latest head; there are no actionable comments to address

CI:

  • GitHub CI is green on 62de479 (Build, Conformance Smoke, Docs, Format, Lint, Test, Typecheck, scope)

This PR is ready to merge from my side, but I have not merged it.

@osolmaz osolmaz changed the title feat: validate flow definitions with zod feat: validate flow definitions and require defineFlow Apr 5, 2026
@osolmaz osolmaz marked this pull request as ready for review April 5, 2026 13:18
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 62de479334

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +235 to 236
if (isDefinedFlow(candidate)) {
return candidate;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Support defineFlow for CommonJS flow modules

Switching findFlowDefinition to require the internal defineFlow brand means .cjs flows can no longer use the previously valid plain-object export path, but those modules still hit prepareFlowModuleImport rewriting of "acpx/flows" to a file:// URL. In CommonJS that produces require("file:///..."), which Node resolves as MODULE_NOT_FOUND, so a CJS flow cannot satisfy the new requirement and flow run fails. Please keep the new brand gate, but avoid URL rewriting for CJS/CTS (or rewrite to a filesystem path) so CommonJS flows remain loadable.

Useful? React with 👍 / 👎.

@osolmaz osolmaz self-assigned this Apr 5, 2026
@osolmaz osolmaz merged commit ead133c into main Apr 5, 2026
8 checks passed
@osolmaz osolmaz deleted the codex/flow-doc-design branch April 5, 2026 13:34
@osolmaz
Copy link
Copy Markdown
Contributor Author

osolmaz commented Apr 5, 2026

Landed via temp rebase onto main.\n\n- Gate: \

acpx@0.4.1 check:docs /private/tmp/acpx-flow-docs-vAAONK
pnpm run format:docs:check && pnpm run lint:docs

acpx@0.4.1 format:docs:check /private/tmp/acpx-flow-docs-vAAONK
git ls-files 'docs//*.md' 'examples/flows//*.md' 'README.md' | xargs oxfmt --check

Checking formatting...

All matched files use the correct format.
Finished in 186ms on 4 files using 8 threads.

acpx@0.4.1 lint:docs /private/tmp/acpx-flow-docs-vAAONK
markdownlint-cli2 README.md docs//*.md examples/flows//*.md

markdownlint-cli2 v0.22.0 (markdownlint v0.40.0)
Finding: README.md docs/**/*.md examples/flows/pr-triage/README.md examples/flows/pr-triage/TUNING.md examples/flows/replay-viewer/README.md
Linting: 22 file(s)
Summary: 0 error(s) passed; \

acpx@0.4.1 check /private/tmp/acpx-flow-docs-vAAONK
pnpm run format:check && pnpm run typecheck && pnpm run lint && pnpm run build && pnpm run viewer:typecheck && pnpm run viewer:build && pnpm run test:coverage

acpx@0.4.1 format:check /private/tmp/acpx-flow-docs-vAAONK
oxfmt --check

Checking formatting...

All matched files use the correct format.
Finished in 750ms on 280 files using 8 threads.

acpx@0.4.1 typecheck /private/tmp/acpx-flow-docs-vAAONK
tsgo --noEmit

acpx@0.4.1 lint /private/tmp/acpx-flow-docs-vAAONK
oxlint --type-aware src && pnpm run lint:persisted-key-casing && pnpm run lint:flow-schema-terms

Found 0 warnings and 0 errors.
Finished in 283ms on 70 files with 136 rules using 8 threads.

acpx@0.4.1 lint:persisted-key-casing /private/tmp/acpx-flow-docs-vAAONK
tsx scripts/lint-persisted-key-casing.ts

acpx@0.4.1 lint:flow-schema-terms /private/tmp/acpx-flow-docs-vAAONK
tsx scripts/lint-flow-schema-terms.ts

acpx@0.4.1 build /private/tmp/acpx-flow-docs-vAAONK
tsdown src/cli.ts src/flows.ts --format esm --dts --clean --platform node --target node22 --no-fixedExtension

ℹ tsdown v0.21.7 powered by rolldown v1.0.0-rc.12
ℹ entry: src/cli.ts, src/flows.ts
ℹ target: node22
ℹ tsconfig: tsconfig.json
ℹ Build start
ℹ Cleaning 26 files
ℹ Granting execute permission to dist/cli.js
ℹ dist/cli.js 60.67 kB │ gzip: 12.49 kB
ℹ dist/flows.js 0.39 kB │ gzip: 0.21 kB
ℹ dist/session-CB-vnqUr.js.map 342.62 kB │ gzip: 70.93 kB
ℹ dist/session-CB-vnqUr.js 166.68 kB │ gzip: 34.63 kB
ℹ dist/queue-ipc-CUSJZqbV.js.map 136.64 kB │ gzip: 27.18 kB
ℹ dist/flows-B3KMclNk.js.map 123.34 kB │ gzip: 26.69 kB
ℹ dist/cli.js.map 116.69 kB │ gzip: 24.06 kB
ℹ dist/queue-ipc-CUSJZqbV.js 61.39 kB │ gzip: 12.84 kB
ℹ dist/flows-B3KMclNk.js 60.63 kB │ gzip: 13.54 kB
ℹ dist/output-Du3m6oPQ.js.map 49.43 kB │ gzip: 12.13 kB
ℹ dist/output-Du3m6oPQ.js 22.75 kB │ gzip: 6.12 kB
ℹ dist/flags-BY7Wapac.js.map 18.53 kB │ gzip: 5.25 kB
ℹ dist/cli-DMPZuVeI.js.map 13.99 kB │ gzip: 4.20 kB
ℹ dist/flags-BY7Wapac.js 9.96 kB │ gzip: 3.07 kB
ℹ dist/output-render-Bivn28wJ.js.map 9.30 kB │ gzip: 2.33 kB
ℹ dist/cli-DMPZuVeI.js 7.50 kB │ gzip: 2.40 kB
ℹ dist/output-render-Bivn28wJ.js 5.61 kB │ gzip: 1.41 kB
ℹ dist/acp-jsonrpc-BbBgC5gO.js.map 5.57 kB │ gzip: 1.61 kB
ℹ dist/flows.d.ts.map 4.75 kB │ gzip: 1.22 kB
ℹ dist/acp-jsonrpc-BbBgC5gO.js 2.69 kB │ gzip: 0.78 kB
ℹ dist/types-CeRKmEQ1.d.ts.map 1.71 kB │ gzip: 0.54 kB
ℹ dist/rolldown-runtime-CiIaOW0V.js 0.36 kB │ gzip: 0.26 kB
ℹ dist/cli.d.ts.map 0.29 kB │ gzip: 0.21 kB
ℹ dist/flows.d.ts 9.34 kB │ gzip: 2.27 kB
ℹ dist/cli.d.ts 0.69 kB │ gzip: 0.34 kB
ℹ dist/types-CeRKmEQ1.d.ts 3.58 kB │ gzip: 1.20 kB
ℹ 26 files, total: 1.24 MB
✔ Build complete in 707ms

acpx@0.4.1 viewer:typecheck /private/tmp/acpx-flow-docs-vAAONK
tsc -p examples/flows/replay-viewer/tsconfig.json --noEmit && tsc -p examples/flows/replay-viewer/tsconfig.server.json --noEmit

acpx@0.4.1 viewer:build /private/tmp/acpx-flow-docs-vAAONK
vite build --config examples/flows/replay-viewer/vite.config.ts

vite v8.0.3 building client environment for production...
�[2K
transforming...✓ 205 modules transformed.
rendering chunks...
computing gzip size...
examples/flows/replay-viewer/dist/index.html 0.40 kB │ gzip: 0.27 kB
examples/flows/replay-viewer/dist/assets/index-BOBF28CF.css 36.48 kB │ gzip: 7.06 kB
examples/flows/replay-viewer/dist/assets/index-_mI_2XBQ.js 431.66 kB │ gzip: 136.46 kB
examples/flows/replay-viewer/dist/assets/elk.bundled-2oSef6ok.js 1,432.28 kB │ gzip: 441.54 kB

✓ built in 412ms

acpx@0.4.1 test:coverage /private/tmp/acpx-flow-docs-vAAONK
pnpm run build:test && node --experimental-test-coverage --test-coverage-lines=83 --test-coverage-branches=76 --test-coverage-functions=86 --test dist-test/test/*.test.js

acpx@0.4.1 build:test /private/tmp/acpx-flow-docs-vAAONK
node -e "require('node:fs').rmSync('dist-test',{recursive:true,force:true})" && tsc -p tsconfig.test.json

✔ resolveAgentCommand maps known agents to commands (0.497375ms)
✔ resolveAgentCommand returns raw value for unknown agents (0.056292ms)
✔ resolveAgentCommand maps factory droid aliases to the droid command (0.042291ms)
✔ resolveAgentCommand prefers explicit alias overrides over built-in alias mapping (0.043542ms)
✔ trae built-in uses the standard traecli executable (0.040542ms)
✔ kiro built-in uses kiro-cli-chat directly (0.033ms)
✔ listBuiltInAgents preserves the required example prefix and alphabetical tail (0.405084ms)
✔ default agent is codex (0.039791ms)
✔ agent session id precedence is stable (1.188125ms)
✔ extractAgentSessionId reads agentSessionId when present (0.32175ms)
✔ extractAgentSessionId falls back to sessionId (0.07275ms)
✔ extractAgentSessionId prefers agentSessionId over sessionId (0.047541ms)
✔ extractAgentSessionId ignores legacy alias keys (0.04375ms)
✔ extractAgentSessionId ignores non-string and empty values (0.054417ms)
✔ resolvePermissionMode honors explicit approve-reads overrides (0.450584ms)
✔ hasExplicitPermissionModeFlag detects explicit permission grants (0.073416ms)
✔ CLI --version prints package version (190.445667ms)
✔ parseTtlSeconds parses and rounds valid numeric values (0.255584ms)
✔ parseTtlSeconds rejects non-numeric values (0.818583ms)
✔ parseTtlSeconds rejects negative values (0.313667ms)
✔ parseAllowedTools parses empty and comma-separated values (1.182375ms)
✔ parseAllowedTools rejects empty entries (0.143958ms)
✔ parseMaxTurns accepts positive integers and rejects invalid values (0.161333ms)
✔ formatPromptSessionBannerLine prints single-line prompt banner for matching cwd (0.476417ms)
✔ formatPromptSessionBannerLine includes routed-from path when cwd differs (0.328458ms)
✔ CLI resolves unknown subcommand names as raw agent commands (248.007875ms)
✔ global passthrough flags are present in help output (254.402ms)
✔ sessions new command is present in help output (899.651375ms)
✔ flow run command is present in help output (438.112042ms)
✔ sessions new --resume-session loads ACP session and stores resumed ids (880.891209ms)
✔ sessions new --resume-session fails when agent does not support session/load (458.056667ms)
✔ sessions new --resume-session surfaces not-found loadSession errors without fallback (581.672167ms)
✔ sessions ensure creates when missing and returns existing on subsequent calls (824.908792ms)
✔ sessions ensure --resume-session loads ACP session when creating missing session (943.001167ms)
✔ sessions ensure exits even when agent ignores SIGTERM (350.149833ms)
✔ sessions ensure resolves existing session by directory walk (129.585709ms)
✔ sessions and status surface agentSessionId for codex and claude in JSON mode (1230.378334ms)
✔ prompt reconciles agentSessionId from loadSession metadata (572.13075ms)
✔ set-mode persists across load fallback and replays on fresh ACP sessions (1332.131958ms)
✔ codex thought_level aliases to reasoning_effort (360.717792ms)
✔ codex set model passes the requested model through unchanged (339.6285ms)
✔ set-mode load fallback failure does not persist the fresh session id to disk (391.378042ms)
✔ set-mode surfaces actionable guidance when agent rejects session/set_mode params (405.524458ms)
✔ set returns an error when agent rejects unsupported session config params (399.417167ms)
✔ --ttl flag is parsed for sessions commands (547.885916ms)
✔ --auth-policy flag validates supported values (353.641667ms)
✔ --non-interactive-permissions validates supported values (369.405667ms)
✔ --json-strict requires --format json (118.984375ms)
✔ --json-strict rejects --verbose (273.709917ms)
✔ queued prompt failures emit exactly one JSON error event (3492.693666ms)
✔ json-strict queued prompt failure emits JSON-RPC lines only (2520.89225ms)
✔ queued prompt failures remain visible in quiet mode (2495.433083ms)
✔ non-queued write permission denial exits with code 5 (792.261708ms)
✔ --json-strict suppresses session banners on stderr (416.751125ms)
✔ prompt exits with NO_SESSION when no session exists (no auto-create) (110.618ms)
✔ json format emits structured no-session error event (222.841167ms)
✔ set-mode exits with NO_SESSION when no session exists (102.812792ms)
✔ set command exits with NO_SESSION when no session exists (246.603166ms)
✔ cancel prints nothing to cancel and exits success when no session exists (113.790375ms)
✔ cancel resolves named session when -s is before subcommand (245.296583ms)
✔ status resolves named session when -s is before subcommand (144.307875ms)
✔ set-mode resolves named session when -s is before subcommand (162.609667ms)
✔ set resolves named session when -s is before subcommand (250.820875ms)
✔ prompt reads from stdin when no prompt argument is provided (194.893708ms)
✔ prompt reads from --file for persistent prompts (95.558792ms)
✔ prompt supports --file - with additional argument text (98.91875ms)
✔ exec accepts structured ACP prompt blocks from stdin (428.239375ms)
✔ prompt preserves structured ACP prompt blocks through the queue owner (1162.508709ms)
✔ exec rejects structured image prompts with invalid mime types (221.267458ms)
✔ exec rejects structured image prompts with invalid base64 payloads (111.10525ms)
✔ prompt subcommand accepts --file without being consumed by parent command (102.341166ms)
✔ exec subcommand accepts --file without being consumed by parent command (132.192042ms)
✔ sessions history prints stored history entries (208.797292ms)
✔ sessions read prints full history by default and supports --tail (464.376042ms)
✔ status reports running queue owner when owner socket is reachable (137.193875ms)
✔ config defaults are loaded from global and project config files (248.355583ms)
✔ exec subcommand is blocked when disableExec is true (134.5845ms)
✔ exec subcommand is blocked in json format when disableExec is true (101.256125ms)
✔ exec subcommand works when disableExec is false (352.13125ms)
✔ buildAgentSpawnOptions normalizes auth env keys and preserves existing values (8.807833ms)
✔ resolveAgentCloseAfterStdinEndMs gives qodercli extra EOF shutdown grace (0.265834ms)
✔ shouldIgnoreNonJsonAgentOutputLine ignores qoder shutdown chatter only (2.979167ms)
✔ buildQoderAcpCommandArgs forwards allowed-tools and max-turns (0.157125ms)
✔ buildQoderAcpCommandArgs preserves explicit qoder startup flags (0.058583ms)
✔ AcpClient prefers env auth credentials over config credentials (0.372958ms)
✔ AcpClient authenticateIfRequired throws when auth policy is fail and credentials are missing (0.330584ms)
✔ AcpClient handlePermissionRequest short-circuits cancels and tracks unavailable prompts (2.192042ms)
✔ AcpClient handlePermissionRequest records approved decisions (0.136ms)
✔ AcpClient client-method permission errors update permission stats (0.247792ms)
✔ AcpClient createSession forwards claudeCode options in _meta (0.332791ms)
✔ AcpClient createSession forwards codex model metadata without setting it explicitly (0.146875ms)
✔ AcpClient setSessionModel uses session/set_model (0.113ms)
✔ AcpClient session update handling drains queued callbacks and swallows handler failures (0.183833ms)
✔ AcpClient lifecycle snapshot and cancel helpers reflect active prompt state (5.270417ms)
✔ AcpClient prompt rejects when the agent disconnects mid-prompt (0.511333ms)
✔ AcpClient close resets in-memory state and shuts down terminal manager (0.48675ms)
✔ loadResolvedConfig merges global and project config with project priority (21.910208ms)
✔ loadResolvedConfig rejects invalid mcpServers config (10.706875ms)
✔ initGlobalConfigFile creates the config once and then reports existing file (12.616458ms)
✔ loadResolvedConfig defaults disableExec to false (11.8145ms)
✔ loadResolvedConfig parses disableExec from global config (23.256833ms)
✔ loadResolvedConfig parses disableExec from project config with priority (49.00875ms)
✔ loadResolvedConfig rejects invalid disableExec value (15.269667ms)
✔ runner reports initialize failures as failed cases and still writes a report (12858.187375ms)
✔ runner reports missing adapter commands as failed initialize cases (229.263541ms)
✔ runner resolves relative file reads within session cwd without changing adapter command cwd (4241.583834ms)
✔ runner rejects reads outside the session cwd root (3024.795125ms)
✔ connectAndLoadSession resumes an existing load-capable session (19.936791ms)
✔ connectAndLoadSession falls back to createSession when load returns resource-not-found (6.875834ms)
✔ connectAndLoadSession fails instead of creating a fresh session when resume policy requires the same session (9.030625ms)
✔ connectAndLoadSession falls back to createSession for empty sessions on adapter internal errors (4.802291ms)
✔ connectAndLoadSession fails clearly when same-session resume is required but session/load is unsupported (1.440916ms)
✔ connectAndLoadSession falls back to session/new on -32602 Invalid params (2.436416ms)
✔ connectAndLoadSession falls back to session/new on -32601 Method not found (4.834708ms)
✔ connectAndLoadSession rethrows load failures that should not create a new session (4.612875ms)
✔ connectAndLoadSession fails when desired mode replay cannot be restored on a fresh session (2.965833ms)
✔ connectAndLoadSession replays desired model on a fresh session (2.690709ms)
✔ connectAndLoadSession reuses an already loaded client session (2.296333ms)
✔ normalizeOutputError maps permission prompt unavailable errors (0.768083ms)
✔ normalizeOutputError maps ACP resource not found errors to NO_SESSION (0.509959ms)
✔ isAcpResourceNotFoundError recognizes session-not-found hints in nested errors (0.085041ms)
✔ isAcpResourceNotFoundError recognizes Cursor session-not-found format (0.281542ms)
✔ isAcpQueryClosedBeforeResponseError matches typed ACP payload (0.055708ms)
✔ isAcpQueryClosedBeforeResponseError ignores unrelated ACP errors (0.040541ms)
✔ normalizeOutputError preserves queue metadata from typed queue errors (0.090375ms)
✔ normalizeOutputError maps AuthPolicyError to AUTH_REQUIRED detail (0.074375ms)
✔ normalizeOutputError infers AUTH_REQUIRED detail from ACP payload (0.083459ms)
✔ normalizeOutputError extracts ACP payload from wrapped errors (0.066625ms)
✔ exitCodeForOutputErrorCode maps machine codes to stable exits (0.052583ms)
✔ isAcpJsonRpcMessage accepts JSON-RPC request (0.515625ms)
✔ isAcpJsonRpcMessage accepts JSON-RPC notification (0.066833ms)
✔ isAcpJsonRpcMessage accepts JSON-RPC success response (0.063708ms)
✔ isAcpJsonRpcMessage accepts JSON-RPC error response (0.05825ms)
✔ isAcpJsonRpcMessage rejects non-JSON-RPC payload (0.048292ms)
✔ isAcpJsonRpcMessage rejects invalid request and response shapes (0.054917ms)
✔ isAcpJsonRpcMessage accepts request/notification/response fixtures after roundtrip (0.096958ms)
✔ isSessionUpdateNotification matches session/update notifications only (0.064666ms)
✔ notification and response helpers parse expected fields only (0.08725ms)
✔ readTextFile respects line/limit and logs operations (10.018375ms)
✔ readTextFile is denied in deny-all mode (4.416375ms)
✔ writeTextFile prompts in approve-reads mode and can deny (2.015333ms)
✔ writeTextFile fails when prompt is unavailable and policy is fail (2.966917ms)
✔ writeTextFile blocks paths outside cwd subtree (1.910916ms)
✔ readTextFile requires absolute paths (0.765542ms)
✔ renderShellCommand quotes arguments consistently (0.550291ms)
✔ formatShellActionSummary prefixes rendered commands (0.078042ms)
✔ runShellAction captures stdout and stderr (63.3615ms)
✔ runShellAction allows non-zero exits when requested (51.483125ms)
✔ runShellAction rejects non-zero exits by default (355.983125ms)
✔ runShellAction times out long-running commands (55.276875ms)
✔ runShellAction rejects commands terminated by signal (14.092542ms)
✔ flowRunsBaseDir defaults under the acpx home directory (0.474583ms)
✔ FlowRunStore writes manifest, projections, flow snapshot, and trace events (20.844875ms)
✔ FlowRunStore uses unique temp paths for concurrent live writes (8.853958ms)
✔ FlowRunStore preserves bundled session event order across concurrent appends (39.589875ms)
✔ extractJsonObject parses direct, fenced, and embedded JSON (2.34425ms)
✔ parseJsonObject supports strict and fenced-only modes (0.381333ms)
✔ flow node helpers validate node-local shape before runtime (1.878791ms)
✔ defineFlow validates flow definition shape before execution (1.136791ms)
✔ defineFlow allows staged assembly before full graph validation (0.213667ms)
✔ validateFlowDefinition accepts structural copies of defined flows (0.085583ms)
✔ repo flow modules use defineFlow(...) and import from "acpx/flows" (12.458041ms)
✔ FlowRunner executes isolated ACP nodes and branches deterministically (751.752083ms)
✔ FlowRunner resolves and persists dynamic run titles (9.276584ms)
✔ FlowRunner writes isolated ACP bundle traces and artifacts (465.568458ms)
✔ FlowRunner writes persistent ACP bundle traces and session bindings (455.041959ms)
✔ FlowRunner keeps the first persistent prompt on the creating client when empty sessions cannot be reloaded (476.979834ms)
✔ FlowRunner fails persistent ACP sessions when session/load cannot resume the saved session (632.898584ms)
✔ FlowRunner fails persistent ACP sessions when the agent cannot reload the same session (641.597083ms)
✔ FlowRunner stops at checkpoint nodes and marks the run as waiting (7.669375ms)
✔ FlowRunner marks a checkpoint run failed when waiting snapshot persistence fails (4.897792ms)
✔ FlowRunner executes native shell actions and parses structured output (167.686708ms)
✔ FlowRunner marks a completed run failed when the final snapshot write fails (39.568417ms)
✔ full flow validation rejects multiple outgoing edges from the same node (0.296ms)
✔ FlowRunner persists active node state while a shell step is running (258.308709ms)
✔ FlowRunner lets ACP nodes run in a dynamic working directory (549.853ms)
✔ FlowRunner keeps same session handles isolated by working directory (917.071292ms)
✔ FlowRunner marks timed out shell steps explicitly (60.967291ms)
✔ FlowRunner can route timed out nodes by outcome (66.81425ms)
✔ FlowRunner times out async shell exec callbacks (61.150542ms)
✔ FlowRunner times out async shell parse callbacks (64.016125ms)
✔ FlowRunner times out async ACP prompt callbacks (67.684458ms)
✔ FlowRunner times out async ACP parse callbacks (61.3165ms)
✔ FlowRunner respects per-node timeouts while creating persistent ACP sessions (67.429916ms)
✔ FlowRunner times out async checkpoint callbacks (65.683ms)
✔ FlowRunner stores successful node results separately from outputs (33.811792ms)
✔ integration: exec echo baseline (537.461875ms)
✔ integration: built-in cursor agent resolves to cursor-agent acp (790.114583ms)
✔ integration: flow run executes multiple ACP steps in one session and branches (1415.515ms)
✔ integration: flow run supports dynamic ACP working directories (1029.473667ms)
✔ integration: flow run executes function and shell actions from --input-file (557.013ms)
✔ integration: flow run finalizes interrupted bundles on SIGHUP (264.683ms)
✔ integration: flow run fails ACP nodes promptly when the agent disconnects mid-prompt (976.796834ms)
✔ integration: flow run fails fast when a flow requires an explicit approve-all grant (279.764042ms)
✔ integration: flow run requires defineFlow before permission gating (246.120375ms)
✔ integration: flow run preserves approve-all through persistent ACP writes (486.795667ms)
✔ integration: flow run resolves "acpx/flows" imports for external flow files (356.219709ms)
✔ integration: flow run supports staged defineFlow assembly in external modules (257.064083ms)
✔ integration: flow run reports waiting checkpoints in json mode (165.148791ms)
✔ integration: built-in droid agent resolves to droid exec --output-format acp (396.016375ms)
✔ integration: factory-droid alias resolves to droid exec --output-format acp (405.258625ms)
✔ integration: built-in iflow agent resolves to iflow --experimental-acp (448.399ms)
✔ integration: built-in qoder agent resolves to qodercli --acp (420.897958ms)
✔ integration: qoder session reuse preserves persisted startup flags (582.051958ms)
✔ integration: exec forwards model, allowed-tools, and max-turns in session/new _meta (836.616125ms)
✔ integration: exec --model calls session/set_model when agent advertises models (401.641625ms)
✔ integration: exec --model skips session/set_model when agent does not advertise models (398.847333ms)
✔ integration: exec --model fails when session/set_model fails (350.008333ms)
✔ integration: sessions new --model fails when session/set_model fails (360.593083ms)
✔ integration: set model routes through session/set_model and succeeds (774.495584ms)
✔ integration: set model rejects with clear error on ACP invalid params (1742.996917ms)
✔ integration: status shows model after session creation with --model (625.814958ms)
✔ integration: status shows updated model after set model (761.617167ms)
✔ integration: perf metrics capture writes ndjson records for CLI runs (346.102ms)
✔ integration: perf metrics capture checkpoints queue-owner turns before owner exit (1341.509583ms)
✔ integration: perf report tolerates malformed lines and keeps role and gauge summaries (310.986667ms)
✔ integration: perf metrics capture preserves SIGTERM termination semantics (531.241084ms)
✔ integration: configured mcpServers are sent to session/new and session/load (1565.8235ms)
✔ integration: timeout emits structured TIMEOUT json error (156.113167ms)
✔ integration: gemini ACP startup timeout is surfaced as actionable error for gemini.cmd too (380.747833ms)
✔ integration: built-in gemini falls back to --experimental-acp for Gemini CLI before 0.33.0 (388.44925ms)
✔ integration: built-in gemini keeps --acp for Gemini CLI 0.33.0 and newer (358.876875ms)
✔ integration: copilot ACP unsupported binary is surfaced as actionable error (325.924291ms)
✔ integration: claude ACP session creation timeout is surfaced as actionable error (416.006792ms)
✔ integration: non-interactive fail emits structured permission error (442.890875ms)
✔ integration: json-strict suppresses runtime stderr diagnostics (344.609208ms)
✔ integration: json-strict exec success emits JSON-RPC lines only (351.394042ms)
✔ integration: json-strict exec retries without emitting stderr notices (1354.509458ms)
✔ integration: fs/read_text_file through mock agent (370.286208ms)
✔ integration: --suppress-reads hides read file body in text format (453.018ms)
✔ integration: --suppress-reads hides read file body in json format (416.092ms)
✔ integration: fs/write_text_file through mock agent (527.099416ms)
✔ integration: fs/read_text_file outside cwd is denied (336.398ms)
✔ integration: terminal lifecycle create/output/wait/release (595.123584ms)
✔ integration: terminal kill leaves no orphan sleep process (2256.488958ms)
✔ integration: prompt reuses warm queue owner and agent pid across turns (1095.051208ms)
✔ integration: config agent command with flags is split correctly and stores protocol version (348.053917ms)
✔ integration: prompt recovers when loadSession fails on empty session without emitting load error (979.918208ms)
✔ integration: prompt retries stop after partial prompt output (791.15875ms)
✔ integration: exec retries stop after partial prompt output (396.976959ms)
✔ integration: prompt recovers when loadSession returns not found without emitting load error (772.498125ms)
✔ integration: load replay session/update notifications are suppressed from output and event log (1443.495625ms)
✔ integration: cancel yields cancelled stopReason without queue error (1013.87325ms)
✔ integration: prompt exits after done while detached owner stays warm (1104.868583ms)
✔ integration: session remains resumable after queue owner exits and agent has exited (2689.633708ms)
✔ buildJsonRpcErrorResponse preserves ACP payload when available (0.825834ms)
✔ buildJsonRpcErrorResponse shapes fallback ACPX metadata (0.107375ms)
✔ parseOptionalMcpServers returns undefined for missing values (0.49475ms)
✔ parseMcpServers parses http, sse, and stdio servers (0.679542ms)
✔ parseMcpServers rejects invalid top-level and entry fields (0.305542ms)
✔ parseMcpServers rejects invalid nested header, args, env, and meta values (0.106667ms)
✔ text formatter batches thought chunks from ACP notifications (0.892667ms)
✔ text formatter preserves line breaks in thought chunks (0.118042ms)
✔ text formatter renders tool call lifecycle from ACP updates (0.581ms)
✔ json formatter passes through ACP messages (1.180125ms)
✔ json formatter emits ACP JSON-RPC error response from onError (0.221667ms)
✔ text formatter suppresses read output when requested (0.212042ms)
✔ json formatter suppresses read output when requested (0.209416ms)
✔ json formatter suppresses read-like tool updates inferred from title (0.134291ms)
✔ json formatter leaves non-read tool updates unchanged with suppression enabled (0.075458ms)
✔ quiet formatter ignores suppress-reads and still outputs assistant text only (0.092584ms)
✔ quiet formatter outputs only agent text and flushes on prompt result (0.073083ms)
✔ incrementPerfCounter creates a new counter starting at 1 (0.663833ms)
✔ incrementPerfCounter accumulates multiple increments (0.102834ms)
✔ incrementPerfCounter accepts a custom delta (0.076292ms)
✔ setPerfGauge sets and overwrites gauge values (0.081666ms)
✔ recordPerfDuration tracks count, totalMs, and maxMs (0.110084ms)
✔ recordPerfDuration rounds values to 3 decimal places in snapshot (0.069875ms)
✔ measurePerf records duration of an async function (21.277167ms)
✔ measurePerf records duration even when the function throws (0.654042ms)
✔ startPerfTimer returns a stop function that records elapsed time (0.188875ms)
✔ getPerfMetricsSnapshot returns empty maps after reset (0.868ms)
✔ getPerfMetricsSnapshot isolates counters, gauges, and timings (0.297917ms)
✔ formatPerfMetric formats name and duration with 3 decimal places (0.132792ms)
✔ promptForPermission returns false when stdin or stderr is not a TTY (0.898708ms)
✔ promptForPermission writes header/details and accepts yes answers (0.616125ms)
✔ promptForPermission rejects non-yes answers and skips blank details (0.129625ms)
✔ approve-all approves everything (0.886625ms)
✔ deny-all denies everything (0.062708ms)
✔ approve-reads approves reads and denies writes (0.318375ms)
✔ non-interactive policy fail throws when prompt is required (0.3275ms)
✔ approve-all falls back to the first option when no allow option exists (0.084083ms)
✔ deny-all cancels when no reject option exists (0.058083ms)
✔ approve-reads infers read-like titles without an explicit tool kind (0.512666ms)
✔ approve-reads rejects non-read title inference when prompting is unavailable (0.104791ms)
✔ approve-reads prompts interactively for non-read tools (0.197ms)
✔ classifyPermissionDecision maps selected outcomes to approved, denied, or cancelled (0.067792ms)
✔ serialized session record satisfies persisted key policy (2.336083ms)
✔ persisted key policy rejects camelCase acpx-owned keys (0.379209ms)
✔ selectLocalCodexReviewText prefers stdout when present (0.469334ms)
✔ selectLocalCodexReviewText extracts the codex tail from stderr logs (0.307167ms)
✔ extractCodexReviewTail falls back to the final non-log block (0.235417ms)
✔ fix_ci_failures owns CI monitoring until a terminal state (4.22725ms)
✔ human handoff is split into ready-for-landing and needs-judgment lanes (0.863709ms)
✔ maintenance PRs stay on the feature path without adding a new flow node (0.566833ms)
✔ validation stays in ACP nodes instead of hardcoded runtime helpers (0.800125ms)
✔ judge_refactor asks whether anything should be added removed simplified or refactored (1.083667ms)
✔ pr-triage configures a descriptive run title from repo and PR number (1.021917ms)
✔ parsePromptSource accepts valid image blocks (1.118375ms)
✔ parsePromptSource rejects image blocks with non-image mime types (0.358ms)
✔ parsePromptSource rejects image blocks with invalid base64 payloads (0.077584ms)
✔ parsePromptSource keeps non-JSON bracket text as plain text (0.0715ms)
✔ parsePromptSource accepts resource and resource_link blocks (0.161042ms)
✔ parsePromptSource rejects invalid text and resource block shapes (0.120166ms)
✔ parsePromptSource returns an empty prompt for blank input (0.047292ms)
✔ mergePromptSourceWithText appends or creates prompt text (0.074791ms)
✔ promptToDisplayText renders text, resources, and images (0.09275ms)
✔ isRetryablePromptError returns true for ACP internal error (-32603) (0.594958ms)
✔ isRetryablePromptError returns true for ACP parse error (-32700) (0.0645ms)
✔ isRetryablePromptError returns true for wrapped ACP internal error (0.076625ms)
✔ isRetryablePromptError returns false for auth-required error (-32000) (0.05975ms)
✔ isRetryablePromptError returns false for method-not-found error (-32601) (0.041417ms)
✔ isRetryablePromptError returns false for invalid-params error (-32602) (0.035917ms)
✔ isRetryablePromptError returns false for resource-not-found error (-32002) (0.039333ms)
✔ isRetryablePromptError returns false for PermissionDeniedError (0.098334ms)
✔ isRetryablePromptError returns false for PermissionPromptUnavailableError (0.063833ms)
✔ isRetryablePromptError returns false for TimeoutError (0.039791ms)
✔ isRetryablePromptError returns false for non-ACP errors (0.038208ms)
✔ isRetryablePromptError returns false for null/undefined (0.029209ms)
✔ isRetryablePromptError returns false for auth message in -32603 error (0.033375ms)
✔ runSessionSetModeDirect resumes a load-capable session and closes the client once (573.41075ms)
✔ runSessionSetConfigOptionDirect falls back to createSession and returns updated options (366.130458ms)
✔ runSessionSetModelDirect updates current and desired model (558.52475ms)
✔ trySubmitToRunningOwner propagates typed queue prompt errors (12.204ms)
✔ trySetModeOnRunningOwner propagates typed queue control errors (3.859416ms)
[acpx] requested session/set_config_option on owner pid 46911 for session control-config-success-session
✔ trySetConfigOptionOnRunningOwner returns the queue owner response (6.036333ms)
✔ trySubmitToRunningOwner surfaces protocol invalid JSON detail code (2.467833ms)
✔ trySubmitToRunningOwner surfaces disconnect-before-ack detail code (2.261167ms)
✔ trySubmitToRunningOwner rejects oversized queue messages (1236.343958ms)
✔ trySubmitToRunningOwner streams queued lifecycle and returns result (3.616167ms)
✔ SessionQueueOwner emits typed invalid request payload errors (2.692875ms)
✔ SessionQueueOwner emits typed shutdown errors for pending prompts (1.70125ms)
✔ SessionQueueOwner rejects prompts when queue depth exceeds the configured limit (2.159334ms)
✔ trySubmitToRunningOwner clears stale owner lock on protocol mismatch (60.039958ms)
✔ probeQueueOwnerHealth clears stale dead owners even if a stray socket exists (12.263ms)
✔ probeQueueOwnerHealth reports unavailable socket when pid is alive (107.897292ms)
✔ probeQueueOwnerHealth clears stale dead owner lock (2.979583ms)
✔ SessionQueueOwner handles control requests and nextTask timeouts (35.410958ms)
✔ SessionQueueOwner enqueues fire-and-forget prompts and rejects invalid owner generations (15.200583ms)
✔ cancelSessionPrompt sends cancel request to active queue owner (94.822208ms)
✔ readQueueOwnerRecord returns undefined for missing and malformed lock files (10.368916ms)
✔ tryAcquireQueueOwnerLease creates a lease that can be refreshed and released (9.836375ms)
✔ tryAcquireQueueOwnerLease clears stale dead owners and can acquire on retry (5.621708ms)
✔ readQueueOwnerStatus returns live owner details for a healthy owner (7.7305ms)
✔ ensureOwnerIsUsable cleans up stale live owners (54.393958ms)
✔ terminateProcess and terminateQueueOwnerForSession handle live and missing owners (52.871584ms)
✔ parseQueueRequest accepts submit_prompt with nonInteractivePermissions (0.894875ms)
✔ parseQueueRequest rejects invalid nonInteractivePermissions value (0.072833ms)
✔ parseQueueOwnerMessage accepts typed queue error payload (0.165875ms)
✔ parseQueueOwnerMessage rejects untyped queue error payload (0.052625ms)
✔ parseQueueRequest rejects invalid owner generation (0.041459ms)
✔ parseQueueRequest accepts control requests and explicit prompt blocks (0.141708ms)
✔ parseQueueRequest rejects invalid control and prompt payload shapes (0.3505ms)
✔ parseQueueOwnerMessage accepts structured non-error owner messages (1.336792ms)
✔ parseQueueOwnerMessage accepts result payloads and optional emitted-error flag (0.470459ms)
✔ parseQueueOwnerMessage rejects invalid structured owner message payloads (0.171958ms)
▶ parseQueueOwnerPayload
✔ parses valid payload (1.910625ms)
✔ rejects invalid payloads (0.290167ms)
✔ parseQueueOwnerPayload (7.483209ms)
▶ runQueueOwnerFromEnv
✔ fails when payload env is missing (0.140125ms)
✔ runQueueOwnerFromEnv (6.67775ms)
▶ resolveQueueOwnerSpawnArgs
✔ prefers ACPX_QUEUE_OWNER_ARGS when provided (1.278958ms)
✔ returns and __queue-owner (5.685542ms)
✔ throws when argv lacks an entry path (0.788ms)
✔ resolveQueueOwnerSpawnArgs (8.518542ms)
▶ sanitizeQueueOwnerExecArgv
✔ drops test runner coverage flags but keeps loader args (0.24375ms)
✔ drops debugger flags from queue-owner exec args (0.093ms)
✔ sanitizeQueueOwnerExecArgv (0.45675ms)
▶ buildQueueOwnerArgOverride
✔ returns null when no loader args remain after sanitization (0.17225ms)
✔ returns a serialized override when loader args are required (0.088125ms)
✔ buildQueueOwnerArgOverride (0.363875ms)
✔ queue path helpers derive stable lock and socket paths (4.691875ms)
✔ queueSocketPath stays short on unix even for long home paths (3.753917ms)
✔ SUPPRESSED_READ_OUTPUT is stable (0.53825ms)
✔ isReadLikeTool matches explicit read kind (0.082ms)
✔ isReadLikeTool infers read-like titles (0.07775ms)
✔ isReadLikeTool rejects unrelated titles and blanks (0.043791ms)
✔ applyReplayPatch supports JSON Patch+ append for strings and arrays (0.972625ms)
✔ createReplayPatch normalizes string growth and array growth to JSON Patch+ append (7.728167ms)
✔ synthesizeLiveRunState replays bundled ACP events into a live current ACP attempt (4.054834ms)
✔ synthesizeLiveRunState replays only new session events beyond record.lastSeq (0.52225ms)
✔ replay viewer streams live sidebar and run patches over websocket (54.578084ms)
✔ computeResourceDelta falls back to a snapshot when patch generation throws (0.664583ms)
✔ computeResourceDelta produces a stable patch when recent runs reorder (0.314208ms)
✔ replay viewer refreshes runs snapshots after idle periods (56.473209ms)
✔ replay viewer streams selected-run ACP text as JSON Patch+ append updates (54.949208ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader bootstrap stays stable after recent-runs state updates (35.552875ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader ignores stale bootstrap results after a newer live runs snapshot (31.632708ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader waits for recent runs instead of loading the bundled sample (4.625417ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader auto-loads the first recent run when the list becomes non-empty (7.51875ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader ignores stale recent-run loads when a newer live selection wins (7.580125ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader resyncs runs when a live runs patch cannot be applied (12.027125ms)
✔ useRunBundleLoader resyncs the selected run when a live run patch cannot be applied (9.1325ms)
✔ listRunBundles returns newest valid bundles first (21.170417ms)
✔ listRunBundles prefers live status over stale run projections (5.857333ms)
✔ resolveRunBundleFilePath rejects traversal outside a run bundle (0.633125ms)
✔ readRequestedRunId returns the requested run query (0.716708ms)
✔ buildRunLocation preserves unrelated params and hash (0.14725ms)
✔ parseReplayViewerCliArgs defaults to start and supports control flags (1.304333ms)
✔ parseReplayViewerCliArgs rejects invalid flags (0.438708ms)
✔ replay viewer status and stop helpers report and stop a running server (114.830084ms)
✔ replay viewer CLI status prints running details (73.210125ms)
✔ replay viewer start rejects reusing a server for a different runs dir (39.930542ms)
✔ resolveSessionRenderState keeps live tool calls and results visible while a run is streaming (1.183917ms)
✔ resolveSessionRenderState replays tool calls before the step fully completes (1.299584ms)
✔ isPinnedToBottom treats near-bottom scroll positions as sticky (1.0925ms)
✔ isPinnedToBottom disables follow when the reader scrolls away from the bottom (1.08475ms)
✔ isPinnedToBottom honors a custom threshold (0.858084ms)
✔ didUserScrollUp disables follow on small upward reader scrolls (0.068083ms)
✔ selectAttemptView shapes ACP session content into readable conversation parts (4.434708ms)
✔ buildGraph infers start terminal and branch semantics across the full definition (2.019333ms)
✔ buildGraph applies playback progress to the active node during preview (0.425792ms)
✔ buildGraph renders the last completed terminal step as completed instead of active (0.13325ms)
✔ buildGraph pulls pre-terminal handoff chains toward the bottom automatically (0.242ms)
✔ buildGraphLayout uses layered routing and sinks terminal chains (331.597208ms)
✔ selectAttemptView falls back to hidden payloads for unknown structured messages (0.31675ms)
✔ selectAttemptView summarizes encoded tool inputs and hidden tool results without text output (0.242208ms)
✔ selectAttemptView falls back to the latest visible ACP session for non-ACP steps (0.138667ms)
✔ revealConversationSlice progressively reveals tool calls before the full assistant turn completes (0.29425ms)
✔ revealConversationTranscript keeps prior session messages visible while streaming the current slice (0.13075ms)
✔ listSessionViews returns all run sessions and marks the current streaming source (12.386125ms)
✔ listSessionViews stays empty when the selected step has no ACP session source (0.190208ms)
✔ buildPlaybackTimeline and anchors support continuous preview with discrete snapping (0.248792ms)
✔ resolvePlaybackResumeMs wraps terminal selections back to the start (0.14825ms)
✔ playbackSelectionMs clamps the final discrete step to the true timeline end (7.751041ms)
✔ advancePlaybackPlayhead applies playback speed and clamps to the timeline end (0.22775ms)
✔ resolveSelectedStepIndexAfterBundleUpdate follows the live edge when new steps append (0.103541ms)
✔ resolveSelectedStepIndexAfterBundleUpdate preserves rewind position while a run grows (0.044542ms)
✔ format helpers keep replay labels stable (0.067959ms)
✔ deriveRunOutcomeView separates replay position from a failed run outcome (0.077708ms)
✔ deriveRunOutcomeView reports completed runs independently of replay position (0.041583ms)
✔ conversation model captures prompt, chunks, tool calls, and metadata (1.831208ms)
✔ recordClientOperation keeps state and advances timestamp (0.128084ms)
✔ cloneSessionAcpxState preserves desired mode id (0.112833ms)
✔ listSessionEvents reads all configured stream segments (37.222083ms)
✔ SessionEventWriter stores actual segment_count and increments lastSeq (11.357875ms)
✔ listSessionEvents skips malformed NDJSON lines (4.011042ms)
✔ SessionEventWriter recovers stale stream lock files (6.607667ms)
✔ normalizeModeId trims valid values and drops blanks (0.63075ms)
✔ getDesiredModeId reads normalized desired_mode_id (0.110166ms)
✔ setDesiredModeId creates and clears acpx mode preference state (0.570333ms)
✔ SessionRecord allows optional closed and closedAt fields (0.694833ms)
✔ listSessions preserves acpx desired_mode_id (174.978042ms)
✔ listSessions preserves acpx session_options (10.025708ms)
✔ listSessions ignores unsupported conversation message shapes (8.117167ms)
✔ listSessions preserves lifecycle and conversation metadata (10.167167ms)
✔ listSessions preserves optional agentSessionId (6.558375ms)
✔ findSession and findSessionByDirectoryWalk resolve expected records (12.92525ms)
✔ writeSessionRecord maintains an index and listSessions rebuilds it when missing (7.859459ms)
✔ closeSession soft-closes and terminates matching process (62.692958ms)
✔ normalizeQueueOwnerTtlMs applies default and edge-case normalization (1.954583ms)
✔ withTimeout resolves when timeout is disabled (3.54275ms)
✔ withTimeout rejects with TimeoutError when promise takes too long (13.152875ms)
✔ withTimeout preserves the original rejection (0.749042ms)
✔ withInterrupt resolves normally without invoking interrupt cleanup (0.42575ms)
✔ withInterrupt rejects with InterruptedError on SIGINT and runs cleanup once (0.20975ms)
✔ withInterrupt rejects with InterruptedError on SIGTERM and removes signal listeners (0.121083ms)
✔ withInterrupt rejects with InterruptedError on SIGHUP (0.104208ms)
✔ buildAgentSpawnOptions hides Windows console windows and preserves auth env (4.545959ms)
✔ buildTerminalSpawnOptions hides Windows console windows and maps env entries (0.227041ms)
✔ buildQueueOwnerSpawnOptions hides Windows console windows and passes payload (0.112625ms)
✔ buildSpawnCommandOptions enables shell for .cmd/.bat on Windows (0.25875ms)
✔ buildSpawnCommandOptions enables shell for PATH-resolved .cmd wrappers on Windows (3.272542ms)
✔ buildSpawnCommandOptions keeps shell disabled for non-batch commands (1.664125ms)
✔ buildTerminalSpawnOptions enables shell for PATH-resolved .cmd wrappers on Windows (1.54775ms)
✔ buildTerminalSpawnOptions keeps shell disabled for non-batch commands (0.755334ms)
✔ terminal manager create/output/wait/release lifecycle (68.265292ms)
✔ terminal manager kill sends termination and process exits (2.823833ms)
✔ terminal manager prompts in approve-reads mode and can deny (0.963208ms)
✔ terminal manager fails when prompt is unavailable and policy is fail (1.00225ms)
✔ QueueOwnerTurnController tracks explicit lifecycle states (0.5025ms)
✔ QueueOwnerTurnController cancels immediately for active prompts (0.118166ms)
✔ QueueOwnerTurnController defers cancel while turn is starting (0.099125ms)
✔ QueueOwnerTurnController routes setSessionMode through active controller (0.509333ms)
✔ QueueOwnerTurnController routes setSessionModel through active controller (0.116209ms)
✔ QueueOwnerTurnController routes setSessionConfigOption through fallback when inactive (0.115458ms)
✔ QueueOwnerTurnController rejects control requests while closing (0.371375ms)
✔ resolveAcpxVersion prefers npm_package_version from env when package name is acpx (0.461583ms)
✔ resolveAcpxVersion ignores npm_package_version from non-acpx package env (15.950708ms)
✔ resolveAcpxVersion reads version from package.json when env is unset (3.077959ms)
✔ resolveAcpxVersion falls back to unknown when version cannot be resolved (0.308708ms)
✔ resolveAcpxVersion ignores blank env versions and blank package versions (5.316417ms)
✔ getAcpxVersion caches the first resolved version (2.013792ms)
ℹ tests 478
ℹ suites 5
ℹ pass 478
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 40503.226417
ℹ start of coverage report
ℹ ----------------------------------------------------------
ℹ file | line % | branch % | funcs % | uncovered lines
ℹ ----------------------------------------------------------
ℹ ----------------------------------------------------------
ℹ all files | 100.00 | 100.00 | 100.00 |
ℹ ----------------------------------------------------------
ℹ end of coverage report passed all checks except the known local Node 24 coverage threshold failure (82.24% vs 83%) while PR CI was green.\n- Land commit: \n- Merge commit: \n\nThanks @osolmaz!

Copy link
Copy Markdown
Contributor Author

osolmaz commented Apr 5, 2026

Landed via temp rebase onto main.

  • Gate: pnpm run check:docs passed; pnpm run check passed all checks except the known local Node 24 coverage threshold failure (82.24% vs 83%) while PR CI was green.
  • Land commit: 62de4793345725549cfbff3f71092f648b64a7a6
  • Merge commit: ead133cfb22592f60fd6deff19d4c873662f873a

Thanks @osolmaz!

@osolmaz
Copy link
Copy Markdown
Contributor Author

osolmaz commented Apr 5, 2026

Landed via temp rebase onto main.\n\n- Gate: \

acpx@0.4.1 check:docs /private/tmp/acpx-flow-docs-vAAONK
pnpm run format:docs:check && pnpm run lint:docs

acpx@0.4.1 format:docs:check /private/tmp/acpx-flow-docs-vAAONK
git ls-files 'docs//*.md' 'examples/flows//*.md' 'README.md' | xargs oxfmt --check

Checking formatting...

All matched files use the correct format.
Finished in 170ms on 4 files using 8 threads.

acpx@0.4.1 lint:docs /private/tmp/acpx-flow-docs-vAAONK
markdownlint-cli2 README.md docs//*.md examples/flows//*.md

markdownlint-cli2 v0.22.0 (markdownlint v0.40.0)
Finding: README.md docs/**/*.md examples/flows/pr-triage/README.md examples/flows/pr-triage/TUNING.md examples/flows/replay-viewer/README.md
Linting: 22 file(s)
Summary: 0 error(s) passed; \

acpx@0.4.1 check /private/tmp/acpx-flow-docs-vAAONK
pnpm run format:check && pnpm run typecheck && pnpm run lint && pnpm run build && pnpm run viewer:typecheck && pnpm run viewer:build && pnpm run test:coverage

acpx@0.4.1 format:check /private/tmp/acpx-flow-docs-vAAONK
oxfmt --check

Checking formatting...

All matched files use the correct format.
Finished in 737ms on 280 files using 8 threads.

acpx@0.4.1 typecheck /private/tmp/acpx-flow-docs-vAAONK
tsgo --noEmit

acpx@0.4.1 lint /private/tmp/acpx-flow-docs-vAAONK
oxlint --type-aware src && pnpm run lint:persisted-key-casing && pnpm run lint:flow-schema-terms

Found 0 warnings and 0 errors.
Finished in 360ms on 70 files with 136 rules using 8 threads.

acpx@0.4.1 lint:persisted-key-casing /private/tmp/acpx-flow-docs-vAAONK
tsx scripts/lint-persisted-key-casing.ts

acpx@0.4.1 lint:flow-schema-terms /private/tmp/acpx-flow-docs-vAAONK
tsx scripts/lint-flow-schema-terms.ts

acpx@0.4.1 build /private/tmp/acpx-flow-docs-vAAONK
tsdown src/cli.ts src/flows.ts --format esm --dts --clean --platform node --target node22 --no-fixedExtension

ℹ tsdown v0.21.7 powered by rolldown v1.0.0-rc.12
ℹ entry: src/cli.ts, src/flows.ts
ℹ target: node22
ℹ tsconfig: tsconfig.json
ℹ Build start
ℹ Cleaning 26 files
ℹ Granting execute permission to dist/cli.js
ℹ dist/cli.js 60.67 kB │ gzip: 12.49 kB
ℹ dist/flows.js 0.39 kB │ gzip: 0.21 kB
ℹ dist/session-CB-vnqUr.js.map 342.62 kB │ gzip: 70.93 kB
ℹ dist/session-CB-vnqUr.js 166.68 kB │ gzip: 34.63 kB
ℹ dist/queue-ipc-CUSJZqbV.js.map 136.64 kB │ gzip: 27.18 kB
ℹ dist/flows-B3KMclNk.js.map 123.34 kB │ gzip: 26.69 kB
ℹ dist/cli.js.map 116.69 kB │ gzip: 24.06 kB
ℹ dist/queue-ipc-CUSJZqbV.js 61.39 kB │ gzip: 12.84 kB
ℹ dist/flows-B3KMclNk.js 60.63 kB │ gzip: 13.54 kB
ℹ dist/output-Du3m6oPQ.js.map 49.43 kB │ gzip: 12.13 kB
ℹ dist/output-Du3m6oPQ.js 22.75 kB │ gzip: 6.12 kB
ℹ dist/flags-BY7Wapac.js.map 18.53 kB │ gzip: 5.25 kB
ℹ dist/cli-DMPZuVeI.js.map 13.99 kB │ gzip: 4.20 kB
ℹ dist/flags-BY7Wapac.js 9.96 kB │ gzip: 3.07 kB
ℹ dist/output-render-Bivn28wJ.js.map 9.30 kB │ gzip: 2.33 kB
ℹ dist/cli-DMPZuVeI.js 7.50 kB │ gzip: 2.40 kB
ℹ dist/output-render-Bivn28wJ.js 5.61 kB │ gzip: 1.41 kB
ℹ dist/acp-jsonrpc-BbBgC5gO.js.map 5.57 kB │ gzip: 1.61 kB
ℹ dist/flows.d.ts.map 4.75 kB │ gzip: 1.22 kB
ℹ dist/acp-jsonrpc-BbBgC5gO.js 2.69 kB │ gzip: 0.78 kB
ℹ dist/types-CeRKmEQ1.d.ts.map 1.71 kB │ gzip: 0.54 kB
ℹ dist/rolldown-runtime-CiIaOW0V.js 0.36 kB │ gzip: 0.26 kB
ℹ dist/cli.d.ts.map 0.29 kB │ gzip: 0.21 kB
ℹ dist/flows.d.ts 9.34 kB │ gzip: 2.27 kB
ℹ dist/cli.d.ts 0.69 kB │ gzip: 0.34 kB
ℹ dist/types-CeRKmEQ1.d.ts 3.58 kB │ gzip: 1.20 kB
ℹ 26 files, total: 1.24 MB
✔ Build complete in 952ms

acpx@0.4.1 viewer:typecheck /private/tmp/acpx-flow-docs-vAAONK
tsc -p examples/flows/replay-viewer/tsconfig.json --noEmit && tsc -p examples/flows/replay-viewer/tsconfig.server.json --noEmit

acpx@0.4.1 viewer:build /private/tmp/acpx-flow-docs-vAAONK
vite build --config examples/flows/replay-viewer/vite.config.ts

vite v8.0.3 building client environment for production...
�[2K
transforming...✓ 205 modules transformed.
rendering chunks...
computing gzip size...
examples/flows/replay-viewer/dist/index.html 0.40 kB │ gzip: 0.27 kB
examples/flows/replay-viewer/dist/assets/index-BOBF28CF.css 36.48 kB │ gzip: 7.06 kB
examples/flows/replay-viewer/dist/assets/index-_mI_2XBQ.js 431.66 kB │ gzip: 136.46 kB
examples/flows/replay-viewer/dist/assets/elk.bundled-2oSef6ok.js 1,432.28 kB │ gzip: 441.54 kB

✓ built in 779ms

acpx@0.4.1 test:coverage /private/tmp/acpx-flow-docs-vAAONK
pnpm run build:test && node --experimental-test-coverage --test-coverage-lines=83 --test-coverage-branches=76 --test-coverage-functions=86 --test dist-test/test/*.test.js

acpx@0.4.1 build:test /private/tmp/acpx-flow-docs-vAAONK
node -e "require('node:fs').rmSync('dist-test',{recursive:true,force:true})" && tsc -p tsconfig.test.json

✔ resolveAgentCommand maps known agents to commands (0.714125ms)
✔ resolveAgentCommand returns raw value for unknown agents (0.086041ms)
✔ resolveAgentCommand maps factory droid aliases to the droid command (0.051833ms)
✔ resolveAgentCommand prefers explicit alias overrides over built-in alias mapping (0.058708ms)
✔ trae built-in uses the standard traecli executable (0.055459ms)
✔ kiro built-in uses kiro-cli-chat directly (0.039666ms)
✔ listBuiltInAgents preserves the required example prefix and alphabetical tail (1.354375ms)
✔ default agent is codex (0.044333ms)
✔ agent session id precedence is stable (1.8825ms)
✔ extractAgentSessionId reads agentSessionId when present (0.319916ms)
✔ extractAgentSessionId falls back to sessionId (0.095833ms)
✔ extractAgentSessionId prefers agentSessionId over sessionId (0.082375ms)
✔ extractAgentSessionId ignores legacy alias keys (0.214458ms)
✔ extractAgentSessionId ignores non-string and empty values (0.138ms)
✔ resolvePermissionMode honors explicit approve-reads overrides (0.537833ms)
✔ hasExplicitPermissionModeFlag detects explicit permission grants (0.094208ms)
✔ CLI --version prints package version (252.43025ms)
✔ parseTtlSeconds parses and rounds valid numeric values (1.771583ms)
✔ parseTtlSeconds rejects non-numeric values (0.365333ms)
✔ parseTtlSeconds rejects negative values (0.067041ms)
✔ parseAllowedTools parses empty and comma-separated values (0.679083ms)
✔ parseAllowedTools rejects empty entries (0.058917ms)
✔ parseMaxTurns accepts positive integers and rejects invalid values (0.090875ms)
✔ formatPromptSessionBannerLine prints single-line prompt banner for matching cwd (0.201167ms)
✔ formatPromptSessionBannerLine includes routed-from path when cwd differs (0.10525ms)
✔ CLI resolves unknown subcommand names as raw agent commands (557.830125ms)
✔ global passthrough flags are present in help output (376.313208ms)
✔ sessions new command is present in help output (1838.752458ms)
✔ flow run command is present in help output (326.950917ms)
✔ sessions new --resume-session loads ACP session and stores resumed ids (706.607833ms)
✔ sessions new --resume-session fails when agent does not support session/load (660.534916ms)
✔ sessions new --resume-session surfaces not-found loadSession errors without fallback (621.1145ms)
✔ sessions ensure creates when missing and returns existing on subsequent calls (885.949375ms)
✔ sessions ensure --resume-session loads ACP session when creating missing session (676.153792ms)
✔ sessions ensure exits even when agent ignores SIGTERM (442.745875ms)
✔ sessions ensure resolves existing session by directory walk (125.87325ms)
✔ sessions and status surface agentSessionId for codex and claude in JSON mode (1252.746208ms)
✔ prompt reconciles agentSessionId from loadSession metadata (532.729375ms)
✔ set-mode persists across load fallback and replays on fresh ACP sessions (1404.491ms)
✔ codex thought_level aliases to reasoning_effort (422.351792ms)
✔ codex set model passes the requested model through unchanged (417.257667ms)
✔ set-mode load fallback failure does not persist the fresh session id to disk (452.078958ms)
✔ set-mode surfaces actionable guidance when agent rejects session/set_mode params (433.618125ms)
✔ set returns an error when agent rejects unsupported session config params (429.434125ms)
✔ --ttl flag is parsed for sessions commands (791.072167ms)
✔ --auth-policy flag validates supported values (406.048791ms)
✔ --non-interactive-permissions validates supported values (380.348084ms)
✔ --json-strict requires --format json (125.986875ms)
✔ --json-strict rejects --verbose (243.623291ms)
✔ queued prompt failures emit exactly one JSON error event (2637.082084ms)
✔ json-strict queued prompt failure emits JSON-RPC lines only (2647.196125ms)
✔ queued prompt failures remain visible in quiet mode (2599.977208ms)
✔ non-queued write permission denial exits with code 5 (772.459125ms)
✔ --json-strict suppresses session banners on stderr (366.19375ms)
✔ prompt exits with NO_SESSION when no session exists (no auto-create) (191.3935ms)
✔ json format emits structured no-session error event (121.313916ms)
✔ set-mode exits with NO_SESSION when no session exists (254.869125ms)
✔ set command exits with NO_SESSION when no session exists (122.993125ms)
✔ cancel prints nothing to cancel and exits success when no session exists (241.235583ms)
✔ cancel resolves named session when -s is before subcommand (130.926542ms)
✔ status resolves named session when -s is before subcommand (249.089042ms)
✔ set-mode resolves named session when -s is before subcommand (119.700625ms)
✔ set resolves named session when -s is before subcommand (259.030958ms)
✔ prompt reads from stdin when no prompt argument is provided (209.316459ms)
✔ prompt reads from --file for persistent prompts (109.364375ms)
✔ prompt supports --file - with additional argument text (117.257167ms)
✔ exec accepts structured ACP prompt blocks from stdin (368.265041ms)
✔ prompt preserves structured ACP prompt blocks through the queue owner (1134.515375ms)
✔ exec rejects structured image prompts with invalid mime types (141.503542ms)
✔ exec rejects structured image prompts with invalid base64 payloads (277.985375ms)
✔ prompt subcommand accepts --file without being consumed by parent command (152.345834ms)
✔ exec subcommand accepts --file without being consumed by parent command (279.26875ms)
✔ sessions history prints stored history entries (282.203542ms)
✔ sessions read prints full history by default and supports --tail (431.620708ms)
✔ status reports running queue owner when owner socket is reachable (459.3015ms)
✔ config defaults are loaded from global and project config files (314.62125ms)
✔ exec subcommand is blocked when disableExec is true (460.485542ms)
✔ exec subcommand is blocked in json format when disableExec is true (170.257333ms)
✔ exec subcommand works when disableExec is false (446.831083ms)
✔ buildAgentSpawnOptions normalizes auth env keys and preserves existing values (24.864208ms)
✔ resolveAgentCloseAfterStdinEndMs gives qodercli extra EOF shutdown grace (0.359ms)
✔ shouldIgnoreNonJsonAgentOutputLine ignores qoder shutdown chatter only (0.089166ms)
✔ buildQoderAcpCommandArgs forwards allowed-tools and max-turns (0.144834ms)
✔ buildQoderAcpCommandArgs preserves explicit qoder startup flags (0.076041ms)
✔ AcpClient prefers env auth credentials over config credentials (0.435791ms)
✔ AcpClient authenticateIfRequired throws when auth policy is fail and credentials are missing (0.622833ms)
✔ AcpClient handlePermissionRequest short-circuits cancels and tracks unavailable prompts (1.212375ms)
✔ AcpClient handlePermissionRequest records approved decisions (0.17025ms)
✔ AcpClient client-method permission errors update permission stats (0.300917ms)
✔ AcpClient createSession forwards claudeCode options in _meta (0.407958ms)
✔ AcpClient createSession forwards codex model metadata without setting it explicitly (0.137792ms)
✔ AcpClient setSessionModel uses session/set_model (0.166667ms)
✔ AcpClient session update handling drains queued callbacks and swallows handler failures (0.239833ms)
✔ AcpClient lifecycle snapshot and cancel helpers reflect active prompt state (4.835125ms)
✔ AcpClient prompt rejects when the agent disconnects mid-prompt (0.408208ms)
✔ AcpClient close resets in-memory state and shuts down terminal manager (1.919792ms)
✔ loadResolvedConfig merges global and project config with project priority (26.7495ms)
✔ loadResolvedConfig rejects invalid mcpServers config (7.962334ms)
✔ initGlobalConfigFile creates the config once and then reports existing file (5.67425ms)
✔ loadResolvedConfig defaults disableExec to false (5.871875ms)
✔ loadResolvedConfig parses disableExec from global config (6.999125ms)
✔ loadResolvedConfig parses disableExec from project config with priority (10.172ms)
✔ loadResolvedConfig rejects invalid disableExec value (27.1635ms)
✔ runner reports initialize failures as failed cases and still writes a report (12905.337875ms)
✔ runner reports missing adapter commands as failed initialize cases (196.132125ms)
✔ runner resolves relative file reads within session cwd without changing adapter command cwd (3223.36175ms)
✔ runner rejects reads outside the session cwd root (2982.008ms)
✔ connectAndLoadSession resumes an existing load-capable session (9.0305ms)
✔ connectAndLoadSession falls back to createSession when load returns resource-not-found (6.781625ms)
✔ connectAndLoadSession fails instead of creating a fresh session when resume policy requires the same session (4.844958ms)
✔ connectAndLoadSession falls back to createSession for empty sessions on adapter internal errors (6.167459ms)
✔ connectAndLoadSession fails clearly when same-session resume is required but session/load is unsupported (12.823375ms)
✔ connectAndLoadSession falls back to session/new on -32602 Invalid params (18.446666ms)
✔ connectAndLoadSession falls back to session/new on -32601 Method not found (5.398584ms)
✔ connectAndLoadSession rethrows load failures that should not create a new session (4.390583ms)
✔ connectAndLoadSession fails when desired mode replay cannot be restored on a fresh session (6.020958ms)
✔ connectAndLoadSession replays desired model on a fresh session (8.529ms)
✔ connectAndLoadSession reuses an already loaded client session (3.529375ms)
✔ normalizeOutputError maps permission prompt unavailable errors (6.308416ms)
✔ normalizeOutputError maps ACP resource not found errors to NO_SESSION (1.268875ms)
✔ isAcpResourceNotFoundError recognizes session-not-found hints in nested errors (0.21725ms)
✔ isAcpResourceNotFoundError recognizes Cursor session-not-found format (0.5535ms)
✔ isAcpQueryClosedBeforeResponseError matches typed ACP payload (0.108709ms)
✔ isAcpQueryClosedBeforeResponseError ignores unrelated ACP errors (0.057875ms)
✔ normalizeOutputError preserves queue metadata from typed queue errors (0.138458ms)
✔ normalizeOutputError maps AuthPolicyError to AUTH_REQUIRED detail (1.268333ms)
✔ normalizeOutputError infers AUTH_REQUIRED detail from ACP payload (0.368458ms)
✔ normalizeOutputError extracts ACP payload from wrapped errors (0.1945ms)
✔ exitCodeForOutputErrorCode maps machine codes to stable exits (0.136666ms)
✔ isAcpJsonRpcMessage accepts JSON-RPC request (0.637834ms)
✔ isAcpJsonRpcMessage accepts JSON-RPC notification (0.080334ms)
✔ isAcpJsonRpcMessage accepts JSON-RPC success response (0.074666ms)
✔ isAcpJsonRpcMessage accepts JSON-RPC error response (0.066625ms)
✔ isAcpJsonRpcMessage rejects non-JSON-RPC payload (0.054375ms)
✔ isAcpJsonRpcMessage rejects invalid request and response shapes (0.0625ms)
✔ isAcpJsonRpcMessage accepts request/notification/response fixtures after roundtrip (0.111209ms)
✔ isSessionUpdateNotification matches session/update notifications only (0.071292ms)
✔ notification and response helpers parse expected fields only (0.103292ms)
✔ readTextFile respects line/limit and logs operations (9.944458ms)
✔ readTextFile is denied in deny-all mode (12.907416ms)
✔ writeTextFile prompts in approve-reads mode and can deny (3.140084ms)
✔ writeTextFile fails when prompt is unavailable and policy is fail (5.907042ms)
✔ writeTextFile blocks paths outside cwd subtree (1.877459ms)
✔ readTextFile requires absolute paths (2.899917ms)
✔ renderShellCommand quotes arguments consistently (0.551709ms)
✔ formatShellActionSummary prefixes rendered commands (0.198209ms)
✔ runShellAction captures stdout and stderr (68.186208ms)
✔ runShellAction allows non-zero exits when requested (54.799ms)
✔ runShellAction rejects non-zero exits by default (415.007542ms)
✔ runShellAction times out long-running commands (55.733666ms)
✔ runShellAction rejects commands terminated by signal (23.280458ms)
✔ flowRunsBaseDir defaults under the acpx home directory (0.647291ms)
✔ FlowRunStore writes manifest, projections, flow snapshot, and trace events (37.790459ms)
✔ FlowRunStore uses unique temp paths for concurrent live writes (11.834791ms)
✔ FlowRunStore preserves bundled session event order across concurrent appends (55.103ms)
✔ extractJsonObject parses direct, fenced, and embedded JSON (1.7405ms)
✔ parseJsonObject supports strict and fenced-only modes (0.321708ms)
✔ flow node helpers validate node-local shape before runtime (2.26425ms)
✔ defineFlow validates flow definition shape before execution (2.603542ms)
✔ defineFlow allows staged assembly before full graph validation (0.364625ms)
✔ validateFlowDefinition accepts structural copies of defined flows (0.107208ms)
✔ repo flow modules use defineFlow(...) and import from "acpx/flows" (10.823541ms)
✔ FlowRunner executes isolated ACP nodes and branches deterministically (892.584834ms)
✔ FlowRunner resolves and persists dynamic run titles (18.239708ms)
✔ FlowRunner writes isolated ACP bundle traces and artifacts (532.310291ms)
✔ FlowRunner writes persistent ACP bundle traces and session bindings (694.952709ms)
✔ FlowRunner keeps the first persistent prompt on the creating client when empty sessions cannot be reloaded (579.378417ms)
✔ FlowRunner fails persistent ACP sessions when session/load cannot resume the saved session (936.375958ms)
✔ FlowRunner fails persistent ACP sessions when the agent cannot reload the same session (747.843084ms)
✔ FlowRunner stops at checkpoint nodes and marks the run as waiting (20.277667ms)
✔ FlowRunner marks a checkpoint run failed when waiting snapshot persistence fails (19.067083ms)
✔ FlowRunner executes native shell actions and parses structured output (118.232708ms)
✔ FlowRunner marks a completed run failed when the final snapshot write fails (66.716583ms)
✔ full flow validation rejects multiple outgoing edges from the same node (1.110792ms)
✔ FlowRunner persists active node state while a shell step is running (476.635708ms)
✔ FlowRunner lets ACP nodes run in a dynamic working directory (736.70925ms)
✔ FlowRunner keeps same session handles isolated by working directory (661.176667ms)
✔ FlowRunner marks timed out shell steps explicitly (68.161167ms)
✔ FlowRunner can route timed out nodes by outcome (69.075833ms)
✔ FlowRunner times out async shell exec callbacks (65.372083ms)
✔ FlowRunner times out async shell parse callbacks (59.729166ms)
✔ FlowRunner times out async ACP prompt callbacks (57.959834ms)
✔ FlowRunner times out async ACP parse callbacks (58.337792ms)
✔ FlowRunner respects per-node timeouts while creating persistent ACP sessions (59.494458ms)
✔ FlowRunner times out async checkpoint callbacks (69.265584ms)
✔ FlowRunner stores successful node results separately from outputs (10.983166ms)
✔ integration: exec echo baseline (603.284ms)
✔ integration: built-in cursor agent resolves to cursor-agent acp (924.220041ms)
✔ integration: flow run executes multiple ACP steps in one session and branches (1409.853875ms)
✔ integration: flow run supports dynamic ACP working directories (907.799334ms)
✔ integration: flow run executes function and shell actions from --input-file (615.310708ms)
✔ integration: flow run finalizes interrupted bundles on SIGHUP (271.051458ms)
✔ integration: flow run fails ACP nodes promptly when the agent disconnects mid-prompt (763.490917ms)
✔ integration: flow run fails fast when a flow requires an explicit approve-all grant (663.923541ms)
✔ integration: flow run requires defineFlow before permission gating (331.046708ms)
✔ integration: flow run preserves approve-all through persistent ACP writes (678.809459ms)
✔ integration: flow run resolves "acpx/flows" imports for external flow files (397.263375ms)
✔ integration: flow run supports staged defineFlow assembly in external modules (267.189917ms)
✔ integration: flow run reports waiting checkpoints in json mode (154.845292ms)
✔ integration: built-in droid agent resolves to droid exec --output-format acp (492.255ms)
✔ integration: factory-droid alias resolves to droid exec --output-format acp (371.892833ms)
✔ integration: built-in iflow agent resolves to iflow --experimental-acp (355.275ms)
✔ integration: built-in qoder agent resolves to qodercli --acp (400.836709ms)
✔ integration: qoder session reuse preserves persisted startup flags (580.489125ms)
✔ integration: exec forwards model, allowed-tools, and max-turns in session/new _meta (880.114417ms)
✔ integration: exec --model calls session/set_model when agent advertises models (433.186416ms)
✔ integration: exec --model skips session/set_model when agent does not advertise models (449.540917ms)
✔ integration: exec --model fails when session/set_model fails (429.787958ms)
✔ integration: sessions new --model fails when session/set_model fails (472.063208ms)
✔ integration: set model routes through session/set_model and succeeds (961.202625ms)
✔ integration: set model rejects with clear error on ACP invalid params (742.588416ms)
✔ integration: status shows model after session creation with --model (747.819708ms)
✔ integration: status shows updated model after set model (868.265833ms)
✔ integration: perf metrics capture writes ndjson records for CLI runs (423.06325ms)
✔ integration: perf metrics capture checkpoints queue-owner turns before owner exit (1260.7205ms)
✔ integration: perf report tolerates malformed lines and keeps role and gauge summaries (560.551125ms)
✔ integration: perf metrics capture preserves SIGTERM termination semantics (511.485792ms)
✔ integration: configured mcpServers are sent to session/new and session/load (2244.577292ms)
✔ integration: timeout emits structured TIMEOUT json error (165.410209ms)
✔ integration: gemini ACP startup timeout is surfaced as actionable error for gemini.cmd too (412.015834ms)
✔ integration: built-in gemini falls back to --experimental-acp for Gemini CLI before 0.33.0 (354.548291ms)
✔ integration: built-in gemini keeps --acp for Gemini CLI 0.33.0 and newer (362.581292ms)
✔ integration: copilot ACP unsupported binary is surfaced as actionable error (316.949792ms)
✔ integration: claude ACP session creation timeout is surfaced as actionable error (533.54925ms)
✔ integration: non-interactive fail emits structured permission error (452.947208ms)
✔ integration: json-strict suppresses runtime stderr diagnostics (371.530166ms)
✔ integration: json-strict exec success emits JSON-RPC lines only (367.87725ms)
✔ integration: json-strict exec retries without emitting stderr notices (1378.293625ms)
✔ integration: fs/read_text_file through mock agent (384.842291ms)
✔ integration: --suppress-reads hides read file body in text format (434.45275ms)
✔ integration: --suppress-reads hides read file body in json format (503.942917ms)
✔ integration: fs/write_text_file through mock agent (416.160041ms)
✔ integration: fs/read_text_file outside cwd is denied (431.159875ms)
✔ integration: terminal lifecycle create/output/wait/release (626.6355ms)
✔ integration: terminal kill leaves no orphan sleep process (2923.886458ms)
✔ integration: prompt reuses warm queue owner and agent pid across turns (1103.948125ms)
✔ integration: config agent command with flags is split correctly and stores protocol version (351.409875ms)
✔ integration: prompt recovers when loadSession fails on empty session without emitting load error (1017.634791ms)
✔ integration: prompt retries stop after partial prompt output (797.515ms)
✔ integration: exec retries stop after partial prompt output (365.378625ms)
✔ integration: prompt recovers when loadSession returns not found without emitting load error (785.106708ms)
✔ integration: load replay session/update notifications are suppressed from output and event log (1007.07675ms)
✔ integration: cancel yields cancelled stopReason without queue error (958.960083ms)
✔ integration: prompt exits after done while detached owner stays warm (1060.503584ms)
✔ integration: session remains resumable after queue owner exits and agent has exited (2492.24925ms)
✔ buildJsonRpcErrorResponse preserves ACP payload when available (2.014084ms)
✔ buildJsonRpcErrorResponse shapes fallback ACPX metadata (0.357583ms)
✔ parseOptionalMcpServers returns undefined for missing values (0.512042ms)
✔ parseMcpServers parses http, sse, and stdio servers (0.773834ms)
✔ parseMcpServers rejects invalid top-level and entry fields (1.131417ms)
✔ parseMcpServers rejects invalid nested header, args, env, and meta values (0.15675ms)
✔ text formatter batches thought chunks from ACP notifications (1.953333ms)
✔ text formatter preserves line breaks in thought chunks (0.157542ms)
✔ text formatter renders tool call lifecycle from ACP updates (1.228541ms)
✔ json formatter passes through ACP messages (1.405792ms)
✔ json formatter emits ACP JSON-RPC error response from onError (0.84825ms)
✔ text formatter suppresses read output when requested (0.202666ms)
✔ json formatter suppresses read output when requested (0.206708ms)
✔ json formatter suppresses read-like tool updates inferred from title (0.144ms)
✔ json formatter leaves non-read tool updates unchanged with suppression enabled (0.071416ms)
✔ quiet formatter ignores suppress-reads and still outputs assistant text only (0.093292ms)
✔ quiet formatter outputs only agent text and flushes on prompt result (0.052834ms)
✔ incrementPerfCounter creates a new counter starting at 1 (0.688458ms)
✔ incrementPerfCounter accumulates multiple increments (0.102375ms)
✔ incrementPerfCounter accepts a custom delta (0.076959ms)
✔ setPerfGauge sets and overwrites gauge values (0.071041ms)
✔ recordPerfDuration tracks count, totalMs, and maxMs (0.12025ms)
✔ recordPerfDuration rounds values to 3 decimal places in snapshot (0.071375ms)
✔ measurePerf records duration of an async function (20.979041ms)
✔ measurePerf records duration even when the function throws (0.340375ms)
✔ startPerfTimer returns a stop function that records elapsed time (0.101875ms)
✔ getPerfMetricsSnapshot returns empty maps after reset (0.509833ms)
✔ getPerfMetricsSnapshot isolates counters, gauges, and timings (0.083959ms)
✔ formatPerfMetric formats name and duration with 3 decimal places (0.0565ms)
✔ promptForPermission returns false when stdin or stderr is not a TTY (0.904708ms)
✔ promptForPermission writes header/details and accepts yes answers (0.698167ms)
✔ promptForPermission rejects non-yes answers and skips blank details (0.146625ms)
✔ approve-all approves everything (1.248125ms)
✔ deny-all denies everything (0.109458ms)
✔ approve-reads approves reads and denies writes (0.996208ms)
✔ non-interactive policy fail throws when prompt is required (0.87725ms)
✔ approve-all falls back to the first option when no allow option exists (0.169542ms)
✔ deny-all cancels when no reject option exists (0.071084ms)
✔ approve-reads infers read-like titles without an explicit tool kind (0.405084ms)
✔ approve-reads rejects non-read title inference when prompting is unavailable (0.256959ms)
✔ approve-reads prompts interactively for non-read tools (0.48725ms)
✔ classifyPermissionDecision maps selected outcomes to approved, denied, or cancelled (0.193875ms)
✔ serialized session record satisfies persisted key policy (1.576ms)
✔ persisted key policy rejects camelCase acpx-owned keys (0.518375ms)
✔ selectLocalCodexReviewText prefers stdout when present (0.498084ms)
✔ selectLocalCodexReviewText extracts the codex tail from stderr logs (0.359958ms)
✔ extractCodexReviewTail falls back to the final non-log block (0.241084ms)
✔ fix_ci_failures owns CI monitoring until a terminal state (2.953958ms)
✔ human handoff is split into ready-for-landing and needs-judgment lanes (0.669417ms)
✔ maintenance PRs stay on the feature path without adding a new flow node (1.529417ms)
✔ validation stays in ACP nodes instead of hardcoded runtime helpers (0.621333ms)
✔ judge_refactor asks whether anything should be added removed simplified or refactored (0.377416ms)
✔ pr-triage configures a descriptive run title from repo and PR number (0.410292ms)
✔ parsePromptSource accepts valid image blocks (2.399041ms)
✔ parsePromptSource rejects image blocks with non-image mime types (1.90675ms)
✔ parsePromptSource rejects image blocks with invalid base64 payloads (0.194916ms)
✔ parsePromptSource keeps non-JSON bracket text as plain text (0.11425ms)
✔ parsePromptSource accepts resource and resource_link blocks (0.146667ms)
✔ parsePromptSource rejects invalid text and resource block shapes (0.138542ms)
✔ parsePromptSource returns an empty prompt for blank input (0.061375ms)
✔ mergePromptSourceWithText appends or creates prompt text (0.083459ms)
✔ promptToDisplayText renders text, resources, and images (0.148ms)
✔ isRetryablePromptError returns true for ACP internal error (-32603) (1.045833ms)
✔ isRetryablePromptError returns true for ACP parse error (-32700) (0.072167ms)
✔ isRetryablePromptError returns true for wrapped ACP internal error (0.33075ms)
✔ isRetryablePromptError returns false for auth-required error (-32000) (0.211ms)
✔ isRetryablePromptError returns false for method-not-found error (-32601) (0.118958ms)
✔ isRetryablePromptError returns false for invalid-params error (-32602) (0.092459ms)
✔ isRetryablePromptError returns false for resource-not-found error (-32002) (0.09475ms)
✔ isRetryablePromptError returns false for PermissionDeniedError (0.168084ms)
✔ isRetryablePromptError returns false for PermissionPromptUnavailableError (2.741375ms)
✔ isRetryablePromptError returns false for TimeoutError (0.083917ms)
✔ isRetryablePromptError returns false for non-ACP errors (0.053083ms)
✔ isRetryablePromptError returns false for null/undefined (0.036875ms)
✔ isRetryablePromptError returns false for auth message in -32603 error (0.040334ms)
✔ runSessionSetModeDirect resumes a load-capable session and closes the client once (656.322708ms)
✔ runSessionSetConfigOptionDirect falls back to createSession and returns updated options (600.7235ms)
✔ runSessionSetModelDirect updates current and desired model (677.926125ms)
✔ trySubmitToRunningOwner propagates typed queue prompt errors (20.8925ms)
✔ trySetModeOnRunningOwner propagates typed queue control errors (6.648ms)
[acpx] requested session/set_config_option on owner pid 51342 for session control-config-success-session
✔ trySetConfigOptionOnRunningOwner returns the queue owner response (7.322125ms)
✔ trySubmitToRunningOwner surfaces protocol invalid JSON detail code (6.849209ms)
✔ trySubmitToRunningOwner surfaces disconnect-before-ack detail code (3.589208ms)
✔ trySubmitToRunningOwner rejects oversized queue messages (1567.452125ms)
✔ trySubmitToRunningOwner streams queued lifecycle and returns result (3.755709ms)
✔ SessionQueueOwner emits typed invalid request payload errors (3.519375ms)
✔ SessionQueueOwner emits typed shutdown errors for pending prompts (2.022ms)
✔ SessionQueueOwner rejects prompts when queue depth exceeds the configured limit (2.103667ms)
✔ trySubmitToRunningOwner clears stale owner lock on protocol mismatch (54.611333ms)
✔ probeQueueOwnerHealth clears stale dead owners even if a stray socket exists (15.498291ms)
✔ probeQueueOwnerHealth reports unavailable socket when pid is alive (114.443834ms)
✔ probeQueueOwnerHealth clears stale dead owner lock (6.75375ms)
✔ SessionQueueOwner handles control requests and nextTask timeouts (48.652459ms)
✔ SessionQueueOwner enqueues fire-and-forget prompts and rejects invalid owner generations (32.909625ms)
✔ cancelSessionPrompt sends cancel request to active queue owner (114.079083ms)
✔ readQueueOwnerRecord returns undefined for missing and malformed lock files (14.347583ms)
✔ tryAcquireQueueOwnerLease creates a lease that can be refreshed and released (7.7215ms)
✔ tryAcquireQueueOwnerLease clears stale dead owners and can acquire on retry (5.528333ms)
✔ readQueueOwnerStatus returns live owner details for a healthy owner (6.796625ms)
✔ ensureOwnerIsUsable cleans up stale live owners (54.698667ms)
✔ terminateProcess and terminateQueueOwnerForSession handle live and missing owners (55.60925ms)
✔ parseQueueRequest accepts submit_prompt with nonInteractivePermissions (1.035208ms)
✔ parseQueueRequest rejects invalid nonInteractivePermissions value (0.079583ms)
✔ parseQueueOwnerMessage accepts typed queue error payload (0.195666ms)
✔ parseQueueOwnerMessage rejects untyped queue error payload (0.076375ms)
✔ parseQueueRequest rejects invalid owner generation (0.044958ms)
✔ parseQueueRequest accepts control requests and explicit prompt blocks (0.155042ms)
✔ parseQueueRequest rejects invalid control and prompt payload shapes (0.314459ms)
✔ parseQueueOwnerMessage accepts structured non-error owner messages (2.365834ms)
✔ parseQueueOwnerMessage accepts result payloads and optional emitted-error flag (0.194834ms)
✔ parseQueueOwnerMessage rejects invalid structured owner message payloads (0.066916ms)
▶ parseQueueOwnerPayload
✔ parses valid payload (1.372875ms)
✔ rejects invalid payloads (0.610875ms)
✔ parseQueueOwnerPayload (3.344ms)
▶ runQueueOwnerFromEnv
✔ fails when payload env is missing (0.174667ms)
✔ runQueueOwnerFromEnv (0.23825ms)
▶ resolveQueueOwnerSpawnArgs
✔ prefers ACPX_QUEUE_OWNER_ARGS when provided (1.1195ms)
✔ returns and __queue-owner (4.952167ms)
✔ throws when argv lacks an entry path (1.014458ms)
✔ resolveQueueOwnerSpawnArgs (8.036958ms)
▶ sanitizeQueueOwnerExecArgv
✔ drops test runner coverage flags but keeps loader args (0.169ms)
✔ drops debugger flags from queue-owner exec args (0.06025ms)
✔ sanitizeQueueOwnerExecArgv (0.309917ms)
▶ buildQueueOwnerArgOverride
✔ returns null when no loader args remain after sanitization (0.109666ms)
✔ returns a serialized override when loader args are required (0.064917ms)
✔ buildQueueOwnerArgOverride (0.239083ms)
✔ queue path helpers derive stable lock and socket paths (0.846459ms)
✔ queueSocketPath stays short on unix even for long home paths (0.120375ms)
✔ SUPPRESSED_READ_OUTPUT is stable (0.507125ms)
✔ isReadLikeTool matches explicit read kind (0.088292ms)
✔ isReadLikeTool infers read-like titles (0.083583ms)
✔ isReadLikeTool rejects unrelated titles and blanks (0.052167ms)
✔ applyReplayPatch supports JSON Patch+ append for strings and arrays (1.134959ms)
✔ createReplayPatch normalizes string growth and array growth to JSON Patch+ append (10.264042ms)
✔ synthesizeLiveRunState replays bundled ACP events into a live current ACP attempt (3.9345ms)
✔ synthesizeLiveRunState replays only new session events beyond record.lastSeq (0.367542ms)
✔ replay viewer streams live sidebar and run patches over websocket (34.2575ms)
✔ computeResourceDelta falls back to a snapshot when patch generation throws (0.729875ms)
✔ computeResourceDelta produces a stable patch when recent runs reorder (0.438292ms)
✔ replay viewer refreshes runs snapshots after idle periods (13.555542ms)
✔ replay viewer streams selected-run ACP text as JSON Patch+ append updates (12.6695ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader bootstrap stays stable after recent-runs state updates (18.491292ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader ignores stale bootstrap results after a newer live runs snapshot (28.688ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader waits for recent runs instead of loading the bundled sample (4.987833ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader auto-loads the first recent run when the list becomes non-empty (9.15225ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader ignores stale recent-run loads when a newer live selection wins (7.206833ms)
react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer
✔ useRunBundleLoader resyncs runs when a live runs patch cannot be applied (7.285417ms)
✔ useRunBundleLoader resyncs the selected run when a live run patch cannot be applied (10.922084ms)
✔ listRunBundles returns newest valid bundles first (19.835666ms)
✔ listRunBundles prefers live status over stale run projections (8.472417ms)
✔ resolveRunBundleFilePath rejects traversal outside a run bundle (0.455625ms)
✔ readRequestedRunId returns the requested run query (0.648625ms)
✔ buildRunLocation preserves unrelated params and hash (0.203792ms)
✔ parseReplayViewerCliArgs defaults to start and supports control flags (1.16375ms)
✔ parseReplayViewerCliArgs rejects invalid flags (0.322959ms)
✔ replay viewer status and stop helpers report and stop a running server (108.375584ms)
✔ replay viewer CLI status prints running details (35.054625ms)
✔ replay viewer start rejects reusing a server for a different runs dir (21.100625ms)
✔ resolveSessionRenderState keeps live tool calls and results visible while a run is streaming (0.864166ms)
✔ resolveSessionRenderState replays tool calls before the step fully completes (0.7425ms)
✔ isPinnedToBottom treats near-bottom scroll positions as sticky (0.679875ms)
✔ isPinnedToBottom disables follow when the reader scrolls away from the bottom (0.087ms)
✔ isPinnedToBottom honors a custom threshold (1.110292ms)
✔ didUserScrollUp disables follow on small upward reader scrolls (0.067ms)
✔ selectAttemptView shapes ACP session content into readable conversation parts (2.292459ms)
✔ buildGraph infers start terminal and branch semantics across the full definition (1.668458ms)
✔ buildGraph applies playback progress to the active node during preview (0.481458ms)
✔ buildGraph renders the last completed terminal step as completed instead of active (2.521792ms)
✔ buildGraph pulls pre-terminal handoff chains toward the bottom automatically (1.318583ms)
✔ buildGraphLayout uses layered routing and sinks terminal chains (395.831833ms)
✔ selectAttemptView falls back to hidden payloads for unknown structured messages (1.426834ms)
✔ selectAttemptView summarizes encoded tool inputs and hidden tool results without text output (0.288375ms)
✔ selectAttemptView falls back to the latest visible ACP session for non-ACP steps (0.14275ms)
✔ revealConversationSlice progressively reveals tool calls before the full assistant turn completes (0.338667ms)
✔ revealConversationTranscript keeps prior session messages visible while streaming the current slice (0.287541ms)
✔ listSessionViews returns all run sessions and marks the current streaming source (9.856167ms)
✔ listSessionViews stays empty when the selected step has no ACP session source (0.16175ms)
✔ buildPlaybackTimeline and anchors support continuous preview with discrete snapping (0.180417ms)
✔ resolvePlaybackResumeMs wraps terminal selections back to the start (0.119042ms)
✔ playbackSelectionMs clamps the final discrete step to the true timeline end (0.053542ms)
✔ advancePlaybackPlayhead applies playback speed and clamps to the timeline end (0.056417ms)
✔ resolveSelectedStepIndexAfterBundleUpdate follows the live edge when new steps append (0.078167ms)
✔ resolveSelectedStepIndexAfterBundleUpdate preserves rewind position while a run grows (0.046542ms)
✔ format helpers keep replay labels stable (0.065542ms)
✔ deriveRunOutcomeView separates replay position from a failed run outcome (0.080875ms)
✔ deriveRunOutcomeView reports completed runs independently of replay position (0.045541ms)
✔ conversation model captures prompt, chunks, tool calls, and metadata (2.445ms)
✔ recordClientOperation keeps state and advances timestamp (0.100208ms)
✔ cloneSessionAcpxState preserves desired mode id (0.125875ms)
✔ listSessionEvents reads all configured stream segments (95.893417ms)
✔ SessionEventWriter stores actual segment_count and increments lastSeq (30.951208ms)
✔ listSessionEvents skips malformed NDJSON lines (12.68125ms)
✔ SessionEventWriter recovers stale stream lock files (18.410042ms)
✔ normalizeModeId trims valid values and drops blanks (0.95875ms)
✔ getDesiredModeId reads normalized desired_mode_id (0.121917ms)
✔ setDesiredModeId creates and clears acpx mode preference state (1.272875ms)
✔ SessionRecord allows optional closed and closedAt fields (1.559708ms)
✔ listSessions preserves acpx desired_mode_id (131.947458ms)
✔ listSessions preserves acpx session_options (5.176792ms)
✔ listSessions ignores unsupported conversation message shapes (8.070208ms)
✔ listSessions preserves lifecycle and conversation metadata (7.200125ms)
✔ listSessions preserves optional agentSessionId (6.130791ms)
✔ findSession and findSessionByDirectoryWalk resolve expected records (18.27275ms)
✔ writeSessionRecord maintains an index and listSessions rebuilds it when missing (11.079666ms)
✔ closeSession soft-closes and terminates matching process (60.319417ms)
✔ normalizeQueueOwnerTtlMs applies default and edge-case normalization (1.410542ms)
✔ withTimeout resolves when timeout is disabled (0.613375ms)
✔ withTimeout rejects with TimeoutError when promise takes too long (11.177833ms)
✔ withTimeout preserves the original rejection (0.435667ms)
✔ withInterrupt resolves normally without invoking interrupt cleanup (0.244208ms)
✔ withInterrupt rejects with InterruptedError on SIGINT and runs cleanup once (0.747291ms)
✔ withInterrupt rejects with InterruptedError on SIGTERM and removes signal listeners (0.379833ms)
✔ withInterrupt rejects with InterruptedError on SIGHUP (0.372375ms)
✔ buildAgentSpawnOptions hides Windows console windows and preserves auth env (1.662625ms)
✔ buildTerminalSpawnOptions hides Windows console windows and maps env entries (0.348625ms)
✔ buildQueueOwnerSpawnOptions hides Windows console windows and passes payload (0.161958ms)
✔ buildSpawnCommandOptions enables shell for .cmd/.bat on Windows (0.384167ms)
✔ buildSpawnCommandOptions enables shell for PATH-resolved .cmd wrappers on Windows (29.74025ms)
✔ buildSpawnCommandOptions keeps shell disabled for non-batch commands (2.904375ms)
✔ buildTerminalSpawnOptions enables shell for PATH-resolved .cmd wrappers on Windows (2.653416ms)
✔ buildTerminalSpawnOptions keeps shell disabled for non-batch commands (2.346792ms)
✔ terminal manager create/output/wait/release lifecycle (86.440084ms)
✔ terminal manager kill sends termination and process exits (14.725917ms)
✔ terminal manager prompts in approve-reads mode and can deny (4.864458ms)
✔ terminal manager fails when prompt is unavailable and policy is fail (4.116208ms)
✔ QueueOwnerTurnController tracks explicit lifecycle states (0.812166ms)
✔ QueueOwnerTurnController cancels immediately for active prompts (0.216ms)
✔ QueueOwnerTurnController defers cancel while turn is starting (0.148667ms)
✔ QueueOwnerTurnController routes setSessionMode through active controller (0.784584ms)
✔ QueueOwnerTurnController routes setSessionModel through active controller (0.180166ms)
✔ QueueOwnerTurnController routes setSessionConfigOption through fallback when inactive (0.134375ms)
✔ QueueOwnerTurnController rejects control requests while closing (0.584417ms)
✔ resolveAcpxVersion prefers npm_package_version from env when package name is acpx (0.604125ms)
✔ resolveAcpxVersion ignores npm_package_version from non-acpx package env (4.856292ms)
✔ resolveAcpxVersion reads version from package.json when env is unset (2.179084ms)
✔ resolveAcpxVersion falls back to unknown when version cannot be resolved (0.210708ms)
✔ resolveAcpxVersion ignores blank env versions and blank package versions (1.418583ms)
✔ getAcpxVersion caches the first resolved version (1.768042ms)
ℹ tests 478
ℹ suites 5
ℹ pass 478
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 42030.775666
ℹ Error: 82.24% line coverage does not meet threshold of 83%.
ℹ start of coverage report
ℹ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ℹ file | line % | branch % | funcs % | uncovered lines
ℹ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ℹ dist-test | | | |
ℹ examples | | | |
ℹ flows | | | |
ℹ pr-triage | | | |
ℹ review-text.js | 89.19 | 71.43 | 100.00 | 8-9 23-24
ℹ replay-viewer | | | |
ℹ server.js | 56.99 | 76.19 | 50.00 | 24-25 35-37 51-53 72-74 80-83 91-118 121-146 152-153 172-173 178-179 182-186
ℹ server | | | |
ℹ filesystem-bundle-reader.js | 85.71 | 100.00 | 75.00 | 19-21
ℹ live-run-state.js | 82.79 | 48.10 | 90.91 | 26-27 29-30 66-67 71-72 78-79 81 122-123 125-132 155-156 162-163 166-167 177-178 212 216-217 223-224 229-236
ℹ live-source.js | 100.00 | 100.00 | 100.00 |
ℹ live-sync.js | 72.87 | 71.25 | 87.50 | 55-61 65-70 73-74 82-84 92-95 97-101 114-115 128-135 139-141 168-171 184-190 201 214-215 234-240 249-250 264-271 274-287 330-331 351-353 365-366 368-369 371-372 377-378 381-387
ℹ run-bundles.js | 88.46 | 81.82 | 85.71 | 13-16 32 40-41 68-69
ℹ viewer-server.js | 67.86 | 65.00 | 73.91 | 52-63 66-71 82-83 97-98 119-149 160-161 188-189 199-201 213-224
ℹ src | | | |
ℹ hooks | | | |
ℹ use-playback-controller.js | 21.05 | 78.57 | 60.00 | 6-133 151-153 156-157 159-160
ℹ use-run-bundle-loader.js | 76.83 | 71.79 | 90.00 | 54-58 76-80 85-86 88-89 105-109 149-150 176-182 194-200 209-210 227-232 235 244-246 257-263 267-268 276-286 288-291 300-301 304 312-313
ℹ use-sticky-auto-follow.js | 9.64 | 100.00 | 66.67 | 9-83
ℹ lib | | | |
ℹ bundle-reader.js | 6.67 | 100.00 | 0.00 | 2-19 21-42 44-45 47-74 76-77 79-90
ℹ json-patch-plus.js | 82.32 | 78.43 | 100.00 | 59 65-66 74 78-79 81-82 106-107 113-114 117-127 129-130 136-137 150-151
ℹ live-sync.js | 100.00 | 66.67 | 100.00 |
ℹ load-bundle.js | 86.79 | 100.00 | 62.50 | 47-53
ℹ run-state.js | 85.71 | 75.00 | 100.00 | 3-4
ℹ run-url.js | 100.00 | 87.50 | 100.00 |
ℹ runs-state.js | 100.00 | 85.71 | 100.00 |
ℹ session-render-state.js | 78.26 | 80.00 | 100.00 | 18-22
ℹ view-model-conversation.js | 81.15 | 70.51 | 95.56 | 4-5 53-54 59-60 62-63 71-72 75-78 80-81 99-100 131 168-169 209 211 233-241 266-272 295-301 303-310 334 356 360-362 380-381 383-384 397 429-430 432 441-442 448-451 456-457 464-475 477-480 487
ℹ view-model-format.js | 66.67 | 83.33 | 80.00 | 9-10 24-26 29-36
ℹ view-model-graph.js | 89.83 | 76.17 | 100.00 | 137-147 149-163 165-174 261-262 274-275 324 326 328 330 342-343 345-346 348-349 388-389 471-473 477-478 492-495 526-527 540-541 555-556 598-599 619-620
ℹ view-model-playback.js | 95.60 | 72.41 | 90.91 | 24-25 57-58
ℹ view-model.js | 100.00 | 100.00 | 100.00 |
ℹ src | | | |
ℹ acp-error-shapes.js | 91.06 | 91.89 | 90.00 | 17-18 27-28 70-71 73 92-93 98-99
ℹ acp-jsonrpc.js | 85.71 | 85.48 | 100.00 | 3-4 26-27 51-52 55 71-72 75-76 79-80 92-93
ℹ agent-registry.js | 100.00 | 100.00 | 100.00 |
ℹ agent-session-id.js | 100.00 | 93.33 | 100.00 |
ℹ cli-core.js | 82.43 | 74.42 | 88.31 | 53-54 62-63 66-67 74-75 114-117 174-176 179-180 247-249 263-267 281-283 299-303 346-347 366-367 392-393 419-423 438-442 463-465 500-506 512-521 527-528 535-536 550-551 561-588 593-601 603-607 610-612 617-632 643-646 660 690 810-811 821-823 848-849 859 872-877 879-880 889-890 902-906 914-915 920-921 938-939 971-974 977-982 1001 1004 1021-1028
ℹ cli.js | 79.31 | 40.00 | 100.00 | 10-11 15-16 24-25
ℹ cli | | | |
ℹ config-command.js | 31.15 | 100.00 | 16.67 | 3-41 50 56 59
ℹ flags.js | 90.29 | 71.70 | 100.00 | 11-12 30-31 44-45 51-52 58-59 83-84 90-91 133-134 144-145 195-196
ℹ json-output.js | 100.00 | 100.00 | 100.00 |
ℹ output-render.js | 76.06 | 60.00 | 91.67 | 11-12 31-38 50-51 67-69 71-73 87-90 95-106
ℹ status-command.js | 73.45 | 41.67 | 100.00 | 8-9 12-13 32-52 88-90 93-94
ℹ client.js | 90.11 | 81.04 | 92.59 | 35-36 45 73-74 84 88-89 110-113 115-117 141-142 144-145 150-151 190-191 198-199 205-206 295 299-300 304-305 332-333 342-343 351 354 386-387 396-397 405 408 517-518 523-524 526-527 536 647-648 709-710 712-713 742 752 811-812 830-831 934-936 952-953 1007 1010-1013 1020-1025 1043-1045 1047-1048 1073-1080 1102-1103 1107-1114 1116-1124 1136-1142 1146-1147 1154 1169-1174 1187-1189 1217-1218 1269-1270 1380-1382 1394
ℹ codex-compat.js | 35.00 | 66.67 | 33.33 | 2-7 9-14 19
ℹ config.js | 82.75 | 86.15 | 95.00 | 39-40 48-50 57-58 66-67 76-77 85-86 94-95 103-104 112-113 117-118 121-122 132-133 137-138 160-164 166-167 223-224 265-282
ℹ error-normalization.js | 88.18 | 85.87 | 100.00 | 14-15 35-42 44-46 48-50 61-62 99-100 113-114 134-135
ℹ errors.js | 94.78 | 96.00 | 93.75 | 86-92
ℹ filesystem.js | 91.67 | 77.27 | 93.33 | 20-21 23-24 27-33 136-137 164-165
ℹ flows.js | 100.00 | 100.00 | 100.00 |
ℹ flows | | | |
ℹ authoring.js | 88.89 | 75.00 | 100.00 | 4-5
ℹ cli.js | 83.57 | 64.52 | 100.00 | 54-55 68-69 99-100 108-109 122-123 127 161-162 186-206
ℹ definition.js | 100.00 | 100.00 | 100.00 |
ℹ executors | | | |
ℹ shell.js | 96.34 | 85.71 | 90.00 | 62-63 70
ℹ graph.js | 79.31 | 71.11 | 100.00 | 5-6 39-40 43-44 53-54 57-58 61-62 70-71 76-77 83-84
ℹ json.js | 90.65 | 81.25 | 100.00 | 6-7 29 76-77 79-80 99-100 106
ℹ runtime.js | 93.74 | 77.55 | 84.93 | 88-89 245-246 283-285 398-399 570-571 584-586 609-610 620-627 637-638 662 772-773 776-777 785 794-796 830 861-862 865-866 887-888 894-895 1007-1008 1028-1032 1035-1036 1041-1042 1053-1055 1057-1062 1071-1073 1079
ℹ schema.js | 100.00 | 100.00 | 100.00 |
ℹ store.js | 92.05 | 91.01 | 100.00 | 202-224 333-334 369-370 372-373 381-382
ℹ jsonrpc-error.js | 100.00 | 86.67 | 100.00 |
ℹ mcp-servers.js | 91.22 | 87.04 | 100.00 | 18-19 24-25 40-41 56-57 62-63 88-89 130
ℹ output-json-formatter.js | 92.09 | 80.00 | 100.00 | 6-7 22-23 31-32 48-49 123-124 138-139 146-147
ℹ output.js | 72.73 | 65.24 | 89.23 | 29 31 35 37 42-43 61-64 80-81 92-93 95-96 98-99 102-103 110-111 139-140 144-145 166-169 171 178-198 200-231 236-257 261-262 268-269 271-272 274-281 284-285 287-288 304 306-308 317-318 330-331 336-338 340-341 384-389 418-424 426 435-438 450-452 457-458 462-463 482-483 513-514 541-542 550-551 576-577 593-594 605 617-619 621 626 659-660 677-680
ℹ perf-metrics-capture.js | 88.54 | 72.22 | 88.89 | 49-51 75-76 91-96
ℹ perf-metrics.js | 100.00 | 100.00 | 100.00 |
ℹ permission-prompt.js | 100.00 | 100.00 | 100.00 |
ℹ permissions.js | 92.37 | 87.67 | 100.00 | 33-34 59 80-81 107-108 114-116
ℹ persisted-key-policy.js | 97.53 | 96.97 | 100.00 | 43-44
ℹ prompt-content.js | 91.98 | 85.92 | 100.00 | 9-10 47-48 64-65 73-74 79-80 84 105 135-136 181
ℹ queue-ipc-health.js | 95.92 | 83.33 | 100.00 | 36-37
ℹ queue-ipc-server.js | 82.46 | 88.06 | 88.57 | 18-35 38-39 72-73 87-88 112-113 141-148 184-187 198-203 217-218 267-280
ℹ queue-ipc-transport.js | 78.13 | 66.67 | 87.50 | 16-21 25-26 34-35 55-56 61-62
ℹ queue-ipc.js | 64.02 | 72.22 | 84.38 | 24 28-29 38-43 71-72 78-79 89-90 100-101 148 152-153 185-191 223-229 239-243 254-267 287-293 295-301 305-317 329-330 332-337 349-359 361-381 393-394 396-401 427-428 431-439 449-450 453-461 469-483 490-505 519-527
ℹ queue-lease-store.js | 88.63 | 86.57 | 76.92 | 8-9 42-43 55-56 74 80 83-85 119-120 124-131 141 150-151 187 209 233 237-238
ℹ queue-messages.js | 85.71 | 88.81 | 90.91 | 13-15 31-32 34-35 57-58 71 127-137 154 159-160 169-170 176-177 191-192 198-199 201-202 260-269
ℹ queue-owner-env.js | 91.18 | 76.92 | 75.00 | 5-6 13-14 57-58
ℹ queue-owner-turn-controller.js | 96.04 | 87.88 | 94.74 | 82 91 97-98
ℹ queue-paths.js | 85.71 | 70.00 | 100.00 | 15-16 25-26
ℹ read-output-suppression.js | 90.48 | 93.75 | 100.00 | 9-10
ℹ runtime-session-id.js | 100.00 | 100.00 | 100.00 |
ℹ session-conversation-model.js | 76.64 | 64.67 | 97.67 | 16-17 24-25 33-42 50-80 117-118 131-132 135-137 150 154-155 166-167 173-174 180-181 183 187-188 193-194 233-234 262-263 273 280-281 300-301 314 327-328 360-383 390-391 401 413-423 477-479 481 495-496 506 533-534
ℹ session-event-log.js | 100.00 | 100.00 | 100.00 |
ℹ session-events.js | 83.96 | 69.84 | 83.33 | 30-41 51-53 60-61 79-80 88-89 101-102 108-112 139 146-148 197-198 200-201 206-207 239-240 243-247 250-251
ℹ session-mode-preference.js | 87.84 | 81.82 | 100.00 | 42-44 50-52 61-63
ℹ session-persistence.js | 100.00 | 100.00 | 100.00 |
ℹ session-persistence | | | |
ℹ index.js | 89.55 | 83.33 | 100.00 | 7-8 14-15 23-24 26-27 61-62 65-66 71-72
ℹ parse.js | 68.22 | 68.07 | 80.77 | 10-12 18-19 22-23 37-40 45-46 49-50 53-58 61-75 79-80 84-91 93-125 129-130 134-148 168-169 172-173 186-187 191-192 210-211 222-223 225-226 250-251 262-263 280-281 290-291 296-297 316 328 333-334 336-337 367-368 376-377
ℹ repository.js | 78.66 | 80.88 | 74.36 | 28-29 43-44 88-89 91-92 96-97 99-100 132-133 198-199 202-203 206-215 217-239
ℹ serialize.js | 100.00 | 100.00 | 100.00 |
ℹ session-runtime-helpers.js | 100.00 | 100.00 | 100.00 |
ℹ session-runtime.js | 75.84 | 70.29 | 63.27 | 33 35-42 64-65 81-82 104-114 121 124 127 130 133-203 218-219 254-275 304-305 374 377 380 425-426 443-446 452-453 464-476 481-488 493 526-536 541-542 557 560 648-649 751 785-796 839-840 863-872 875-884 887-898 906-908 930-935 938 941 944 951 956-957 959 962-964 1008 1020-1021 1038 1070-1077 1092-1100 1115-1125 1141-1142 1149-1150 1154-1162
ℹ session-runtime | | | |
ℹ connect-load.js | 93.99 | 91.49 | 100.00 | 13-14 26-27 53-59
ℹ lifecycle.js | 100.00 | 100.00 | 100.00 |
ℹ prompt-runner.js | 93.68 | 88.89 | 72.22 | 46 84-90 100 163-164
ℹ queue-owner-process.js | 100.00 | 100.00 | 100.00 |
ℹ session.js | 100.00 | 100.00 | 100.00 |
ℹ spawn-command-options.js | 88.89 | 86.67 | 100.00 | 22-23 27-28 35-36
ℹ terminal.js | 78.26 | 76.62 | 83.33 | 35-50 58-59 65-69 133-134 137-139 200-201 215-216 235-244 256-264 268 281-290 294-295 308-309 328-329 337-343
ℹ types.js | 100.00 | 100.00 | 100.00 |
ℹ version.js | 50.91 | 50.00 | 60.00 | 9-10 14-36 45-46
ℹ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ℹ all files | 82.24 | 78.31 | 88.08 |
ℹ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ℹ end of coverage report
 ELIFECYCLE  Command failed with exit code 1.
 ELIFECYCLE  Command failed with exit code 1. passed all checks except the known local Node 24 coverage threshold failure (82.24% vs 83%) while PR CI was green.\n- Land commit: \n- Merge commit: \n\nThanks @osolmaz!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant