chore: commit remaining worktree changes

This commit is contained in:
2026-08-26 08:10:37 +02:00
parent ec061c42d4
commit f48196a57f
234 changed files with 146 additions and 61044 deletions
@@ -1,19 +0,0 @@
# Button Press Feedback Design
## Context
Buttons currently change on hover, but many provide little or no visible acknowledgment while the pointer is pressed. The interface mixes a shared Base UI button with native buttons, so changing only the shared component would leave inconsistent behavior.
## Chosen interaction
Apply one CSS press vocabulary to every enabled native button. During `:active`, the button compresses to `scale(0.97)`, loses raised shadow, and receives a restrained brightness change. The transition lasts 140 ms and uses an ease-out-quint curve (`cubic-bezier(0.22, 1, 0.36, 1)`). This reads as a physical press without bounce, ripple, layout movement, or JavaScript state.
The existing one-pixel translation on the shared button is removed so shared and native buttons do not combine two motion patterns.
## Accessibility
Under `prefers-reduced-motion: reduce`, scale is disabled. The brightness and shadow change remain, providing a clear pressed state without kinetic motion. Disabled buttons receive no press treatment.
## Verification
A focused contract test checks the global enabled-button selector, scale, timing, easing, and reduced-motion override. The full frontend suite and typecheck guard regressions. Playwright then holds a real button in the active state and confirms its computed transform, followed by a visual screenshot/snapshot check.
@@ -1,72 +0,0 @@
# Button Press Feedback Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Give every enabled button immediate, consistent click acknowledgment while preserving a non-kinetic reduced-motion alternative.
**Architecture:** Define the interaction once in the global Tailwind base layer so both Base UI and native buttons inherit it. Remove the shared button's older translation-only active state to avoid compounded transforms. Verify the CSS contract first, then exercise the real interaction in Playwright.
**Tech Stack:** React 18, Tailwind CSS 3, Vitest, Playwright CLI.
---
### Task 1: Specify the global press contract
**Files:**
- Create: `frontend/src/button-press-feedback.test.ts`
- Test: `frontend/src/button-press-feedback.test.ts`
**Step 1: Write the failing test**
Read `src/index.css` and assert the enabled-button active selector, `scale(0.97)`, 140 ms duration, ease-out-quint curve, disabled exclusion, and reduced-motion transform override. Assert that `components/ui/button.tsx` no longer contains the legacy translation active class.
**Step 2: Run test to verify it fails**
Run: `npx vitest run src/button-press-feedback.test.ts`
Expected: FAIL because the global press rules do not exist and the shared button still uses translation.
### Task 2: Implement the press feedback
**Files:**
- Modify: `frontend/src/index.css`
- Modify: `frontend/src/components/ui/button.tsx`
- Test: `frontend/src/button-press-feedback.test.ts`
**Step 1: Add the minimal CSS**
Add a global enabled-button transition and active state using only transform, filter, and shadow. Add a `prefers-reduced-motion` override that removes scale while preserving non-kinetic contrast feedback.
**Step 2: Remove the legacy shared-button translation**
Delete `active:not-aria-[haspopup]:translate-y-px` from the shared variant base string.
**Step 3: Run the focused test**
Run: `npx vitest run src/button-press-feedback.test.ts`
Expected: PASS.
### Task 3: Verify regressions and real-browser behavior
**Files:**
- Verify: `frontend/src/index.css`
- Verify: `frontend/src/components/ui/button.tsx`
**Step 1: Run frontend verification**
Run: `npx vitest run`
Run: `npx tsc -b`
Expected: all tests pass and typecheck exits 0.
**Step 2: Verify in Playwright**
Open `http://localhost:5173`, hold pointer-down on an enabled button, and inspect its computed transform and filter before release. Repeat with reduced motion emulation and confirm transform remains `none` while contrast feedback remains.
**Step 3: Review the final diff**
Run: `git diff --check` and inspect `git diff --stat`.
Expected: no whitespace errors and only the intended product/design, CSS, component, and test files changed.
@@ -1,773 +0,0 @@
# Internal Qdrant and Ollama Implementation Plan
> **Historical nomenclature:** this plan predates the native host CLI convergence. The current
> operator command is `tht`; any older `thothctl` smoke-script or rollback wording below is retained
> only as historical evidence.
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Make Qdrant and Ollama mandatory internal ThothII services while keeping the analytical
DWH external and associating each workspace with one Qdrant collection for schema, Evidence, and
Memory embeddings.
**Architecture:** Introduce workspace schema v3, preserve v1/v2 only as migration inputs, and keep
the existing harness `VectorStore` port behind a new Qdrant REST adapter. Base Compose owns Qdrant,
Ollama, their persistent volumes, and model initialization; workspace descriptors contain semantic
identity but no vector/embedding endpoints or credentials.
**Tech Stack:** TypeScript/Fastify/Zod, Python 3.12/Pydantic/requests, React 18, Docker Compose,
Qdrant REST API, Ollama `/api/embed`, Vitest, pytest.
---
## Guardrails
- Apply `@superpowers:test-driven-development` to every behavior change: add one focused failing
test, observe the expected failure, implement the minimum, and rerun the focused test.
- Do not run broad suites until the corresponding code/config changes exist; this preserves the
requested ordering while still using TDD.
- Preserve the external DWH connector contract and session persistence model.
- Do not retain an operational fallback to pgvector or an external embedding endpoint.
- Do not delete or rewrite user workspace repositories or Qdrant data. Migration is descriptor-only;
semantic data is rebuilt explicitly.
- Commit after each task only when focused tests are green.
### Task 1: Define workspace schema v3
**Files:**
- Modify: `backend/src/workspaces/schema.ts`
- Modify: `backend/src/workspaces/types.ts`
- Modify: `backend/test/workspaces-schema.test.ts`
- Modify: `backend/test/workspaces-migrate-legacy.test.ts`
- Create: `backend/src/workspaces/migrate-v2-qdrant.ts`
- Create: `backend/test/workspaces-migrate-v2-qdrant.test.ts`
**Step 1: Write the failing schema tests**
Add tests proving that schema v3 accepts only this semantic shape:
```ts
const semantic_index = {
vector_store: {
engine: "qdrant",
collection: "psd-clinical",
dimensions: 1024,
distance: "cosine",
},
embedding: {
provider: "ollama_internal",
model: "qwen3-embedding:0.6b",
dimensions: 1024,
},
};
```
Add separate rejection cases for `pgvector`, `supported_transports`, external embedding providers,
non-1024 dimensions, non-cosine distance, and unknown fields. Assert v1/v2 remain parseable as
legacy descriptors but `isOperationalWorkspace()` returns false.
**Step 2: Run the tests and verify RED**
Run:
```bash
cd backend
npx vitest run test/workspaces-schema.test.ts test/workspaces-migrate-v2-qdrant.test.ts
```
Expected: failure because schema version 3 and `migrateWorkspaceV2ToV3` do not exist.
**Step 3: Implement the minimum schema and migration**
Add `QdrantVectorStore`, `InternalEmbedding`, and `WorkspaceV3` types. Replace the operational type
guard with schema-v3-only semantics. Implement:
```ts
export function migrateWorkspaceV2ToV3(
legacy: WorkspaceV2,
collection: string,
): WorkspaceV3 {
return validateOperationalWorkspace({
workspace: { ...legacy.workspace, schema_version: 3 },
dwh: legacy.dwh,
semantic_index: {
vector_store: {
engine: "qdrant",
collection,
dimensions: 1024,
distance: "cosine",
},
embedding: {
provider: "ollama_internal",
model: "qwen3-embedding:0.6b",
dimensions: 1024,
},
},
llm_policy: legacy.llm_policy,
...(legacy.diagnostics?.dwh_rest
? { diagnostics: { dwh_rest: legacy.diagnostics.dwh_rest } }
: {}),
});
}
```
Do not copy vector/embedding diagnostics or transports.
**Step 4: Verify GREEN**
Run the command from Step 2. Expected: all selected tests pass.
**Step 5: Commit**
```bash
git add backend/src/workspaces/schema.ts backend/src/workspaces/types.ts \
backend/src/workspaces/migrate-v2-qdrant.ts backend/test/workspaces-schema.test.ts \
backend/test/workspaces-migrate-legacy.test.ts backend/test/workspaces-migrate-v2-qdrant.test.ts
git commit -m "feat: define internal semantic workspace schema"
```
### Task 2: Make collection ownership unique in the Git registry
**Files:**
- Modify: `backend/src/workspaces/registry.ts`
- Modify: `backend/src/workspaces/migrate-legacy.ts`
- Modify: `backend/test/workspace-registry.test.ts`
- Modify: `backend/test/workspaces-migrate-legacy.test.ts`
**Step 1: Write failing registry tests**
Add fixtures with two schema-v3 workspaces claiming `collection: shared`. Assert snapshot activation
fails with `workspace_invalid` and retains the previous active snapshot. Assert v1/v2 entries are
listed as `migration_required` and cannot be acquired with `acquireSessionRevision()`.
**Step 2: Verify RED**
```bash
cd backend
npx vitest run test/workspace-registry.test.ts test/workspaces-migrate-legacy.test.ts \
-t "collection|migration_required"
```
Expected: duplicate collections are currently accepted and v2 is currently operational.
**Step 3: Implement uniqueness and migration state**
During snapshot validation, build `Map<collection, workspaceId>` for operational descriptors and
raise a sanitized `workspace_invalid` error on a duplicate. Update migration output and CLI wording
to require an explicit target collection and schema v3.
**Step 4: Verify GREEN and commit**
```bash
cd backend
npx vitest run test/workspace-registry.test.ts test/workspaces-migrate-legacy.test.ts \
-t "collection|migration_required"
cd ..
git add backend/src/workspaces/registry.ts backend/src/workspaces/migrate-legacy.ts \
backend/test/workspace-registry.test.ts backend/test/workspaces-migrate-legacy.test.ts
git commit -m "feat: reserve one qdrant collection per workspace"
```
### Task 3: Remove external semantic bindings and render internal endpoints
**Files:**
- Modify: `backend/src/workspaces/contracts.ts`
- Modify: `backend/src/workspaces/bindings.ts`
- Modify: `backend/src/workspaces/runtime-renderer.ts`
- Modify: `backend/src/config.ts`
- Modify: `backend/test/workspaces-contracts.test.ts`
- Modify: `backend/test/workspaces-bindings.test.ts`
- Modify: `backend/test/workspace-runtime-renderer.test.ts`
- Modify: `backend/test/config.test.ts`
**Step 1: Write failing contract tests**
Assert schema-v3 installation contracts contain DWH variables only. Assert environment variables
matching `*_VECTOR_*`, `*_EMBEDDING_BASE_URL`, or semantic API-key suffixes are ignored/rejected.
Assert the rendered harness config always contains:
```yaml
resources:
vector:
engine: qdrant
base_url: http://qdrant:6333
collection: psd-clinical
embeddings:
provider: ollama_internal
base_url: http://embedding:11434
model: qwen3-embedding:0.6b
dimensions: 1024
```
**Step 2: Verify RED**
```bash
cd backend
npx vitest run test/workspaces-contracts.test.ts test/workspaces-bindings.test.ts \
test/workspace-runtime-renderer.test.ts test/config.test.ts
```
Expected: current contracts require external vector and embedding bindings.
**Step 3: Implement internal runtime configuration**
Add typed backend config fields with Compose defaults:
```ts
internalQdrantUrl: "http://qdrant:6333"
internalEmbeddingUrl: "http://embedding:11434"
internalEmbeddingModel: "qwen3-embedding:0.6b"
internalEmbeddingDimensions: 1024
```
Accept only `qdrant`, `embedding`, `localhost`, or loopback hosts. Keep these values out of Git
workspace descriptors, API payloads, and generated installation docs. Render them into the
ephemeral backend-owned harness config after descriptor validation.
**Step 4: Verify GREEN and commit**
Run Step 2, then:
```bash
git add backend/src/config.ts backend/src/workspaces/contracts.ts backend/src/workspaces/bindings.ts \
backend/src/workspaces/runtime-renderer.ts backend/test/config.test.ts \
backend/test/workspaces-contracts.test.ts backend/test/workspaces-bindings.test.ts \
backend/test/workspace-runtime-renderer.test.ts
git commit -m "feat: render private semantic service endpoints"
```
### Task 4: Narrow harness embedding configuration to internal Ollama
**Files:**
- Modify: `harness/tht/config.py`
- Modify: `harness/tht/config_compat.py`
- Modify: `harness/tht/vectorstore/embeddings.py`
- Modify: `harness/tht/cli/ollama_cmd.py`
- Modify: `harness/tests/test_config_resources.py`
- Create: `harness/tests/test_internal_embeddings.py`
**Step 1: Write failing embedding tests**
Use a fake `requests.Session` to prove `OllamaInternalEmbeddings.embed()` calls `/api/embed` with
model and batch input, returns 1024-dimensional finite vectors, and rejects count/dimension/NaN
mismatches. Add config tests rejecting external providers, API keys, and non-private base URLs.
**Step 2: Verify RED**
```bash
cd harness
.venv/bin/pytest tests/test_internal_embeddings.py tests/test_config_resources.py -q
```
Expected: `OllamaInternalEmbeddings` and internal-only config do not exist.
**Step 3: Implement the client**
Implement one bounded `/api/embed` request per batch:
```python
response = self._session.post(
f"{self.base_url}/api/embed",
json={"model": self.model, "input": texts},
timeout=self.timeout,
)
```
Validate response shape before returning any vector. Keep retry behavior bounded and sanitize URLs
and response bodies from raised errors.
**Step 4: Verify GREEN and commit**
```bash
cd harness
.venv/bin/pytest tests/test_internal_embeddings.py tests/test_config_resources.py -q
cd ..
git add harness/tht/config.py harness/tht/config_compat.py harness/tht/vectorstore/embeddings.py \
harness/tht/cli/ollama_cmd.py harness/tests/test_config_resources.py \
harness/tests/test_internal_embeddings.py
git commit -m "feat: use internal ollama embeddings"
```
### Task 5: Implement the Qdrant VectorStore adapter
**Files:**
- Create: `harness/tht/adapters/vector/qdrant.py`
- Modify: `harness/tht/adapters/vector/__init__.py`
- Modify: `harness/tht/ports/vector.py`
- Modify: `harness/tht/vectorstore/records.py`
- Modify: `harness/tht/vectorstore/store.py`
- Create: `harness/tests/test_qdrant_vector_store.py`
- Modify: `harness/tests/test_vector_port_contract.py`
**Step 1: Write failing adapter tests**
Test a real adapter against a deterministic fake HTTP server. Cover:
- idempotent collection create with 1024/Cosine;
- mismatch fails without delete/recreate;
- keyword payload-index creation;
- deterministic UUIDv5 point IDs;
- upsert payload for `schema`, `evidence`, and `memory`;
- query filtered by workspace and allowed kinds;
- `existing_hashes`, exact Evidence generation list/delete, and health;
- sanitized timeouts and malformed responses.
The point ID helper must satisfy:
```python
def point_id(workspace_id: str, kind: str, record_key: str) -> str:
return str(uuid5(NAMESPACE_URL, f"thothii:{workspace_id}:{kind}:{record_key}"))
```
**Step 2: Verify RED**
```bash
cd harness
.venv/bin/pytest tests/test_qdrant_vector_store.py tests/test_vector_port_contract.py -q
```
Expected: import failure for the Qdrant adapter.
**Step 3: Implement minimal REST mappings**
Use existing `requests` dependency and these endpoints:
```text
GET /collections/{collection}
PUT /collections/{collection}
PUT /collections/{collection}/index
PUT /collections/{collection}/points?wait=true
POST /collections/{collection}/points/query
POST /collections/{collection}/points/scroll
POST /collections/{collection}/points/delete?wait=true
```
Every operation must include the workspace filter even though the collection is workspace-owned.
Map Qdrant scores and payloads back into existing `VectorHit` objects.
**Step 4: Verify GREEN and commit**
```bash
cd harness
.venv/bin/pytest tests/test_qdrant_vector_store.py tests/test_vector_port_contract.py -q
cd ..
git add harness/tht/adapters/vector/qdrant.py harness/tht/adapters/vector/__init__.py \
harness/tht/ports/vector.py harness/tht/vectorstore/records.py \
harness/tht/vectorstore/store.py harness/tests/test_qdrant_vector_store.py \
harness/tests/test_vector_port_contract.py
git commit -m "feat: add qdrant vector adapter"
```
### Task 6: Wire schema, Evidence, and Memory through Qdrant
**Files:**
- Modify: `harness/tht/vectorstore/reader.py`
- Modify: `harness/tht/cli/vector_cmd.py`
- Modify: `harness/tht/cli/memory_cmd.py`
- Modify: `harness/tht/corpus/pipeline.py`
- Modify: `harness/tht/search/evidence.py`
- Modify: `harness/tht/cli/schema_cmd.py`
- Modify: `harness/tests/test_memory_save_one.py`
- Modify: `harness/tests/test_search_pack.py`
- Create: `harness/tests/test_semantic_kind_isolation.py`
**Step 1: Write failing integration tests**
Use an in-memory fake implementing the `VectorStore` port. Assert:
- schema records use `kind=schema`;
- corpus records use `kind=evidence` and exact generation;
- approved memories use `kind=memory`;
- search pack requests only its allowed kind set;
- all three paths share `workspace_id`, `workspace_revision`, hashing, and point-key construction;
- retries do not duplicate points.
**Step 2: Verify RED**
```bash
cd harness
.venv/bin/pytest tests/test_semantic_kind_isolation.py tests/test_memory_save_one.py \
tests/test_search_pack.py -q
```
Expected: current factories select pgvector/HTTP adapters and payloads lack the v3 identity fields.
**Step 3: Wire the adapter**
Make schema-v3 `qdrant` the only operational vector factory branch. Reuse the current canonical
record builders; add only missing identity fields. Keep the JSONL Memory registry and filesystem
Evidence corpus as sources of truth.
**Step 4: Verify GREEN and commit**
Run Step 2, then commit the listed files with:
```bash
git commit -m "feat: index semantic records in qdrant"
```
### Task 7: Add mandatory Qdrant and Ollama Compose services
**Files:**
- Modify: `compose.yaml`
- Create: `deploy/compose.embedding-gpu.yaml`
- Create: `docker/embedding-model-init.sh`
- Modify: `docker/core.Dockerfile`
- Modify: `deploy/env/local.env.example`
- Modify: `deploy/env/server.env.example`
- Modify: `scripts/run-stack.sh`
- Modify: `scripts/test-default-compose.sh`
- Modify: `scripts/test-unified-compose.sh`
- Create: `scripts/test-internal-semantic-compose.sh`
**Step 1: Write failing Compose contract tests**
Assert the rendered base profile has `core`, `frontend`, `qdrant`, `embedding`, and
`embedding-model-init`; private services have no published ports; persistent volumes exist; core
depends on Qdrant health and successful model init; no external vector/embedding binding is required.
Also assert all service images use version plus immutable digest. Resolve and record supported
multi-architecture digests for Qdrant v1.18.x and Ollama v0.32.x during implementation:
```bash
docker buildx imagetools inspect qdrant/qdrant:v1.18.2
docker buildx imagetools inspect ollama/ollama:0.32.0
```
**Step 2: Verify RED**
```bash
./scripts/test-default-compose.sh
./scripts/test-unified-compose.sh
./scripts/test-internal-semantic-compose.sh
```
Expected: required services and volumes are absent.
**Step 3: Implement the services**
`embedding-model-init.sh` must wait with a bounded deadline, call `ollama pull` for the exact model,
and verify it appears in `/api/tags`. The Qdrant healthcheck uses its HTTP health endpoint. The CPU
base has no device reservation; the GPU override adds only the supported device stanza.
**Step 4: Verify GREEN and commit**
Run Step 2, then:
```bash
git add compose.yaml deploy/compose.embedding-gpu.yaml docker/embedding-model-init.sh \
docker/core.Dockerfile deploy/env/local.env.example deploy/env/server.env.example \
scripts/run-stack.sh scripts/test-default-compose.sh scripts/test-unified-compose.sh \
scripts/test-internal-semantic-compose.sh
git commit -m "feat: run qdrant and ollama inside thothii"
```
### Task 8: Retire pgvector deployment and external semantic connectors
**Files:**
- Delete: `deploy/compose.local-vector.yaml`
- Delete: `deploy/compose.preprocess-local-vector.yaml`
- Delete: `deploy/sql/20-vector-roles.sql`
- Delete: `deploy/vector/reconcile-roles.sh`
- Delete: `deploy/vector/rotate-bootstrap-password.py`
- Delete: `deploy/vector/secret-policy.sh`
- Delete: `deploy/vector/vector-db-entrypoint.sh`
- Delete: `scripts/local-vector-smoke.sh`
- Delete: `scripts/test-local-vector-smoke-safety.sh`
- Delete: `scripts/test-local-vector-smoke-live-collision.sh`
- Delete: `scripts/test-vector-bootstrap-rotation.sh`
- Delete: `scripts/test-vector-migration-image.sh`
- Delete: `scripts/test-vector-secret-policy.sh`
- Modify: `scripts/test-no-deployment-coupling.sh`
- Modify: `scripts/test-no-deployment-coupling-scope.sh`
- Modify: `scripts/test-compose-secret-policy.sh`
- Modify: `.github/workflows/deployment.yml`
**Step 1: Write the failing coupling test**
Teach the coupling gate to reject active `pgvector`, `local-vector`, `THT_VECTOR_*`, workspace
embedding URLs/API keys, and external vector transports while allowing historical specs and the
explicit descriptor migration module.
**Step 2: Verify RED**
```bash
./scripts/test-no-deployment-coupling-scope.sh
./scripts/test-no-deployment-coupling.sh
./scripts/test-compose-secret-policy.sh
```
Expected: active pgvector deployment paths are reported.
**Step 3: Remove the retired paths and update CI**
Remove only repository deployment machinery. Retain harness pgvector code temporarily only if it
is needed to read/export legacy data during migration; it must not be reachable from schema v3 or
Compose. Remove it in a follow-up task once migration fixtures no longer import it.
**Step 4: Verify GREEN and commit**
Run Step 2 and the workflow fixture tests, then commit all deletions and modifications:
```bash
git add -A deploy scripts .github/workflows/deployment.yml
git commit -m "refactor: retire external vector deployment"
```
### Task 9: Update frontend workspace editing and examples
**Files:**
- Modify: `frontend/src/api/workspaces.ts`
- Modify: `frontend/src/shell/WorkspaceEditor.tsx`
- Modify: `frontend/src/shell/WorkspaceEditor.test.tsx`
- Modify: `frontend/src/shell/WorkspaceManager.test.tsx`
- Modify: `frontend/src/api/workspaces.test.ts`
- Modify: `frontend/src/workspaces/drafts.test.ts`
- Modify: `deploy/workspaces/example.yaml`
- Modify: `deploy/workspaces/psd.yaml.example`
**Step 1: Write failing UI tests**
Assert editor/preview show Qdrant collection and fixed internal embedding model, expose no vector
endpoint/credential fields, and publish schema v3. Assert legacy descriptors display a migration
banner and cannot be selected for a new session.
**Step 2: Verify RED**
```bash
cd frontend
npx vitest run src/shell/WorkspaceEditor.test.tsx src/shell/WorkspaceManager.test.tsx \
src/api/workspaces.test.ts src/workspaces/drafts.test.ts
```
Expected: fixtures and controls still use pgvector/external embedding.
**Step 3: Implement fixed semantic controls**
Collection remains editable and validated. Engine, provider, model, dimensions, and distance render
as fixed architecture values. Remove external semantic diagnostics from drafts and publish payloads.
**Step 4: Verify GREEN and commit**
Run Step 2, then commit the listed files with:
```bash
git commit -m "feat: edit qdrant workspace collections"
```
### Task 10: Add a real internal semantic smoke
**Files:**
- Create: `scripts/internal-semantic-smoke.sh`
- Modify: `scripts/unified-deployment-smoke.sh`
- Modify: `scripts/server-deployment-smoke.sh`
- Modify: `scripts/task13-runtime-fixture-check.ts`
- Modify: `scripts/test-task13-runtime-fixtures.sh`
**Step 1: Write failing smoke fixture assertions**
The fixture must require private Qdrant/Ollama services, model volume, Qdrant volume, fixed internal
URLs, and no host ports. It must reject wrong service names, external URLs, collection reuse, and
dimension changes.
**Step 2: Verify RED**
```bash
./scripts/test-task13-runtime-fixtures.sh local
./scripts/test-task13-runtime-fixtures.sh server
```
Expected: current fixture expects the two-service topology.
**Step 3: Implement the live smoke**
Using disposable volumes and a fixture workspace, start the stack on CPU, wait for the model, ensure
the collection, embed one record of each kind, query each kind with filters, restart offline, and
prove all points and the model remain available. Cleanup must remain exact and must not prune global
Docker resources.
**Step 4: Verify GREEN and commit**
```bash
./scripts/test-task13-runtime-fixtures.sh local
./scripts/test-task13-runtime-fixtures.sh server
./scripts/internal-semantic-smoke.sh
git add scripts/internal-semantic-smoke.sh scripts/unified-deployment-smoke.sh \
scripts/server-deployment-smoke.sh scripts/task13-runtime-fixture-check.ts \
scripts/test-task13-runtime-fixtures.sh
git commit -m "test: cover internal semantic services"
```
### Task 11: Update operator documentation and state
**Files:**
- Modify: `README.md`
- Modify: `AGENTS.md`
- Modify: `PROJECT_STATE.md`
- Modify: `docs/install/local-workspace-registry.md`
- Modify: `docs/install/server-workspace-registry.md`
- Modify: `docs/installazione-docker-4-contesti.md`
- Modify: `docs/workspace-diagnostic-protocol.md`
- Modify: `docs/gestione-memory.md`
- Modify: `deploy/secrets/README.md`
- Modify: `scripts/verify-workspace-install-docs.sh`
- Modify: `scripts/test-verify-workspace-install-docs.sh`
**Step 1: Write failing documentation contract assertions**
Require the four-service topology, CPU/GPU behavior, volume backup/restore, schema-v3 migration,
Qdrant collection ownership, and removal of external vector/embedding variables from active manuals.
**Step 2: Verify RED**
```bash
./scripts/test-verify-workspace-install-docs.sh
./scripts/verify-workspace-install-docs.sh --fixtures-only
```
Expected: manuals still describe external pgvector/embedding and a two-service mandatory stack.
**Step 3: Update documentation**
Document Qdrant as a derived but persistent index, Ollama model cache behavior, CPU-first startup,
optional GPU override, snapshot/restore, explicit legacy migration, and the fact that only the DWH
and LLM remain external application endpoints.
**Step 4: Verify GREEN and commit**
Run Step 2, then:
```bash
git add README.md AGENTS.md PROJECT_STATE.md docs deploy/secrets/README.md \
scripts/verify-workspace-install-docs.sh scripts/test-verify-workspace-install-docs.sh
git commit -m "docs: document internal semantic infrastructure"
```
### Task 12: Remove unreachable pgvector runtime code
**Files:**
- Delete: `harness/tht/adapters/vector/pgvector.py`
- Delete: `harness/tht/adapters/vector/legacy_direct.py`
- Delete: `harness/tht/adapters/vector/thoth_http.py`
- Delete: `harness/tht/vectorstore/rest_client.py`
- Delete: `harness/tht/vectorstore/rest_writer.py`
- Delete: `harness/tht/migrations/vector/001_extensions.sql`
- Delete: `harness/tht/migrations/vector/002_schema_tables.sql`
- Delete: `harness/tht/migrations/vector/003_roles.sql`
- Delete: `harness/tht/migrations/vector/004_evidence_generation_gc.sql`
- Modify: `harness/pyproject.toml`
- Modify/Delete: affected pgvector and migration tests under `harness/tests/l0/`
**Step 1: Prove the code is unreachable**
```bash
rg -n "PgVectorStore|ThothHttpVectorStore|LegacyDirectVectorStore|migrations/vector" \
harness backend frontend compose.yaml deploy scripts docker docs \
--glob '!docs/plans/**' --glob '!docs/superpowers/**'
```
Expected before cleanup: matches only in the files scheduled for deletion and legacy tests. If an
operational call site remains, stop and migrate it before deleting anything.
**Step 2: Delete obsolete runtime and tests**
Retain descriptor migration tests, but remove PostgreSQL vector runtime/migration packaging tests.
Remove `psycopg2-binary` only if the DWH/session PostgreSQL paths do not need it; otherwise keep it.
**Step 3: Verify focused imports and packaging**
```bash
cd harness
.venv/bin/pytest tests/test_qdrant_vector_store.py tests/test_vector_port_contract.py \
tests/test_semantic_kind_isolation.py tests/test_vector_migration_packaging.py -q
python -m build
```
Expected: Qdrant tests pass and the wheel contains no pgvector migrations. Adjust the packaging test
to assert Qdrant has no SQL migration payload.
**Step 4: Commit**
```bash
git add -A harness
git commit -m "refactor: remove pgvector runtime"
```
### Task 13: Run complete verification
**Files:**
- Modify only if a genuine regression is discovered.
**Step 1: Deterministic layer gates**
```bash
cd harness && .venv/bin/pytest -q && .venv/bin/ruff check .
cd ../backend && npx vitest run && npx tsc --noEmit -p . && npm run build
cd ../frontend && npx vitest run && npx tsc -b && npm run build
cd .. && git diff --check
```
Expected: all gates pass. Existing unrelated Ruff debt must be reported separately if it remains;
new/modified files must be Ruff-clean.
**Step 2: Deployment contracts**
```bash
./scripts/test-default-compose.sh
./scripts/test-unified-compose.sh
./scripts/test-internal-semantic-compose.sh
./scripts/test-no-deployment-coupling.sh
./scripts/test-compose-secret-policy.sh
./scripts/verify-workspace-install-docs.sh --fixtures-only
```
Expected: all pass without external vector/embedding settings.
**Step 3: Docker smokes**
```bash
./scripts/internal-semantic-smoke.sh
./scripts/workspace-registry-smoke.sh
./scripts/unified-deployment-smoke.sh
./scripts/thothctl-update-smoke.sh
./scripts/server-deployment-smoke.sh
```
Expected: CPU semantic smoke passes, persistence survives offline restart, and every script proves
exact cleanup. Investigate the previously observed `thothctl` rollback failure independently if it
recurs; do not weaken the new semantic gate to hide it.
**Step 4: Final audit**
```bash
rg -n "pgvector|local-vector|THT_VECTOR_|EMBEDDING_BASE_URL|openai_compatible|ollama_compatible" \
. --glob '!docs/plans/**' --glob '!docs/superpowers/**' --glob '!**/node_modules/**' \
--glob '!**/.venv/**' --glob '!**/.git/**'
git status --short
```
Expected: no active operational references; only explicit legacy descriptor migration fixtures may
remain. Worktree contains only intentional changes.
**Step 5: Commit verification metadata**
Update `PROJECT_STATE.md` with exact counts, image digests, smoke durations, CPU hardware, and any
manual GPU/Windows gates. Commit only verified claims:
```bash
git add PROJECT_STATE.md
git commit -m "docs: record qdrant ollama verification"
```
@@ -1,447 +0,0 @@
# 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.
@@ -1,401 +0,0 @@
# Read-only Workspace Runtime Secrets Implementation Plan
> **Historical nomenclature:** this plan predates the native host CLI convergence. References to
> `thothctl` and `tools/thothctl` describe the implementation snapshot from which this plan was
> written; current operator commands and paths use native `tht` and `tools/tht`.
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Make workspace consumption strictly read-only while adding installation-scoped Git identity and persistent GUI-managed runtime secrets.
**Architecture:** Git remains the source of truth and is fetched into an application-owned checkout; complete candidate commits are validated before atomic activation and the backend has no Git write path. Runtime connector credentials are discovered from trusted connector contracts, stored as authenticated ciphertext by a backend vault, and materialized only for the lifetime of diagnostics or runtime leases. The browser exposes repository/readiness status and write-only secret forms without workspace persistence.
**Tech Stack:** Fastify, TypeScript, Node.js crypto/filesystem, React 18, TanStack Query, Vitest, Go `thothctl`, Docker Compose.
---
### Task 1: Freeze the Git repository boundary to read-only
**Files:**
- Modify: `backend/src/workspaces/types.ts`
- Modify: `backend/src/workspaces/git-repository.ts`
- Modify: `backend/src/workspaces/registry.ts`
- Modify: `backend/test/workspaces-git-repository.test.ts`
- Modify: `backend/test/workspace-registry.test.ts`
- Modify: `backend/test/workspace-registry-deployment.test.ts`
**Step 1: Write failing tests**
Add tests proving that pull never configures a Git author, writes generated files, commits, or pushes; that a malformed candidate leaves the prior active snapshot intact; and that a missing catalog descriptor rejects the whole candidate instead of producing a bootstrap slot.
**Step 2: Run the focused tests**
Run: `cd backend && npx vitest run test/workspaces-git-repository.test.ts test/workspace-registry.test.ts test/workspace-registry-deployment.test.ts`
Expected: FAIL on write/publish behavior and missing-descriptor semantics.
**Step 3: Implement the read-only boundary**
Remove `gitAuthorName`, `gitAuthorEmail`, mutation helpers, generated-document reconciliation, publish/conflict types, and bootstrap-slot activation. `pull()` must fetch, validate the complete commit in a candidate snapshot, and replace active state only after validation succeeds.
**Step 4: Run focused tests**
Run the command from Step 2.
Expected: PASS.
**Step 5: Commit**
```bash
git add backend/src/workspaces backend/test/workspaces-git-repository.test.ts backend/test/workspace-registry.test.ts backend/test/workspace-registry-deployment.test.ts
git commit -m "refactor: make workspace repository strictly read only"
```
### Task 2: Remove publishing and bundle HTTP contracts
**Files:**
- Modify: `backend/src/routes/workspaces.ts`
- Modify: `backend/test/routes-workspaces.test.ts`
- Modify: `backend/test/workspaces-runtime-v3-boundaries.test.ts`
- Modify: `backend/src/config.ts`
- Modify: `backend/test/workspaces-config.test.ts`
**Step 1: Write failing route tests**
Assert `POST /workspaces/publish`, `GET /workspaces/:id/export`, and `POST /workspaces/import` return 404 and that the backend no longer registers multipart or ZIP handling. Assert configuration no longer accepts Git author or bundle-limit settings as workspace-registry fields.
**Step 2: Run tests and observe failure**
Run: `cd backend && npx vitest run test/routes-workspaces.test.ts test/workspaces-config.test.ts test/workspaces-runtime-v3-boundaries.test.ts`
Expected: FAIL because mutation and bundle routes still exist.
**Step 3: Remove the mutation surface**
Delete publish/import/export schemas and helpers, remove `multipart`, `yauzl`, and `yazl` usage from the route, and simplify safe workspace errors to read/validate/sync errors.
**Step 4: Run tests**
Run the command from Step 2 plus `cd backend && npx tsc --noEmit -p .`.
Expected: PASS.
**Step 5: Commit**
```bash
git add backend/src backend/test package.json package-lock.json
git commit -m "refactor: remove workspace publishing and bundles"
```
### Task 3: Expose a sanitized installation repository identity
**Files:**
- Modify: `backend/src/workspaces/git-repository.ts`
- Modify: `backend/src/routes/workspaces.ts`
- Modify: `backend/test/workspaces-git-repository.test.ts`
- Modify: `backend/test/routes-workspaces.test.ts`
- Modify: `tools/thothctl/internal/config/installation.go`
- Modify: `tools/thothctl/internal/config/installation_test.go`
- Modify: `deploy/psd/thothii-installation.yaml.example`
- Modify: `docs/install/examples/thothii-installation.local.yaml`
- Modify: `docs/install/examples/thothii-installation.server.yaml`
**Step 1: Write failing parser and status tests**
Cover HTTPS, SSH URL, and SCP-style remotes; reject embedded user-info for HTTPS; return only `host`, `repository`, `branch`, and `transport`; never return a token, key path, or raw credential-bearing URL. Add installation-descriptor tests for a required `workspaceRepository` block and exactly one read-only transport.
**Step 2: Run focused tests**
Run: `cd backend && npx vitest run test/workspaces-git-repository.test.ts test/routes-workspaces.test.ts && cd ../tools/thothctl && go test ./internal/config`
Expected: FAIL because repository identity and typed installation configuration do not exist.
**Step 3: Implement safe normalization and installation validation**
Add the normalized identity to registry status. Extend `thothii-installation.yaml` with remote, branch, and SSH/HTTPS access metadata, validate it against the selected Compose override and environment without reading or returning secret values, and retain the existing environment rendering boundary.
**Step 4: Run focused tests**
Run the command from Step 2.
Expected: PASS.
**Step 5: Commit**
```bash
git add backend tools/thothctl deploy docs/install/examples
git commit -m "feat: declare workspace repository in installation config"
```
### Task 4: Add the persistent encrypted workspace secret store
**Files:**
- Create: `backend/src/workspaces/secret-store.ts`
- Create: `backend/test/workspace-secret-store.test.ts`
- Modify: `backend/src/config.ts`
- Modify: `backend/src/app.ts`
- Modify: `compose.yaml`
- Modify: `deploy/compose.local.yaml`
- Modify: `deploy/compose.server.yaml`
**Step 1: Write failing vault tests**
Test first-start initialization, atomic blind replacement, deletion, enumeration by configured ID only, AES-256-GCM ciphertext with installation/workspace/field associated data, corruption failure, restrictive files/directories, size limits, and absence of plaintext in persistent bytes.
**Step 2: Run the vault test**
Run: `cd backend && npx vitest run test/workspace-secret-store.test.ts`
Expected: FAIL because `WorkspaceSecretStore` does not exist.
**Step 3: Implement the vault**
Create an injectable `WorkspaceSecretStore` backed by an application-managed data root. Persist a versioned encrypted document atomically, generate or load the installation vault key in the private control area, expose only `has`, `put`, `delete`, and scoped materialization operations, and never add a plaintext read API.
**Step 4: Run tests and typecheck**
Run: `cd backend && npx vitest run test/workspace-secret-store.test.ts && npx tsc --noEmit -p .`
Expected: PASS.
**Step 5: Commit**
```bash
git add backend compose.yaml deploy
git commit -m "feat: persist encrypted workspace runtime secrets"
```
### Task 5: Derive connector requirements and integrate temporary materialization
**Files:**
- Create: `backend/src/workspaces/secret-requirements.ts`
- Create: `backend/test/workspace-secret-requirements.test.ts`
- Modify: `backend/src/workspaces/bindings.ts`
- Modify: `backend/src/workspaces/runtime-config-lease.ts`
- Modify: `backend/src/tht/tht-runner.ts`
- Modify: `backend/src/app.ts`
- Modify: `backend/test/workspace-runtime-config-lease.test.ts`
- Modify: `backend/test/workspace-runtime-handoff.test.ts`
- Modify: `backend/test/workspaces-bindings.test.ts`
**Step 1: Write failing requirement and lifecycle tests**
Cover PostgreSQL password, REST bearer API key, unauthenticated REST, SSH private key/password, signed HTTP Evidence, and static S3 credentials. Assert temporary files are restrictive, live for exactly one diagnostic/runtime lease, disappear on release and error, and are never persisted in the encrypted vault document.
**Step 2: Run focused tests**
Run: `cd backend && npx vitest run test/workspace-secret-requirements.test.ts test/workspaces-bindings.test.ts test/workspace-runtime-config-lease.test.ts test/workspace-runtime-handoff.test.ts`
Expected: FAIL because requirements still come from installation secret-file paths.
**Step 3: Implement dynamic requirement resolution**
Use the selected DWH transport and Evidence authentication contract to map trusted installation-contract suffixes to stable GUI requirement IDs. Overlay materialized temporary file paths only while resolving existing file-oriented connectors, and attach cleanup to every runtime lease.
**Step 4: Run tests and typecheck**
Run the command from Step 2 plus `cd backend && npx tsc --noEmit -p .`.
Expected: PASS.
**Step 5: Commit**
```bash
git add backend/src backend/test
git commit -m "feat: resolve workspace secrets from connector requirements"
```
### Task 6: Add write-only workspace secret and readiness APIs
**Files:**
- Modify: `backend/src/routes/workspaces.ts`
- Modify: `backend/src/app.ts`
- Modify: `backend/src/workspaces/types.ts`
- Modify: `backend/test/routes-workspaces.test.ts`
**Step 1: Write failing API tests**
Test `GET /workspaces/:id/runtime-configuration`, blind `PUT /workspaces/:id/secrets`, and `DELETE /workspaces/:id/secrets/:requirementId`. Assert strict bodies, limits, unknown-ID rejection, status-only responses, diagnostic invalidation, and `configuration_required`/`ready` state transitions.
**Step 2: Run tests**
Run: `cd backend && npx vitest run test/routes-workspaces.test.ts`
Expected: FAIL because the routes do not exist.
**Step 3: Implement the routes and readiness projection**
Inject the secret store into workspace routes and runtime support. Compute per-workspace readiness from active descriptor, current requirement set, configured IDs, and diagnostic generation. Materialize values only inside the diagnostic request and always clean up.
**Step 4: Run backend gates**
Run: `cd backend && npx vitest run && npx tsc --noEmit -p . && npm run build`.
Expected: PASS.
**Step 5: Commit**
```bash
git add backend
git commit -m "feat: manage runtime workspace secrets through the API"
```
### Task 7: Replace workspace management with the two-level read-only UI
**Files:**
- Modify: `frontend/src/api/workspaces.ts`
- Modify: `frontend/src/api/workspaces.test.ts`
- Modify: `frontend/src/shell/WorkspaceManager.tsx`
- Modify: `frontend/src/shell/WorkspaceManager.test.tsx`
- Delete: `frontend/src/shell/WorkspacePublishDialog.tsx`
- Delete: corresponding publish-dialog tests
- Modify/Delete: `frontend/src/shell/WorkspaceEditor.tsx` and bootstrap-only tests as references permit
- Modify: `frontend/src/workspaces/drafts.ts`
- Modify: `frontend/src/workspaces/drafts.test.ts`
**Step 1: Write failing UI/API tests**
Assert the dialog uses at least 60% viewport width and height, shows general repository concepts and exact button consequences at level 1, gates workspace-specific controls on selection, renders requirement explanations and write-only fields at level 2, and has no create/edit/publish/import/export/bundle controls.
**Step 2: Run focused tests**
Run: `cd frontend && npx vitest run src/api/workspaces.test.ts src/shell/WorkspaceManager.test.tsx src/workspaces/drafts.test.ts`
Expected: FAIL on the old draft/publish interface.
**Step 3: Implement the read-only interface**
Replace bootstrap editor state with repository status, selection, validation/readiness details, dynamic secret fields, blind save/forget actions, and connection test. Remove workspace draft persistence and clear secret field component state after submit/close.
**Step 4: Run focused tests and typecheck**
Run the command from Step 2 plus `cd frontend && npx tsc -b`.
Expected: PASS.
**Step 5: Commit**
```bash
git add frontend
git commit -m "feat: add read-only workspace and secret management UI"
```
### Task 8: Remove browser-persisted workspace preferences
**Files:**
- Modify: `frontend/src/workspaces/preferences.ts`
- Modify: `frontend/src/workspaces/preferences.test.ts`
- Modify: `frontend/src/api/sessions.ts`
- Modify: `frontend/src/api/sessions.test.ts`
- Modify: `frontend/src/shell/SteerInput.tsx`
- Modify: `frontend/src/shell/SteerInput.test.tsx`
**Step 1: Write failing persistence-boundary tests**
Assert workspace/model/thinking choices are kept only in current application memory or saved through the existing backend settings API, and that no workspace code calls `localStorage`.
**Step 2: Run focused tests**
Run: `cd frontend && npx vitest run src/workspaces/preferences.test.ts src/api/sessions.test.ts src/shell/SteerInput.test.tsx`
Expected: FAIL because preferences still use browser storage.
**Step 3: Implement ephemeral preferences**
Replace the storage adapter with an in-memory external store seeded from backend settings. Preserve concurrent workspace-policy gates and session request determinism without persisting selections in the browser.
**Step 4: Run frontend gates**
Run: `cd frontend && npx vitest run && npx tsc -b && npm run build`.
Expected: PASS.
**Step 5: Commit**
```bash
git add frontend
git commit -m "refactor: stop persisting workspace state in the browser"
```
### Task 9: Update deployment contracts and documentation
**Files:**
- Modify: `compose.yaml`
- Modify: `deploy/compose.git-ssh.yaml`
- Modify: `deploy/compose.git-https.yaml`
- Modify: `deploy/workspace-registry.env.example`
- Modify: `deploy/psd/operator.env.example`
- Modify: `docs/install/local-workspace-registry.md`
- Modify: `docs/install/server-workspace-registry.md`
- Modify: `docs/guida-utente.md`
- Modify: `scripts/verify-workspace-install-docs.sh`
- Modify: `scripts/workspace-registry-smoke.sh`
**Step 1: Update executable contract tests first**
Require read-only Git wording and configuration, repository identity visibility, vault persistence,
and absence of author/push/bundle/browser-secret instructions.
**Step 2: Run contract tests and observe failure**
Run: `bash scripts/verify-workspace-install-docs.sh`
Expected: FAIL against the old manuals and examples.
**Step 3: Update deployment and manuals**
Remove Git author settings and write-oriented documentation. Document installation Git bootstrap,
GUI runtime-secret completion, platform-neutral application storage, rotation/forget flows, and
candidate validation semantics.
**Step 4: Run contract and Go gates**
Run: `bash scripts/verify-workspace-install-docs.sh && cd tools/thothctl && go test ./...`
Expected: PASS.
**Step 5: Commit**
```bash
git add compose.yaml deploy docs scripts tools/thothctl
git commit -m "docs: describe read-only workspace runtime configuration"
```
### Task 10: Full verification and deployed-container refresh
**Files:**
- Modify only files needed to fix failures found by verification.
**Step 1: Run static and unit gates**
```bash
cd backend && npx vitest run && npx tsc --noEmit -p . && npm run build
cd ../frontend && npx vitest run && npx tsc -b && npm run build
cd ../harness && .venv/bin/pytest -q
cd ../tools/thothctl && go test ./...
```
Expected: all gates PASS.
**Step 2: Run deployment contract gates**
Run: `bash scripts/verify-workspace-install-docs.sh` and the focused workspace registry smoke appropriate to the configured installation.
Expected: PASS without Git writes or secret disclosure.
**Step 3: Inspect the final diff and secret scan**
Run: `git diff --check`, inspect `git status --short`, and search active code/config for removed publish, bundle, Git author, and workspace-localStorage contracts.
Expected: no whitespace errors, no accidental secrets, and only intended changes.
**Step 4: Rebuild and restart affected services**
Use the installation-aware `thothctl` lifecycle for the configured installation to rebuild/restart `core` and `frontend`, then verify health and repository status. Do not restart if no valid local installation descriptor is available; report that external gate explicitly.
**Step 5: Commit verification fixes**
```bash
git add <only-files-changed-for-verification>
git commit -m "test: verify read-only workspace secret flow"
```
@@ -1,217 +0,0 @@
# Evidence canonica — struttura tipizzata per disambiguazione, schema linking e SQL
> **Superseded (2026-08-24).** Questo documento conserva la storia della prima
> proposta. Il disegno approvato è
> [`2026-08-24-evidence-restructuring-design.md`](2026-08-24-evidence-restructuring-design.md)
> e il relativo piano esecutivo è
> [`2026-08-24-evidence-restructuring.md`](2026-08-24-evidence-restructuring.md).
## Contesto e decisioni prese
ThothII ha già due livelli separati che non si parlano:
- **`EvidenceDoc`** (`harness/tht/evidence/model.py`) — runtime: frontmatter piatto
(`id/title/tier/status/tables/concepts/sources`) + `body` markdown libero. `tier`
distingue solo `structural|concept`, insufficiente rispetto ai 6 tipi reali del corpus.
- **Pipeline corpus** (`harness/tht/corpus/`) — canonizzazione *tecnica* (hash,
provenienza, chunking, vettorizzazione), agnostica rispetto al tipo di evidenza.
Il corpus reale (`ChironeWp3/artifacts/evidence/`) ha una tassonomia implicita in 6
directory (`00-glossario`, `10-domini-clinici`, `20-valori-enum`, `30-esempi-nlq`,
`40-mapping-semantico`, `50-metadati-normalizzazione`) ma:
- frontmatter piatto, `tier` inadeguato;
- file già rotti (`--` invece di `---`, bullet `•⁠ ⁠` invece di `-`) che `EvidenceDoc.parse`
rifiuterebbe;
- al retrieval la struttura si perde: `tht search pack` proietta solo `title` + 400 char.
**Decisioni (confermate nel brainstorming):**
1. **Obiettivo**: strutturare il *contenuto* runtime, non toccare la pipeline corpus.
2. **Forma**: ibrido — frontmatter tipizzato + sezioni canoniche per `kind`.
3. **Tassonomia**: doppia — `kind` (contenuto) + `applies_to` (destinazioni:
`disambiguation`, `rewriting`, `schema_linking`, `sql_generation`, `memory`).
4. **Anchors come fonte primaria** per il value-grounding in F4; LSH solo fallback.
5. **Approccio**: contratto in `tht` + authoring sottile (niente app separata, niente
client LLM diretto in `tht`).
6. **Modello sorgente→canonizzato** (non sovrascrittura in place): file umani in
`source_root/evidence/`, canonizzati derivati in `artifacts/evidence/`, coerente con
l'esistente `tht evidence extract`.
7. **Review**: batch con diff aggregato (approvazione per file).
8. **Rielaborazione**: LLM-assistita via Pi (sessione di manutenzione + gate), con parte
deterministica in `tht`.
## Modello canonico v2
### `CanonicalEvidence` (frontmatter tipizzato)
```yaml
---
schema_version: 2
id: ev-dom-ablazione-see
title: Dominio Ablazione e SEE
kind: domain # glossario | domain | enum | example | mapping | normalization
applies_to: # destinazioni d'uso
- disambiguation # F1
- schema_linking # F4
- sql_generation # F6/F7
status: reviewed
language: it
concepts:
- term: ablazione
synonyms: [ablazione transcatetere, SEE, studio elettrofisiologico]
- term: fibrillazione atriale
synonyms: [FA]
tables:
- name: datawarehouse.fact_studio_elettrofisiologico_endocavitario_ablazione
role: fact
columns: [ablazione_transcatetere, cod_paz, num]
anchors:
- column: datawarehouse.fact_see_ablazione_procedura_patologia.patologia
value: ablazione
match: exact
sources: [...]
# provenienza del derivato (aggiunta dal canonicalize, non dall'umano):
source_file: 10-domini-clinici/ablazione.md
source_fingerprint: sha256:...
canonicalized_at: 2026-08-18T...
---
```
Il `body` resta markdown, ma con **titoli di sezione canonici per `kind`**:
- `glossario`: `## Definizione`
- `domain`: `## Cosa rappresenta`, `## Schema a stella`, `## Granularità`, `## Domande di business tipiche`
- `enum`: `## Valori ammessi`
- `example`: `## Domanda → SQL` + `## Nota clinica`
- `mapping`: `## Trasformazioni disponibili`
- `normalization`: `## Regole di normalizzazione`
Le sezioni canoniche permettono al retrieval di estrarre solo la sezione rilevante per
fase invece di 400 caratteri generici.
### `kind` vs `applies_to`
- `kind` descrive il *contenuto* (i 6 tipi già impliciti).
- `applies_to` descrive *quando usarlo*. Esempi: `enum-tipo-intervento` è `kind: enum` ma
`applies_to: [disambiguation, sql_generation]`; un `example` è
`applies_to: [sql_generation, memory]`.
## Modello a 3 livelli
```
source_root/evidence/*.md (umano, libero, può essere sporco)
│ tht evidence canonicalize (deterministico + LLM via Pi + review batch)
▼
artifacts/evidence/*.md (canonico, validato, derivato, rigenerabile)
│ tht evidence index (esistente)
▼
corpus / vector store (vettorializzato dal canonico, mai dal sorgente)
```
Il canonizzato porta `source_file` + `source_fingerprint`: se il sorgente cambia, la
canonizzazione ripropone il diff; se invariato, no-op.
## Componenti da creare/modificare
### 1. `harness/tht/evidence/model.py` (modifica)
- Aggiungere `CanonicalEvidence` (pydantic, v2) con `schema_version`, `kind`,
`applies_to`, `concepts[]` (`{term, synonyms[]}`), `tables[]`
(`{name, role, columns[]}`), `anchors[]` (`{column, value, match}`), `source_file`,
`source_fingerprint`, `canonicalized_at`.
- Validatore strict: `kind` ammesso, `applies_to` ammesso, `anchors[].column` deve
essere `schema.colonna` ben formato, `match` in `{exact, contains, regex, substring}`.
- `EvidenceDoc` v1 resta per leggere il sorgente e per retro-compatibilità dei vecchi
canonizzati; `CanonicalEvidence` è un modello separato, non una sottoclasse.
- Validatore che garantisce `source_fingerprint` = sha256 del contenuto sorgente.
### 2. `harness/tht/evidence/lint.py` (nuovo, deterministico)
- `lint_source(path) -> list[Diagnostic]`: frontmatter rotto, `tier`/`status` non validi,
bullet Unicode, campi mancanti, `tables` non qualificate con schema, concetti senza
sinonimi, sezioni non canoniche per il `kind` atteso.
- Exit code 0 se nessun errore, 1 se warning, 2 se errori. Nessun LLM.
### 3. `harness/tht/evidence/canonicalize.py` (nuovo)
- `plan(sources, artifacts) -> CanonicalizePlan`: confronta fingerprint dei sorgenti con
i canonizzati esistenti, produce la lista dei file da (ri)canonizzare.
- `render_proposal(source, llm_completions) -> CanonicalEvidence`: assembla il
canonizzato da parsing deterministico + campi semantici forniti da Pi.
- `apply(plan, approved_ids) -> None`: scrive solo i canonizzati approvati in
`artifacts/evidence/`, atomico per file, mantiene la gerarchia per dominio.
- `diff(source, candidate) -> str`: diff markdown per il gate.
### 4. `harness/tht/vectorstore/records.py` (modifica)
- `evidence_records()`: metadata ora include `kind`, `applies_to`, `anchors` (non solo
`status/tier/tables/concepts`).
- Il `content` di ogni record resta title+body, ma per file con sezioni canoniche si
indicizza anche un record per sezione (id `evidence:<id>:<sezione>`) così il retrieval
può restringere per sezione oltre che per documento.
### 5. `harness/tht/search/__init__.py` + `cli/search_cmd.py` (modifica)
- `SearchResult` e `combined_search` accettano `applies_to` come filtro metadata.
- `tht search pack`: la sezione "Evidence rilevanti" ora proietta `kind` + sezione
canonica pertinente (non solo excerpt generico); usa `applies_to` per non mischiare
destinazioni.
- `tht search find --kind evidence --applies-to <dest>` per il retrieval mirato.
### 6. `harness/tht/cli/evidence_cmd.py` (modifica)
- Nuovi comandi:
- `tht evidence lint --source <path|dir>` — diagnostica deterministica.
- `tht evidence canonicalize plan --source-root <dir> --json` — piano di
(ri)canonizzazione.
- `tht evidence canonicalize apply --plan <file> --approved <ids> --json` — applica.
- `--json` sempre pristine (solo JSON su stdout), come da contratto di progetto.
### 7. `harness/.pi/extensions/tht-gate.js` (modifica)
- Nuovo tool `reviewer_evidence_batch`: riceve il piano + i diff aggregati e presenta un
multiselect per file (approva/rifiuta/richiedi modifica). Le scelte approvate vengono
persistite tramite `tht evidence canonicalize apply`.
- Aggiungere `tht evidence canonicalize apply` alla FORBIDDEN anti-bypass list (il
modello non può applicare canonizzazioni senza review).
### 8. Sessione di manutenzione Pi (nuova skill o sezione SKILL)
- Una skill dedicata `tht-evidence-canonicalize` (o un comando slash nel gate) descrive
la sessione di manutenzione: il modello legge i sorgenti marcati dal piano, propone i
campi semantici (`kind`, `applies_to`, `concepts` con sinonimi, `tables` con ruolo,
`anchors`) e li invia al `reviewer_evidence_batch`.
- Il gate è l'unico canale di review; il modello non scrive mai direttamente
`artifacts/evidence/`.
### 9. `harness/.pi/skills/tht-sessione/SKILL.md` (modifica)
- Aggiornare i punti F1/F4/F6-F7 dove il modello legge evidence: spiegare che l'evidence
canonica espone `kind`/`applies_to`/`anchors`, che gli `anchors` sono la fonte primaria
per il value-grounding in F4, e che le sezioni canoniche vanno citate per destinazione.
- Aggiungere il nuovo tool `reviewer_evidence_batch` alla lista dei tool disponibili.
## Migrazione del corpus (incrementale, v1+v2 convivono)
- `CanonicalEvidence` (v2) convive con `EvidenceDoc` (v1): `lint` segnala i non-canonici
ma nulla si rompe; `load_evidence_dir` carica entrambi.
- Convertire a lotti, partendo da `20-valori-enum` e `10-domini-clinici` (impatto
maggiore su F1/F4, anchors più ricchi).
- Il canonizzato derivato in `artifacts/evidence/` sostituisce progressivamente il file
sorgente mirrorato; finché un sorgente non è canonizzato, `extract` continua a
rispecchiare il v1 come oggi.
## Ordine di implementazione
1. `CanonicalEvidence` + `lint` (TDD, nessun LLM).
2. `canonicalize.py` (plan/apply/diff) + comandi CLI (TDD).
3. `records.py` + filtro `applies_to` in `search` + proiezione pack (TDD).
4. Gate `reviewer_evidence_batch` + skill manutenzione Pi.
5. Aggiornamento `SKILL.md` tht-sessione.
6. Conversione primo lotto (`enum` + `domain`) con review batch.
## Verifica
- `cd harness && .venv/bin/pytest -q` — test nuovi per model/lint/canonicalize/records/search.
- `node --test` sul gate per `reviewer_evidence_batch` e anti-bypass.
- Su un campione del corpus: `tht evidence lint` riporta i file rotti (frontmatter `--`,
bullet Unicode) senza crash; `tht evidence canonicalize plan --json` produce piano
corretto; `apply` con fingerprint invariato è no-op.
- `tht search pack "<domanda ablazione>"` mostra evidence con `kind`/sezione pertinente e
gli anchor presenti; `tht search find --kind evidence --applies-to schema_linking`
restituisce solo evidence pertinenti.
- Live: una sessione F4 su psd usa un anchor canonico per il value-grounding invece del
solo LSH (verificabile dal `reviewer_decide` con opzioni `value_grounded` provenienti
dall'evidence, non dal ranking LSH).
- `git diff --check` e typecheck/ruff puliti.
@@ -1,6 +1,6 @@
# ThothII Authentication Acceptance and PSD Deployment Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to execute this plan task-by-task.
> **For agentic workers:** execute one task at a time, record its completion criteria, and stop at every documented approval boundary.
**Goal:** Validate local and OIDC authentication on macOS, deploy the exact feat/thoth-auth candidate to the Aritmolab/PSD server before merging it into main, and complete end-to-end acceptance with remote Authentik.
@@ -1,92 +0,0 @@
# Tht Documentation Convergence Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Align current documentation and documentation smoke checks with the converged native host CLI `tht`, while preserving historical references only where they describe past decisions or evidence.
**Architecture:** Treat `tools/tht/cmd/tht/main.go` as the canonical host CLI surface for installation, authentication, diagnostics, lifecycle, and workspace operations. Keep the Python `harness/.venv/bin/tht` distinction explicit for the workflow runtime, and update current operator/test instructions to invoke the native `tht` with `--installation`.
**Tech Stack:** Markdown documentation, shell smoke tests, Go CLI command surface, repository search-based verification.
---
### Task 1: Classify current and historical legacy CLI references
**Files:**
- Inspect: `README.md`, `PROJECT_STATE.md`, `AGENTS.md`, `docs/**`, `scripts/**`
- Reference: `tools/tht/cmd/tht/main.go`
**Step 1:** Build a complete occurrence inventory with a case-insensitive search for the former host CLI name and classify every match.
**Step 2:** Classify each occurrence as current operator documentation, documentation smoke expectation, executable/script contract, or historical design/evidence.
**Step 3:** Record the classification in the implementation notes before editing.
### Task 2: Update canonical operator and installation documentation
**Files:**
- Modify: `README.md`
- Modify: `AGENTS.md`
- Modify: `PROJECT_STATE.md`
- Modify: `docs/guida-utente.md`
- Modify: `docs/contracts/workspace-preprocessing-cli.md`
- Rename/update: `docs/contracts/tht-pi.md` as the current `tht` Pi contract
- Modify: relevant installation and architecture pages that expose operator commands
**Step 1:** Replace current host/operator invocations with `tht --installation ...`.
**Step 2:** Document the distinction between the native host CLI `tht` and the Python harness CLI invoked by the backend/runtime.
**Step 3:** Update command examples for `start`, `status`, `doctor`, `auth`, `workspace`, and `pi`.
**Step 4:** Add a short historical note only where a document must explain the former name.
### Task 3: Rewrite authentication acceptance and manual test instructions
**Files:**
- Modify: `docs/testing/authentication-manual-acceptance.md`
- Modify: `docs/plans/2026-08-18-thothii-authentication-acceptance-and-psd-deployment.md`
- Modify: `docs/install/authentication-local.md`
- Modify: `docs/install/authentication-oidc.md`
- Modify: `docs/install/authentik.md`
**Step 1:** Make `tht auth status`, `tht auth check`, `tht auth check --interactive`, and `tht doctor --json` the canonical terminal preflight.
**Step 2:** Use `tht status`, `tht start`, and `tht workspace inspect --workspace psd-clinical --json` for PSD deployment checks.
**Step 3:** Clarify that the P8 L2 gate is authentication-to-application integration through the first reviewer gate.
**Step 4:** Retain the prior functional test suite as a baseline and add only the authentication boundary smoke required for this acceptance.
### Task 4: Align documentation smoke tests
**Files:**
- Modify: `scripts/auth-docs-smoke.sh`
- Modify: `scripts/test-auth-docs-smoke.sh`
- Inspect/update: any current smoke script whose user-facing command examples still require the legacy CLI name
**Step 1:** Replace forbidden/current command assertions with `tht` equivalents.
**Step 2:** Preserve negative checks for obsolete authentication CLI wording.
**Step 3:** Run the positive and negative documentation fixtures.
### Task 5: Preserve or annotate historical material
**Files:**
- Inspect the historical discovery specification for context, without treating it as current operator documentation.
- Inspect: dated reports and archived acceptance scripts
**Step 1:** Do not rewrite historical titles, commit evidence, or old implementation names solely to erase history.
**Step 2:** Add a concise “historical nomenclature” note where an archived document could otherwise be mistaken for current instructions.
### Task 6: Verify the convergence
**Step 1:** Run `scripts/auth-docs-smoke.sh` and `scripts/test-auth-docs-smoke.sh`.
**Step 2:** Search active documentation for remaining legacy CLI references.
**Step 3:** Confirm every remaining match is either an explicit historical note, an ignored runtime directory name, or a non-document executable compatibility artifact.
**Step 4:** Run `git diff --check` and report the exact files changed plus any intentionally retained historical references.
@@ -1,6 +1,6 @@
# PSD Server Deployment Program Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
> **For agentic workers:** execute one task at a time, record its completion criteria, and stop at every documented approval boundary.
**Goal:** Replace the legacy PSD ThothII installation, prove the replacement with local authentication, and then integrate the accepted release with Supabase, Authentik, Nginx, the load balancer, and the Aritmolab sidebar.
@@ -1,6 +1,6 @@
# PSD Server Project A Standalone Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
> **For agentic workers:** execute one task at a time, record its completion criteria, and stop at every documented approval boundary.
**Goal:** Install a clean PSD ThothII stack with local authentication, direct read-only DWH access, internal Qdrant/Ollama, rebuilt preprocessing, and one completed F1-F8 work session.
@@ -1,6 +1,6 @@
# PSD Server Project B Authentik Integration Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
> **For agentic workers:** execute one task at a time, record its completion criteria, and stop at every documented approval boundary.
**Goal:** Convert the accepted Project A installation to public OIDC mode, store owned work sessions in the existing Supabase database's `thoth_sessions` schema, and restore the established Aritmolab-sidebar user journey through the load balancer and Nginx.
+1 -1
View File
@@ -1,6 +1,6 @@
# PSD Server Survey Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
> **For agentic workers:** execute one task at a time, record its completion criteria, and stop at every documented approval boundary.
**Goal:** Produce a non-mutating, redacted survey of the PSD server that resolves every path, owner, network boundary, credential location, and rollback prerequisite needed by Projects A and B.
@@ -1,7 +1,7 @@
# Ristrutturazione delle Evidence — disegno approvato
**Stato:** approvato il 24 agosto 2026
**Sostituisce:** `docs/plans/2026-08-18-evidence-canonica-design.md`
**Sostituisce:** il precedente disegno di Evidence canonica, disponibile nella storia Git
**Ambito:** authoring, revisione, pubblicazione, indicizzazione e uso runtime delle Evidence
## 1. Obiettivo
File diff suppressed because it is too large Load Diff