Files
makelore/.project-docs/30-worklog/tasks/20260822-pi-schema-v2-5e4b7a91.md

9.6 KiB

Task: Implement PI-020 project and conversation schema v2

Identity

  • Task ID: 20260822-pi-schema-v2-5e4b7a91
  • Mode: Feature
  • Branch: codex/20260822-pi-schema-v2-5e4b7a91-pi-schema-v2
  • Worktree: D:\Datas\OthersProjects\makelore-pi-schema-v2-5e4b7a91
  • Base commit: 9a31dacb2a
  • Owner: codex
  • Status: Completed

Scope

  • Implement PI-020 — Project and Conversation schema v2 migration from the merged Pi hard-cutover Spec/ticket graph.
  • Add vendor-neutral project configuration, project registry, Conversation metadata store, atomic JSON persistence, and one-time OpenCode cutover migration under electron/coding-projects.
  • Preserve stable Agent metadata while mapping legacy string models only through an injected unique resolver; unresolved/no-account models remain explicit user-selection requirements.
  • Back up schema v1 metadata before replacement, initialize empty schema v2 Conversations, expose a persistent one-time notice state, and clean only proven generated .opencode/agent files while moving uncertain content to the migration backup.
  • Add focused table, rollback, path-validation, single-flight, local-only creation, and performance tests without wiring the new stores into Renderer, Host routes, Provider Service, or Pi workers yet.

Intent And Constraints

  • Keep project/Agent/Conversation identity product-owned. Conversation IDs are Makelore UUIDs; Pi session IDs and opaque session keys remain optional Main-private binding fields.
  • Reuse the vendor-neutral ProductModelRef and thinking-level contract from PI-010. Do not duplicate Pi/OpenCode provider identifiers in persisted schema v2.
  • A legacy model string maps automatically only when the injected resolver returns one unique account/model reference. Missing, ambiguous, or unavailable account mappings persist { model: null, modelResolution: "required" }; no default model fallback is allowed.
  • Treat migration as one explicit v1→v2 branch, not a generic framework: create a timestamped backup first, use atomic per-file replacement, and restore original metadata/Agent files if any later migration operation fails.
  • Never recursively delete userData/opencode or arbitrary project .opencode content. Only exact current generated Agent materializations may be deleted; modified or unknown Agent files move to backup, and other .opencode paths remain untouched and unread by new code.
  • Project, partner, and empty Conversation creation are local metadata operations and must not import or call child-process/runtime code. Per-Conversation Pi binding creation exposes a single-flight contract but does not start Pi in this ticket.
  • Preserve the explicit real-Provider Accepted Risk and deferred macOS decisions; neither affects this local metadata ticket or becomes a Pass here.

Project Context Loaded

  • maintain-project-docs created and verified isolated feature ownership at base 9a31dacb2aad92a2deee0cec11fdb162a2916bfc; Concurrent Task Gate and Planning Gate passed.
  • The planner audited PI-030 as Done in commit fc7b80793c0a8b0a39d8eef31b57ee42895dd9fd, recomputed the unchanged 18-node/31-edge DAG, and identified PI-020 as the unique Ready Frontier ticket from implementation base 9a31dac.
  • The planner status commit remains read-only on its own branch because the repository Integration Gate is currently held by blocked task 20260821-integrate-model-switch-fix-8f2d6c41; this does not block isolated PI-020 feature work.
  • Repository guidance, shared project memory, PI Spec sections 5/6/15/17/19/20, the PI-020 ticket, PI-010 contracts, existing v1 project/conversation modules, tests, and all planning peer task records were inspected before planning.
  • Existing v1 ownership is split between shared/project-config.ts, shared/project-conversations.ts, and electron/opencode/*; those remain the old product path until later cutover tickets. PI-020 introduces the new electron/coding-projects boundary rather than incidentally rewriting current OpenCode routes.
  • Other planning peers do not declare writes to the PI-020 files. 20260820-partner-create-model-parity-c83d has an undefined scope and is retained as an unknown coordination warning; no confirmed contradictory decision or file ownership was found.
  • codebase-design keeps persistence/migration details behind small store interfaces. The repository prohibition on subagents is honored; no parallel agent was created.

Plan

  1. Implement schema v2 types/normalizers and atomic JSON persistence, reusing PI-010 product model contracts without runtime imports beyond types.
  2. Implement local project registry/config/Agent creation and Conversation CRUD with UUID identity, opaque session-key validation, serialized writes, and per-Conversation binding single-flight.
  3. Implement the explicit v1 cutover: complete backup, injected unique model resolution, v2 atomic writes, one-time notice, generated/modified Agent classification, and rollback on failure.
  4. Add migration-table, atomic-failure/retry, Agent-file, path, single-flight, no-spawn, and local performance tests.
  5. Run focused tests, typecheck, lint, full tests, build when warranted, documentation gates, commit, and planner handoff.

Outcome

  • Added the vendor-neutral electron/coding-projects boundary with atomic JSON replacement, strict project schema v2, product-owned project registry, and Conversation schema v2. Agent and Conversation model state uses the PI-010 ProductModelRef; unresolved/no-account state is persisted as model: null plus modelResolution: "required" with no default fallback.
  • Added local-only project, Agent, and unbound Conversation creation. Project path upserts and Conversation writes are serialized; concurrent first prompts share one per-Conversation binding flight and persist one validated Pi session ID/opaque session key pair.
  • Added explicit v1→v2 migration with timestamped .niancode/migration-backups/opencode-cutover-* backup, injected unique legacy-model resolution, empty v2 Conversation initialization, and persistent pending→acknowledged legacy notice state.
  • Migration preserves stable Agent ID/name/prompt/skills/archive. Exact cleanup proof uses the old runtime's normalized buildProjectAgentManifest output; locally modified or unknown .opencode/agent files are copied into the migration backup before being removed, while unrelated .opencode content remains untouched.
  • A missing backup aborts before either v2 write. A failure after writes begin restores project metadata, Conversation metadata, and Agent file contents so the original v1 project remains retryable; a retry matrix test completes successfully after a deliberately corrupt Conversation write.
  • The real Provider gate remains explicitly waived: real protocol/account compatibility, Provider concurrency, credential isolation, and Provider-specific behavior are Accepted Risk and remain unverified, not Pass. No real Provider or macOS validation was performed in this ticket.

Verification

  • pnpm install --frozen-lockfile: passed with repository-pinned pnpm 10.33.4.
  • Focused schema/migration suite: 2 files, 15 tests passed. Coverage includes unique/unresolved/no-account mapping, stable Agent fields, modified/unknown generated files, no-backup refusal, corrupt write rollback/retry, empty v2 Conversations, one-time notice consumption, traversal/absolute session-key rejection, per-Conversation single-flight, atomic replacement/temp cleanup, local metadata performance budgets, and spawn spy = 0.
  • pnpm run typecheck: passed.
  • Scoped ESLint over electron/coding-projects and both focused tests: passed with no findings.
  • pnpm run lint:check: passed with 0 errors and 6 pre-existing warnings outside this task's files.
  • pnpm test: 184 files, 2133 tests passed.
  • pnpm run build:vite: passed for Renderer, Main, Preload, and release utility output; existing dynamic-import and chunk-size warnings remain unchanged.
  • git diff --check: passed.

Follow-ups

  • PI-040 may consume project/Agent ProductModelRef data after integration; it owns Provider catalog, credential projection, and managed prompt/skill resources. The accepted real-Provider risks must remain labeled unverified rather than being inferred from these local metadata tests.
  • PI-050 may connect ensureSessionBinding to the Pi worker pool/session registry. Its runtime integration must retain the store's single-flight semantics and keep the opaque key relative/private.
  • PI-100 may expose project/Agent/Conversation create routes. These routes must stay local-only until a prompt explicitly requests runtime preparation.
  • PI-140 owns final cutover wiring and old OpenCode removal. It should consume the one-time legacy notice and must not broaden cleanup beyond the conservative migration behavior delivered here.

Promotion Candidates

  • Target: Pi cutover migration implementation guidance in the architecture/planner task. Proposal: preserve v1 Agent prompt and selected skill IDs from raw project metadata, but classify deletable generated Agent files only against the old runtime's normalized manifest; any mismatch remains uncertain and is moved into the migration backup. Evidence: the focused migration matrix preserves a retired legacy skill ID and prompt whitespace while deleting two exact generated files, backing up one modified generated file plus one unknown file, and leaving unrelated .opencode/skills content intact. Future impact: PI-140 can remove old runtime code without reimplementing or widening the data-cleanup boundary. Semantic conflicts: none; this is the conservative implementation of PI-020 Required work 6 and Acceptance data-preservation rules. Human confirmation required: no.