Title: fix(native-chat): reset history when a saved record key is damaged by AmoabaKelvin · Pull Request #37549 · stablyai/orca · GitHub
Open Graph Title: fix(native-chat): reset history when a saved record key is damaged by AmoabaKelvin · Pull Request #37549 · stablyai/orca
X Title: fix(native-chat): reset history when a saved record key is damaged by AmoabaKelvin · Pull Request #37549 · stablyai/orca
Description: Files Added Deleted Net Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$96 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$96 Prod 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$23 $\color{#cf222e}{\Huge{\mathbf{−}}}$9 $\color{#1a7f37}{\Huge{\mathbf{+}}}$14 ELI5 When a saved chat record has a damaged key, a phone reconnecting to that chat now gets a fresh copy of the chat. Before, it got an error and kept retrying the same read. What Changed Before: a client catching up from a cursor got a runtime_error (for a numeric key, invalid journal public outcome key) from agentSession.subscribe or agentSession.history (direction: 'after'). The client reconnected from the same cursor and hit the same record again. Live publishes threw on the same read, so that subscriber went stale. After: the client gets a schema_unreadable reset with a page built from the chat's reduced state, and its cursor moves to the live one, past the damaged record. readJournalOutcomeGroups parsed each key with a bare JSON.parse and plain throws, so damage looked like any other error. It now reports damage as JournalOutcomeDecodeError through decodingOutcome, the same class open uses. readJournalSince, which already returns { ok: false, reset }, maps that class to a reset. reusePromptProjection reads through it too and falls back to a full projection. The ticket says the chat still opens when a superseded record has a damaged key. That holds only in two cases, and the tests cover both: a numeric key whose newest record is a deletion, which admission accepts on reopen; any damaged key that appears while the chat is already open. A garbled key ({damaged) forms its own key group, so open reads it as that group's newest record and still refuses the chat as journalCorrupt after a restart. I left that as it is. Why Mapping in readJournalSince covers every readSince caller. Mapping in readForward would have left the prompt projection throwing during publishes. readJournalRowsAfterCursor has no way to return a reset. The catch is limited to JournalOutcomeDecodeError, and decodingOutcome wraps only the key parse, so a SQLite error stays a retryable error instead of discarding the client's place. journal_read_only still throws, because a reset page built from memory would hide a newer writer. schema_unreadable was already in AGENT_JOURNAL_RESET_REASONS. journal_gap means missing sequences, which isn't what happened here. Linked Issue Fixes STA-13100 Visual Proof N/A. No UI changes. The client handles this reset with its existing reset path. Testing Three regression tests in structured-agent-session-at-rest.test.ts go through the real RPC dispatcher and host, against a real SQLite database on disk: a numeric superseded key after a restart: open works, history and subscribe from a stale cursor reset, and subscribe from the live cursor gets a plain batch; unparseable and non-text keys damaged under an open chat: history resets; a real storage failure (table renamed away): history errors, then succeeds once the table is back. The two damage tests fail on main with a runtime_error reply instead of a reset. The storage test fails if the catch is widened to every error. Ran on macOS, with focused tests and changed-file checks only. I didn't run this in a live app or on a phone. I manually tested these changes locally Automated tests added/updated, or explained why not below Risk The risky part is a stored record that is actually fine but rejected by the key check. That client would get one reset and a fresh page, then carry on from the live cursor. No stored data changes, and intact histories read as before. Older clients are safe: they branch on the frame type, not the reset reason, and the reason was already part of the shared type. Back out with a plain revert. Level: Low AI Disclosure Review Agent skill upstream boundary Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation. Notes Security: no new input trust. Cross-platform: SQLite reads only, no platform branches. Remote SSH and mobile: both use the same host read, and the reset frame already exists on the wire. Performance: one closure per key on a read that already parses JSON per key. Checklist This PR is small and focused I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives) I stated the risk: what could break, for whom, and how to back it out Before/after screenshots or videos attached for UI changes, or N/A with reason Self-reviewed for correctness, security, and performance Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A) pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)
Open Graph Description: Files Added Deleted Net Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$96 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$96 Prod 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$23 $\color{#cf222e}{\Huge{\mat...
X Description: Files Added Deleted Net Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$96 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$96 Prod 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$23 $\color{#cf222e}{\Huge{\mat...
Opengraph URL: https://github.com/stablyai/orca/pull/37549
X: @github
Domain: github.com
| react-profiling | 0 |
| react-import-map | react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf |
| route-pattern | /:user_id/:repository/pull/:id/files(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:359228cd-f83b-0782-b405-600ec7c9926c |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | CD46:2B933C:D2DCA:111ADE:6AEBE044 |
| html-safe-nonce | c1f20350af27d2efb12805c5340628f59b1580b843a953d0a46da992aafe9128 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDRDQ2OjJCOTMzQzpEMkRDQToxMTFBREU6NkFFQkUwNDQiLCJ2aXNpdG9yX2lkIjoiMjQwMDIyODE4NTgwNzI0OTQ3NiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | adac6b5623246a679a27736c9f23aadbed96abbfbeac5671bbeed7b894155b11 |
| hovercard-subject-tag | pull_request:5127384048 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/stablyai/orca/pull/37549/files |
| twitter:image | https://avatars.githubusercontent.com/u/97001695?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/97001695?s=400&v=4 |
| og:image:alt | Files Added Deleted Net Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$96 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$96 Prod 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$23 $\color{#cf222e}{\Huge{\mat... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | 701f7e3aecc56e7594e73fa7b7e1483af74322a67f7038be453d0feb05e86e77 |
| turbo-cache-control | no-preview |
| diff-view | unified |
| go-import | github.com/stablyai/orca git https://github.com/stablyai/orca.git |
| octolytics-dimension-user_id | 127256420 |
| octolytics-dimension-user_login | stablyai |
| octolytics-dimension-repository_id | 1183888342 |
| octolytics-dimension-repository_nwo | stablyai/orca |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1183888342 |
| octolytics-dimension-repository_network_root_nwo | stablyai/orca |
| turbo-body-classes | logged-out env-production page-responsive full-width |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 12d1048a3491dd63e4193b2937cf72f1c24a2a52 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width