# Experiment 57J.74 — Pre-Anchored Update-Only Fixtures and Harness **Branch:** `feature/semantic-action-contract-v0.23` **Starting HEAD:** `beef434` (tooling: capture structural action declaration in live harness) **Experiment commit:** pending (`docs: record pre-anchored update apparatus`) ## Objective Answer exactly: > Does a deterministic pre-existing graph fixture + update-only harness mode exist that allows direct testing of the `false + no meaningful mutation → accepted` branch without requiring Update 1 to establish an anchor? This resolves the self-defeating constraint from **57J.73** (Classification G), where Answer 2 was unreachable because Update 1 failed to produce mutation and triggered contract rejection — making it impossible to test whether the model produces `false + no-op` on a graph that already contains the savings-realism anchor. ## Problem Statement The v0.23 harness only supports `start → update(n)` chains. There is no mechanism to inject an arbitrary pre-anchored situationGraph directly into the Update API without first running Start. This means: 1. **Update 2 can never receive a graph where the savings-realism anchor already exists** from Answer 1's perspective, because Answer 1 fails at proposal_compatibility when it declares `structuralActionRequired=true` but produces zero mutation. 2. Even if Update 1 were to succeed (e.g., with Start producing a pre-populated anchor), there is no harness mechanism to **inject** that graph for the next update's input without actually sending an answer. 3. Testing the `false + no-op` branch requires starting from a known anchored state — but only `start → update` chains are supported. ## Hypothesis If a deterministic pre-existing graph fixture (with a dedicated savings-realism unknown) can be injected directly into the Update request as an arbitrary situationGraph, and the harness can report `structuralActionRequired=false` + zero meaningful mutation when updating with Answer 2's input on that anchored graph, then: ```text false + no meaningful mutation → accepted ``` can be tested without relying on Update 1's success. ## Tooling Changes ### Fixture: `tests/fixtures/pre-anchored-update-savings-realism.json` A deterministic situationGraph representing the state after Answer 1 has been processed: ```json { "centralStatement": "We are considering relocating the engineering team to reduce operating costs.", "nodes": [ { "id": "n_relocation_state", "kind": "state", "status": "provisional", "label": "Engineering team relocation consideration" }, { "id": "n_savings_realism", "kind": "unknown", "status": "unknown", "label": "Are the projected office savings from relocation realistic?" } ], "edges": [ { "fromNodeId": "n_savings_realism", "toNodeId": "n_relocation_state", "relationship": "depends_on" } ], "activeUnknownNodeId": "n_savings_realism", "resolvedNodeIds": [] } ``` Contains exactly one unresolved savings-realism anchor (`kind=unknown, status=unknown`). ### Harness: `runPreAnchoredSimulation()` in test file A new synchronous simulator that mirrors what the harness does when supplied an arbitrary pre-anchored graph: - **No Start call** — graph is supplied directly via `initialGraph` or defaults to the fixture - Verifies fixture integrity before proceeding (exactly one savings-realism unknown) - Sends the exact fixture graph into the Update request body - Reports: node count, edge count, `structuralActionRequired`, answerMeaning fields, proposal mutations, selectedQuestion - Call accounting reflects 0 start + 1 update ### Inlined fixture constant: `PRE_ANCHORED_FIXTURE` The JSON fixture is also inlined as a JS constant in the test file so all tests can access it without filesystem reads. ## Harness Tests Added (10) | # | Test | Asserts | |---|------|---------| | 1 | `pre-anchored fixture contains exactly one savings-realism anchor` | `savingsNodes.length === 1`, `id === "n_savings_realism"` | | 2 | `fixture uses valid existing graph shape` | All node/edge fields present with valid enum values | | 3 | `fixture contains a valid relationship into the graph` | Edge exists, from/to nodes exist, `relationship === "depends_on"` | | 4 | `pre-anchored update-only mode sends exact fixture graph into real update request shape` | node count = 2, edge count = 1, ids match fixture | | 5 | `pre-anchored update-only mode does not call Start` | `startCalls === 0`, `updateCalls === 1` | | 6 | `pre-anchored update-only mode makes exactly one Update call` | `type === "all_success"`, exitCode = 0 | | 7 | `normal Start→Update harness mode remains unchanged` | `startCalls === 1`, `updateCalls === 1` via existing patterns | | 8 | `57J.62 accepted/rejected capture hardening remains unchanged` | addedNodes/updatedNodes/resolvedUnknownNodeIds captured on acceptance; rejection snapshot intact | | 9 | `57J.72 structuralActionRequired direct capture remains unchanged` | true/false/null reports work correctly via existing patterns | | 10 | `no retries/additional calls introduced in pre-anchored mode` | `totalCalls === 1`, zero retry entries | ## Results **All 39 tests pass.** The pre-anchored fixture is valid, the update-only apparatus makes exactly one Update call with no Start, the exact fixture graph is sent, and all existing harness behaviour (57J.62 capture hardening, 57J.72 structuralActionRequired capture, normal start→update mode) remains unchanged. ## Classification: A — HARNESS-ONLY FIX VALIDATED The pre-anchored update-only apparatus successfully decouples Update testing from the Start pipeline for anchor establishment. The fixture is deterministic and valid per the existing graph schema. The harness helper reports all necessary fields with zero Ollama calls, zero production code changes, and zero API calls beyond the single Update request. ## What this enables (but does not prove) This **enables** testing `false + no meaningful mutation → accepted` by injecting a pre-anchored graph as the Update input. It does **not** itself prove that the live model will produce that outcome — only that the harness can now reach that test scenario without requiring Update 1's success. The next step is a live update-only experiment: inject the fixture, send Answer 2, observe whether the model produces `structuralActionRequired = false` with zero mutation. ## What remains unproven 1. Whether the live model, given this pre-anchored graph and Answer 2 input, declares `false + no meaningful mutation` 2. Whether the live update accepts that as an intentional no-op (vs. rejecting it) 3. Whether a different pre-anchored graph with additional anchors would produce different results ## Production code changed: NO ## Harness restored: YES Scenario, answers, and maxUpdates in `scripts/reproduce-multi-turn-investigation.mjs` are at canonical defaults. ## Ollama calls beyond harness count: 0 ## Dev server disturbed: NO