Skip to content

[Reliability] Add a versioned crash-safe project format, autosave, migration and recovery #962

Description

@seonghobae

Parent: #958
Baseline: #968

Buyer-visible gap

A rehearsal project is durable user work: local audio references, role selections, analysis results, user-corrected boundaries, cue decisions, handoff metadata, and future player state. The current 83-PR inventory contains handoff and many UI/security slices, but no live PR is designated as the canonical owner of a versioned crash-safe project format, autosave, atomic publication, migration, backup, and recovery.

A commercial desktop product must prove that a crash, power loss, interrupted write, application upgrade, or rollback does not silently destroy or reinterpret a band's work.

Product outcome

BandScope owns one documented, versioned, and recoverable local project format:

open or create project
→ mutate through typed commands
→ append bounded recovery-safe autosave evidence
→ atomically publish a consistent snapshot
→ migrate a validated copy on upgrade
→ restore or roll back without hidden data loss

Required scope

Canonical project contract

  • Define a stable public schema and project_format_version independent of the application package version.
  • Separate source references, derived analysis artifacts, user decisions/corrections, portable handoff data, UI preferences, and volatile runtime state.
  • Store local audio through app-owned identifiers and bounded file/content evidence; do not leak arbitrary absolute paths into portable artifacts.
  • Version analysis engine/backend/model identity and preserve confidence/limitations with each result.
  • Publish a machine-verifiable schema and golden fixtures for every supported version.
  • Preserve unknown forward-compatible data or fail closed according to an explicit compatibility rule; never silently discard fields.

Atomic persistence

  • Stage a complete candidate, flush required data, validate it, atomically replace the previous snapshot, and retain a known-good backup.
  • Ensure crash, cancellation, disk-full, and permission failure cannot replace a good project with a partial file.
  • Bound file size, collection counts, string lengths, nesting depth, and artifact counts before allocation.
  • Defend the actual filesystem boundary against symlink/path traversal and time-of-check/time-of-use failures.
  • Use one storage authority and one transaction boundary rather than independent React/localStorage/native writers.

Autosave and recovery

  • Debounce/coalesce autosaves without losing the latest accepted mutation.
  • Keep a bounded journal or rotating recovery snapshots with integrity hashes and monotonic ordering.
  • Detect unclean shutdown or a newer recoverable draft at startup and offer accessible Restore / Compare / Discard choices.
  • Support manual save, Save As, export, and safe close while autosave or analysis completion is in flight.
  • Never upload recovery content or include private project/audio payloads in diagnostics.

Migration and rollback

  • Implement ordered, deterministic, idempotent migrations with source/target version, input/output hash, and result receipt.
  • Migrate a copy first; publish only after full validation; retain the pre-migration artifact until the new version opens successfully.
  • Provide supported downgrade behavior when compatible and an explicit block/portable-export path otherwise.
  • Test clean install, upgrade from every supported fixture, interrupted migration, repeated migration, and application rollback.

Boundary with current handoff work

Live PRs #737 and #740 own versioned outbound/inbound rehearsal handoff slices. They are portable, bounded interchange contracts—not substitutes for the durable local project source of truth.

The project contract must integrate the active rehearsal-player state from #961 only after that public state machine is stable.

Acceptance criteria

  • One documented project schema and public command API own every durable project mutation.
  • Every supported historical fixture opens or returns an explicit actionable incompatibility result.
  • Fault injection proves no partial snapshot replaces the last known-good project during crash, kill, disk-full, permission error, or cancellation.
  • Autosave is bounded, preserves the latest accepted edit, and cannot race project close or Save As.
  • Recovery choices are usable by keyboard and screen reader and disclose what will be restored without unnecessary path exposure.
  • Migrations are deterministic and idempotent and produce version/hash receipts; rollback evidence is retained.
  • Unknown fields, malformed data, excessive depth/count/size, duplicate IDs, cycles, and unsupported versions follow the published fail-closed contract.
  • A project remains semantically equivalent across supported Windows and macOS path conventions.
  • Property, fuzz, filesystem integration, migration, and platform-specific atomicity tests pass on the exact head.
  • Repository-owned production statement/branch coverage and public API documentation remain 100%.
  • Current-head checks, qualifying independent approval, zero unresolved actionable threads, and branch protection pass without bypass.

Real-world fault cases

  • termination between write, flush, validation, and replace;
  • disk full after staging but before publication;
  • source audio moved, replaced, truncated, or permission-revoked;
  • two windows attempt to mutate the same project;
  • system clock moves backward;
  • hostile project with huge counts, nesting, strings, or duplicate identities;
  • migration succeeds but first open of migrated data fails;
  • application rollback after opening a newer format;
  • autosave fires while analysis, handoff import, or player state changes.

Non-goals

  • No mandatory cloud account or remote database.
  • No opaque binary format without a documented migration/export story.
  • No silent best-effort data dropping.
  • No raw project/audio content in ordinary logs or support bundles.

Activity

  1. added
    area: accessibilityAccessibility and assistive-technology support
    area: apiAPI, protocol, event, or external contract
    area: authAuthentication, authorization, identity, or tenant isolation
    area: securitySecurity boundary, hardening, or vulnerability prevention
    scope: researchResearch, statistical validation, or scientific evidence
    status: triagedOpen issue has an organization taxonomy assignment
    type: featureNew or expanded product capability
    on Aug 22, 2026
  2. seonghobae commented on Sep 5, 2026

    @seonghobae
    CollaboratorAuthor

    Fresh prerequisite finding from the #961/#1160 player stack: the current shared RehearsalSong contract already admits tempo, collaboration, and role-level harmonicExplanation, transpositionPlan, transcription, and practiceProgress, while native RehearsalSongPayload on #1160 predecessor ded24060f7cd7e3ab5cc69111d7545e76ccbbe0e omitted them under deny_unknown_fields. The ordinary renderer Save path validates the shared contract first and then native save_project deserializes it again, so a valid current song could fail with Invalid project payload before reaching disk.

    A test-first prerequisite repair is now carried on Draft #1160 because selected-source persistence cannot safely build on a Save path that rejects the current song contract: RED 0926ab89950221e595e0f002962838330b464066 adds an exact native round-trip fixture; causal fix 38b1328b12bf2285f3ca632f208ecf82029ede0a restores structural field parity without weakening deny_unknown_fields; TRACEABILITY 44601e9d49e6c7caf163f7ffab4edffb71a3f55d; current format documentation 978441510fc85206626a6aa4695fba4e8a5313dd.

    This does not transfer #962 ownership into #1160 and does not claim crash safety. save_project still publishes with direct std::fs::write; project_format_version, atomic stage/flush/validate/replace, backup, autosave, recovery, migration, bounds/fault injection and portable durable player semantics remain #962 work. When Active Player selection becomes durable, persist a stable semantic (e.g. source kind) through this canonical project contract, never the revocable opaque playback authority or renderer-local receipt.

  3. seonghobae commented on Sep 5, 2026

    @seonghobae
    CollaboratorAuthor

    Canonical #970 owner update: protected-base drift is repaired without force-push. fix/project-save-atomic-publication-962 now descends from develop@314ddeae7b775a4957594b599358c8255617eb2e through two-parent merge 7e2fb827198655e46ebc87d7faa70bb853c28921; fresh compare is behind_by=0 while retaining the Project Persistence delta.

    New canonical RED 93e9e80fa13d93692fdbd8d7d9acd10714ee8e8d proves current strict native persistence still rejects shared RehearsalSong fields already present in the product contract: collaboration and role-level harmonicExplanation, transpositionPlan, transcription, practiceProgress. Keep deny_unknown_fields and the v1 envelope; repair by typed DTO parity rather than serde_json::Value passthrough. Until that RED is GREEN, #970 must remain Draft.

    Separately, RED becb11c0a75059fdf5889b8181c962a58de468e8 exposed that the Windows persistence evidence lane was not triggered by core DTO/fixture or Tauri entry/manifests changes. Fix 5b397ce9cc8bf5aa8bb1cb61a826a2f0091587b9 expands only the path filter; the pinned Windows test command and protected gates are unchanged.

    Selected Active Player source persistence remains downstream of this foundation: persist a stable semantic (full_mix|vocals|bass|drums|other or its eventual canonical equivalent), never a revocable bandscope-playback authority; reload must re-resolve through current native availability and fail closed to Full mix when unavailable.

  4. seonghobae commented on Sep 5, 2026

    @seonghobae
    CollaboratorAuthor

    Canonical Project Persistence owner #970 advanced to exact head c461d4664fd372964306328962c44bfea76b7286 without force-push. The shared-song schema drift is now repaired in the owner branch rather than duplicated downstream: structural RED 93e9e80fa13d93692fdbd8d7d9acd10714ee8e8d → typed DTO fix 819d8af80e425dc5627d86659a5fc97ec90c2767, then domain-parity RED 6bcdf160a7e95cc540d96e49e25868c19a438106 → fix a1cf37ea98db2f8024ca710d563d879c04204961. Native persistence now preserves current collaboration plus role harmonicExplanation, transpositionPlan, transcription, and practiceProgress, uses exact shared collaboration state enums, and rejects progress outside integer 0..100 while retaining deny_unknown_fields, finite-positive tempo validation, and projectFormatVersion: 1. Traceability: docs/traceability/project-persistence-shared-song-contract.md.

    This does not complete #962. Remaining owner-path findings include exact cross-language parity for older stringly DTO domains and optional-field null semantics, autosave/backup rotation, globally discoverable startup recovery, deterministic migrations beyond v1, restore/compare/discard UX, exhaustive fault injection, and stable selected-playback-source persistence. Selected source must be durable semantic (full_mix | vocals | bass | drums | other), never a revocable bandscope-playback authority; reload must resolve a fresh native authority and fail closed to Full mix when unavailable. Current exact-head hosted checks are still queued/pending, so #970 remains Draft and no GREEN/merge is claimed.

  5. seonghobae commented on Sep 5, 2026

    @seonghobae
    CollaboratorAuthor

    Fresh owner-path evidence from canonical Project Persistence PR #970:

    • Current fix(project): enforce crash-safe revision-bound persistence #970 exact head is aff7ecc4547f771eff6a0fc081e07077bc555f20, ordinary-descended from protected develop@314ddeae7b775a4957594b599358c8255617eb2e (behind_by=0).
    • Shared-song structural parity, collaboration/progress domains, omission-vs-explicit-null semantics, and the remaining stringly shared closed domains are now covered by RED→fix chains on fix(project): enforce crash-safe revision-bound persistence #970. The latest chain is closed-domain RED 2b0a47e6305b7b7a3e87857335d0f36dfabc9712 → typed native fix 96d66ed6f5fad918b0ddef8a1e6494b76f8bafd0, with positive coverage f8c30150375b39d54e1775d941f6515d2686410c for every current valid section-form/confidence/provenance/role/cue/priority/export token. deny_unknown_fields, finite-positive tempo validation and the v1 envelope remain intact.
    • Current exact-head hosted workflows are materialized but non-terminal, so this is not repository GREEN and fix(project): enforce crash-safe revision-bound persistence #970 remains Draft.

    Next durable Active Player integration should not be added as another optional field inside the existing v1 song payload. #970 already documents projectFormatVersion: 1 as a compatibility view until source/derived/decision/handoff/preference/runtime sections are promoted in a later format version, and this issue requires those concerns to remain separated. #1160 already defines the stable renderer semantic as full_mix | vocals | bass | drums | other; a future project-format revision should persist that semantic in the preference/player-state boundary, never the revocable bandscope-playback authority. Reopen must resolve a fresh authority from current native availability and fail closed to Full mix when the saved semantic is unavailable.

    Do not silently expand v1 in a way an older v1 reader would reject without a version change. The next implementation slice therefore needs an explicit later-version envelope plus deterministic v1→current migration/fixture evidence before selected-source persistence is wired into #1160.

  6. seonghobae commented on Sep 5, 2026

    @seonghobae
    CollaboratorAuthor

    Project Persistence owner #970 advanced the selected-playback-source prerequisite instead of adding a second writer in #1160.

    Current exact owner head: ae97f885fbd91da1ec0958444b94e3af2fa68410.

    Test-first chain:

    • RED 86207ea0459f1a6e27e80f571ad5d6462a0d6fab: v1/legacy → v2 migration, exact full_mix | vocals | bass | drums | other domain, realistic bandscope-playback://... rejection, no-runtime-authority typed construction.
    • Causal source be4ce61f9a865229aad9b46ad27adb79b1028258: current projectFormatVersion: 2 boundary with typed preferences.selectedPlaybackSource; historical v1/legacy parser remains the strict migration authority.
    • Golden v2 fixture 4aa18fa8cbe5e59cf3f1e195f9a20e51c36e4da7 + fixture test 73dc9a7314c0e20938fc767c207e4102e1bbf106.
    • Format docs 9518d84eb621b03211a4ad5a164969268ae68cdd; Security Notes/decision traceability ae97f885fbd91da1ec0958444b94e3af2fa68410.

    Migration is deliberately evidence-conservative: v1 has no selected-stem record, so it migrates to full_mix rather than fabricating a stem choice. Revocable playback URLs, filesystem paths, and generation receipts are not durable state.

    This does not close #962 or selected-source reopen. Existing Tauri song-only save callers now have a v2 compatibility writer but still write the deterministic Full-mix default. Next consumer work is #1160 → typed Project Persistence preference on save, then reopen → fresh native availability → fresh authority, falling back to Full mix when the persisted stem is unavailable. Autosave, backup rotation, startup recovery UX, migration receipts/hashes, downgrade/rollback, descriptor-bound parent authority, and exhaustive interruption/power-loss evidence remain open. #970 stays Draft pending exact-head checks and independent review.

  7. 44 remaining items

  8. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    Project Persistence owner #970 advanced the restart/reopen revision boundary on exact head a6d399067186c74c94e7c488e0ed8ae4f9bd9fc8 without moving ownership into Score Storage.

    Valid hosted RED: 1109799c69a2f75234f9ae6bd4e793191638be17 added a native restart-binding regression requiring an existing app-owned workspace to return its current content revision when the renderer has lost its process-local receipt but the canonical reopened candidate is byte-identical. Pre-fix exact runs failed on both owner lanes: macOS 35485742398 / job 106011658681, Windows Server 2025 35485742321 / job 106011658268.

    Repair: native Project Persistence now performs recovery and exact-workspace identity/digest validation under the existing process-external admission lease. None + existing target is accepted only for exact candidate equality, returning the current SHA-256 receipt without staging/replacing bytes. A differing existing workspace still fails closed with Project changed since it was opened.; selected/import file path or digest is never workspace authority. The renderer reopen bridge now binds through the BandScope-minted project id before returning the loaded document to UI state. An additional edge regression proved equality binding cannot bypass ordinary content admission; empty and >5 MiB candidates remain rejected before revision binding.

    Exact-current-head native evidence is terminal GREEN on both supported desktop lanes: macOS run 35486114211, job 106012683805; Windows run 35486114237, job 106012683969. Both succeeded on exact a6d399... with the warning-gated native Project Persistence regression suite.

    This does not close #962. Repository ci remains the execution authority for the TypeScript reopen bridge and must settle on the exact head before frontend GREEN is claimed. The next Project Persistence slice is buyer-visible revision-conflict handling for a differing durable workspace: Reload / Compare / Recover / Discard or equivalent, keyboard/screen-reader operable, no local-path exposure, and no automatic stale snapshot replay/rebase. PDF durable -> attachment metadata not durable remains a separate recovery-candidate boundary with #1239/#1241. Packaged process-kill, disk-full, permission, cancellation, power-loss, signing/notarization, immutable release/provenance/updater rollback also remain open.

  9. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    #970 owner update — rejected reopen must not revoke the still-active session's CAS authority.

    Fresh review of exact a6d399067186c74c94e7c488e0ed8ae4f9bd9fc8 found that loadProjectDocument() deliberately deleted the process-local revision receipt before restart equality binding, but a native Project changed since it was opened. rejection left that receipt deleted even though App rejected the Open attempt and retained the previously active project. The next mutation of that still-active aggregate therefore crossed the native boundary without its previously verified expectedContentSha256 and became an avoidable availability/integrity dead end.

    Source-level RED afd03ea5583a6afaeabbdc5aa4a4b329a8bd5d9e establishes a valid active receipt, forces a conflicting reopen for the same BandScope project id, then requires a subsequent mutation of the still-active project to forward the original receipt. A descendant repair was pushed before repository CI reached terminal RED, so this is not claimed as hosted RED.

    Causal fix b0beeb2f230ecd446ae1caeaff91b081950e6210 keeps the restart bind receipt-free, snapshots the prior session receipt, and restores it after bind rejection only when no newer receipt has appeared for that project id. This avoids both silent revocation and rolling a concurrent newer accepted revision back to older renderer authority. Traceability is code-current at 8250dcf6e4adf40782086350aef50f9dc04a7e81.

    This does not close the buyer-visible conflict UX acceptance criterion. Reload / Compare / Recover / Discard or an equivalent bounded, keyboard/screen-reader operable contract remains the next #970/#962 vertical; automatic retry/replay/merge remains out of scope without an explicit semantic merge contract.

  10. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    #970 Project Persistence owner update — exact fdbbe93854c426cb1c18fedb2f1bdb5e11d09a9f

    Fresh product-path review found that native CAS was storage-safe but the application treated Project changed since it was opened. as a fatal generic error. In Workspace view that replaced the still-authoritative accepted rehearsal with ErrorState; in Score view the same conflict could be invisible.

    Repair lineage:

    • b19f59009ca55ba7cbf1b4f6ad944a4bbaab750d: source-level RED for conflicting reopen and stale mutation preserving the accepted rehearsal. No hosted RED claimed; repair landed before workflow materialization.
    • cbf21d6c5e9c3e5ac60af2b21c456bffd3c371c4: exact owner-error classification + path-free bounded conflict state; generic failures remain generic. Only existing actions are exposed: keep/dismiss current rehearsal or choose another project.
    • 76bfba5fbe3c6c6b3aaea48c8f990bfae93e9fef: source-level RED showing the first repair hid the notice in Score view. Its CI was superseded before terminal assertion verdict.
    • 44b0dd7971a6b9d6f6da8d847c48b4a7f90d4acb: conflict notice moved above Workspace/Score switching so the accepted aggregate and warning remain visible from both rehearsal surfaces.
    • fdbbe93854c426cb1c18fedb2f1bdb5e11d09a9f: TRACEABILITY updated with decision, trust boundary, privacy/safe-failure notes, test points, and remaining reconciliation scope.

    Exact-current-head native owner evidence is GREEN: macOS run 35488483937 SUCCESS; Windows Server 2025 run 35488483902 SUCCESS. Repository ci is still queued and build-baseline is in progress; Security Scan/SBOM/Semgrep are queued and CodeQL PR pending, so no frontend/repository-wide GREEN is claimed. Fresh formal review has no qualifying independent non-author APPROVED; returned review threads are resolved. REST reports mergeable=true, mergeable_state=blocked, so this is gate-blocked rather than a source conflict with protected develop@314ddeae7b775a4957594b599358c8255617eb2e.

    This does not satisfy the issue's Restore / Compare / Discard acceptance. The UI intentionally does not pretend those owner operations exist. The next Project Persistence contract is explicit semantic reconciliation: inspect/reload the exact app-owned durable workspace, retain a rejected edit as a recovery candidate where warranted, and discard a side only with auditable user intent. Automatic stale-snapshot replay/merge remains prohibited. EN/KO exist because the current repository i18n runtime exposes those locales only; JA/ZH/VI/ES/DE/FR plus keyboard/screen-reader/400%/responsive packaged evidence remain open.

  11. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    Project Persistence integration finding repaired on #970: a successfully reopened app-owned project preserved its native-admitted sourceReference.projectId in jobResultPublicationProjectId, but ScoreView still consumed jobResultBootstrap?.projectId. Because reopen intentionally clears the transient analysis bootstrap, Score attachment read/attach/remove could remain disabled after restart even though Project Persistence had rebound the durable project identity.

    Source-level RED: 8412c96bdf981aec98ccca2d7b6498f477ed3aae adds App.score-project-identity.test.tsx, reopening a project with a valid path-free source reference and requiring the Score application boundary to receive its project id. No hosted RED is claimed: no workflow run materialized for that test-only head before repair.

    Causal fix: 0b43dad7fe4a1d78e84f16155fbca390390e611d wires ScoreView.projectId to jobResultPublicationProjectId, the same Project Persistence identity already used by durable workspace mutation. Portable documents with no admitted source reference still get no Score Storage authority; no path/hash identity is inferred.

    CI ownership was repaired so the focused regression is a tracked input of both native Project Persistence workflow trigger sets and the workflow-policy contract (3e30aaf..., 670a577..., e323263...). A focused traceability contract now lives at docs/traceability/project-persistence-score-publication-identity.md; current branch head after traceability trigger ownership repair is aee578a54f2960c2a847aebd5c6427cb502c9a05.

    Claim boundary: this restores admitted project identity to the Score orchestration surface after reopen. It does not close PDF durable -> project attachment metadata not durable; that restart-reconciliation state remains a separate Project Persistence / Score Storage recovery-candidate problem and must not be solved by silent PDF adoption/deletion.

  12. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    #970 Project Persistence exact head is now 75e5efe1be2c4f4b818d191b2ed8d79a04a38d2b.

    Valid restart-recovery gap verified: after Score Storage can enumerate validated published score ids (#1241), Project Persistence still lacked a canonical way to compare that byte/object truth with durable scoreAttachments references without scanning storage or copying Score Storage validation.

    Source-level RED 3484d5169b6e9b00501f4c6bf2f48e1165d6e144 defined the path-free reconciliation contract. Causal implementation 67febe0a049e642f5ced0c8cfb355d8b1108e25b adds derive_score_attachment_recovery_candidates, classifying (1) referenced+published, (2) published-without-reference, and (3) referenced-but-missing ids. Malformed/duplicate identities fail closed; the service performs no I/O and never infers attach/delete intent. Canonical export is 95aee6d...; TRACEABILITY is 85d7440...; macOS/Windows/workflow-policy ownership is 51901c8..., b8f3a37..., 1114d2e....

    Self-review caught a test-compilation defect in the initial error assertion (Result<T, String>::as_deref() on a non-Deref success type). That was repaired in e8f8da6... and final 75e5efe... using err().as_deref(); no hosted RED is claimed for the superseded test-only head.

    Claim boundary remains strict: unreferenced_published_score_ids is a recovery candidate set, not an orphan-delete list, because the same state can mean interrupted attach or completed detach with failed byte cleanup. #970 does not consume #1241 implementation until the canonical owner path is integrated/protected. Exact-head hosted gates for 75e5efe... are being materialized; predecessor GREEN is not transferred.

  13. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    Exact-head follow-up: #970 moved once more to 5f74aeb12a1b87f16ef9db4954d08467f73a29aa only to make the TRACEABILITY record include the test-harness RCA. Production reconciliation semantics are unchanged from 67febe0a...; the err().as_deref() compilation repairs remain e8f8da6... / 75e5efe.... Fresh exact-head macOS, Windows, CI, build-baseline, Security, SBOM, Semgrep, and CodeQL runs are now materialized and queued; no predecessor GREEN is transferred.

  14. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    Project Persistence recovery disposition follow-up on #970 exact 03921928f1d0bdc5226b011dc5342d15a56978d8:

    • source-level RED 25a3e6c93db2464de90063910ae0de58aa8e7f05 proves that public recovery classification alone must not become destructive cleanup authority;
    • 93a2e9ce313db949eda2fa5ee4535feb3c26af78 adds explicit Preserve / Discard decisions plus opaque AuthorizedUnreferencedScoreRecoveryAction;
    • authorization revalidates canonical score-id shape, uniqueness and mutual exclusion across all three recovery sets, and refuses referenced, missing-reference, unknown, malformed or forged cross-set identities;
    • Project Persistence still performs no Score Storage I/O or byte deletion. Discard is intent evidence only for later owner integration.

    No hosted RED is claimed because repair commits followed before terminal workflow verdict. Exact-current-head macOS/Windows owner runs are now in progress and repository/security/SBOM/CodeQL gates are queued.

    Next owner gap is not classification anymore: truthful reattach presentation metadata. #1241 inventory intentionally returns score ids only, but durable ScoreAttachment metadata needs a display fileName; a crash after PDF publication and before project metadata durability cannot currently restore the original selected filename. Add an owner-safe recovery metadata receipt or a truthful generated recovery label—do not claim the original filename was recovered.

  15. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    #970 review follow-up: the explicit Project Persistence core allowlist had a valid fail-open drift risk. Source-level RED 4ebb60f73389589a4720453ef3a58be4434a912a now discovers the actual project_persistence*.rs, project_format*.rs, project_migration*.rs integration targets plus the shared content-identity contract, parses workflow --test execution, and requires exact set equality on both macOS and Windows. A hostile future-contract fixture proves an unexecuted matching test fails policy. The same review exposed a real trigger hole: project_migration_receipt_input_binding.rs was executed but project_migration*.rs changes did not trigger the owner lanes. 757881a975fae50b12c7a04e67b6fb7fe634349c and 4984b5d001a387941bd6a018d32519931e2a484c add that trigger coverage without returning to --all-targets. Exact-head native runs are materialized; no predecessor GREEN is transferred.

  16. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    Project Persistence recovery follow-up on #970 exact 95ea6f7f154ab7d57411fcc496c8834de2dc3b05:

    • Source-level RED e1ff85e77c08b030bc54995b8213c47cc634a5ab requires an explicit Recover decision for a current unreferenced_published score and proves Preserve/Discard cannot be converted into reattachment metadata. No hosted RED is claimed because causal descendants followed before terminal verdict.
    • 184690416054be6aba415e574f94965f3e89338c adds Recover, opaque RecoveredScoreAttachmentMetadata, and recovery_attachment_metadata_for_action.
    • Restart inventory does not contain the buyer's original selected filename. Recovery therefore uses the truthful deterministic presentation label recovered-score-<score-id>.pdf; it does not fabricate filename provenance or expose a local path.
    • 6a77bec1353ced292337e034435111da6a3f6289 exports the contract; 95ea6f7f154ab7d57411fcc496c8834de2dc3b05 updates TRACEABILITY.

    This remains domain authorization/presentation only: no filesystem I/O, no auto-attach/delete, and no accepted attachment until the application persists recovered metadata through Project Persistence CAS/durability. #1241 remains Score Storage owner for restart inventory/bytes. Next buyer vertical is cross-owner application orchestration plus explicit Recover / Preserve / Discard UX and missing-reference presentation.

    Exact-head macOS/Windows Project Persistence owner workflows are currently running; repository/security gates and independent approval are not settled, so #970 stays Draft.

  17. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    Project Persistence recovery freshness repair on canonical #970:

    • source-level RED f22b3d235343e38f7cafe54807004e61bcffbdd7 models a stale recovery dialog: Recover/Discard is authorized while a score is unreferenced_published, then fresh owner evidence shows the same score has become durably referenced before the decision is consumed;
    • causal fix cf89afc80c780ecf71dc550910849aadde751992 adds revalidate_unreferenced_score_recovery_action and makes recovered-metadata construction require fresh reconciliation;
    • export 707431ab52e990a10fb38753f503f9836007b668 and TRACEABILITY 5873c023cbcb74461abb497f071bbbdf7429f18b make the authorization explicitly session-local intent rather than a durable capability.

    Current #970 exact head is 5873c023cbcb74461abb497f071bbbdf7429f18b, Open/Draft/mergeable on protected develop@314ddeae7b775a4957594b599358c8255617eb2e. Exact-head workflows have materialized but are queued; predecessor GREEN is not transferred. No qualifying independent approval exists, so merge/release gates remain closed.

    Claim boundary: this prevents an older Recover/Discard decision from crossing a later Project Persistence/Score Storage lifecycle change. It does not yet implement the product recovery flow because #1241 restart inventory is not protected/released into this owner branch. After owner integration, the application must refresh both owner evidences immediately before Recover metadata commit or Score Storage Discard, and must surface missing references without silent metadata rewrite.

  18. seonghobae commented on Sep 20, 2026

    @seonghobae
    CollaboratorAuthor

    Project Persistence recovery finding / repair update (exact source lineage):

    A recovery decision was fresh with respect to score lifecycle state but was not bound to the active project aggregate. Project A and Project B can both classify the same opaque score id as unreferenced_published; if a recovery dialog survives a project switch, a decision authorized under A could otherwise pass score-set revalidation under B.

    • Source-level RED: 3aaf84d9dd34b3f7f7c12f17cd4a9ffa97b8dca9 adds a project-switch regression with identical recovery candidate sets and rejects malformed project identity. No hosted RED is claimed because causal descendants followed before terminal workflow evidence.
    • Causal repair: f0fc96b67d18c9a2c168f1864a091edf835ea3e2 adds opaque ProjectScopedScoreRecoveryAction, canonical project-id validation, and mutation-boundary project identity + fresh lifecycle revalidation.
    • Public boundary hardening: 85c48a02ed8d09b11df1dd2bebf5eae60b38570f removes unscoped recovery mutation authority from the desktop-core crate-root API and exposes only the project-scoped wrapper.
    • CI ownership / traceability: d87e6fe9570d71d187ac9652b49de896e0d6886d, f63668fcdc271c67cd1dfd4ac166b3a2859b7377, dfc8bc82403c6cf619b7248968cbaa02284dabb4, c0b0b284f84e9b191aa7e5d7d2ba2e2a2d403de4, b909ac80934031bbf7366bc909984735d7792866, a30749871792b1a5ec569441f8c4f5766c24bd3e, 17ee600cec13fec9475e988402efbb7e1370bbd6 make the new source and project-scope TRACEABILITY exact-head inputs of both macOS and Windows owner lanes.

    Current #970 exact head is 17ee600cec13fec9475e988402efbb7e1370bbd6; fresh owner workflows have materialized but are not yet terminal, so predecessor GREEN is not transferred. The repair is domain-level only: application recovery still awaits protected/released Score Storage inventory integration (#1241), explicit Recover/Preserve/Discard UX, re-read of both owner evidence plus active project identity at action time, Project Persistence CAS for Recover, and Score Storage-only byte cleanup for Discard.

  19. seonghobae commented on Sep 22, 2026

    @seonghobae
    CollaboratorAuthor

    현재 canonical Project Persistence implementation owner는 Draft PR #970입니다. Issue 본문의 “no live PR is designated” 문구는 역사적 baseline으로만 해석해야 합니다.

    Fresh owner authority:

    직전 exact 0f147709ccdce2aa367ebd2fbee1fd2dd0f737af의 repository ci run 35671231614는 queued가 아니라 terminal FAILURE였습니다. Ubuntu build-and-test job 106598332027의 유일한 terminal defect는 services/analysis-engine/src/bandscope_analysis/api.py의 Ruff 0.15.5 I001 import-order failure였습니다. Native Windows/macOS, build-baseline, Semgrep, Security Scan, SBOM predecessor success는 이 새 head로 전용하지 않습니다.

    Repair lineage:

    • 82bbfe5aec6d480d5ac1ecc9c842fb6dc2c235ed: private aliased cache-publication import block을 같은 module의 non-aliased block보다 앞에 배치.
    • immediate diff inspection에서 섞인 unrelated HarmonyPayload docstring delta를 발견했고, ordinary descendant 2892a43615fc29b119fefb3851d34aa511020965에서 제거.
    • 0f147709... → 2892a436... 최종 delta는 api.py 한 파일의 import block reorder만 남습니다 (+3/-3). Persistence/cache runtime semantics, resource bound, warning/test/workflow gate는 변경하지 않았습니다.

    현재 exact-head generation은 live/nonterminal입니다: Windows native 35704190409 in_progress, macOS native 35704190460 queued, build-baseline 35704190549 pending, ci 35704190510 queued, Security 35704190381 queued, Semgrep 35704190442 queued, SBOM 35704190467 queued, CodeQL 35704190383 pending. Qualifying independent non-author current-head APPROVED도 아직 없습니다. 따라서 #962/#970은 계속 Open/Draft이며 protected integration, recovery UX/fault evidence와 release gates가 남아 있습니다.

  20. seonghobae commented on Sep 22, 2026

    @seonghobae
    CollaboratorAuthor

    Current Project Persistence owner update:

    Fresh hosted RCA supersedes the earlier runnerless-CI description. Repository ci run 35704190510 is terminal FAILURE at Ubuntu build-and-test job 106717643693: Ruff 0.15.5 format --check names five files. Four are #970-owned Project Persistence files (final_result_cache.py, test_analysis_cache_admission_identity.py, test_final_result_cache_shared_contract.py, test_project_persistence_workflow_policy.py) and remain #970 repair work. The fifth, test_supply_chain_policy.py, is not a #970 delta and is already owned by one-file prerequisite #1176.

    The unchanged #970 source head still has Windows/macOS native persistence, build-baseline, Security Scan, Semgrep and SBOM success from its direct-develop generation. Those receipts are lineage after the base retarget, not final stacked merge evidence. No qualifying independent current-head approval exists; CodeQL is unsettled. Keep #962 and #970 open/Draft until #1176 normally reaches protected ancestry, #970 reconciles ordinary/non-force, its four owned formatter findings are repaired, and fresh exact-head/base gates plus buyer recovery evidence are obtained.

    No force-push, destructive rebase, duplicate formatter fix, no-op wake commit, blind rerun, self-approval or gate weakening was used.

  21. seonghobae commented on Sep 22, 2026

    @seonghobae
    CollaboratorAuthor

    Project Persistence owner update: canonical PR #970 is now exact 25b6095f12d461ef9e3a7e647fa2a31a27e6fc1c, stacked on #1176 8fe6b6d99c009527ef0bcba419e6f6debdb23c23 with actual ordinary two-parent ancestry, not base-label retargeting only. The branch was fast-forwarded (force=false), and fresh compare from #1176 is ahead=815 / behind=0 with merge base exactly #1176.

    The hosted direct-develop CI RCA is now exact from job 106717643693: Ruff 0.15.5 would reformat five files. test_supply_chain_policy.py is the foreign protected-base defect canonically owned by #1176 and is now consumed through ancestry. Four files remain Project Persistence-owned and unresolved: final_result_cache.py, test_analysis_cache_admission_identity.py, test_final_result_cache_shared_contract.py, and test_project_persistence_workflow_policy.py. Do not treat the ancestry repair as fixing those four.

    Current stacked head has no repository-owned workflow generation; that is absence of evidence, not GREEN. Required order remains: #1176 protected integration → ordinary #970 reconciliation → four owner Ruff repairs → fresh exact-head/base repository/native/security/SBOM/CodeQL/review evidence. #962 acceptance remains open.

  22. seonghobae commented on Sep 22, 2026

    @seonghobae
    CollaboratorAuthor

    Project Persistence authority update:

    Canonical implementation remains PR #970. Its dependency topology is now actual ancestry rather than metadata-only retargeting:

    A real persisted-cache contract drift was found while reconciling the stack. #1254 rejects finite but impossible audio-relative note intervals (onset < 0, offset <= onset), while #970's Python final-result cache validator still accepted any finite onset/offset pair. #970 now carries source RED 3314730077b7c24c077e2f15cec73eb627b8d75e for negative, zero-duration and inverted intervals, followed by minimal consumer repair 3dfd77e11187211e9b7ed2317b8f559e5e1fb018 adding only onset >= 0 and offset > onset. Shared timing policy remains #1254-owned; no duplicate consumer policy branch was created.

    Evidence boundary remains fail-closed: current stacked #970 exact head has zero repository-owned check runs, so there is no final exact-head GREEN to claim. Four #970-owned Ruff-format findings from the last direct-develop CI are still unresolved/unproven. The previous semantic head's native Windows/macOS, build, Security, Semgrep and SBOM successes remain predecessor semantic evidence only.

    The previous #970 CodeQL run 35704190383 is now known to be terminal, not merely pending: language detection succeeded, three compatibility jobs failed at verdict enforcement, and the current-head CodeQL scan dispatch only materialized afterward. That same-generation publication/re-entry evidence has been routed to canonical central owner ContextualWisdomLab/.github#1929 rather than treated as a Project Persistence source-security finding.

    Issue #962 stays Open. Crash/power-loss/disk-full/permission fault acceptance, recovery UI/a11y, protected prerequisite integration, final exact-head gates/review, signing/notarization and release/rollback evidence are still incomplete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: accessibilityAccessibility and assistive-technology supportarea: apiAPI, protocol, event, or external contractarea: authAuthentication, authorization, identity, or tenant isolationarea: securitySecurity boundary, hardening, or vulnerability preventionbugSomething isn't workingpriority: mediumNormal-priority or P2 workscope: product-gapCustomer-visible product gapscope: researchResearch, statistical validation, or scientific evidencestatus: triagedOpen issue has an organization taxonomy assignmenttype: bugDefect or incorrect behaviortype: featureNew or expanded product capability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions