From c70842b6df497de7784e178eb6963c220fc3eb58 Mon Sep 17 00:00:00 2001 From: Rezolv Date: Fri, 12 Jun 2026 13:04:31 -0400 Subject: [PATCH] enhance(spec-phase): edge-probe `precision` probe should name tie-breaking / rounding-mode (#1108) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(spec-phase): name tie-breaking/rounding mode in the edge-probe precision probe (#1102) The precision edge probe fired on numeric-range requirements but its text never named the most common rounding failure mode — tie-breaking / rounding mode (half-up vs half-to-even, ceil/floor/truncate). In an A/B experiment the weak tier (haiku) false-passed 50% of tie-class defects against the surfaced- unresolved spec; naming the rule in the probe text drove honest abstention 83%→100% (false-pass 17%→0%, haiku 50%→0%) with no category regression (precision still fires only on numeric-range). Sharpen the single TAXONOMY probe string and update every rendering together so the doc↔fixture↔machine contract (edge-probe-docs-fixtures.test.cjs) stays green: src/edge-probe.cts, the edge-probe.md taxonomy table + 2 worked examples, the 01-round-half-even and 04-money-rounding fixtures, and the resolve-edge-coverage how-to. Prose-only — no consumer keys on the probe text; SHAPE_CUES firing unchanged; fully backward compatible. * chore(changeset): Changed fragment for edge-probe precision probe text (#1108) --- .changeset/graceful-zebras-munch.md | 5 +++++ docs/how-to/resolve-edge-coverage-findings.md | 2 +- .../01-round-half-even/expected-coverage.json | 2 +- .../04-money-rounding/expected-coverage.json | 2 +- gsd-core/references/edge-probe.md | 6 +++--- src/edge-probe.cts | 2 +- 6 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 .changeset/graceful-zebras-munch.md diff --git a/.changeset/graceful-zebras-munch.md b/.changeset/graceful-zebras-munch.md new file mode 100644 index 000000000..1a361d6b1 --- /dev/null +++ b/.changeset/graceful-zebras-munch.md @@ -0,0 +1,5 @@ +--- +type: Changed +pr: 1108 +--- +Edge-probe `precision` probe text now names tie-breaking / rounding-mode (half-up vs half-to-even, ceil/floor/truncate), so a surfaced precision edge cues the most common rounding failure mode. Prose-only; firing rule and the 8-category core unchanged. diff --git a/docs/how-to/resolve-edge-coverage-findings.md b/docs/how-to/resolve-edge-coverage-findings.md index fed067e19..8dac0bdc3 100644 --- a/docs/how-to/resolve-edge-coverage-findings.md +++ b/docs/how-to/resolve-edge-coverage-findings.md @@ -12,7 +12,7 @@ For the category taxonomy and the reasoning behind front-of-pipeline edge analys Each finding is one **applicable** edge for one requirement — a boundary the probe's relevance filter decided is in scope for that requirement's shape, and that you have not yet addressed. A finding is phrased as a probe question, for example: -> **R3 · precision** — Where can precision loss or overflow occur, and what is the contract? +> **R3 · precision** — Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)? You must resolve each finding into exactly one of four states. Claude presents them as a numbered choice (or an `AskUserQuestion` menu). diff --git a/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json b/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json index 87c90f32f..ef3bf14e0 100644 --- a/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +++ b/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json @@ -1,7 +1,7 @@ { "items": [ { "requirement_id": "R1", "category": "boundary", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What happens exactly at each min/max/threshold — and one step either side?" }, - { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss or overflow occur, and what is the contract?" } + { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?" } ], "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } } } diff --git a/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json b/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json index 87c90f32f..ef3bf14e0 100644 --- a/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +++ b/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json @@ -1,7 +1,7 @@ { "items": [ { "requirement_id": "R1", "category": "boundary", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What happens exactly at each min/max/threshold — and one step either side?" }, - { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss or overflow occur, and what is the contract?" } + { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?" } ], "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } } } diff --git a/gsd-core/references/edge-probe.md b/gsd-core/references/edge-probe.md index acac6068e..2cfb2de70 100644 --- a/gsd-core/references/edge-probe.md +++ b/gsd-core/references/edge-probe.md @@ -62,7 +62,7 @@ truncation). Growth happens via optional domain packs, not by bloating the core. | empty | Empty / degenerate | collection, text | What is the result for empty, single-element, or null input? | | encoding | Encoding / representation | text | Whose definition of length/equality applies — bytes, code points, grapheme clusters, or normalized form? | | ordering | Ordering / stability | collection | When elements compare equal, is output order specified and stable? | -| precision | Precision / overflow | numeric-range | Where can precision loss or overflow occur, and what is the contract? | +| precision | Precision / overflow | numeric-range | Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)? | | idempotency | Idempotency / repetition | stateful | What happens if this runs twice on the same input? | | concurrency | Concurrency / effect ordering | stateful, io | If interrupted or run in parallel, what is guaranteed? | @@ -170,7 +170,7 @@ rule, the requirement classifies as `numeric-range`, which raises `boundary` and { "items": [ { "requirement_id": "R1", "category": "boundary", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What happens exactly at each min/max/threshold — and one step either side?" }, - { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss or overflow occur, and what is the contract?" } + { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?" } ], "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } } } @@ -209,7 +209,7 @@ classifies as `numeric-range`, which raises `boundary` and `precision`: { "items": [ { "requirement_id": "R1", "category": "boundary", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What happens exactly at each min/max/threshold — and one step either side?" }, - { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss or overflow occur, and what is the contract?" } + { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?" } ], "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } } } diff --git a/src/edge-probe.cts b/src/edge-probe.cts index 8d7f7a7ef..2a4ec793a 100644 --- a/src/edge-probe.cts +++ b/src/edge-probe.cts @@ -88,7 +88,7 @@ export const TAXONOMY: TaxonomyEntry[] = [ { id: 'empty', name: 'Empty / degenerate', shapes: ['collection', 'text'], probe: 'What is the result for empty, single-element, or null input?' }, { id: 'encoding', name: 'Encoding / representation', shapes: ['text'], probe: 'Whose definition of length/equality applies — bytes, code points, grapheme clusters, or normalized form?' }, { id: 'ordering', name: 'Ordering / stability', shapes: ['collection'], probe: 'When elements compare equal, is output order specified and stable?' }, - { id: 'precision', name: 'Precision / overflow', shapes: ['numeric-range'], probe: 'Where can precision loss or overflow occur, and what is the contract?' }, + { id: 'precision', name: 'Precision / overflow', shapes: ['numeric-range'], probe: 'Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?' }, { id: 'idempotency', name: 'Idempotency / repetition', shapes: ['stateful'], probe: 'What happens if this runs twice on the same input?' }, { id: 'concurrency', name: 'Concurrency / effect ordering', shapes: ['stateful', 'io'], probe: 'If interrupted or run in parallel, what is guaranteed?' }, ];