feat(self-check): command-restates-standard lint (consistency category, VERSION 1.4.2)

Task 3 leftover. Adds a 'consistency' category to /self-check that catches a standard
drifting back into restating/contradicting the command that owns the rule -- the Syncro
timers failure mode (standard said 'always timer' while /syncro said 'outlier only').

Deterministic half: each manifest.command_standard_links pair's standard must still carry
its defer-to-SSOT pointer (must_reference regex). Lost pointer = WARN. Seeded with
syncro-billing (time-entry-protocol.md -> /syncro). Semantic contradiction pass delegated
to the model in SKILL.md, mirroring check_memory. Verified PASS; negative-tested.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-08 08:29:58 -07:00
parent 9163a29251
commit 07744d46c7
5 changed files with 72 additions and 1 deletions

View File

@@ -82,6 +82,7 @@ SELFCHECK_TS="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
| **duplicates** | command/skill names present in BOTH the repo and `~/.claude`. Divergent content = WARN (the "same `/cmd`, different behaviour on the Mac" bug); identical = INFO (redundant, will drift). CRLF-only differences are ignored. |
| **memory** | `MEMORY.md` index exists; no orphaned memory files; manifest-declared contradiction patterns (see semantic pass below). Never FAILs the grade. |
| **harness** | the 1.4.0 invariants (read-only): VERSION marker present + not older than `manifest.harness.min_version`; **skill-registry description budget** (sum of all SKILL.md `description:` fields under `registry_desc_budget_chars` — WARN on regrowth); global deploy targets `~/.claude/skills` + `~/.claude/commands` populated (the "Mac wiped global skills" failure); `harness-guard.sh` present + wired into `sync.sh`; core scripts parse (`bash -n` on sync/guard/now-phoenix); `now-phoenix.sh --date` emits a valid date. Budget/min-version/script-list are tunable in `manifest.harness`. |
| **consistency** | the **command-restates-standard** lint (deterministic half): for each `manifest.command_standard_links` pair, the standard must still contain its defer-to-SSOT pointer to the owning command. A lost pointer = WARN (the standard likely drifted back into restating the command — the Syncro-timers failure mode). The semantic contradiction judgement is delegated to the model (see below). |
| **vault** | vault repo exists; sops+age present; `vault.sh list` succeeds (decrypt wired). |
| **connectivity** | coord API (required), main API + internal Gitea (advisory; off-network is OK). |
@@ -110,6 +111,26 @@ Ollama Tier-0 per the house rules; Claude reviews the result):
Genuinely machine-specific guidance in a *shared* memory is the usual culprit —
the fix is to scope it ("on Windows…") or split it, not to globally flip it.
### Semantic pass 2 — command vs standard contradiction
The `consistency` category only checks that the defer-to-SSOT *pointer* is present.
Whether a command and its standard actually **say contradictory things** is a
judgement task — do it the same way (Ollama Tier-0 for the read/classify, Claude
reviews):
1. For each `manifest.command_standard_links` pair, read BOTH the standard and the
owning command it points to.
2. Flag any rule the standard states that **conflicts** with the command (e.g. the
standard mandates a timer for routine billing while `/syncro` says line-item is
normal and timers are outlier-only — the original drift this lint exists to catch).
3. Report: the topic, the conflicting claims (quote both sides), and which one is the
SSOT. **Do not edit** — surface for the operator; the SSOT (the command) wins, so
the fix is almost always to correct the standard, not the command.
New links are cheap to add — drop another `{topic, standard, must_reference, why}`
into `manifest.command_standard_links` whenever a command and a standard speak to the
same rule.
## Fleet self-remediation loop (machines fix themselves)
We never fix a remote machine. The flow is: