Add the per-unit fidelity vocabulary (inert) (#374, PR-A) - #374
Merged
Conversation
Foundational, deterministically inert step toward verifying not just that carried content is present but how faithfully it survives the carry. Fidelity is a second per-unit axis, orthogonal to the appliesTo scope: scope decides which repos get a unit, fidelity decides how faithfully they must carry it. - spec/files.schema.json: add the `fidelity` enum (presence, intent, verbatim, interface) and the optional `contract` object (the interface engine's spec, consumed in a later PR). - spec/files.json: cross-link the fidelity model in the note, and set fidelity explicitly - verbatim on .markdownlint-cli2.jsonc, intent on the whole-carried governed configs and docs, presence (default) on the rest. - spec/validate.py: enforce the vocabulary - valid enum, a contract only on an interface unit (and required for one), and a verbatim unit's canonical source must resolve. - spec/fidelity-model.md (new, hub-only, sibling to scope-model.md): the fixed-vs-overridable contract, the four levels, why each unit sits where, the workflow override-seam contract, placeholder normalization, and the hash-not-version stale-vs-violated semantics. No audit behavior change: audit.py is untouched and no baseline path is added, so the required-file set and every finding are identical. The interface and verbatim engines that consume these fields follow in later PRs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces the "fidelity" axis to the carry-spec model as an inert (non-audit-impacting) foundation: a per-unit vocabulary describing how strictly carried content must match its canonical source, alongside optional interface-contract metadata for future engines.
Changes:
- Extend
spec/files.schema.jsonto allowfidelityand an optionalcontractobject on baseline entries. - Annotate baseline entries in
spec/files.jsonwith fidelity values (withpresenceas the default when omitted). - Add
spec/validate.pychecks enforcing the fidelity vocabulary and basic contract placement rules, plus a newspec/fidelity-model.mdexplainer.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| spec/validate.py | Adds validation rules for fidelity enum values, contract placement, and verbatim canonical-source existence. |
| spec/files.schema.json | Extends the JSON schema with fidelity and contract fields for baseline entries. |
| spec/files.json | Documents fidelity in the baseline note and assigns fidelity values to selected carried units. |
| spec/fidelity-model.md | New documentation describing the four fidelity levels and the intended verification semantics. |
- files.json: mark AGENTS.md fidelity intent (it is a governed carried doc, like CODESTYLE/WORKFLOW; its sections are judged by meaning, with the section-presence check the separate baseline layer). - validate.py: report the declared source string on a missing verbatim canonical instead of canonical.relative_to(ROOT), which raises ValueError for an absolute or outside-ROOT reference. Verified against an absolute reference. - files.json note: the audit mechanically checks presence; equivalence (intent) is judged by hand - correct the earlier "checks equivalence" overclaim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
spec/validate.py:236
- Since CI does not run JSON Schema validation (see the comment above this loop),
validate.pyshould also validate the shape of the newcontractobject and rejectreferencevalues that resolve outside the repo root. Otherwise malformedcontractvalues (null/non-object/typo keys) or an absolutereferencepath can slip through validation and later crash or create non-reproducible checks.
Also, while touching this comment block, keep it to one sentence without a semicolon per AGENTS.md comment/prose rules.
# fidelity governs how faithfully the unit is checked (spec/fidelity-model.md). A contract belongs
# only to an interface unit; a verbatim unit must have a resolvable canonical source to hash against.
fid = item.get("fidelity", "presence")
if fid not in FIDELITIES:
errors.append(f"files.json: {path} fidelity '{fid}' invalid (expected one of {', '.join(FIDELITIES)})")
Copilot round-2 findings: - files.json note: "each entry also has a fidelity (presence by default, or intent, verbatim, interface)" - the previous "carries a fidelity" implied every entry states one, but most rely on the default. - validate.py: since CI runs no JSON-schema validation, shape-check the new fidelity fields - a contract must be an object with only known keys, and a reference must be a repo-relative path (no leading / or ..) so an outside-root canonical cannot slip through. Verified against a non-object contract, an unknown contract key, and absolute/traversal references. Also drop the clause-joining semicolon in the edited comment. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
) Copilot round-3 findings: - validate.py: a non-string reference (number/list) reached ROOT / ref and raised TypeError; guard that reference is a string before using it, and only build the canonical path from a string source. Verified against a numeric and a list reference. - fidelity-model.md: "fidelity is a declared field defaulting to presence, never inferred from whole/placeholders" - the earlier "stated explicitly" read as if every entry writes it, but most rely on the default; the real point is declared-not-derived. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot round-4 finding: the contract was checked as an object with known keys, but value types were unchecked, so a malformed contract (a string where a job list is expected, etc.) would pass validation and later crash the interface engine. Verify each contract value type - requiredJobKeys/verbatimJobs are string arrays, requiredCheckName/artifactNameToken are strings, and require/forbidTokensInJob are objects of job name to string array. Verified each malformed shape is caught and a fully valid contract passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot round-5 finding: the fidelity shape-checks guard the new fields but the primary path field was still read with a default and never type-checked, so a missing or non-string path could slip through (CI runs no schema validation). Require path to be a string and skip the entry otherwise. Verified a missing and a non-string path are both reported without crashing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ptr727
added a commit
that referenced
this pull request
Jul 21, 2026
… PR-B) (#375) Second of the fidelity series (#374). Consumes `fidelity: interface`: the audit now verifies a carried workflow honors its **fixed contract by name and wiring**, never the owned body — the virtual-function signature check. ## Change - **`spec/audit.py`** - `split_jobs(text)` — slices a workflow into `{job_key: block}` by the jobs-level indent, no YAML parser (stdlib), mirroring `heading_texts`. - `check_interface(path, contract, text)` — required job keys, the ruleset-bound check `name:`, the `release-asset-<branch>-<target>` handoff, and per-job required (`pattern:`/`merge-multiple:`) and forbidden (`artifact-ids:`) tokens. **All findings DRIFT.** - An `interface` unit's **absence** is DRIFT too (not a hard LETTER) — a workflow's naming varies more than a carried config, so everything here is advisory. - `--selftest` (no network) — 7 fixture cases. - **`spec/files.json`** — two workflow `interface` entries: `test-pull-request.yml` (`appliesTo: "*"`, the universal `check-workflow-status` job + its ruleset-bound name) and `build-release-task.yml` (build types, the `get-version`/`github-release` jobs + artifact handoff + no-`artifact-ids:` rule). - **`AUDIT.md`** — notes the new check, and fixes pre-existing clause-joining semicolons in this file's comments/docstrings so they don't fester. ## Verified - `python3 spec/audit.py --selftest` → **7/7** (conformant, missing job+name, renamed check, artifact-ids fork, missing merge-multiple, owned extra-leaf-job no-finding, split_jobs). - **Positive control:** the hub's own canonical `test-pull-request.yml` and `build-release-task.yml` are **conformant** (0 findings). - `validate.py` green (contracts pass PR-A's value-type guards), lints clean. Scoping of `build-release-task.yml` is best-effort (excludes source-only/docs to avoid false "absent" DRIFTs); any mis-scope only yields advisory DRIFTs to triage. It refines as downstreams are audited. Held on `develop`. PR-C adds the verbatim engine. --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
ptr727
added a commit
that referenced
this pull request
Jul 21, 2026
…374, PR-C) (#377) Adds the verbatim fidelity engine: content-hash a carried unit (whole file, or a workflow job region) against the hub's canonical after EOL normalization, classifying a mismatch as stale (matches a past hub revision) or modified (matches none) via the canonical's git history. Integrity by hash, never a version stamp. Runs at DRIFT. Enabled on .markdownlint-cli2.jsonc and the github-release job region.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First of the fidelity series (#374). Adds a second per-unit axis to the carry model: fidelity — how faithfully carried content must survive — orthogonal to the
appliesToscope (which repos get it). This PR is the inert foundation; the engines that consume it follow.Changes
spec/files.schema.json— thefidelityenum (presence | intent | verbatim | interface) + the optionalcontractobject (the interface engine's spec, used in PR-B).spec/files.json— note cross-links the fidelity model; each entry gets an explicitfidelity:verbatimon.markdownlint-cli2.jsonc,intenton the whole-carried governed configs/docs,presence(default) on the rest.spec/validate.py— enforces the vocabulary: valid enum,contractonly on (and required for) aninterfaceunit, and averbatimunit's canonical source must resolve.spec/fidelity-model.md(new, hub-only, sibling toscope-model.md) — the fixed-vs-overridable contract, the four levels, why each unit sits where, the workflow override-seam contract, placeholder normalization, and the hash-not-version stale-vs-violated semantics.Inert
audit.pyis untouched and no baseline path is added, so the required-file set and every finding are identical — this PR only adds capability and documents the model.validate.pystays green and now also enforces fidelity; markdownlint/editorconfig-checker clean. Held ondevelop.Fidelity levels: presence (exists), intent (carried faithfully, judged by meaning), verbatim (byte-identical to canonical after placeholder normalization → content-hash), interface (honors a named contract by name/wiring, body owned). PR-B adds the interface engine + workflow entries; PR-C adds the verbatim engine.