Skip to content

Commit 8ca7817

Browse files
GiniGini
authored andcommitted
Document follow-up lease recovery boundaries
1 parent a6f049c commit 8ca7817

6 files changed

Lines changed: 23 additions & 7 deletions

File tree

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Run `npm run e2e:auth-owner` for the local auth/ownership proof. It uses a loopb
6565

6666
The Postgres TaskStore proof additionally covers standalone-message restart recovery, atomic native-envelope/projection replay and conflict handling, transaction-backed fork history, owner-isolated MCP/org/skill operations, lease allocation/transition/restart recovery, transaction-backed workspace bytes/version restore/compare/copy, current project-file bytes/revisions, interrupted-task reconciliation, HTTP driver/read-boundary evidence, a real legacy import proof for workspace/project/native bytes and projection metadata, attachment path/size validation, a two-instance event-allocation/durable-polling proof, and `npm run e2e:postgres-http-sse` authenticated two-process HTTP live delivery plus suffix replay. Postgres is now an opt-in running driver when `ONEVIBE_PERSISTENCE_DRIVER=postgres` and `DATABASE_URL` are present; authenticated owner scope is required for its data plane. `TaskStore.beginTurn` uses a stable client request key to reuse a durable turn/message pair across SQLite/Postgres and does not reactivate terminal replays. Centralized private-path filtering keeps conventional and metadata-declared attachments/evidence out of public file lists, direct reads/edits, and portable exports. Keyed follow-ups now create a durable `follow_up_operation` journal, recover prepared/ready work after restart, and fail running work closed when the external provider outcome is unknown; `npm run e2e:follow-up-recovery` is the local proof. Remaining gaps are atomic attachment/task persistence, durable execution leases, provider request identity/unknown-outcome reconciliation, production broker/tuning, and production deployment controls.
6767

68-
The Postgres target contract lives in `server/db/schema.ts` and `server/db/migrations/`; run `npm run db:check` and regenerate only through the reviewed Drizzle config. `npm run db:import -- --dry-run` is the safe first inspection of legacy data; the write path requires `DATABASE_URL`, an existing Better Auth owner, and explicit owner assignment for ownerless records. `server/persistence/postgres-chat.ts`, `postgres-metadata.ts`, `postgres-operations.ts`, and `postgres-workspace.ts` plus the isolated repository E2Es prove the conversation, metadata, operational, workspace, and project-revision slices. `PostgresStateCoordinator` composes those repositories over one shared raw postgres-js client; it keeps a separate Drizzle client because Drizzle mutates date/JSON serializers during construction. `TaskStore` has an opt-in runtime path covered by `npm run e2e:postgres-taskstore`; the actual server cutover and owner-scope/read-boundary proof are covered by `npm run e2e:postgres-http`; authenticated cross-process SSE is covered by `npm run e2e:postgres-http-sse`; the real legacy import is covered by `npm run e2e:postgres-import`; local backup/restore and representative byte/hash recovery are covered by `npm run e2e:postgres-backup-restore` with the disposable mutation flag. `npm run db:ops -- migrate` is the checked-in release migration command used by the Fly deployment contract, and `npm run db:ops -- verify` checks the ten-migration ledger. `/api/health/live` is liveness and `/api/health/ready` is initialization/Postgres migration readiness. Remaining P4 gates are durable attachment metadata/cleanup round trips, full workflow transactionality/provider-side idempotency, production broker/secret/PITR/deployment operations, and sandbox isolation. A passing schema generator, import dry-run, or isolated repository proof is not sufficient to claim production readiness.
68+
The Postgres target contract lives in `server/db/schema.ts` and `server/db/migrations/`; run `npm run db:check` and regenerate only through the reviewed Drizzle config. `npm run db:import -- --dry-run` is the safe first inspection of legacy data; the write path requires `DATABASE_URL`, an existing Better Auth owner, and explicit owner assignment for ownerless records. `server/persistence/postgres-chat.ts`, `postgres-metadata.ts`, `postgres-operations.ts`, and `postgres-workspace.ts` plus the isolated repository E2Es prove the conversation, metadata, operational, workspace, and project-revision slices. `PostgresStateCoordinator` composes those repositories over one shared raw postgres-js client; it keeps a separate Drizzle client because Drizzle mutates date/JSON serializers during construction. `TaskStore` has an opt-in runtime path covered by `npm run e2e:postgres-taskstore`; the actual server cutover and owner-scope/read-boundary proof are covered by `npm run e2e:postgres-http`; authenticated cross-process SSE is covered by `npm run e2e:postgres-http-sse`; the real legacy import is covered by `npm run e2e:postgres-import`; local backup/restore and representative byte/hash recovery are covered by `npm run e2e:postgres-backup-restore` with the disposable mutation flag. `npm run db:ops -- migrate` is the checked-in release migration command used by the Fly deployment contract, and `npm run db:ops -- verify` checks the eleven-migration ledger. `/api/health/live` is liveness and `/api/health/ready` is initialization/Postgres migration readiness. Remaining P4 gates are atomic attachment metadata/task persistence, provider-side idempotency, lease heartbeat/renewal, production broker/secret/PITR/deployment operations, and sandbox isolation. A passing schema generator, import dry-run, or isolated repository proof is not sufficient to claim production readiness.
6969

7070
Run `npm run e2e:golden` for the local release flow: it starts its own temporary API/data root, proves real Claude/LiteLLM streaming, follow-up persistence, SSE suffix replay, API restart recovery, server-side search, and distinct task identity. The raw `LITELLM_MODEL` in the handover environment may not be a valid ONEVibe router alias; set an explicit compatible alias (currently `claude-sonnet-5` for the documented local route) and record that alias in evidence. The harness proves `executionBoundary=host_process` only; it must not be used to claim ONEComputer, microVM, OpenVTC, or production egress enforcement.
7171

@@ -91,7 +91,7 @@ Assistant-ui deliverable cards must be projections of durable artifact events wh
9191

9292
Follow-up attachments must pass through the `/api/tasks/:id/messages` ingestion boundary and be written under numbered `inputs/` paths before task metadata changes. Preserve per-file, per-turn, and per-conversation limits. Bind files to the exact turn through durable evidence; queued guidance owns its attachment paths and cancellation must remove those staged files. Keyed follow-ups must use the durable `follow_up_operation` journal and deterministic attachment paths so retries/restarts do not duplicate staged bytes or guidance. Never place bytes/base64 content in messages, events, logs, or assistant-ui metadata.
9393

94-
Run `npm run e2e:follow-up-attachment` against a running local API to prove a two-turn transcript, normalized workspace bytes, exact-turn evidence binding, concurrent duplicate follow-up acceptance, deterministic keyed attachment paths, and changed-payload `409` rejection. Run `npm run e2e:follow-up-recovery` to prove restart recovery after preparation and explicit no-replay handling for an operation whose provider outcome is unknown. The TaskStore unit boundary also proves stable client-request turn replay without duplicate messages or terminal-run reactivation. Clients may send `idempotencyKey` in the JSON body or the standard `Idempotency-Key` header; if both are present they must match. This is durable acceptance/replay protection, not a transaction across attachment/task persistence and provider execution. Do not claim crash-safe exactly-once execution until durable leases, stable provider request identity, unknown-outcome reconciliation, and a transactional attachment/task boundary exist.
94+
Run `npm run e2e:follow-up-attachment` against a running local API to prove a two-turn transcript, normalized workspace bytes, exact-turn evidence binding, concurrent duplicate follow-up acceptance, deterministic keyed attachment paths, and changed-payload `409` rejection. Run `npm run e2e:follow-up-recovery` to prove restart recovery after preparation, safe reclamation before provider start, and explicit no-replay/acknowledgment handling for an operation whose provider outcome is unknown. The TaskStore unit boundary also proves stable client-request turn replay without duplicate messages or terminal-run reactivation. Clients may send `idempotencyKey` in the JSON body or the standard `Idempotency-Key` header; if both are present they must match. This is durable acceptance/replay protection and correlation, not a transaction across attachment/task persistence or provider-side execution. Do not claim crash-safe exactly-once execution until provider-side idempotency, lease heartbeat/renewal, and a transactional attachment/task boundary exist.
9595

9696
For mobile work, verify the sidebar starts collapsed, opens with a backdrop and reachable in-panel close control, and leaves the main task in a nonzero grid column. A DOM-only assertion is insufficient when layout is involved; inspect a 390px browser screenshot and reset the viewport afterward.
9797

HANDOVER.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ONEVibe — Agent Handover Document
22

33
> **Date**: 2026-07-17
4-
> **Status**: Local phases 1–3 are implemented and the professional UI has crossed the Zustand and ordinary-collection TanStack Query boundaries. Governed MCP declarations, bounded MCP health probing, a tested opt-in MCP capability facade, truthful demo skill status, a GitHub-catalog skill marketplace with protected Claude/LiteLLM materialization evidence, feature-gated Better Auth, authenticated owner scoping, a local organization-membership scaffold, and a reviewed Drizzle/Postgres import proof (including organization/member staging) are present. The running server can opt into the owner-scoped Postgres TaskStore and matching Better Auth database; authenticated two-process HTTP SSE, separate liveness/readiness endpoints, graceful shutdown, representative backup/restore, a migration-first Fly.io deployment contract, browser evidence, a durable follow-up operation journal, and controlled crash recovery are now proven or statically validated locally. LiteLLM-only enforcement remains mandatory for every harness and every environment: data sovereignty, centralized routing, cost control, and model optimization are product requirements. TaskStore turn reservation now reuses replayed durable turns/message pairs across SQLite/Postgres and does not reactivate terminal turns; centralized private-path filtering keeps attachments/evidence out of public file lists, direct reads/edits, and portable exports. The follow-up journal resumes prepared operations after restart and marks claimed provider operations failed instead of silently replaying an unknown external outcome. Remaining P4 gaps are atomic attachment/task persistence, durable execution leases, provider request identity/unknown-outcome reconciliation, production broker/secret/PITR/deployment operations, cloud sandbox attestation, MCP secret brokering, and external MCP health/attestation. P7-01 token foundation and the pure P7-02 versioned schema/resolution boundary are now implemented with tests; tenant persistence/admin mutation remains dependency-gated.
4+
> **Status**: Local phases 1–3 are implemented and the professional UI has crossed the Zustand and ordinary-collection TanStack Query boundaries. Governed MCP declarations, bounded MCP health probing, a tested opt-in MCP capability facade, truthful demo skill status, a GitHub-catalog skill marketplace with protected Claude/LiteLLM materialization evidence, feature-gated Better Auth, authenticated owner scoping, a local organization-membership scaffold, and a reviewed Drizzle/Postgres import proof (including organization/member staging) are present. The running server can opt into the owner-scoped Postgres TaskStore and matching Better Auth database; authenticated two-process HTTP SSE, separate liveness/readiness endpoints, graceful shutdown, representative backup/restore, a migration-first Fly.io deployment contract, browser evidence, a durable follow-up operation journal, controlled crash recovery, durable execution leases, stable ONEVibe/provider correlation identities, and explicit provider-unknown acknowledgment are now proven or statically validated locally. LiteLLM-only enforcement remains mandatory for every harness and every environment: data sovereignty, centralized routing, cost control, and model optimization are product requirements. TaskStore turn reservation now reuses replayed durable turns/message pairs across SQLite/Postgres and does not reactivate terminal turns; centralized private-path filtering keeps attachments/evidence out of public file lists, direct reads/edits, and portable exports. The follow-up journal resumes prepared operations after restart, safely reclaims operations that had not reached the provider boundary, and fails closed when a provider request was durably marked started but its external outcome is unknown. Remaining P4 gaps are atomic attachment/task persistence, provider-side idempotency and lease heartbeat/renewal, production broker/secret/PITR/deployment operations, cloud sandbox attestation, MCP secret brokering, and external MCP health/attestation. P7-01 token foundation and the pure P7-02 versioned schema/resolution boundary are now implemented with tests; tenant persistence/admin mutation remains dependency-gated.
55
> **For**: The next agent (or human) picking this up cold.
66
> **Read this entire document before touching any code.**
77

TODO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Reference: `plan/03-runtime-routing.md`
6868
Reference: `plan/04-cloud-infrastructure.md`
6969

7070
- [ ] **P4-01** Add auth — feature-gated Better Auth + hashed email-OTP foundation, real delivery webhook, session middleware, login UI, expanded local cross-user route negative coverage, matching Postgres auth-handle wiring, and `npm run e2e:postgres-auth-http` authenticated Postgres owner-scope proof are implemented; keep open until production delivery, org-backed policy, and exhaustive authenticated Postgres route/deployment acceptance are complete
71-
- [ ] **P4-02** Migrate database — reviewed ten-migration Drizzle/PostgreSQL schema contract, owner-bound conversation/task-lineage/provider-message/MCP-history/legacy-provenance tables, isolated async chat, metadata, operational, workspace, project-revision, and durable follow-up-operation repositories, owner-required importer, organization/member staging, cross-owner relationship validation, optimistic-conflict/restart proofs, MCP audit retention, lease fencing, native-event projection proofs, transaction-backed fork history, HTTP driver/read-boundary evidence, authenticated two-process HTTP SSE suffix/replay evidence (`npm run e2e:postgres-http-sse`), an opt-in `TaskStore` runtime (`npm run e2e:postgres-taskstore`, `npm run e2e:postgres-http`), bounded follow-up idempotency/replay protection (`npm run e2e:follow-up-attachment`), crash-recovery failure-injection proof (`npm run e2e:follow-up-recovery`), TaskStore-level replay-safe turn reservation, and centralized private-path filtering for public files/direct reads/exports are now present; the real importer also round-trips workspace/project/native bytes and projection metadata; keep open until atomic attachment/task persistence, durable execution leases, provider request identity/unknown-outcome reconciliation, production broker/deployment tuning, and production migration/deployment controls are safe
71+
- [ ] **P4-02** Migrate database — reviewed eleven-migration Drizzle/PostgreSQL schema contract, owner-bound conversation/task-lineage/provider-message/MCP-history/legacy-provenance tables, isolated async chat, metadata, operational, workspace, project-revision, and durable follow-up-operation repositories, owner-required importer, organization/member staging, cross-owner relationship validation, optimistic-conflict/restart proofs, MCP audit retention, lease fencing, native-event projection proofs, transaction-backed fork history, HTTP driver/read-boundary evidence, authenticated two-process HTTP SSE suffix/replay evidence (`npm run e2e:postgres-http-sse`), an opt-in `TaskStore` runtime (`npm run e2e:postgres-taskstore`, `npm run e2e:postgres-http`), bounded follow-up idempotency/replay protection (`npm run e2e:follow-up-attachment`), crash-recovery failure-injection proof (`npm run e2e:follow-up-recovery`), TaskStore-level replay-safe turn reservation, durable follow-up leases/correlation IDs, explicit provider-unknown acknowledgment, and centralized private-path filtering for public files/direct reads/exports are now present; the real importer also round-trips workspace/project/native bytes and projection metadata; keep open until atomic attachment/task persistence, provider-side idempotency, lease heartbeat/renewal, production broker/deployment tuning, and production migration/deployment controls are safe
7272
- [ ] **P4-03** Containerise — current non-root multi-stage `Dockerfile`, hardened Compose image, explicit operator-controlled Postgres/auth environment contract, separate liveness/readiness health endpoints, graceful SIGTERM TaskStore shutdown, `.env.example`, reviewed migration/backup/restore/rollback runbook, Fly.io release contract with migration-first `release_command`, and GitHub Actions build/non-root/read-only/Postgres backup smoke gates are implemented; keep open until production secret delivery, managed deployment, PITR/retention, and rollout/rollback controls are exercised
7373

7474
P4-02 progress note: Postgres is now a controlled opt-in server driver with matching Better Auth handle wiring and authenticated owner-scope rejection. The proofs cover standalone messages, atomic native projections, transaction-backed fork history, workspace byte/version restore/compare/copy recovery, current project-file update/restart recovery, durable project revision restore, interrupted-task reconciliation, HTTP driver/read-boundary checks, authenticated two-process HTTP SSE suffix/replay, a real legacy import of workspace/project/native bytes plus projection metadata, bounded duplicate follow-up acceptance with deterministic keyed attachment paths, replay-safe TaskStore turn reservation on SQLite/Postgres, private attachment exclusion from public files/direct file reads/edits/portable export, and a durable follow-up operation journal with controlled crash recovery. A repeated client request now reuses the durable turn/message pair and does not reactivate a terminal turn; a crash after operation preparation resumes exactly one demo follow-up after restart, while an operation already claimed for provider execution is marked failed rather than automatically replayed. Remaining blockers are atomic attachment/task persistence, durable execution leases, provider request identity/unknown-outcome reconciliation, production broker/deployment tuning, and production migration/deployment controls.

0 commit comments

Comments
 (0)