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

20 KiB
Raw Blame History

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:

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:
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:

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:

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:

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:

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 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:
cd backend
npm run build
npx tsc --noEmit -p .
npx vitest run
  • Eseguire frontend:
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:
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:
./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:
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:
./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:
./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.