Files
ThothII/docs/plans/2026-08-10-rimozione-schema-v1-v2.md
T

448 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.