feat: add coding project schema v2 migration
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# 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: 9a31dacb2aad92a2deee0cec11fdb162a2916bfc
|
||||
- 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.
|
||||
Reference in New Issue
Block a user