Skip to content

feat(response): persist in-progress events across restart - #174

Closed
cursor[bot] wants to merge 4 commits into
mainfrom
cursor/bc-b3c36c69-8e1a-4c9d-9230-611b5eae7696-c8eb
Closed

feat(response): persist in-progress events across restart#174
cursor[bot] wants to merge 4 commits into
mainfrom
cursor/bc-b3c36c69-8e1a-4c9d-9230-611b5eae7696-c8eb

Conversation

@cursor

@cursor cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Why

Protected main can freeze a completed response snapshot, but a buyer still loses in-progress answers on process restart. A two-item Korean Big Five path that has not completed cannot be scored or continued from durable evidence.

This is independent of Active PR #161/#149 (session HTTP), #154 (session command lock), #151 (completed snapshot reload), and #162 (restricted linkage). Do not fold those slices into this head.

What

  • ResponseLedger::from_persisted rebuilds server sequence 1..n after restart without re-checking live session activity.
  • migrations/0020_response_event.sql stores opaque event identity, session binding, client idempotency, item version, payload digest, server sequence, and distinct observed/received timestamps.
  • persist_response_ledger / load_response_ledger use READ COMMITTED insert-then-classify. Exact replay is idempotent; client, server, sequence, or session rebinding fails closed.

Out of scope

  • HTTP POST /v1/sessions/{session_ref}/responses
  • Raw response bodies
  • Completed snapshot changes (#55 / #151)
  • Session persist/HTTP (#161 / #149 / #154)

Test plan

  • cargo test --test response_ledger
  • cargo test --lib postgres_response_event
  • cargo test --test documentation_architecture_contract --test traceability_active_pr_contract
  • cargo clippy --all-targets -- -D warnings
  • cargo test --test postgres_response_event_persistence --test postgres_response_event_error_contract (needs TEST_DATABASE_URL)

Do not merge until exact-head checks and independent last-push approval are satisfied. Do not self-approve.

Open in Web View Automation 

cursoragent and others added 3 commits August 16, 2026 16:10
A two-item path can now reload the same answers after restart without
re-checking live session activity. Gapped sequence, reused client or
server identity, and blank session references fail closed.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Store accepted response_event rows with observed and received time so a
two-item path reloads the same answers after process restart. Exact
replay is idempotent; client, server, sequence, or session rebinding
fails closed under READ COMMITTED.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
@cursor
cursor Bot requested a review from seonghobae August 16, 2026 16:13
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
cursor Bot pushed a commit that referenced this pull request Aug 16, 2026
Match the ERD and #174 temporal contract so source-valid time cannot
replace platform receipt time, and fail closed on inverted or rebound
timestamps.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Same mid-session persist slice as #182. Keep the observed/received time contract, but do not land this head beside #182. Prefer #182, which adds restart scoring-prefix proof, recovery copy of response_event, and the same temporal fail-closed checks.

Do not merge #174 or #53 in parallel.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Verdict: COMMENT

HEAD 71c751497f47cfc50eb9384268b5b2fa3104a601 persist/load is sound. I did not find a fail-open, 3NF, naming, injection, or idempotency defect that should block this slice.

Do not APPROVE and do not merge: the PR is draft, Runtime CI was still queued at review time, and independent last-push approval is still required. Do not self-approve.

What holds

  • Product persistence only. No bodies, no scores, no fast-mlsirm kernels.
  • response_event names are two-or-more-word snake_case. Public refs stay opaque TEXT with the shared numeric-like CHECK.
  • Unique (session_ref, client_event_ref) and (session_ref, server_sequence) plus observed_at <= received_at match ADR-0015.
  • persist_response_ledger / load_response_ledger use parameterized SQL and exact SHOW transaction_isolation = read committed.
  • The insert-then-classify CTE is the safer READ COMMITTED shape. Exact PK replay is Duplicate and does not overwrite times. Client/item/digest mismatch is ConflictingReplay. Sequence reuse is SequenceConflict. Session rebinding of the same server ref is ConflictingReplay. Gapped stored history fails closed.
  • Domain tests cover the two-item Korean path, gapped/rewound sequence, and reused identities. PostgreSQL tests cover exact replay, rebinding, inverted/zero/arity time, Repeatable Read rejection, and a deleted-prefix gap.

Do not prefer #182 blindly

#182 (86e5669) adds recovery COPY, AS_BUILT, and a scoring-prefix persist proof. It does not make this head obsolete:

  • This head persists a whole ledger in one transaction. #182 persists one event and leaves the loop to the caller.
  • This head returns None for a missing session. #182 returns an empty ledger, which hides “never stored” versus “empty persist”.
  • Both migrations already store observed_at / received_at. #182’s AS_BUILT text omits those columns.

Keep #174, #182, and #53 draft. Do not land them in parallel. The landing vehicle needs this head’s ledger API and #182’s recovery/AS_BUILT/scoring-prefix proof.

Residual gaps on this head

  1. tests/postgres_recovery_invariants.rs still COPY-restores only outbox/inbox/consumption/snapshot. In-progress answers are not restore-proven.
  2. docs/architecture/AS_BUILT_SCHEMA.md does not name migrations/0020_response_event.sql.
  3. ADR-0015 cites Berenson et al. (1995) and ISO 8601-1, but docs/doctoring/standards-and-evidence.md still lacks the isolation paper.
  4. No persist test does load → record item 3 → persist → reload, so continue-after-restart is implied rather than proven.
  5. UML ResponseEvent still omits observed/received time.

Next buyer action

Close those evidence gaps on one landing vehicle, then keep HTTP POST /v1/sessions/{session_ref}/responses off this branch. That later slice must load the stored ledger before record(), then persist with distinct observed vs received time, and reject new answers unless the session is Active.

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

Comment thread src/postgres_response_event.rs
Comment thread src/postgres_response_event.rs
Comment thread docs/TRACEABILITY.md
Comment thread tests/postgres_response_event_persistence.rs

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Review

Do not land this head. The response_event persist landing is #182 (4dd8e6d). That successor also reloads distinct observed/received clocks after restart.

Keep this PR Draft. Do not add HTTP or snapshot-reload here. Prefer #182 over #53 and snapshot-only #151.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

cursor Bot pushed a commit that referenced this pull request Aug 16, 2026
Prefer this head over #174, #182, and #53 so later agents do not open
another overlapping response_event persist slice.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Prefer #201 as the response_event persist landing vehicle.

This head (71c7514) remains sound, but #201 adds stored-time reload, InvalidEventTimeArity, recovery COPY, AS_BUILT, doctoring isolation citations, and the load → record item 3 → persist → freeze scoring-prefix proof.

Keep #174, #182, and #53 draft. Do not land them in parallel with #201. Independent last-push approval is still required. Do not self-approve.

Next buyer slice after #201 lands: HTTP POST /v1/sessions/{session_ref}/responses on #195, not on this branch.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

cursor Bot pushed a commit that referenced this pull request Aug 16, 2026
Prefer this head over #201, #174, #182, and #53. Recovery COPY now
asserts first-write times; HTTP response transport stays outside.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Do not merge this persist slice.

Prefer PR #208 for in-progress response_event persist/load, first-write observed/received times, recovery COPY proof, and continue-after-restart scoring prefix.

This head is an earlier overlapping persist attempt. Landing #174, #182, #201, and #53 in parallel would fight over the same table and reconstruction contract. HTTP responses stay on #195. Independent last-push review is still required on #208. Do not self-approve.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

Copy link
Copy Markdown
Contributor

Closing as superseded by PR #201. #201 explicitly carries this durable response-prefix work and adds the missing recovery COPY, AS_BUILT/doctoring evidence, persisted observed/received-time reload, arity failure contract, and continue-after-restart scoring-prefix proof. Its current scope says to prefer #201 over #174/#182/#53 and not land these overlapping persistence slices in parallel. Continue on #201 or its later successor.

@seonghobae seonghobae closed this Aug 16, 2026
cursor Bot pushed a commit that referenced this pull request Aug 16, 2026
Prefer the continue-from-reload successor over #182 and the overlapping
#174/#201 persist slices. HTTP response transport stays outside this head.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
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.

2 participants