Skip to content

Commit 1ff3bf5

Browse files
fix(hypatia): triage all 15 findings — 8 at source, 7 baselined (closes the red gate) (#146)
Closes the last red gate on main (governance / Validate Hypatia Baseline, failing since ≥07-22 when the scanner started actually working). **Fixed at source (8):** - The **critical** — `.hypatia-ignore:86` "Generic API key": self-referential FP; the comment *explaining* the API-key exemption itself contained the `KEY=\"...\"` assignment shape. Reworded. - my-hir guarded unwrap → `match`; my-lint 2× genuine empty-name panics → `is_some_and`; my-llvm SAFETY-comment adjacency. - ENSAID abi-verify workflow: `src/abi/*.idr` (nonexistent) → real Idris tree via **ipkg build** (per-file `--check` is a known fake gate). - Roadmap doc `Planned: src/{hir,mir,runtime}` → the shipped crates. **Baselined (7 entries, expire 2026-10-27, tracked in #145):** parser `self.expect()` name-collision FP (157×), my-fmt infallible Write-to-String unwraps (26×), my-llvm internal-invariant unwraps (3×), my-mir/string.rs deliberate invariant expects, measure_depth example, modules.md illustrative user-project paths. **Verified:** ran the reusable's own `apply-baseline.sh` locally against the post-fix finding set → 7 suppressed, 0 kept, exit 0. `cargo test -p my-hir -p my-lint` green. **Hygiene (owner-approved):** `.gitignore` secrets entries salvaged from the 07-26 sweep stash; `mise.toml` boilerplate → pinned rust 1.97.0. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 13b97a3 commit 1ff3bf5

9 files changed

Lines changed: 95 additions & 71 deletions

File tree

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,11 @@ CoqMakefile.conf
7272
.*.aux
7373
.*.d
7474
.lia.cache
75+
76+
# Secrets & local environment — never commit (salvaged from the 07-26 sweep,
77+
# the only useful entries in an otherwise template-clobbering diff)
78+
.env
79+
.env.*
80+
*.pem
81+
*.key
82+
.venv/

.hypatia-baseline.json

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,65 @@
1-
[]
1+
[
2+
{
3+
"severity": "medium",
4+
"rule_module": "code_safety",
5+
"type": "expect_in_hot_path",
6+
"file": "crates/my-lang/src/parser.rs",
7+
"note": "TRACKED DEBT (hypatia triage 2026-07-27): scanner false positive by name collision — the 157 hits are the parser's own `self.expect(TokenKind)?` Result-returning method, not Option/Result::expect panics. Worth an upstream hypatia rule fix.",
8+
"expires_at": "2026-10-27",
9+
"tracking_issue": "hyperpolymath/my-lang#145"
10+
},
11+
{
12+
"severity": "high",
13+
"rule_module": "code_safety",
14+
"type": "unwrap_without_check",
15+
"file": "crates/my-fmt/src/lib.rs",
16+
"note": "TRACKED DEBT (hypatia triage 2026-07-27): 26x `write!(self.output, ...).unwrap()` where output is String — fmt::Write to String is infallible, the unwrap can never panic. Candidate mechanical cleanup (w! macro / let _ =).",
17+
"expires_at": "2026-10-27",
18+
"tracking_issue": "hyperpolymath/my-lang#145"
19+
},
20+
{
21+
"severity": "high",
22+
"rule_module": "code_safety",
23+
"type": "unwrap_without_check",
24+
"file": "crates/my-llvm/src/lib.rs",
25+
"note": "TRACKED DEBT (hypatia triage 2026-07-27): 3x unwrap on get_nth_param/node_weight with indices from iterating the same structure — internal MIR invariants. Convert to expect(\"MIR invariant\") when the crate next compiles against system LLVM (cannot build here without LLVM 21).",
26+
"expires_at": "2026-10-27",
27+
"tracking_issue": "hyperpolymath/my-lang#145"
28+
},
29+
{
30+
"severity": "medium",
31+
"rule_module": "code_safety",
32+
"type": "expect_in_hot_path",
33+
"file": "crates/my-mir/src/lib.rs",
34+
"note": "TRACKED DEBT (hypatia triage 2026-07-27): 5x deliberate `expect(\"internal error: ...\")` invariant style on petgraph node lookups — panic-on-internal-bug is the crate's chosen failure mode for graph-index corruption.",
35+
"expires_at": "2026-10-27",
36+
"tracking_issue": "hyperpolymath/my-lang#145"
37+
},
38+
{
39+
"severity": "medium",
40+
"rule_module": "code_safety",
41+
"type": "expect_in_hot_path",
42+
"file": "crates/my-lang/lib/common/string.rs",
43+
"note": "TRACKED DEBT (hypatia triage 2026-07-27): single expect whose message carries the totality proof (`digit = num % radix < radix <= 36, so from_digit is total`) — infallible by construction.",
44+
"expires_at": "2026-10-27",
45+
"tracking_issue": "hyperpolymath/my-lang#145"
46+
},
47+
{
48+
"severity": "medium",
49+
"rule_module": "code_safety",
50+
"type": "expect_in_hot_path",
51+
"file": "crates/my-lang/examples/measure_depth.rs",
52+
"note": "TRACKED DEBT (hypatia triage 2026-07-27): 2x expect in a stack-depth probe example binary — panics are the appropriate failure mode in examples, there is no hot path.",
53+
"expires_at": "2026-10-27",
54+
"tracking_issue": "hyperpolymath/my-lang#145"
55+
},
56+
{
57+
"severity": "medium",
58+
"rule_module": "structural_drift",
59+
"type": "SD022",
60+
"file": "docs/wiki/language/modules.md",
61+
"note": "TRACKED DEBT (hypatia triage 2026-07-27): `src/utils/` here is an ILLUSTRATIVE user-project layout in the module-system documentation (how `mod utils;` resolves in a my-lang project), not a reference to this repo's tree. Rewording would degrade the docs; scoped suppression is correct.",
62+
"expires_at": "2026-10-27",
63+
"tracking_issue": "hyperpolymath/my-lang#145"
64+
}
65+
]

.hypatia-ignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ workflow_audit/scorecard_wrapper_missing_job_permissions:scorecard.yml
8383
code_safety/coq_axiom:proofs/verification/coq/solo-core/ResourceAlgebra.v
8484

8585
# --- Scanner false positive: env-var EXAMPLES in user docs. The install /
86-
# getting-started guides show `export OPENAI_API_KEY="..."` / `ANTHROPIC_API_KEY`
87-
# setup. The secret detector flags the `<KEY>="<value>"` assignment SHAPE
86+
# getting-started guides show how to export the OpenAI / Anthropic API-key
87+
# environment variables. The secret detector flags the assignment SHAPE
8888
# regardless of the value (the values here are placeholders — `<your-openai-key>`,
8989
# truncated `sk-ant-...` stubs — NOT real credentials; verified by inspection).
9090
# These are documentation, not code, and a real key does not belong in them.

.machine_readable/ENSAID_CONFIG.a2ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ description = "Run type system tests when type checker changes"
9090

9191
[workflows.abi-verify]
9292
trigger = "file_save"
93-
match = "src/abi/*.idr"
93+
match = "proofs/verification/idris/solo-core/*.idr"
9494
action = "run_command"
95-
command = "idris2 --check src/abi/Types.idr"
96-
description = "Verify ABI definitions when Idris2 files change"
95+
command = "idris2 --build proofs/verification/idris/solo-core/solo-core.ipkg"
96+
description = "Verify the mechanised solo-core when Idris2 files change (ipkg build, not per-file --check, so a missing module is a hard failure)"
9797

9898
; ─────────────────────────────────────────────────────────────────────
9999
; [clades] — panel clade taxonomy for this project

crates/my-hir/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,10 +586,9 @@ fn lower_ai_expr(ai_expr: &AiExpr) -> Result<HirExpr, HirError> {
586586
.map(lower_expr)
587587
.collect::<Result<Vec<_>, _>>()?;
588588

589-
let prompt = if hir_args.is_empty() {
590-
Box::new(HirExpr::Literal(HirLiteral::String(String::new())))
591-
} else {
592-
Box::new(hir_args.into_iter().next().unwrap())
589+
let prompt = match hir_args.into_iter().next() {
590+
None => Box::new(HirExpr::Literal(HirLiteral::String(String::new()))),
591+
Some(first) => Box::new(first),
593592
};
594593

595594
Ok(HirExpr::AI(match keyword {

crates/my-lint/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ impl Linter {
119119
TopLevel::Function(f) => self.lint_function(f),
120120
TopLevel::Struct(s) => {
121121
if self.config.check_naming_conventions {
122-
if !s.name.name.chars().next().unwrap().is_uppercase() {
122+
if s.name.name.chars().next().is_some_and(|c| !c.is_uppercase()) {
123123
self.diagnostics.push(Diagnostic {
124124
severity: Severity::Warning,
125125
code: "naming-convention".to_string(),
@@ -137,7 +137,7 @@ impl Linter {
137137
fn lint_function(&mut self, func: &FnDecl) {
138138
// Check naming conventions
139139
if self.config.check_naming_conventions {
140-
if !func.name.name.chars().next().unwrap().is_lowercase() {
140+
if func.name.name.chars().next().is_some_and(|c| !c.is_lowercase()) {
141141
self.diagnostics.push(Diagnostic {
142142
severity: Severity::Warning,
143143
code: "naming-convention".to_string(),

crates/my-llvm/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ impl<'ctx> Codegen<'ctx> {
320320
// 3. We use `i8_type()` as the element type so the indices are
321321
// byte-offset indices; the caller is responsible for having
322322
// scaled them to the intended element width before lowering.
323+
// SAFETY: see the GetElementPtr invariant argument directly above.
323324
unsafe {
324325
let gep = self.builder.build_gep(
325326
self.context.i8_type(),

docs/wiki/roadmap/compiler.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ Transformations:
171171
- Normalize AI expressions
172172

173173
```rust
174-
// Planned: src/hir/mod.rs
174+
// Shipped: crates/my-hir/src/lib.rs
175175
pub enum HirExpr {
176176
Literal(Literal, Type),
177177
Variable(DefId, Type),
@@ -194,7 +194,7 @@ Features:
194194
- AI call boundaries
195195

196196
```rust
197-
// Planned: src/mir/mod.rs
197+
// Shipped: crates/my-mir/src/lib.rs
198198
pub struct MirBody {
199199
blocks: IndexVec<BasicBlock, BasicBlockData>,
200200
locals: IndexVec<Local, LocalDecl>,
@@ -300,7 +300,7 @@ Components:
300300
**Target: Q3 2025**
301301

302302
```rust
303-
// Planned: src/runtime/ai.rs
303+
// Shipped: crates/my-ai/src/lib.rs
304304
pub trait AIProvider: Send + Sync {
305305
fn query(&self, request: QueryRequest) -> BoxFuture<QueryResponse>;
306306
fn embed(&self, text: &str) -> BoxFuture<Vec<f32>>;

mise.toml

Lines changed: 8 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,9 @@
1-
[tools]
2-
# Language runtimes
3-
node = "latest"
4-
python = "latest"
5-
rust = "latest"
6-
go = "latest"
7-
zig = "latest"
8-
java = "latest"
9-
bun = "latest"
10-
denojs = "latest"
11-
12-
# Package managers
13-
npm = "latest"
14-
yarn = "latest"
15-
pnpm = "latest"
16-
pip = "latest"
17-
cargo = "latest"
18-
go-task = "latest"
19-
20-
# Formatting & Linting
21-
gofmt = "latest"
22-
black = "latest"
23-
isort = "latest"
24-
ruff = "latest"
25-
prettier = "latest"
26-
shfmt = "latest"
27-
stylua = "latest"
28-
29-
# Build tools
30-
cmake = "latest"
31-
make = "latest"
32-
ninja = "latest"
1+
# SPDX-License-Identifier: MPL-2.0
2+
# mise toolchain pins — only what this repo actually uses.
3+
# The previous file was mint-time boilerplate pinning ~30 tools to "latest"
4+
# (Node/Go/Zig/Java/… none used here), which contradicts the estate's
5+
# reproducibility doctrine. my-lang is a Rust workspace + Coq/Idris2 proofs;
6+
# the provers are installed by CI (proofs.yml), not by mise.
337

34-
# Shell tools
35-
git = "latest"
36-
gnu-sed = "latest"
37-
gnu-tar = "latest"
38-
gnu-grep = "latest"
39-
40-
# Testing
41-
vitest = "latest"
42-
pytest = "latest"
43-
jest = "latest"
44-
45-
[env]
46-
# Common environment variables
47-
NODE_ENV = "development"
48-
PYTHONDONTWRITEBYTECODE = "1"
49-
PYTHONUNBUFFERED = "1"
50-
51-
# Task runner alias
52-
[alias]
53-
task = "go-task"
54-
build = "cargo build --release || npm run build || go build"
55-
test = "cargo test || npm test || go test ./..."
56-
lint = "ruff check . || prettier --check . || black --check ."
57-
fmt = "ruff format . || prettier --write . || black ."
8+
[tools]
9+
rust = "1.97.0"

0 commit comments

Comments
 (0)