Skip to content

gate-46 stops consulting the capability index the moment the canonical spec file exists, so a requirement that is early inside a capability that is not cannot be cited #732

Description

@rubenvdlinde

Third sibling of #726 and #727, same helper. The three are one question, asked at three points: #726 is what gate-46 does not read, #727 is where it does not look, and this is when it stops resolving.

The gap

resolve() in scripts/lib/check_spec_anchors.py consults the capability index only after every literal spelling has already failed:

# LAST RESORT ONLY — see build_capability_index.
if not cands and capability_index:

That is what makes the "an anchor may name a canonical path whose spec is still in an open change" convention work at all: resolution falls through to the index and finds the requirement in the change's delta.

It stops working the moment the canonical file exists. A capability file that is present for other reasons makes cands non-empty, the index is never reached, and the delta sitting beside it in an open change is never opened. The anchor then reports anchor not found, and the requirement it names is written, reviewed and merged.

So a requirement that is early inside a capability that is not cannot be cited at all. The only spellings that resolve are the change path, which will move on archive, or an exclusion, which claims no coverage.

Reproduced

Two spec files, one anchor, nothing else:

openspec/specs/case-management/spec.md                              (exists, older scenarios)
openspec/changes/case-delete-guard/specs/case-management/spec.md    (the new scenario)
lib/Thing.php:  @spec openspec/specs/case-management/spec.md#a-case-delete-is-refused-when-the-schema-is-archival

Run through the real helper:

lib/Thing.php: @spec anchor not found in openspec/specs/case-management/spec.md
               → #a-case-delete-is-refused-when-the-schema-is-archival

Repoint the same tag at the change path and the finding disappears. The requirement never moved; only the spelling did.

Measured in the field: eight anchors in dossiq, in an open change with 11 of 13 tasks done, all naming scenarios that are written. They now carry explicit exclusions naming the governing scenario and its change, which claims no coverage and makes the post-archive sweep mechanical. That is a workaround for a resolver gap, not an end state.

What a fix has to weigh, and why it is not in either open PR

The obvious repair is to consult the capability index alongside the literal candidates rather than after them. That only ever adds candidates, so it can only ever remove findings, and a change that can only remove findings from a gate is exactly the kind that needs its own review rather than a ride inside a widening. Both PRs against #726 and #727 deliberately leave it alone.

The reason to be careful is on the same page as the reason to fix it.

A citation can resolve to the wrong thing, and no count catches that

From the same measurement: one anchor resolves cleanly to a scenario that says the opposite of what its test asserts. The scenario says deleting a case succeeds. The test asserts it is refused with a 403, because the schema is archival. The anchor resolves, so it passes gate-46 and reads as verified coverage.

Every fix in this family counts resolution, and resolution is not agreement. Widening the index makes more anchors resolve, which is the point, and it also makes this failure mode more available. Worth stating plainly here so that whoever loosens the resolver decides it on purpose:

an anchor that resolves to the wrong requirement is worse than one that dangles, because the dangling one gets fixed on the day it is typed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions