The AM-1 coverage gate failed the build on GR-P05 being uncovered, which is what showed the rule was in the offer layer rather than in validate. A rule enforced only by the offer is enforced only for clients that ask what is legal. The gate did not catch a bug, it caught a design error. And the reported case was not the one reported. CB-WP-0018, CB-EV-0016 and the message to ground-game all described SOLVE offered on a face-down Problem; validate already rejected face-down, so it never was. Problem 1 is the Surface Problem, face-up from the deal, so the three inert SOLVEs were the HAND case. The ruling covers both so nothing is invalidated, but a ruling was requested on a wrong description -- the second time in three passes that a premise reached ground-game unchecked, after the '12 points available' that voided GR-E01. Two of two. The pattern is not careless analysis; it is that a claim gets SENT the moment it is interesting and checked afterwards. Unexecuted verification, one step further out: not a belief acted on, but a belief published. CB-WP-0022's reproduction rule would have caught both. An earlier mutation run reported three survivors and was wrong -- the replacement strings did not match, so nothing was mutated. It proved nothing and looked like a result. Also renames CB-WP-0022-T06B to T07; the hub flagged it as an unregistered species. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
138 lines
5.6 KiB
Markdown
138 lines
5.6 KiB
Markdown
---
|
|
id: CB-WP-0023
|
|
kind: product
|
|
title: "SOLVE is offered only where it can do something"
|
|
status: done
|
|
state_hub_workstream_id: "ae3a1491-4417-4cb2-b490-b694463cc171"
|
|
---
|
|
|
|
# Purpose
|
|
|
|
```
|
|
structural tier S (implements a ruling inside an existing capability —
|
|
no new port, no canonical interface, no dependency)
|
|
chaos d8 = 6 → no override
|
|
declared tier S
|
|
```
|
|
|
|
Declaration 6 of chaos window 2.
|
|
|
|
## A ruling, not a judgment call
|
|
|
|
`ground-game` ruled SOLVE's legality on 2026-08-03 (GROUND-WP-0002 T02),
|
|
after clay-borg raised it from play:
|
|
|
|
| sub | ruling |
|
|
|---|---|
|
|
| **(a)** face-down Problem | **Not offered — illegal target.** *"only face-up, non-Denied. Browser no-ops were a filter bug, not a bluff mechanic."* |
|
|
| **(b)** no matching Solution in hand | **Not offered.** *"the engine only offers SOLVE when a matching suit is held."* |
|
|
| **(c)** already-claimed Problem | **Same-round race legal; prior-round claim not offered.** |
|
|
|
|
**The bluff reading is dead.** CB-WP-0018 raised (a) as *possibly* an
|
|
intended bluff in a commit/reveal game and deferred to ground-game rather
|
|
than deciding. The answer is that it was a filter bug, and the engine has
|
|
been offering an inert move since the day `legal_commands` was written.
|
|
|
|
`legal_commands` offers Investigate and SOLVE on **every** problem key,
|
|
with no reference to `face_up`, `denied`, `claimed_by` or the hand.
|
|
|
|
**Only SOLVE is ruled on. Investigate is not touched** — implementing more
|
|
than was ruled would be inventing rules, which is what this whole exchange
|
|
exists to stop.
|
|
|
|
## Task: filter SOLVE to what the ruling allows
|
|
|
|
```task
|
|
id: CB-WP-0023-T01
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "52637f6f-314f-4715-9d81-5e9bea8ced97"
|
|
```
|
|
|
|
SOLVE is offered on problem `p` for seat `s` **iff** `p.face_up`,
|
|
`!p.denied`, `p.claimed_by.is_none()`, and `s`'s hand holds a card of
|
|
`p.suit`.
|
|
|
|
On (c): at Select time every `claimed_by` is from a prior round — claims
|
|
land at Resolve — so *"prior-round claim not offered"* is exactly
|
|
`claimed_by.is_none()`, and the same-round race is already legal because
|
|
both seats select before either resolves. **Say this in the code**, or the
|
|
next reader will add a round comparison that does nothing.
|
|
|
|
**Controls:**
|
|
- each of the four conditions must be independently mutation-provable —
|
|
drop one filter, and a test naming *that* condition goes red;
|
|
- the maintainer's reported case must be reproduced and then fixed: SOLVE
|
|
on a face-down Problem is offered before, not offered after;
|
|
- **`make sim` must still pass**, or the ruling has broken a scenario that
|
|
encoded the old behaviour — in which case the scenario was encoding a
|
|
bug and must be updated with a note, not quietly edited.
|
|
|
|
**Done 2026-08-04.** `make all` exits 0, 26 scenarios, rule coverage
|
|
**59/59**. **No scenario encoded the bug** — all 25 passed unchanged.
|
|
|
|
**The rule ended up somewhere other than where I put it, and a gate moved
|
|
it.** It went into `legal_commands` first. The AM-1 coverage gate then
|
|
demanded a scenario for the new GR-P05 — and scenarios drive `validate`,
|
|
not the offer layer. That is what showed the rule belonged in `validate`:
|
|
**a rule enforced only by the offer is enforced only for clients that ask
|
|
what is legal.** The browser would have been filtered and a scenario file
|
|
would have walked straight past it.
|
|
|
|
Once GR-P05 moved into `validate`, every condition in `legal_commands`
|
|
was dead code, and my own layering test said so in those words
|
|
(*"validate now rejects claimed — drop the filter"*). The offer layer is
|
|
back to one arm for Investigate and SOLVE together.
|
|
|
|
**And the reported case was not the one I reported.** CB-WP-0018 and the
|
|
message to ground-game described SOLVE offered on a **face-down** Problem.
|
|
Measured: `validate` already rejected face-down, so it never was offered.
|
|
Problem 1 is the Surface Problem and is face-up from the deal — the
|
|
maintainer's three inert SOLVEs were the **hand** case, holding no Clarify
|
|
for a Clarify Problem. The ruling covers both, so nothing is invalidated,
|
|
but the record was wrong and is corrected here.
|
|
|
|
Four conditions, each asserted separately, because one "SOLVE is filtered"
|
|
test would pass with three of four implemented. Mutations: dropping the
|
|
claimed filter and dropping the hand filter each turn their own test red;
|
|
inverting the layering assertion turns `validate_enforces_all_four` red.
|
|
|
|
## Task: retire what the ruling settles
|
|
|
|
```task
|
|
id: CB-WP-0023-T02
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "4a436635-2eff-42b1-957c-fdb8b310f910"
|
|
```
|
|
|
|
Update `specs/GroundRules.md` §Underdetermined for the SOLVE items, and
|
|
retire the provisional flags the ruling closes. **A ruling that lands in
|
|
code but not in the spec leaves the next reader with two sources.**
|
|
|
|
Report to `ground-game` that the ruling is implemented — closing the loop
|
|
is the part that has failed twice.
|
|
|
|
**Done 2026-08-04.** `specs/GroundRules.md` gains **GR-P05** stating the
|
|
rule and recording that the bluff reading is dead, and
|
|
`scenarios/ground/gr-p05-solve-legality.yaml` covers it — P1 refused for
|
|
holding no Clarify, P2 admitted and claiming. The prior-round-claim half
|
|
is asserted in the unit test instead, because reaching a second round
|
|
costs a dozen commands to test one rejection, and that is said in the
|
|
scenario rather than left as a gap.
|
|
|
|
## Task: evidence
|
|
|
|
```task
|
|
id: CB-WP-0023-T03
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "3a05165c-df33-4668-8ca2-2340789b3531"
|
|
```
|
|
|
|
`evidence/CB-EV-0020-*.md`. Short.
|
|
|
|
- **How long the inert move survived**, and what it cost: a maintainer
|
|
played SOLVE three rounds running with no effect and no explanation.
|
|
- **Whether any scenario encoded the bug.**
|
|
- **Quote CB-WP-0022's cost by re-running the instrument.**
|