Skip to content

PR-06: Checkpoint schema + cache invalidation + CI self-test (scanner) - #35

Merged
emmanuelgjr merged 1 commit into
mainfrom
improve/pr-06-checkpoint-schema-ci
Jul 18, 2026
Merged

emmanuelgjr merged 1 commit into
mainfrom
improve/pr-06-checkpoint-schema-ci

Conversation

@emmanuelgjr

Copy link
Copy Markdown
Contributor

Completes Phase 1 (the trust foundation). Depends on PR-05.

What's here

  • schemas/dsgai-scan.schema.json — formal schema for DSGAI-scan.json. It forbids match_text/content/value/raw_grep_output on every finding via "field": false (not "not": {"required": [...]}, which would let a lone forbidden field slip through). The redaction guarantee is now machine-checkable.
  • CLI self-checkself_validate_checkpoint() runs before writing (stdlib only, no jsonschema at runtime) and refuses (exit 2) to emit a finding carrying match content.
  • Cache invalidationcheckpoint_is_valid() reuses a checkpoint only at the current HEAD, on a clean working tree, with the current ruleset. The skill's resume logic calls this from PR-07 on. A compliance artifact must never serve stale findings with a fresh date.
  • .github/workflows/scanner-selftest.yml — installs ripgrep, runs pytest, validates the ruleset + a fixture scan against their schemas, and checks JSON⇄YAML sync. This is the gate that makes external rule PRs safely mergeable.

Bug fixed while here

The PCRE compile check keyed on the string "regex parse error" — but --pcre2 emits "PCRE2: error compiling...". So a broken PCRE2 pattern would have passed the check and not failed CI, defeating the whole gate. Now it keys on rg's exit code (>=2), with a guard-the-guard test.

Verification (all local)

  • pytest tests/ -q14 passed (adds checkpoint-schema, ruleset-schema, match_text-rejection, self-guard, and compile-guard tests).
  • Schema rejects a finding containing match_text (the acceptance negative test).
  • A deliberately broken PCRE is detected by exit code.
  • actionlint clean; both action SHAs verified real (checkout v4.2.2, setup-python v5.3.0).

After this merges, CONTRIBUTING's "rule PRs welcome once the self-test lands" is now true.

- schemas/dsgai-scan.schema.json: formal schema for DSGAI-scan.json that
  FORBIDS match_text/content/value/raw_grep_output on every finding
  ('field': false, not 'not/required' which would miss a lone field). The
  redaction guarantee is now machine-checkable.
- CLI self-validates the checkpoint (stdlib, no jsonschema at runtime) before
  writing and refuses to emit a finding carrying match content (exit 2).
- checkpoint_is_valid(): cache invalidation — a checkpoint may be reused only at
  the current HEAD, on a clean tree, with the current ruleset. The skill's
  resume logic uses this from PR-07 on; never serve stale findings with a fresh
  date.
- .github/workflows/scanner-selftest.yml: installs ripgrep, runs pytest,
  validates the ruleset + a fixture scan against their schemas, and asserts the
  JSON stays in sync with the YAML. This is the gate that makes external rule
  PRs safely mergeable.
- Fixed the PCRE compile check to key on rg's exit code (>=2) instead of the
  string 'regex parse error' — PCRE2 emits a different message, so the old
  check would have missed a broken PCRE2 pattern (and not failed CI). Added a
  guard-the-guard test.

Acceptance: pytest green (16 checks); schema rejects a match_text finding
(negative test); a deliberately broken PCRE is detected by exit code.
@requires_rg
def test_checkpoint_validates_against_schema(scan):
jsonschema = pytest.importorskip("jsonschema")
schema = json.loads(open(SCAN_SCHEMA, encoding="utf-8").read())
"""The redaction guarantee is machine-checkable: a finding carrying match
content must be rejected by the checkpoint schema."""
jsonschema = pytest.importorskip("jsonschema")
schema = json.loads(open(SCAN_SCHEMA, encoding="utf-8").read())

def test_rules_validate_against_schema():
jsonschema = pytest.importorskip("jsonschema")
rules = yaml.safe_load(open(RULES_YAML, encoding="utf-8"))
def test_rules_validate_against_schema():
jsonschema = pytest.importorskip("jsonschema")
rules = yaml.safe_load(open(RULES_YAML, encoding="utf-8"))
schema = json.loads(open(RULES_SCHEMA, encoding="utf-8").read())
@emmanuelgjr
emmanuelgjr merged commit 0874a0b into main Jul 18, 2026
9 checks passed
@emmanuelgjr
emmanuelgjr deleted the improve/pr-06-checkpoint-schema-ci branch July 18, 2026 06:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant