cas (Zig App-Server Control)
Overview
$cas is Zig-only in this repo.
Use the native cas dispatcher and subcommands:
cas conformance for swarm conformance checks around $st claims, $mesh reconciliation, and retry policy.
cas smoke_check for protocol/API smoke checks.
cas instance_runner for method execution across one or many isolated instances.
cas review_session for detached review/start lifecycle control with persisted reviewThreadId handles.
run_cas_tool request (helper alias) for single-request flows via instance_runner --instances 1.
Current cas smoke_check verifies the native client can complete the v2 handshake and reach experimentalFeature/list, thread/start, thread/resume, and turn/steer.
Current cas conformance covers these swarm-hardening scenarios:
claim_safe_wave: verify two disjoint $st claims can run in parallel without overlapping lock roots
stale_claim_reclaim: verify expired held claims become stale and return to pending
mesh_row_accountability: verify imported mesh output completes only reported rows and leaves missing rows outstanding
overload_backoff: verify the bounded retry/backoff policy with a deterministic synthetic overload script
cas conformance is the harness; it is not the owner of durable claims or mesh state. $st remains the source of truth for claims/runtime/proof metadata.
Current cas review_session is the review-control lane:
start launches detached review/start on a supplied or freshly created parent thread
start supports --parent-mode auto|fresh|reuse; reuse rejects unsafe or unmaterialized parent threads, and fresh-parent startup retries once after a bootstrap materialization turn when the installed codex needs it
wait is the primary completion path only on runtimes that keep detached review alive across connections
- On Codex
0.118.x over stdio, detached review output is connection-scoped, so start --wait is the supported detached-result lane and split fresh-process start/wait should fail closed until CAS has a websocket-backed transport
status reads the detached review thread from a fresh CAS process when that runtime path is supported
interrupt sends turn/interrupt for the persisted detached review turn
reviewThreadId is the recoverable handle. Session records live under ~/.codex/cas/review_sessions/, and CAS appends raw request/response artifacts to a per-review NDJSON log beside that record.
Review boundary:
- Use
cas review_session when you need detached lifecycle control: persisted reviewThreadId, explicit interrupt, compatibility diagnostics, or approval/runtime overrides on the detached lane. On Codex 0.118.x stdio, same-process start --wait is the supported review-result path; fresh-process polling is not.
- If you only need a one-shot git-backed review verdict and do not need detached control, prefer native
codex review --base ... or codex review --commit ... instead of introducing CAS transport risk. First-party caller flows such as $fix should treat native review as the default path.
cas smoke_check is never review proof; it only proves handshake/method reachability.
cas instance_runner is never the production review lane; it is for method probing and schema sanity checks.
When start, start --wait, status, or wait emit JSON, the output includes the detached review handle/result fields plus launch compatibility metadata:
resolvedCodexPath
resolvedCodexVersion
compatibilityVerdict
failureCode
failureHint
reviewResultAvailable
reviewResultSource
reviewResult
findings
overallCorrectness
overallExplanation
overallConfidenceScore
fallbackUsed
fallbackTransport
fallbackExitCode
fallbackOutputText
fallbackErrorText
Use the fields this way:
compatibilityVerdict="compatible" means the detached review launch path succeeded under the resolved codex binary
compatibilityVerdict="incompatible" means CAS identified a detached-review runtime mismatch and failed closed
compatibilityVerdict="not_checked" means no compatibility verdict was persisted for that record yet (older session record or pre-launch failure)
failureCode="wait_timed_out" means retry cas review_session wait on the same reviewThreadId or increase --timeout-ms; it is not a successful review
failureCode="review_interrupted" means the detached review was interrupted before it emitted a structured review result
failureCode="approval_denied" means the detached review stopped on an approval or permissions denial before it emitted a structured review result
failureCode="review_failed" means the detached review failed or errored before it emitted a structured review result
failureCode="review_output_missing" means the detached review reached terminal state without a structured review result even though it was not classified as an interrupt or approval failure
failureCode="parent_thread_not_materialized" or failureCode="unsafe_parent_thread_state" means the supplied parent thread is not safe to reuse for detached review
fallbackUsed=true means --fallback native-review ran codex review and returned its raw text output instead of a structured detached-review result
Review result classification:
- Detached review success requires all of:
compatibilityVerdict="compatible", fallbackUsed=false, reviewResultAvailable=true, and no blocking failureCode.
- Native-fallback success is a different class of result:
fallbackUsed=true means the review text came from native codex review, not detached CAS review. Report it as native fallback, not detached-review proof.
- Transport progress is not review success:
reviewThreadId creation, start --wait returning, or status showing a terminal turn is insufficient unless the result fields above classify it as success.
Compatibility note: on Codex 0.118.x stdio, detached review requires two compatibility moves. First, a fresh parent thread must be materialized before detached review/start, so CAS --parent-mode auto now pre-materializes that path and fresh retries once after bootstrap materialization when needed. Second, detached review output streams on the live app-server connection, so split fresh-process start/wait should fail closed; use start --wait, native codex review, or a future websocket-backed CAS lane.
Node runtime paths (cas_proxy.mjs, cas_client.mjs, and related wrappers) are removed from this skill and must not be used.
This skill assumes codex is available on PATH and does not require access to any repo source tree.
Zig CLI Iteration Repos
When iterating on the Zig-backed cas helper CLI path, use these two repos:
skills-zig (/Users/tk/workspace/tk/skills-zig): source for the cas Zig binaries, build/test wiring, and release tags.
homebrew-tap (/Users/tk/workspace/tk/homebrew-tap): Homebrew formula updates/checksum bumps for released cas binaries.
Quick Start
run_cas_tool() {
local subcommand="${1:-}"
if [ -z "$subcommand" ]; then
echo "usage: run_cas_tool <conformance|conformance-suite|smoke-check|smoke_check|instance-runner|instance_runner|review-session|review_session|request> [args...]" >&2
return 2
fi
shift || true
local cas_subcommand=""
local marker=""
local -a pre_args=()
case "$subcommand" in
conformance|conformance-suite|conformance_suite)
cas_subcommand="conformance"
marker="cas_conformance_suite.zig"
;;
smoke-check|smoke_check)
cas_subcommand="smoke_check"
marker="cas_smoke_check.zig"
;;
instance-runner|instance_runner)
cas_subcommand="instance_runner"
marker="cas_instance_runner.zig"
;;
review-session|review_session)
cas_subcommand="review_session"
marker="cas_review_session.zig"
;;
request)
cas_subcommand="instance_runner"
marker="cas_instance_runner.zig"
pre_args=(--instances 1 --sample 1)
;;
*)
echo "unknown cas subcommand: $subcommand" >&2
return 2
;;
esac
install_cas_direct() {
local repo="${SKILLS_ZIG_REPO:-$HOME/workspace/tk/skills-zig}"
if ! command -v zig >/dev/null 2>&1; then
echo "zig not found. Install Zig from https://ziglang.org/download/ and retry." >&2
return 1
fi
if [ ! -d "$repo" ]; then
echo "skills-zig repo not found at $repo." >&2
echo "clone it with: git clone https://github.com/tkersey/skills-zig \"$repo\"" >&2
return 1
fi
if ! (cd "$repo" && zig build -Doptimize=ReleaseSafe); then
echo "direct Zig build failed in $repo." >&2
return 1
fi
if [ ! -x "$repo/zig-out/bin/cas" ] || [ ! -x "$repo/zig-out/bin/cas_review_session" ] || [ ! -x "$repo/zig-out/bin/cas_smoke_check" ] || [ ! -x "$repo/zig-out/bin/cas_instance_runner" ] || [ ! -x "$repo/zig-out/bin/cas_conformance_suite" ]; then
echo "direct Zig build did not produce the full CAS binary set in $repo/zig-out/bin." >&2
return 1
fi
mkdir -p "$HOME/.local/bin"
install -m 0755 "$repo/zig-out/bin/cas" "$HOME/.local/bin/cas"
install -m 0755 "$repo/zig-out/bin/cas_review_session" "$HOME/.local/bin/cas_review_session"
install -m 0755 "$repo/zig-out/bin/cas_smoke_check" "$HOME/.local/bin/cas_smoke_check"
install -m 0755 "$repo/zig-out/bin/cas_instance_runner" "$HOME/.local/bin/cas_instance_runner"
install -m 0755 "$repo/zig-out/bin/cas_conformance_suite" "$HOME/.local/bin/cas_conformance_suite"
}
local os="$(uname -s)"
if command -v cas >/dev/null 2>&1 && cas --help 2>&1 | grep -q "cas.zig"; then
if cas "$cas_subcommand" --help 2>&1 | grep -q "$marker"; then
cas "$cas_subcommand" "${pre_args[@]}" "$@"
return
fi
echo "cas binary found, but marker check failed for subcommand: $cas_subcommand" >&2
return 1
fi
if [ "$os" = "Darwin" ]; then
if ! command -v brew >/dev/null 2>&1; then
echo "homebrew is required on macOS: https://brew.sh/" >&2
return 1
fi
if ! brew install tkersey/tap/cas; then
echo "brew install tkersey/tap/cas failed." >&2
return 1
fi
elif ! (command -v cas >/dev/null 2>&1 && cas --help 2>&1 | grep -q "cas.zig"); then
if ! install_cas_direct; then
return 1
fi
fi
if command -v cas >/dev/null 2>&1 && cas --help 2>&1 | grep -q "cas.zig"; then
if cas "$cas_subcommand" --help 2>&1 | grep -q "$marker"; then
cas "$cas_subcommand" "${pre_args[@]}" "$@"
return
fi
echo "cas binary found, but marker check failed for subcommand: $cas_subcommand" >&2
return 1
fi
echo "cas binary missing or incompatible after install attempt." >&2
if [ "$os" = "Darwin" ]; then
echo "expected install path: brew install tkersey/tap/cas" >&2
else
echo "expected direct path: SKILLS_ZIG_REPO=<skills-zig-path> zig build -Doptimize=ReleaseSafe" >&2
fi
return 1
}
run_cas_tool smoke-check --cwd /path/to/workspace --json
run_cas_tool review-session start --cwd /path/to/workspace --uncommitted --json
Terminology (Instances)
- An "instance" is one
cas_proxy_client-managed codex app-server child process.
- Each instance executes one request path with isolated client metadata and optional state-file isolation.
- "N instances" means N parallel client+app-server pairs in
cas instance_runner.
Trigger Cues
- "instances" / "multi-instance" / "parallel sessions"
- "review session" / "detached review" / "reviewThreadId" / "interrupt review"
- "swarm conformance" / "claim-safe wave" / "stale-claim reclaim" / "mesh row accountability"
- app-server method checks (
thread/start, thread/resume, thread/fork, thread/read, thread/list, thread/archive, thread/unarchive, thread/rollback, turn/start, turn/steer, turn/interrupt, review/start)
- command/file approval behavior, especially
availableDecisions
- session mining through direct app-server method execution
- protocol sanity checks before orchestration
Workflow
Validate basic app-server wiring first.
run_cas_tool smoke-check --cwd /path/to/workspace --json
- Treat this as a protocol preflight before any fanout run.
Use review_session when the real job is detached review lifecycle control rather than one-shot probing.
- Default decision rule:
- Need detached control on Codex
0.118.x stdio: use cas review_session start --wait.
- Need detached control on a runtime that keeps detached review alive across connections: use
cas review_session split start plus wait.
- Need only a one-shot git-backed verdict: use native
codex review unless the caller explicitly needs detached control. $fix-style repair loops should not CAS-first by default.
- Start detached review:
cas review_session start --cwd /path/to/workspace --uncommitted --json
cas review_session start --cwd /path/to/workspace --base main --json
cas review_session start --cwd /path/to/workspace --parent-thread-id <threadId> --parent-mode reuse --base main --json
cas review_session start --cwd /path/to/workspace --commit <sha> --title "<subject>" --json
cas review_session start --cwd /path/to/workspace --custom-instructions @review.txt --json
cas review_session start --wait --cwd /path/to/workspace --base main --fallback native-review --json
- Read current status from a fresh process when the runtime supports detached polling:
cas review_session status --review-thread-id <reviewThreadId> --json
- Wait for the detached review turn to settle when the runtime supports detached polling:
cas review_session wait --review-thread-id <reviewThreadId> --timeout-ms 300000 --json
- Supported same-process lane on Codex
0.118.x stdio:
cas review_session start --wait --cwd /path/to/workspace --base main --json
- Interrupt the detached review turn:
cas review_session interrupt --review-thread-id <reviewThreadId> --json
reviewThreadId is the handle; do not invent a second review session id.
- Review hygiene:
- On Codex
0.118.x stdio, prefer start --wait ... --json when the detached verdict matters; that is the supported lane because review items stream on the live connection.
- On runtimes that keep detached review alive across connections, prefer
start ... --json followed by wait ... --json when the verdict matters; it leaves a recoverable handle if wait times out or the process dies.
- In first-party caller workflows, treat one detached CAS attempt as one
start plus any wait retries on the returned reviewThreadId, keyed by the frozen review target plus resolved Codex path/version. If that attempt returns incompatible_codex_review_runtime, stop relaunching detached CAS for the same key in that run and let the caller decide whether to switch to native codex review.
- Reuse a parent thread only with
--parent-mode reuse plus a known materialized parent; otherwise let CAS choose auto or force fresh.
- Treat
reviewResultAvailable, compatibilityVerdict, fallbackUsed, and failureCode as the verdict surface. Do not infer success from process exit alone.
Detached review is the public review-control path; do not route review-session control through instance_runner.
instance_runner remains a method probe lane and is still useful for schema sanity checks.
review_session owns persisted review handles, fresh-process status polling, wait loops, and interruption.
- For workflows that need the actual review verdict, use the live connection lane the runtime supports:
start --wait on Codex 0.118.x stdio, or split start ... --json then wait ... --json on runtimes that keep detached review alive across connections.
- Treat
failureCode as authoritative. CAS never silently falls back to native codex review; callers that want a temporary fallback must do it explicitly at their own layer.
For swarm-hardening runs, treat $st as the durable source of truth before any worker starts.
st import-orchplan --file .step/st-plan.jsonl --input .step/orchplan.yaml
st claim --file .step/st-plan.jsonl --wave w1 --executor teams
- CAS probes the wave; it does not replace the durable claim ledger.
Enforce handshake assumptions when diagnosing failures.
- Confirm the session completed
initialize then initialized before method calls.
- If you see
"Not initialized" or "Already initialized", treat it as connection-lifecycle error, not a method payload error.
Run one direct method request (single-request lane).
run_cas_tool request --cwd /path/to/workspace --method thread/start --params-json '{"cwd":"/path/to/workspace","experimentalRawEvents":false}' --json
Run fanout/multi-instance requests.
run_cas_tool instance-runner --cwd /path/to/workspace --instances 12 --method thread/list --params-json '{"cursor":null,"limit":1}' --json
Run the conformance suite when you need repeatable swarm checks around claims, mesh closeout, or retry policy.
cas conformance --cwd /path/to/workspace --json
- Narrow to one scenario when debugging:
cas conformance --cwd /path/to/workspace --scenario mesh_row_accountability --json
- Use
--skip-smoke-check only when you intentionally want the local $st/mesh scenarios without the live CAS preflight.
Apply overload handling on request saturation.
- If app-server returns JSON-RPC error code
-32001 ("Server overloaded; retry later."), retry with exponential backoff and jitter.
- Do not treat
-32001 as a permanent protocol mismatch.
- In
cas conformance, the retry policy scenario is currently synthetic and should be treated as retry-policy proof, not live saturation proof.
Drive specific thread/turn methods as needed.
- Start thread:
run_cas_tool request --cwd /path/to/workspace --method thread/start --params-json '{"cwd":"/path/to/workspace","experimentalRawEvents":false}' --json
- Start turn:
run_cas_tool request --cwd /path/to/workspace --method turn/start --params-json '{"threadId":"thr_123","input":[{"type":"text","text":"summarize the repo status"}]}' --json
- Thread read:
run_cas_tool request --cwd /path/to/workspace --method thread/read --params-json '{"threadId":"thr_123","includeTurns":true}' --json
- Resume thread:
run_cas_tool request --cwd /path/to/workspace --method thread/resume --params-json '{"threadId":"thr_123"}' --json
- Steer turn:
run_cas_tool request --cwd /path/to/workspace --method turn/steer --params-json '{"threadId":"thr_123","expectedTurnId":"turn_abc","input":[{"type":"text","text":"continue"}]}' --json
- Interrupt turn:
run_cas_tool request --cwd /path/to/workspace --method turn/interrupt --params-json '{"threadId":"thr_123","turnId":"turn_abc"}' --json
- Use method-specific params for list/mine flows.
thread/list supports filter params (cursor, limit, searchTerm, cwd, etc.) as provided by your app-server version.
turn/steer requires expectedTurnId.
After a mesh batch, reconcile the exported CSV back into $st.
st import-mesh-results --file .step/st-plan.jsonl --input .step/mesh-output.csv
- CAS may validate the wave around that closeout, but it does not own the CSV reconciliation.
Gate experimental methods and payload fields explicitly.
- Experimental surfaces such as
thread/backgroundTerminals/clean, thread/realtime/*, and thread/start dynamic-tool fields require initialize.params.capabilities.experimentalApi = true.
- If omitted, treat failures as capability negotiation errors.
- Respect native CAS server-request limits.
- The current Zig client auto-answers
item/commandExecution/requestApproval, item/fileChange/requestApproval, item/permissions/requestApproval, item/tool/requestUserInput, mcpServer/elicitation/request, and item/tool/call.
- Default native behavior is conservative: permissions requests are denied, request-user-input questions use the first option label when present, MCP elicitations are declined, and dynamic tool calls return
success: false unless you override with explicit CLI flags.
Approval and Request Semantics
- Exec/file approval decisions are handled by the Zig client (
--exec-approval, --file-approval, --read-only).
- Permission approvals can be controlled with
--permissions-approval deny|grant-turn|grant-session.
item/tool/requestUserInput, mcpServer/elicitation/request, and item/tool/call can be overridden with --request-user-input-response-json, --elicitation-action plus --elicitation-content-json, and --dynamic-tool-response-json.
cas review_session now accepts the same approval/runtime overrides as cas instance_runner; use them when detached review must be permissioned or fully deterministic under approval prompts.
- For command approvals, CAS resolves decisions against server-provided
availableDecisions when present.
- Unknown server-request methods are rejected fail-closed in native mode to prevent deadlocks.
- For overload responses (
-32001), CAS callers should retry with exponential backoff and jitter.
Scope Boundaries (Zig-Only Cutover)
- This skill no longer exposes a Node JSONL proxy lifecycle.
- Legacy message envelopes (
cas/request, cas/respond, cas/send, cas/state/get, cas/stats/get) are removed from this skill contract.
- Dynamic tool reply loops are supported only through static response payloads passed on the CAS CLI; native CAS is not a full interactive tool-runtime host.
cas review_session persists raw request/response artifacts and detached review handles; it is not a generalized streaming event mirror for all app-server notifications.
Canonical Schema Source
Use your installed codex binary to generate schemas that match your version:
codex app-server generate-ts --out DIR
codex app-server generate-json-schema --out DIR
# If you need experimental methods/fields, include:
codex app-server generate-ts --experimental --out DIR
codex app-server generate-json-schema --experimental --out DIR
Local References
Read references/codex_app_server_contract.md for API/method notes that inform CAS request usage.
Resources
cas binary dispatcher:
cas conformance
cas review_session
cas smoke_check
cas instance_runner
cas_conformance_suite binary: swarm conformance around $st claims, $mesh closeout, and retry policy.
cas_review_session binary: detached review start/status/wait/interrupt with persisted reviewThreadId handles.
cas_smoke_check binary: protocol/API smoke validation.
cas_instance_runner binary: single or multi-instance method execution.
Runtime bootstrap policy mirrors seq: require installed cas Zig binaries, default to brew install tkersey/tap/cas on macOS, and fallback to direct Zig install from skills-zig on non-macOS.
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: cas3description: Run Zig CAS helpers (`cas`, `cas_smoke_check`, `cas_instance_runner`, `cas_review_session`, `cas_conformance_suite`) for v2 app-server smoke checks, direct thread/turn request execution, detached review-session control, multi-instance fanout, and swarm conformance checks around `$st` claim sets and `$mesh` reconciliation. Use when this capability is needed.4---56# cas (Zig App-Server Control)78## Overview910`$cas` is Zig-only in this repo.1112Use the native `cas` dispatcher and subcommands:1314- `cas conformance` for swarm conformance checks around `$st` claims, `$mesh` reconciliation, and retry policy.15- `cas smoke_check` for protocol/API smoke checks.16- `cas instance_runner` for method execution across one or many isolated instances.17- `cas review_session` for detached `review/start` lifecycle control with persisted `reviewThreadId` handles.18- `run_cas_tool request` (helper alias) for single-request flows via `instance_runner --instances 1`.1920Current `cas smoke_check` verifies the native client can complete the v2 handshake and reach `experimentalFeature/list`, `thread/start`, `thread/resume`, and `turn/steer`.2122Current `cas conformance` covers these swarm-hardening scenarios:2324- `claim_safe_wave`: verify two disjoint `$st` claims can run in parallel without overlapping lock roots25- `stale_claim_reclaim`: verify expired held claims become stale and return to pending26- `mesh_row_accountability`: verify imported mesh output completes only reported rows and leaves missing rows outstanding27- `overload_backoff`: verify the bounded retry/backoff policy with a deterministic synthetic overload script2829`cas conformance` is the harness; it is not the owner of durable claims or mesh state. `$st` remains the source of truth for claims/runtime/proof metadata.3031Current `cas review_session` is the review-control lane:3233- `start` launches detached `review/start` on a supplied or freshly created parent thread34- `start` supports `--parent-mode auto|fresh|reuse`; `reuse` rejects unsafe or unmaterialized parent threads, and fresh-parent startup retries once after a bootstrap materialization turn when the installed `codex` needs it35- `wait` is the primary completion path only on runtimes that keep detached review alive across connections36- On Codex `0.118.x` over stdio, detached review output is connection-scoped, so `start --wait` is the supported detached-result lane and split fresh-process `start`/`wait` should fail closed until CAS has a websocket-backed transport37- `status` reads the detached review thread from a fresh CAS process when that runtime path is supported38- `interrupt` sends `turn/interrupt` for the persisted detached review turn3940`reviewThreadId` is the recoverable handle. Session records live under `~/.codex/cas/review_sessions/`, and CAS appends raw request/response artifacts to a per-review NDJSON log beside that record.4142Review boundary:4344- Use `cas review_session` when you need detached lifecycle control: persisted `reviewThreadId`, explicit interrupt, compatibility diagnostics, or approval/runtime overrides on the detached lane. On Codex `0.118.x` stdio, same-process `start --wait` is the supported review-result path; fresh-process polling is not.45- If you only need a one-shot git-backed review verdict and do not need detached control, prefer native `codex review --base ...` or `codex review --commit ...` instead of introducing CAS transport risk. First-party caller flows such as `$fix` should treat native review as the default path.46- `cas smoke_check` is never review proof; it only proves handshake/method reachability.47- `cas instance_runner` is never the production review lane; it is for method probing and schema sanity checks.4849When `start`, `start --wait`, `status`, or `wait` emit JSON, the output includes the detached review handle/result fields plus launch compatibility metadata:5051- `resolvedCodexPath`52- `resolvedCodexVersion`53- `compatibilityVerdict`54- `failureCode`55- `failureHint`56- `reviewResultAvailable`57- `reviewResultSource`58- `reviewResult`59 - `findings`60 - `overallCorrectness`61 - `overallExplanation`62 - `overallConfidenceScore`63- `fallbackUsed`64- `fallbackTransport`65- `fallbackExitCode`66- `fallbackOutputText`67- `fallbackErrorText`6869Use the fields this way:7071- `compatibilityVerdict="compatible"` means the detached review launch path succeeded under the resolved `codex` binary72- `compatibilityVerdict="incompatible"` means CAS identified a detached-review runtime mismatch and failed closed73- `compatibilityVerdict="not_checked"` means no compatibility verdict was persisted for that record yet (older session record or pre-launch failure)74- `failureCode="wait_timed_out"` means retry `cas review_session wait` on the same `reviewThreadId` or increase `--timeout-ms`; it is not a successful review75- `failureCode="review_interrupted"` means the detached review was interrupted before it emitted a structured review result76- `failureCode="approval_denied"` means the detached review stopped on an approval or permissions denial before it emitted a structured review result77- `failureCode="review_failed"` means the detached review failed or errored before it emitted a structured review result78- `failureCode="review_output_missing"` means the detached review reached terminal state without a structured review result even though it was not classified as an interrupt or approval failure79- `failureCode="parent_thread_not_materialized"` or `failureCode="unsafe_parent_thread_state"` means the supplied parent thread is not safe to reuse for detached review80- `fallbackUsed=true` means `--fallback native-review` ran `codex review` and returned its raw text output instead of a structured detached-review result8182Review result classification:8384- Detached review success requires all of: `compatibilityVerdict="compatible"`, `fallbackUsed=false`, `reviewResultAvailable=true`, and no blocking `failureCode`.85- Native-fallback success is a different class of result: `fallbackUsed=true` means the review text came from native `codex review`, not detached CAS review. Report it as native fallback, not detached-review proof.86- Transport progress is not review success: `reviewThreadId` creation, `start --wait` returning, or `status` showing a terminal turn is insufficient unless the result fields above classify it as success.8788Compatibility note: on Codex `0.118.x` stdio, detached review requires two compatibility moves. First, a fresh parent thread must be materialized before detached `review/start`, so CAS `--parent-mode auto` now pre-materializes that path and `fresh` retries once after bootstrap materialization when needed. Second, detached review output streams on the live app-server connection, so split fresh-process `start`/`wait` should fail closed; use `start --wait`, native `codex review`, or a future websocket-backed CAS lane.8990Node runtime paths (`cas_proxy.mjs`, `cas_client.mjs`, and related wrappers) are removed from this skill and must not be used.9192This skill assumes `codex` is available on PATH and does not require access to any repo source tree.9394## Zig CLI Iteration Repos9596When iterating on the Zig-backed `cas` helper CLI path, use these two repos:9798- `skills-zig` (`/Users/tk/workspace/tk/skills-zig`): source for the `cas` Zig binaries, build/test wiring, and release tags.99- `homebrew-tap` (`/Users/tk/workspace/tk/homebrew-tap`): Homebrew formula updates/checksum bumps for released `cas` binaries.100101## Quick Start102103```bash104run_cas_tool() {105 local subcommand="${1:-}"106 if [ -z "$subcommand" ]; then107 echo "usage: run_cas_tool <conformance|conformance-suite|smoke-check|smoke_check|instance-runner|instance_runner|review-session|review_session|request> [args...]" >&2108 return 2109 fi110 shift || true111112 local cas_subcommand=""113 local marker=""114 local -a pre_args=()115 case "$subcommand" in116 conformance|conformance-suite|conformance_suite)117 cas_subcommand="conformance"118 marker="cas_conformance_suite.zig"119 ;;120 smoke-check|smoke_check)121 cas_subcommand="smoke_check"122 marker="cas_smoke_check.zig"123 ;;124 instance-runner|instance_runner)125 cas_subcommand="instance_runner"126 marker="cas_instance_runner.zig"127 ;;128 review-session|review_session)129 cas_subcommand="review_session"130 marker="cas_review_session.zig"131 ;;132 request)133 cas_subcommand="instance_runner"134 marker="cas_instance_runner.zig"135 pre_args=(--instances 1 --sample 1)136 ;;137 *)138 echo "unknown cas subcommand: $subcommand" >&2139 return 2140 ;;141 esac142143 install_cas_direct() {144 local repo="${SKILLS_ZIG_REPO:-$HOME/workspace/tk/skills-zig}"145 if ! command -v zig >/dev/null 2>&1; then146 echo "zig not found. Install Zig from https://ziglang.org/download/ and retry." >&2147 return 1148 fi149 if [ ! -d "$repo" ]; then150 echo "skills-zig repo not found at $repo." >&2151 echo "clone it with: git clone https://github.com/tkersey/skills-zig \"$repo\"" >&2152 return 1153 fi154 if ! (cd "$repo" && zig build -Doptimize=ReleaseSafe); then155 echo "direct Zig build failed in $repo." >&2156 return 1157 fi158 if [ ! -x "$repo/zig-out/bin/cas" ] || [ ! -x "$repo/zig-out/bin/cas_review_session" ] || [ ! -x "$repo/zig-out/bin/cas_smoke_check" ] || [ ! -x "$repo/zig-out/bin/cas_instance_runner" ] || [ ! -x "$repo/zig-out/bin/cas_conformance_suite" ]; then159 echo "direct Zig build did not produce the full CAS binary set in $repo/zig-out/bin." >&2160 return 1161 fi162 mkdir -p "$HOME/.local/bin"163 install -m 0755 "$repo/zig-out/bin/cas" "$HOME/.local/bin/cas"164 install -m 0755 "$repo/zig-out/bin/cas_review_session" "$HOME/.local/bin/cas_review_session"165 install -m 0755 "$repo/zig-out/bin/cas_smoke_check" "$HOME/.local/bin/cas_smoke_check"166 install -m 0755 "$repo/zig-out/bin/cas_instance_runner" "$HOME/.local/bin/cas_instance_runner"167 install -m 0755 "$repo/zig-out/bin/cas_conformance_suite" "$HOME/.local/bin/cas_conformance_suite"168 }169170 local os="$(uname -s)"171 if command -v cas >/dev/null 2>&1 && cas --help 2>&1 | grep -q "cas.zig"; then172 if cas "$cas_subcommand" --help 2>&1 | grep -q "$marker"; then173 cas "$cas_subcommand" "${pre_args[@]}" "$@"174 return175 fi176 echo "cas binary found, but marker check failed for subcommand: $cas_subcommand" >&2177 return 1178 fi179180 if [ "$os" = "Darwin" ]; then181 if ! command -v brew >/dev/null 2>&1; then182 echo "homebrew is required on macOS: https://brew.sh/" >&2183 return 1184 fi185 if ! brew install tkersey/tap/cas; then186 echo "brew install tkersey/tap/cas failed." >&2187 return 1188 fi189 elif ! (command -v cas >/dev/null 2>&1 && cas --help 2>&1 | grep -q "cas.zig"); then190 if ! install_cas_direct; then191 return 1192 fi193 fi194195 if command -v cas >/dev/null 2>&1 && cas --help 2>&1 | grep -q "cas.zig"; then196 if cas "$cas_subcommand" --help 2>&1 | grep -q "$marker"; then197 cas "$cas_subcommand" "${pre_args[@]}" "$@"198 return199 fi200 echo "cas binary found, but marker check failed for subcommand: $cas_subcommand" >&2201 return 1202 fi203204 echo "cas binary missing or incompatible after install attempt." >&2205 if [ "$os" = "Darwin" ]; then206 echo "expected install path: brew install tkersey/tap/cas" >&2207 else208 echo "expected direct path: SKILLS_ZIG_REPO=<skills-zig-path> zig build -Doptimize=ReleaseSafe" >&2209 fi210 return 1211}212213run_cas_tool smoke-check --cwd /path/to/workspace --json214run_cas_tool review-session start --cwd /path/to/workspace --uncommitted --json215```216217## Terminology (Instances)218219- An "instance" is one `cas_proxy_client`-managed `codex app-server` child process.220- Each instance executes one request path with isolated client metadata and optional state-file isolation.221- "N instances" means N parallel client+app-server pairs in `cas instance_runner`.222223## Trigger Cues224225- "instances" / "multi-instance" / "parallel sessions"226- "review session" / "detached review" / "reviewThreadId" / "interrupt review"227- "swarm conformance" / "claim-safe wave" / "stale-claim reclaim" / "mesh row accountability"228- app-server method checks (`thread/start`, `thread/resume`, `thread/fork`, `thread/read`, `thread/list`, `thread/archive`, `thread/unarchive`, `thread/rollback`, `turn/start`, `turn/steer`, `turn/interrupt`, `review/start`)229- command/file approval behavior, especially `availableDecisions`230- session mining through direct app-server method execution231- protocol sanity checks before orchestration232233## Workflow2342351. Validate basic app-server wiring first.236 - `run_cas_tool smoke-check --cwd /path/to/workspace --json`237 - Treat this as a protocol preflight before any fanout run.2382392. Use `review_session` when the real job is detached review lifecycle control rather than one-shot probing.240 - Default decision rule:241 - Need detached control on Codex `0.118.x` stdio: use `cas review_session start --wait`.242 - Need detached control on a runtime that keeps detached review alive across connections: use `cas review_session` split `start` plus `wait`.243 - Need only a one-shot git-backed verdict: use native `codex review` unless the caller explicitly needs detached control. `$fix`-style repair loops should not CAS-first by default.244 - Start detached review:245 - `cas review_session start --cwd /path/to/workspace --uncommitted --json`246 - `cas review_session start --cwd /path/to/workspace --base main --json`247 - `cas review_session start --cwd /path/to/workspace --parent-thread-id <threadId> --parent-mode reuse --base main --json`248 - `cas review_session start --cwd /path/to/workspace --commit <sha> --title "<subject>" --json`249 - `cas review_session start --cwd /path/to/workspace --custom-instructions @review.txt --json`250 - `cas review_session start --wait --cwd /path/to/workspace --base main --fallback native-review --json`251 - Read current status from a fresh process when the runtime supports detached polling:252 - `cas review_session status --review-thread-id <reviewThreadId> --json`253 - Wait for the detached review turn to settle when the runtime supports detached polling:254 - `cas review_session wait --review-thread-id <reviewThreadId> --timeout-ms 300000 --json`255 - Supported same-process lane on Codex `0.118.x` stdio:256 - `cas review_session start --wait --cwd /path/to/workspace --base main --json`257 - Interrupt the detached review turn:258 - `cas review_session interrupt --review-thread-id <reviewThreadId> --json`259 - `reviewThreadId` is the handle; do not invent a second review session id.260 - Review hygiene:261 - On Codex `0.118.x` stdio, prefer `start --wait ... --json` when the detached verdict matters; that is the supported lane because review items stream on the live connection.262 - On runtimes that keep detached review alive across connections, prefer `start ... --json` followed by `wait ... --json` when the verdict matters; it leaves a recoverable handle if wait times out or the process dies.263 - In first-party caller workflows, treat one detached CAS attempt as one `start` plus any `wait` retries on the returned `reviewThreadId`, keyed by the frozen review target plus resolved Codex path/version. If that attempt returns `incompatible_codex_review_runtime`, stop relaunching detached CAS for the same key in that run and let the caller decide whether to switch to native `codex review`.264 - Reuse a parent thread only with `--parent-mode reuse` plus a known materialized parent; otherwise let CAS choose `auto` or force `fresh`.265 - Treat `reviewResultAvailable`, `compatibilityVerdict`, `fallbackUsed`, and `failureCode` as the verdict surface. Do not infer success from process exit alone.2662673. Detached review is the public review-control path; do not route review-session control through `instance_runner`.268 - `instance_runner` remains a method probe lane and is still useful for schema sanity checks.269 - `review_session` owns persisted review handles, fresh-process status polling, wait loops, and interruption.270 - For workflows that need the actual review verdict, use the live connection lane the runtime supports: `start --wait` on Codex `0.118.x` stdio, or split `start ... --json` then `wait ... --json` on runtimes that keep detached review alive across connections.271 - Treat `failureCode` as authoritative. CAS never silently falls back to native `codex review`; callers that want a temporary fallback must do it explicitly at their own layer.2722734. For swarm-hardening runs, treat `$st` as the durable source of truth before any worker starts.274 - `st import-orchplan --file .step/st-plan.jsonl --input .step/orchplan.yaml`275 - `st claim --file .step/st-plan.jsonl --wave w1 --executor teams`276 - CAS probes the wave; it does not replace the durable claim ledger.2772785. Enforce handshake assumptions when diagnosing failures.279 - Confirm the session completed `initialize` then `initialized` before method calls.280 - If you see `"Not initialized"` or `"Already initialized"`, treat it as connection-lifecycle error, not a method payload error.2812826. Run one direct method request (single-request lane).283 - `run_cas_tool request --cwd /path/to/workspace --method thread/start --params-json '{"cwd":"/path/to/workspace","experimentalRawEvents":false}' --json`2842857. Run fanout/multi-instance requests.286 - `run_cas_tool instance-runner --cwd /path/to/workspace --instances 12 --method thread/list --params-json '{"cursor":null,"limit":1}' --json`2872888. Run the conformance suite when you need repeatable swarm checks around claims, mesh closeout, or retry policy.289 - `cas conformance --cwd /path/to/workspace --json`290 - Narrow to one scenario when debugging: `cas conformance --cwd /path/to/workspace --scenario mesh_row_accountability --json`291 - Use `--skip-smoke-check` only when you intentionally want the local `$st`/mesh scenarios without the live CAS preflight.2922939. Apply overload handling on request saturation.294 - If app-server returns JSON-RPC error code `-32001` (`"Server overloaded; retry later."`), retry with exponential backoff and jitter.295 - Do not treat `-32001` as a permanent protocol mismatch.296 - In `cas conformance`, the retry policy scenario is currently synthetic and should be treated as retry-policy proof, not live saturation proof.29729810. Drive specific thread/turn methods as needed.299 - Start thread:300 - `run_cas_tool request --cwd /path/to/workspace --method thread/start --params-json '{"cwd":"/path/to/workspace","experimentalRawEvents":false}' --json`301 - Start turn:302 - `run_cas_tool request --cwd /path/to/workspace --method turn/start --params-json '{"threadId":"thr_123","input":[{"type":"text","text":"summarize the repo status"}]}' --json`303 - Thread read:304 - `run_cas_tool request --cwd /path/to/workspace --method thread/read --params-json '{"threadId":"thr_123","includeTurns":true}' --json`305 - Resume thread:306 - `run_cas_tool request --cwd /path/to/workspace --method thread/resume --params-json '{"threadId":"thr_123"}' --json`307 - Steer turn:308 - `run_cas_tool request --cwd /path/to/workspace --method turn/steer --params-json '{"threadId":"thr_123","expectedTurnId":"turn_abc","input":[{"type":"text","text":"continue"}]}' --json`309 - Interrupt turn:310 - `run_cas_tool request --cwd /path/to/workspace --method turn/interrupt --params-json '{"threadId":"thr_123","turnId":"turn_abc"}' --json`31131211. Use method-specific params for list/mine flows.313 - `thread/list` supports filter params (`cursor`, `limit`, `searchTerm`, `cwd`, etc.) as provided by your app-server version.314 - `turn/steer` requires `expectedTurnId`.31531612. After a mesh batch, reconcile the exported CSV back into `$st`.317 - `st import-mesh-results --file .step/st-plan.jsonl --input .step/mesh-output.csv`318 - CAS may validate the wave around that closeout, but it does not own the CSV reconciliation.31932013. Gate experimental methods and payload fields explicitly.321 - Experimental surfaces such as `thread/backgroundTerminals/clean`, `thread/realtime/*`, and `thread/start` dynamic-tool fields require `initialize.params.capabilities.experimentalApi = true`.322 - If omitted, treat failures as capability negotiation errors.32332414. Respect native CAS server-request limits.325 - The current Zig client auto-answers `item/commandExecution/requestApproval`, `item/fileChange/requestApproval`, `item/permissions/requestApproval`, `item/tool/requestUserInput`, `mcpServer/elicitation/request`, and `item/tool/call`.326 - Default native behavior is conservative: permissions requests are denied, request-user-input questions use the first option label when present, MCP elicitations are declined, and dynamic tool calls return `success: false` unless you override with explicit CLI flags.327328## Approval and Request Semantics329330- Exec/file approval decisions are handled by the Zig client (`--exec-approval`, `--file-approval`, `--read-only`).331- Permission approvals can be controlled with `--permissions-approval deny|grant-turn|grant-session`.332- `item/tool/requestUserInput`, `mcpServer/elicitation/request`, and `item/tool/call` can be overridden with `--request-user-input-response-json`, `--elicitation-action` plus `--elicitation-content-json`, and `--dynamic-tool-response-json`.333- `cas review_session` now accepts the same approval/runtime overrides as `cas instance_runner`; use them when detached review must be permissioned or fully deterministic under approval prompts.334- For command approvals, CAS resolves decisions against server-provided `availableDecisions` when present.335- Unknown server-request methods are rejected fail-closed in native mode to prevent deadlocks.336- For overload responses (`-32001`), CAS callers should retry with exponential backoff and jitter.337338## Scope Boundaries (Zig-Only Cutover)339340- This skill no longer exposes a Node JSONL proxy lifecycle.341- Legacy message envelopes (`cas/request`, `cas/respond`, `cas/send`, `cas/state/get`, `cas/stats/get`) are removed from this skill contract.342- Dynamic tool reply loops are supported only through static response payloads passed on the CAS CLI; native CAS is not a full interactive tool-runtime host.343- `cas review_session` persists raw request/response artifacts and detached review handles; it is not a generalized streaming event mirror for all app-server notifications.344345## Canonical Schema Source346347Use your installed `codex` binary to generate schemas that match your version:348349```sh350codex app-server generate-ts --out DIR351codex app-server generate-json-schema --out DIR352353# If you need experimental methods/fields, include:354codex app-server generate-ts --experimental --out DIR355codex app-server generate-json-schema --experimental --out DIR356```357358## Local References359360Read `references/codex_app_server_contract.md` for API/method notes that inform CAS request usage.361362## Resources363364- `cas` binary dispatcher:365 - `cas conformance`366 - `cas review_session`367 - `cas smoke_check`368 - `cas instance_runner`369- `cas_conformance_suite` binary: swarm conformance around `$st` claims, `$mesh` closeout, and retry policy.370- `cas_review_session` binary: detached review start/status/wait/interrupt with persisted `reviewThreadId` handles.371- `cas_smoke_check` binary: protocol/API smoke validation.372- `cas_instance_runner` binary: single or multi-instance method execution.373374Runtime bootstrap policy mirrors `seq`: require installed `cas` Zig binaries, default to `brew install tkersey/tap/cas` on macOS, and fallback to direct Zig install from `skills-zig` on non-macOS.375376---377> Converted and distributed by [TomeVault](https://tomevault.io/claim/tkersey) — claim your Tome and manage your conversions.378<!-- tomevault:4.0:skill_md:2026-04-11 -->