Skip to content

fix(governance): consult .hypatia-ignore for tsconfig/rescript.json check#167

Closed
hyperpolymath wants to merge 2 commits into
mainfrom
fix/governance-rescript-config-exemption
Closed

fix(governance): consult .hypatia-ignore for tsconfig/rescript.json check#167
hyperpolymath wants to merge 2 commits into
mainfrom
fix/governance-rescript-config-exemption

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Brings the Check for tsconfig / rescript config step in governance-reusable.yml in line with the existing banned-language-files step — both now honour .hypatia-ignore + inline # hypatia:ignore pragma per the Explicit-Escape Principle (standards#72).

The gap

Before this fix the step was:

if [ -f "rescript.json" ] || [ -f "bsconfig.json" ]; then
  echo "❌ rescript.json/bsconfig.json detected - use AffineScript config instead"
  exit 1
fi

— a hard [ -f config ] && exit 1 with no exemption mechanism. This blocks PRs in repos that legitimately retain ReScript while in mid-migration (per their .claude/CLAUDE.md language policy).

Reproduction

verisimdb#40 is a working example: the repo's .hypatia-ignore correctly exempts all 34 .res source files, and the banned-language-files step honours those. But rescript.json at the repo root still hard-fails the governance gate because this step has no .hypatia-ignore consultation.

Surfaced during the 2026-05-26 PR-queue sweep (see verisimdb#40 triage comment).

What changes

Same exemption mechanism as the banned-language-files step:

# .hypatia-ignore
cicd_rules/banned_config_file:rescript.json

…or an inline # hypatia:ignore cicd_rules/banned_config_file pragma in the first 8 lines (works for JSONC; strict JSON cannot carry a # comment).

Rule name

Introduces cicd_rules/banned_config_file — parallel to the existing cicd_rules/banned_language_file. Distinct rule because the failure surface is different (one config file vs many source files) and users can suppress them independently.

Behaviour now

  • File absent → no-op (silent pass)
  • File present, no exemption → unchanged failure (❌ … exit 1)
  • File present, exempted → prints ⏭️ exempt (cicd_rules/banned_config_file): <path> and continues

Refs verisimdb#40.

🤖 Generated with Claude Code

…heck

Brings the "Check for tsconfig / rescript config" step into line with
the existing banned-language-files step (which already honours
`.hypatia-ignore` + inline `# hypatia:ignore` pragma per the
Explicit-Escape Principle, standards#72).

Before this fix the step was an unconditional `[ -f rescript.json ] && exit 1`
with no exemption mechanism, which blocked PRs in repos that legitimately
retain ReScript while in mid-migration (per their `.claude/CLAUDE.md`).
Concrete case: verisimdb#40 has `.hypatia-ignore` exempting all 34 `.res`
source files correctly, but `rescript.json` at the repo root still hard-fails
the governance gate.

New behaviour:

  # .hypatia-ignore
  cicd_rules/banned_config_file:rescript.json
  cicd_rules/banned_config_file:tsconfig.json   # if needed

…or an inline `# hypatia:ignore cicd_rules/banned_config_file` pragma in
the first 8 lines (works for JSONC; not strict JSON).

Rule name: `cicd_rules/banned_config_file` — parallel to the existing
`cicd_rules/banned_language_file` rule.

Refs verisimdb#40 (the repro PR that surfaced this gap).

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

🔍 Hypatia Security Scan

Findings: 204 issues detected

Severity Count
🔴 Critical 64
🟠 High 114
🟡 Medium 26

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Python file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml-templates/state-scm-to-v2.py",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml/bindings/deno/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/lol/test/vitest.config.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/k9-svc/bindings/deno/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "Agda postulate assumes without proof -- potential soundness hole (4 occurrences, CWE-704)",
    "type": "agda_postulate",
    "file": "/home/runner/work/standards/standards/lol/proofs/theories/information_theory.agda",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "critical"
  },
  {
    "reason": "believe_me undermines formal verification (1 occurrences, CWE-704)",
    "type": "believe_me",
    "file": "/home/runner/work/standards/standards/lol/src/abi/Locale.idr",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "critical"
  },
  {
    "reason": "Wildcard CORS -- restrict to specific origins or use env var (1 occurrences, CWE-942)",
    "type": "js_wildcard_cors",
    "file": "/home/runner/work/standards/standards/consent-aware-http/examples/reference-implementations/deno/aibdp_middleware.js",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "high"
  },
  {
    "reason": "innerHTML assignment -- XSS risk, use textContent or SafeDOM (1 occurrences, CWE-79)",
    "type": "js_innerhtml",
    "file": "/home/runner/work/standards/standards/axel-protocol/src/Tea.res.js",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "high"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

hyperpolymath added a commit that referenced this pull request May 26, 2026
…ble (semantics-level fix for estate-template drift) (#168)

## Why

Multiple PRs in the estate inbox are failing on a single bug class:
**per-repo workflow templates copy-drift away from the canonical estate
policy**. The repro that surfaced it was self-inflicted: PR #167 to this
repo failed its own \`Check for Banned Languages\` step because
\`language-policy.yml\` does a naive \`find -name \"*.py\"\` that
bypasses
\`.hypatia-baseline.json\` — even though the file in question is already
acknowledged there.

The same gap appears in absolute-zero, maa-framework, and any other repo
that still ships a local copy of either workflow. Patching each copy
individually treats the symptom; the foundational fix is to delete the
copies and consume a single reusable workflow.

## What changes

| File | Change |
|---|---|
| \`.github/workflows/governance-reusable.yml\` | language-policy job
extended: now also catches Makefiles, Java/Kotlin, Swift, Flutter/Dart,
V-lang manifests, ATS2 sources, and \`package.json\` with runtime
\`\"dependencies\"\`. All go through the existing \`enforce()\` /
\`is_exempt()\` helpers — so every newly-covered check honours
\`.hypatia-baseline.json\`, \`.hypatia-ignore\`, and inline \`#
hypatia:ignore …\` pragmas. |
| \`.github/workflows/language-policy.yml\` | Deleted.
\`governance.yml\` (the thin wrapper) already calls
\`governance-reusable.yml\` via \`workflow_call\`, so estate coverage is
unchanged — but the bug class becomes structurally impossible: the naive
find-based check no longer exists to be drift-copied. |
| \`.github/workflows/deno-ci-reusable.yml\` | **New**. Replaces the
broken \`rescript-deno-ci.yml\` template that's been failing across the
estate. Detects Deno targets/tests/config first and only runs
lint/fmt/test/check when applicable. Declares top-level
\`permissions:\`. Drops the banned \`npx rescript\` step and the
vestigial security-grep job. |

## What was broken in the old \`rescript-deno-ci.yml\`

Observed across absolute-zero #41 and tma-mark2 #41:

* \`deno test --allow-all\` ran unconditionally and exit-1'd on \`No
test modules found\` in repos without Deno tests.
* \`deno lint\` / \`deno fmt --check\` ran unconditionally and exit-1'd
on \`No target files found\` in repos without JS/TS targets.
* Missing top-level \`permissions:\` declaration — tripped
governance-reusable's workflow-security-linter.
* Still ran \`npm install && npx rescript\` even though ReScript was
banned in new code 2026-04-30 (per \`.claude/CLAUDE.md\`).
* Vestigial \`security\` job that grep'd for permission strings and did
nothing with the output.

## Downstream rollout

Each repo carrying \`rescript-deno-ci.yml\` or its own
\`language-policy.yml\` is now eligible to delete its copy and consume
the reusable:

\`\`\`yaml
jobs:
  deno-ci:
uses:
hyperpolymath/standards/.github/workflows/deno-ci-reusable.yml@main
\`\`\`

Follow-up PRs will land per-repo against absolute-zero, tma-mark2, etc.

## Relationship to PR #167

#167 patches the tsconfig/rescript-config check in this same file to
honour \`.hypatia-baseline.json\`. This PR is orthogonal: #167 fixes a
single step's exemption logic; this PR consolidates two workflows so the
duplication itself goes away. Either can land first; rebase is trivial.

## Test plan

- [ ] Governance reusable still passes on this PR (its own CI run will
exercise the consolidated language-policy job, including against this
repo's \`a2ml-templates/state-scm-to-v2.py\` baseline entry — which the
reusable already honours).
- [ ] Workflow-security-linter check passes (deno-ci-reusable has SPDX +
top-level \`permissions:\`).
- [ ] Once merged, run a fanout PR converting \`absolute-zero\` +
\`tma-mark2\` to the wrappers and confirm green.
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 192 issues detected

Severity Count
🔴 Critical 64
🟠 High 100
🟡 Medium 28

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/deno-ci-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "deno-ci-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Python file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml-templates/state-scm-to-v2.py",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml/bindings/deno/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/lol/test/vitest.config.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/k9-svc/bindings/deno/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "Agda postulate assumes without proof -- potential soundness hole (4 occurrences, CWE-704)",
    "type": "agda_postulate",
    "file": "/home/runner/work/standards/standards/lol/proofs/theories/information_theory.agda",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "critical"
  },
  {
    "reason": "believe_me undermines formal verification (1 occurrences, CWE-704)",
    "type": "believe_me",
    "file": "/home/runner/work/standards/standards/lol/src/abi/Locale.idr",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "critical"
  },
  {
    "reason": "Wildcard CORS -- restrict to specific origins or use env var (1 occurrences, CWE-942)",
    "type": "js_wildcard_cors",
    "file": "/home/runner/work/standards/standards/consent-aware-http/examples/reference-implementations/deno/aibdp_middleware.js",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "high"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath enabled auto-merge (squash) May 26, 2026 07:14
@hyperpolymath
Copy link
Copy Markdown
Owner Author

Closing as obsolete: #168 (merged) subsumed this fix's scope. The tsconfig/rescript-config check now lives in the consolidated language-policy job within governance-reusable.yml and honours .hypatia-baseline.json + .hypatia-ignore + inline pragmas via the shared enforce()/is_exempt() helpers.

auto-merge was automatically disabled May 26, 2026 07:58

Pull request was closed

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