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 edcbc5f7ea
commit e180a463e2
5 changed files with 72 additions and 1 deletions

View File

@@ -58,3 +58,12 @@ or old harness during a heterogeneous rollout. See
machine; budget WARN trips correctly on a synthetic over-budget value. machine; budget WARN trips correctly on a synthetic over-budget value.
- Also reconciled the remaining "GrepAI first" docs (standard + CODING_GUIDELINES) with the - Also reconciled the remaining "GrepAI first" docs (standard + CODING_GUIDELINES) with the
wiki-first recall hierarchy (started in CLAUDE_EXTENDED). wiki-first recall hierarchy (started in CLAUDE_EXTENDED).
## 1.4.2 — 2026-06-08 (Task 3 leftover: command-restates-standard lint)
- /self-check gained a `consistency` category — the command-restates-standard lint. Deterministic
half: for each manifest.command_standard_links pair, the standard must still carry its
defer-to-SSOT pointer to the owning command; a lost pointer WARNs (the standard likely drifted
back into restating the command — the Syncro-timers failure mode). Seeded with the syncro-billing
link (time-entry-protocol.md -> /syncro). Semantic contradiction pass (read both, judge actual
conflict) delegated to the model in SKILL.md, mirroring the memory pass. Verified PASS; negative-
tested (WARN fires when the pointer is removed). New pairs: add to manifest.command_standard_links.

View File

@@ -1 +1 @@
1.4.1 1.4.2

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. | | **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. | | **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`. | | **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). | | **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). | | **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 — 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. 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) ## Fleet self-remediation loop (machines fix themselves)
We never fix a remote machine. The flow is: We never fix a remote machine. The flow is:

View File

@@ -18,6 +18,16 @@
"guard_wired_in": ".claude/scripts/sync.sh" "guard_wired_in": ".claude/scripts/sync.sh"
}, },
"command_standard_links": [
{
"topic": "syncro-billing",
"standard": ".claude/standards/syncro/time-entry-protocol.md",
"must_reference": "syncro\\.md|single source of truth",
"why": "the time-entry standard must DEFER to the /syncro command (one SSOT), not restate billing mechanics. A past drift had the standard say 'always timer' while the command said 'outlier only' — losing the pointer is the early warning of that re-drift."
}
],
"command_standard_links_note": "Deterministic half of the command-restates-standard lint: each linked standard must contain a defer-to-SSOT pointer (must_reference, a grep -iE regex). A WARN means the standard may have drifted back into restating/contradicting the command. The SEMANTIC contradiction judgement (read both files, decide if they actually conflict) is delegated to the model in SKILL.md, mirroring the memory contradiction pass.",
"required_tools": [ "required_tools": [
{ "name": "bash", "why": "hooks, scripts, sync, vault wrapper" }, { "name": "bash", "why": "hooks, scripts, sync, vault wrapper" },
{ "name": "git", "why": "repo + submodules + Gitea sync" }, { "name": "git", "why": "repo + submodules + Gitea sync" },

View File

@@ -661,6 +661,36 @@ check_harness_smoke() {
fi fi
} }
# ---------------------------------------------------------------------------
# CHECK: command <-> standard consistency (the "command-restates-standard" lint).
# Deterministic core only: for each manifest-declared (command, standard) link,
# verify the standard still contains its defer-to-SSOT pointer (must_reference).
# A standard that loses the pointer has likely drifted back into RESTATING the
# command's rules -- the exact failure mode behind the Syncro timers contradiction
# (standard said 'always timer' while /syncro said 'outlier only'). The SEMANTIC
# pass (read both, judge actual contradiction) is delegated to the model in
# SKILL.md, mirroring check_memory.
# ---------------------------------------------------------------------------
check_command_standard() {
local has; has="$(jq -r '(.command_standard_links // []) | length' "$MANIFEST" 2>/dev/null)"
[ "${has:-0}" -gt 0 ] 2>/dev/null || return
local topic stdf ref why p
while IFS=$'\t' read -r topic stdf ref why; do
[ -n "$topic" ] || continue
p="$REPO_ROOT/$stdf"
if [ ! -f "$p" ]; then
emit "consistency.$topic" consistency WARN "standard missing for '$topic': $stdf" \
"Restore via /sync, or remove the link from manifest.command_standard_links"
elif grep -qiE "$ref" "$p" 2>/dev/null; then
emit "consistency.$topic" consistency PASS "'$topic' standard defers to the owning command (SSOT pointer present)"
else
emit "consistency.$topic" consistency WARN \
"'$topic' standard ($stdf) lost its defer-to-SSOT pointer ($why)" \
"Re-add the pointer to the owning command, and confirm the standard does NOT restate or contradict it"
fi
done < <(jq -r '(.command_standard_links // [])[] | [.topic, .standard, .must_reference, .why] | @tsv' "$MANIFEST")
}
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Build the census JSON from accumulated results # Build the census JSON from accumulated results
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -846,6 +876,7 @@ check_skills_commands
check_duplicates check_duplicates
check_memory check_memory
check_harness_smoke check_harness_smoke
check_command_standard
check_vault check_vault
check_connectivity check_connectivity