diff --git a/claude-tooling/plugins/pulseengine-claude/.claude-plugin/plugin.json b/claude-tooling/plugins/pulseengine-claude/.claude-plugin/plugin.json index 4f86061..fb866a3 100644 --- a/claude-tooling/plugins/pulseengine-claude/.claude-plugin/plugin.json +++ b/claude-tooling/plugins/pulseengine-claude/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "pulseengine-claude", - "version": "0.14.1", + "version": "0.15.0", "description": "PulseEngine methodology as installable Claude Code tooling — philosophy + toolchain + repo-taxonomy + model-operating-contract memory, memory-persistence hooks (situational awareness at session start, working-context checkpoints across sessions/compaction), plus fifteen procedural skills (clean-room verification, release execution with a V-model traceability gate, oracle-gating, the full feature loop, the standardized release-artifact pipeline, tool-friction reporting, session-learning capture, STPA/STPA-Sec hazard-analysis audit, backend-agnostic proof synthesis, full bidirectional traceability audit across the V, greenfield verification bootstrap, release planning with an issue-driven delivery loop, an incremental issue-hunt loop, and a quiesce-gated post-release repo-hygiene sweep).", "author": { "name": "PulseEngine", diff --git a/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/SKILL.md b/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/SKILL.md index cd7579b..63d49ce 100644 --- a/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/SKILL.md +++ b/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/SKILL.md @@ -3,7 +3,7 @@ name: claim-verification description: This skill should be used whenever writing or editing a README, a badge, a project description, a blog claim, an honesty ledger, a dossier, or ANY document that asserts what the system does, is, or proves — especially verification claims ("formally verified", "proven", "sound", "verified N/N", trusted-base counts). It treats a document's load-bearing claims as requirements that must stay true over time: mark the assertion, bind it to checkable evidence, and gate it so drift fails the build. Use it to author an honest claim, to audit a doc whose claims may have drifted from reality, or to stand up the claim-check gate in a repo. Composes with traceability-audit (requirements↔tests), oracle-gate-a-change (the gate), and clean-room-verification (review the claim cold). metadata: author: pulseengine.eu - version: "0.1.0" + version: "0.2.0" --- # Claim verification @@ -35,8 +35,13 @@ commit.* 2. **Bind each claim to evidence a machine can re-derive** — never a number typed in prose (it goes stale the day the code changes). Evidence is a predicate: - `file-exists` — the proof/harness the claim rests on is present. - - `count-max` — re-count `external_body` / `admit` / `sorry` / `assume` from the - *actual source*; fail if it exceeds the recorded trusted-base size. + - `count-max` — an *upper bound*: re-count `external_body` / `admit` / `sorry` / + `assume` from the *actual source*; fail if it exceeds the recorded trusted-base + size. Use it only for growth claims — it greens a 0-match (`0 > max` is false), + so it must **not** gate a presence claim. + - `count-min` — the *presence* dual: fail when the pattern appears *fewer* than + `min` times. Use for must-exist claims (a version string, a required proof + marker) — it catches drift-to-absent, which `count-max` silently passes. - `no-new` — no new `sorry`/`admit` since the ledger's recorded count. - `badge` / `verbatim` — the README badge/tagline matches the ledger's honest wording exactly (a badge can't say "Formally Verified" while the ledger says diff --git a/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/claim-check.py b/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/claim-check.py index 5295e7a..9a5a8e9 100755 --- a/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/claim-check.py +++ b/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/claim-check.py @@ -86,6 +86,19 @@ def check_claim(c, root): f'trusted base grew: {n} > recorded max {ev["max"]} ' f'[/{ev["pattern"]}/] — update the claim, not the number' ) + elif kind == "count-min": + # PRESENCE claim: the pattern MUST appear >= min times. The dual of + # count-max (which greens a 0-match, since 0 > max is false). Catches + # DRIFT-TO-ABSENT — a string the doc asserts that the source no longer + # carries (e.g. a version bumped in Cargo.toml the README still names). + n, matched = _count(ev["pattern"], ev["glob"], root) + if not matched: + fails.append(f'predicate matched NO files (measures nothing): glob {ev["glob"]}') + elif n < ev["min"]: + fails.append( + f'claim evidence absent: {n} < required min {ev["min"]} ' + f'[/{ev["pattern"]}/] — the doc asserts it; the source no longer carries it' + ) elif kind == "no-new": n, matched = _count(ev["pattern"], ev["glob"], root) if not matched: diff --git a/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/claims.example.yaml b/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/claims.example.yaml index d4c053c..1bbfe8a 100644 --- a/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/claims.example.yaml +++ b/claude-tooling/plugins/pulseengine-claude/skills/claim-verification/claims.example.yaml @@ -43,3 +43,17 @@ claims: evidence: - kind: file-exists path: crates/falcon-esc-dshot/src/kani_proofs.rs + + # A PRESENCE claim: the README's version string must really be the shipped one. + # The obvious binding — count-max over Cargo.toml — SILENTLY GREENS a drift: when + # the version bumps, the pattern matches 0 times and `0 > max` is false. Presence + # / must-exist claims use count-min (fail when n < min), which bites the moment + # the source stops carrying the string the doc asserts. + - id: STATUS-VERSION + doc: README.md + text: "v3.2.4 shipped" + evidence: + - kind: count-min # Cargo.toml MUST still carry this exact version + pattern: 'version = "3\.2\.4"' + glob: ['Cargo.toml'] + min: 1 # bump the version → 0 matches → RED (drift caught)