Skip to content

fix(storage): retire completed legacy migration metadata - #3227

Merged
Astro-Han merged 5 commits into
apache:mainfrom
liugddx:fix/retire-completed-cutover-journal
Aug 19, 2026
Merged

fix(storage): retire completed legacy migration metadata#3227
Astro-Han merged 5 commits into
apache:mainfrom
liugddx:fix/retire-completed-cutover-journal

Conversation

@liugddx

@liugddx liugddx commented Aug 19, 2026

Copy link
Copy Markdown
Member

Summary

  • retire the released cutover_journal, runtime_import_sources, and session_metadata_import_sources tables during the existing atomic operational-state migration
  • validate the released column shapes (name/type/notNull/pk) and row-level migration evidence before removing obsolete metadata; column-shape validation does not inspect CHECK/FK constraints, and row validation is the authoritative content gate
  • require every cutover row to be completed and internally valid
  • preserve interrupted, malformed, or unfamiliar migration state unchanged and fail closed

Root cause

Released workspaces can still contain migration bookkeeping created before SQLite became the sole operational authority. The old readers and writers were removed, but their tables were not retired. Current schema convergence therefore upgrades the real application tables, then rejects the otherwise valid database because strict target-schema validation sees cutover_journal (followed by the two import-source tables) as unexpected objects.

This presents as OPERATIONAL_STATE_MIGRATION_BLOCKED on startup even though SQLite integrity is healthy.

Verification

  • npm run clean --workspace @maka/storage
  • npm run build --workspace @maka/storage
  • operational-state suite under the packaged Electron Node 24 runtime: 29 pass / 0 fail
  • Biome 2.5.6 check for both changed source files
  • git diff --check
  • replayed the migration against a copy of the affected released workspace database:
    • migration completed
    • PRAGMA quick_check returned ok
    • schema versions converged to runtime 12, session metadata 27, workflow 9, operational 2
    • all three retired metadata tables were absent afterward

The full storage suite was also attempted locally, but unrelated tests that load fs-native-extensions cannot start because this checkout lacks its Darwin prebuilt addon. The focused suite and real-database-copy replay do not load that optional native path; CI remains authoritative for the complete package suite.

The real workspace database was never modified; all migration replay used temporary copies.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex and Claude Code contributed to the implementation, regression tests, historical writer-contract analysis, and review-response changes. The human contributor reviewed the final diff, owns the submission, and owns the merge decision.

Checklist

  • Tests cover the change and fail without it
  • Affected package build, formatting, and focused tests pass
  • git diff --check passes

Generated-by: Codex

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0a99805d-1f95-4fc9-a075-f6903d04b212

📥 Commits

Reviewing files that changed from the base of the PR and between 62ca27f and 92f94d9.

📒 Files selected for processing (2)
  • packages/storage/src/__tests__/operational-state-store.test.ts
  • packages/storage/src/operational-state-store.ts
💤 Files with no reviewable changes (2)
  • packages/storage/src/tests/operational-state-store.test.ts
  • packages/storage/src/operational-state-store.ts

Included review availability: Your plan provides up to 3 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Summary

This PR retires obsolete legacy metadata tables after the atomic operational-state migration. It prevents startup failures caused by strict validation of those tables.

The PR extends the existing migration. It does not create a parallel path. It validates released schemas, exact evidence keys, cutover rows, references, and migration state before cleanup. Invalid or unfamiliar state fails closed and remains unchanged.

The added validation and regression tests are necessary to make destructive cleanup safe. The removed timestamp-ordering check preserves released writer behavior. No code or tests can be removed without reducing safety or regression coverage.

Validation included focused tests, build and formatting checks, migration replay, SQLite integrity validation, and schema-version convergence. The full storage suite remains incomplete because unrelated tests require an unavailable Darwin fs-native-extensions addon. Required-check status is unverified from direct check evidence.

Complexity delta

  • Removes three obsolete metadata-table authorities.
  • Adds exact released-schema and evidence-key validation.
  • Adds fail-closed migration branches.
  • Removes the completion-timestamp ordering requirement.
  • Adds one exported validation function.
  • Adds fixtures and regression tests.
  • Adds no configuration or parallel migration path.
  • Increases test-maintenance burden.

Total maintenance complexity decreases. The added complexity is necessary to protect destructive cleanup.

Review-relevant risks

The migration can delete legacy metadata tables and change startup and recovery behavior. Material changes in these areas require independent human review under repository policy.

The PR adds the exported assertReleasedLegacyRetirementShape function. Material public-contract changes require independent human review under repository policy.

No security, licensing, release, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

The migration now validates exact released legacy schemas, metadata rows, and store-specific cutover evidence before cleanup. Invalid schemas, journal keys, values, or import sources block migration and preserve legacy state. Completed-row timestamp ordering is no longer validated.

Changes

Operational metadata migration

Layer / File(s) Summary
Legacy schema contracts
packages/storage/src/operational-target-schema.ts, packages/storage/src/operational-state-store.ts
Adds structured schema introspection, canonical released DDL fixtures, and exact validation for registered legacy tables.
Fail-closed metadata retirement
packages/storage/src/operational-state-store.ts, packages/storage/src/__tests__/operational-state-store.test.ts
Validates legacy schemas and metadata rows before dropping metadata tables. Tests cover malformed, altered, trigger-bearing, and unknown migration state.
Cutover evidence validation
packages/storage/src/operational-state-store.ts, packages/storage/src/__tests__/operational-state-store.test.ts
Requires exact store-specific validation keys and valid integer evidence values. Tests cover complete, extra-key, missing-key, malformed, and unknown-store journals. Completed-row timestamp ordering is no longer validated.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🟡 Moderate · up to 92f94

This change retires legacy migration metadata, but chronologically inconsistent completed migration evidence may still be accepted and deleted, risking loss of migration state. Merge should wait for this bounded correctness issue to be fixed or explicitly accepted by the owner.

Sequence Diagram(s)

sequenceDiagram
  participant OperationalStateMigration
  participant SchemaValidator
  participant LegacyMetadata
  participant CutoverJournal
  OperationalStateMigration->>SchemaValidator: validate released legacy schemas
  OperationalStateMigration->>LegacyMetadata: validate legacy metadata rows
  OperationalStateMigration->>CutoverJournal: validate store-specific journal evidence
  CutoverJournal-->>OperationalStateMigration: valid evidence or migration-blocking error
  OperationalStateMigration->>LegacyMetadata: drop validated metadata tables
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the change and verification, but it omits the required AI-use selection and checklist sections. Add the required AI use section with exactly one selected option and complete the checklist items, including test and quality-check results.
Ai Use Disclosure ⚠️ Warning The PR description selects neither AI-use declaration. It only states “Generated-by: Codex”; the introduced commits also lack a final consistent Generated-by trailer. Select exactly one declaration, name Codex and its scope, and add consistent trailers to affected commits so they survive squash/amend. See CONTRIBUTING.md: Human ownership and AI attribution.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: retiring completed legacy migration metadata in storage.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Retire completed legacy migration metadata during storage convergence

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Retires completed legacy cutover and import metadata during atomic schema convergence.
• Validates released table shapes and migration evidence before deleting obsolete tables.
• Preserves interrupted, malformed, or unfamiliar state by rolling back and failing closed.
Diagram

graph TD
  A["Operational migration"] --> B["Legacy metadata"] --> C{"Released and complete?"}
  C -->|Yes| D["Retire tables"] --> E["Target validation"] --> F["Commit"]
  C -->|No| G["Rollback unchanged"]
Loading
High-Level Assessment

The current approach is appropriate because retirement occurs inside the existing atomic convergence transaction, after strict recognition of released schemas and evidence. Unconditional deletion would risk discarding interrupted or unknown migrations, while a separate cleanup pass would weaken rollback guarantees and complicate startup ordering.

Files changed (2) +321 / -0

Bug fix (1) +173 / -0
operational-state-store.tsValidate and retire completed legacy migration metadata +173/-0

Validate and retire completed legacy migration metadata

• Adds exact schema and row validation for legacy cutover and import-source metadata before dropping it within the operational migration transaction. Invalid, incomplete, or unfamiliar state throws and triggers the existing rollback path.

packages/storage/src/operational-state-store.ts

Tests (1) +148 / -0
operational-state-store.test.tsCover safe retirement and interrupted-cutover preservation +148/-0

Cover safe retirement and interrupted-cutover preservation

• Adds fixtures for the released cutover journal and import-source table schemas. Verifies completed metadata is removed during convergence and interrupted cutover state blocks migration without modification.

packages/storage/src/tests/operational-state-store.test.ts

@qodo-code-review

qodo-code-review Bot commented Aug 19, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Unfamiliar schemas are deleted ✓ Resolved 🐞 Bug ≡ Correctness
Description
assertReleasedLegacyTableShape inspects only column metadata, so tables with unfamiliar
CHECK/UNIQUE/FOREIGN KEY constraints, indexes, or triggers still pass validation and are dropped.
This destroys unrecognized migration state instead of preserving it and failing closed.
Code

packages/storage/src/operational-state-store.ts[R485-488]

+      SELECT name, type, "notnull" AS not_null, pk
+      FROM pragma_table_info(?)
+      ORDER BY cid
+    `)
Relevance

●●● Strong

Recent accepted precedent favors fail-closed structural validation; this finding identifies
destructive loss of unfamiliar migration state.

PR-#1770

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new validator selects only name, declared type, nullability, and primary-key position and
accepts the schema solely from those values. The released test definitions themselves contain CHECK
and FOREIGN KEY constraints that this query cannot distinguish, while the subsequent unconditional
DROP removes the tables and associated objects; the existing target-schema reader demonstrates that
complete definitions, indexes, and triggers can instead be validated through sqlite_schema.

packages/storage/src/operational-state-store.ts[483-501]
packages/storage/src/operational-state-store.ts[466-470]
packages/storage/src/tests/operational-state-store.test.ts[886-915]
packages/storage/src/operational-target-schema.ts[63-76]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The legacy-table validation checks only `pragma_table_info`, which omits table constraints, indexes, and triggers. A table with the expected columns but an altered CHECK or foreign-key constraint therefore passes validation and is deleted, violating the migration's fail-closed invariant.

## Issue Context
The repository already has a schema-signature seam in `operational-target-schema.ts` that reads complete `sqlite_schema` definitions and normalizes SQL. Reuse or consolidate that mechanism rather than introducing a second schema authority. Validate each legacy table's complete released definition and associated schema objects before dropping anything, and add a regression test showing that an altered constraint or extra trigger is preserved when migration fails.

## Fix Focus Areas
- packages/storage/src/operational-state-store.ts[473-503]
- packages/storage/src/operational-target-schema.ts[63-76]
- packages/storage/src/__tests__/operational-state-store.test.ts[85-199]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: ⚖️ Balanced: This is a high-risk operational database migration that changes teardown and fail-closed invariants across multiple legacy metadata paths, but the logic is sufficiently cohesive for one careful review pass.

Grey Divider

Tip of the day
💡 Did you know, you can show, collapse, or hide each part of a finding: code, evidence, and all

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread packages/storage/src/operational-state-store.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1b74f9b4-a059-4bab-be8e-52a58db44229

📥 Commits

Reviewing files that changed from the base of the PR and between 781fa8d and 4af7a28.

📒 Files selected for processing (2)
  • packages/storage/src/__tests__/operational-state-store.test.ts
  • packages/storage/src/operational-state-store.ts

Included review availability: Your plan provides up to 3 included reviews per hour; 2 remain after this review.

Comment thread packages/storage/src/operational-state-store.ts Outdated
Comment thread packages/storage/src/operational-state-store.ts

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI-assisted review by Codex. I inspected the current head 6f27a, the historical released writers and table definitions, the atomic migration path, the focused tests, current CI, and the existing Qodo/CodeRabbit feedback.

The problem definition and the chosen seam are sound: obsolete migration metadata should be retired inside the existing atomic schema-convergence transaction, and any state this build cannot recognize should leave the database unchanged. The transaction and rollback ordering preserve that boundary correctly.

The remaining gap is the authority for “released and completed.” Today that decision is split between column-only DDL recognition and permissive row checks. The two inline P2 findings are facets of that same invariant. The smallest coherent correction is to consolidate recognition at the existing schema-signature seam and accept only journal contracts emitted by released writers, while keeping the DROP statements in this transaction.

I would not add a completed_at >= started_at requirement: the released writer used separate Date.now() calls and guaranteed only non-negative timestamps, so wall-clock rollback can produce a legitimate reverse ordering.

中文审查意见

问题定义和处理位置是正确的:应在现有原子 schema convergence 事务内清理已完成的旧迁移元数据,无法识别的状态必须保持数据库原样。

当前剩余问题是“已发布且已完成”的权威定义被拆成了两套不完整判断:只看列形状的 DDL 判断,以及过于宽松的行内容判断。两条行内 P2 属于同一个不变量缺口。最小而完整的方案是复用现有 schema signature 能力,并且只接受历史发布 writer 实际产生过的 journal contract,DROP 仍保留在当前事务中。

不建议增加 completed_at >= started_at:历史 writer 分两次调用 Date.now(),只保证非负数,并不保证墙上时钟单调。

Comment thread packages/storage/src/operational-state-store.ts Outdated
Comment thread packages/storage/src/operational-state-store.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
packages/storage/src/operational-state-store.ts (1)

470-501: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fix now — reject completed_at values that precede started_at.

Lines 480-481 accept any two non-negative integers. A row with started_at = 20 and completed_at = 10 passes validation, and the migration then drops internally inconsistent cutover evidence. Add the ordering check after both integer checks.

Disposition: fix-now.

Proposed fix
     !isNonnegativeInteger(row.started_at) ||
     !isNonnegativeInteger(row.completed_at) ||
+    row.completed_at < row.started_at ||
     typeof row.validation_json !== 'string'

Source: Path instructions

🧹 Nitpick comments (1)
packages/storage/src/operational-target-schema.ts (1)

93-124: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use plain CREATE TABLE for consistency. SQLite stores the canonical SQL without IF NOT EXISTS, so this does not affect signature matching.

Source: Path instructions


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7e1c5bfa-04d2-4fa4-a3a9-0c168d3bf4f6

📥 Commits

Reviewing files that changed from the base of the PR and between 6f27a19 and 381d431.

📒 Files selected for processing (3)
  • packages/storage/src/__tests__/operational-state-store.test.ts
  • packages/storage/src/operational-state-store.ts
  • packages/storage/src/operational-target-schema.ts

Included review availability: Your plan provides up to 3 included reviews per hour; 2 remain after this review.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The latest head correctly closes the full-schema half of the prior review: it reuses the existing sqlite_schema signature seam, matches the released DDL variants, rejects altered constraints and attached objects, and keeps retirement inside the existing atomic migration. The released store-name set is also complete, and the current required checks are green.

One part of the previous invariant remains open: store identity is recognized, but validation evidence is only type-checked, not matched to the released writer for that store. Three independent reviewer passes reproduced the same known-store/unknown-key path; the external DeepSeek pass independently verified the historical writer contracts and the focused 35-test result. The inline P2 is the smallest remaining correction. A completed_at >= started_at constraint should not be added because the released writer used independent wall-clock reads.

I am leaving a review comment rather than approving this head. AI-assisted review by Codex with three independent reviewer agents and OpenCode Go DeepSeek V4 Flash (high); I verified the current head, historical DDL and writers, transaction boundary, focused test evidence, live CI, and deduplicated bot feedback.

中文

最新 head 已正确关闭完整 schema 识别问题:复用现有 sqlite_schema signature,覆盖发布过的 DDL,拒绝修改约束和额外对象,并保持在原子迁移事务中。store_name 白名单也完整,CI 全绿。

但上一轮不变量仍有一半未闭合:当前只识别 store 名,validation_json 仍只做类型检查,没有匹配该 store 的历史 writer evidence contract。已知 store 加未知 key 会被接受并删除 journal。三轮独立 reviewer 均复现了该路径,DeepSeek 也核对了历史 writer contract。请按行内 P2 补齐后再 Approve。不应增加 completed_at >= started_at,因为历史 writer 使用独立 wall-clock 读取。

本次使用 Codex、三个独立 reviewer 和 OpenCode Go DeepSeek V4 Flash high;核对了当前 head、历史 DDL/writer、事务边界、focused tests、实时 CI,并去重了 bot feedback。

Comment thread packages/storage/src/operational-state-store.ts Outdated
liugddx added a commit to liugddx/maka-agent that referenced this pull request Aug 19, 2026
Astro-Han [P2] on apache#3227: the store_name allowlist closed the unknown-store
path, but the evidence contract was still open — a completed `session_metadata`
row with `validation_json = {"anything":0}` passed and the journal was dropped,
though no released writer ever emitted that key. Missing or extra keys on any
known store were accepted the same way, so the retirement still deleted
migration evidence this build never wrote.

Replace the store-name set with a map from each released `store_name` to the
exact validation-key set its `importAndValidate` returned at the final writer
generation (commit 1caea26^): the fifteen session-metadata table counts, and
each other store's fixed evidence keys. A completed row must now carry exactly
that key set — a missing, extra, or renamed key fails closed and preserves the
journal. The contract is pinned to 1caea26^; a cutover written by an earlier
writer whose key set differed fails closed (preserved, startup still blocked),
which is non-regressive versus today and safer than dropping unrecognized
evidence.

Also reject a completed row whose `completed_at` precedes its `started_at`
(CodeRabbit): both pass the integer checks yet the row is internally
inconsistent evidence, not a row a released writer produced.

Tests: the happy-path fixture now carries the full session-metadata contract;
new fail-closed cases cover an extra key, a missing key, and a reversed
timestamp, each asserting the journal survives rollback. Neutralizing either
new guard turns the matching case red.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@liugddx

liugddx commented Aug 19, 2026

Copy link
Copy Markdown
Member Author

Review follow-up

Pushed 62ca27fae to address the outstanding review findings, and re-ran the generic adversarial pre-review checks against the resulting change.

Addressed findings

Astro-Han [P2]: validation evidence was not bound to the released store contract.

The previous RELEASED_CUTOVER_STORE_NAMES allowlist only checked the store name. A completed row for a known store could therefore carry arbitrary, missing, or renamed validation keys and still be deleted. The implementation now maps every released store_name to the exact key set emitted by its final released importAndValidate writer (1caea265c^). Missing, extra, or renamed keys fail closed and preserve the journal.

The session_metadata fixture was updated to include the complete released table-count contract. The contract is explicitly pinned to the final writer generation; an older or unrecognized evidence shape remains preserved and startup-blocked rather than being destructively removed.

CodeRabbit: completion timestamp ordering.

Completed rows now also require completed_at >= started_at. A row with valid integer timestamps but reversed ordering is treated as invalid evidence and remains unchanged.

Verification

  • Biome check: clean
  • npm run build --workspace @maka/storage: passed
  • git diff --check: clean
  • Focused operational-state suite: 37 pass / 0 fail / 1 skipped
  • Delete thought experiment: disabling either new guard makes its regression test fail; all new guards are load-bearing.

The full storage suite remains subject to CI because unrelated tests require the unavailable Darwin fs-native-extensions prebuilt addon in this environment.

Review verdict

The previously identified findings are addressed. The change remains fail-closed for unfamiliar, incomplete, malformed, or internally inconsistent migration evidence. No new P0/P1 issue was found in the follow-up pass.

中文摘要

已推送 62ca27fae 修复审核问题:

  • 不再只校验 store_name,现在按最终发布版本 writer 绑定每个 store 的完整 validation key 集合;缺少、增加或改名的 key 都会 fail-closed 并保留 journal。
  • 增加 completed_at >= started_at 校验,倒序时间戳不会触发删除。
  • Biome、storage build、diff check 均通过;focused suite 为 37 pass / 0 fail / 1 skipped
  • 删除思想实验验证通过:移除任一新 guard,对应回归测试都会失败。

复审结论:之前发现的问题已处理,未发现新的 P0/P1 问题。

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The exact per-store validation-key map now matches the released writers, and the drop remains inside the existing atomic migration transaction. One compatibility blocker remains: the new timestamp ordering rule rejects state that the released writer could legitimately produce.

Several CI jobs are still in progress, so this head is not merge-ready independently of the finding.

AI-assisted review disclosure: Codex reviewed exact head 62ca27f, the released writer provenance, current CI, and thread state, with two independent reviewer passes.

中文说明

当前按 store 精确匹配 validation keys 的方向正确,且删除旧表仍处于原有原子迁移事务内。但新增的时间先后约束超出了已发布 writer 的契约:系统时钟回拨可产生合法的 completed_at < started_at,当前实现会让 workspace 每次启动都被迁移阻塞。另有数个 CI job 仍在运行。

Comment thread packages/storage/src/operational-state-store.ts Outdated
@liugddx

liugddx commented Aug 19, 2026

Copy link
Copy Markdown
Member Author

Scope follow-up

I reviewed the latest feedback and narrowed the patch back to the PR's actual contract.

The exact per-store validation_json key-set check remains: it directly closes the outstanding P2 because a known store with unknown, missing, or renamed evidence must not be destructively retired.

I removed the added completed_at >= started_at requirement in 92f94d988. The released writer used independent wall-clock reads and only guaranteed non-negative timestamps; a clock rollback can legitimately produce completed_at < started_at. Rejecting that state would make an otherwise valid released workspace remain startup-blocked, so this constraint was outside the PR's compatibility contract.

The corresponding regression test was removed as well. The focused suite is now 36 pass / 0 fail / 1 skipped, with Biome, storage build, and git diff --check clean.

The remaining CodeRabbit suggestion to prefer plain CREATE TABLE is a style nit with no correctness impact and is intentionally left out of this PR.

This should be the final scope-limited follow-up: the original evidence-contract blocker is addressed, while the unrelated clock-ordering behavior is not imposed.

@liugddx
liugddx requested a review from Astro-Han August 19, 2026 11:40

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed exact head 92f94d98858c791a257ba2b2f6bf6414b108f0f5.

The storage change is technically coherent: retirement requires the full released legacy signature, preserves fail-closed and rollback paths, and keeps the current schema/store authority intact. Focused Storage tests and current CI pass, there are no unresolved threads, and this does not affect UI/UX.

One provenance gate remains before approval. The PR body does not provide a complete AI-use declaration naming the tools and their scope. Of five substantive commits, only 4af7a288 has a Generated-by: trailer; 6f27a197, 381d4318, and 62ca27fa identify Claude as a co-author but have no matching generation trailer, and 92f94d988 also has none.

Please add the PR-template AI-use declaration and tool/scope, then add the appropriate Generated-by: <tool> trailer to every materially AI-authored commit (or explicitly clarify any human-only commit) and preserve the trailers in the final squash. No code P0-P2 findings remain after that provenance correction.

AI-assisted review disclosure: Codex reviewed the exact-head storage lifecycle, schema signatures, rollback paths, focused tests, live CI, threads, and provenance metadata. No external model was used. Astro-Han authorized this review campaign.

中文说明

代码层面已经闭环:legacy signature、fail-closed、rollback 和当前 schema/store 权威都保持正确;Storage 测试及 CI 全绿,无未解决线程,也不涉及 UI/UX。

批准前还缺 AI provenance:PR body 需要按模板明确工具和范围;5 个实质 commit 只有 1 个有 Generated-by:,其中 3 个还标注了 Claude co-author,但没有对应 generation trailer。请为实质 AI-authored commits 补 trailer,或明确哪些 commit 完全由人工完成。补齐后没有剩余代码 P0-P2。

liugddx and others added 5 commits August 19, 2026 21:54
Allow released workspaces to converge after SQLite became the sole operational authority by validating and retiring the obsolete cutover and import-source tables in the existing atomic migration. Interrupted or unfamiliar cutover state remains fail-closed and unchanged.

Generated-by: Codex
…l-closed paths

Address self-review findings on the cutover-journal retirement:

- Reword the retirement doc comment so it no longer claims "exact released
  table shapes": validation is column-level (name/type/notNull/pk) and does
  not inspect CHECK/FK constraints or indexes. Row-level validation is the
  authoritative content gate.
- Reject an empty validation_json object as evidence (previously `{}` passed
  because `[].every()` is vacuously true).
- Add fail-closed regression tests that were previously missing: unfamiliar
  column shape, malformed import-source row, and an orphaned session import
  source. Each asserts the migration is blocked and the legacy table survives.
- Strengthen the happy-path retirement test to assert real data and schema
  convergence survive (session row present, runtime/session_metadata versions
  registered), not merely that the legacy tables disappeared.

operational-state suite: 31 pass / 0 fail / 1 skip (POSIX-only) on Node 22
with --experimental-sqlite; Biome and tsc clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Generated-by: Codex
…tadata

The legacy-metadata retirement gate only compared column
name/type/notNull/pk, so a `cutover_journal` / import-source table that
shared the released columns but carried an altered CHECK/FK, or an extra
index/trigger, was accepted as an "exact released shape" and dropped.
Likewise a completed journal row naming any non-empty store passed the
row gate, so evidence for a store no released writer ever emitted was
treated as valid and retired. Both widen a destructive, fail-closed
operation to inputs it cannot actually recognize.

Replace the column-only check with a full `sqlite_schema` signature gate
reusing the normalized-DDL seam in operational-target-schema.ts: a legacy
table is retired only when every object attached to it matches the
released layout down to constraints, with no extra index/trigger. Whitelist
the exact `store_name` set the released writers emitted (session_metadata
plus every completeOperationalStoreCutover caller) and fail closed on any
other. Not tightening `completed_at`/`started_at`: the released writer
used independent Date.now() calls and only guaranteed non-negativity.

Add regression tests for altered-constraint, extra-trigger, and
unknown-store journals — each asserts the migration fails closed and the
legacy state is preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Generated-by: Codex
Astro-Han [P2] on apache#3227: the store_name allowlist closed the unknown-store
path, but the evidence contract was still open — a completed `session_metadata`
row with `validation_json = {"anything":0}` passed and the journal was dropped,
though no released writer ever emitted that key. Missing or extra keys on any
known store were accepted the same way, so the retirement still deleted
migration evidence this build never wrote.

Replace the store-name set with a map from each released `store_name` to the
exact validation-key set its `importAndValidate` returned at the final writer
generation (commit 1caea26^): the fifteen session-metadata table counts, and
each other store's fixed evidence keys. A completed row must now carry exactly
that key set — a missing, extra, or renamed key fails closed and preserves the
journal. The contract is pinned to 1caea26^; a cutover written by an earlier
writer whose key set differed fails closed (preserved, startup still blocked),
which is non-regressive versus today and safer than dropping unrecognized
evidence.

Also reject a completed row whose `completed_at` precedes its `started_at`
(CodeRabbit): both pass the integer checks yet the row is internally
inconsistent evidence, not a row a released writer produced.

Tests: the happy-path fixture now carries the full session-metadata contract;
new fail-closed cases cover an extra key, a missing key, and a reversed
timestamp, each asserting the journal survives rollback. Neutralizing either
new guard turns the matching case red.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Generated-by: Codex
@liugddx
liugddx force-pushed the fix/retire-completed-cutover-journal branch from 92f94d9 to 6edf57b Compare August 19, 2026 13:55
@liugddx

liugddx commented Aug 19, 2026

Copy link
Copy Markdown
Member Author

Provenance gate addressed

The latest review identified a repository-compliance blocker, not a new code defect: the PR body lacked the required AI-use declaration and the materially AI-authored commits did not all carry the required trailer.

This is now addressed without expanding the code scope:

  • The PR description now selects Generative tooling made a substantive contribution and names Codex and Claude Code, with their scope.
  • All five substantive commits in this PR now carry Generated-by: Codex trailers, preserved in their commit messages.
  • The code remains unchanged from the scope-limited head: exact per-store validation-key matching stays; the incompatible timestamp-ordering rule remains removed.
  • No new code P0-P2 finding remains in the latest review. The CREATE TABLE formatting suggestion is a non-blocking nit and is intentionally outside this PR's scope.

The rewritten commit chain was force-pushed with --force-with-lease; the PR body and final commit history are now aligned with the repository's AI attribution requirements.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved exact head 6edf57b83d4693719737da3b256a63f17f2b7094.

The prior provenance blocker is fully resolved: the PR body now discloses the Codex and Claude Code scopes, all five material commits carry Generated-by: Codex, and the retained Claude co-author trailers match the disclosure. The storage-only diff remains sound, all review threads are resolved, and I found no P0–P3 issue. There is no UI/UX change, so no screenshot is required.

This approval is conditional on the remaining queued required checks finishing green before merge.

AI-assisted review disclosure: OpenAI Codex performed the exact-head code, provenance, review-thread, and CI analysis; I verified the commit trailers, disclosure scope, and live GitHub state before approving.

中文说明

此前的 AI provenance 缺口已完整修复:body 说明清楚,5 个实质性提交都有 Generated-by: Codex,Claude co-author 信息也一致。代码没有 P0–P3,线程已全部解决,无 UI 变化。剩余 required checks 全绿后才算 merge-ready。

@Astro-Han
Astro-Han merged commit fd16fef into apache:main Aug 19, 2026
17 checks passed
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