diff --git a/.superpowers/sdd/onboarding-cache-fix-report.md b/.superpowers/sdd/onboarding-cache-fix-report.md index b3331611..31384416 100644 --- a/.superpowers/sdd/onboarding-cache-fix-report.md +++ b/.superpowers/sdd/onboarding-cache-fix-report.md @@ -263,3 +263,31 @@ Staged follow-up audit ran `git diff --cached --check`, `--name-status`, and `-- passed, and the staged set contained exactly nine follow-up paths: this report, the production route adapter, handler, payload boundary, route fake/test, policy test, candidate test, and root CI contract. Unrelated `.superpowers/sdd/task-1-report.md` and `.omo/` remained unstaged. + +## Review cleanup: behavioral authority + +The post-review cleanup removes implementation-text assertions from the root Python contract and +leaves stateful TypeScript route tests as the authority for cache claim and completion behavior. +Broad UI, authentication, migration, and structured suggestion-marker coverage remains in the +Python contract; exact natural-language prompt prose is no longer pinned there. + +The one-use `createOnboardingCompletionTransition` wrapper and its tautological unit test were +removed. The handler now passes `identity.pendingVersion` and `identity.readyVersion` directly to +the repository completion command. This is a refactor only, so the existing route integration +matrix provided the behavior-preservation check rather than adding a new RED case. + +### Cleanup verification + +- Focused route, policy, and candidate-completion tests: exit 0; 30 passed, 0 failed. +- Full frontend suite: exit 0; 454 passed, 0 failed. +- Python agent-chat contract: exit 0; 2 passed. +- Changed-file ESLint and Ruff: exit 0 with zero diagnostics. +- Webpack production build: exit 0; compiled successfully, TypeScript completed, and 22/22 pages + generated. +- `git diff --check`: exit 0. +- Pure LOC: cache policy 70, onboarding handler 182, policy test 154, and root contract 69; every + modified code/test file remains below 200 pure LOC. + +The build continues to use repository-standard CI placeholder Supabase values and webpack because +the worktree's external dependency symlink is incompatible with default Turbopack. No new concern +was introduced by this cleanup. diff --git a/frontend/src/lib/onboarding-cache-policy.ts b/frontend/src/lib/onboarding-cache-policy.ts index 5cc73ac9..c37ba07d 100644 --- a/frontend/src/lib/onboarding-cache-policy.ts +++ b/frontend/src/lib/onboarding-cache-policy.ts @@ -19,11 +19,6 @@ export type OnboardingCacheIdentity = { readonly pendingVersion: string; }; -export type OnboardingCompletionTransition = { - readonly expectedVersion: string; - readonly readyVersion: string; -}; - type OnboardingCacheObservation = { readonly identity: OnboardingCacheIdentity; readonly observedVersion: string | null; @@ -83,12 +78,3 @@ export function decideOnboardingCache( pendingVersion: observation.identity.pendingVersion, }; } - -export function createOnboardingCompletionTransition( - identity: OnboardingCacheIdentity, -): OnboardingCompletionTransition { - return { - expectedVersion: identity.pendingVersion, - readyVersion: identity.readyVersion, - }; -} diff --git a/frontend/src/lib/onboarding-post.ts b/frontend/src/lib/onboarding-post.ts index 9627506c..4748fcd1 100644 --- a/frontend/src/lib/onboarding-post.ts +++ b/frontend/src/lib/onboarding-post.ts @@ -1,6 +1,5 @@ import { createOnboardingCacheIdentity, - createOnboardingCompletionTransition, decideOnboardingCache, } from "./onboarding-cache-policy.ts"; import { @@ -181,11 +180,10 @@ export function createOnboardingPost(dependencies: OnboardingPostDependencies): ); } - const completion = createOnboardingCompletionTransition(identity); const completed = await session.repository.completeProfile({ userId: session.userId, - expectedPendingVersion: completion.expectedVersion, - readyVersion: completion.readyVersion, + expectedPendingVersion: identity.pendingVersion, + readyVersion: identity.readyVersion, payload, generatedAt: dependencies.now().toISOString(), }); diff --git a/frontend/tests/onboarding-cache-policy.test.ts b/frontend/tests/onboarding-cache-policy.test.ts index 926f87e4..2a79c3b1 100644 --- a/frontend/tests/onboarding-cache-policy.test.ts +++ b/frontend/tests/onboarding-cache-policy.test.ts @@ -2,7 +2,6 @@ import assert from "node:assert/strict"; import test from "node:test"; import { createOnboardingCacheIdentity, - createOnboardingCompletionTransition, decideOnboardingCache, ONBOARDING_CLAIM_TTL_MS, } from "../src/lib/onboarding-cache-policy.ts"; @@ -64,22 +63,6 @@ test("changed profile cannot wait on the previous profile's active pending claim }); }); -test("stale profile completion loses ownership after the current profile claims", () => { - // Given: B has replaced A's pending identity in the row. - const identityA = createOnboardingCacheIdentity(profileA); - const identityB = createOnboardingCacheIdentity({ ...profileA, cityCode: "310100" }); - const rowVersionAfterBClaims = identityB.pendingVersion; - - // When: each completion prepares an exact compare-and-set transition. - const completionA = createOnboardingCompletionTransition(identityA); - const completionB = createOnboardingCompletionTransition(identityB); - - // Then: A cannot match the row, while B can commit its own ready identity. - assert.notEqual(rowVersionAfterBClaims, completionA.expectedVersion); - assert.equal(rowVersionAfterBClaims, completionB.expectedVersion); - assert.equal(completionB.readyVersion, identityB.readyVersion); -}); - test("current profile accepts only valid ready content and an active current pending claim", () => { // Given: one current profile identity and a valid cached payload. const identity = createOnboardingCacheIdentity(profileA); diff --git a/tests/test_agent_chat_contract.py b/tests/test_agent_chat_contract.py index 19811549..2b4e48fb 100644 --- a/tests/test_agent_chat_contract.py +++ b/tests/test_agent_chat_contract.py @@ -5,10 +5,6 @@ PAGE = ROOT / "frontend" / "src" / "app" / "page.tsx" AGENT = ROOT / "frontend" / "src" / "mastra" / "index.ts" ONBOARDING_ROUTE = ROOT / "frontend" / "src" / "app" / "api" / "onboarding" / "route.ts" ONBOARDING_CLIENT = ROOT / "frontend" / "src" / "lib" / "onboarding-client.ts" -ONBOARDING_POST = ROOT / "frontend" / "src" / "lib" / "onboarding-post.ts" -ONBOARDING_CACHE_POLICY = ( - ROOT / "frontend" / "src" / "lib" / "onboarding-cache-policy.ts" -) CONSULT_ROUTE = ROOT / "frontend" / "src" / "app" / "api" / "consult" / "route.ts" MODELS_ROUTE = ROOT / "frontend" / "src" / "app" / "api" / "models" / "route.ts" MODEL_SELECTION = ROOT / "frontend" / "src" / "lib" / "consultation-model-selection.ts" @@ -29,8 +25,6 @@ def test_onboarding_and_agent_suggestion_contract() -> None: agent = AGENT.read_text(encoding="utf-8") route = ONBOARDING_ROUTE.read_text(encoding="utf-8") onboarding_client = ONBOARDING_CLIENT.read_text(encoding="utf-8") - onboarding_post = ONBOARDING_POST.read_text(encoding="utf-8") - cache_policy = ONBOARDING_CACHE_POLICY.read_text(encoding="utf-8") consult_route = CONSULT_ROUTE.read_text(encoding="utf-8") migration = ONBOARDING_MIGRATION.read_text(encoding="utf-8") @@ -54,32 +48,12 @@ def test_onboarding_and_agent_suggestion_contract() -> None: assert "export function getOnboardingAgent" in agent assert "skills: [jyotishSkillPath]" in agent - assert "This is onboarding, not a chart reading" in agent assert "