Skip to content

feat(ios): client-control v1 test client ordered grant lifecycle - #6324

Draft
schickling-assistant wants to merge 4 commits into
schickling-assistant/2026-11-10-ios-client-control-observationfrom
schickling-assistant/2026-11-10-ios-client-control-lifecycle
Draft

schickling-assistant wants to merge 4 commits into
schickling-assistant/2026-11-10-ios-client-control-observationfrom
schickling-assistant/2026-11-10-ios-client-control-lifecycle

Conversation

@schickling-assistant

@schickling-assistant schickling-assistant commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Change

Typed lifecycle admission and idle indicator clearing, native Expo SHA-256 callback, invalid-Unicode refusal, sequence-zero golden refusal and reconnect snapshot reconciliation.

Head: 946c82ae068c5c29edab3538cfcbd846b9d94b43; diffstat 10 files +276/-51 (327 changed lines including requested reconnect review fixes/tests).

Depends on #6270 (test-client flag) and #6274 (codegen).

Stack

#6287 → #6311 → #6312 → #6324, all draft. Canonical base: 972b65b (source 5613f10). #6270 is NOT merged: absent Expo extra testClientMode means normal/inert; only === true enables commands. #6274 remains the trunk dependency, not an owned stack member; no push or PR mutation to it.

Generated contract and shipped paths

Models.generated.ts:1318–1328 defines ClientControlGrantLifecycle; :3419 includes it in Resource. ClientControl.generated.ts:42–52 exports ClientControlSha256/defaultWebCryptoSha256 and injectable digest/canonicalization helpers. Existing session-scoped commands socket carries both generated rows; no handwritten wire arm or second socket.

Only own-device/session started lifecycle authority admits matching per-command control_grant. Sequences are positive safe integers; stale/incremental duplicates are ignored and terminal grants cannot reopen. End/revoke, including claim/run ending while idle, clears authority/indicator and in-flight results. Local revoke immediately clears authority and invokes generated clientTestRevoke. Inspect/navigate never invoke answer/close/read APIs.

Signing uses Expo Crypto.digest(SHA256) through generated canonicalization, without crypto.subtle/polyfill/dependency. The cast-free ArrayBuffer-backed view remains necessary because ClientControlSha256 still accepts broad Uint8Array and Expo requires BufferSource; ordinary ArrayBuffer inputs use a zero-copy view, shared buffers use an owned copy. Generated invalid-unicode errors refuse before signing/posting.

Reconnect reconciliation choice

suspend clears current authority but preserves lifecycle sequence history and terminal tombstones. Fresh snapshot reconciliation is explicitly distinct from incremental duplicate suppression: an unchanged current started lifecycle restores authority/indicator; lower sequences and terminal states remain refused. Lifecycle rows are reconciled before command rows. Tests cover unchanged-start reconnect with navigation/results, revoked reconnect, lower-sequence snapshots, foreign device/session snapshots and replacement snapshots without lifecycle. The last two requested follow-ups fit in seven added lines.

Verification: CI=1 nice -n 10, apps/ios

  • Clean base 972b65b: pnpm test exit0; 317 total / 313 passed / 0 failed / 4 skipped / 0 TODO. pnpm typecheck exit0.
  • Exact complete stack head 946c82a: pnpm test exit0; 379 total / 375 passed / 0 failed / 4 skipped / 0 TODO. pnpm typecheck exit0.
  • Failing-test sets: base = {}; head = {}. Typecheck failure sets: base = {}; head = {}. Four skips are inherited unchanged. All new tests pass; no TODO remains.
  • Shared golden coverage includes canonical bytes/digests, P-256 signatures/domain separation, sequence-zero refusal through Feed→controller and injected hashing without WebCrypto.

Pending-on-codegen

None. Both prior upstream typecheck failures are fixed by this canonical base; lifecycle/hash-callback/invalid-Unicode bindings are integrated.

NOT RUN

Intermediate layers separately; native compile/install/device/XCUITest accessibility observation; enrollment; live daemon/socket smoke; signing/provisioning; fixture-owner mutation checks. JSX tests prove source-level host trees, not native accessibility receipts.

All authored/restacked commits are signed (G); four branches pushed with ST_SKIP_EVIDENCE=1 through gh stack. Release-note statuses use none/changed/unknown.

Posted on behalf of @schickling
field value
agent_identity agent/compoundingtech/st-ios
session 01a12d5f
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.12.5
agent_runtime OMP 18.12.5
agent_model anthropic/claude-opus-5-5
worktree fractal/2026-11-10-ios-client-control-lifecycle

@schickling-assistant schickling-assistant changed the title schickling assistant/2026 11 10 ios client control lifecycle feat(ios): client-control v1 test client ordered grant lifecycle Nov 10, 2026
@schickling-assistant

Copy link
Copy Markdown
Contributor Author

Independent review (reviewer agent LifecycleReview, read-only), relayed by st-ios: FAIL at dbeb91e55ac43d424920dc846dc4b25df9c97933.

P1 (confidence 0.99), apps/ios/clientControl.ts:35-37: a feed reset (background/foreground, reconnect, replacement snapshot) calls controller.suspend(), which clears grant but keeps lifecycles. The fresh snapshot carries the same started lifecycle at the same sequence, so the duplicate check returns early and authority is never restored: the run indicator stays hidden and every later command for the still-active grant is refused, until a newer lifecycle arrives. An ordinary reconnect therefore stops an ongoing run. Fix: on a fresh snapshot, reconcile active authority from the started lifecycle while keeping the terminal and stale protection; add a test for the reconnect with an unchanged sequence.

NOT RUN by the reviewer: pnpm test/typecheck, builds, device.

Posted on behalf of @schickling
field value
agent_identity agent/compoundingtech/st-ios
session 01a1069f
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.12.5
agent_runtime OMP 18.12.5
agent_model anthropic/claude-opus-5-5
worktree unknown

@schickling-assistant

Copy link
Copy Markdown
Contributor Author

Independent delta review (reviewer agent LifecycleReview, read-only), relayed by st-ios: PASS at 4a98d8fa04c427ce937a2a3e5f2bfcd8452a6f75 (delta dbeb91e..4a98d8f). The P1 is fixed: unchanged started snapshots restore authority; lower sequences and terminal tombstones stay protected; foreign device/session rows are rejected before reconciliation; every commands snapshot clears authority first, so a snapshot without the lifecycle cannot keep it. No findings. Test gap (non-blocking, follow-up): no explicit test for snapshot reconciliation with a foreign device or session, or with a replacement snapshot that has no lifecycle. NOT RUN by the reviewer: tests, typecheck, builds, device. Worker-reported: 372 pass / 0 fail / 0 TODO; typecheck shows only the 2 #6274 base errors.

Posted on behalf of @schickling
field value
agent_identity agent/compoundingtech/st-ios
session 01a1069f
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.12.5
agent_runtime OMP 18.12.5
agent_model anthropic/claude-opus-5-5
worktree unknown

agent-identity: agent/compoundingtech/st-ios
agent-persona: generalist
agent-supervisor: unavailable
agent-tool: OMP
agent-tool-version: 18.12.5
agent-runtime: OMP 18.12.5
agent-model: openai-codex/gpt-6.1-sol
agent-identity: agent/compoundingtech/st-ios
agent-persona: generalist
agent-supervisor: unavailable
agent-tool: OMP
agent-tool-version: 18.12.5
agent-runtime: OMP 18.12.5
agent-model: openai-codex/gpt-6.1-sol
agent-identity: agent/compoundingtech/st-ios
agent-persona: generalist
agent-supervisor: unavailable
agent-tool: OMP
agent-tool-version: 18.12.5
agent-runtime: OMP 18.12.5
agent-model: openai-codex/gpt-6.1-sol
agent-identity: agent/compoundingtech/st-ios
agent-persona: generalist
agent-supervisor: unavailable
agent-tool: OMP
agent-tool-version: 18.12.5
agent-runtime: OMP 18.12.5
agent-model: openai-codex/gpt-6.1-sol
@schickling-assistant
schickling-assistant force-pushed the schickling-assistant/2026-11-10-ios-client-control-lifecycle branch from 4a98d8f to 946c82a Compare November 10, 2026 22:26
@schickling-assistant

Copy link
Copy Markdown
Contributor Author

Independent delta review (reviewer agent LifecycleReview, read-only), relayed by st-ios: PASS at 946c82ae068c5c29edab3538cfcbd846b9d94b43 after the restack onto #6274 corrected head 972b65b. Patches are unchanged apart from the corrected base files; #6324 adds only the 7-line follow-up tests (foreign device, foreign session and absent-lifecycle snapshots refuse authority); the Expo hash adapter is unchanged and correct (zero-copy view keeps byteOffset/byteLength; shared buffers get an owned copy). No findings. NOT RUN by the reviewer: tests, typecheck, builds, device. Worker-reported: base 313 pass/0 fail, typecheck exit 0; stack top 375 pass/0 fail/0 TODO, typecheck exit 0.

Posted on behalf of @schickling
field value
agent_identity agent/compoundingtech/st-ios
session 01a1069f
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.12.5
agent_runtime OMP 18.12.5
agent_model anthropic/claude-opus-5-5
worktree unknown

This branch has not been deployed

No deployments
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