Skip to content

Audit umbrella: documented behaviour the code does not have (schema link restrictions, export flags, doc recursion) #958

Description

@avrabe

Umbrella from the inconsistency audit, claim-vs-code lens. Headline instance filed separately: #952 (sql read-only claim + --qualification-mode scope).

Note rivet docs check passes (64 files, 0 violations) — none of these gaps are machine-gated, which is itself the pattern.

Verification status: agent-reported with claim file:line + code file:line + an empirical check for each. I re-ran the sql and --qualification-mode ones myself (#952); the rest are recorded as reported.

1. link-types: source-types / target-types are documented as restrictions and never enforced

schemas/common.yaml:102-106 — the header defining the construct for all 30 shipped schemas: "source-types — (optional) restrict which artifact types may originate / target-types — (optional) restrict which artifact types may be targeted."

rivet-core/src/schema.rs:306-308 declares the fields; no validation path reads them. The only non-render reader is validate.rs:1254-1256, a suppression heuristic for prose-mention-without-typed-link — it uses the restriction to decide when not to warn. The sole enforced restriction is the artifact-type-level link-fields[].target-types (validate.rs:925-926). There is no source-type check anywhere.

Empirical: stpa.yaml:314-318 declares prevents with source-types: [system-constraint, controller-constraint], target-types: [hazard, sub-hazard]. A uca emitting prevents → L-001 (a loss) violates both, and validate returns PASS with zero diagnostics — while the coverage rule still reports the hazard as "needs an incoming prevents link". The illegal link is simultaneously unflagged and uncounted.

Highest-consequence item in this list: a schema author declaring source-types believes the graph is constrained.

2. export --format html — three documented flags silently ignored, config.js never generated

main.rs:742,746,750 document --homepage "written to config.js", --version-label, --versions. They arrive as _homepage, _version_label, _versions_json — underscore-prefixed unused params at main.rs:12114-12116. cmd_export_zola doesn't take them at all.

docs.rs:1807"Runtime customization is done entirely through config.js"; :1813 shows a file tree with config.js, requirements.html, matrix.html…; :1804 says "CSS is embedded inline with no external dependencies"; :1951 describes an externalCss mechanism. RIVET_EXPORT, config.js, externalCss and all seven documented CSS classes appear only in docs.rs.

Empirical: export with all three flags produces no config.js and no file containing the URL or label; index.html has zero <style> tags and links href="_assets/styles.css". Real layout is artifacts/index.html, matrix/index.html, etc.

3. Document scanning is non-recursive; the prose says recursive, and skips are silent

docs.rs:920-921- docs # loads docs/*.md recursively. document.rs:406 is std::fs::read_dir(dir) — one level. The module's own test comment at :2590 concedes it.

docs/ holds 60 .md but only 21 at top level; 4 frontmattered documents under docs/research/, docs/design/, docs/historical/ are invisible to the link graph, dropped with no warning — contradicting the "Loud-by-default doc scanning" design at docs.rs:625, since a file never enumerated cannot be declined. Knock-on: the exclude: "generated/**" example at :623 can never match.

4. init --vendor-schemas "immune to release-to-release rule drift" — false for bridges

main.rs:303 / docs.rs:790 make that claim. embedded.rs:249 discover_bridges() iterates the compiled-in list and falls back to embedded_bridge() when the on-disk file is absent, so a bridge added in a later release fires on a project vendored before it existed.

Empirical: with common/dev/stpa vendored and no stpa-dev.bridge.yaml, schema rules shows constraint-has-requirement active and rivet schema sources prints stpa-dev.bridge … embedded (compiled into rivet — changes on upgrade; vendor under schemas/ to pin) — the binary contradicting its own help text in one run.

5. ai-generated-needs-review can never fire on a valid store

schemas/common.yaml:430"AI-generated artifacts with active/approved status must have a reviewer." The rule body uses when: {field: status, equals: active}, but active is not among the nine values in the status enum (common.yaml:58-67), which is gated at Error severity. Condition::Equals is single-valued, so approved — also named in the description — never matches either.

Empirical: an AI-authored requirement with status: approved and no reviewer produces no such diagnostic (a sibling conditional rule does fire, proving the machinery works); with status: active it errors on the enum.

The shipped review gate on AI-authored artifacts emits zero warnings on every valid store — in a repo whose tool-confidence story leans on AI provenance. check_conditional_consistency (schema.rs:929-981) never cross-checks a when.equals value against the field's allowed-values, so nothing reports the dead rule.

6. AGENTS.md documents the release plan as baseline; the field is release

AGENTS.md:188-198"rivet's release plan lives in the baseline field … Scope a release = rivet list --filter '(= baseline "vX.Y.Z-track")'". The model field is release (model.rs:322), with --release, --set-release and a rivet release subcommand. sexpr_eval.rs:581-586 falls unknown bare names through to fields.get(...), so the query returns empty rather than erroring.

Empirical: --filter '(= baseline "v0.35.0-track")' → 0 artifacts; --release v0.35.0 → 12.

Second gap in the same file: AGENTS.md:7-10 says hand-authored content "lives below [the markers] … they survive regeneration" — but this section is at lines 186-205, inside the marker pair (END at :220). managed_section.rs:121 replaces the whole region, so rivet init --agents destroys it.

7. Smaller

  • docs.rs:2736-2738"At schema load time … the schema is rejected with a diagnostic." It's a validate-time Warning (schema.rs:936), reached from validation not load, and requirements_overlap only fires on identical requirements. Three overstatements in one sentence.
  • docs.rs:1085"Orphan detection: Artifacts never referenced in any document are flagged." links.rs:216-221 is "no incoming or outgoing links"; documents are not consulted.
  • main.rs:1522-1525"schemas for every --format json output (validate, stats, coverage, list)". Five ship (incl. query); ~52 --format json sites exist; diff, matrix, audit, commits, impact have none.
  • docs.rs:2106,2108,2240"The 15-Tool Catalog" / "fifteen tools". rivet mcp --list-tools16; the table omits rivet_bundle. CLI_DOC in the same binary says "the 16-tool catalog".
  • README.md:89rivet init --preset dev # scaffold rivet.yaml + schemas/ + artifacts/. main.rs:4355 guards the only create_dir_all(&schemas_dir) behind if vendor_schemas. A fresh init produces no schemas/.

Explicitly not filed

Stale counts with no behavioural consequence (schema type-count tables, "33 Playwright spec files", "28 Kani harnesses", README.md:152's "v0.5.0 series"), and normative statements whose adjacent comments already disclose non-enforcement (DSGVO at common.yaml:228-230, the SIL/DAL parentheticals). Worth a tidy pass, not a bug.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions