Skip to content

[feat] /goal v2 production harden - #55

Merged
echobt merged 6 commits into
mainfrom
cursor/goal-v2-production-harden-a28e
Sep 9, 2026
Merged

[feat] /goal v2 production harden#55
echobt merged 6 commits into
mainfrom
cursor/goal-v2-production-harden-a28e

Conversation

@echobt

@echobt echobt commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Production harden of /goal long-horizon persisted goals for the next Cortex CLI release (0.1.11).

This follow-up to the merged /goal tip keeps Cortex session harness state (persist, continue, wrap up). It does not add a second coding provider.

  • Persist: atomic + fsynced goal.json; corrupt or empty-objective files are quarantined so session resume continues
  • Quarantine status is honest: if goal.json cannot be moved aside, the reason says it remains in place
  • Load never deletes .goal.json.tmp.*, so a concurrent save's in-flight temp cannot be stolen (writer rename no longer ENOENT)
  • Commands: /goal status is a reserved status token; pause/resume/clear stay reserved only as the entire argument
  • Continuation: record a finished turn, then wrap-up/continue so the last remaining turn still runs
  • Evidence: UpdateGoal complete accepts only file / command / test (normalized, globally deduped — not adjacent-only)
  • UX: status, pause, resume, and session resume print the chip (Goal · 2/8 / paused / done / budget / blocked)
  • Version: 0.1.11 in VERSION_CLI, workspace package metadata, src/cortex-cli/VERSION, SDK package, changelog, and OpenAPI info version
  • CI: Test job artifact uploads continue-on-error so a FinalizeArtifact HTTP 403 cannot fail the job after tests, doctests, contracts, and local QA already passed

Tip: 7fcedca9cd19a297ef9ae7970328c439f5bff77f (echobt).

Test plan

  • cargo fmt --all -- --check
  • cargo test -p cortex-engine --lib goal::persist:: — 9 passed, including two-process child-temp vs parent load
  • CI on this tip (Format, Clippy, Test, TUI, audit, version, coverage, source policy)

Attestation (required)

I attest that:

  • Security reviewed — auth, exec/sandbox, path traversal, network egress, and secret handling in this diff were reviewed. No secrets, tokens, or keyring dumps are in the change. Live /goal smoke still SKIP without an operator-injected key. Load never deletes another writer's goal temp.
  • Product-facing errors — user-visible failures use Cortex product copy. API-down paths say The coding service is temporarily unavailable. No raw provider, SDK, or transport names. Quarantine copy no longer claims a move that failed.
  • TUI verified — composer chip lock boards keep text-only copy (Goal · 2/8 / paused / done / budget / blocked). This revision does not change chip copy.
  • Tests added — unit tests cover persist quarantine (including rename failure), global evidence dedup, load leaving temps in place, in-flight writer rename after load, and a two-process child writer. No mocks that report success.
  • No secrets — no API keys, WorkOS secrets, R2/AWS credentials, or .env files are included.

Risk

Harness-only /goal state on the session directory. Resume now survives a corrupt goal.json instead of failing the session. Leftover .goal.json.tmp.* from a crashed writer are no longer auto-deleted on load (hidden files; the next save uses its own pid-scoped temp).

Do not merge until Protect has the required review (Designer cli).

Open in Web Open in Cursor 

echobt and others added 2 commits September 8, 2026 15:24
Co-authored-by: Mathis <echobt@users.noreply.github.com>
Co-authored-by: Mathis <echobt@users.noreply.github.com>
@echobt
echobt marked this pull request as ready for review September 8, 2026 15:39
Co-authored-by: Mathis <echobt@users.noreply.github.com>
@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown

Greptile Summary

This change improves goal persistence and recovery behavior, but concurrent session activity can still discard a goal update. The concurrent-save issue must be resolved before merging; the corrupt-file reporting and legacy evidence cleanup issues are non-blocking but should be addressed for accurate recovery and status output.

Confidence Score: 4/5

Not safe to merge until concurrent goal saves cannot be interrupted by temporary-file cleanup. The remaining confirmed issues are non-blocking persistence and display consistency concerns.

A reproduced concurrent persistence failure can prevent a user's updated goal state from being saved. Two additional reproduced issues affect recovery messaging and duplicate legacy evidence display.

Files Needing Attention: src/cortex-engine/src/goal/persist.rs needs synchronization or stale-file detection for cleanup and accurate quarantine error handling. src/cortex-engine/src/goal/types.rs needs order-preserving global evidence deduplication.

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced a proof for a posted P1 finding and linked it to the corresponding review comment.
  • T-Rex produced proofs for posted P2 findings and attached the corresponding review comments as evidence.
  • A general-contract-validation proof shows the before and after outcomes of the concurrency-cleanup test, with the before state confirming SAVE_OK and the after state showing a missing loader and an IO error on save.
  • A general-contract-validation proof documents the quarantine-rename failure harness, including the authored before source and the after-test output.
  • A general-contract-validation proof describes the non-adjacent-evidence harness run, including the before/after outputs and duplicated file entries visible in the artifacts.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (3)

  1. General comment

    P1 Goal temporary-file cleanup can abort another process's in-flight atomic save

    • Bug
      • load_goal_report calls cleanup_stale_tmps, which removed a temporary file currently being written by a separate save_goal process. The writer then failed its std::fs::rename(tmp, goal.json) with ENOENT, so its new state was not persisted.
    • Cause
      • cleanup_stale_tmps at src/cortex-engine/src/goal/persist.rs:107-119 treats every matching temporary filename as stale. durable_atomic_write creates names with the matching .goal.json.tmp.<pid> pattern at :127-131, but cleanup neither identifies whether that PID is active nor applies an age threshold or locking protocol.
    • Fix
      • Do not delete matching temporary files solely by name. Coordinate writers and cleanup with a lock and/or use unique temp names plus an age threshold; at minimum, retain files associated with a live process and only remove demonstrably stale entries.

    T-Rex Ran code and verified through T-Rex

  2. General comment

    P1 Failed goal quarantine is reported as successful

    • Bug
      • When goal.json contains invalid JSON and renaming it to goal.json.corrupt fails, load_goal_report still returns GoalLoad::Quarantined using the message “goal.json was unreadable. Moved aside so the session can resume.” The corrupt source remains in place, so every subsequent resume/reload repeats the same misleading result.
    • Cause
      • quarantine at src/cortex-engine/src/goal/persist.rs:99-105 intentionally ignores std::fs::rename(path, &dest) at line 101 and unconditionally constructs GoalLoad::Quarantined at lines 102-104.
    • Fix
      • Propagate or explicitly represent the rename failure rather than returning Quarantined; for example, make quarantine return Result<GoalLoad> and return the rename I/O error, or add a distinct non-success load result whose user message states that the corrupt file could not be moved.

    T-Rex Ran code and verified through T-Rex

  3. General comment

    P2 Non-adjacent legacy evidence duplicates persist and display twice

    • Bug
      • A legacy goal whose normalized evidence is [file: src/lib.rs, command: cargo test, file: src/lib.rs] loads with all three entries. Re-saving writes both file entries back to goal.json, and /goal-style status_text displays both.
    • Cause
      • Goal::sanitize canonicalizes and preserves input order, then invokes Vec::dedup_by at src/cortex-engine/src/goal/types.rs:182-183. That API compares neighboring elements only, so the intervening command prevents the first and third equivalent file evidence records from being considered duplicates.
    • Fix
      • Replace adjacent-only deduplication with order-preserving global deduplication keyed by (kind, detail) after normalization (for example, retain items while tracking seen pairs in a HashSet). Add a regression test covering [Path A, shell B, FILE A] through load/save/display.

    T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "test(tui): restore goal event adapter te..." | Re-trigger Greptile

Comment thread src/cortex-engine/src/goal/persist.rs Outdated
Comment thread src/cortex-engine/src/goal/persist.rs Outdated
Comment thread src/cortex-engine/src/goal/types.rs Outdated
echobt and others added 3 commits September 8, 2026 15:59
Do not delete another process's in-flight goal temp on load.
Only drop leftovers whose owner pid is gone. Say so when a
corrupt goal.json cannot be moved aside, and dedup evidence
across the whole list rather than adjacent pairs only.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
Child::wait needs a mutable Child; the unix leftover-temp
regression was not compiling under libtest.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
Load no longer scans or removes .goal.json.tmp.* files. A
concurrent save can keep its in-flight temp, then rename it
onto goal.json instead of failing with ENOENT.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
@echobt
echobt merged commit 2ba757d into main Sep 9, 2026
20 checks passed
@echobt
echobt deleted the cursor/goal-v2-production-harden-a28e branch September 9, 2026 04:11
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