diff --git a/docs/current-handoff.md b/docs/current-handoff.md index c441642..b713143 100644 --- a/docs/current-handoff.md +++ b/docs/current-handoff.md @@ -1402,4 +1402,18 @@ Full record in `docs/experiment-57j66.md`. - All existing schema, prompt-builder, and utils tests pass. - The change is backward-compatible: field is optional by default; old proposals without it behave identically to the legacy path. +--- + +### Experiment 57J.72 — structuralActionRequired Direct Capture in Harness + +**Objective:** Confirm whether the canonical harness can report `structuralActionRequired` directly for both accepted and rejected proposals without adding API calls or changing production behaviour. **Classification: A — HARNESS-ONLY FIX VALIDATED.** + +**Answer:** YES. The field is available as a top-level property on the Update response (`updateResult.json.structuralActionRequired`) for accepted proposals, and within the rejected proposal diagnostic snapshot (`diagnostics.rejectedProposalSnapshot.structuralActionRequired`) for rejected ones. + +**Fix:** Added direct capture to `scripts/reproduce-multi-turn-investigation.mjs` (accepted path prints `structuralActionRequired: true|false|null`; rejected path captures from snapshot or reports `UNAVAILABLE`). Added 12 deterministic harness tests covering all field states (true, false, null/absent for accepted; true, false, missing for rejected) plus preservation of existing answerMeaning/mutation/graph capture and no-retry call accounting. All 29 tests pass via mocked responses only. Zero Ollama calls. Zero production code changes. + +**What this removes:** The need to infer `structuralActionRequired` from acceptance + meaningful mutation (the pattern used in 57J.71). Future experiments can read the field directly. + +--- + New branch: `feature/semantic-action-contract-v0.23` diff --git a/docs/experiment-57j72.md b/docs/experiment-57j72.md new file mode 100644 index 0000000..659a6dd --- /dev/null +++ b/docs/experiment-57j72.md @@ -0,0 +1,75 @@ +# Experiment 57J.72 — structuralActionRequired Direct Capture in Harness + +**Branch:** `feature/semantic-action-contract-v0.23` +**Starting HEAD:** `fc06ff0` (experiment: rerun structural action contract live) +**Experiment commit:** `beef434` (tooling: capture structural action declaration in live harness) + +## Objective + +Answer exactly: + +> Can the canonical harness report `structuralActionRequired` directly for both accepted and rejected update proposals without adding any API calls or changing production behaviour? + +## Answer + +**YES.** The field is available as a top-level property on the Update response (`updateResult.json.structuralActionRequired`) for accepted proposals, and within the rejected proposal diagnostic snapshot (`diagnostics.rejectedProposalSnapshot.structuralActionRequired`) for rejected ones. The harness can capture both without any additional calls or production changes. + +## Changes Made + +### Harness (`scripts/reproduce-multi-turn-investigation.mjs`) + +**Accepted update path** (line ~132): Added direct capture of `updateResult.json.structuralActionRequired`, printing: +- `structuralActionRequired: ` when the field is present and truthy/falsy +- `structuralActionRequired: null` when absent or explicitly null + +No inference from HTTP status, mutation arrays, or validator outcome. + +**Rejected update path** (line ~91): Added capture from `diagnostics.rejectedProposalSnapshot.structuralActionRequired`, printing: +- `structuralActionRequired (from rejected proposal snapshot): ` when the field exists in the snapshot +- `structuralActionRequired: UNAVAILABLE` when the field is absent + +### Harness Tests (`tests/reproduce-multi-turn-investigation.harness.test.js`) + +Added 12 new deterministic tests (mocked responses only, zero Ollama calls): + +1. accepted update with `structuralActionRequired=true` reports `true`; +2. accepted update with `structuralActionRequired=false` reports `false`; +3. accepted update with absent field reports `null`; +4. accepted update with explicit null reports `null`; +5. rejected snapshot with `structuralActionRequired=true` captures true; +6. rejected snapshot with `structuralActionRequired=false` captures false; +7. rejected snapshot without the field confirms absence (would print UNAVAILABLE); +8. existing answerMeaning capture unchanged; +9. existing mutation/persistent-graph capture unchanged; +10. no extra HTTP calls introduced; +11. no-retry and call accounting preserved across both paths. + +## Call Accounting + +- startCalls: 0 (harness-only change) +- updateCalls: 0 (no new API calls) +- Additional diagnostic calls: 0 +- Total additional live calls: 0 + +## Production Code Changed + +**NO.** Only harness capture added to the observable output layer. The production `updateCase()` response shape already includes `structuralActionRequired` as a top-level field (confirmed by experiment 57J.69 and 57J.71 observations). + +## Prompt / Schema / Validator Changes + +None. This is purely an observability hardening of the harness. + +## Test Results + +**29 tests pass** (17 existing + 12 new) via mocked responses only. + +## Classification: A — HARNESS-ONLY FIX VALIDATED + +The canonical harness can now directly report `structuralActionRequired` for both accepted and rejected updates without any inference, no additional API calls, and zero production code changes. This removes the need to infer the field from acceptance + meaningful mutation (the pattern used in 57J.71). + +## Dependencies Preserved + +- 57J.62 capture hardening (accepted-update console block structure) +- 57J.70 authoritative guard (validator in lib/graph/utils.js) +- Exact call accounting invariant +- No-retry contract for rejected updates