Skip to content

proof(conformance): fix corpus to match grammar; wire conformance gate - #43

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/gifted-fermat-EmVcv
Jun 14, 2026
Merged

hyperpolymath merged 1 commit into
mainfrom
claude/gifted-fermat-EmVcv

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Completes the conformance half of the "wire and conformance" task (the consensus/TLC half landed in #42). Wires the parser conformance corpus into CI and fixes the divergences uncovered when the corpus was first executed end-to-end against the real parser.

Root causes fixed

  1. The runner never actually ran the parser. conformance/run_conformance.sh invoked a non-existent entry point (Phronesis.CLI.parse). Replaced with mix run --no-start -e calling the real Phronesis.parse/1 (Lexer.tokenize |> Parser.parse). --no-start avoids booting the ra consensus supervision tree just to parse a file.

  2. Four "valid" samples were written against a syntax the language does not have (per spec/grammar.ebnf v0.2.0, whose stated source is parser.ex):

    • v02/v03/v07 used IF as the policy body, but the grammar requires logical_expr THEN action — IF is only a conditional action after THEN. They also dropped the required : on PRIORITY:/EXPIRES:/CREATED_BY:, used atoms (:valid), and string metadata.
    • v05 used x = expr let-bindings, for which there is no production.

    Rewritten to the real grammar while preserving each file's intent (conditional action, AND/OR connectives, IMPORT + module-qualified call, nested conditional action).

The parser was correct throughout — the corpus and the (also-broken) runner were the defects.

Interesting / worth noting

  • Parenthesised logical expressions are not in the grammar (factor only parenthesises arithmetic expressions). v03 therefore uses the equal-precedence left-associative form a AND b OR c = ((a AND b) OR c), which matches the original grouping intent semantically. Flagging in case grouped boolean conditions are desired as a future language feature.

Verification

Verified locally against the actual lib/phronesis/{token,ast,lexer,parser}.ex (the parse path compiled standalone and run over the corpus): 7/7 valid parse, 3/3 invalid rejected (10/10). The remaining 64 lib/ modules also compile cleanly standalone, so the CI mix compile step is expected green. (Full mix compile/mix deps.get could not be run locally — hex is unavailable in this environment — so the end-to-end mix run path is exercised in CI.)

New gate

.github/workflows/conformance.yml runs the corpus on every push/PR, reusing the estate-vetted actions/checkout + erlef/setup-beam pins and the project toolchain (Elixir 1.16 / OTP 26 per .tool-versions).

https://claude.ai/code/session_01DQACj3RFmAPZaBPgR9SAaS


Generated by Claude Code

Wire the parser conformance corpus into CI and fix the divergences found
when it was first run end-to-end against the real parser.

Root causes fixed:

* run_conformance.sh invoked a non-existent entry point
  (`Phronesis.CLI.parse`), so the corpus had never actually executed.
  Replaced with `mix run --no-start -e` calling the real
  `Phronesis.parse/1` (Lexer.tokenize |> Parser.parse). `--no-start`
  avoids booting the ra consensus supervision tree just to parse.

* Four "valid" samples were written against a syntax the language does
  not have (per spec/grammar.ebnf v0.2.0, whose source is parser.ex):
    - v02/v03/v07 used `IF` as the policy *body*; the grammar requires
      `logical_expr THEN action`, with `IF` only as a conditional
      *action* after THEN. They also dropped the required `:` on
      PRIORITY:/EXPIRES:/CREATED_BY:, used atoms (:valid), and string
      metadata.
    - v05 used `x = expr` let-bindings, for which there is no production.
  Rewritten to the real grammar while preserving each file's intent
  (conditional action, AND/OR connectives, IMPORT + module-qualified
  call, nested conditional action). Note: parenthesised *logical*
  expressions are not in the grammar, so v03 uses the equal-precedence
  left-associative form `a AND b OR c` = `((a AND b) OR c)`.

The parser was correct throughout; the corpus and the (also-broken)
runner were the defects. Verified locally against the actual
lib/phronesis/{lexer,parser}.ex: 7/7 valid parse, 3/3 invalid rejected.

New gate conformance.yml runs the corpus on every push/PR, reusing the
estate-vetted checkout + setup-beam pins and the project toolchain
(Elixir 1.16 / OTP 26 per .tool-versions).

https://claude.ai/code/session_01DQACj3RFmAPZaBPgR9SAaS
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 30 issues detected

Severity Count
🔴 Critical 0
🟠 High 7
🟡 Medium 23
View findings
[
  {
    "reason": "Action trufflesecurity/trufflehog@main needs attention",
    "type": "unpinned_action",
    "file": "secret-scanner.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Issue in secret-scanner.yml",
    "type": "missing_timeout_minutes",
    "file": "secret-scanner.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in scorecard-enforcer.yml",
    "type": "scorecard_publish_with_run_step",
    "file": "scorecard-enforcer.yml",
    "action": "split_scorecard_publish_job",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "binary_to_term without :safe option -- deserialization attack (1 occurrences, CWE-502)",
    "type": "elixir_send_unsanitised",
    "file": "/home/runner/work/phronesis/phronesis/lib/phronesis/compiler.ex",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "high"
  },
  {
    "reason": "Nominal-only SAST in phronesis: codeql.yml language matrix contains no language present in the repo and lacks `actions`, so CodeQL records zero results on every commit. Remediation: set the CodeQL matrix to `language: actions`.",
    "type": "StaticAnalysis",
    "file": "/home/runner/work/phronesis/phronesis",
    "action": "auto_fix",
    "rule_module": "scorecard",
    "severity": "medium",
    "remediation": "Add CodeQL or equivalent SAST workflow.",
    "scorecard_check": "SAST"
  },
  {
    "reason": "Repository has 3 non-main remote branch(es). Policy: single main branch only.",
    "type": "GS007",
    "file": ".",
    "action": "delete_remote_branches",
    "rule_module": "git_state",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD007 -- Hypatia structural_drift: SD007 -- 2 day(s) old",
    "type": "CSA001",
    "file": ".claude/CLAUDE.md",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD007 -- Hypatia structural_drift: SD007 -- 2 day(s) old",
    "type": "CSA001",
    "file": ".claude/CLAUDE.md",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD007 -- Hypatia structural_drift: SD007 -- 2 day(s) old",
    "type": "CSA001",
    "file": ".claude/CLAUDE.md",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD007 -- Hypatia structural_drift: SD007 -- 2 day(s) old",
    "type": "CSA001",
    "file": ".claude/CLAUDE.md",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath
hyperpolymath marked this pull request as ready for review June 14, 2026 12:43
@hyperpolymath
hyperpolymath merged commit 44c97cb into main Jun 14, 2026
9 checks passed
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.

2 participants