Skip to content

feat(rules): SD022 + SD023 — stale-path-after-rename + STATE.a2ml divergence#425

Merged
hyperpolymath merged 2 commits into
mainfrom
feat/sd022-sd023-rename-drift-state-divergence-2026-06-02
Jun 2, 2026
Merged

feat(rules): SD022 + SD023 — stale-path-after-rename + STATE.a2ml divergence#425
hyperpolymath merged 2 commits into
mainfrom
feat/sd022-sd023-rename-drift-state-divergence-2026-06-02

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Two new structural-drift rules wired into Hypatia.Rules.StructuralDrift.scan/1, addressing exactly the drift patterns surfaced by the 2026-06-02 estate sweep against JoshuaJewell/paint-type.

  • SD022 — stale path references after directory rename. Scans docs (.md/.adoc/.a2ml/.contractile/.toml/.twasm) for src/<dir>/ patterns where <dir> is not a real subdir. Exempts CHANGELOG.md (historical) + third_party/ (vendored). trigger_intensive: true (one drift hit predicts others).
  • SD023 — STATE.a2ml divergence between .machine_readable/STATE.a2ml and .machine_readable/6a2/STATE.a2ml. Matches last-updated in both TOML and Scheme variants.

Empirical motivation

paint-type PR #48 renamed src/ephapax/src/paint_core/ in the Cargo workspace, leaving 49 stale references across 25 docs. Top-level STATE.a2ml said 2026-06-01 / 22%; 6a2/STATE.a2ml said 2026-05-11 / 10%. Caught only by manual sweep (paint-type#49). These rules close that detection gap.

Test plan

  • mix compile (verified via Code.string_to_quoted: both files parse clean)
  • mix test test/structural_drift_test.exs — 7 new tests under describe "sd022_…" + describe "sd023_…"
  • StructuralDrift.scan/1 returns SD022+SD023 in findings when triggered

…ergence

Adds two new structural-drift rules to catch the exact drift patterns
surfaced by the 2026-06-02 estate sweep against JoshuaJewell/paint-type.

## SD022 — stale-path-after-rename (medium / trigger_intensive)

When a source directory is renamed in a single commit, trailing-edge
doc references frequently outlive the rename. Detection: enumerate
real `src/*/` subdirs in the tree, scan docs (.md / .adoc / .a2ml /
.contractile / .toml / .twasm) for `src/<dir>/` regex matches, flag
any whose `<dir>` is not in the real-subdir set.

Exemptions:
  - CHANGELOG.md (historical references are documentation, not drift)
  - third_party/ subtree (vendored, owned upstream)

Recovery action: `sed -i s|src/<stale>|src/<new>|g` across the
flagged file set. Identify <new> via `git log --diff-filter=R`.

Empirical: caught 49 occurrences across 25 files on paint-type after
PR #48 renamed src/ephapax → src/paint_core in the Cargo workspace
but updated no docs. Manual sweep landed as paint-type#49.

## SD023 — STATE.a2ml divergence (medium)

Some repos retain both legacy `.machine_readable/STATE.a2ml` and
canonical `.machine_readable/6a2/STATE.a2ml`. When both exist, they
MUST agree on `last-updated` — otherwise consumers (Hypatia, agents
reading 6a2) see inconsistent reality.

Detection: extract `last-updated` from each via regex matching both
TOML (`last-updated = "..."`) and Scheme (`(last-updated "...")`)
variants. Flag if both exist + dates disagree.

Empirical: paint-type top-level STATE was 2026-06-01 / 22% completion;
6a2/STATE was 2026-05-11 / 10% completion. Unified in paint-type#49.

## Test coverage

7 new test cases:
  - SD022: positive case (ephapax→paint_core); CHANGELOG exemption;
    third_party/ exemption; empty src/ baseline
  - SD023: positive divergence; matching dates (no finding);
    only-one-file (no finding); Scheme-variant matching

All tests use the same temporary-dir + git-init pattern as existing
SD001-SD014 tests.

## Wired into scan/1

Both rules appended to the comprehensive scan pipeline. SD022 finds
contribute trigger_intensive=true (one rename-drift hit predicts
others); SD023 stays advisory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

🔍 Hypatia Security Scan

Findings: 146 issues detected

Severity Count
🔴 Critical 0
🟠 High 0
🟡 Medium 146
View findings
[
  {
    "reason": "Action urin 21 JRE\n        uses: actions/setup-java@be666c2fcd27 needs attention",
    "type": "unpinned_action",
    "file": "verify-proofs.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in clusterfuzzlite.yml",
    "type": "missing_timeout_minutes",
    "file": "clusterfuzzlite.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath merged commit 34f6451 into main Jun 2, 2026
@hyperpolymath hyperpolymath deleted the feat/sd022-sd023-rename-drift-state-divergence-2026-06-02 branch June 2, 2026 19:15
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

🔍 Hypatia Security Scan

Findings: 166 issues detected

Severity Count
🔴 Critical 0
🟠 High 0
🟡 Medium 166
View findings
[
  {
    "reason": "Action urin 21 JRE\n        uses: actions/setup-java@be666c2fcd27 needs attention",
    "type": "unpinned_action",
    "file": "verify-proofs.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in clusterfuzzlite.yml",
    "type": "missing_timeout_minutes",
    "file": "clusterfuzzlite.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

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