-
-
Notifications
You must be signed in to change notification settings - Fork 0
fix: the Hypatia gate could never fire — the defects that made it unconditionally vacuous #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,14 +45,28 @@ jobs: | |
| if: steps.install.outputs.installed == 'true' | ||
| run: | | ||
| set +e | ||
| panic-attack assail --format json . > panic-attack-findings.json 2>&1 | ||
| panic-attack assail --format json . > panic-attack-findings.json | ||
| PA_EXIT=$? | ||
| set -e | ||
|
|
||
| # Same defect class as the Hypatia job below: `2>&1` folded the | ||
| # scanner's stderr into the JSON payload, so every jq parse failed, | ||
| # every count silently became 0 via `|| echo 0`, and "Fail on critical | ||
| # findings" could never fire on any input. Keep stderr on the log. | ||
| if [ ! -s panic-attack-findings.json ]; then | ||
| echo "[]" > panic-attack-findings.json | ||
| fi | ||
|
|
||
| # Deliberately a WARNING, not a failure. panic-attack is a downloaded | ||
| # release binary whose exit-code and output contract are not verified | ||
| # here, and it has no confirmed --exit-zero equivalent, so we surface a | ||
| # malformed payload in the log rather than block on an unverified tool. | ||
| # Promote to `exit 1` (as the Hypatia job does) once that contract is | ||
| # confirmed -- see the follow-up issue linked from this PR. | ||
| if ! jq -e 'type == "array"' panic-attack-findings.json >/dev/null 2>&1; then | ||
| echo "::warning::panic-attack output is not a JSON array (exit ${PA_EXIT}); counts below are unreliable" | ||
|
Comment on lines
+66
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Normalise invalid panic-attack output before upload. When this branch only emits a warning, it retains the malformed payload for Replace the invalid payload with 🤖 Prompt for AI Agents
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please address this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
sed -n '45,85p;295,320p' .github/workflows/static-analysis-gate.ymlLength of output: 3588
Update the existing warning branch as follows: if ! jq -e 'type == "array"' panic-attack-findings.json >/dev/null 2>&1; then
echo "::warning::panic-attack output is not a JSON array (exit ${PA_EXIT}); counts below are unreliable"
echo "[]" > panic-attack-findings.json
fiThis keeps You are interacting with an AI system. |
||
| fi | ||
|
|
||
| # Parse finding counts | ||
| TOTAL=$(jq '. | length' panic-attack-findings.json 2>/dev/null || echo 0) | ||
| CRITICAL=$(jq '[.[] | select(.severity == "critical")] | length' panic-attack-findings.json 2>/dev/null || echo 0) | ||
|
|
@@ -71,13 +85,19 @@ jobs: | |
| if: steps.install.outputs.installed == 'true' | ||
| run: | | ||
| # Convert JSON findings into GitHub Actions annotations | ||
| jq -r '.[] | select(.file != null) | | ||
| # Findings carry no `.message` (keys: action,file,line,reason,rule_module, | ||
| # severity,type), so every annotation read "null". `.file` is an absolute | ||
| # runner path, which GitHub cannot anchor to the diff, so it is made | ||
| # workspace-relative here. | ||
| jq -r --arg ws "$GITHUB_WORKSPACE" '.[] | select(.file != null) | | ||
| (.file | ltrimstr($ws + "/")) as $f | | ||
| (.reason // .message // .type // "finding") as $m | | ||
| if .severity == "critical" then | ||
| "::error file=\(.file),line=\(.line // 1)::[panic-attack] \(.message)" | ||
| "::error file=\($f),line=\(.line // 1)::[panic-attack] \($m)" | ||
| elif .severity == "high" then | ||
| "::error file=\(.file),line=\(.line // 1)::[panic-attack] \(.message)" | ||
| "::error file=\($f),line=\(.line // 1)::[panic-attack] \($m)" | ||
| else | ||
| "::warning file=\(.file),line=\(.line // 1)::[panic-attack] \(.message)" | ||
| "::warning file=\($f),line=\(.line // 1)::[panic-attack] \($m)" | ||
| end | ||
| ' panic-attack-findings.json || true | ||
|
|
||
|
|
@@ -160,12 +180,28 @@ jobs: | |
| if: steps.build.outputs.ready == 'true' | ||
| run: | | ||
| set +e | ||
| HYPATIA_FORMAT=json "$HOME/hypatia/hypatia-cli.sh" scan . > hypatia-findings.json 2>&1 | ||
| HYPATIA_FORMAT=json "$HOME/hypatia/hypatia-cli.sh" scan . --exit-zero > hypatia-findings.json | ||
| HYP_EXIT=$? | ||
| set -e | ||
|
|
||
| if [ ! -s hypatia-findings.json ] || ! jq empty hypatia-findings.json 2>/dev/null; then | ||
| echo "[]" > hypatia-findings.json | ||
| # --exit-zero is Hypatia's own documented CI recipe (lib/hypatia/cli.ex), | ||
| # for exactly this case: "use in CI when a downstream step gates on | ||
| # severity counts". Findings go to stdout, the one-line summary to | ||
| # stderr, and the process exits 0 unless the SCANNER itself failed. | ||
| # | ||
| # Do NOT redirect stderr into the payload with `2>&1`: that folds the | ||
| # summary line into the JSON, so every parse fails, the old `[]` | ||
| # fallback substituted a clean result, CRITICAL was always 0, and the | ||
| # gate below could never fire on any input. Keep stderr on the log. | ||
| if [ "$HYP_EXIT" -ne 0 ]; then | ||
| echo "::error::Hypatia scanner execution failed with exit ${HYP_EXIT}" | ||
| exit "$HYP_EXIT" | ||
| fi | ||
| # `jq empty` is NOT sufficient -- it succeeds on any valid JSON, | ||
| # including a bare string, object or null. Assert the array. | ||
| if [ ! -s hypatia-findings.json ] || ! jq -e 'type == "array"' hypatia-findings.json >/dev/null; then | ||
| echo "::error::Hypatia did not produce a valid JSON findings array" | ||
| exit 1 | ||
| fi | ||
|
|
||
| TOTAL=$(jq '. | length' hypatia-findings.json 2>/dev/null || echo 0) | ||
|
|
@@ -183,13 +219,19 @@ jobs: | |
| - name: Emit check annotations | ||
| if: steps.build.outputs.ready == 'true' | ||
| run: | | ||
| jq -r '.[] | select(.file != null) | | ||
| # Findings carry no `.message` (keys: action,file,line,reason,rule_module, | ||
| # severity,type), so every annotation read "null". `.file` is an absolute | ||
| # runner path, which GitHub cannot anchor to the diff, so it is made | ||
| # workspace-relative here. | ||
| jq -r --arg ws "$GITHUB_WORKSPACE" '.[] | select(.file != null) | | ||
| (.file | ltrimstr($ws + "/")) as $f | | ||
| (.reason // .message // .type // "finding") as $m | | ||
| if .severity == "critical" then | ||
| "::error file=\(.file),line=\(.line // 1)::[hypatia] \(.message)" | ||
| "::error file=\($f),line=\(.line // 1)::[hypatia] \($m)" | ||
| elif .severity == "high" then | ||
| "::error file=\(.file),line=\(.line // 1)::[hypatia] \(.message)" | ||
| "::error file=\($f),line=\(.line // 1)::[hypatia] \($m)" | ||
| else | ||
| "::warning file=\(.file),line=\(.line // 1)::[hypatia] \(.message)" | ||
| "::warning file=\($f),line=\(.line // 1)::[hypatia] \($m)" | ||
| end | ||
| ' hypatia-findings.json || true | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,7 +23,7 @@ Part of the hyperpolymath -iser family (https://github.com/hyperpolymath/iserise | |
|
|
||
| ### Machine-Readable Metadata: `.machine_readable/` ONLY | ||
|
|
||
| These 6 a2ml files MUST exist in `.machine_readable/6a2/` directory ONLY: | ||
| These 6 a2ml files MUST exist in `.machine_readable/descriptiles/` directory ONLY: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Use canonical descriptor paths in maintenance and release metadata.
🤖 Prompt for AI Agents |
||
| 1. **STATE.a2ml** - Project state, progress, blockers | ||
| 2. **META.a2ml** - Architecture decisions, governance | ||
| 3. **ECOSYSTEM.a2ml** - Position in ecosystem, relationships | ||
|
|
@@ -111,7 +111,7 @@ dafniser/ | |
| ├── docs/ | ||
| │ └── architecture/ | ||
| │ └── TOPOLOGY.md # Module topology and data flow diagram | ||
| └── .machine_readable/ # ALL machine-readable metadata (6a2/ subdirectory) | ||
| └── .machine_readable/ # ALL machine-readable metadata (descriptiles/ subdirectory) | ||
| ``` | ||
|
|
||
| ## CORE INVARIANTS | ||
|
|
@@ -131,7 +131,7 @@ dafniser/ | |
|
|
||
| 1. Read THIS file (0-AI-MANIFEST.a2ml) first | ||
| 2. Understand canonical location: `.machine_readable/` | ||
| 3. Read `.machine_readable/6a2/STATE.a2ml` for current project state | ||
| 3. Read `.machine_readable/descriptiles/STATE.a2ml` for current project state | ||
| 4. State understanding of canonical locations | ||
|
|
||
| ## ATTESTATION PROOF | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Align the
.envguidance with the trust gate.If a developer follows this instruction and creates
.env,contractile.justfailstrust-no-secrets-committedbecause it runstest ! -f .env. Git-ignoring the file does not satisfy that check. Update the gate to reject only tracked secret files, or change this guidance and the loader to use a permitted file.🤖 Prompt for AI Agents