chore: commit remaining worktree changes
This commit is contained in:
@@ -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,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
Reference in New Issue
Block a user