Skip to content

Latest commit

 

History

History
94 lines (85 loc) · 13.1 KB

File metadata and controls

94 lines (85 loc) · 13.1 KB
id 20260507-698664c-resume-followups
title cbth Resume Follow-ups
status completed
created 2026-05-07
updated 2026-05-07
branch wip/cbth-resume-followups
pr #45
supersedes
superseded_by

cbth Resume Follow-ups

Summary

  • Complete the three follow-ups deferred from PR #43 in order: native resume cwd UX parity, canonical permissionProfile read-side parsing, and soft Codex CLI version compatibility warnings.
  • Keep cbth resume <thread-id> [-- <codex_args>] on the managed app-server / sidecar path while avoiding silent caller-cwd override when the operator did not provide --cd.
  • Treat codex-cli 0.128.x as the currently validated range and warn, rather than fail, when the local Codex CLI reports a different or unparsable version.

Current State

  • cbth resume now forwards a single explicit cwd only when --cd / -C is supplied or an interactive cwd selection has been made. Non-interactive no-override resumes omit --cd, so the native resume path can preserve the previous thread cwd instead of forcing the caller cwd.
  • In interactive terminals, cbth resume reads the previous thread cwd with thread/read(includeTurns=false) before startup materialization and prompts between the prior thread cwd and the current cwd when they differ.
  • The managed app-server lease refresher starts before any interactive cwd prompt, so an operator pause cannot let the app-server reservation expire before the foreground codex resume process launches.
  • Auto permission snapshots prefer thread/resume.permissionProfile when available. Legacy approvalPolicy / sandbox remains the fallback, and canonical/legacy disagreement on derived network or write permissions fails closed.
  • Startup, current, effective, and audit snapshot JSON now records the permission snapshot source and canonical profile body when present. Request-side turn/start pinning still emits legacy approvalPolicy / sandboxPolicy because Codex 0.128 exposes canonical profile state on the read side while accepting legacy override fields.
  • Managed startup and cbth doctor cli run codex --version, report compatibility details, and warn when the local CLI is outside 0.128.x; protocol parsing remains the fail-closed safety gate.

Next Steps

  • Continue the broader CLI / daemon recovery backlog from current follow-ups.
  • Revisit request-side exact permission-profile pinning only after Codex exposes a turn/start override field for canonical profiles.

Evidence

  • Base: 698664c from PR #43; branch also merges bcc86b7 / v0.1.1 before review.
  • Branch: wip/cbth-resume-followups.
  • Review:
    • Internal codex-review on the initial branch range reported no blocking findings.
    • External bounded review found that the interactive cwd prompt could outlive the pre-refresher app-server lease; the follow-up fix starts lease refresh before cwd resolution and extends the no---cd resume test to assert the initial sidecar thread/resume omits cwd.
    • Internal review then found a permission-profile/legacy write-scope mismatch hole; the fix now rejects canonical profiles whose write entries do not cover legacy writable roots, tmp access, or external sandbox shape.
    • Internal codex-readonly fallback found that thread/read cwd parsing only handled nested thread.cwd, and that permission drift did not report permissionProfile body changes. The final fix accepts both nested and top-level cwd response shapes and records permission_profile drift when the canonical body changes.
    • Final internal codex-readonly review on origin/master..HEAD returned LGTM.
    • Clean-context reviewer on PR #45 found that interactive resume cwd probing accepted thread/read cwd without proving the response belonged to the requested thread. The fix now requires nested thread.id, top-level id, or top-level threadId to explicitly match before using cwd, and treats missing/foreign ids as no history cwd so native no---cd fallback remains intact.
    • Codex PR review gate found that canonical permissionProfile workspace writes can use special.kind: "project_roots" in normal Codex 0.128 responses. The fix treats unsuffixed project_roots as covering legacy workspace writable roots while still rejecting narrower project_roots subpaths as unrepresentable for legacy sandbox pinning.
    • A later clean-context review found four follow-up gaps: mixed-shape thread/read cwd identity, permission-affecting --config forwarding, malformed canonical permissionProfile shapes, and nested-root drift direction. The next fix requires the cwd-bearing nested thread to carry a matching id, rejects known sandbox-scope config overrides, validates canonical profile object/network/fileSystem shapes strictly, and computes root drift by normalized containment instead of exact string-set subset checks.
    • Follow-up clean-context review found that the --config guard missed canonical permission config roots. The guard now also rejects sandbox_permissions.*, permissions.*, and likely permission-profile aliases until those overrides can be represented in the sidecar's initial thread/resume.
    • Follow-up clean-context review found that read-only canonical profiles with nested access: "none" denials were accepted even though automatic turn/start can only emit legacy sandbox fields. The parser now fail-closes any canonical deny scope until exact permission profile pinning exists.
    • A further clean-context review found canonical read allow scopes could also be narrower than legacy readable roots. The parser now requires canonical read/write coverage to cover legacy access / readOnlyAccess readable roots before trusting a canonical profile.
    • Follow-up clean-context review found --config default_permissions=... also selects a canonical permission profile while bypassing initial sidecar resume params. The managed resume config guard now rejects default_permissions / default-permissions / defaultPermissions, and resume arg validation now runs before daemon startup so invalid forwarded args fail before managed flow setup.
    • Follow-up clean-context review found --search could enable the native web_search tool in foreground Codex while the sidecar initial thread/resume still recorded a no-network permission snapshot, and found nested cwd reads could ignore contradictory top-level thread ids. The latest fix rejects forwarded live web-search enablement until it can be represented in initial resume params and validates all present thread/read ids before using any cwd.
    • Follow-up clean-context review found direct foreground permission overrides, unrepresentable canonical read scopes, and mixed-id activity snapshots were still accepted. The latest fix rejects forwarded --sandbox / --ask-for-approval / danger-bypass plus matching config keys, fail-closes canonical read scopes that cannot be pinned with legacy sandbox fields, and validates all present ids on activity / turn-status snapshots.
    • GitHub Codex review and clean-context follow-up found web-search aliases and inline config tables could still bypass the deny list. The fix now treats web_search_request as live web-search and rejects top-level features, top-level web_search*, and top-level / nested tools.web_search* managed-resume config overrides.
    • Follow-up clean-context review found Codex permission aliases and indirect config roots could still make foreground Codex diverge from the sidecar startup snapshot. The fix now rejects forwarded --full-auto / --yolo aliases plus permission-affecting profiles.*, projects.*, and trust_level config overrides.
    • Follow-up clean-context review found Codex options placed after the resume prompt were not scanned, so foreground Codex could still apply permission, web-search, cwd, or profile overrides that the sidecar did not mirror. Managed resume now fail-closes any forwarded option after the prompt unless the operator uses an explicit -- sentinel for literal prompt text.
    • Follow-up clean-context review found non-search feature toggles such as use_legacy_landlock / request_permissions could still be forwarded through --enable / --disable or equivalent config aliases without being carried in the sidecar's first thread/resume. Managed resume now rejects all forwarded feature overrides and all features.* / top-level known feature config roots until feature state can be mirrored exactly.
    • Follow-up clean-context review found provider selection (--oss / --local-provider) and unmirrored config keys such as model_reasoning_effort could still let foreground Codex diverge from the sidecar's first thread/resume. Managed resume now rejects provider overrides and only accepts config keys that are explicitly mirrored into initial resume params.
    • GitHub review-gate found TOML quoted config keys such as "sandbox_mode" and tools."web_search".context_size could bypass the managed-resume deny list. Config key matching now normalizes quoted dotted key segments before deciding whether a key is mirrored, permission-affecting, or unsupported.
    • Follow-up clean-context review found native resume selector flags (--last, --all, --include-non-interactive) could retarget foreground Codex independently of the managed bound thread id. Managed resume now rejects those selectors before daemon/app-server startup.
  • Validation:
    • cargo fmt --all -- --check
    • cargo clippy --locked --all-targets -- -D warnings
    • cargo test --locked
    • cargo test --locked thread_read_cwd_reads_nested_and_top_level_shapes --lib
    • cargo test --locked thread_read_cwd --lib
    • cargo test --locked permission_snapshot_rejects_malformed_permission_profiles --lib
    • cargo test --locked permission_drift_tracks_nested_workspace_roots_by_containment --lib
    • cargo test --locked permission_snapshot_rejects_permission_profile_denials_for_legacy_read_only --lib
    • cargo test --locked permission_snapshot_rejects_permission_profile_narrower_than_legacy_readable_root --lib
    • cargo test --locked permission_snapshot_accepts_project_roots_permission_profile_for_legacy_workspace_write --lib
    • cargo test --locked permission_snapshot_rejects_project_roots_subpath_for_legacy_workspace_write --lib
    • cargo test --locked cbth_resume_rejects_permission_affecting_config_overrides --test cli_run (including canonical permission config root cases)
    • cargo test --locked cbth_resume_rejects_permission_affecting_config_overrides --test cli_run after adding default_permissions aliases to the rejection matrix.
    • cargo test --locked thread_read_cwd_rejects_missing_or_foreign_thread_id --lib
    • cargo test --locked cbth_resume_rejects_forwarded_live_web_search --test cli_run
    • cargo test --locked cbth_resume_rejects_forwarded_permission_policy_overrides --test cli_run
    • cargo test --locked permission_snapshot_rejects_unrepresentable_permission_profile_read_scopes --lib
    • cargo test --locked thread_result_activity_snapshot_rejects_missing_or_foreign_thread_id --lib
    • cargo test --locked thread_result_turn_status_reads_top_level_turns_with_thread_metadata --lib
    • cargo test --locked cbth_resume_rejects_forwarded_live_web_search --test cli_run after adding web_search_request aliases.
    • cargo test --locked cbth_resume_rejects_permission_affecting_config_overrides --test cli_run after adding features / web_search / tools.web_search aliases.
    • cargo test --locked cbth_resume_rejects_forwarded_permission_policy_overrides --test cli_run after adding --full-auto / --yolo aliases.
    • cargo test --locked cbth_resume_rejects_permission_affecting_config_overrides --test cli_run after adding profiles.* / projects.* / trust_level overrides.
    • cargo test --locked cbth_resume_rejects_post_prompt_forwarded_options --test cli_run
    • cargo test --locked cbth_resume_rejects_forwarded_live_web_search --test cli_run after broadening feature override rejection to all --enable / --disable values.
    • cargo test --locked cbth_resume_rejects_permission_affecting_config_overrides --test cli_run after broadening config rejection to all features.* plus use_legacy_landlock / request_permissions.
    • cargo test --locked cbth_resume_rejects_forwarded_provider_overrides --test cli_run
    • cargo test --locked cbth_resume_rejects_unmirrored_config_overrides --test cli_run
    • cargo test --locked cbth_resume_rejects_permission_affecting_config_overrides --test cli_run after adding TOML quoted-key normalization cases.
    • cargo test --locked cbth_resume_rejects_forwarded_thread_selectors --test cli_run
    • cargo test --locked permission_drift_tracks_permission_profile_body_changes --lib
    • CARGO_TARGET_DIR=.codex-tmp/cargo-target-precommit git commit -S ... pre-commit hook passed cargo fmt --all, cargo clippy --locked --all-targets -- -D warnings, and cargo test --locked in an isolated target directory after the shared target produced a cross-worktree binary mismatch.
    • uv run python /Users/hoteng/.codex/skills/project-journal/scripts/project_journal.py validate --repo /Users/hoteng/.codex/worktrees/aef0/codex-background-task-handler