| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
harden(app): CaptureLifetime — every capture timer, subscription and listener is cancelled on dispose (#14361) * harden(dev-harness): define V1 live-session and V8 spine contracts Add strict Python/Dart pending contracts and introducing-commit protection. Reserve the live-session CLI, wire, ownership/attachment seams and failing builder acceptance tests. Add live attribution before freezing evidence v1. Verification: - bash scripts/dev-harness/run-tests.sh: 287 passed, 7 existing skips, 40 strict xfailed (24 pending V1 markers), Python 3.11.15. - make preflight: 16 checks passed, using supported PYTHON selection. - make mobile-verify fast --paths harness/session contract inputs with an absolute evidence directory: 20 executed, 20 passed, no failures/skips. - bash app/test.sh: 2014 passed, 5 skipped, one unchanged UTC+7 search_rank_grouping_test failure; affected baseline inputs match main. - Real module CLI refusals exit 2 without traceback; regression covered. - Dart SDK probe proves ext. prefix required; marker-removal formatter probe proves no incidental Dart diff. Runtime is intentionally unimplemented. App UI must repair current invalid VM extension names before live acceptance; unsupported journeys block. Simulator/emulator latency and detached-process acceptance remain V1 work. make setup installed hooks but full backend wheel sync stalled; isolated Python 3.11 harness dependencies ran the owner checks without any skip flag. Failure-Class: none * harden(dev-harness): scope the spine-contracts check to spine paths The check protects files under the spine roots and their registry, so it only needs to run when those change. A repo-wide trigger would run it, and its full-history requirement, on every unrelated contributor PR. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs(dev-harness): clarify the live journey adapter boundary V1 must refuse live journey execution until a shared executable adapter exists; B1 addressability alone cannot attach Dart integration tests. Pure admission contracts remain valid with injected supported IDs. Verification: harness 287 passed, 7 skipped, 40 strict xfailed; make preflight passed 20 checks. * harden(app): define capture ownership and seam contracts C1 pending contracts specify recovery, foreground service, socket and session ownership; no existing runtime path changed. Verified UTC app suite (2041 passed), harness (287 passed, 7 skipped, 40 strict xfailed), 20 hermetic journeys, and 21 preflight checks. * harden(app): close capture adoption and late-completion contract gaps Specify inventory revision coalescing without losing explicit retries, late location-upload/finalization fences, and zero legacy actor adoption checks. Existing protected tests are unchanged. UTC app: 2048 passed; harness: 287 passed, 7 skipped, 40 strict xfailed; preflight: 21 passed. Correction to earlier verification record: C1 selected 3 journeys, all passed, not 20. One intermediate unchanged baseline replay test returned zero restored WALs; the full final run passed and its exact failure is retained in .local/c1-app-final.log. * harden(dev-harness): pin reviewed spine revisions and align B0 capabilities Coordinator turn-4 review authorizes the V1 fixture correction. Exact before/after digests pin the revised oracle; immutable revision records do not permit builder assertion edits. Active tests reject missing/tampered records and prove the fake machine response. Verification: full harness 289 passed, 7 skipped, 40 strict xfailed; UTC app 2020 passed; spine 24 pending/7 protected; make preflight 16 passed. No live device acceptance claimed. * harden(dev-harness): preserve marker retirement across spine revisions Track retained marker occurrences rather than counts so retiring a second test cannot restore the first test's retired marker. The active regression covers this swap and legitimate continued retirement. Verification: full harness 290 passed, 7 skipped, 40 strict xfailed; spine 24 pending/7 protected; make preflight 16 passed. Dart sources unchanged after the earlier UTC app 2020-pass run. * harden(dev-harness): retain corrected spine oracles through squash merges A squash can introduce a corrected contract and its review records in the same commit. Absorb only the revision prefix ending at that introducing file's exact digest, preserving immutable records and later marker-only edits. Active temp-repo regression covers multiple corrections in one squash and rejects restoring old or altered assertions. Verification: harness 291 passed, 7 skipped, 40 strict xfailed; B1 make preflight 20 passed; final B1 journeys 20/20. Dart unchanged after UTC app 41 opt-in and 2051 ordinary passed. * test(dev-harness): revise live session acceptance after builder review * test(app): scope capture ownership adoption and exercise real effects * test(dev-harness): bind machine fixture to actual child identity * test(app): keep capture adoption scoped to ownership extractions * docs: align capture contributor guidance with staged adoption * harden(app): implement CaptureLifetime resource bag Timers, streams, and owned cancels drain on close even when one cancel fails. Close is idempotent and invalidates first, so a late acquisition after close dies immediately. Co-authored-by: Cursor <cursoragent@cursor.com> * harden(app): untrack CaptureLifetime resources on fire and cancel A day-long capture session would pin one dead cancel closure per once()/listen() that completed on its own. Release on fire, caller cancel, and stream done so the bag only holds live work. Co-authored-by: Cursor <cursoragent@cursor.com> * harden(app): join in-flight CaptureLifetime close and keep terminal bookkeeping A second close() while the first is still draining must wait for the same completion, asFuture must untrack even after it replaces inner callbacks, and replacement data/error/done handlers must not run after close begins. Co-authored-by: Cursor <cursoragent@cursor.com> * harden(app): join explicit CaptureLifetime cancellation until it finishes Untracking a callback is not the same as teardown completing; close now waits for in-flight own/subscription cancels without running them a second time. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(app): record that CaptureLifetime close joins in-flight cancellation Co-authored-by: Cursor <cursoragent@cursor.com> * test(app): register the CaptureLifetime drain spine file Co-authored-by: Cursor <cursoragent@cursor.com> * chore(app): restore memories/page.dart to origin/main after merge format The merge-forward pre-commit hook reindented main's file and tripped INV-MEM-1 on a formatter-only diff. Lifetime does not own that page. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(app): restore dart format on merge-forward trailing-comma splits Conflict resolution dropped trailing commas while keeping a split layout the formatter will not emit. Let dart format rewrite those 14 files; no semantic change. Co-authored-by: Cursor <cursoragent@cursor.com> * harden(app): retire the five satisfied C1 lifetime pending markers #14327 landed c1_lifetime_review_test.dart and c1_lifetime_terminal_test.dart on main with pendingContract('C1') still set. The behaviour they pin was already implemented on this branch by f04ec71709 and acdc197180, so after the merge-forward all five executed green and the contract harness failed them as XPASS ("remove the pending marker") rather than as unmet contracts. No implementation change is required, and none is made here; only the five stale markers are removed, which is the one edit the spine protection allows. What each contract pins, and the capture_lifetime.dart behaviour that satisfies it: - concurrent close joins outstanding cancellation: a second close() used to hand back a fresh completed future and report teardown finished while the first drain was still awaiting an own() cancel. close() now short-circuits only on _closeFinished and otherwise returns the memoised _closing future, so every caller joins the same drain. - asFuture preserves completion untracking: _inner.asFuture replaces the subscription's done handler, so the listen-time drop() never ran and the registration outlived its future. _LifetimeSubscription.asFuture now chains whenComplete(_drop). - C1 asFuture error completion releases its registration: the same path on the error completion - whenComplete(_drop) untracks on throw as well as on done. - replaced callbacks and errors stay closed while cancellation drains: a handler installed through onData/onError after listen bypassed the closed guard and could still fire while close() was blocked on an earlier release. Those wrappers now consult _isClosed() before forwarding. - C1 original and replacement done callbacks respect closing: both the listen-time onDone wrapper and an onDone replacement now drop() the registration but return without calling the owner once _closed is set. Verified in this worktree at app/: flutter test 2161 passed, 0 failed. scripts/check_spine_contracts.py exit 0, 69 pending markers (was 74), 27 protected files. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> | 24 天前 | |
fix(conversations): title every kept row; offer Retry only when it can succeed (#19951) * fix(conversations): title every kept row; offer Retry only when it can succeed Server: every terminal that moves a processing row into the default list (finalization dead-letter, BYOK abandonment, crash-orphan recovery) replaces an empty generated title with the model-free deterministic_minimum_title, decoded from the transactional snapshot (enhanced rows included). The dead-letter also sets a new additive Conversation.summary_retryable=true only after a transient failure (final_attempt_failed / processing_failed) on a row with transcript or photos and no earlier summary. recovery_structure_unavailable never sets it. Enrichment and the free-tier terminal persist clear it with an explicit null. A new processing_state enum value was rejected by the released app-client compatibility gate, so the marker is a separate optional field. Mobile: parse summary_retryable; the list row and the detail Summary tab show "Summary failed · Retry" only for that marker (replacing the client-side "Title didn't generate" heuristic). Untitled fallbacks (list, map, actions, home widget, detail hint) use transcript text first; a bare "Untitled Conversation" render emits the registered, bounded "Conversation Untitled Rendered" event so it can be verified to reach zero. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: add failure class and mobile changelog fragment for untitled-row fix Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(conversations): move terminal title helpers into their own database module Keeps conversation_finalization_jobs.py from growing: the transcript decode, deterministic title update and time-zone read shared by the dead-letter, BYOK abandonment and orphan terminals now live in database/conversation_terminal_title.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(conversations): keep the dead-letter row update beside the terminal title helpers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(conversations): narrow uid and snapshot types for the BYOK terminal title Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(conversations): address review of the untitled-row fix - Terminal title and retry marker are added only when the document's estimated size stays under the 1 MiB ceiling; at the ceiling the dead-letter, BYOK and orphan terminals commit their status-only write (tests at the limit). - Transcript decode for the title is strict: a blob that fails authentication (decrypt returns its input) degrades to the time title with no Retry. - summary_retryable requires usable summarizer input: decoded transcript text or a photo with a description; undescribed photos and has_photos do not count. - A blank user_title is no override on read, processing persists, the title PATCH and the set_title sync mutation (effective_user_title), tested from the terminal write through the API model to the Flutter row. - Flutter's fallback title ports deterministic_minimum_title exactly, pinned by contracts/parity/deterministic_title.json on both backend and Flutter. - Untitled telemetry saturates its session budget instead of evicting and re-reporting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(recovery): a refused discard's dead-letter keeps protected content and gains a title Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(conversations): use a public verified transcript decode for terminal titles Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(conversations): exact map overhead in the terminal size estimate; keep title writes unchanged - Size maps like embedded documents (fields plus 32 bytes), per Firestore's storage-size rules, and raise the terminal headroom to 64 KiB. Tested against an independent reference calculation with nested maps and arrays, and the 128-action-item repro near the ceiling. - Revert the write-side blank-title handling: the title PATCH, set_title and its receipt behave as on main. A blank user_title stays no override on read, in the processing persists that re-apply it, and in the terminal write. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 12 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 24 天前 | ||
| 12 天前 |