Skip to content

feat(docs-hygiene): extract-ssot — bucket candidates by rule-of-one/two/three and gate artifact creation, not reporting #3114

Description

@kyle-sexton

User Story

As a maintainer running /docs-hygiene:extract-ssot over a repo, I want the survey to inventory duplication at every multiplicity — rule-of-one, -two, and -three — and let me choose which buckets to act on (after review, or up front via args), so that single- and double-instance defects are surfaced and fixable instead of being silently refused by a hard Rule of Three.

Affected area / component

plugins/docs-hygiene/skills/extract-ssotSKILL.md, actions/identify.md, actions/verify.md, actions/batch.md, context/decision-framework.md, context/anti-patterns.md.

Context — what is wrong today

Rule of Three is currently doing double duty: it gates abstraction (correct) and it gates reporting (wrong). identify refuses to roster a cluster below three instances and verify returns REFUSE-premature, so two real defect classes never reach the user at all:

  • N=1 — inline recap of an existing SSOT. One consumer restating a rule that already has a canonical home is a genuine defect at a single instance. The remedy is trim-to-citation, which creates no new artifact — so none of the premature-abstraction risk that motivates Rule of Three applies to it.
  • N=2 — source-of-truth bifurcation. Two files asserting the same contract with no declared owner, drifting independently. The skill already names this as anti-pattern fix(markdown-formatter): harden hook + simplify plumbing #11, but it is unreachable in practice because the roster gate fires first.

Observed live while running the skill against melodic-software/.github: the survey refused every cluster and returned zero candidates. That repo's policy files nonetheless state the same org-wide-override rule in three different phrasings, with two sibling files silent on it — a real reader-burden defect that the gate discarded, correctly reasoning that no new artifact was warranted and then wrongly concluding there was nothing to report.

Proposed design — separate the two gates

Bucket Rostered? Permitted remedies Creates a new artifact?
N=1 always trim-to-citation, normalize-wording never
N=2 always edit-existing-rule, name-an-owner, normalize-wording never
N≥3 always all of the above, plus rule-file / new-skill / new-action only behind the existing 6-test gate

Rule of Three keeps gating creation of a new SSOT artifact — the failure mode the cited evidence (~19% curated / ~50% practitioner-authored) is actually about. It stops gating whether the user is told.

This is what makes a rule-of-one default safe: at N=1 and N=2 the only remedies offered are non-abstracting ones, so lowering the reporting threshold does not lower the abstraction threshold.

Args and flags

Aligned with the prevailing conventions across the marketplace (--fix 67 uses, --apply 54, --yes 36, --dry-run 35) and with docs-hygiene's own read-only-by-default posture:

Flag Default Behavior
--min-instances=<N> 1 Lowest bucket to roster. --min-instances=3 restores today's behavior
--buckets=<list> all Filter the roster, e.g. --buckets=1,2
--fix off Apply only the non-abstracting remedies (trim-to-citation, normalize-wording); never creates an artifact
--dry-run off Print the diff --fix would apply, write nothing
--yes off Non-interactive; skip the per-bucket review gate

Read-only stays the default with no flags: bare invocation reports buckets and stops, matching audit-noise / audit-derivability.

argument-hint in frontmatter needs updating to carry the new args.

Acceptance Criteria

  • identify rosters candidates at N=1 and N=2 instead of refusing them, in three labelled buckets
  • Bucket membership and instance count are shown per candidate in the roster output
  • verify returns a bucket-appropriate verdict; REFUSE-premature fires only against artifact-creating remedies, not against reporting or against trim-to-citation / normalize-wording
  • N=1 and N=2 candidates can never be routed to rule-file / new-skill / new-action
  • --min-instances, --buckets, --fix, --dry-run, --yes are implemented and documented in the action router
  • --min-instances=3 reproduces current behavior exactly (regression guard)
  • Bare invocation remains read-only and applies no edits
  • context/decision-framework.md documents the reporting-gate vs abstraction-gate split
  • context/anti-patterns.md fix(markdown-formatter): harden hook + simplify plumbing #11 (source-of-truth bifurcation) is reachable from the N=2 bucket
  • Skill description and argument-hint updated — the description currently promises refusal below three, which would become false
  • Eval coverage: one N=1 case, one N=2 case, one N≥3 case, and one case asserting no new artifact is proposed below N=3

Out of scope

  • Changing the 6-test gate itself for N≥3 extraction
  • Code/config-class clusters — still referred to language-idiomatic tooling

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions