9.5 KiB
9.5 KiB
Task 3 — TypeScript Engine Adapter and Trust Boundary
Implementation
- Added snake-case serializers for dynamic opportunity and deterministic choice-scoring requests. Only server-resolved
ServerChoiceEvidencebecomespartition_id/candidate_scores; client option IDs and confidence fields are never serialized. - Added strict dynamic response adapters. Opportunity responses are versioned, endpoint-bound, exact-field parsed, and split into a model-safe
packet, privatecandidateModel, and privatescoringPartitions. - Candidate score maps must contain finite nonnegative values keyed by exactly every minute in the submitted range, including cross-midnight ranges. Duplicate opportunity/partition IDs and unexpected response fields are rejected.
- Dynamic scoring responses require
birth-time-choice-scoring-v2,dynamic_choiceevidence mode, empty public evidence, matching compatibility/effective counts, and the existing deterministic candidate safety gates. - Added authenticated server-only engine calls for both dynamic Python endpoints. They fail before fetch when
JYOTISH_DYNAMIC_RECTIFICATION_TOKENis absent and send the configured value only as a bearer header. Legacy scan, questionnaire score, and dated-event score calls remain unauthenticated. - Extended the legacy-compatible engine contract with optional dynamic methods and added
DynamicBirthTimeJourneyEngine, where both methods are required. The production factory returns the required dynamic subtype while existing legacy-only test doubles remain source-compatible. - Raised only the shared candidate-result compatibility cap from 6 to 10 and changed the high-gate message to “effective evidence items.” The dated-event request contract remains capped at 6.
- Added source-contract coverage preventing snake-case or camel-case candidate model, partition, score, and token identifiers from entering client, request, response, component, or hook modules.
Files changed
frontend/src/lib/birth-time-journey-service.tsfrontend/src/lib/birth-time-journey-engine.tsfrontend/src/lib/birth-time-journey-adapters.tsfrontend/src/lib/birth-time-journey-engine-model.tsfrontend/src/lib/birth-time-evidence.tsfrontend/tests/birth-time-journey-engine.test.tsfrontend/tests/birth-time-journey-adapters.test.ts.superpowers/sdd/task-3-report.md
RED
- Bundled Node focused run:
/Users/jesse/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node --test tests/birth-time-journey-engine.test.ts tests/birth-time-journey-adapters.test.ts- Failed during module instantiation because
parseCandidateDifferenceBuildandparseDynamicChoiceScoringdid not exist. Baseline result: 1 pass, 1 file-load failure.
- After the first adapter implementation, the malformed score-key regression failed because a response containing
candidate_scores: { "not-a-time": 1 }was accepted. - The exact-range regression then failed because an otherwise valid
05:34score key could be added outside the05:30—05:33range. - The initial source-level legacy-auth assertion was too broad and matched the next dynamic method. It was narrowed to the exact legacy method section; production behavior did not change for this test-only correction.
GREEN
- Focused Task 3 suite:
/Users/jesse/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node --test tests/birth-time-journey-engine.test.ts tests/birth-time-journey-adapters.test.ts- 21 passed, 0 failed.
- Complete birth-time frontend regression suite:
/Users/jesse/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node --test tests/birth-time*.test.ts- 207 passed, 0 failed.
- Focused ESLint over all Task 3 source and test files:
/Users/jesse/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node node_modules/eslint/bin/eslint.js ...- Passed with no diagnostics.
- TypeScript diagnostic:
/Users/jesse/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node node_modules/typescript/bin/tsc --noEmit --pretty false- No Task 3 diagnostics. It reproduces only the existing baseline
TS1501intests/profile-persistence.test.ts:7because the project targets ES2017 while that test uses an ES2018 regex flag.
git diff --check- Passed with no whitespace errors.
Pre-work gate
- Ran
/Users/jesse/Downloads/Copse/astrology/yinduzhanxing/.venv/bin/python scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45after reading both required sweep documents and the error ledger. - The gate remained red only on the unrelated known fragment-governance baseline:
candidate_countexpected0, observed1. Remote visibility was blocked, so no cloud-sync claim is made.
Self-review
- Dynamic secrets and score vectors stay behind the existing server-only engine entrypoint. The public dynamic packet deliberately drops
candidateScores, while the private partition map retains the exact server vector for later binding. - Both response adapters are strict at their dynamic endpoint roots; model-controlled extra fields cannot be silently retained.
- The dynamic scorer cannot elevate confidence by mismatching effective counts, dimensions, evidence mode, evidence contents, algorithm version, or the existing high-confidence candidate gates.
- Cross-midnight ranges enumerate minutes modulo 24 hours, preventing a valid
23:59—00:00result from being rejected or split. - Legacy request payloads, endpoints, timeout, parsing behavior, and authentication remain unchanged. The event request schema remains at 6 even though the shared result compatibility schema can represent the v2 cap of 10.
- No dependency, logging, model prompt field, client response field, or persistence write was added.
Concerns
- The repository still lacks a standalone runtime
server-onlypackage for direct Node imports. Per the approved module-boundary decision, verification uses the production file's existingimport "server-only"plus strict projection and source-contract tests rather than adding an unavailable dependency. - The complete TypeScript diagnostic remains blocked by the unrelated ES2017/ES2018 regex baseline described above.
Review fixes
- Restored byte-compatible legacy candidate parsing. Unknown nested evidence metadata is accepted and stripped exactly as before Task 3; dynamic response parsing no longer changes the legacy schema.
- Moved every v2 response schema, invariant, and mapping into
birth-time-journey-dynamic-adapters.ts. Root responses, ranges, opportunities, partitions, and winning segments are strict; empty dynamic evidence is enforced before candidate construction. - Split dynamic adapter regressions into
birth-time-journey-dynamic-adapters.test.ts. Added duplicate opportunity/partition attacks, nested extra-field attacks, exact-range keys, cross-midnight mapping, and independent expected-value assertions. - Made
buildDifferencePacketandscoreChoicesrequired on the primaryBirthTimeJourneyEngine. Existing services use the explicitLegacyBirthTimeJourneyEnginepick, and legacy-only test doubles were narrowed without runtime behavior changes. - Refactored HTTP execution into
createJourneyEngineWire, whosepostaccepts one typed request object. The server-only factory remains the environment owner; engine assembly is injectable for executable fake-fetch verification without adding the unavailableserver-onlyruntime dependency. - Replaced greedy source-regex authentication tests with executable coverage for both exact dynamic URLs, serialized bodies, POST method, bearer header, 45-second abort signal, and missing-token zero-fetch behavior. All three legacy engine endpoints execute without an Authorization header.
- Removed newly introduced non-null assertions and narrowed the ownership scan to the client/request/component/hook boundary named by the plan.
- Kept every modified production and test TypeScript module at or below 250 pure LOC. The largest is
birth-time-journey-test-support.tsat 249; Task 3 production modules range from 19 to 239.
Review RED
- The legacy compatibility regression failed with
unrecognized_keyswhen an existing engine evidence item contained extra server metadata. - The new dynamic adapter suite failed to load because the protocol-specific module did not yet exist.
- Independent review probes had shown nested dynamic
winning_segmentextras were silently stripped, optional primary engine methods weakened consumers, and the source-regex auth proof could remain green after removing authentication from one endpoint.
Review GREEN
- Focused legacy/dynamic/wire suite:
/Users/jesse/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node --test tests/birth-time-journey-engine.test.ts tests/birth-time-journey-adapters.test.ts tests/birth-time-journey-dynamic-adapters.test.ts- 24 passed, 0 failed.
- Complete birth-time suite:
/Users/jesse/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node --test tests/birth-time*.test.ts- 210 passed, 0 failed.
- Full frontend suite:
/Users/jesse/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node --test tests/*.test.ts- 285 passed, 0 failed.
- Focused ESLint across all changed production/test TypeScript modules:
- Passed with no diagnostics.
- TypeScript diagnostic:
- No Task 3 diagnostics; only the known
tests/profile-persistence.test.ts:7 TS1501baseline remains.
- No Task 3 diagnostics; only the known
- Pure-LOC audit and
git diff --check:- Every changed TypeScript file is at or below 250 pure LOC; no whitespace errors.