# Task: Implement ML-01 project identity contract ## Identity - Task ID: 20260826-ml01-project-identity-4d8a7c21 - Mode: Feature - Branch: codex/20260826-ml01-project-identity-4d8a7c21-ml01-project-identity - Worktree: D:\Datas\OthersProjects\makelore-ml01-project-identity-4d8a7c21 - Base commit: 7e54b8fbda1899b73334d7c3e732ce8e73460ed8 - Owner: ml01-project-identity - Status: Ready for integration ## Scope - Implement ML-01 durable project identity core from the accepted MakeLore Data Service P0 specification, sections 5.1 and 8.1/8.3-8.5, on the exact base `7e54b8fbda1899b73334d7c3e732ce8e73460ed8`. - Own only the ticket paths: shared project contracts; project config, project service, migration, coding-project Host routes and composition identity callback wiring; Pi release-proof create fixtures; and identity focused/direct create-project tests required by the new request contract. - Deliver optional canonical `projectId` persistence, required create/bind creation identity, one-time legacy resolution, immutable ordinary saves, confirmed independent-copy identity rotation, one centralized active-real- project-with-identity helper, and atomic preview/resource invalidation. ## Intent And Constraints - Work in the isolated ticket worktree and branch owned by this task. Do not modify the occupied root `main` worktree or absorb changes from other tasks. - Preserve local `CodingProjectSummary.id`, normalized-path reuse/index behavior, Pi local project/session identifiers, and the `opencode-projects` electron-store compatibility name. None may become the durable cloud ID. - Do not add Data Service cloud/Host calls, Firebase compatibility, published runtime support, generic operation multiplexing, or a filesystem-copy engine. - New creation must require an explicit `{kind: "create"|"bind"}` identity; Main generates `crypto.randomUUID()` for create and validates canonical lowercase hyphenated UUIDs for bind. Legacy config opening/migration must remain identity-free until a dedicated identity operation. - Ordinary config saves preserve an existing identity and reject changes or clear attempts; only the identity-resolution or confirmed independent-copy operation may write it. Preview invalidation runs before the atomic metadata write and callback failure must leave config unchanged. - The centralized active-real-project helper must validate indexed active project, resolved/stat'ed directory, `.niancode/project.json`, durable ID, and trusted-context path equality without accepting model/tool owner or ID. ## Planning Gate - Result: Passed on 2026-08-26 after Concurrent Task Gate isolation. - Task identity, exact base, branch, worktree, and owner match the local `task_context.py status --json` record. - Loaded MakeLore AGENTS, required project-memory entry documents, accepted architecture/domain/decision/evidence/commitment material, the cross-repo Data Service spec sections 5.1 and 8.1/8.3-8.5, and the ML-01 ticket plan. - Active peer review found the parent client coordinator task with the same overall program but no semantic conflict; other planning records were either placeholder/unknown or unrelated. The root integration record is completed; root remains out of scope per the user handoff. - Project positioning is still a template placeholder and therefore stale context, not a source of product behavior; the accepted spec and contract are the authoritative task inputs. ## Implementation Plan 1. Inspect the exact-base project identity/config/migration/service/route, composition, Pi release-proof, and affected test seams; map all direct create callers before editing. 2. Add contract/config normalization and migration-preserving optional identity, then enforce required create identity and atomic creation semantics. 3. Add immutable save and one-time identity-resolution/independent-copy operations, centralized active-real-project helper, route wiring, callback invalidation, and release-proof/test fixtures. 4. Run focused identity tests plus typecheck and relevant lint/build checks; inspect the diff for ownership boundaries and task-specific regressions. 5. Update this record with actual outcome/verification, run doc drift and complete the task context, then commit one implementation commit. ## Outcome - Implemented ML-01 in the isolated client worktree. V2 project metadata now optionally persists a canonical lowercase hyphenated UUID without silently backfilling legacy projects; Main-owned creation requires an explicit create/bind choice and validates/generates the durable ID before any project directory/config write. Ordinary saves preserve identity immutability. - Added one-time legacy resolution and confirmed independent-copy operations, exact Host routes, callback-before-atomic-write sequencing, resource refresh hooks, centralized active-real-project-with-identity validation, and the affected Pi release-proof/direct create fixtures. - Preserved local summary/store IDs, migration omission, normalized-path behavior, local Pi identifiers, and the existing project-store compatibility name. No cloud/data-service calls or filesystem-copy engine were added. ## Verification - `tsc --noEmit` passed with the bundled Node/TypeScript runtime. - Focused Vitest passed: `coding-project-identity.test.ts` (8 tests), `coding-projects-migration.test.ts` (8 tests), `coding-core-routes.test.ts` (28 tests), and `coding-projects-schema-v2.test.ts` (4 tests); 48 tests total. - Focused ESLint passed for all modified implementation and test files. - `git diff --check` passed. - The initial dependency install attempted to add an approval note to `pnpm-workspace.yaml`; it was removed immediately and is not part of this task's diff. ## Follow-ups - ML-02 must project the required identity choice into the Renderer create and legacy/independent-copy UX. ML-03 must use `requireActiveRealProjectWithIdentity()` for all Data Service callers. - Parent merger should integrate this commit after confirming the exact post-ML-00 base and rerun the repository-wide client gates. ## Promotion Candidates - None: this ticket implements the accepted identity contract without a new project-memory decision or canonical-document change.