Skip to content

History / static guards

Revisions

  • docs: the tool-kind validation guards and the shape that was invisible Written from the diff, per ai-meta's change-documentation rule. validate_tool_kinds read tool: as a mapping only. serde_yaml's Value::get("kind") on a Sequence returns None, and the recursion cannot recover it because each sequence item is a {name, kind, …} mapping with no tool key of its own. So for the sequence form the walker collected nothing: the guard ran, returned successfully, and validated an empty set. Measured against the e2e corpus (166 files carrying a tool: key): 59 files had kinds it could not see, roughly 219 of 1,178. Shape distribution — 20 sequence-only, 109 mapping-only, 37 using BOTH in one file, so the mixed case is ordinary. Hand-verified on test_vars_block.yaml: five list-form blocks each carrying kind: python, extracted zero. Also records that the probe's raw after-figure is 3 rather than 0, and that all three are ground-truth over-counting on text inside string literals — so nobody later treats 3 as a residual gap to chase.

    @kadyapam kadyapam committed Oct 6, 2026
  • docs: the catalog listing guards, the partial-result failure mode, and Hazard 4 Written from the diff rather than from the central log, per ai-meta's change-documentation rule. Adds a `db/queries/catalog.rs` guards subsection and documents the failure mode it prevents, which is the part worth keeping: /api/catalog/list filtered `kind` case-sensitively while the column holds BOTH spellings, so a filter returned a PARTIAL set rather than an empty one. Measured on prod across 1,527 rows: 'Playbook' 875, 'playbook' 650, 'mcp' 2 — so "playbook" returned 650 of 1,525 playbooks and "Playbook" returned 875. Neither returned zero, which is why it survived four months. An empty result gets reported as a bug; a 43%-complete one gets believed. Nothing in tests/ mentioned resource_type (0 of 27 files), and the pre-existing shape guard asserted page.contains("kind = $1") — it had pinned the buggy predicate as correct while passing Some("Playbook") to it. Both halves are recorded because each alone is still wrong: predicate-only makes a caller sending Playbook match nothing, parameter-only still misses the 875 legacy rows written before f0301e86 lowercased registration and did not backfill. Also notes that an index on kind, if ever added, must be ON noetl.catalog (LOWER(kind)). Hazard 4 is new and distinct from Hazard 1: a guard that reads its whole file with include_str! counts the needle inside its OWN assertion messages. Mine reported 4 uses where the code has 2 and failed with the fix correctly in place — a false FAILURE, which invites relaxing a correct assertion until it agrees with the miscount. The fix slices with rfind rather than Hazard 1's split(..).next(), because this file has an earlier #[cfg(test)] with real code after it, and asserts the slice is plausibly large before using it.

    @kadyapam kadyapam committed Oct 6, 2026
  • wiki(static-guards): three pinned-label guards, and a stale claim about CI noetl/ai-meta#415, noetl/server#493. ## Corrects a stale claim this page was built on It said no cargo test runs in CI on any NoETL Rust repo, citing noetl/ai-meta#232. That stopped being true: #232 closed on 2026-10-02 and test.yml runs `cargo test --all-targets` on every pull request here, so these guards gate merges. Rewritten with the better reason they are tests rather than CI scripts: a guard beside the thing it guards moves with it, while a script reading src/ from outside drifts silently the moment a file is renamed. ## The three new guards Each uses a total match, so a new variant fails the BUILD rather than quietly adding an unpinned label, and each asserts the REVERSE direction too -- nothing pinned that no caller can produce. That reverse assertion found a live bug on its first run: engine_unavailable was pinned in EMBEDDED_READ_OUTCOMES and reachable by NO caller, because the verify handler returned early without touching the metric. The series was registered, read 0 for ever, and told anyone watching that the embedded engine was always available. ## Hazard 3 added: a mutation battery where no mutant was applied The battery for these guards reported 5 of 5 FIRES on its first run and was worthless -- the helper never forwarded its arguments, so nothing was mutated and the non-zero exits came from E0308 after a sed changed an array's length but not its contents. Records the three things a battery here must do: assert the mutation applied, count compile errors separately and require 0, and establish a green baseline one filter at a time (cargo test --lib a b c is a usage error, not three tests, and a red baseline makes every mutant look caught). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    @kadyapam kadyapam committed Oct 5, 2026
  • docs(server): record what every static guard prevents, and the two scanning hazards New page static-guards.md, cross-linked from Home and the sidebar. Written alongside noetl/server#490, which reviewed the four split("#[cfg(test)]") uses in handlers/ehdb_eventlog_mirror.rs. Two are sound — their assertions are contains(..), so truncation can only make them stricter — and were deliberately left unchanged. Two compare counts within the truncated slice and could false-pass on a site hidden below the cut; in handlers/events.rs that invisible region is 67% of the file, and two past direct-write defects were in exactly that file. The page exists because a guard whose purpose is unrecorded is a guard someone deletes as noise. It records, per guard, the defect that already happened at least once, plus the two hazards that produce confident wrong zeros: the truncation idiom and a test filter that matches nothing and exits 0. Refs noetl/ai-meta#361 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    @kadyapam kadyapam committed Oct 2, 2026