Skip to content

fix(FN-7952): require PostgreSQL in CLI and desktop#2110

Merged
gsxdsm merged 4 commits into
mainfrom
feature/postgres-cutover-cli-desktop
Jul 15, 2026
Merged

fix(FN-7952): require PostgreSQL in CLI and desktop#2110
gsxdsm merged 4 commits into
mainfrom
feature/postgres-cutover-cli-desktop

Conversation

@gsxdsm

@gsxdsm gsxdsm commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

CLI commands, daemon/dashboard startup, packaged desktop startup, and live-data maintenance scripts now share the mandatory PostgreSQL lifecycle. Operators no longer risk a command silently reading or writing a disconnected SQLite shadow when PostgreSQL setup fails.

Design decisions

  • Every startup owner retains and awaits its PostgreSQL shutdown callback, including partial-startup failure paths.
  • CLI project context and lock-retry flows resolve through asynchronous project stores.
  • Maintenance scripts use the shared backend helper; explicit database migration/inspection remains the only CLI surface allowed to read legacy SQLite sources.

Validation

  • CLI and Desktop typechecks pass on the stacked branch.
  • pnpm test:gate passes all 478 gate tests.
  • This PR changes 54 files.

Stack

Related: #2105

Summary by CodeRabbit

  • New Features

    • PostgreSQL is now the authoritative store for structured project and task metadata.
    • Projects can be recognized and initialized using .fusion/project.json, without creating a legacy SQLite database.
    • CLI commands now retry transient PostgreSQL contention errors.
  • Bug Fixes

    • Improved cleanup when commands complete, fail, or run in the background, preventing lingering resources.
    • Improved desktop, server, and session shutdown reliability.
  • Documentation

    • Updated storage and standalone binary guidance to reflect PostgreSQL and legacy SQLite compatibility.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@gsxdsm, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 24 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0681283d-d7a4-4020-b8db-8f173c3612d5

📥 Commits

Reviewing files that changed from the base of the PR and between bff151c and 9048434.

📒 Files selected for processing (20)
  • packages/cli/src/__tests__/project-context-lifecycle.test.ts
  • packages/cli/src/__tests__/project-resolver.test.ts
  • packages/cli/src/commands/__tests__/agent-import.test.ts
  • packages/cli/src/commands/__tests__/project-lock-retry.test.ts
  • packages/cli/src/commands/__tests__/research-lock-retry.test.ts
  • packages/cli/src/commands/__tests__/research.test.ts
  • packages/cli/src/commands/__tests__/settings-export.test.ts
  • packages/cli/src/commands/agent-import.ts
  • packages/cli/src/commands/agent.ts
  • packages/cli/src/commands/chat.ts
  • packages/cli/src/commands/desktop.ts
  • packages/cli/src/commands/experiment-finalize.ts
  • packages/cli/src/commands/mission.ts
  • packages/cli/src/commands/project.ts
  • packages/cli/src/commands/research.ts
  • packages/cli/src/commands/settings-export.ts
  • packages/cli/src/project-context.ts
  • packages/cli/src/project-resolver.ts
  • packages/cli/vitest.config.ts
  • scripts/lib/test-quarantine.json
📝 Walkthrough

Walkthrough

The CLI now treats PostgreSQL as the authoritative runtime store, uses .fusion/project.json for local identity, and routes command, project, extension, desktop, and script cleanup through explicit asynchronous backend ownership.

Changes

PostgreSQL CLI lifecycle

Layer / File(s) Summary
Project identity and migration detection
packages/cli/src/commands/init.ts, project.ts, ensure-project-registered.ts, project-context.ts, scripts/lib/start-local-project.mjs
Initialization and project discovery recognize .fusion/project.json; legacy fusion.db remains migration input only.
Owned project and backend shutdown
packages/cli/src/project-context.ts, project-resolver.ts, packages/cli/src/commands/desktop.ts, extension.ts
Backend factories return shutdown owners, project stores close idempotently, CentralCore teardown follows store ownership, and cached session stores await shutdown.
Command cleanup adoption
packages/cli/src/commands/{agent,chat,message,mission,research,settings-export,settings-import,workflow,experiment-finalize}.ts
Commands use PostgreSQL async layers and await store or backend cleanup before exits, including background research runs and mission control-flow exits.
Retry and supporting integrations
packages/cli/src/lock-retry.ts, scripts/*.mjs, packages/desktop/src/**, packages/cli/src/**/__tests__/*
PostgreSQL contention becomes retryable, scripts use openBackend, and tests cover shutdown ordering, project identity, backend ownership, and async-layer wiring.

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

Sequence Diagram(s)

sequenceDiagram
  participant CLICommand
  participant ProjectContext
  participant BackendFactory
  participant TaskStore
  participant CentralCore
  CLICommand->>ProjectContext: resolve project and store owner
  ProjectContext->>BackendFactory: createTaskStoreForBackend
  BackendFactory-->>ProjectContext: taskStore and shutdown
  CLICommand->>TaskStore: execute command operations
  CLICommand->>ProjectContext: close project store
  ProjectContext->>BackendFactory: shutdown backend
  ProjectContext->>CentralCore: close retained core
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the core change: requiring PostgreSQL in the CLI and desktop stack.
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
  • Commit unit tests in branch feature/postgres-cutover-cli-desktop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes PostgreSQL the required runtime store across CLI, desktop, and maintenance workflows. The main changes are:

  • Explicit PostgreSQL startup and shutdown ownership for short-lived commands and long-running processes.
  • Asynchronous project-store resolution and cleanup across CLI commands.
  • Durable queued dispatch for non-wait research runs.
  • project.json-based project discovery with legacy SQLite migration support.
  • Shared PostgreSQL backend access for maintenance scripts.

Confidence Score: 4/5

The research queue race should be fixed before merging.

  • An active dispatcher can claim a queued run before its query is stored.
  • The run can execute with an empty query and persist incorrect results.
  • The PostgreSQL ownership fixes otherwise cover the reported cleanup paths.

packages/cli/src/commands/research.ts

Important Files Changed

Filename Overview
packages/cli/src/commands/research.ts Moves non-wait research to queued dispatch, but the query and dispatchable state are not persisted atomically.
packages/cli/src/project-context.ts Adds explicit ownership and retryable cleanup for cached PostgreSQL project stores.
packages/cli/src/commands/settings-export.ts Closes resolver and export backend ownership before process exit.
packages/cli/src/commands/experiment-finalize.ts Releases resolver and finalization backends across success and failure paths.
scripts/lib/start-local-project.mjs Recognizes current project markers and valid legacy SQLite migration inputs.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant CLI as Research CLI
    participant DB as PostgreSQL
    participant Dispatcher as Research Dispatcher
    CLI->>DB: Create queued run with empty query
    Dispatcher->>DB: Poll queued runs
    DB-->>Dispatcher: Return incomplete run
    Dispatcher->>Dispatcher: Start run with empty query
    CLI->>DB: Store supplied query
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant CLI as Research CLI
    participant DB as PostgreSQL
    participant Dispatcher as Research Dispatcher
    CLI->>DB: Create queued run with empty query
    Dispatcher->>DB: Poll queued runs
    DB-->>Dispatcher: Return incomplete run
    Dispatcher->>Dispatcher: Start run with empty query
    CLI->>DB: Store supplied query
Loading

Reviews (4): Last reviewed commit: "fix(FN-7952): resolve CLI lifecycle feed..." | Re-trigger Greptile

Comment thread packages/cli/src/commands/research.ts Outdated
Comment thread packages/cli/src/commands/settings-export.ts Outdated
Comment thread packages/cli/src/commands/experiment-finalize.ts Outdated
Comment thread scripts/start-local.mjs Outdated
@gsxdsm
gsxdsm force-pushed the feature/postgres-cutover-runtime branch from 8b9125d to 73ed302 Compare July 15, 2026 05:06
Base automatically changed from feature/postgres-cutover-runtime to main July 15, 2026 05:16
gsxdsm added 3 commits July 14, 2026 22:18
Move CLI commands, desktop startup, and operational maintenance scripts onto the authoritative PostgreSQL lifecycle without runtime SQLite fallback.

Fusion-Task-Id: FN-7952
@gsxdsm
gsxdsm force-pushed the feature/postgres-cutover-cli-desktop branch from 4cf7da9 to bff151c Compare July 15, 2026 05:34
Comment thread packages/cli/src/commands/research.ts Outdated

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/cli/src/commands/project.ts (2)

152-180: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Use the backend shutdown owner as the sole cleanup path.

boot.shutdown() already closes boot.taskStore; closing the store first performs teardown twice and obscures ownership.

Proposed fix
-    try {
-      await store?.close();
-    } catch {
-      // Best-effort: an already-closed/never-initialized store must not throw.
-    }
     if (backendShutdown) {
       await backendShutdown().catch(() => undefined);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/commands/project.ts` around lines 152 - 180, Update the
cleanup logic in the surrounding task-counting function to use backendShutdown
as the sole teardown path: remove the direct store.close() call from finally and
invoke boot.shutdown() when available, preserving best-effort error handling for
shutdown failures.

361-373: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Treat BackendBootResult.shutdown() as the sole cleanup owner.

The current production paths manually close the store, while one test mock omits that behavior from shutdown. This causes double closure and leaks the backend when initialization rejects.

  • packages/cli/src/commands/project.ts#L361-L373: wrap initialization in try/finally and invoke only boot.shutdown().
  • packages/cli/src/commands/project.ts#L152-L180: remove the direct store.close() and invoke the retained shutdown owner.
  • packages/cli/src/commands/__tests__/project-lock-retry.test.ts#L49-L51: make mocked shutdown call the corresponding task store’s close().
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/commands/project.ts` around lines 361 - 373, Make
BackendBootResult.shutdown() the sole cleanup owner: in
packages/cli/src/commands/project.ts lines 361-373, wrap store initialization in
try/finally and invoke only boot.shutdown(), ensuring cleanup runs when
initialization rejects; in packages/cli/src/commands/project.ts lines 152-180,
remove direct store.close() calls and retain shutdown cleanup; in
packages/cli/src/commands/__tests__/project-lock-retry.test.ts lines 49-51,
update the mocked shutdown to close its corresponding task store.
🧹 Nitpick comments (2)
packages/cli/src/commands/agent.ts (1)

167-173: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove redundant catch blocks.

The catch block is completely redundant because it only executes closeAgentStoreSafely(agentStore) before rethrowing, and the finally block immediately executes the exact same cleanup.

  • packages/cli/src/commands/agent.ts#L167-L173: Remove the catch block and leave only the finally block for runAgentStop.
  • packages/cli/src/commands/agent.ts#L222-L228: Remove the catch block and leave only the finally block for runAgentStart.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/commands/agent.ts` around lines 167 - 173, Remove the
redundant catch blocks from runAgentStop at packages/cli/src/commands/agent.ts
lines 167-173 and runAgentStart at lines 222-228; retain each finally block’s
closeAgentStoreSafely(agentStore) and owned.cleanup() calls so cleanup still
runs while errors propagate naturally.
packages/cli/src/project-resolver.ts (1)

973-1018: 🚀 Performance & Scalability | 🔵 Trivial

Cap status fan-out in getProjectsWithStatus. createTaskStoreForBackend still opens a fresh connection set per call, so a large registry can create N concurrent pools on this hot path. Reuse one backend boot for the listing or bound the concurrency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/project-resolver.ts` around lines 973 - 1018, Update
getProjectsWithStatus so task listing does not create one concurrent
createTaskStoreForBackend boot per project. Prefer initializing a single shared
backend boot for the operation and reusing its task store across project
listings, ensuring its shutdown runs once after all work completes; otherwise
introduce an explicit concurrency limit while preserving per-project taskCount
fallback behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/__tests__/project-resolver.test.ts`:
- Around line 177-207: Add rejection cases for listTasks in both
getProjectsWithStatus and getProjectTaskCounts, and assert the operation rejects
while the owned store’s shutdown function is still called once. Preserve the
existing successful-path assertions and use the same createTaskStoreForBackend
mocks to cover both aggregate status and one-shot column-count flows.

In `@packages/cli/src/commands/__tests__/agent-import.test.ts`:
- Around line 9-12: Update the resolveAgentStoreBase mock used by the
agent-import tests so asyncLayer is a non-null fake PostgreSQL backend, matching
the updated agent export and command test fixtures; keep the mock’s existing
rootDir and cleanup behavior unchanged.

In `@packages/cli/src/commands/__tests__/project-lock-retry.test.ts`:
- Line 48: Update the FNXC comment in the project-lock retry test to describe
the current mock and decision now that it no longer returns null, and replace
the date-only timestamp with the required yyyy-MM-dd-hh:mm format. Keep the
existing FNXC:Area-of-product structure and do not add an FNXC_LOG token.
- Around line 49-51: Update the createTaskStoreForBackend mock so its shutdown
implementation explicitly invokes taskStore.close() before resolving. Preserve
the existing shutdown mock behavior while ensuring the mock owns TaskStore
lifecycle cleanup like production BackendBootResult.shutdown().

In `@packages/cli/src/commands/__tests__/settings-export.test.ts`:
- Around line 166-171: Update the test case around runSettingsExport to verify
cleanup ordering, not just invocation count: capture or inspect the call order
of closeProjectStore and createTaskStoreForBackend, and assert closeProjectStore
is invoked before backend startup is attempted. Keep the existing startup
failure assertion and cleanup-count check.

In `@packages/cli/src/commands/agent-import.ts`:
- Around line 236-239: Update the exitWithCleanup helper so base.cleanup()
always runs even when agentStore.close() throws by placing cleanup in a finally
block. Preserve the helper’s Promise<never> exit behavior, ensuring
process.exit(code) occurs after all teardown attempts.

In `@packages/cli/src/commands/chat.ts`:
- Around line 33-37: Ensure cleanup always runs when store closure fails: in
packages/cli/src/commands/chat.ts lines 33-37, wrap store.close() in a
synchronous try/catch before awaiting base.cleanup(); in lines 229-233, apply
the same pattern to agentStore.close() so ownedAgentStore.cleanup() executes,
and safely suppress rejection from messageOwner?.db.close() with catch handling.

In `@packages/cli/src/commands/desktop.ts`:
- Around line 35-36: Update the FNXC comment in the desktop startup section to
replace the date-only timestamp with the actual change date and time in
yyyy-MM-dd-hh:mm format, while preserving the existing FNXC:PostgresCutover
prefix and comment content.

In `@packages/cli/src/commands/experiment-finalize.ts`:
- Around line 53-55: Prevent shutdown rejection from bypassing CLI termination:
in packages/cli/src/commands/experiment-finalize.ts lines 53-55, update
exitWithError to contain or handle shutdown failure, then preserve the original
mapped error and established exit code; in
packages/cli/src/commands/settings-export.ts lines 38-42, apply the same
teardown-failure guard so error handling always reaches the intended failure
process.exit.

In `@packages/cli/src/commands/mission.ts`:
- Around line 227-230: Update the FNXC comment near the PostgreSQL
mission-interview draft query to include the required hour-and-minute component
in its date, using the yyyy-MM-dd-hh:mm format while preserving the existing
area and explanation.

In `@packages/cli/src/project-context.ts`:
- Around line 48-55: Update the store shutdown flow around
owner.backendShutdown(), owner.central?.close(), and owner.closePromise so
teardown errors are not swallowed as successful completion. Ensure both
resources are attempted, but only delete the owner and add the store to
closedProjectStores after both close operations succeed; preserve or reset
closePromise on failure so callers can observe the error or retry cleanup.

---

Outside diff comments:
In `@packages/cli/src/commands/project.ts`:
- Around line 152-180: Update the cleanup logic in the surrounding task-counting
function to use backendShutdown as the sole teardown path: remove the direct
store.close() call from finally and invoke boot.shutdown() when available,
preserving best-effort error handling for shutdown failures.
- Around line 361-373: Make BackendBootResult.shutdown() the sole cleanup owner:
in packages/cli/src/commands/project.ts lines 361-373, wrap store initialization
in try/finally and invoke only boot.shutdown(), ensuring cleanup runs when
initialization rejects; in packages/cli/src/commands/project.ts lines 152-180,
remove direct store.close() calls and retain shutdown cleanup; in
packages/cli/src/commands/__tests__/project-lock-retry.test.ts lines 49-51,
update the mocked shutdown to close its corresponding task store.

---

Nitpick comments:
In `@packages/cli/src/commands/agent.ts`:
- Around line 167-173: Remove the redundant catch blocks from runAgentStop at
packages/cli/src/commands/agent.ts lines 167-173 and runAgentStart at lines
222-228; retain each finally block’s closeAgentStoreSafely(agentStore) and
owned.cleanup() calls so cleanup still runs while errors propagate naturally.

In `@packages/cli/src/project-resolver.ts`:
- Around line 973-1018: Update getProjectsWithStatus so task listing does not
create one concurrent createTaskStoreForBackend boot per project. Prefer
initializing a single shared backend boot for the operation and reusing its task
store across project listings, ensuring its shutdown runs once after all work
completes; otherwise introduce an explicit concurrency limit while preserving
per-project taskCount fallback behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ff61df52-4251-43df-b597-bed77e175d41

📥 Commits

Reviewing files that changed from the base of the PR and between ba1e823 and bff151c.

📒 Files selected for processing (58)
  • .changeset/postgres-cli-lifecycle.md
  • packages/cli/STANDALONE.md
  • packages/cli/skill/fusion/references/fusion-capabilities.md
  • packages/cli/skill/fusion/references/task-structure.md
  • packages/cli/src/__tests__/experiment-finalize.test.ts
  • packages/cli/src/__tests__/extension.test.ts
  • packages/cli/src/__tests__/project-context-lifecycle.test.ts
  • packages/cli/src/__tests__/project-context.test.ts
  • packages/cli/src/__tests__/project-resolver.test.ts
  • packages/cli/src/commands/__tests__/agent-export.test.ts
  • packages/cli/src/commands/__tests__/agent-import.test.ts
  • packages/cli/src/commands/__tests__/agent.test.ts
  • packages/cli/src/commands/__tests__/desktop.test.ts
  • packages/cli/src/commands/__tests__/ensure-project-registered.test.ts
  • packages/cli/src/commands/__tests__/init.test.ts
  • packages/cli/src/commands/__tests__/message.test.ts
  • packages/cli/src/commands/__tests__/project-lock-retry.test.ts
  • packages/cli/src/commands/__tests__/research-lock-retry.test.ts
  • packages/cli/src/commands/__tests__/research.test.ts
  • packages/cli/src/commands/__tests__/serve.test.ts
  • packages/cli/src/commands/__tests__/settings-export.test.ts
  • packages/cli/src/commands/__tests__/settings-import-lock-retry.test.ts
  • packages/cli/src/commands/__tests__/settings-import.test.ts
  • packages/cli/src/commands/__tests__/task-lock-retry.test.ts
  • packages/cli/src/commands/agent-export.ts
  • packages/cli/src/commands/agent-import.ts
  • packages/cli/src/commands/agent.ts
  • packages/cli/src/commands/chat.ts
  • packages/cli/src/commands/db.ts
  • packages/cli/src/commands/desktop.ts
  • packages/cli/src/commands/ensure-project-registered.ts
  • packages/cli/src/commands/experiment-finalize.ts
  • packages/cli/src/commands/init.ts
  • packages/cli/src/commands/message.ts
  • packages/cli/src/commands/mission.ts
  • packages/cli/src/commands/onboard-autolaunch.ts
  • packages/cli/src/commands/project.ts
  • packages/cli/src/commands/research.ts
  • packages/cli/src/commands/settings-export.ts
  • packages/cli/src/commands/settings-import.ts
  • packages/cli/src/commands/workflow.ts
  • packages/cli/src/extension.ts
  • packages/cli/src/lock-retry.ts
  • packages/cli/src/project-context.ts
  • packages/cli/src/project-resolver.ts
  • packages/desktop/src/__tests__/local-runtime.test.ts
  • packages/desktop/src/__tests__/local-server.test.ts
  • packages/desktop/vitest.config.ts
  • scripts/__tests__/backfill-fn-4441-transition-evidence.test.mjs
  • scripts/__tests__/start-local-project.test.mjs
  • scripts/backfill-fn-4441-transition-evidence.mjs
  • scripts/cache-stats.mjs
  • scripts/lib/backend-db.mjs
  • scripts/lib/start-local-project.mjs
  • scripts/reconcile-fn-3909-identity.mjs
  • scripts/reconcile-task-state-consistency.mjs
  • scripts/restore-merge-sha-fn-3878.mjs
  • scripts/start-local.mjs

Comment thread packages/cli/src/__tests__/project-resolver.test.ts
Comment thread packages/cli/src/commands/__tests__/agent-import.test.ts
Comment thread packages/cli/src/commands/__tests__/project-lock-retry.test.ts Outdated
Comment thread packages/cli/src/commands/__tests__/project-lock-retry.test.ts Outdated
Comment thread packages/cli/src/commands/__tests__/settings-export.test.ts
Comment thread packages/cli/src/commands/chat.ts
Comment thread packages/cli/src/commands/desktop.ts Outdated
Comment thread packages/cli/src/commands/experiment-finalize.ts Outdated
Comment thread packages/cli/src/commands/mission.ts Outdated
Comment thread packages/cli/src/project-context.ts Outdated
@gsxdsm

gsxdsm commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator Author

Verification evidence for the deletion-ratchet ledger: a combined file-scoped CLI run on 2026-07-14 observed src/__tests__/project-context.test.ts lose its embedded PostgreSQL postmaster, then fail hooks with ECONNREFUSED/10s timeouts and the subprocess guard. The unchanged suite passed 12/12 immediately when isolated (21.6s), while the nine directly changed suites passed 145 tests in the combined run. This is a loaded-lane embedded-cluster interference flake, not an assertion/product failure; it will be quarantined rather than retried, given wider timeouts, or weakened.

@gsxdsm

gsxdsm commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator Author

Use the backend shutdown owner as the sole cleanup path.
Remove redundant catch blocks.
Cap status fan-out in getProjectsWithStatus.

Addressed in 904843416:

  • project task counts and interactive initialization now use BackendBootResult.shutdown() as the sole store owner, including init rejection; the lifecycle mock closes its returned store from shutdown;
  • redundant agent start/stop catches were removed while authoritative finally cleanup remains;
  • project status reads use four bounded workers, preserve registry order and per-project fallback behavior, and release each backend on success or failure;
  • teardown errors remain observable/retryable where callers can recover, while CLI exit helpers preserve their established exit codes.

Verification: focused changed suites passed; CLI typecheck and production lint passed; merge gate passed 479/479 (294 engine + 122 PostgreSQL + 63 CI-shape). The loaded-lane project-context.test.ts postmaster flake was quarantined under the deletion ratchet with evidence in the earlier comment; it passed 12/12 in isolation.

});

const runPromise = orchestrator.startRun(runId, options.query);
await store.getResearchStore().updateRun(runId, { query: options.query });

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.

P1 Queue Complete Runs Atomically

createRun() first publishes a queued row with an empty query, and this separate updateRun() stores the supplied query afterward. When a server, daemon, or desktop engine is already polling the same database, its dispatcher can claim the row between these operations and call startRun() with an empty query. The run can then fail or produce results for the wrong input. Store the query when creating the queued row, or keep the row out of the dispatchable state until this update finishes.

@gsxdsm
gsxdsm merged commit 97172fd into main Jul 15, 2026
7 checks passed
@gsxdsm
gsxdsm deleted the feature/postgres-cutover-cli-desktop branch July 15, 2026 06:18
gsxdsm added a commit that referenced this pull request Jul 15, 2026
## Summary

Operators and contributors now have one current contract for the
completed PostgreSQL cutover: PostgreSQL is mandatory runtime authority,
legacy SQLite files are read-only migration evidence, and rollback is
restore-based rather than a fallback toggle. The major changeset
communicates the same boundary to published CLI users.

## Operational guidance

- Documents the authoritative storage inventory and the five intentional
legacy SQLite readers.
- Defines maintenance-window migration, backup, restore-test, ownership,
and isolation checks.
- Clarifies lifecycle ownership for CLI, desktop, dashboard, engine, and
bundled plugins.
- Supersedes the earlier readiness review without deleting its
historical record.

## Validation

- Changeset format check passes.
- `pnpm test:gate` passes all 478 gate tests on the completed stack.
- Every file from the original oversized PR is represented in the
replacement stack; this PR changes 22 files.

## Stack

- Depends on #2111#2110#2109#2108.
- Merge bottom-up in that order.

Related: #2105
gsxdsm added a commit that referenced this pull request Jul 15, 2026
## Summary

Operators and contributors now have one current contract for the
completed PostgreSQL cutover: PostgreSQL is mandatory runtime authority,
legacy SQLite files are read-only migration evidence, and rollback is
restore-based rather than a fallback toggle. The major changeset
communicates the same boundary to published CLI users.

## Operational guidance

- Documents the authoritative storage inventory and the five intentional
legacy SQLite readers.
- Defines maintenance-window migration, backup, restore-test, ownership,
and isolation checks.
- Clarifies lifecycle ownership for CLI, desktop, dashboard, engine, and
bundled plugins.
- Supersedes the earlier readiness review without deleting its
historical record.

## Validation

- Changeset format check passes.
- `pnpm test:gate` passes all 478 gate tests on the completed stack.
- Every file from the original oversized PR is represented in the
replacement stack; this PR changes 22 files.

## Stack

- Depends on #2111#2110#2109#2108.
- Merge bottom-up in that order.

Related: #2105
gsxdsm added a commit that referenced this pull request Jul 15, 2026
## Summary

Operators and contributors now have one current contract for the
completed PostgreSQL cutover: PostgreSQL is mandatory runtime authority,
legacy SQLite files are read-only migration evidence, and rollback is
restore-based rather than a fallback toggle. The major changeset
communicates the same boundary to published CLI users.

## Operational guidance

- Documents the authoritative storage inventory and the five intentional
legacy SQLite readers.
- Defines maintenance-window migration, backup, restore-test, ownership,
and isolation checks.
- Clarifies lifecycle ownership for CLI, desktop, dashboard, engine, and
bundled plugins.
- Supersedes the earlier readiness review without deleting its
historical record.

## Validation

- Changeset format check passes.
- `pnpm test:gate` passes all 478 gate tests on the completed stack.
- Every file from the original oversized PR is represented in the
replacement stack; this PR changes 22 files.

## Stack

- Depends on #2111#2110#2109#2108.
- Merge bottom-up in that order.

Related: #2105
gsxdsm added a commit that referenced this pull request Jul 15, 2026
## Summary

Bundled plugins now persist shared runtime state in project-scoped
PostgreSQL tables instead of maintaining independent SQLite authority.
Reports, CLI Printing Press, Compound Engineering, Roadmap, Even
Realities, and WhatsApp all follow the same ownership and startup
contract as Fusion core.

## Design decisions

- Plugin schema hooks run through the host’s PostgreSQL owner and
enforce project isolation.
- The SDK exposes the host contract needed by bundled plugins without
importing engine internals.
- Legacy Roadmap ownership fixtures use the supported empty-owner
sentinel, preserving current composite primary/foreign keys while
exercising backfill behavior.
- The lockfile travels with the Even Realities PostgreSQL dependency so
packaged installs remain reproducible.

## Validation

- All six affected plugin builds pass.
- Affected plugin suites pass: 773 tests across Printing Press, Compound
Engineering, Even Realities, Reports, Roadmap, and WhatsApp.
- `pnpm test:gate` passes all 478 gate tests.
- This PR changes 40 files.

## Stack

- Depends on #2110#2109#2108.
- The documentation/release PR completes the stack.

Related: #2105


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Breaking Changes**
* PostgreSQL is now required for runtime storage; SQLite files are used
only as one-time migration inputs.
  * The legacy `FUSION_NO_EMBEDDED_PG` fallback has been removed.

* **New Features**
* Added project-isolated PostgreSQL storage for plugins, reports, tasks,
notifications, and other plugin data.
  * Added agent tools for reports and CLI service drafts.
  * Added PostgreSQL schema initialization support for plugin authors.

* **Bug Fixes**
  * Improved migration and recovery of legacy plugin state.
* Prevented cross-project data access and strengthened transactional
schema updates.

* **Documentation**
* Updated storage, migration, deployment, plugin authoring, CLI, and
dashboard guidance for PostgreSQL.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
gsxdsm added a commit that referenced this pull request Jul 15, 2026
## Summary

CLI commands, daemon/dashboard startup, packaged desktop startup, and
live-data maintenance scripts now share the mandatory PostgreSQL
lifecycle. Operators no longer risk a command silently reading or
writing a disconnected SQLite shadow when PostgreSQL setup fails.

## Design decisions

- Every startup owner retains and awaits its PostgreSQL shutdown
callback, including partial-startup failure paths.
- CLI project context and lock-retry flows resolve through asynchronous
project stores.
- Maintenance scripts use the shared backend helper; explicit database
migration/inspection remains the only CLI surface allowed to read legacy
SQLite sources.

## Validation

- CLI and Desktop typechecks pass on the stacked branch.
- `pnpm test:gate` passes all 478 gate tests.
- This PR changes 54 files.

## Stack

- Depends on #2109, which depends on #2108.
- Bundled plugins and docs/release follow in later PRs.

Related: #2105


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* PostgreSQL is now the authoritative store for structured project and
task metadata.
* Projects can be recognized and initialized using
`.fusion/project.json`, without creating a legacy SQLite database.
  * CLI commands now retry transient PostgreSQL contention errors.

* **Bug Fixes**
* Improved cleanup when commands complete, fail, or run in the
background, preventing lingering resources.
  * Improved desktop, server, and session shutdown reliability.

* **Documentation**
* Updated storage and standalone binary guidance to reflect PostgreSQL
and legacy SQLite compatibility.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
gsxdsm added a commit that referenced this pull request Jul 15, 2026
## Summary

Bundled plugins now persist shared runtime state in project-scoped
PostgreSQL tables instead of maintaining independent SQLite authority.
Reports, CLI Printing Press, Compound Engineering, Roadmap, Even
Realities, and WhatsApp all follow the same ownership and startup
contract as Fusion core.

## Design decisions

- Plugin schema hooks run through the host’s PostgreSQL owner and
enforce project isolation.
- The SDK exposes the host contract needed by bundled plugins without
importing engine internals.
- Legacy Roadmap ownership fixtures use the supported empty-owner
sentinel, preserving current composite primary/foreign keys while
exercising backfill behavior.
- The lockfile travels with the Even Realities PostgreSQL dependency so
packaged installs remain reproducible.

## Validation

- All six affected plugin builds pass.
- Affected plugin suites pass: 773 tests across Printing Press, Compound
Engineering, Even Realities, Reports, Roadmap, and WhatsApp.
- `pnpm test:gate` passes all 478 gate tests.
- This PR changes 40 files.

## Stack

- Depends on #2110#2109#2108.
- The documentation/release PR completes the stack.

Related: #2105


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Breaking Changes**
* PostgreSQL is now required for runtime storage; SQLite files are used
only as one-time migration inputs.
  * The legacy `FUSION_NO_EMBEDDED_PG` fallback has been removed.

* **New Features**
* Added project-isolated PostgreSQL storage for plugins, reports, tasks,
notifications, and other plugin data.
  * Added agent tools for reports and CLI service drafts.
  * Added PostgreSQL schema initialization support for plugin authors.

* **Bug Fixes**
  * Improved migration and recovery of legacy plugin state.
* Prevented cross-project data access and strengthened transactional
schema updates.

* **Documentation**
* Updated storage, migration, deployment, plugin authoring, CLI, and
dashboard guidance for PostgreSQL.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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.

1 participant