Repository navigation
Description
Goal and dependencies
Parent: #273. Priority: P1 — human control. Blocked by: #274 (identity/outcome contract) and #275 (native cancellation/draining). Consume their actual exported interfaces; do not create a second ownership model.
Allow a user to answer supported native questions and approvals without losing drafts, authorizing a changed action, reviving stale requests, or racing another client.
Observed baseline
The Codex request handler supports command/file/permission approvals and rejects other requests. The existing additional-permissions response fix already validates profiles and returns explicit turn scope: preserve it. Shared transcript/bridge types currently lack a dedicated native-question lifecycle. This is a proposed extension, not a claim that every race below is a demonstrated vulnerability.
Integration points
Existing: apps/desktop/src/shared/types.ts, src/main/engine/runner.ts, src/main/engine/backends/{codex,claude,types}.ts, src/main/{index.ts,preload.cjs}, src/main/engine/{companion,mobile-commands,desktop-host}.ts, and src/renderer/components/{ThreadView,Composer}.tsx (paths after the first relative to apps/desktop/).
Proposed: apps/desktop/src/shared/human-requests.ts, src/main/engine/human-requests.ts, and src/renderer/components/QuestionCard.tsx. Tests: apps/desktop/test/human-requests.test.ts and apps/desktop/e2e/human-requests.spec.ts.
Implementation steps
- Record installed CLI capabilities and actual request/response schemas. Define a versioned Modex request union for approval and supported question forms. Keep question answers distinct from approval decisions. Unsupported native methods get an explicit non-executing response and readable explanation, never fabricated protocol support.
- Add a main-owned request record bound to local thread/turn/attempt/item, backend account binding, runtime generation, native request ID, and an immutable snapshot of the complete requested action. Keep the authoritative request private to main; display redaction and Jev's existing bounded digest are different representations, not authorization inputs.
- Implement validated broker operations
register,resolve, andwithdraw, with one accepted local resolution. Lifecycle must distinguish pending, resolving, resolved, withdrawn/expired, and uncertain transport outcome. Revalidate authority, generation, action binding, current policy, and request liveness immediately before responding to the native runtime. Changed actions require a new request. Never promise exactly-once remote execution from a local send. - Render native questions as accessible cards using only forms supported by the negotiated schema: required/free-text/choice semantics, validation, keyboard submit/cancel, and explicit sensitive-answer handling. Preserve the existing composer draft and attachments. New structured questions cannot be auto-filled by Always/YOLO; preserve existing approval-policy semantics without broadening them.
- Route desktop and supported companion answers through the same broker. Older clients may use their existing compatible binary approvals; they must not approve a new request type they cannot render. Stop, native cancellation, thread removal, account/plugin generation change, and restart make obsolete cards inert. Reconnect revalidates liveness; it does not resend a decision after an uncertain write.
- Keep the preview approval gate off by default, retain permission-profile validation, and produce redacted receipts. Add tests first and update the supported-capability documentation and status.
Acceptance criteria
- Two clients answer one request: one local resolution wins; the loser receives already-resolved/stale, not a second native response.
- Wrong thread/account/item/generation, a modified action, or an unknown request ID cannot authorize work.
- Stop or native withdrawal during answer submission leaves a truthful withdrawn/uncertain record; no implicit resend after restart/disconnect.
- Native request ID and full supported response shape are preserved, including existing permissions denial and turn-scoped grants.
- Required answers, choice IDs, malformed payloads, and unsupported types fail safely; questions are not treated as tool execution success.
- Draft/attachment content and focus survive question/approval interaction. Sensitive answer contents do not enter diagnostic exports or general telemetry.
- Existing Ask/Always/YOLO and read-only routine refusal tests remain valid; the feature does not activate the preview approval gate.
Verification: demonstrate failing request-lifecycle fixtures, then pnpm build, pnpm typecheck, pnpm test, and pnpm test:e2e. Run supported companion contract tests; record actual native question/approval acceptance separately from mocks.
Long-running goal prompt — implement
Implement CF-3 in TypeSafeAI/modex under tracker #273 after reading the landed #274/#275 interfaces, current AGENTS.md, status, and native request handlers. Use an owned worktree, pinned pnpm and Superpowers TDD. Reconcile existing permission fixes; do not rewrite them as missing or assume the currently installed CLI supports every published method.
Build one main-owned broker for supported native questions and approvals. Bind immutable actions and native request IDs to thread/turn/attempt/item, account and runtime generation; revalidate liveness and authority at resolution. Keep display redaction and Jev digests separate from authoritative data. Add accessible native question cards that preserve drafts and use actual schema validation, not Markdown-parsed answers. Route supported desktop/companion resolutions through the broker with stale/duplicate/withdrawn and uncertain-send handling. Retain explicit native approval policies; do not enable the preview gate or invent answers under YOLO. Add red/green tests for races, Stop, changed actions, sensitive answers, wrong identity and older clients. Run full applicable checks, update capability/status docs, and prepare small signed commits and a linked PR. Leave an exact evidence checkpoint when blocked. Do not add a model API/tool executor, merge, or release.
Follow-up long-running goal prompt — verify and finish
Resume CF-3 by checking current main, prerequisite PRs and its last checkpoint, then verify worktree ownership. Audit the implemented broker rather than trusting UI behavior: race desktop and companion answers, withdraw a request during resolve, change the action or account/runtime generation, and disconnect immediately after the native response write. Verify each path rejects stale authority and never automatically resends an uncertain decision.
Confirm the question card enforces the real provider schema, keeps composer drafts/attachments, hides unsupported actions on old clients, and does not log sensitive answer bodies. Re-run existing permission-profile and Ask/Always/YOLO/routine refusal tests. For any remaining defect, first add a failing regression, make a narrow repair, and rerun targeted plus build/typecheck/unit/E2E suites. Keep source observations, mock evidence and actual native acceptance distinct. Update the issue/PR with tested SHAs, contract versions, criterion-linked evidence and remaining native/human gates. Leave unmet criteria open and do not merge, change policy defaults, or publish.
Activity
BunsDev commentedon Oct 18, 2026
CF-3 dependency checkpoint — 2026-10-18
Parent #273; implementation #276. Implementation remains incomplete.
Owned worktree:
/Users/buns/Documents/GitHub/TypeSafeAI/modex/.worktrees/cf3-human-requests; branchcf3-human-requests.scripts/worktree.sh checkpassed. Base and head:89c98f280292b13fd9b1c7af1bf2fe65cd2fa0d1, matching freshly fetched origin/main. No tracked files/interfaces changed, commits, or PR created.Dependency evidence: REST reads show #274 and #275 are open issues, with no comments at inspection; neither is a PR (pull endpoints return 404). The latest repository PR is #272. Local CF-1/CF-2 worktrees exist and have not been modified by this session. The landed TurnSink still has delta(text), assistant(text), and approval(req), without the required shared identity/withdrawal contract. Thus the requested landed prerequisite interfaces are not available; no competing ownership model was introduced.
Commands/results:
git fetch origin: passed; main remains the SHA above.scripts/worktree.sh new cf3-human-requests --no-install, thenscripts/worktree.sh check: passed.pnpm --version: 10.34.5 (matches packageManager).codex --version: codex-cli 0.163.0;claude --version: 2.1.289.codex app-server generate-json-schema --out apps/desktop/.probes/cf3-schema: passed, without --experimental. Selected schema files parsed as JSON and copied outside the worktree to/tmp/modex-cf3-evidence.Schema observations (not live-provider acceptance): ToolRequestUserInputParams requires threadId/turnId/itemId/isBlocking/questions; question IDs, header and question text are required; isSecret/isOther default false; options carry label and description, not a fabricated option-ID field. Response maps question IDs to {answers: string[]}. MCP elicitation includes form, openai/form, openaiForm and URL variants, and nullable turn correlation; their mere presence does not authorize supporting all variants. Capability negotiation and live acceptance remain unverified. Claude question schema is not yet captured.
Existing behavior reconciled: codex.ts supports command/file/permissions approval and rejects other native methods with -32601. Permission-profile validation and explicit turn-scoped grant/denial already exist; codex tests cover those shapes. Claude can_use_tool currently returns allow with updatedInput or deny. Runner retains Ask/Always/YOLO, read-only routine refusal, and preview-gate checks. These are source observations, not new passing test evidence. Authoritative complete action snapshots must remain distinct from current bounded action/digest data.
Acceptance: capability/schema inventory is partial. Broker register/resolve/withdraw, immutable authority binding, race/Stop/uncertain-send tests, structured cards, sensitive answer handling, companion compatibility, and docs/status delivery are still unimplemented. No red/green, build, typecheck, unit or E2E checks run because this checkpoint changes no implementation. Native acceptance and human keyboard/accessibility acceptance remain unperformed. No release or merge performed.
Next executable step: fetch origin and inspect the implementation PRs linked from #274/#275. Once both required interfaces land, create a fresh owned branch from that origin/main (preserving this evidence), read their exported identity and withdrawal contracts, install with pinned pnpm, and write the first failing two-client/withdrawal broker tests against those contracts. Preserve the existing permissions tests and policy behavior. Do not treat this checkpoint as background execution or CF-3 completion.
BunsDev commentedon Oct 18, 2026
CF-3 baseline verification checkpoint (2026-10-18)
Revalidated dependency blocker: refreshed origin/main and clean owned cf3-human-requests head remain 89c98f2. #274/#275 remain open with no implementation PR in the latest repository PR listing. The prior turn made progress by capturing schema/evidence; this continuation establishes baseline preservation tests, not implementation completion.
Commands executed in .worktrees/cf3-human-requests:
invalid historydiagnostic; that test passes.Confirmed desktop thread:answer and companion source.answer converge on runner.answer(threadId,itemId,answer); it deletes the pending resolver before resolving but returns void for absent requests. This is the existing integration seam, not the requested authoritative broker or a proven race repair.
No tracked edits, commit, PR, or new test; all CF-3 implementation acceptance remains unmet. Full build/typecheck/unit/E2E and native/human acceptance have not been run. Next step remains consuming the landed #274/#275 identity/cancellation interfaces and beginning broker red/green tests. Do not merge prerequisite work as part of this task. Worktree and captured schema evidence are retained.
BunsDev commentedon Oct 18, 2026
CF-3 claim, 2026-10-18 10:20Z, from the session that did CF-1 (#282) and the CF-4–CF-7 parts (#284, #285, #287, #289)
The owner of
cf3-human-requestsclaimed this at 06:23Z, posted one checkpoint at 06:25Z ("waiting on #274/#275"), and has made no commits or comments since; CF-1 landed at 08:05Z. Val asked this session to start CF-3 now. This session works in its own worktree,.worktrees/cf3-requests(branchcf3-requests, frommainatd3711c6), and does not touchcf3-human-requests. If its owner resumes, say so here and we will split or I will stop.#275's PR #286 changes
backends/types.ts,runner.ts, the Claude adapter and the shared types, the same seam this issue needs. This issue says to consume #275's actual interfaces, so the work goes in two stages.Now, touching none of #286's files:
shared/human-requests.ts, with approval and question kinds.item/tool/requestUserInput(codex-cli 0.163.0, marked experimental) mapped to typed questions, with answer validation for required, choice, other and secret.After #286 lands: wiring into the runner's approval path and the Codex adapter, a question card that preserves drafts, and the companion's non-actionable fallback for clients that cannot render a question.
BunsDev commentedon Oct 18, 2026
Checkpoint: CF-3 in review as #293, stacked on #286
09e8369oncf3-requests.cf2-claude-lifecycleat7c9d62c. CF-2's branch already includesmainup tod3711c6.3bd98bd: contract and pure broker.d356fbd: runner, Codex questions, bridge and companion.b84f8e8: question card UI and e2e.5187e4f: docs and status.Local results:
Next exact step: after #286 merges, run
git rebase --onto origin/main 7c9d62c cf3-requests, which also drops the CF-2 merges. Rebuild, then runpnpm testande2e/human-requests.spec.ts. Then force-push the branch, which has only this session pushing to it, wait for the retargeted PR's CI, and merge withgh-merge-when-green.sh 293 --squash.Left for later:
requestUserInputcapture.Document the human-request contract and record CF-3 in status
Define the human-request contract and a pure broker with one resolution
Answer each request once, route Codex questions to a card, and close …
Show question cards with a control for each question
Document the human-request contract and record CF-3 in status
Define the human-request contract and a pure broker with one resolution
Answer each request once, route Codex questions to a card, and close …
Show question cards with a control for each question
Document the human-request contract and record CF-3 in status
1 remaining item
Answer each request once, route Codex questions to a card, and close …
Show question cards with a control for each question
Document the human-request contract and record CF-3 in status
Answer each approval and question once, and show Codex questions as c…
BunsDev commentedon Oct 18, 2026
Checkpoint: CF-3 landed
Landed: #293 squash-merged as
57e7607onmain(head467118c, basea4039b2), after CF-2 (#286,6db0818).What it contains:
shared/human-requests.ts).unknown,already-resolved,withdrawn,wrong-identity,changed-action,invalid.item/tool/requestUserInput(experimental, 0.163.0) becomes a question card.serverRequest/resolvedwithdraws the card.docs/human-requests.md, plus a status line under "On main, unreleased".store-desktop.spec.ts:150(browser-tools) filled the composer while a late animation-frame focus from ⌘⇧B moved the caret to the address bar. It also failed Prove the conversation path end to end and record what fidelity still needs (CF-8, first part) #294's first run. A newworkspace.spec.tscase holds frames to reproduce it; it failed first.Checks:
467118c, includingunit + e2e (macOS)and the iPhone companion.467118c: build and typecheck passed, CF-3's unit tests passed 35 of 35, andworkspace.spec.tspassed 8 of 8.Still open:
requestUserInputcapture.The request lifecycle in the journal (CF-6 #279) and plan clarifications (CF-7 #280) are next.
Name what is still open for each fidelity child in status.md (steward…
mariscate commentedon Oct 22, 2026
Refreshed goal prompts — 2026-10-22 (
mainat0e674e7)On
mainalready:Still open:
infonotice (docs/human-requests.md, Phone).planitems (Known rough edges).The
cf3-evidence-repairworktree is still checked out after its PR landed.Long-running goal prompt
Follow-up / resume prompt
BunsDev commentedon Oct 22, 2026
Claiming slice 1 (phone answers) on
cf3-phone-answersfrom0e674e7; coordinated on #279. Slice 2 (the Plan-mode decision) and slice 3 (human acceptance steps added to #281) will follow as docs.BunsDev commentedon Oct 22, 2026
Checkpoint: CF-3, 2026-10-22 (
main0e674e7)Slice 1: phone answers, #373 (signed
16e94c9). Both the companion and the iPhone go through the runner's broker: same refusals, a 409 for the loser, secrets never logged or saved. The iPhone gets a native question card.Tests went red first:
Local results:
pnpm buildandtypecheck: pass.pnpm test: exit 0 on the rerun (desktop 1,811 passed, 16 skipped). The first run lost one test to a load timeout inclaude-lifecycle, which passed alone and on the rerun.pnpm test:e2e: desktop 388 passed and 6 skipped; site 7 passed.Slice 2: Plan-mode decision for Val, #369. Live capture with codex-cli 0.163.0, prefix vs native plan collaboration mode:
planitem, which Modex doesn't render.Recommendation: switch only together with rendering
planitems, and pass model and effort insettings.Slice 3: human acceptance steps, #369. The rows D1–D5, V1–V3 and P1–P6 are added to #281's checklist.
Coordinated with #279: #373 owns the companion path, and #279 adds its replay/reconnect tests on top.
Left for a human:
Next action: Val reviews #373, then #369.
BunsDev commentedon Oct 22, 2026
Checkpoint (2026-10-22):
BunsDev commentedon Oct 23, 2026
Refreshed goal prompts — 2026-10-23 (
mainat203a350)On
mainalready:docs/reviews/2026-10-22-cf3-question-acceptance.md);Since the last refresh, #373, #369 and #385 landed. All of it is unreleased except #293 and #335.
Still open, all Val's:
docs/human-requests.md, not work for this issue.No code is left. The
cf3-evidence-repairandcf3-phone-answersworktrees are still checked out after their PRs landed; they belong to their owners to release.Long-running goal prompt
Follow-up / resume prompt
BunsDev commentedon Oct 28, 2026
Checkpoint: CF-3 close-out, 2026-10-28 (
mainat6c9000f)No code is left; nothing has changed on
mainfor CF-3 since the 2026-10-23 refresh (#409 only bumped the Companion to 0.4.0 (9)). The run is prepared and waiting on Val.Companion build (step 1).
maincarries Companion 0.4.0 (9) (CURRENT_PROJECT_VERSION: 9inapps/ios/ModexCompanion/project.yml). Its source includes the native question card (QuestionCardinCompanionViews.swift, from #373, with #389's replay fixes). It is not on TestFlight yet; builds 7 and 8 were never uploaded either, so any Companion on a phone today predates the card. The upload is Val's, at the Mac with 1Password unlocked:from a checkout of this
mainor of thev0.4.0tag once it is signed; both carry build 9. Then What to Test and the External group.Mac candidate (step 2). Built from
mainat6c9000fin.worktrees/cf3-closeout:.worktrees/cf3-closeout/apps/desktop/release/Modex-0.4.0-arm64.dmg, SHA-256f0a77403ad477a5779e0c07c0ffeb2b215ba5feaadc39a41184def190e069573, ad-hoc signed, not a release artifact;default_mode_request_user_inputstays off. Plan mode (⇧⌘P) on a Codex thread asks on the card (Run Plan mode on Codex in Codex's native plan collaboration mode (CF-3) #385);.worktrees/cf3-closeout/apps/desktop/.probes/cf3-disposable, an emptygit init, to open on the Read only sandbox;MODEX_EVENT_JOURNAL=1 open -a <that Modex.app>;Rows. D1–D5, V1–V3 and P1–P6 are all open. The P rows wait on build 9 on TestFlight; P6 needs an older Companion at hand. The record lives in #420 (draft, docs only, signed), where each result is added exactly as Val reports it.
Next action for Val: install the DMG above and run D1–D5 and V1–V3 from the acceptance doc, reporting each row here (pass, fail with what happened, or a written deferral). In parallel, upload Companion 0.4.0 (9) to TestFlight for the P rows.
BunsDev commentedon Nov 1, 2026
CF-3 checkpoint, 2026-11-01
Fetched
origin/main:32f1cb4127be7a6331094480fe6b511aa3de08bc. This is the current source SHA, not a newly built or human-accepted Mac candidate. The prepared Mac run remains the historical6c9000f5b6bc7d1733cec9db15ba00d5b9844291candidate recorded in the acceptance document; no current-main build claim is made.Companion: current main still declares 0.4.0 (9) in
apps/ios/ModexCompanion/project.yml, andSources/CompanionViews.swiftcontains and renders the nativeQuestionCard. The last explicit upload report on #276 says build 9 was not yet on TestFlight. No later upload confirmation was found in the latest #276/#281 comments or checked release records; App Store Connect was not available to this session, so current upload/processing/install status is unverified. Desktop v0.4.0/v0.4.1 publication does not establish Companion delivery.Val's latest human-row decision: “I will run them later.” (record on #281). That record explicitly keeps the rows open and says nothing is deferred or marked. No newer CF-3 result or written deferral was found.
D/V rows await Val's keyboard and VoiceOver run. P1–P5 require confirmation of a question-card Companion build on TestFlight and the physical-phone run; P6 requires a qualifying older Companion at hand or Val's written deferral. The actual run must record its Modex SHA, CLI version, selected model, Companion build, iPhone model and iOS version. Simulator and e2e results supply no human-row passes. With no new results, the acceptance document and #281 checkboxes remain unchanged; #276 stays open.
One next action for Val: upload Companion 0.4.0 (9) from a verified pinned source containing the question card, then report the uploaded build number, source SHA and TestFlight processing/availability status on #276 so the phone run can be scheduled.
BunsDev commentedon Nov 1, 2026
CF-3 candidate check, 2026-11-01 (
mainat0a8c513)This was a read-only check, and no file changed.
Question path since
6c9000f.git log 6c9000f..origin/mainover the five paths in the prompt finds three commits:9f85d61) is test only: an iPhone UI test now waits for keyboard focus on the secure answer field.afd50ef, OpenCode/MiMo) changescompanion.tsin two lines. It importsisBackendId, and the phone's new-thread check now accepts the new backends. Questions, cards and answers are untouched.c23e6be, LM-3/LM-5) changescodex.ts. Every change sits behindconfiguration.local, andmainnever constructs it, so the cloud Codex path, includingrequestUserInput/Plan mode, is unchanged.The signed v0.4.0 app contains all three. My reading is that the question path is unchanged and the
6c9000fcandidate stands. No re-pin is needed unless Val wants to run on the signed v0.4.0 app instead.Artifacts in
.worktrees/cf3-closeout, which I did not touch:Modex-0.4.0-arm64.dmg: SHA-256f0a77403ad477a5779e0c07c0ffeb2b215ba5feaadc39a41184def190e069573, the same hash docs: pin CF-3 acceptance preparation to its recorded candidate #434 recorded..probes/cf3-disposableis present: an emptygit initrepository.Companion.
project.ymlonmainstill says 0.4.0 (9). I cannot see App Store Connect from here, so it is unconfirmed whether build 9 is on TestFlight.For Val:
MODEX_EVENT_JOURNAL=1for D4. The installed codex-cli is 0.166.0, so record that version when you run the rows.op run --env-file=.env.release -- apps/ios/ModexCompanion/Scripts/release-testflight.sh. P6 also needs an older Companion at hand.All 14 rows are open, and none is passed or deferred. The consolidated "run or defer" list is on #273.
BunsDev commentedon Nov 1, 2026
Val's CF-3 decision, 2026-11-01: “skip voiceover for now and just proceed”. V1–V3 and P5 are deferred for now, not run or passed. #281's checklist now carries that wording beside those rows; their checkboxes remain unticked. The docs-only signed PR #476 preserves the historical table and adds this later decision; it is awaiting Val’s merge go-ahead.
Fetched main at
9ecccc9bcea42ec99cd76092b1fe3bec15d05775; only docs changed since the prepared source candidate85d2c001a73395d5e6e2a1ee388b58253d4bce83. #476 previously passed hosted checks atcd8d50e8eaec5c74e2988403d0ed4cdb161e990c. Its docs conflict with newer CF-8 notes is now reconciled at signed commitb6bbcc6eab7d3e2eea6d19483f80edcb0409cd2b; GitHub reports it mergeable, with fresh checks queued/in progress (run). It remains unmerged pending fresh CI and Val’s go-ahead. Application source is unchanged from the prepared candidate. These checks add no human-row results. Companion remains 0.4.0 (9) with the native question card; its TestFlight upload is still unconfirmed. The refreshed ad-hoc Mac 0.4.1 build is ready at.worktrees/cf3-vo-deferral/apps/desktop/release/Modex-0.4.1-arm64.dmg(SHA-25605ef468da1e50b0e9fa4a43809499043c928f46dd1e5dde101e5bffb895dc36d). The empty disposable repository is.worktrees/cf3-vo-deferral/apps/desktop/.probes/cf3-disposable; use codex-cli 0.166.0, Plan mode and Read only. The build is ad-hoc signed and is not a release artifact. Start itsrelease/mac-arm64/Modex.appwithMODEX_EVENT_JOURNAL=1for D4.Rows: 0 passed, 0 failed, 4 deferred for now (V1–V3, P5), 10 open (D1–D5, P1–P4, P6). No simulator or e2e result is counted as human acceptance. #276 remains open.
Next action for Val: run D1–D5 with the prepared Mac candidate and report each result; VoiceOver is skipped for this pass.