/** * RTO.26B — Branch-scoped experimental fixture * * Replicates the RTO.26A branch record inside the UI layer. * Membership is determined by explicit `branchId` provenance only. * * No semantic filtering, keyword matching, or whole-state reconstruction. */ // ── Deterministic ID generator (mirrors RTO.26A harness) ─────────────── function genId(prefix, label) { let h = 0; for (let i = 0; i < label.length; i++) { h = (Math.imul(31, h) + label.charCodeAt(i)) | 0; } return `${prefix}-${(Math.abs(h) % 1e6).toString(16).padStart(6, "0")}`; } // ── Record model (explicit provenance via `branchId`) ───────────────── function createQuestion(branchId, text) { return { id: genId("question", text.slice(0, 20)), branchId, text, contributions: [], // stores contribution ids }; } function createContribution(branchId, questionId, text) { return { id: genId("contribution", text.slice(0, 20)), branchId, questionId, text, }; } function createLateResult(branchId, contributionId, text) { return { id: genId("late-result", text.slice(0, 20)), branchId, contributionId, text, }; } // ── Fixed fixture data (mirrors RTO.26A stages 1–5) ─────────────────── function buildBranchScopedFixture() { const records = []; // Branch A: Competitor development const qA1 = createQuestion( "branch-competitor-development", "What evidence suggests competitors are actively developing similar products?" ); records.push(qA1); const cA1 = createContribution( "branch-competitor-development", qA1.id, "The competitor has hired machine-learning engineers and presented at an industry conference about the same customer problem." ); records.push(cA1); qA1.contributions.push(cA1.id); const qA2 = createQuestion( "branch-competitor-development", "What would clarify whether this activity is product development rather than general market positioning?" ); records.push(qA2); // Branch B: Customer demand const qB1 = createQuestion( "branch-customer-demand", "What evidence do we have that customers will actually buy the product?" ); records.push(qB1); const cB1 = createContribution( "branch-customer-demand", qB1.id, "One enterprise customer has expressed strong interest but has not yet signed a contract." ); records.push(cB1); qB1.contributions.push(cB1.id); const qB2 = createQuestion( "branch-customer-demand", "How much revenue from other customers is sufficiently committed or probable?" ); records.push(qB2); // Late result scoped to Branch A / Contribution A1 (stage 5) const lateResultA1 = createLateResult( "branch-competitor-development", cA1.id, "This later interpretation relates to Contribution A1." ); records.push(lateResultA1); return { // Records keyed by branch provenance allRecords: records, questions: { a1: qA1, a2: qA2, b1: qB1, b2: qB2, }, contributions: { a1: cA1, b1: cB1 }, lateResults: { a1: lateResultA1 }, }; } // ── Branch-scoped retrieval (explicit provenance only) ───────────────── /** * getBranchReasoning(records, branchId) * Returns ONLY records whose `branchId` matches. No semantic filtering. */ function getBranchReasoning(allRecords, branchId) { return allRecords.filter(r => r.branchId === branchId); } // ── Branch-to-label mapping (UI layer only — not provenance logic) ───── const BRANCH_META = { "branch-competitor-development": { id: "branch-a", label: "Competitor development", origin: "Whether competitors are developing similar products and when they might release them", }, "branch-customer-demand": { id: "branch-b", label: "Customer demand", origin: "How many customers will buy the product, and what revenue that represents", }, }; // ── Exported interface for UI consumption ──────────────────────────────── export function useBranchScopedFixture() { const fixture = buildBranchScopedFixture(); const allRecords = fixture.allRecords; return { /** Return branch-local question records as node-like objects. */ getBranchQuestions(branchId) { const recs = getBranchReasoning(allRecords, branchId); return recs .filter(r => !r.questionId && !r.id.startsWith("late")) .map(q => ({ id: q.id, label: q.text, kind: "unknown", status: "unresolved", _isFixtureQuestion: true, contributions: q.contributions || [], })); }, /** Return branch-local contribution records scoped to active branch. */ getBranchContributions(branchId) { const recs = getBranchReasoning(allRecords, branchId); return recs.filter(r => r.questionId && !r.id.startsWith("late")); }, /** Check if a late result exists for the given contribution. */ hasLateResult(contributionId) { return Object.values(fixture.lateResults).some(lr => lr.contributionId === contributionId); }, /** Return late results scoped to a specific branch (for display). */ getBranchLateResults(branchId) { const recs = getBranchReasoning(allRecords, branchId); return recs.filter(r => r.id.startsWith("late")); }, /** Branch metadata for UI labels. */ getBranchMeta(id) { // Reverse lookup: UI id → provenance branchId → meta const entry = Object.entries(BRANCH_META).find( ([, m]) => m.id === id ); return entry ? { ...entry[1] } : null; }, /** Return the fixed two-branch list for the switcher. */ getBranches() { return Object.values(BRANCH_META).map(m => ({ ...m })); }, /** Return all inferred questions across branches (flat list for post-Analyse surface). */ getAllInferredQuestions() { const qA1 = this._qA1; const qA2 = this._qA2; const qB1 = this._qB1; const qB2 = this._qB2; if (!qA1 || !qA2 || !qB1 || !qB2) return []; return [ { id: qA1.id, text: qA1.text, branchId: "branch-competitor-development" }, { id: qA2.id, text: qA2.text, branchId: "branch-competitor-development" }, { id: qB1.id, text: qB1.text, branchId: "branch-customer-demand" }, { id: qB2.id, text: qB2.text, branchId: "branch-customer-demand" }, ]; }, /** Return all records (for verification / debugging). */ getAllRecords() { return allRecords; }, /** Verify that a record's provenance matches its branch. */ verifyProvenance(record, expectedBranchId) { return record?.branchId === expectedBranchId; }, // ── RTO.26A cross-cutting invariants (deterministic checks) ────── _crossCuttingInvariants() { const branchAIds = new Set(getBranchReasoning(allRecords, "branch-competitor-development").map(r => r.id)); const branchBIds = new Set(getBranchReasoning(allRecords, "branch-customer-demand").map(r => r.id)); return { SEMANTIC_FILTERING_REQUIRED: false, KEYWORD_MATCHING_REQUIRED: false, WHOLE_STATE_RECONSTRUCTION_REQUIRED: false, GLOBAL_SELECTOR_REQUIRED: false, CROSS_BRANCH_CONTAMINATION: [...branchAIds].some(id => branchBIds.has(id)), NEXT_QUESTION_SELECTED: false, }; }, // Expose fixture for inspection (RTO.26A stages 1–5) _fixtureRecords: allRecords, _qA1: fixture.questions.a1, _qA2: fixture.questions.a2, _qB1: fixture.questions.b1, _qB2: fixture.questions.b2, _cA1: fixture.contributions.a1, _cB1: fixture.contributions.b1, _lateResultA1: fixture.lateResults.a1, }; } export { buildBranchScopedFixture };