# Piano di implementazione: workspace descriptor esclusivamente schema v3 > **Per gli agenti esecutori:** SUB-SKILL OBBLIGATORIA: usare `superpowers:subagent-driven-development` (raccomandata) oppure `superpowers:executing-plans`, procedendo task per task con TDD e review tra i task. **Obiettivo:** rimuovere dal prodotto ogni capacità di leggere, migrare, rendere operativo o presentare workspace descriptor schema v1/v2. Il solo descriptor accettato diventa schema v3. Restano intatti i formati versionati non correlati e gli state file del registry già prodotti da versioni recenti con revisioni v3. **Architettura:** parser, registry, renderer, diagnostica, route e frontend convergono su un solo tipo `WorkspaceV3`. Il campo pubblico `WorkspaceRevision.state` scompare. Un decoder privato normalizza in memoria gli state file già scritti con `state: "operational"`, elimina quel campo prima di qualsiasi uso/API e rifiuta ogni combinazione non-v3 o incoerente. I build backend diventano clean-first, così la cancellazione dei migratori sorgente implica anche la loro assenza da `dist` e dall'immagine core. **Tech stack:** TypeScript 5, Zod 4, Fastify 5, React 18, Vitest, Node.js 22, Bash/PowerShell, Git e Docker Compose. **Stato:** piano revisionato dopo review indipendente. La sua approvazione non autorizza l'implementazione; attendere un esplicito ordine separato. --- ## Decisioni confermate 1. Nessun workspace v1/v2 reale deve essere preservato o migrato. 2. Eliminare `migrate-legacy.ts`, `migrate-v2-qdrant.ts` e le relative interfacce CLI. 3. Eliminare il campo `state` dal tipo/API `WorkspaceRevision` e da tutti i nuovi state/manifest del registry. 4. Descriptor v1/v2 presenti in Git o negli snapshot vengono rifiutati, senza conversione automatica. 5. Non toccare i documenti storici sotto `docs/superpowers/` e i vecchi piani; possono descrivere decisioni passate. 6. Non iniziare P2 finché P1 non dispone di nuova evidenza automatica e di una nuova decisione manuale esplicita. ## Confini da non oltrepassare Questa rimozione riguarda soltanto il **workspace descriptor**. Non eliminare o rinominare: - `schemaVersion`/`schema_version` di bundle ZIP, report, job, ledger, manifest di sessione o artifact di fase; - `RevisionLeaseRecord.state` (`creating`/`persisted`), maintenance state, process state o UI state non collegati a `WorkspaceRevision`; - `migration_required` usato nei futuri piani P3–P6 per ownership DWH, punti semantici revisionless o altre migrazioni non-descriptor; - `allowLegacy` del frontend sessioni, che significa “sessione senza revisione workspace” e non descriptor v1/v2; - documenti storici o report conservati. L'unica compatibilità legacy mantenuta nel codice è il decoder privato degli state file già scritti con il campo revisionale `state: "operational"`. Non costituisce supporto a descriptor v1/v2. ## Contratto v3-only - `WorkspaceDescriptor`, `CanonicalWorkspace` e `WorkspaceV3` rappresentano la stessa forma v3; mantenere gli alias soltanto quando migliorano la semantica dei confini. - `parseWorkspaceYaml` e `validateWorkspaceDescriptor` accettano esclusivamente `workspace.schema_version === 3`. - v1/v2 generano l'errore pubblico già sanitizzato `workspace_invalid`; non usare più il messaggio o lo stato `migration_required` per i descriptor. - Un'attivazione Git contenente anche un solo descriptor non-v3 fallisce interamente e conserva il precedente active state. - Le revisioni restituite dalle API contengono esattamente `id`, `commit`, `blob`, `snapshotPath`, senza `state`. - Nuovi `active.json` e `snapshot.json` non contengono `state` nelle revisioni. ## Compatibilità degli state file esistenti Definire due decoder stretti e distinti: ```ts interface StoredWorkspaceRevision { id: string; commit: string; blob: string; snapshotPath: string; state?: "operational"; // solo input compatibile; mai restituito } interface WorkspaceRevision { id: string; commit: string; blob: string; snapshotPath: string; } ``` Regole: 1. `active.json` accetta soltanto `{head,revisions}`; `snapshot.json` soltanto `{head,revisions,files}`. 2. Ogni revision object accetta soltanto i quattro campi correnti più l'opzionale vecchio `state: "operational"`. 3. `state: "migration_required"`, qualsiasi altro valore o campo sconosciuto è rifiutato. 4. Il decoder ricostruisce un nuovo oggetto `WorkspaceRevision`; non restituisce mai l'oggetto JSON originale. 5. Active state e snapshot manifest vengono confrontati dopo la normalizzazione. 6. L'integrità continua a validare path, commit, blob, digest, descriptor v3 e Evidence context. 7. La lettura non modifica snapshot storici. La successiva attivazione riscrive `active.json` nel formato corrente; tutti i nuovi snapshot sono state-free. 8. Un vecchio file già privo di `state` è naturalmente il formato corrente, ma il relativo descriptor deve comunque essere v3. ## Mappa completa dei file ### Backend produttivo - `backend/src/workspaces/schema.ts` - `backend/src/workspaces/types.ts` - `backend/src/workspaces/runtime-renderer.ts` - `backend/src/workspaces/contracts.ts` - `backend/src/workspaces/diagnostics.ts` - `backend/src/workspaces/bindings.ts` - `backend/src/workspaces/registry.ts` - `backend/src/routes/workspaces.ts` - `backend/src/routes/sessions.ts` - `backend/src/routes/sql.ts` - Eliminare `backend/src/workspaces/migrate-legacy.ts` - Eliminare `backend/src/workspaces/migrate-v2-qdrant.ts` ### Build e tooling P1 - `backend/package.json` - Creare `backend/scripts/clean-dist.mjs` - Creare un test Node per il clean build - `backend/scripts/p1-manual-acceptance.mjs` - `backend/scripts/p1-manual-acceptance.test.mjs` - `backend/scripts/p1-render-snapshot.test.mjs` ### Frontend - `frontend/src/api/workspaces.ts` - `frontend/src/api/sessions.ts` - `frontend/src/shell/SteerInput.tsx` - `frontend/src/shell/WorkspaceManager.tsx` - Test/fixture in `api`, `SteerInput`, `WorkspaceManager`, `NewSessionDialog`, `WorkspacePublishDialog` e `drafts`. ### Deploy, fixture e verificatori - `scripts/workspace-registry-smoke.sh` - Creare `scripts/fixtures/workspace-registry-smoke.yaml` - `scripts/test-no-deployment-coupling-scope.sh` - `scripts/test-windows-clone-contract.ps1` - `scripts/verify-workspace-install-docs.sh` - `scripts/test-verify-workspace-install-docs.sh` ### Documentazione corrente - `README.md` - sezione corrente di `PROJECT_STATE.md`, prima di `## Historical snapshots` - `docs/workspace-diagnostic-protocol.md` - `docs/install/local-workspace-registry.md` - `docs/install/server-workspace-registry.md` --- ### Task 0: Congelare scope e baseline prima delle modifiche **File:** nessuna modifica produttiva. - [ ] Registrare `BASE_SHA=$(git rev-parse HEAD)` e verificare che gli altri piani non vengano inclusi nei commit di implementazione. - [ ] Salvare l'inventario iniziale dei simboli descriptor-legacy: ```bash git grep -nE 'WorkspaceV1|WorkspaceV2|LegacyWorkspace|migration_required|migrate-legacy|migrateWorkspaceV1ToV2|migrateWorkspaceV2ToV3' -- \ backend/src backend/test backend/scripts frontend/src scripts README.md PROJECT_STATE.md docs/install docs/workspace-diagnostic-protocol.md ``` - [ ] Classificare ogni risultato come descriptor legacy, compatibility decoder previsto, contratto diverso o documento storico. - [ ] Verificare nei registry/installazioni disponibili che i descriptor attivi siano v3; questa è una precondizione di deploy, non un migratore. - [ ] Non procedere se il worktree contiene modifiche applicative non attribuibili a questo piano. ### Task 1: Scrivere i test RED del contratto v3-only **File:** - `backend/test/workspaces-schema.test.ts` - `backend/test/workspace-registry.test.ts` - `backend/test/routes-workspaces.test.ts` - [ ] Aggiungere test che `parseWorkspaceYaml`, `validateWorkspaceDescriptor` e le route validate/publish rifiutino esplicitamente v1 e v2. - [ ] Aggiungere test registry per: - bootstrap pulito con solo v1/v2: fallimento, nessun `active.json` pubblicato; - repository misto v3+v2: attivazione atomica rifiutata; - pull che introduce v1/v2: precedente active state ancora leggibile; - retained snapshot contenente descriptor non-v3: rifiuto fail-closed; - risposta API state-free. - [ ] Eseguire: ```bash cd backend npx vitest run test/workspaces-schema.test.ts test/workspace-registry.test.ts test/routes-workspaces.test.ts ``` Atteso: RED per i nuovi requisiti, non errori di fixture casuali. ### Task 2: Rendere lo schema backend esclusivamente v3 **File:** - `backend/src/workspaces/schema.ts` - `backend/src/workspaces/types.ts` - test del Task 1 - [ ] Eliminare `WorkspaceV1`, `WorkspaceV2`, `LegacyWorkspace`, relativi Zod schema e `migrateWorkspaceV1ToV2`. - [ ] Rendere `WorkspaceDescriptorSchema = WorkspaceV3Schema`. - [ ] Eliminare `validateCanonicalWorkspace`, aggiornando **tutti** i chiamanti in `routes/workspaces.ts`, incluso il chiamante attualmente oltre quelli elencati nel vecchio piano. - [ ] Eliminare `isCanonicalWorkspace`/`isOperationalWorkspace` dopo aver sostituito i rami condizionali con validazione v3 diretta. - [ ] Conservare test negativi v1/v2; non cancellare le sole prove che impediscono una regressione futura. - [ ] Eseguire test focalizzati e typecheck. - [ ] Commit: `refactor: make workspace descriptors schema v3 only`. ### Task 3: Normalizzare in sicurezza active state e snapshot manifest **File:** - `backend/src/workspaces/registry.ts` - `backend/test/workspace-registry.test.ts` - [ ] Scrivere RED per state/manifest con: - campo assente; - vecchio `state: "operational"`; - `state: "migration_required"`; - valore sconosciuto; - campo extra; - active state e manifest con formati misti; - snapshot attivo, storico e fallback offline. - [ ] Rimuovere `state` da `WorkspaceRevision` e da tutti i nuovi writer. - [ ] Sostituire cast e vecchie migrazioni con decoder stretti che restituiscono oggetti normalizzati state-free. - [ ] Rimuovere `LegacyWorkspaceRevision`, `LegacyActiveState`, `LegacySnapshotManifest`, `deriveStateFromLegacyRevisions`, `migrateLegacyActiveState`, `migrateLegacySnapshotManifest`, `sameLegacyRevisions` e le condizioni operative basate su `state`. - [ ] Mantenere tutti i controlli di integrità e far validare ogni YAML come v3. - [ ] Provare che list/read/API non riemettono il vecchio campo anche immediatamente dopo un restart, prima di una nuova attivazione. - [ ] Commit: `refactor: remove workspace revision state`. ### Task 4: Eliminare i rami v1/v2 da renderer, contracts, bindings e diagnostica **File:** - `backend/src/workspaces/runtime-renderer.ts` - `backend/src/workspaces/contracts.ts` - `backend/src/workspaces/diagnostics.ts` - `backend/src/workspaces/bindings.ts` - relativi test - [ ] Scrivere/aggiornare test RED che accettano v3 e rifiutano input non-v3 al confine, senza renderer/diagnoser legacy. - [ ] Eliminare il renderer v2/pgvector e i rami v1. - [ ] Eliminare variabili contract e diagnostica solamente v2. - [ ] Semplificare bindings dopo la validazione v3, senza indebolire validazione secrets/trasporti. - [ ] Eseguire i test focalizzati: ```bash cd backend npx vitest run \ test/workspace-runtime-renderer.test.ts \ test/workspaces-contracts.test.ts \ test/workspaces-diagnostics.test.ts \ test/workspaces-bindings.test.ts \ test/workspace-runtime-handoff.test.ts ``` - [ ] Commit: `refactor: remove legacy workspace runtime branches`. ### Task 5: Rimuovere migratori senza perdere test di deployment non correlati **File:** - Eliminare i due migratori e i test esclusivamente di migrazione. - Creare/spostare in un test dedicato le prove deployment presenti in `workspaces-migrate-legacy.test.ts:81-114`. - [ ] Prima di eliminare `workspaces-migrate-legacy.test.ts`, spostare in un file con nome coerente: - volume registry durevole e mount Git read-only; - contratto Dockerfile; - fallback offline smoke; - self-test di cleanup dell'immagine per-run. - [ ] Eliminare `migrate-legacy.ts`, `migrate-v2-qdrant.ts` e i test di trasformazione. - [ ] Conservare un fixture v2 soltanto nei test negativi di rifiuto. - [ ] Eseguire i nuovi test deployment e il typecheck. - [ ] Commit: `refactor: remove workspace migration utilities`. ### Task 6: Aggiornare tutte le route backend e il tooling P1 **File:** - `backend/src/routes/workspaces.ts` - `backend/src/routes/sessions.ts` - `backend/src/routes/sql.ts` - test route inclusi `routes-sql-meta.test.ts` - `backend/scripts/p1-manual-acceptance.mjs` - test manual/render P1 - [ ] Rimuovere filtri/gate `revision.state` da tutte le route. La garanzia deriva dal registry v3-only. - [ ] Aggiornare mock/fixture `WorkspaceRevision` in tutti i test backend. - [ ] Aggiornare il validatore del manifest P1 manuale affinché richieda esattamente la revisione state-free. - [ ] Aggiornare i fixture `p1-manual-acceptance.test.mjs` e `p1-render-snapshot.test.mjs`. - [ ] Aggiungere un test JS specifico che rifiuti manifest con revisioni malformate senza reintrodurre `migration_required`. - [ ] Eseguire: ```bash cd backend npx vitest run test/routes-workspaces.test.ts test/routes-sessions.test.ts test/routes-sql-meta.test.ts cd .. node --test --test-concurrency=1 \ backend/scripts/p1-manual-acceptance.test.mjs \ backend/scripts/p1-render-snapshot.test.mjs ``` - [ ] Commit: `refactor: remove workspace revision state consumers`. ### Task 7: Rendere il build backend clean-first **File:** - `backend/package.json` - Creare `backend/scripts/clean-dist.mjs` - Creare test Node del clean build - [ ] Scrivere RED: creare un file sentinella in `backend/dist/workspaces/`, eseguire il clean/build e verificare che non sopravviva. - [ ] Implementare la pulizia con API Node multipiattaforma, non con `rm -rf` nella npm script. - [ ] Fare eseguire il clean prima di `tsc` da `npm run build`. - [ ] Verificare dopo il build: ```bash test ! -e backend/dist/workspaces/migrate-legacy.js test ! -e backend/dist/workspaces/migrate-v2-qdrant.js ``` - [ ] Costruire l'immagine core in un contesto pulito e verificare che i due moduli non esistano nell'immagine. - [ ] Verificare che i manifest di integrità P1 continuino a legare l'intero nuovo `dist`. - [ ] Commit: `build: remove stale backend distribution files`. ### Task 8: Aggiornare frontend e contratto API state-free **File:** - `frontend/src/api/workspaces.ts` - `frontend/src/api/sessions.ts` - `frontend/src/shell/SteerInput.tsx` - `frontend/src/shell/WorkspaceManager.tsx` - test/fixture frontend correlati - [ ] Scrivere/aggiornare test per revisioni senza `state` e risposta non-v3 rifiutata al confine workspace. - [ ] Eliminare `state` dal tipo e dal parser revisionale. - [ ] Rimuovere gate/banner/filtro `migration_required` e anche la visualizzazione `record.revision.state`. - [ ] Mantenere `allowLegacy` per sessioni senza revisione. - [ ] Aggiornare fixture in: - `api/workspaces.test.ts`, `api/sessions.test.ts`; - `SteerInput.test.tsx`, `WorkspaceManager.test.tsx`; - `NewSessionDialog.test.tsx`, `WorkspacePublishDialog.test.tsx`; - `drafts.test.ts`, mantenendo il test negativo di schema non-3. - [ ] Documentare che core e frontend devono essere aggiornati insieme; il parser nuovo non usa più `state`. - [ ] Eseguire typecheck e suite frontend. - [ ] Commit: `refactor: remove legacy workspace UI state`. ### Task 9: Sostituire fixture e smoke con descriptor v3 completi **File:** - `scripts/workspace-registry-smoke.sh` - Creare `scripts/fixtures/workspace-registry-smoke.yaml` - `scripts/test-no-deployment-coupling-scope.sh` - `scripts/test-windows-clone-contract.ps1` - test deployment spostati nel Task 5 - [ ] Creare un descriptor v3 completo `id: local`, collection `local`, embedding interno 1024/cosine, LLM policy e diagnostica DWH; omettere Evidence per non richiedere un tree Git nello smoke registry. - [ ] Validare il fixture con il parser produttivo in un test backend. - [ ] Copiare il fixture nello seed repository e rimuovere sia l'invocazione del migratore sia il build backend ormai inutile allo smoke. - [ ] Nel test Windows non cambiare soltanto il numero di versione: fornire il contratto v3 completo mantenendo lo scopo path-with-spaces/clone. - [ ] Aggiornare il fixture dello scope coupling senza indebolire l'assenza-gate. - [ ] Eseguire test shell focalizzati e, con Docker disponibile, lo smoke reale senza retry. - [ ] Commit: `test: replace legacy workspace deployment fixtures`. ### Task 10: Aggiornare documentazione corrente e relativi verifier **File:** - documenti/verifier indicati nella mappa - [ ] Aggiornare README e soltanto la sezione corrente di `PROJECT_STATE.md`; non riscrivere gli snapshot storici. - [ ] Eliminare procedure di migrazione v1/v2 dai manuali local/server e dal protocollo diagnostico. - [ ] Modificare `verify-workspace-install-docs.sh` perché richieda “schema v3 only” e l'assenza di `migration_required` nella documentazione corrente. - [ ] Aggiornare i fixture negativi del test del verifier. - [ ] Non cambiare gli usi di `migration_required` nei piani P3–P6 relativi a ownership/artifact diversi. - [ ] Eseguire: ```bash bash scripts/test-verify-workspace-install-docs.sh bash scripts/verify-workspace-install-docs.sh --fixtures-only ``` - [ ] Commit: `docs: make schema v3 the only workspace contract`. ### Task 11: Eseguire absence gate e suite complete - [ ] Eseguire backend clean build, typecheck e test: ```bash cd backend npm run build npx tsc --noEmit -p . npx vitest run ``` - [ ] Eseguire frontend: ```bash cd frontend npx tsc -b npx vitest run npm run build ``` - [ ] Eseguire script/verifier interessati, incluso lo smoke Docker obbligatorio se l'ambiente dispone di Docker. Non lasciarlo “opzionale” in una consegna che modifica lo smoke. - [ ] Eseguire `git diff --check`. - [ ] Eseguire l'absence gate ristretto: ```bash git grep -nE 'WorkspaceV1|WorkspaceV2|LegacyWorkspace|migrateWorkspaceV1ToV2|migrateWorkspaceV2ToV3' -- \ backend/src frontend/src scripts && exit 1 || true git grep -nE 'migration_required|migrate-legacy|migrate-v2-qdrant' -- \ backend/src backend/scripts frontend/src scripts README.md docs/install docs/workspace-diagnostic-protocol.md && exit 1 || true test ! -e backend/dist/workspaces/migrate-legacy.js test ! -e backend/dist/workspaces/migrate-v2-qdrant.js ``` Nota: trasformare questi esempi in uno script con allowlist esplicita; non affidarsi a `&& exit 1 || true`, che può mascherare errori di esecuzione. Lo script deve distinguere “nessun match” da errore Git/I/O. - [ ] Ispezionare il diff per assicurarsi che nessun formato non-descriptor sia stato modificato. ### Task 12: Rigenerare l'evidenza automatica P1 - [ ] Partire dal commit sorgente finale pulito. - [ ] Eseguire una sola integrazione completa, senza retry automatico: ```bash ./scripts/p1-acceptance.sh integration --keep ``` - [ ] Verificare report JSON/Markdown, hash dichiarati, manifest sorgente/dist, secret scan, ownership cleanup e porte chiuse. - [ ] Aggiornare `PROJECT_STATE.md` con il nuovo commit/tree/report e con stati distinti: ```text automated integration: PASS manual acceptance: PENDING ``` - [ ] Committare soltanto lo stato tracciato, mai `.artifacts`. - [ ] Non riusare l'evidenza precedente legata a `c733896`. ### Task 13: Riaprire e chiudere il gate manuale P1 - [ ] Preparare un ambiente manuale nuovo: ```bash ./scripts/p1-manual-acceptance.sh prepare ./scripts/p1-manual-acceptance.sh serve ``` - [ ] Il reviewer segue integralmente il nuovo `GUIDE.md`, verificando anche che revisioni/API/manifest siano state-free e che v1/v2 siano rifiutati senza mutazione. - [ ] Arrestare il server e verificare porte/processi: ```bash ./scripts/p1-manual-acceptance.sh stop ``` - [ ] Solo il reviewer crea `VERDICT.md` e decide PASS/FAIL. - [ ] Se PASS, aggiornare `PROJECT_STATE.md` e committare `docs: record schema-v3-only P1 acceptance`. - [ ] Pulire il lab soltanto dopo conferma del reviewer. - [ ] **STOP:** non iniziare P2 finché il reviewer non approva esplicitamente il nuovo P1. --- ## Criteri finali di accettazione 1. Nessun descriptor v1/v2 viene parsato, pubblicato, attivato, renderizzato, diagnosticato o mostrato. 2. I vecchi state file di revisioni v3 con `state: "operational"` continuano a caricarsi, ma API e nuovi file sono state-free. 3. Descriptor non-v3 o state incoerenti falliscono senza sostituire il precedente active state. 4. Nessun migratore sopravvive in sorgenti, `dist`, immagine core, script o documentazione corrente. 5. I formati versionati non collegati ai workspace descriptor sono invariati. 6. Backend, frontend, verifier, smoke e build interessati sono verdi. 7. Una nuova integrazione P1 è PASS al commit finale. 8. La nuova acceptance manuale P1 è decisa esplicitamente dal reviewer. 9. P2 resta non iniziato fino a ulteriore autorizzazione.