Skip to content

the drift check cannot see a requirement that no longer describes the code, whether it lost its implementation or was contradicted by its successor #728

Description

@0xLeif

Found while backfilling the 6.0 changelog, by an agent reading #665's diff rather than its title.

The stale requirement

REQ-change-055 (specs/change/requirements.md:810) is live and unsuperseded. It says:

Change sequence allocation SHALL floor on the highest sequence observed locally (active, archive, local ledger) and, when available, the remote default-branch .specsync/change-sequence.json high-water. Concurrent multi-clone fleets MAY set SPECSYNC_SEQUENCE_BASE to disjoint ranges so agents that cannot see each other do not mint the same numeric CHG prefix.

with the acceptance criterion SPECSYNC_SEQUENCE_BASE=N makes the next allocated sequence at least N.

None of that exists. The ordinal retirement (7cbe820, #665) deleted maximum_observed_sequence and remote_sequence_high_water, and change identity became a slug. Verified rather than assumed:

AGENTS.md:49 still tells agents to prefer SPECSYNC_SEQUENCE_BASE=<N> with disjoint ranges. That guidance is inert rather than dangerous — the collision it guards against cannot occur once identity is a slug — but it is instructions to do something that does nothing.

The part that is actually about the product

specsync check --spec change does not flag REQ-change-055, and by the current model it cannot.

Drift detection measures specs against the code that implements them. A requirement whose implementation was partly changed drifts and is caught. A requirement whose implementation was entirely deleted has nothing left to measure against, so it produces no finding at all — it reads as "nothing to check" rather than "orphaned requirement."

That is this release's most-repeated defect shape one level up, in the tool's own model rather than in a single function: a category empty for want of input, read as a verdict. #672 read an unparseable schema's zero tables as "every table missing"; #684 gated on advice the reader could not take; #720 read an unreadable bypass_actors as "no bypass granted"; #689's first design read absent history as absent readiness. Here, zero implementing symbols reads as zero drift.

The requirement most likely to be stale is exactly the one with no code left pointing at it, and that is precisely the one the current check is blind to.

What this needs

  1. Fix REQ-change-055 — supersede or delete it, and remove the AGENTS.md:49 guidance. Small and unambiguous.
  2. Decide whether the drift model should detect an orphaned requirement at all. A requirement with zero attributable implementation is not automatically a defect — aspirational, process, and policy requirements legitimately have none, and this repository has some. So the answer is probably report, never gate: a distinct unattributed requirement outcome, disclosed and not counted as drift, in the same shape bug: deps silently skips Kotlin import analysis #477 used for unresolvable imports — "owned, foreign, or unattributed and disclosed", where silence is never the default.

(2) is the real work and should not be rushed into 6.0. (1) should land before the stable tag, since a released spec that documents a removed environment variable is the drift this tool exists to catch.

Related: #665 (the retirement), #533 (why the ledger is still read), #477 (the disclosure shape), #672 / #684 / #689 / #720 (the same defect shape).

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

    area:governanceLifecycle, approval, adoption, or release-policy behaviorarea:product-bugRuntime or CLI behavior is incorrectimpact:developer-experienceAffects authors, maintainers, or local workflowspriority:p2Important but not immediately release-blockingresolution:partialRelated work landed but meaningful residual work remainsscope:legacy-validLegacy or migration path remains supported and affectedscope:specsync-6Applies to current SpecSync 6 behavior or release contract

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions