Skip to content

FEAT-088: a forgotten safety goal can't hide behind the undeveloped diamond - #163

Merged
avrabe merged 1 commit into
mainfrom
feat-088-goal-gate
Aug 27, 2026
Merged

FEAT-088: a forgotten safety goal can't hide behind the undeveloped diamond#163
avrabe merged 1 commit into
mainfrom
feat-088-goal-gate

Conversation

@avrabe

@avrabe avrabe commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

The gap

rivet coverage prints goal-has-support 2/5 = 40.0% and cannot distinguish
a goal deliberately marked undeveloped: true
— GSN's diamond, an honest
declared incompleteness — from one somebody forgot. Both render as uncovered.

J-004 investigated this on 2026-08-25 and got it right: G-003 / G-004 / G-005 are
deliberately undeveloped, and closing the number with links would be cosmetic.

That investigation is correct, and it is prose. Prose is exactly what the next
forgotten goal hides behind — add a goal with no evidence and it reads like the
three that were reasoned about. J-004 says so itself:

a genuinely forgotten goal would hide among the declared ones

This makes that sentence mechanical.

The gate

# rule catches
1 no supporting safety-solutionmust carry undeveloped: true a goal nobody developed or declared
2 carries undeveloped: truemust be named by a safety-justification the flag added to quiet the report

Rule 1 alone is satisfiable by typing the flag, so a gate checking only it catches
the mistake nobody was going to make. Rule 2 is the one that matters.

A justification naming the goal only in prose (a rationale field, no typed link)
counts — J-004's own shape must not be flagged.

Why the cross-check exists

The checker cross-checks its own population against rivet list and fails on
disagreement
. Not defensive padding: G-005 lives in roadmap-2.0.yaml, not
safety-case.yaml
, so a checker reading the obvious single file finds 4 of 5
goals, reports clean, and silently omits the one carrying asil: D.

The checker must not be able to have the bug it exists to prevent.

It also fails closed when PyYAML is missing rather than skipping — scry#141's
failure mode was a gate reporting green while running nothing.

Mutation-checked against the real repo

mutant result
scan only safety-case.yaml rivet sees 5 ... this checker sees 4 → exit 1
redact J-004's links and prose exactly 3 violations (G-003/4/5) → exit 1
restored PASS
PyYAML shadowed on PYTHONPATH exit 1 on both the gate and its self-test

Self-test covers 6 cases including the subtle one, and runs before the real
check in CI — the tools/check-gate-coverage.py pattern.

What this does NOT do

It does not make the 40% meaningful. rivet coverage still counts
declared-undeveloped goals as uncovered and will still print
goal-has-support 2/5 40.0%. J-004 notes the figure misleads in both
directions; this closes exactly one — forgotten hiding among declared. The other
needs rivet itself to express undeveloped, already reported upstream.

G-003 / G-004 / G-005 remain deliberately undeveloped. This does not develop
them, and the residual records what developing each would actually require.

rivet=0 claim-check=0 gate-coverage=0 undeveloped-goals=0 fmt=0

⚠️ Per #130 this repo has no required status checks; verify gh pr checks by hand.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KkNzkNYzPh7366DkNijeNc

… diamond

`rivet coverage` prints goal-has-support 2/5 = 40% and cannot tell a goal
DECLARED `undeveloped: true` -- GSN's diamond, an honest declared incompleteness
-- from one somebody forgot. J-004 investigated this on 2026-08-25 and got it
right: all three uncovered goals are deliberate, and adding links would be
cosmetic.

That investigation is correct, and it is prose. Prose is exactly what the next
forgotten goal hides behind -- add a goal with no evidence and it reads like the
three that were reasoned about. J-004 says so itself: "a genuinely forgotten goal
would hide among the declared ones." This makes that sentence mechanical.

Two directions, and the second is the one that matters:

  1. no supporting safety-solution  -> MUST carry `undeveloped: true`
  2. carries `undeveloped: true`    -> MUST be named by a safety-justification

(1) alone is satisfiable by typing the flag, so a gate checking only it catches
the mistake nobody was going to make. (2) is the shape a forgotten goal takes
once someone notices the number and quiets it.

The checker cross-checks its population against `rivet list` and fails on
disagreement -- not padding: G-005 lives in roadmap-2.0.yaml, not
safety-case.yaml, so reading the obvious single file finds 4 of 5 and silently
omits the goal carrying asil: D. It must not be able to have the bug it prevents.

Fails CLOSED when PyYAML is missing instead of skipping (scry#141's failure mode
was a gate that reported green while running nothing).

MUTATION-CHECKED against the REAL repo, both directions:
  scan only safety-case.yaml -> "rivet sees 5 ... this checker sees 4", exit 1
  redact J-004 links + prose -> exactly 3 violations (G-003/4/5), exit 1
  restored                   -> PASS
  PyYAML shadowed on PYTHONPATH -> exit 1 on BOTH the gate and its self-test
Self-test covers 6 cases including the subtle one and runs BEFORE the real check
in CI, mirroring tools/check-gate-coverage.py.

DOES NOT make the 40% meaningful -- rivet still counts declared-undeveloped as
uncovered and still prints 40%. This closes one direction only. Stated in the
artifact residual so the next sweep doesn't read "gated" as "resolved", which is
the re-litigation J-004 exists to stop. G-003/G-004/G-005 remain deliberately
undeveloped; this does not develop them.

rivet=0 claim-check=0 gate-coverage=0 undeveloped-goals=0 fmt=0.

Claude-Session: https://claude.ai/code/session_01KkNzkNYzPh7366DkNijeNc

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

📐 rivet artifact delta

PR: #163 Base SHA: 9478586d

Validation

head — `rivet validate` result
  SR-11 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-12 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-13 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-2 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-3 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-4 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-5 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-6 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-7 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-8 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-9 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SYS-1 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-2 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-3 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-4 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-5 (system-req, status: accepted) — missing: sys-integration-verification
  → run `rivet validate --explain SR-1` to see which link type and source types satisfy a gap

Result: PASS (147 warnings)
Schemas: common@0.3.0 (embedded), dev@0.3.0 (embedded), research@0.1.0 (embedded), research-ext@0.1.0 (on-disk), safety-case@0.1.0 (embedded), aspice@0.2.0 (embedded)
base — `rivet validate` result (for comparison)
  SR-11 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-12 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-13 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-2 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-3 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-4 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-5 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-6 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-7 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-8 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-9 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SYS-1 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-2 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-3 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-4 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-5 (system-req, status: accepted) — missing: sys-integration-verification
  → run `rivet validate --explain SR-1` to see which link type and source types satisfy a gap

Result: PASS (142 warnings)
Schemas: common@0.3.0 (embedded), dev@0.3.0 (embedded), research@0.1.0 (embedded), research-ext@0.1.0 (on-disk), safety-case@0.1.0 (embedded), aspice@0.2.0 (embedded)

Artifact stats

base head
Total artifacts 256 257
full stats — head
Artifact summary:
  academic-reference               24
  competitive-analysis             11
  design-decision                  22
  feature                          87
  market-finding                    7
  requirement                      21
  safety-context                    3
  safety-goal                       5
  safety-justification              4
  safety-solution                   6
  safety-strategy                   1
  stakeholder-req                   3
  sw-req                           13
  sw-verification                  13
  sys-verification                  5
  system-req                        5
  technology-evaluation            12
  verification                     15
  TOTAL                           257

Orphan artifacts (no links): 12
  CA-001
  CA-002
  CA-003
  CA-004
  CA-005
  CA-006
  CA-007
  CA-008
  CA-009
  CA-010
  CA-011
  FEAT-078

Diagnostics: 0 error(s), 147 warning(s), 20 info(s)

Diff (base → head)

+ FEAT-088  v3.4 — A forgotten safety goal cannot hide behind the `undeveloped` diamond

1 added, 0 removed, 0 modified, 256 unchanged

~ NEW    WARN: [FEAT-088] prose mentions 'J-004' but no typed link to it; add a link in `links:` or remove the mention
~ NEW    WARN: [FEAT-088] prose mentions 'G-003' but no typed link to it; add a link in `links:` or remove the mention
~ NEW    WARN: [FEAT-088] prose mentions 'G-004' but no typed link to it; add a link in `links:` or remove the mention
~ NEW    WARN: [FEAT-088] prose mentions 'G-005' but no typed link to it; add a link in `links:` or remove the mention
~ NEW    WARN: [FEAT-088] prose mentions 'FEAT-049' but no typed link to it; add a link in `links:` or remove the mention
0 new errors, 0 resolved errors, 5 new warnings, 0 resolved warnings

AADL model — head

spar/scry.aadl: OK

Posted by the rivet-delta workflow. Informational only — does not gate the PR.

@avrabe
avrabe merged commit 7500b08 into main Aug 27, 2026
11 checks passed
@avrabe
avrabe deleted the feat-088-goal-gate branch August 27, 2026 03:44
avrabe added a commit that referenced this pull request Aug 27, 2026
… 7 -> 4

`implemented`/`proposed` count as NOT-yet-verified in the release gate, so a
shipped, green feature left there blocks its release indefinitely. These three
have shipped AND been verified, so leaving them proposed understates the release
just as promoting them early would overstate it.

Evidence for each, grounded rather than remembered:

  FEAT-087 (#162, 11/11 CI green) -- 3 oracles re-run on main just now:
    the tier-discrimination test, the tier-2 independence pin, and the
    module-scoped decision. Mutation-checked both directions when landed.
  FEAT-088 (#163, 11/11 CI green) -- the gate's --self-test PASSES and the
    real check PASSES on main, and it is wired into ci.yml (self-test before
    the real check). Mutation-checked against the real repo when landed.
  FEAT-090 (#166, 11/11 CI green) -- 5 oracles re-run on main just now,
    including the polarity test that dies only under the `&=` -> `|=` mutant.

NOT promoted, deliberately:
  FEAT-089 -- FILED, not built. The non-zero-fact work does not exist yet; its
    own AC#1 requires a red test that is still red by design.
  FEAT-064 -- AC3 closed by measurement in #164, but AC1 remains FALSIFIED
    (repaired by FEAT-077 only for uniquely-named functions). Closing one AC
    does not clear the artifact, and REQ-020 stays blocked behind it.
  FEAT-057, FEAT-065, REQ-021 -- unbuilt.

rivet=0 claim-check=0 fmt=0.

Refs: FEAT-087

Claude-Session: https://claude.ai/code/session_01KkNzkNYzPh7366DkNijeNc

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
avrabe added a commit that referenced this pull request Aug 27, 2026
… 7 -> 4

`implemented`/`proposed` count as NOT-yet-verified in the release gate, so a
shipped, green feature left there blocks its release indefinitely. These three
have shipped AND been verified, so leaving them proposed understates the release
just as promoting them early would overstate it.

Evidence for each, grounded rather than remembered:

  FEAT-087 (#162, 11/11 CI green) -- 3 oracles re-run on main just now:
    the tier-discrimination test, the tier-2 independence pin, and the
    module-scoped decision. Mutation-checked both directions when landed.
  FEAT-088 (#163, 11/11 CI green) -- the gate's --self-test PASSES and the
    real check PASSES on main, and it is wired into ci.yml (self-test before
    the real check). Mutation-checked against the real repo when landed.
  FEAT-090 (#166, 11/11 CI green) -- 5 oracles re-run on main just now,
    including the polarity test that dies only under the `&=` -> `|=` mutant.

NOT promoted, deliberately:
  FEAT-089 -- FILED, not built. The non-zero-fact work does not exist yet; its
    own AC#1 requires a red test that is still red by design.
  FEAT-064 -- AC3 closed by measurement in #164, but AC1 remains FALSIFIED
    (repaired by FEAT-077 only for uniquely-named functions). Closing one AC
    does not clear the artifact, and REQ-020 stays blocked behind it.
  FEAT-057, FEAT-065, REQ-021 -- unbuilt.

rivet=0 claim-check=0 fmt=0.

Refs: FEAT-087

Claude-Session: https://claude.ai/code/session_01KkNzkNYzPh7366DkNijeNc

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
avrabe added a commit that referenced this pull request Aug 27, 2026
… 7 -> 4

`implemented`/`proposed` count as NOT-yet-verified in the release gate, so a
shipped, green feature left there blocks its release indefinitely. These three
have shipped AND been verified, so leaving them proposed understates the release
just as promoting them early would overstate it.

Evidence for each, grounded rather than remembered:

  FEAT-087 (#162, 11/11 CI green) -- 3 oracles re-run on main just now:
    the tier-discrimination test, the tier-2 independence pin, and the
    module-scoped decision. Mutation-checked both directions when landed.
  FEAT-088 (#163, 11/11 CI green) -- the gate's --self-test PASSES and the
    real check PASSES on main, and it is wired into ci.yml (self-test before
    the real check). Mutation-checked against the real repo when landed.
  FEAT-090 (#166, 11/11 CI green) -- 5 oracles re-run on main just now,
    including the polarity test that dies only under the `&=` -> `|=` mutant.

NOT promoted, deliberately:
  FEAT-089 -- FILED, not built. The non-zero-fact work does not exist yet; its
    own AC#1 requires a red test that is still red by design.
  FEAT-064 -- AC3 closed by measurement in #164, but AC1 remains FALSIFIED
    (repaired by FEAT-077 only for uniquely-named functions). Closing one AC
    does not clear the artifact, and REQ-020 stays blocked behind it.
  FEAT-057, FEAT-065, REQ-021 -- unbuilt.

rivet=0 claim-check=0 fmt=0.

Refs: FEAT-087

Claude-Session: https://claude.ai/code/session_01KkNzkNYzPh7366DkNijeNc

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
avrabe added a commit that referenced this pull request Aug 27, 2026
… 7 -> 4 (#173)

`implemented`/`proposed` count as NOT-yet-verified in the release gate, so a
shipped, green feature left there blocks its release indefinitely. These three
have shipped AND been verified, so leaving them proposed understates the release
just as promoting them early would overstate it.

Evidence for each, grounded rather than remembered:

  FEAT-087 (#162, 11/11 CI green) -- 3 oracles re-run on main just now:
    the tier-discrimination test, the tier-2 independence pin, and the
    module-scoped decision. Mutation-checked both directions when landed.
  FEAT-088 (#163, 11/11 CI green) -- the gate's --self-test PASSES and the
    real check PASSES on main, and it is wired into ci.yml (self-test before
    the real check). Mutation-checked against the real repo when landed.
  FEAT-090 (#166, 11/11 CI green) -- 5 oracles re-run on main just now,
    including the polarity test that dies only under the `&=` -> `|=` mutant.

NOT promoted, deliberately:
  FEAT-089 -- FILED, not built. The non-zero-fact work does not exist yet; its
    own AC#1 requires a red test that is still red by design.
  FEAT-064 -- AC3 closed by measurement in #164, but AC1 remains FALSIFIED
    (repaired by FEAT-077 only for uniquely-named functions). Closing one AC
    does not clear the artifact, and REQ-020 stays blocked behind it.
  FEAT-057, FEAT-065, REQ-021 -- unbuilt.

rivet=0 claim-check=0 fmt=0.

Refs: FEAT-087

Claude-Session: https://claude.ai/code/session_01KkNzkNYzPh7366DkNijeNc

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant