# Task 7 report — revision-pinned sessions ## Delivered - New-session requests may carry `workspaceId`, provider, model, and thinking. The backend resolves the active operational registry revision, enforces its LLM policy, and persists the workspace ID/revision with the selected LLM settings. - The harness manifest and `tht session new` support the optional, backward-compatible `workspace_id` and `workspace_revision` fields. - Resume resolves the manifest's retained snapshot, including after later registry publication. A missing retained revision returns a sanitized `workspace_revision_unavailable` response. Legacy manifests retain the prior workspace behavior and are marked with a visible warning on `GET /sessions/:id`. - `/settings` is now a non-mutating compatibility endpoint: installation defaults remain readable, while anonymous workspace/provider/model/thinking selections are no longer written to backend settings or principal preferences. ## TDD evidence - RED: `npx vitest run test/routes-sessions.test.ts test/routes-settings.test.ts` failed for the new immutable-snapshot and no-settings-mutation assertions; the manifest test failed because `new_session_manifest` did not accept workspace revision fields. - GREEN: `npx vitest run test/tht-runner.test.ts test/routes-sessions.test.ts test/routes-settings.test.ts && npx tsc --noEmit -p .` completed with 97 passing tests and a clean type check. - GREEN: `THT_HOME=/private/tmp/thothii-task7-home .venv/bin/pytest tests/test_session_documents.py tests/test_session_mutations.py -q` completed with 22 passing tests. - `git diff --check` completed cleanly. ## Review fixes — round 3 - The active registry snapshot that located a session now remains the authorization and mutation config for response, steer, events, close/delete, archive/group/rename, documents, and detail. A pruned historical revision cannot block an already-located session's active lifecycle. - Only Resume resolves the retained pinned descriptor because Pi needs that immutable config to restart safely. A pruned pin therefore returns the existing sanitized `workspace_revision_unavailable` 409 solely for Resume. ### Round 3 verification - RED: with a manifest found through an active registry snapshot and `readPinned` forced to fail, `POST /sessions/:id/response` returned 409 instead of forwarding the active gate response. - GREEN: `npx vitest run test/routes-sessions.test.ts test/tht-runner.test.ts test/routes-settings.test.ts && npx tsc --noEmit -p .` — 102 tests passed with a clean type check. The regression confirms response, close, and delete use the locating snapshot without calling `readPinned`, while Resume returns a sanitized 409. - `git diff --check` completed cleanly. ## Review fixes — round 2 - Lifecycle authorization no longer selects the installation-default workspace. The backend now finds each session by querying every operational registry snapshot with the authenticated principal, preserving RLS ownership concealment. - After locating the manifest, durable pinned sessions resolve their retained descriptor before any lifecycle mutation/reopen. Legacy sessions continue using the locating registry snapshot. - Session listing aggregates the owner-visible rows from all operational registry snapshots; detail, response, steer, resume, events, documents, and lifecycle mutations use the same server-side locator. No route depends on browser-local workspace state. ### Round 2 verification - RED: the new cross-workspace route integration test created a B session while installation default A was selected, then demonstrated that `GET /sessions` returned an empty list. - GREEN: `npx vitest run test/routes-sessions.test.ts test/tht-runner.test.ts test/routes-settings.test.ts && npx tsc --noEmit -p .` — 101 tests passed with a clean type check. The integration test covers create B, list, detail, response, and resume through B's pinned descriptor while default A remains configured. - Full backend suite: 342 tests passed. The remaining 7 tests require binding `127.0.0.1` and fail in this sandbox with `listen EPERM: operation not permitted`; no application assertion failed. The focused typecheck above passed. - `git diff --check` completed cleanly. ## Verification note The unscoped backend suite was also run. The Task 7 code regressions in `test/tht-runner.test.ts` were fixed; the remaining failures were existing sandbox restrictions on tests that listen on `127.0.0.1` (`listen EPERM: operation not permitted` in SSE/e2e health tests), not application assertions. ## Review fixes — round 1 - Every new session now resolves `workspaceId` through the registry; an omitted value uses the configured installation default and persists both the resolved ID and revision. Callers cannot bypass revision pinning by supplying a workspace ID. - Browser-local preferences now migrate once from the read-only legacy settings response and hold workspace, provider, model, and thinking. Session creation includes those selections, including direct entry points that run before the composer mounts. The frontend no longer `PUT`s shared settings. - The settings compatibility endpoint honors a stored installation workspace before falling back to the first workspace configuration. - Resume rejects finalized and archived sessions before looking up any pinned snapshot, preserving the read-only response even when a historical snapshot is unavailable. ### Review verification - RED: the added backend tests failed for omitted-default pinning, read-only resume ordering, and stored-default precedence; the added frontend preference tests failed because preferences were neither stored nor included in session requests. - GREEN: `npx vitest run test/tht-runner.test.ts test/routes-sessions.test.ts test/routes-settings.test.ts && npx tsc --noEmit -p .` — 100 tests passed with a clean type check. - GREEN: `npx vitest run && npx tsc -b` — 332 frontend tests passed with a clean type check. - GREEN: `THT_HOME=/private/tmp/thothii-task7-home .venv/bin/pytest tests/test_session_documents.py tests/test_session_mutations.py -q` — 22 tests passed (one existing testcontainers deprecation warning). - `git diff --check` completed cleanly.