# INITKOA CONTEXT PACK repository: Rejean-McCormick/VotingMachine source_commit: 8aa367410822d2013ce0df377fad651aa26bd23e source_mode: git working_tree_markdown: clean working_tree_selected: clean selection_mode: markdown wiki_source_commit: none wiki_working_tree_markdown: none policy_version: 2026-09-10.13 repo_files: 13 wiki_files: 0 source_files: 13 included_files: 13 excluded_files: 0 duplicate_files: 0 content_bytes: 232627 authority_counts: {"reference":13} content_role_counts: {"knowledge":13} generated_at: 2026-09-10T13:04:25-04:00 files: 13 content_sha256: 99dd62272f8ee3cc492d943c6ce335dfdf4cf8b6b0cea62d03271d66d25f1836 ================================================================================================ FILE INDEX ================================================================================================ 01. [reference] [knowledge] CONTRIBUTING.md | bytes=6615 | sha256=064a1ba53c8b538bbb550df1bd243b9ea3dfdd42a308b76daebd0b321593ce9a 02. [reference] [knowledge] docs/Annex A — Variable Canonical Reference Table.md | bytes=17441 | sha256=04109f935e1821f355a5c3702821fc7a26ce0c45bef56f1d7f0babc646837cb0 03. [reference] [knowledge] docs/Annex B — Canonical Test Pack.md | bytes=33811 | sha256=2ef261a67724a9535dd0a054e713c58713284f418c47dd22feed38a0923a3adc 04. [reference] [knowledge] docs/Annex C — Glossary & Definitions.md | bytes=7878 | sha256=9b59f176e44f17d57641b53288eed4c497abb77c2d6be509f0d42b7c9d5c931c 05. [reference] [knowledge] docs/Doc 1 — Database Specification (Entities, Fields, Relationships).md | bytes=30045 | sha256=588612c0d960132b1e3909eabb297f43edeae5b91cd5d906d1dfa66ba044f023 06. [reference] [knowledge] docs/Doc 2 — Common Variables Specification (Core, Operational Defaults, Advanced Controls).md | bytes=18810 | sha256=8876349e09f4e913b8e6b359140bbbde797c2ec0eae06f3e075dbcf9942b08ad 07. [reference] [knowledge] docs/Doc 3 — Technical Platform & Release Policy.md | bytes=13349 | sha256=70a65613deda315434fad00eefa6c55816873c6a5a7cae823416c8efca207e3e 08. [reference] [knowledge] docs/Doc 4 — Algorithm Specification (Steps, Allocation, Gates & Edge Cases).md | bytes=23626 | sha256=a6ddb363639ea9864da29a1a2f17682a219365c875de2a7336eeeffb05a5aadc 09. [reference] [knowledge] docs/Doc 5 — Processing Pipeline Specification (State Machine & Functions).md | bytes=25745 | sha256=708baf42eb7fcbd29b0395eb54a5c06526b4de1bf424d8b6054326ed0cfbc664 10. [reference] [knowledge] docs/Doc 6 — Test Specifications (Allocation, Gates, Frontier & Determinism).md | bytes=22600 | sha256=9c8965c209ebfec0040ccdc48138c846d3bd279c4ac8bb0f8b7bed2e78d20bd3 11. [reference] [knowledge] docs/Doc 7 — Reporting Specification (Structure, Templates & Visual Rules).md | bytes=18218 | sha256=7446e59096b30369962d4ae02eb7525807454508d455985ce313f0f6bcc04028 12. [reference] [knowledge] README.md | bytes=7781 | sha256=d12eb1e7df35b82e6e76c9e01dc98516c5047ed79faafab51738820d00d4c5cd 13. [reference] [knowledge] SECURITY.md | bytes=6708 | sha256=cd7353ea42a1038e648ad4eb8aa7b4e29215ea8b29afea33cac558e90e9daa73 ================================================================================================ FILE: CONTRIBUTING.md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 064a1ba53c8b538bbb550df1bd243b9ea3dfdd42a308b76daebd0b321593ce9a CONTENT_BYTES: 6615 ================================================================================================ ````markdown # CONTRIBUTING.md — VM-ENGINE v0 _Component 11/89 • How to propose changes without breaking specs, determinism, or offline policy._ ## Principles (spec-first) - **Docs 1–7 + Annex A/B/C are normative.** If code conflicts with the specs, fix the code (and its skeleton sheet). - **Normative changes require spec edits first.** Open an ADR and update the relevant Doc/Annex before code lands. - **Determinism is a hard gate.** Same inputs (+ same seed when random ties are enabled) must produce **byte-identical** outputs. --- ## Prerequisites - Rust toolchain pinned by `rust-toolchain.toml` (`rustup show` should match). - `cargo` available; `pre-commit` optional but recommended. - Build **offline by default** (see `.cargo/config.toml`). For a first fetch: `CARGO_NET_OFFLINE=0 cargo fetch`. --- ## Workflow overview 1. **Create a short topic branch** from `main`. 2. Make changes with **Conventional Commits** and **spec references**: - `feat(vm_algo): implement Doc4A §2.2 step order (ref VM-TST-002)` - `fix(vm_report): one-decimal rounding per Doc7 §5` 3. **Run local gates** (fast → heavy): `pre-commit run -a` → `git push` (triggers pre-push hooks) → open PR. 4. In the PR description, include: - Spec refs (e.g., *Doc 4 — Algorithm Specification, §2.2*). - Affected tests/fixtures (e.g., *VM-TST-001/003*). - Whether behavior is normative (FID-affecting) or not. --- ## Formatting, linting, and hygiene - **Rust format**: `cargo fmt --all -- --check` - **Clippy (deny warnings)**: `cargo clippy --all-targets -- -D warnings` - **LF/UTF-8 only**: enforced by `.gitattributes` and hooks. - **Canonical JSON**: UTF-8, **LF**, **sorted keys** (no ad-hoc pretty printing). - **Editor defaults**: see `.editorconfig`. > Tip: install and enable `pre-commit`; the repo includes `.pre-commit-config.yaml` with fast checks and a pre-push smoke test. --- ## Tests you must run locally ```bash # Unit/integration tests cargo test --locked --workspace # Minimal Annex B fixture (example) ./target/release/vm_cli run \ --manifest fixtures/annex_b/VM-TST-001/manifest.json \ --output artifacts/tst001 # Determinism smoke (same seed → identical bytes) SEED=42 ./target/release/vm_cli run --manifest fixtures/annex_b/VM-TST-001/manifest.json --rng-seed $SEED --output artifacts/a ./target/release/vm_cli run --manifest fixtures/annex_b/VM-TST-001/manifest.json --rng-seed $SEED --output artifacts/b cmp -s artifacts/a/result.json artifacts/b/result.json cmp -s artifacts/a/run_record.json artifacts/b/run_record.json ```` **Offline rule:** once dependencies are fetched or vendored, builds/tests must pass with `CARGO_NET_OFFLINE=1`. --- ## Changing schemas, fixtures, or specs ### Schemas (`schemas/**`) 1. Update schema shape (keep canonical ordering stable). 2. Update loader/validator code and any impacted tests. 3. Re-run affected fixtures; if expected outputs must change, explain **why** (spec-driven) in the PR. ### Fixtures (`fixtures/annex_b/**`) * **Never** change fixtures merely to “make a test pass”. Fix the code or the spec. * When normative outputs change, regenerate expected `result.json`/`run_record.json` and document the spec deltas. ### Specs & variables (Doc 2 / Annex A) * **VM-VAR additions/modifications** only via PRs that: * Update **Doc 2** (definitions, ranges, defaults). * Update **Annex A** (canonical reference table, FID membership). * Include migration notes and explicitly call out whether the change is **FID-affecting**. --- ## Algorithm & determinism rules (must-follow) * **Ordering**: Follow Doc 4/5 step order; do not rely on map/hash iteration order. * **Math**: Integers/rationals only for comparisons; avoid floats in outcome logic. * **Rounding**: Apply **once**, at the defined comparison/presentation points (reports show **one decimal**). * **Ties**: * Default deterministic policy: by `order_index` (spec). * If `tie_policy=random` (VM-VAR-050), use the provided seed (VM-VAR-052, **non-FID**) and record it in `RunRecord` **only when a random tie actually occurred**. * **IDs**: `RES:` / `RUN:-` computed over **canonical bytes** (UTF-8/LF/sorted keys; arrays in defined order). --- ## Versioning & Formula ID (FID) * **Engine version**: bump when binaries/public API change **without** altering outcomes. * **Formula ID**: bump when any **normative** behavior changes (variables, constants, steps, ordering). * Include the regenerated FID manifest and a short ADR summarizing the rationale and impacted tests. --- ## Commit & PR conventions * **Conventional Commits**: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `build:`, `chore:` * Keep subject ≤ 72 chars; wrap body at \~100 cols. * Include spec refs and test IDs in the body: ``` Implements Doc4A §2.2; updates Annex A (VM-VAR-050 note). Affects: VM-TST-002/003; FID bumped: yes. ``` --- ## ADRs (Architecture/Decision Records) * Place ADRs in `docs/adr/NNN-title.md` with: * Context → Decision → Consequences → Spec sections affected → Tests affected → FID impact (yes/no). --- ## Reporting (Doc 7) * Renderer reads canonical artifacts; **no recomputation**. * Show **one-decimal** percentages (round-half-up) and keep section order fixed. * If adding sections/visual rules, update **Doc 7** first and add matching tests. --- ## Review & merge flow 1. Author: run local hooks/tests (offline). 2. PR: include spec refs, tests touched, FID/engine version impact, ADR link if normative. 3. Reviewer: verify spec alignment, determinism (double-run bytes), and offline policy. 4. CI mirrors local gates. Merge when **all green**. --- ## Edge cases → reject or fix before review * Random tie policy enabled **without** seed validation. * WTA with `magnitude ≠ 1`. * CRLF introduced or unsorted JSON in canonical artifacts. * Any dependency that forces network at build/test time post-vendoring. --- ## Pre-PR checklist (must pass) * [ ] `cargo fmt --all -- --check` * [ ] `cargo clippy --all-targets -- -D warnings` * [ ] `cargo test --locked --workspace` * [ ] Minimal Annex-B fixture(s) pass and **determinism smoke** is byte-identical with same seed * [ ] Spec references included (Doc/Annex sections) * [ ] If normative: ADR added, FID impact stated, fixtures/expectations updated --- ## Post-merge notes * Keep `CHANGELOG.md` with sections: **Spec compliance** and **Behavioral changes**. * Release bundles in `dist/` must include `LICENSE` (and `NOTICE` if Apache terms are exercised) and third-party attributions. ``` ``` ================================================================================================ FILE: docs/Annex A — Variable Canonical Reference Table.md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 04109f935e1821f355a5c3702821fc7a26ce0c45bef56f1d7f0babc646837cb0 CONTENT_BYTES: 17441 ================================================================================================ # **Annex A — VM-VAR Registry (Updated)** **Part 1 of 3 — Scope, FID/Manifest Rules, Schema & Conventions** ## **1\) Status & scope** * **Normative.** Single source of truth for VM-VAR **IDs, names, domains, defaults, FID inclusion, and usage pointers**. * No backward compatibility notes. The scheme in this edition is: **ties at 050/052; 051 reserved; presentation 060–062 excluded from FID.** ## **2\) Normative Manifest & FID rules** **What goes into the Formula ID (FID):** * All **outcome-affecting rules** \+ the **Included** VM-VAR keys/values from this annex. * Canonicalized and hashed per Doc 1A. **Included (FID) — variable ranges/IDs** `001–007, 010–017, 020–031, 040–049, 050, 021, 029, 030, 031, 045, 046, 047, 048, 049, 073` (De-duplicated list; same meaning: *all outcome-affecting groups, including 050; seed 052 is excluded*.) **Excluded (non-FID)** `032–035, 052, 060–062` (presentation/report toggles and the tie seed). **Ordering when building the manifest:** 1. Sort variables by **numeric ID** ascending (e.g., 001, 002, …, 073). 2. For each, serialize as canonical JSON key/value (`"VM-VAR-###": value`). 3. Do not include absent **Excluded** vars; may be echoed in `RunRecord` but never change FID. **Canonicalization:** bytes \= UTF-8, LF, **sorted keys** at all object levels (Doc 1A). ## **3\) Registry entry schema (authoritative fields)** Every variable is defined with these fields: | Field | Meaning | | ----- | ----- | | `id` | `VM-VAR-###` (three digits, zero-padded) | | `name` | canonical `snake_case` | | `type` | \`enum | | `domain` | precise allowed set/range/shape (deterministic) | | `default` | canonical default value (used if unset) | | `fid` | `Included` or `Excluded` | | `used_by` | pointers to consuming docs/sections (e.g., `Doc4C`) | | `notes` | brief constraints (precedence, ordering, reserved, etc.) | **Machine-readable envelope (packaged with releases):** { "schema\_version": "1.x", "vars": \[ { "id": "VM-VAR-050", "name": "tie\_policy", "type": "enum", "domain": \["status\_quo","deterministic\_order","random"\], "default": "status\_quo", "fid": "Included", "used\_by": \["Doc4C","Doc5B-008","Doc6C"\], "notes": "051 reserved; deterministic order uses option.order\_index" } // ... all other entries appear here in numeric order \] } ## **4\) Determinism & RNG anchors (ties)** * **VM-VAR-050** (*tie\_policy*) is **Included** in FID. * **VM-VAR-052** (*tie\_seed*) is **Excluded** from FID; recorded in `RunRecord.determinism.rng_seed` **iff** a random tie occurred. * **VM-VAR-051** is **reserved** (no meaning). * RNG algorithm/profile is pinned in **Annex B**; engines must draw **exactly *k* 64-bit values for a *k*\-way tie**, sort tied items by `(draw, option_id)`. ## **5\) Naming & reserved IDs** * IDs are **stable**; do not renumber/repurpose. * **051** stays reserved across releases. * Any future variable must claim an unused ID and be added here with full schema. ## **6\) Cross-doc pointers (where these rules bite)** * **Doc 1A** — canonicalization & hashing; **Doc 1B** — schema/validation; **Doc 1C** — ER & lifecycle. * **Doc 2A/2B/2C** — grouping of Included vs Excluded, operational/presentation split. * **Doc 3A** — determinism & RNG behavior; **Doc 3B** — when FID/Engine Version must change. * **Doc 4A–4C** — algorithm touchpoints (gates, frontier, ties, labels). * **Doc 5A–5C** — pipeline, function contracts, RunRecord echo rules. * **Doc 6A–6C** — conformance tests; **Annex B** — expected hashes, RNG profile. ## **7\) Conformance checklist (annex-level)** * **A-REG-ID:** Every engine variable used exists here with correct ID/name. * **A-REG-DOM:** Engine enforces the declared domains/defaults exactly. * **A-REG-FID:** FID recomputation from the **Included** set equals artifacts’ `formula_id`. * **A-REG-TIES:** 050/052 handled per rules; 051 ignored; RNG profile matches Annex B. --- **Next:** *Part 2 of 3 — Full Registry Tables (Outcome-affecting: Global/Thresholds/Frontier/Protected/Ties)*. # **Annex A — VM-VAR Registry (Updated)** **Part 2 of 3 — Full Registry Tables (Outcome-affecting variables only; FID \= Included)** This part lists every **Included** (outcome-affecting) variable with domains, defaults, and consumption points. Excluded/presentation variables (032–035, 052, 060–062) are in **Part 3**. --- ## **A. Global & algorithm family (IDs 001–007, 073, 021\)** | id | name | type | domain | default | used\_by | notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-001** | `algorithm_family` | enum | per release (e.g., `family_v1`) | `family_v1` | Doc 4A; 5B-007; 6A-105 | Chooses allocation/rounding semantics. | | **VM-VAR-002** | `rounding_policy` | enum | `half_up` | `bankers` | `half_up` | Doc 4A; 6A-105 | Must be stable across builds. | | **VM-VAR-003** | `share_precision` | integer | 0..6 | 3 | Doc 4A; 7A | Internal calc/display base; renderer still formats per 7A. | | **VM-VAR-004** | `denom_rule` | enum | per family | `standard` | Doc 4A | Family-defined denominators. | | **VM-VAR-005** | `aggregation_mode` | enum | per family | `sum` | Doc 4A | Aggregate strategy. | | **VM-VAR-006** | `seat_allocation_rule` | enum | per family | `none` | Doc 4A | Use `none` if seats not modeled. | | **VM-VAR-007** | `tie_scope_model` | enum | `winner_only` | `rank_all` | `winner_only` | Doc 4C | Where ties can trigger. | | **VM-VAR-073** | `algorithm_variant` | enum | `v1` (others per release) | `v1` | Doc 4A; 3B | Micro-variant anchor; print in footer if ≠ default. | | **VM-VAR-021** | `run_scope` | enum/object | `all_units` | selector map | `all_units` | Doc 4A (S0/S2); 5A | Fixes working set; record in RunRecord. | --- ## **B. Thresholds, eligibility, overrides & integrity (IDs 010–017, 020–031, 029–031)** | id | name | type | domain | default | used\_by | notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-010** | `min_turnout_pct` | integer | 0..100 | 0 | Doc 4B; 6B-201 | Eligibility gate. | | **VM-VAR-011** | `min_valid_share_pct` | integer | 0..100 | 0 | Doc 4B | Eligibility gate. | | **VM-VAR-012** | `eligibility_gate_1` | enum/number | per release | value | Doc 4B | If unused this release, omit from params. | | **VM-VAR-013** | `eligibility_gate_2` | enum/number | per release | value | Doc 4B | — | | **VM-VAR-014** | `participation_floor_pct` | integer | 0..100 | 0 | Doc 4B | — | | **VM-VAR-015** | `unit_quorum_pct` | integer | 0..100 | 0 | Doc 4B | — | | **VM-VAR-016** | `option_quorum_pct` | integer | 0..100 | 0 | Doc 4B | Option-level continuation. | | **VM-VAR-017** | `reserved_threshold` | integer | 0..100 | 0 | Doc 4B | Reserved slot; define only if used. | | **VM-VAR-020** | `threshold_A` | number/int | per release | value | Doc 4B | Generic named cutoff. | | **VM-VAR-022** | `threshold_B` | number/int | per release | value | Doc 4B | Generic named cutoff. | | **VM-VAR-023** | `threshold_C` | number/int | per release | value | Doc 4B | Generic named cutoff. | | **VM-VAR-024** | `threshold_D` | number/int | per release | value | Doc 4B | Generic named cutoff. | | **VM-VAR-025** | `threshold_E` | number/int | per release | value | Doc 4B | Generic named cutoff. | | **VM-VAR-026** | `threshold_F` | number/int | per release | value | Doc 4B | Generic named cutoff. | | **VM-VAR-027** | `threshold_G` | number/int | per release | value | Doc 4B | Generic named cutoff. | | **VM-VAR-028** | `threshold_H` | number/int | per release | value | Doc 4B | Generic named cutoff. | | **VM-VAR-029** | `symmetry_exceptions` | array\ | deterministic selectors | `[]` | Doc 4B; 6B-203 | Narrow eligibility overrides; deterministic grammar; no regex entropy. | | **VM-VAR-030** | `eligibility_override_list` | array\ | \`{unit\_id, mode: include | exclude}\` | `[]` | Doc 4B; 5B-005; 6B-204 | | **VM-VAR-031** | `ballot_integrity_floor` | integer | 0..100 | 0 | Doc 4B; 6B-205/207 | Failure ⇒ unit invalid; cannot be bypassed. | --- ## **C. Frontier & refinements (IDs 040–042, 047–049) \+ Protected/Autonomy (045–046)** | id | name | type | domain | default | used\_by | notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-040** | `frontier_mode` | enum | `none` | `banded` | `ladder` | `none` | Doc 4C §2; 6B-210..216 | Master switch. | | **VM-VAR-041** | `frontier_cut` | number/enum | per mode | 0.00 | Doc 4C §2; 6B-211 | Core band/cut parameter. | | **VM-VAR-042** | `frontier_strategy` | enum | `apply_on_entry` | `apply_on_exit` | `sticky` | `apply_on_entry` | Doc 4C §2; 6B-211 | Application timing. | | **VM-VAR-047** | `frontier_band_window` | number | 0.00..1.00 | 0.00 | Doc 4C §2; 6B-213 | Expands/contracts around 041\. | | **VM-VAR-048** | `frontier_backoff_policy` | enum | `none` | `soften` | `harden` | `none` | Doc 4C §2; 6B-214 | Borderline behavior. | | **VM-VAR-049** | `frontier_strictness` | enum | `strict` | `lenient` | `strict` | Doc 4C §2; 6B-215 | Coarse multiplier on 047/048. | | **VM-VAR-045** | `protected_area_override` | enum | `deny` | `allow` | `deny` | Doc 4B §3.4; 6B-206/207 | May bypass **eligibility** only; never sanity/integrity. | | **VM-VAR-046** | `autonomy_package_map` | object | documented map | `{}` | Doc 4C; 6B-216 | Ladder/autonomy step selection; deterministic keys. | --- ## **D. Ties (Outcome-affecting policy; seed is Excluded)** | id | name | type | domain | default | used\_by | notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-050** | `tie_policy` | enum | `status_quo` | `deterministic_order` | `random` | `status_quo` | Doc 4C §3; 5B-008; 6C | **Included** in FID. `deterministic_order` uses `option.order_index` (then `option_id`). | | **VM-VAR-051** | — | — | — | — | — | **Reserved**; do not assign. | | *(see Part 3\)* | `tie_seed` | integer | ≥ 0 | 0 | Doc 3A; 4C; 6C | **VM-VAR-052** is **Excluded** from FID; recorded only if random ties occurred. | --- ### **Notes on domains marked “per release”** * Where domain is **per release**, you must enumerate allowed values (enums) or bounds (numbers) in the machine-readable registry you ship with the tag. * Any change to the domain/default/semantics of these **Included** variables ⇒ **new FID** (Doc 3B). --- **Next:** *Part 3 of 3 — Excluded/Presentation variables (032–035, 052, 060–062) \+ machine-readable export and examples.* # **Annex A — VM-VAR Registry (Updated)** **Part 3 of 3 — Excluded / Presentation Variables \+ Machine-Readable Export** This part lists the **Excluded** (non-FID) variables and provides the machine-readable registry excerpt plus examples. Excluded variables **never** change outcomes or the FID; they only affect rendering or optional diagnostics. --- ## **E. Presentation & pipeline toggles (Excluded from FID)** ### **E.1 Report/pipeline toggles (IDs 032–035)** | id | name | type | domain | default | used\_by | notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-032** | `unit_sort_order` | enum | `unit_id` | `label_priority` | `turnout` | `unit_id` | Doc 7A §8; 7B §5 | Reorders **report sections only**. No effect on JSON array order. | | **VM-VAR-033** | `ties_section_visibility` | enum | `auto` | `always` | `never` | `auto` | Doc 7A §4/§6.3 | Shows/omits Ties section. `auto` shows if `RunRecord.ties[]` non-empty. | | **VM-VAR-034** | `frontier_map_enabled` | boolean | — | `true` | Doc 5C §3; 7A §4/§6.4 | Toggles emission of **FrontierMap** file and appendix visibility; allocations/FID unchanged. | | **VM-VAR-035** | `sensitivity_analysis_enabled` | boolean | — | `false` | Doc 5C §4; 7A §4/§6.5 | Enables **non-canonical** diagnostics appendix. Never alters canonical artifacts. | ### **E.2 Tie seed (non-FID)** | id | name | type | domain | default | used\_by | notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-052** | `tie_seed` | integer | ≥ 0 | `0` | Doc 3A RNG; 4C §3; 5C §2.1/§2.3 | Recorded in `RunRecord.determinism.rng_seed` **iff** a random tie occurred. Does not enter FID. | ### **E.3 Labels & language (IDs 060–062)** | id | name | type | domain | default | used\_by | notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-060** | `majority_label_threshold` | integer | 0..100 | `55` | Doc 4C §4; 7A §3/§5 | Threshold for label text only. No effect on allocations. | | **VM-VAR-061** | `decisiveness_label_policy` | enum | `fixed` | `dynamic_margin` | `dynamic_margin` | Doc 4C §4; 7A | Presentation policy; reads deterministic flags produced by the algorithm. | | **VM-VAR-062** | `unit_display_language` | string | `auto` or IETF tag | `auto` | Doc 7A §5; 7B locales | Localizes unit names/strings in renderer; deterministic fallback. | --- ## **F. Machine-readable registry (release payload excerpt)** Ship a JSON file (e.g., `annex-a.vars.json`) containing **all variables** (Included and Excluded) in **numeric ID order**. Below is the **Excluded** slice (the Included slice appears in Part 2). { "schema\_version": "1.x", "vars": \[ { "id":"VM-VAR-032","name":"unit\_sort\_order","type":"enum", "domain":\["unit\_id","label\_priority","turnout"\],"default":"unit\_id", "fid":"Excluded","used\_by":\["Doc7A","Doc7B"\], "notes":"Reorders report sections only; canonical JSON unchanged." }, { "id":"VM-VAR-033","name":"ties\_section\_visibility","type":"enum", "domain":\["auto","always","never"\],"default":"auto", "fid":"Excluded","used\_by":\["Doc7A"\], "notes":"Show ties section based on RunRecord.ties\[\] unless overridden." }, { "id":"VM-VAR-034","name":"frontier\_map\_enabled","type":"boolean", "default":true,"fid":"Excluded","used\_by":\["Doc5C","Doc7A"\], "notes":"Controls FrontierMap emission and appendix visibility only." }, { "id":"VM-VAR-035","name":"sensitivity\_analysis\_enabled","type":"boolean", "default":false,"fid":"Excluded","used\_by":\["Doc5C","Doc7A","Doc7B"\], "notes":"Diagnostic appendix; never alters canonical artifacts." }, { "id":"VM-VAR-052","name":"tie\_seed","type":"integer", "domain":{"min":0},"default":0,"fid":"Excluded", "used\_by":\["Doc3A","Doc4C","Doc5C"\], "notes":"Echoed as RunRecord.determinism.rng\_seed iff any random tie occurred." }, { "id":"VM-VAR-060","name":"majority\_label\_threshold","type":"integer", "domain":{"min":0,"max":100},"default":55,"fid":"Excluded", "used\_by":\["Doc4C","Doc7A"\], "notes":"Labels only; allocations unaffected." }, { "id":"VM-VAR-061","name":"decisiveness\_label\_policy","type":"enum", "domain":\["fixed","dynamic\_margin"\],"default":"dynamic\_margin","fid":"Excluded", "used\_by":\["Doc4C","Doc7A"\], "notes":"Presentation policy; reads deterministic flags, does not change outputs." }, { "id":"VM-VAR-062","name":"unit\_display\_language","type":"string", "domain":\["auto","IETF"\],"default":"auto","fid":"Excluded", "used\_by":\["Doc7A","Doc7B"\], "notes":"Localization for renderer; deterministic fallback to canonical names." } \] } **Packaging rules** * Place the combined file (Included \+ Excluded) under the release tag. * The verifier uses **only** entries marked `fid:"Included"` when recomputing the FID. --- ## **G. Examples & rules of use** ### **G.1 ParameterSet excerpt (presentation toggles present; FID unchanged)** { "schema\_version": "1.x", "vars": { "VM-VAR-050": "random", // Included (affects FID) "VM-VAR-052": 424242, // Excluded (seed) "VM-VAR-040": "banded", // Included "VM-VAR-034": true, // Excluded (appendix toggle) "VM-VAR-060": 55, // Excluded (labels) "VM-VAR-061": "dynamic\_margin", "VM-VAR-062": "auto" } } * Runs with different **052** values have **identical FID**. * Toggling **034/035/032/033/060/061/062** never changes allocations nor FID. ### **G.2 Normative Manifest build rule (reminder)** * Include **only** variables with `fid:"Included"` (Parts 1–2 list). * Sort by numeric ID; canonical JSON; then hash to FID (Doc 1A). ### **G.3 RunRecord echo policy (non-FID)** * Producer **may** echo Excluded vars in `vars_effective` for transparency. * `rng_seed` appears **only** if a random tie occurred. --- ## **H. Conformance (Excluded set)** * **A-EX-IMMUT:** Changing any Excluded var **must not** alter canonical artifacts (`Result`, `RunRecord`) **except** optional presence/absence of `FrontierMap.json` (034). * **A-EX-FID:** FID recomputation **ignores** Excluded vars (including 052). * **A-EX-RPT:** Renderer behavior aligns with Doc 7A/7B; no recomputation; section ordering changes are presentation-only. --- ## **I. Change policy (Excluded set)** * You **may** change defaults or allowed values of Excluded vars between releases **without** a new FID, but you **must**: * Update Annex A and Doc 7A/7B as needed. * Disclose any non-default presentation toggles in the report footer “Non-normative toggles” block (Doc 7A §7.3). *End Annex A (Part 3 of 3).* ================================================================================================ FILE: docs/Annex B — Canonical Test Pack.md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 2ef261a67724a9535dd0a054e713c58713284f418c47dd22feed38a0923a3adc CONTENT_BYTES: 33811 ================================================================================================ # **Annex B — Canonical Test Pack (Updated)** **Part 1 of 3 — Scope, Repository Layout, Schemas & File Contracts** ## **1\) Status & scope** * **Normative.** Annex B is the single source of truth for machine verification of Docs **6A–6C**. * **Oracle:** `expected/hashes.json` is the **only** normative comparator. Any `expected/*.json` files are **informative** convenience copies. * **Alignment:** Uses the updated ID scheme (ties **050/052**, **051 reserved**; presentation **060–062** excluded from FID). ## **2\) Repository layout (must)** /annex-b/ manifest.json \# Case index (schema §3.1) rng\_profile.json \# Pinned RNG spec for random ties (Part 2 §2) /schemas/ \# JSON Schemas (normative) manifest.schema.json hashes.schema.json /cases/ \/ registry.json \# Canonical inputs (Doc 1B) tally.json params.json /expected/ \# Informative (fat mode) \+ Normative hashes result.json \# (informative) canonical Result run\_record.json \# (informative) canonical RunRecord frontier\_map.json \# (informative) only when frontier\_expected=true hashes.json \# (normative) see §3.2 **Thin mode:** Only `expected/hashes.json` is required. If fat and thin artifacts are both present, **`hashes.json` governs**. ## **3\) File contracts (normative)** ### **3.1 `manifest.json`** Purpose: enumerate all test cases and their essential properties so runners can select/route without opening each case folder. **Required structure** * `schema_version: "1.x"` * `engine_matrix: string[]` — target OS/arch identifiers (e.g., `"linux-x86_64"`). * `cases: Case[]` **Case object (required fields)** * `id: string` — stable ID (e.g., `"VM-TST-211"`). * `suite: "6A" | "6B" | "6C"` — maps to Doc 6 parts. * `title: string` * `purpose: string` * `files: ["registry.json","tally.json","params.json"]` (fixed) * `expected_mode: "fat" | "thin"` * `frontier_expected: boolean` — `true` only if a `frontier_map.json` is part of expected artifacts. * `tie_expected: boolean` — `true` when `RunRecord.ties[]` must be non-empty. * `features: string[]` — tags to speed routing (e.g., `["gates","frontier","ties","protected","overrides"]`). Schema constraints: `id` unique; `suite` ∈ {6A,6B,6C}; `files` exactly the three filenames above; `features` values are free-form but lower\_snake\_case. ### **3.2 `expected/hashes.json` (the oracle)** Purpose: bind **inputs** to **expected outputs** via hashes, and pin the expected **FID** and tie expectations. **Required structure** * `schema_version: "1.x"` * `expected_fid: "<64hex>"` — the FID both artifacts must report. * `inputs_sha256: { registry, tally, params }` — 64-hex of the **canonical** input JSON bytes. * `result_sha256: "<64hex>"` * `run_record_sha256: "<64hex>"` * `frontier_map_sha256: "<64hex>" | null` — must be non-null iff `frontier_expected=true` in `manifest.json`. * `tie_expectations` (object, required; fields conditional): * `policy: "status_quo" | "deterministic_order" | "random"` * `rng_seed_expected: integer ≥ 0` — **required iff** `policy="random"`. * `events_expected: integer ≥ 0` — optional sanity check count for `RunRecord.ties[]`. **Binding rule:** Verifiers **must** check that the producer’s input digests match `inputs_sha256` **before** comparing output hashes. ### **3.3 Canonical input files (per case)** * `registry.json`, `tally.json`, `params.json` **must** already be in canonical JSON form (Doc 1A §2.1: UTF-8, LF, sorted keys; arrays ordered). * They **must** validate against Doc 1B schemas and Annex A domains. ### **3.4 Informative expected artifacts (fat mode only)** * `expected/result.json`, `expected/run_record.json`, `expected/frontier_map.json` * If present, they are **informative**. Tools may display diffs for human debugging, but **hash comparisons are authoritative**. ## **4\) JSON Schemas (normative envelopes)** ### **4.1 `/schemas/manifest.schema.json` (outline)** * Enforces `schema_version`, `engine_matrix` (array of non-empty strings), and `cases` as an array of Case objects with required fields in §3.1. * Constraints: * `cases[].id` unique across the array. * `cases[].files` **exactly** `["registry.json","tally.json","params.json"]`. * `cases[].expected_mode` ∈ `{"fat","thin"}`. * `cases[].frontier_expected` and `cases[].tie_expected` are booleans. ### **4.2 `/schemas/hashes.schema.json` (outline)** * Enforces `schema_version`, `expected_fid` as 64-hex, each `*_sha256` as 64-hex or null per §3.2, and `tie_expectations`. * Conditional logic: * If `tie_expectations.policy = "random"`, then `rng_seed_expected` is **required**. * If `frontier_expected` is `true` (from manifest for this case), then `frontier_map_sha256` is **non-null**. *(Full JSON Schemas can be generated from these outlines; they’re normative once committed.)* ## **5\) Norms & invariants (applies to all cases)** * **Canonicalization:** All inputs and expected outputs are measured as canonical JSON bytes (Doc 1A §2.1). * **FID linkage:** `expected_fid` is authoritative; the producer’s `Result.formula_id` and `RunRecord.formula_id` **must equal** it. * **Thin vs fat:** When both are present, **hashes.json wins**; content of informative files must not override hashes. * **No network:** Test runs must not perform network I/O (Docs 3A/5A). * **Variable inclusion:** Verifiers recompute FID using only variables marked **Included** in Annex A; Excluded vars (e.g., 032–035, 052, 060–062) are ignored for FID. --- **Next (Part 2):** Verification algorithm (step-by-step, incl. `run_id` suffix rule), RNG profile (pinned spec), and matrix conformance. # **Annex B — Canonical Test Pack (Updated)** **Part 2 of 3 — Verification Algorithm, RNG Profile, Matrix Conformance** ## **1\) Verification algorithm (normative)** Given a case folder `/cases//` and its `expected/hashes.json` (Part 1 §3.2): ### **1.1 Inputs & canonicalization** 1. Read `registry.json`, `tally.json`, `params.json`. 2. Canonicalize each (Doc 1A §2.1: UTF-8, LF, **sorted keys**, arrays in spec order). 3. Compute sha256 of the canonical bytes and compare to `inputs_sha256.{registry,tally,params}`. **Fail** the case if any mismatch. ### **1.2 Run producer (engine)** 4. Invoke CLI per Doc 6 harness (no network; exit codes per Doc 3A/5A). 5. On non-zero exit, only cases explicitly designed to fail validation may do so (Doc 6A/6B describe those). Otherwise **fail**. ### **1.3 Artifact identity & structure** 6. Canonicalize produced `result.json` and `run_record.json` (and `frontier_map.json` if it exists). 7. Compute: * `RES:` \+ sha256(canonical(result.json)) and compare to `Result.result_id`. * `RUN:` \+ `` \+ `-` \+ sha256(canonical(run\_record.json)) and compare to `RunRecord.run_id`. * **Rule:** Only the **hash suffix after the first hyphen** must match; the timestamp prefix may vary but **MUST** be RFC3339 UTC (`YYYY-MM-DDThh:mm:ssZ` or with `Z` offset). * If `frontier_map.json` exists: `FR:` \+ sha256(canonical(frontier\_map.json)) vs `frontier_id` (if embedded) and vs `frontier_map_sha256` (expected). ### **1.4 Hash oracle (authoritative)** 8. Compare computed output hashes to `expected/hashes.json`: * `result_sha256` (must match). * `run_record_sha256` (must match). * `frontier_map_sha256`: * If `manifest.frontier_expected = true` ⇒ **must be non-null and match**. * If `manifest.frontier_expected = false` ⇒ **must be null** and producer **must not** emit a `frontier_map.json`. ### **1.5 FID integrity** 9. Recompute the **Normative Manifest** (Annex A “Included” set only; Doc 1A) from the **producer’s** ParameterSet; hash to FID; compare to: * `expected_fid` (from `hashes.json`), * `Result.formula_id`, * `RunRecord.formula_id`. All three must be equal. ### **1.6 Variable echo & policy checks** 10. Verify `RunRecord.vars_effective` **includes all outcome-affecting** VM-VARs actually used (Annex A Included set). Excluded vars may appear. 11. **Tie expectations** (from `hashes.json.tie_expectations`): * `policy` must equal the effective `VM-VAR-050` in `vars_effective`. * If `policy="random"`: * `RunRecord.determinism.rng_seed` **present** and equals `rng_seed_expected`. * Each `ties[]` entry has `"policy":"random"` and `"seed":`. * If `events_expected` provided, `ties.length` must equal it. * If `policy!="random"`: `RunRecord.determinism.rng_seed` **absent**; `ties[]` may be empty or contain non-random events consistent with the policy (e.g., `"status_quo"`). ### **1.7 Suite-specific assertions (Doc 6\)** 12. Apply additional assertions from the relevant suite: * **6A**: no RNG, no frontier; ordering checks. * **6B**: gate `reasons[]` ordering (by VM-VAR ID then symbolic), protected bypass rules, frontier presence per case. * **6C**: RNG usage only when a real tie exists; “**exactly k draws for a k-way tie**” (see RNG profile). **Pass criteria:** All steps above succeed. Any deviation ⇒ **fail** the case. --- ## **2\) Verifier pseudocode (normative)** load expected \= read\_json("expected/hashes.json") canon\_inputs \= { r \= canon("registry.json"), t \= canon("tally.json"), p \= canon("params.json") } assert sha256(canon\_inputs.r) \== expected.inputs\_sha256.registry assert sha256(canon\_inputs.t) \== expected.inputs\_sha256.tally assert sha256(canon\_inputs.p) \== expected.inputs\_sha256.params run\_engine("--registry registry.json \--tally tally.json \--params params.json \--out outdir") assert exit\_code in allowed\_for\_case res \= canon("outdir/result.json") rr \= canon("outdir/run\_record.json") fm? \= exists("outdir/frontier\_map.json") ? canon("outdir/frontier\_map.json") : null assert ("RES:" \+ sha256(res)) \== read\_json(res).result\_id assert suffix\_after\_hyphen(read\_json(rr).run\_id) \== sha256(rr) if expected.frontier\_map\_sha256 \!= null: assert fm? \!= null assert sha256(fm?) \== expected.frontier\_map\_sha256 else: assert fm? \== null assert sha256(res) \== expected.result\_sha256 assert sha256(rr) \== expected.run\_record\_sha256 fid \= recompute\_fid(IncludedVarsFromAnnexA, params\_from(rr or inputs)) assert fid \== expected.expected\_fid assert fid \== read\_json(res).formula\_id \== read\_json(rr).formula\_id check\_vars\_effective(rr.vars\_effective, AnnexA.Included) check\_tie\_expectations(rr, expected.tie\_expectations) apply\_suite\_assertions(case.suite, res, rr, fm?, manifest) --- ## **3\) RNG profile (pinned, normative)** The RNG used for `VM-VAR-050="random"` ties is frozen by `/annex-b/rng_profile.json`. Engines and verifiers **must** implement it exactly. ### **3.1 Required fields** { "name": "xorshift128plus", // example; choose and freeze per release "state\_bits": 128, "seed\_type": "u64", "endianness": "little", "next\_u64\_spec": "formula or reference defining next()", // exact spec or paper ref "draws\_per\_tie\_item": 1, "tiebreak\_sort\_key": \["draw","option\_id"\], "test\_vectors": \[ { "seed": 0, "next\_u64\_first5": \["...","...","...","...","..."\] }, { "seed": 424242, "next\_u64\_first5": \["...","...","...","...","..."\] } \], "notes": "Use exactly k draws for a k-way tie; do not draw when no tie exists." } ### **3.2 Norms (must)** * **Seeding:** Initialize once per run from **VM-VAR-052** (integer ≥ 0). No per-unit reseeding. * **Consumption:** A **k-way** tie consumes **exactly k** 64-bit draws; subsequent ties resume from the current RNG state. * **Permutation:** Order tied options by `(draw_value, option_id)` ascending to obtain a stable permutation. * **Platform identity:** Implementation must produce **identical sequences** across OS/arch. * **Change control:** Any change to `rng_profile.json` (algorithm, seeding, or sort key) is **normative** ⇒ **new FID** and **regenerate all case hashes**. --- ## **4\) Matrix conformance (OS/arch)** ### **4.1 Engine matrix** `manifest.json.engine_matrix` lists target platforms (e.g., `["linux-x86_64","macos-arm64","windows-x86_64"]`). A release **passes** only if **all cases** pass on **all** listed targets. ### **4.2 Identity requirement** For the **same case** and **same inputs/ParameterSet** (including seed), produced artifacts **must** be byte-identical across all targets: * Same `result_sha256` and `run_record_sha256`. * If applicable, same `frontier_map_sha256`. * Same `Result.formula_id` and `RunRecord.formula_id`. * `run_id` **hash suffix** identical; timestamp prefix may differ but must be RFC3339 UTC. ### **4.3 CI gating (recommended, informative but expected in practice)** * Validate both JSON Schemas (`manifest.schema.json`, `hashes.schema.json`). * For each target in `engine_matrix`, run every case, then compare produced hashes to `expected/hashes.json`. * Fail the release if any target fails; publish per-target logs. --- ## **5\) Error classification during verification** * **Input bind failure** (inputs don’t match `inputs_sha256`) ⇒ case invalid (stop). * **Producer exit code** outside the case’s allowance (per Doc 6 case design) ⇒ fail. * **Canonicalization/ID mismatch** (`RES:`/`RUN:`/`FR:` rules) ⇒ fail. * **Hash mismatch** vs `expected/hashes.json` ⇒ fail. * **FID mismatch** (recomputed vs `expected_fid` or artifact fields) ⇒ fail. * **Tie/frontier expectation mismatch** (policy/seed/events/presence) ⇒ fail. --- **Next (Part 3):** Suite catalog & examples (concise list of cases 6A (101–110), 6B (201–216), 6C (301–312) with minimal per-case metadata and sample `hashes.json`). # **Annex B — Canonical Test Pack (Updated)** **Part 3 of 3 — Suite Catalog & Examples (machine-usable)** Below is a ready-to-commit **`manifest.json`** case catalog (concise but complete), plus **sample `hashes.json`** for one case in each suite. It follows the contracts from Parts 1–2 (hash oracle; run\_id suffix rule; RNG profile). --- ## **1\) `manifest.json` (full case list)** { "schema\_version": "1.x", "engine\_matrix": \["linux-x86\_64", "macos-arm64", "windows-x86\_64"\], "cases": \[ // \---------- 6A: Allocation correctness (101–110) \---------- { "id": "VM-TST-101", "suite": "6A", "title": "Simple 2-option majority", "purpose": "Baseline allocation; no ties; no gates; frontier off.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["allocation"\] }, { "id": "VM-TST-102", "suite": "6A", "title": "Three options — preserve registry order", "purpose": "Allocation array keeps option.order\_index regardless of vote order.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["ordering","allocation"\] }, { "id": "VM-TST-103", "suite": "6A", "title": "Zero-vote minor option", "purpose": "Zero votes do not imply invalidity or tie consumption.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["allocation"\] }, { "id": "VM-TST-104", "suite": "6A", "title": "Multiple units — deterministic iteration", "purpose": "Units sorted by unit\_id; per-unit results correct.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["ordering","allocation"\] }, { "id": "VM-TST-105", "suite": "6A", "title": "Rounding policy application", "purpose": "Family constants and rounding drive exact expected shares.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["rounding","allocation"\] }, { "id": "VM-TST-106", "suite": "6A", "title": "Large counts stability", "purpose": "64-bit safety; canonicalization with big tallies.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["allocation","bigint"\] }, { "id": "VM-TST-107", "suite": "6A", "title": "Missing option in tally ⇒ validation error", "purpose": "Referential integrity failure (no coerced zero rows).", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["validation","fk"\] }, { "id": "VM-TST-108", "suite": "6A", "title": "Duplicate order\_index ⇒ validation error", "purpose": "Detect non-unique order\_index within a unit.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["validation","ordering"\] }, { "id": "VM-TST-109", "suite": "6A", "title": "Sum of votes \> valid\_ballots ⇒ validation error", "purpose": "Sanity check on tallies.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["validation","sanity"\] }, { "id": "VM-TST-110A", "suite": "6A", "title": "FID lock — labels fixed policy", "purpose": "Presentation change only; FID constant across 110A/110B.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["fid","labels"\] }, { "id": "VM-TST-110B", "suite": "6A", "title": "FID lock — labels dynamic policy", "purpose": "Presentation change only; FID constant across 110A/110B.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["fid","labels"\] }, // \---------- 6B: Gates & Frontier (201–216) \---------- { "id": "VM-TST-201", "suite": "6B", "title": "Eligibility threshold (020) invalidates unit", "purpose": "Unit becomes Invalid; reasons include 020.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["gates","eligibility"\] }, { "id": "VM-TST-202", "suite": "6B", "title": "Multiple eligibility failures — ordered reasons", "purpose": "Record all reasons in ascending VM-VAR ID order.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["gates","reasons\_order"\] }, { "id": "VM-TST-203", "suite": "6B", "title": "Symmetry exceptions (029) narrow override", "purpose": "029 exempts a unit; unit remains valid; record applied\_exceptions.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["gates","exceptions"\] }, { "id": "VM-TST-204", "suite": "6B", "title": "Precedence 030 over 029", "purpose": "030 exclude wins over 029 exception; reasons reflect 030.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["gates","precedence"\] }, { "id": "VM-TST-205", "suite": "6B", "title": "Integrity floor (031) cannot be bypassed", "purpose": "Invalid even if 029/045 would allow eligibility.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["gates","integrity"\] }, { "id": "VM-TST-206", "suite": "6B", "title": "Protected area (045=allow) bypasses eligibility", "purpose": "Unit valid; protected\_bypass=true; no reason for bypassed gate.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["gates","protected"\] }, { "id": "VM-TST-207", "suite": "6B", "title": "Protected area cannot bypass integrity (031)", "purpose": "Invalid; reasons include 031; protected\_bypass absent/false.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["gates","protected","integrity"\] }, { "id": "VM-TST-208", "suite": "6B", "title": "Frontier pre-check failure recorded", "purpose": "Missing frontier inputs ⇒ validity failure token 'frontier\_missing\_inputs'.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["gates","frontier","precheck"\] }, { "id": "VM-TST-210", "suite": "6B", "title": "Frontier disabled", "purpose": "No frontier\_map; allocations unaffected; FID excludes 034.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["frontier"\] }, { "id": "VM-TST-211", "suite": "6B", "title": "Frontier banded — entry cut", "purpose": "Deterministic gating; diagnostics emitted.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "fat", "frontier\_expected": true, "tie\_expected": false, "features": \["frontier","diagnostics"\] }, { "id": "VM-TST-212A", "suite": "6B", "title": "FrontierMap toggle — on", "purpose": "034=true: file present; allocations/FID unchanged vs 212B.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "fat", "frontier\_expected": true, "tie\_expected": false, "features": \["frontier","diagnostics","toggle\_034"\] }, { "id": "VM-TST-212B", "suite": "6B", "title": "FrontierMap toggle — off", "purpose": "034=false: file absent; allocations/FID unchanged vs 212A.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["frontier","toggle\_034"\] }, { "id": "VM-TST-213", "suite": "6B", "title": "Advanced window (047) near cut", "purpose": "047 expands/contracts effective band; flips at margins per fixture.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "fat", "frontier\_expected": true, "tie\_expected": false, "features": \["frontier","047"\] }, { "id": "VM-TST-214", "suite": "6B", "title": "Backoff policy (048)", "purpose": "Borderline handling: none vs soften vs harden.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "fat", "frontier\_expected": true, "tie\_expected": false, "features": \["frontier","048"\] }, { "id": "VM-TST-215", "suite": "6B", "title": "Strictness (049) multiplies effects", "purpose": "Compare strict vs lenient with fixed 047/048.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "fat", "frontier\_expected": true, "tie\_expected": false, "features": \["frontier","049"\] }, { "id": "VM-TST-216", "suite": "6B", "title": "Ladder mode with autonomy map (046)", "purpose": "Deterministic package selection across steps.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "fat", "frontier\_expected": true, "tie\_expected": false, "features": \["frontier","ladder","046"\] }, // \---------- 6C: Determinism & Ties (301–312) \---------- { "id": "VM-TST-301", "suite": "6C", "title": "Reproducibility (no RNG)", "purpose": "Identical runs produce byte-identical artifacts.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["determinism"\] }, { "id": "VM-TST-302", "suite": "6C", "title": "Deterministic tie by order\_index", "purpose": "Resolve 2/3-way ties via registry order; no RNG; ties\[\] may be empty.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["ties","deterministic\_order"\] }, { "id": "VM-TST-303", "suite": "6C", "title": "Status quo policy path", "purpose": "Policy applied; ties\[\] entries present (no seed).", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": true, "features": \["ties","status\_quo"\] }, { "id": "VM-TST-304", "suite": "6C", "title": "Random tie, 2-way, fixed seed", "purpose": "Permutation stable across runs; rng\_seed echoed.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": true, "features": \["ties","random","seed"\] }, { "id": "VM-TST-305", "suite": "6C", "title": "Random tie, 3-way, fixed seed", "purpose": "k draws, sort by (draw, option\_id).", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": true, "features": \["ties","random","seed"\] }, { "id": "VM-TST-306A", "suite": "6C", "title": "Seed variation A", "purpose": "Different seed can change outcomes where ties exist; FID unchanged.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": true, "features": \["ties","random","seed","fid"\] }, { "id": "VM-TST-306B", "suite": "6C", "title": "Seed variation B", "purpose": "Companion to 306A (different seed).", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": true, "features": \["ties","random","seed","fid"\] }, { "id": "VM-TST-307", "suite": "6C", "title": "Random policy but no ties", "purpose": "No RNG use; rng\_seed absent; identical to deterministic order.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["ties","random","no\_tie"\] }, { "id": "VM-TST-308", "suite": "6C", "title": "Multiple tie events (k draws per event)", "purpose": "3-way then 2-way consume draws in order; permutations match fixture.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": true, "features": \["ties","random","draw\_count"\] }, { "id": "VM-TST-309", "suite": "6C", "title": "Repeated ties within one unit", "purpose": "Independent tie points consume sequential draws.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": true, "features": \["ties","random","draw\_order"\] }, { "id": "VM-TST-310", "suite": "6C", "title": "Policy change alters FID; seed does not", "purpose": "050 in FID; 052 excluded.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": true, "features": \["ties","fid","seed"\] }, { "id": "VM-TST-311A", "suite": "6C", "title": "Random ties — frontier off", "purpose": "Baseline with random ties and 040='none'.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": true, "features": \["ties","random"\] }, { "id": "VM-TST-311B", "suite": "6C", "title": "Random ties — frontier on", "purpose": "Same permutations as 311A; frontier diagnostics may emit.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "fat", "frontier\_expected": true, "tie\_expected": true, "features": \["ties","random","frontier"\] }, { "id": "VM-TST-312", "suite": "6C", "title": "Invalid unit ⇒ no tie resolution", "purpose": "Gates pre-empt ties; no RNG for invalid unit.", "files": \["registry.json","tally.json","params.json"\], "expected\_mode": "thin", "frontier\_expected": false, "tie\_expected": false, "features": \["gates","ties","integrity"\] } \] } --- ## **2\) Example `hashes.json` (one per suite)** Replace `<64hex>` with real hashes from your canonical outputs. These are **normative**. ### **2.1 6A example — `cases/VM-TST-101/expected/hashes.json`** { "schema\_version": "1.x", "expected\_fid": "\<64hex\>", "inputs\_sha256": { "registry": "\<64hex\>", "tally": "\<64hex\>", "params": "\<64hex\>" }, "result\_sha256": "\<64hex\>", "run\_record\_sha256": "\<64hex\>", "frontier\_map\_sha256": null, "tie\_expectations": { "policy": "deterministic\_order" } } ### **2.2 6B example — `cases/VM-TST-211/expected/hashes.json`** { "schema\_version": "1.x", "expected\_fid": "\<64hex\>", "inputs\_sha256": { "registry": "\<64hex\>", "tally": "\<64hex\>", "params": "\<64hex\>" }, "result\_sha256": "\<64hex\>", "run\_record\_sha256": "\<64hex\>", "frontier\_map\_sha256": "\<64hex\>", "tie\_expectations": { "policy": "deterministic\_order" } } ### **2.3 6C example — `cases/VM-TST-304/expected/hashes.json`** { "schema\_version": "1.x", "expected\_fid": "\<64hex\>", "inputs\_sha256": { "registry": "\<64hex\>", "tally": "\<64hex\>", "params": "\<64hex\>" }, "result\_sha256": "\<64hex\>", "run\_record\_sha256": "\<64hex\>", "frontier\_map\_sha256": null, "tie\_expectations": { "policy": "random", "rng\_seed\_expected": 424242, "events\_expected": 1 } } --- ## **3\) Notes for implementers (brief)** * **IDs:** Do not renumber; subcases (`110A/B`, `212A/B`, `306A/B`, `311A/B`) exist **only** to supply unique expected hashes when a single narrative test requires two distinct runs. * **Fat vs thin:** If you include `expected/*.json`, ensure they match the hashes; **hashes.json governs** in case of conflict. * **RNG:** Ensure your `rng_profile.json` (Annex B Part 2 §3) is identical across OS/arch; changing it requires a **new FID** and regenerating **all** hashes. That’s the full Annex B generated across three passes. If you want, I can save these JSON stubs into your repo structure now so your CI can start wiring against them. ================================================================================================ FILE: docs/Annex C — Glossary & Definitions.md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 9b59f176e44f17d57641b53288eed4c497abb77c2d6be509f0d42b7c9d5c931c CONTENT_BYTES: 7878 ================================================================================================ # **Annex C — Glossary & Definitions (Updated)** ## **1\) Scope** Canonical, one-page definitions for recurring terms and tokens used across Docs **1–7** and Annexes **A–B**. Aligns IDs to the **current scheme** (e.g., ties \= **VM-VAR-050/052**, **051 reserved**; presentation **060–062** are non-FID). --- ## **2\) Terms** **Algorithm family** The counted method and rounding/denominator rules selected by **VM-VAR-001..007** (+ optional **VM-VAR-073**). Controls allocation semantics (Doc 4A). *Outcome-affecting; in FID.* **Algorithm variant (VM-VAR-073)** Documented micro-variant within the same family (e.g., a prescribed rounding preference). Printed in report footer if not default (Doc 3B, 7A). *In FID.* **Allocation** Per-unit mapping of `option_id → votes/share` produced after gates/frontier/ties (Docs 4A–4C). Ordered by Registry `order_index`. **Annex A — VM-VAR Registry** Single source of truth for variable **domains, defaults, and FID inclusion**. The “Included” list defines the **Normative Manifest** inputs (Doc 1A). **Annex B — Canonical Test Pack** Machine-readable fixtures (inputs, expected outputs/hashes) for suites 6A/6B/6C, plus RNG profile (Annex B §7). **Band / band\_met** Frontier predicate indicating whether a unit lies within the effective band/cut for the configured model. Emitted in `FrontierMap.units[i].band_met` (Doc 4C). Field name is **`band_met`**. **BallotTally** Input JSON giving per-unit totals and per-option votes (Doc 1B). Must align to **DivisionRegistry**. **Canonical JSON** Serialization used for hashing: UTF-8, LF newlines, **sorted keys** at all object levels; arrays ordered per Doc 1A §5; no BOM (Doc 1A §2.1). **Determinism (byte-identical outputs)** Given identical inputs \+ ParameterSet (incl. seed), all artifacts are bit-for-bit identical across OS/arch (Doc 3A). Enforced by ordering rules, canonical JSON, and fixed RNG profile (Annex B §7). **DivisionRegistry** Input JSON defining the universe of `units` and their `options`, including deterministic `order_index` per option (Docs 1B–1C). Source of all FK references. **FID — Formula ID** 64-hex SHA-256 over the **Normative Manifest** (algorithm rules \+ “Included” VM-VAR values). Recorded at `Result.formula_id` and `RunRecord.formula_id` (Doc 1A §2.3). *Presentation toggles are excluded.* **Frontier (040–042, 047–049)** Outcome-affecting gating model (e.g., `banded`, `ladder`) applied pre-allocation (Doc 4C). Advanced refinements: window/backoff/strictness. *In FID.* **FrontierMap** Optional canonical artifact with per-unit frontier diagnostics (Doc 1A §4.6). Emitted only if **VM-VAR-034=true** and frontier executed. **Gate (sanity/eligibility/validity)** Deterministic checks applied before allocation (Doc 4B) using **010–017**, **020–031** (+ **045**, **029**, **030** precedence). Failure ⇒ unit `Invalid`. **Included / Excluded (FID)** A VM-VAR is **Included** if it can change outcomes (in FID); **Excluded** if it is presentation-only (not in FID). See Annex A §5. **Invalid (label)** Unit state when any gate fails; `allocations=[]`; label is `"Invalid"` (Docs 4B, 7A). **Label (Decisive/Marginal)** Presentation-only outcome text computed **after** allocation using **VM-VAR-060/061**; never affects counts or FID (Doc 4C). **Normative Manifest** Ordered, canonical snapshot of all outcome-affecting rules \+ Included VM-VAR values used to compute **FID** (Doc 1A §2.3; Annex A §5). **Option / option\_id** A selectable alternative within a unit (e.g., party/candidate). Identified by stable `option_id` and deterministic `order_index` (Docs 1B–1C). **Order index (order\_index)** Deterministic integer ordering key for options within a unit. Used to break ties under `deterministic_order` policy (Docs 1A §5, 4C). **ParameterSet** Input JSON map `vars{ "VM-VAR-###": value }`. Must provide explicit values for all **Included** VM-VARs; presentation vars may be present but are non-FID (Docs 1B, 2A–2C). **Protected area / override (045)** Registry flag `protected_area` on a unit; **VM-VAR-045** may bypass **eligibility** only; never bypasses **sanity** nor **integrity floor (031)** (Doc 4B). **Random tie (050= random, 052 seed)** Policy that resolves ties via a deterministic RNG seeded by **VM-VAR-052**. Exactly **k** 64-bit draws for a k-way tie; permutation sorted by `(draw, option_id)`; events logged (Docs 3A, 4C, 5C; Annex B §7). *050 is in FID; 052 is not.* **Renderer** Read-only consumer of canonical artifacts. Applies Doc 7A visual rules and 7B templates; never re-computes allocations; may include optional appendices (Doc 5C) (Docs 7A–7B). **Result / result\_id** Canonical outcome artifact; `result_id = "RES:" + sha256(canonical(Result))` (Doc 1A §4.4). **RNG profile** Frozen algorithm/spec used for random ties; defined in Annex B §7 to ensure cross-platform identical sequences. Changing it ⇒ new FID. **RunRecord / run\_id** Canonical provenance artifact containing engine info, input digests, `vars_effective`, determinism block, and TieLog. `run_id = "RUN:" + + "-" + sha256(canonical(RunRecord))` (Doc 1A §4.5). **Scope (run\_scope, 021\)** Selector that fixes which units are included in the run before counting (Docs 2A/2C, 4A). **Sensitivity analysis (035)** Non-canonical appendix switch for diagnostic comparisons. No changes to canonical artifacts/hashes (Docs 5C, 7A–7B). *Excluded from FID.* **Symmetry exceptions (029)** Deterministic allow/deny selectors that narrowly override **eligibility** gates; applied after 030 precedence (Doc 4B). *In FID.* **Tie policy (050) / deterministic order** Tie policy ∈ `{ status_quo | deterministic_order | random }`. Deterministic order uses **Registry `order_index`** (then `option_id`); **VM-VAR-051 is reserved** (Docs 4C, Annex A). **Tie seed (052)** Run parameter for random ties. Echoed in `RunRecord.determinism.rng_seed` **iff** any random tie occurred; otherwise omitted (Docs 3A, 5C). *Excluded from FID.* **TieLog** Ordered list of tie events in `RunRecord.ties[]` with `{unit_id, type, policy, seed?}` (Doc 5C §2.3). **Unit / unit\_id** A counting division (e.g., district). Primary key for per-unit results; arrays of units ordered by ascending `unit_id` (Doc 1A §5). --- ## **3\) Token & naming conventions (normative)** * **Variables:** `VM-VAR-###` (three digits, zero-padded). * **Reason tokens (4B):** `"VM-VAR-0xx:"` ordered by numeric ID; symbolic reasons (e.g., `"frontier_missing_inputs"`) appear **after** ID-based reasons and are sorted lexicographically. * **Field names:** `snake_case`. Use **`band_met`** (not variants). * **IDs & hashes:** lowercase 64-hex; prefixes `RES:`, `RUN:`, `FR:` as defined in Doc 1A. --- ## **4\) Quick cross-reference (where defined)** | Concept | Primary definition | Also referenced | | ----- | ----- | ----- | | Canonical JSON & IDs | Doc 1A §2, §4 | Doc 3A, Doc 5A/S5 | | VM-VAR registry & FID inclusion | Annex A §3–§5 | Doc 2A–2C | | Algorithm flow | Doc 4A | Doc 5A/S3 | | Gates & edge cases | Doc 4B | Doc 6B | | Frontier model | Doc 4C §2 | Doc 6B, FrontierMap in Doc 1A §4.6 | | Ties & RNG | Doc 4C §3 | Doc 3A (RNG), Doc 6C, Doc 5C (TieLog) | | Labels & presentation | Doc 4C §4, Doc 7A | Doc 2B, Doc 7B | | Test harness & cases | Doc 6A–6C | Annex B | | Release/versioning | Doc 3B | Footers in Doc 7A | --- ## **5\) ID alignment notes (this edition)** * **Tie controls** live at **VM-VAR-050 (policy)** and **VM-VAR-052 (seed)**; **VM-VAR-051 reserved**. * **Presentation & language** (`VM-VAR-060..062`) are **Excluded from FID**. * Any previous references to ties at **032–033** or to “seed at 033” are obsolete. *End Annex C.* ================================================================================================ FILE: docs/Doc 1 — Database Specification (Entities, Fields, Relationships).md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 588612c0d960132b1e3909eabb297f43edeae5b91cd5d906d1dfa66ba044f023 CONTENT_BYTES: 30045 ================================================================================================ # **Doc 1A — Database Definition: Entities & IDs (Updated, Normative)** ## **1\) Purpose & scope** Defines the **canonical data model** (entities, fields, relationships) and **identifier rules** for all persistent artifacts produced or consumed by the counting engine and report renderer. This part is **normative**. It integrates the former addenda (FID/canonicalization and cross-refs) so no separate addendum is required. Applies to local, offline runs. With the **same inputs** and the **same ParameterSet** (including seeds), outputs must be **byte-identical** across OS/arch. --- ## **2\) Canonical serialization & identifiers** ### **2.1 Canonical JSON** All artifacts are JSON with the following canonical form (used both for storage and hashing): * **UTF-8**, Unix newlines (**LF**), no BOM. * **Sorted keys** at every object level (ascending Unicode code point). * **Numbers** emitted as JSON numbers (no trailing zeros beyond what the algorithm outputs). * **Stable ordering** for arrays as defined in §5 (never “natural”/incidental order). ### **2.2 Artifact files and IDs** The engine emits up to three canonical artifacts per run: * `result.json` — final outcome (**Result**). `result_id`: `"RES:" + ` * `run_record.json` — provenance & audit (**RunRecord**). `run_id`: `"RUN:" + + "-" + ` * `frontier_map.json` — optional diagnostic (**FrontierMap**). `frontier_id`: `"FR:" + ` ### **2.3 Formula ID (FID)** * **FormulaID** is a **64-hex sha256** over the **Normative Manifest** (the set of outcome-affecting rules and defaults). * **Inclusion**: only variables/rules that can change outcomes. * **Exclusion**: presentation/reporting toggles (e.g., labels, display language, formatting) are **not** in FID. * **Where recorded**: `Result.formula_id` and `RunRecord.formula_id`. * **Verification aid**: `RunRecord.nm_digest` (see §4.5) enables third parties to recompute the FID. Full variable coverage (what’s in/out of FID) is centralized in **Annex A — VM-VAR Registry**. This doc references those IDs where needed (e.g., ties). --- ## **3\) Entity overview & relationships** **Inputs (consumed)** * **DivisionRegistry** — stable universe of Units and Options (and metadata). * **BallotTally** — counts by Unit/Option (already validated & normalized). * **ParameterSet** — effective variable values by **VM-VAR-ID**. **Outputs (produced)** * **Result** — elected/allocated outputs and derived metrics. * **RunRecord** — immutably documents inputs, engine, variables, seeds, hashes. * **FrontierMap** *(optional)* — per-Unit diagnostics for frontier/band gating. * **TieLog** *(embedded in RunRecord)* — events when ties are encountered. **Key relationships** * **Result** references Units/Options defined in **DivisionRegistry**. * **RunRecord** references **Result** (by `result_id`) and includes digests of all inputs. * **FrontierMap** references Units and the gating bands used in the algorithm. --- ## **4\) Schemas (normative)** Field names are **snake\_case**. “Required” means the field MUST be present. ### **4.1 DivisionRegistry (input)** Purpose: authoritative catalog of **units** (e.g., districts) and their **options** (e.g., parties/candidates). Minimum schema: { "schema\_version": "1.x", "units": \[ { "unit\_id": "U-001", // stable ID (string) "name": "District 1", "protected\_area": false, // if true, gating rules may apply "options": \[ { "option\_id": "O-A1", // stable ID (string) "name": "Option A", "order\_index": 1 // integer; see §5 for determinism } \] } \] } Constraints: * `unit_id` and `option_id` are **unique** and **stable** across runs. * Each `options[].order_index` is **unique within its unit** and a **non-negative integer**. ### **4.2 BallotTally (input)** Purpose: per-unit counts for each option (already validated upstream). Minimum schema: { "schema\_version": "1.x", "units": \[ { "unit\_id": "U-001", "totals": { "valid\_ballots": 12345, "invalid\_ballots": 67 }, "options": \[ { "option\_id": "O-A1", "votes": 6000 }, { "option\_id": "O-B1", "votes": 5000 } \] } \] } Constraints: * Every `unit_id` and `option_id` MUST exist in **DivisionRegistry**. * Totals are non-negative and consistent (engine validation rules apply in tests). ### **4.3 ParameterSet (input)** Purpose: effective **VM-VAR** values for this run. Schema: { "schema\_version": "1.x", "vars": { "VM-VAR-050": "status\_quo", // tie\_policy "VM-VAR-052": 0, // tie\_seed (used only if policy=random) "VM-VAR-060": 55, // majority label threshold (%), presentation "VM-VAR-061": "dynamic\_margin", // label policy, presentation "VM-VAR-062": "auto" // unit display language, presentation // ... other outcome-affecting variables per Annex A } } Rules: * **Tie controls**: `VM-VAR-050` (**tie\_policy**) ∈ {`status_quo`, `deterministic_order`, `random`}. `VM-VAR-052` (**tie\_seed**) is an integer ≥ 0; **only used** if policy=`random`. `VM-VAR-051` is **reserved** (no variable; deterministic\_order always uses `option.order_index`). * **Presentation variables** (e.g., `060–062`) MUST be recorded in `ParameterSet` for transparency but are **excluded from FID**. * All outcome-affecting variables listed in **Annex A (Included)** MUST appear explicitly (no implicit defaults when hashing the FID). ### **4.4 Result (output)** Purpose: canonical, minimal outcome record used for hashing and reporting. Minimum schema: { "result\_id": "RES:\<64hex\>", "formula\_id": "\<64hex\>", "engine\_version": "vX.Y.Z", "created\_at": "2025-08-12T14:00:00Z", "summary": { /\* global metrics, turnout, thresholds actually used, etc. \*/ }, "units": \[ { "unit\_id": "U-001", "allocations": \[ { "option\_id": "O-A1", "votes": 6000, "share": 0.545 }, { "option\_id": "O-B1", "votes": 5000, "share": 0.455 } \], "label": "Decisive" // derived; presentation logic uses VM-VAR-060/061 } \] } Rules: * `result_id` is computed **after** canonicalization (see §2.2). * Arrays follow **ordering rules** in §5. ### **4.5 RunRecord (output)** Purpose: verifiability & full provenance. Minimum schema: { "run\_id": "RUN:\-\<64hex\>", "result\_id": "RES:\<64hex\>", "formula\_id": "\<64hex\>", "engine": { "vendor": "acme.labs", // fork identifier "name": "vm\_engine", "version": "vX.Y.Z", "build": "commit:abcd1234" }, "inputs": { "division\_registry\_sha256": "\<64hex\>", "ballot\_tally\_sha256": "\<64hex\>", "parameter\_set\_sha256": "\<64hex\>" }, "nm\_digest": { "schema\_version": "1.x", "nm\_sha256": "\<64hex\>" // digest of the Normative Manifest used to compute FID }, "vars\_effective": { // echo of effective VM-VARs actually used "VM-VAR-050": "status\_quo", "VM-VAR-052": 0, /\* ... all outcome-affecting variables; presentation vars may be listed as well \*/ }, "determinism": { "rng\_seed": 0, // same as VM-VAR-052 when policy=random; omitted otherwise "tie\_policy": "status\_quo" // from VM-VAR-050 }, "ties": \[ { "unit\_id": "U-002", "type": "winner\_tie", "policy": "random", "seed": 424242 } \] } Rules: * `vars_effective` MUST include the **exact values** used at runtime for every **outcome-affecting** variable (Annex A Included). Presentation variables SHOULD be echoed for transparency. * `rng_seed` MUST be present **only** when `tie_policy="random"` was invoked at least once. * `engine.vendor/name/version` are **required** to identify forks and builds. ### **4.6 FrontierMap (optional output)** Purpose: diagnostics for frontier/band gating decisions. Schema (excerpt): { "frontier\_id": "FR:\<64hex\>", "units": \[ { "unit\_id": "U-001", "band\_met": true, // boolean (normalized name) "band\_value": 0.12, // numeric metrics used by gates "notes": "within band-1 threshold" } \] } Rules: * Field name is **`band_met`** (not “band met” or other variants). * Units are ordered per §5. --- ## **5\) Global ordering & determinism** To guarantee byte-identical outputs: * **Units** arrays are ordered by ascending `unit_id` (string compare). * **Options within a Unit** are ordered by ascending `order_index`; ties by ascending `option_id`. * **Allocations** and similar per-unit arrays reflect the **same option order**. * **Ties** * If `tie_policy = status_quo`: apply the policy as defined by the algorithm (no reordering). * If `tie_policy = deterministic_order`: break ties by ascending `order_index` (no extra variable). * If `tie_policy = random`: break ties using the deterministic RNG seeded with `VM-VAR-052`; record events in `RunRecord.ties[]`. --- ## **6\) Validation & integrity constraints** * **Referential integrity**: every `unit_id`/`option_id` in **BallotTally**, **Result**, **FrontierMap** MUST exist in **DivisionRegistry**. * **Hash integrity**: * `result_id`, `run_id`, `frontier_id` MUST match the sha256 of the **canonical** payloads (see §2.1). * `RunRecord.inputs.*_sha256` MUST match the canonical inputs used. * **FID integrity**: * `Result.formula_id` and `RunRecord.formula_id` MUST match the FID recomputed from **Annex A (Included)** and the algorithm code at the declared `engine.version`. * Presentation toggles (e.g., `VM-VAR-060..062`) MUST NOT participate in FID hashing. * **Determinism**: with identical inputs \+ ParameterSet (including `VM-VAR-052` when applicable) on any supported platform, artifacts must be **byte-identical**. --- ## **7\) File layout & naming** Default output filenames in the run directory: * `result.json`, `run_record.json`, optionally `frontier_map.json` * It is permitted to emit compressed mirrors (e.g., `.json.zst`) **in addition** to canonical JSON, but IDs and hashes are computed over the **canonical JSON**. --- ## **8\) Notes for implementers** * Keep **DivisionRegistry** and **BallotTally** schemas stable; additions MUST be strictly additive and non-reordering. * Treat **`order_index`** as a **hard determinism primitive**; never infer order from display names or input order. * Echo the **effective** values you actually used in `RunRecord.vars_effective` (no “implicit defaults” during hashing). * If you extend diagnostics, do so under **new fields**; never mutate existing canonical fields or their ordering semantics. --- ### **Appendix: VM-VAR touchpoints referenced in this part** * **Ties**: `VM-VAR-050 tie_policy`, `VM-VAR-052 tie_seed` (051 reserved). * **Presentation (excluded from FID)**: `VM-VAR-060 majority_label_threshold`, `VM-VAR-061 decisiveness_label_policy`, `VM-VAR-062 unit_display_language`. --- # **Doc 1B — Field Catalog & Validation Constraints (Updated, Normative)** ## **1\) Purpose & scope** Defines **every field**, its **type/domain**, **cardinality/keys**, **size limits**, and **validation rules** for all artifacts named in Doc 1A. No legacy or back-compat paths are provided. Artifacts covered: `DivisionRegistry`, `BallotTally`, `ParameterSet`, `Result`, `RunRecord`, `FrontierMap`. JSON is canonical as per Doc 1A (§2.1). All field names are `snake_case`. --- ## **2\) Identifiers, strings, numbers** **2.1 IDs & hashes** * `unit_id`, `option_id`: non-empty strings, max **64** chars; allowed: `A–Z a–z 0–9 _ - : .`. * `result_id` \= `"RES:"` \+ **64-hex** (lowercase). `run_id` \= `"RUN:"` \+ `` \+ `-` \+ **64-hex**. `frontier_id` \= `"FR:"` \+ **64-hex**. * All sha256 digests are **64 lowercase hex**. **2.2 Strings** * Unicode **UTF-8**, NFC-normalized. * No leading/trailing spaces. No control chars except LF in free-text `notes`. **2.3 Numbers** * Integers: 64-bit signed non-negative unless noted. * Percentages stored as integers in **0…100** (%). * Ratios/shares as JSON numbers; engine sets precision; reporters round per Doc 7\. **2.4 Date/times** * `created_at` in **UTC**, RFC 3339/ISO 8601 (e.g., `2025-08-12T14:00:00Z`). --- ## **3\) Entity catalog (fields, domains, keys)** ### **3.1 DivisionRegistry (input)** { "schema\_version": "1.x", "units": \[ { ... } \] } * `schema_version` — string, required. * `units[]` — array ≥ 1, required. **Order**: ascending `unit_id`. **Unit object** * `unit_id` — string, required, **PK** in this document. * `name` — string 1..200, required. * `protected_area` — boolean, required. * `options[]` — array ≥ 1, required. **Order**: ascending `order_index`. **Option object** * `option_id` — string, required, **PK** within unit. * `name` — string 1..200, required. * `order_index` — integer ≥ 0, **unique within unit**, required. **Integrity** * (`unit_id`, `option_id`) pairs define the **universe**. Must be stable across runs. --- ### **3.2 BallotTally (input)** { "schema\_version": "1.x", "units": \[ { ... } \] } **Unit tally** * `unit_id` — string, required, **FK → DivisionRegistry.units.unit\_id**. * `totals.valid_ballots` — int ≥ 0, required. * `totals.invalid_ballots` — int ≥ 0, required. * `options[]` — array of per-option tallies. **Option tally** * `option_id` — string, required, **FK → corresponding unit option\_id**. * `votes` — int ≥ 0, required. **Integrity** * Sum of `options[].votes` ≤ `totals.valid_ballots`. * Every tallied `option_id` must exist for that `unit_id`. * Units **ordered** as in Registry; options **ordered** by Registry `order_index`. --- ### **3.3 ParameterSet (input)** { "schema\_version": "1.x", "vars": { "VM-VAR-\#\#\#\#": \, ... } } * `vars` is a map keyed by **VM-VAR-\#\#\#\#** strings. * **Outcome-affecting variables** listed in Annex A/“Included in FID”: **MUST** be present with explicit values. * **Presentation/reporting variables** (e.g., `VM-VAR-060..062`) **MAY** be present for transparency; they are **excluded from FID**. * Domains for each `VM-VAR` are defined in **Annex A**. This doc only enforces that keys are syntactically `VM-VAR-000…999`. --- ### **3.4 Result (output)** { "result\_id": "RES:\<64hex\>", "formula\_id": "\<64hex\>", "engine\_version": "vX.Y.Z", "created\_at": "2025-08-12T14:00:00Z", "summary": { ... }, "units": \[ { ... } \] } * `result_id` — required; sha256 over canonical `Result`. * `formula_id` — required; **64-hex** FID per Doc 1A. * `engine_version` — string 1..32, required. * `created_at` — RFC3339 UTC, required. * `summary` — object, required (global metrics; schema below). * `units[]` — array ≥ 1, required. **Order**: ascending `unit_id`. **summary (minimum)** * `valid_ballots_total` — int ≥ 0, required. * `invalid_ballots_total` — int ≥ 0, required. * `turnout_rate` — number ≥ 0 (engine-chosen precision). * Any thresholds/parameters that materially affected outcomes (e.g., gating bands actually used) MUST be echoed here or in `RunRecord`. **unit result** * `unit_id` — string, required, **FK → Registry**. * `allocations[]` — array ≥ 1, required. **Order**: by Registry `order_index`. * `label` — string, required (“Decisive”, “Marginal”, “Invalid”); derived. **allocation** * `option_id` — string, required, **FK**. * `votes` — int ≥ 0, required. * `share` — number in \[0,1\], required (engine precision policy). * Optional deriveds (e.g., seats) only if relevant to the algorithm family. --- ### **3.5 RunRecord (output)** { "run\_id": "RUN:\-\<64hex\>", "result\_id": "RES:\<64hex\>", "formula\_id": "\<64hex\>", "engine": { "vendor": "...", "name": "...", "version": "vX.Y.Z", "build": "commit:...." }, "inputs": { "division\_registry\_sha256": "\<64hex\>", "ballot\_tally\_sha256": "\<64hex\>", "parameter\_set\_sha256": "\<64hex\>" }, "nm\_digest": { "schema\_version": "1.x", "nm\_sha256": "\<64hex\>" }, "vars\_effective": { "VM-VAR-\#\#\#\#": \, ... }, "determinism": { "tie\_policy": "status\_quo|deterministic\_order|random", "rng\_seed": 0 }, "ties": \[ { ... } \] } * `run_id`, `result_id`, `formula_id` — required, formats as above. * `engine.vendor`, `.name`, `.version` — non-empty strings ≤ 64, required. `engine.build` — free string ≤ 128 (e.g., commit), required. * `inputs.*_sha256` — required **64-hex**; digests of **canonical** inputs. * `nm_digest.nm_sha256` — required **64-hex** digest of the Normative Manifest used for FID. * `vars_effective` — required map; MUST include all **outcome-affecting** VM-VARs with the **exact** values used. Presentation vars MAY be included. * `determinism.tie_policy` — required; mirrors `VM-VAR-050`. `determinism.rng_seed` — present **only** if any tie used random policy (mirrors `VM-VAR-052` value used at runtime). * `ties[]` — optional list of events (see below). **tie event** { "unit\_id": "U-001", "type": "winner\_tie|rank\_tie|other", "policy": "status\_quo|deterministic\_order|random", "seed": 424242 } * `seed` present only if `policy="random"` on that event. --- ### **3.6 FrontierMap (optional output)** { "frontier\_id": "FR:\<64hex\>", "units": \[ { "unit\_id": "U-001", "band\_met": true, "band\_value": 0.12, "notes": "..." } \] } * `frontier_id` — required if file emitted. * `units[]` — required, **order** by ascending `unit_id`. * `band_met` — **boolean**, required (normalized name). * `band_value` — number (engine precision policy). * `notes` — optional string ≤ 280\. --- ## **4\) Cross-entity invariants** * **Referential integrity:** Every `unit_id`/`option_id` in `BallotTally`, `Result`, `FrontierMap`, and `RunRecord.ties[]` **must** exist in `DivisionRegistry`. * **Ordering invariants (determinism):** Units: ascending `unit_id`. Options: ascending `order_index` (ties by `option_id`). All arrays reflect these orders (Doc 1A §5). * **Hash integrity:** `result_id`, `run_id`, `frontier_id` exactly match sha256 of the **canonical** payloads. `inputs.*_sha256` match canonical inputs used. * **FID integrity:** `Result.formula_id` and `RunRecord.formula_id` equal recomputed FID for the run. Presentation vars (e.g., `VM-VAR-060..062`) are **excluded** from FID. * **Non-negativity & bounds:** Votes, ballots ≥ 0; percentages 0..100; shares 0..1. --- ## **5\) Indexing & size guidance (implementation-level, informative)** * Recommended indexes if persisted in a DBMS: * `DivisionRegistry.units(unit_id)`; `options(unit_id, order_index)` unique. * `BallotTally.units(unit_id)`; `options(unit_id, option_id)`. * `Result.units(unit_id)`; `allocations(unit_id, option_id)`. * File size expectations (guidance): `result.json` ≤ few MB for national runs; `run_record.json` may be larger due to `vars_effective` and `ties`. --- ## **6\) Validation failures (non-exhaustive)** | Code | Condition | Artifact | | ----- | ----- | ----- | | `E-DR-UNIT-DUP` | Duplicate `unit_id` in DivisionRegistry | DivisionRegistry | | `E-DR-OPT-DUP` | Duplicate `option_id` within a unit | DivisionRegistry | | `E-DR-ORD-UNIQ` | Duplicate `order_index` within a unit | DivisionRegistry | | `E-BT-FK-UNIT` | `BallotTally.unit_id` missing in Registry | BallotTally | | `E-BT-FK-OPT` | Tallied `option_id` not in unit’s options | BallotTally | | `E-BT-SUM` | Sum of option votes exceeds `valid_ballots` | BallotTally | | `E-PS-MISS` | Required outcome-affecting VM-VAR missing | ParameterSet | | `E-RR-HASH` | Any recorded hash/digest does not verify | RunRecord | | `E-RR-FID` | Reported FID cannot be recomputed | Result/RunRecord | --- ## **7\) Minimal worked examples (conformant)** **DivisionRegistry (excerpt)** {"schema\_version":"1.x","units":\[ {"unit\_id":"U-001","name":"District 1","protected\_area":false, "options":\[{"option\_id":"O-A1","name":"Option A","order\_index":1}, {"option\_id":"O-B1","name":"Option B","order\_index":2}\]} \]} **BallotTally (excerpt)** {"schema\_version":"1.x","units":\[ {"unit\_id":"U-001", "totals":{"valid\_ballots":11000,"invalid\_ballots":67}, "options":\[{"option\_id":"O-A1","votes":6000},{"option\_id":"O-B1","votes":5000}\]} \]} **ParameterSet (excerpt)** {"schema\_version":"1.x","vars":{ "VM-VAR-050":"status\_quo", "VM-VAR-052":0, "VM-VAR-060":55, "VM-VAR-061":"dynamic\_margin", "VM-VAR-062":"auto" }} **Result.units\[0\].allocations (ordering)** {"unit\_id":"U-001","allocations":\[ {"option\_id":"O-A1","votes":6000,"share":0.545}, {"option\_id":"O-B1","votes":5000,"share":0.455} \]} **FrontierMap.units\[0\]** {"unit\_id":"U-001","band\_met":true,"band\_value":0.12,"notes":"within band-1 threshold"} --- ### **Appendix A — Tie & presentation touchpoints (for traceability)** * Ties are controlled by **VM-VAR-050** (policy) and **VM-VAR-052** (seed). There is **no** variable for deterministic order; it always uses `order_index`. * Presentation/report toggles (e.g., **VM-VAR-060..062**) are recorded for transparency and **excluded from FID**. *End Doc 1B.* # **Doc 1C — Cross-Artifact Mapping, ER & Worked Examples (Updated)** ## **1\) Purpose & scope** Binds the schemas from **Doc 1A/1B** into a single, enforceable model: entity-relationships, lifecycle of a run, validation flows, and minimal “golden” examples. Normative where it defines constraints; illustrative where it shows examples. No legacy/back-compat paths. --- ## **2\) Entity–relationship model (canonical)** ### **2.1 Text ER (cardinalities & keys)** DivisionRegistry └── units \[1..N\] PK: unit\_id └── options \[1..N\] PK: (unit\_id, option\_id) UNIQUE within unit: order\_index BallotTally └── units \[1..N\] FK: unit\_id → DivisionRegistry.units └── options \[0..N\] FK: (unit\_id, option\_id) → DivisionRegistry.options Result └── units \[1..N\] FK: unit\_id → DivisionRegistry.units └── allocations \[1..N\] FK: (unit\_id, option\_id) → DivisionRegistry.options RunRecord ├── inputs.digests of canonical inputs hashes of DivisionRegistry, BallotTally, ParameterSet ├── vars\_effective VM-VAR map MUST include all outcome-affecting variables └── ties \[0..N\] unit\_id present; seed present iff policy=random FrontierMap (optional) └── units \[0..N\] FK: unit\_id → DivisionRegistry.units ### **2.2 Referential rules (normative)** * Every `BallotTally.units[].unit_id`, `Result.units[].unit_id`, `FrontierMap.units[].unit_id`, and `RunRecord.ties[].unit_id` **MUST** exist in `DivisionRegistry.units`. * Every tallied or allocated `(unit_id, option_id)` **MUST** exist in `DivisionRegistry.options` for that unit. --- ## **3\) Run lifecycle (deterministic pipeline)** 1. **Load & canonicalize inputs** * Parse `DivisionRegistry`, `BallotTally`, `ParameterSet`. * Enforce Doc 1B domains/bounds. * Compute and record each input’s sha256 (64-hex) for `RunRecord.inputs`. 2. **Compute Normative Manifest → FID** * Collect outcome-affecting rules & VM-VARs (per Annex A “Included”). * Canonicalize the manifest and hash → **FormulaID (64-hex)**. * Presentation/report toggles (e.g., `VM-VAR-060..062`) are **excluded**. 3. **Count / allocate** * Apply algorithm (Doc 4). Respect `option.order_index` as the determinism key. * Resolve ties per `VM-VAR-050 tie_policy`; if `random`, use `VM-VAR-052 tie_seed`. * Record any tie event into `RunRecord.ties[]`. 4. **Render artifacts** * Build **Result**, **RunRecord**, optional **FrontierMap** in canonical JSON (Doc 1A §2.1). * Compute `result_id`, `run_id`, `frontier_id` (sha256 over canonical payloads). * Set `Result.formula_id` and `RunRecord.formula_id` to the FID from step 2\. * Populate `RunRecord.vars_effective` with **exact** outcome-affecting values used; presentation vars may be echoed. 5. **Verify & emit** * Self-verify all recorded hashes. * Emit files; optional compressed mirrors are allowed but IDs are over canonical JSON. --- ## **4\) Ordering contract (single source of determinism)** * **Units arrays**: ascending `unit_id` (string compare). * **Options within a Unit**: ascending `order_index`; ties by `option_id`. * **Allocations and all per-unit arrays**: mirror Registry option order. * **Tie policies**: * `status_quo` — policy per algorithm; no extra variable. * `deterministic_order` — break by `order_index` (no variable; `VM-VAR-051` is reserved). * `random` — deterministic RNG seeded by `VM-VAR-052`; record events. --- ## **5\) Validation flow (pseudo-algorithm)** validate\_division\_registry(reg): assert reg.units.length ≥ 1 assert unit\_id unique for u in reg.units: assert options.length ≥ 1 assert option\_id unique within u assert order\_index unique within u and ≥ 0 validate\_ballot\_tally(tally, reg): for ut in tally.units: assert ut.unit\_id in reg.units sum\_votes \= 0 for ot in ut.options: assert (ut.unit\_id, ot.option\_id) in reg.options assert ot.votes ≥ 0 sum\_votes \+= ot.votes assert sum\_votes ≤ ut.totals.valid\_ballots validate\_parameter\_set(ps): for each REQUIRED VM-VAR in AnnexA.Included: assert present and in domain // presentation vars may be present; excluded from FID validate\_referential(result, reg): for ru in result.units: assert ru.unit\_id in reg.units for a in ru.allocations: assert (ru.unit\_id, a.option\_id) in reg.options Error codes align with Doc 1B §6. --- ## **6\) Worked “golden” examples (minimal)** ### **6.1 Inputs** **DivisionRegistry** {"schema\_version":"1.x","units":\[ {"unit\_id":"U-001","name":"District 1","protected\_area":false, "options":\[ {"option\_id":"O-A1","name":"Option A","order\_index":1}, {"option\_id":"O-B1","name":"Option B","order\_index":2} \]} \]} **BallotTally** {"schema\_version":"1.x","units":\[ {"unit\_id":"U-001", "totals":{"valid\_ballots":11000,"invalid\_ballots":67}, "options":\[{"option\_id":"O-A1","votes":6000},{"option\_id":"O-B1","votes":5000}\]} \]} **ParameterSet** {"schema\_version":"1.x","vars":{ "VM-VAR-050":"status\_quo", "VM-VAR-052":0, "VM-VAR-060":55, "VM-VAR-061":"dynamic\_margin", "VM-VAR-062":"auto" }} ### **6.2 Outputs (canonical form excerpts)** **Result** { "result\_id": "RES:\<64hex\>", "formula\_id": "\<64hex\>", "engine\_version": "vX.Y.Z", "created\_at": "2025-08-12T14:00:00Z", "summary": { "valid\_ballots\_total": 11000, "invalid\_ballots\_total": 67, "turnout\_rate": 0.000 }, "units": \[ { "unit\_id": "U-001", "allocations": \[ {"option\_id":"O-A1","votes":6000,"share":0.545}, {"option\_id":"O-B1","votes":5000,"share":0.455} \], "label": "Decisive" } \] } **RunRecord** { "run\_id": "RUN:\-\<64hex\>", "result\_id": "RES:\<64hex\>", "formula\_id": "\<64hex\>", "engine": {"vendor":"acme.labs","name":"vm\_engine","version":"vX.Y.Z","build":"commit:abcd1234"}, "inputs": { "division\_registry\_sha256": "\<64hex\>", "ballot\_tally\_sha256": "\<64hex\>", "parameter\_set\_sha256": "\<64hex\>" }, "nm\_digest": {"schema\_version":"1.x","nm\_sha256":"\<64hex\>"}, "vars\_effective": { "VM-VAR-050":"status\_quo", "VM-VAR-052":0 /\* ... \*/ }, "determinism": { "tie\_policy":"status\_quo" }, "ties": \[\] } **FrontierMap (optional)** { "frontier\_id":"FR:\<64hex\>", "units":\[{"unit\_id":"U-001","band\_met":true,"band\_value":0.12,"notes":"within band-1 threshold"}\] } --- ## **7\) Conformance checklist (doc-level)** * **C-ER-01**: All FK references resolve to DivisionRegistry. * **C-ORD-02**: All arrays follow ordering contract (§4). * **C-HASH-03**: `result_id`, `run_id`, `frontier_id` verify against canonical payloads. * **C-FID-04**: FID recomputes from Annex A “Included” and equals both `Result.formula_id` and `RunRecord.formula_id`. * **C-TIE-05**: If any random tie occurred, `RunRecord.determinism.rng_seed` is present and `ties[]` contains at least one event. * **C-PRES-06**: Presentation variables (e.g., `VM-VAR-060..062`) recorded for transparency but do **not** affect FID. --- ## **8\) Implementation notes (informative)** * Treat `order_index` as a **hard determinism primitive**; never infer order from human labels. * When emitting diffs or audits, diff **canonical JSON** to avoid false changes from key order or whitespace. * If you add diagnostic fields, add new keys; **never** mutate existing canonical fields or their ordering semantics. *End Doc 1C.* ================================================================================================ FILE: docs/Doc 2 — Common Variables Specification (Core, Operational Defaults, Advanced Controls).md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 8876349e09f4e913b8e6b359140bbbde797c2ec0eae06f3e075dbcf9942b08ad CONTENT_BYTES: 18810 ================================================================================================ # **Doc 2A — Common Variables: Core (Updated, Normative)** ## **1\) Purpose & scope** Defines the **outcome-affecting variables** (“VM-VARs”) that the engine reads at runtime and that are **included in the Formula ID (FID)** per Doc 1A. This part is **normative** and replaces any prior numbering/legacy notes. Presentation/reporting toggles are **not** here (they live in Doc 2B and are excluded from FID). Result: with the **same inputs** and the **same 2A values**, outputs are **byte-identical** across OS/arch. --- ## **2\) Canonical registry & format** * Every variable is registered as **`VM-VAR-###`** (three digits, zero-padded). * Values are carried in the **ParameterSet** (`ParameterSet.vars["VM-VAR-###"]`) as canonical JSON (Doc 1A §2.1). * **Domains** (type, allowed values/ranges), **defaults**, and **FID inclusion** are centralized in **Annex A — VM-VAR Registry**. Doc 2A defines *which* variables are normative core and how they are used by Docs 4/5. --- ## **3\) Inclusion policy (FID)** * **Included**: only variables that can change outcomes (the “2A core set”). * **Excluded**: presentation/reporting toggles (Doc 2B) — e.g., labels, language, formatting. * FID recomputation uses the 2A core set **and** the algorithm rules (Doc 4). See Doc 1A §2.3. --- ## **4\) Core set (IDs & groups)** Doc 2A groups the **included** variables by function. The **precise per-variable spec** (domain, default, semantics) is in **Annex A**; this section fixes **membership** and **cross-doc usage**. ### **4.1 Global algorithm & scope** * **VM-VAR-001 … 007** — Global algorithm family/rounding/flow constants (see Annex A). *Used by*: Doc 4A step order; Doc 5A state machine. * **VM-VAR-021** — Run **scope** / inclusion guard (e.g., filter or eligibility scope). *Used by*: Doc 4A preconditions; Doc 6A validity tests. ### **4.2 Thresholds & eligibility (per-unit / national)** * **VM-VAR-010 … 017** — Eligibility/validity gates (core percentages/flags). * **VM-VAR-020 … 029** — Outcome-affecting thresholds (e.g., minimum shares, gating cutoffs). *Used by*: Doc 4B gates & edge cases; Doc 6B conformance. ### **4.3 Frontier & gating model** * **VM-VAR-040** — Frontier/gating **mode** (model selector). * **VM-VAR-041** — Frontier **band**/cut param(s). * **VM-VAR-042** — Frontier **application strategy** (how bands affect flow). *Used by*: Doc 4C Frontier rules; Doc 5B Frontier stage; optional FrontierMap (Doc 1A §4.6). ### **4.4 Protected & autonomy controls** * **VM-VAR-045** — **Protected-area override** (allow/deny policy when flagged). * **VM-VAR-046** — **Autonomy package map** (selection for autonomy ladder mode). *Used by*: Doc 4C §Protected/Autonomy; Doc 6C edge-case tests. ### **4.5 Ties — pointer only (variables live in Doc 2B)** (Referential note): Tie controls are **VM-VAR-050** (*tie\_policy*) and **VM-VAR-052** (*tie\_seed*). They are specified and defaulted in Doc 2B. **VM-VAR-050 is Included in FID (affects outcomes); VM-VAR-052 is Excluded from FID (seed only).** The RNG algorithm/profile used for random ties is pinned in **Annex B** (`rng_profile.json`). **Used by:** Doc 4C (tie resolution); Doc 5B (`VM-FUN-008 ResolveTies`); Doc 5C (TieLog); Doc 6C (determinism). **Complete 2A membership for FID (by range):** `001–007, 010–017, 020–031 (incl. 021, 029–031), 040–049, 050, 073.` **Excluded (presentation/reporting or seed):** `032–035, 052, 060–062` (see Doc 2B). --- ## **5\) Cross-doc contract (how 2A is consumed)** | Group | Consumed by | Contract highlights | | ----- | ----- | ----- | | Global & scope (001–007, 021\) | Doc 4A, Doc 5A | Fix step order/rounding and run scope before any counting. | | Thresholds (010–017, 020–029) | Doc 4B, Doc 6B | Apply before allocation; failing gates invalidate/branch as defined. | | Frontier (040–042) | Doc 4C, Doc 5B, FrontierMap | Drive band selection and gating; emit `band_met` diagnostics if enabled. | | Protected/Autonomy (045–046) | Doc 4C, Doc 6C | Override rules when units are protected; map autonomy packages deterministically. | | Ties (050, 052\) | Doc 4C, Doc 5C, Doc 6C | Policy & deterministic RNG; events logged in RunRecord.ties. | --- ## **6\) Defaults & mutability (where set)** * **Defaults** for all 2A variables are declared in **Annex A** and surfaced in **Doc 2B** tables for operational clarity. * Any change to a **2A** default or domain is a **normative change** → **new FID** (Doc 3B change policy). * Variables in 2A are **stable IDs**: do not renumber or repurpose. --- ## **7\) Conformance checks** * **C-2A-INC**: ParameterSet contains explicit values for **all** 2A variables listed as “Included” in Annex A. * **C-2A-DOM**: Each value is within the Annex A domain; engine rejects out-of-range. * **C-2A-USE**: Engine consumes 2A variables exactly at the documented points (Doc 4/5 references). * **C-FID-LOCK**: Recomputing FID with these variables yields `Result.formula_id` (Doc 1A §2.3). --- ## **8\) Notes for implementers** * Treat **Annex A** as the *single source of truth* for per-variable domains & defaults; Doc 2A fixes **membership** and **usage points**. * Do **not** add engine-specific hidden toggles that alter outcomes; propose new VM-VAR IDs via Annex A if a feature becomes normative. * When adding diagnostics, ensure they don’t alter any 2A flow or array ordering (Doc 1A §5). --- ### **Appendix (traceability stubs)** * **VM-VAR-040/041/042 →** Doc 4C Frontier; Doc 5B Frontier stage; FrontierMap schema (Doc 1A §4.6). * **VM-VAR-045 →** Doc 4C Protected override; Doc 6C tests. * **VM-VAR-050/052 →** Doc 4C Ties; Doc 5C ResolveTies; Doc 6C determinism. *End Doc 2A.* # **Doc 2B — Operational Defaults & Presentation (Updated)** ## **1\) Purpose & scope** Defines the **operational defaults** and **presentation/reporting toggles** the engine and renderer read at runtime. This part integrates the former integration/addendum notes and removes legacy numbering. Two classes of variables live here: * **Outcome-affecting operational defaults** (e.g., *tie policy*). Some of these **are included** in the Formula ID (FID) per Doc 1A/Annex A. * **Presentation/report toggles** (labels, language, layout). These are **not included** in FID. Unless stated otherwise, values are carried in `ParameterSet.vars["VM-VAR-###"]` and are read deterministically by Docs 4/5/7. Canonicalization rules are in Doc 1A. --- ## **2\) Grouping & FID policy (at a glance)** | Group | IDs | FID? | What they influence | | ----- | ----- | ----- | ----- | | A. Tie & RNG controls | **050, 051 (reserved), 052** | **Policy: YES** / **Seed: NO** | Winner/rank resolution when ties occur (Doc 4C, Doc 5C). | | B. Pipeline/Report toggles | **032–035** | **NO** | Whether to emit diagnostic artifacts/sections; report section ordering. | | C. Labeling & language | **060–062** | **NO** | Outcome *labels* and display language (Doc 4C labels, Doc 7). | FID inclusion/exclusion is authoritative in **Annex A — VM-VAR Registry**. This doc mirrors that policy. --- ## **3\) Variables — specifications** ### **A) Tie & RNG controls (operational; outcome-affecting)** These control **how** ties are resolved. They affect outcomes; thus **tie\_policy** is in FID. The **seed** is a run parameter and **not** in FID; it is recorded in RunRecord. | ID | Name | Type / Domain | Default | FID? | Used by | Notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-050** | `tie_policy` | enum: `status_quo` | `deterministic_order` | `random` | `status_quo` | **Yes** | Doc 4C (§Ties), Doc 5C (`ResolveTies`), Doc 6C | `deterministic_order` uses `Option.order_index`; no separate variable exists for the order key. | | **VM-VAR-051** | *(reserved)* | — | — | — | — | Intentionally unused (kept to avoid future renumbering). | | **VM-VAR-052** | `tie_seed` | integer ≥ 0 | `0` | **No** | Doc 3A (RNG), Doc 4C (§Ties), Doc 5C, Doc 6C | Used **only** when `tie_policy= random`. Recorded in `RunRecord.determinism.rng_seed` and `RunRecord.ties[]`. | --- ### **B) Pipeline / report toggles (operational; non-FID)** These **do not** change outcomes. They gate diagnostics or influence **report layout only**. JSON serialization and algorithm arrays still follow Doc 1A ordering rules. | ID | Name | Type / Domain | Default | FID? | Used by | Notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-032** | `unit_sort_order` | enum: `unit_id` | `label_priority` | `turnout` | `unit_id` | **No** | Doc 7 (rendering) | Affects **report section order only**. JSON arrays remain ordered by canonical rules (Doc 1A §5). | | **VM-VAR-033** | `ties_section_visibility` | enum: `auto` | `always` | `never` | `auto` | **No** | Doc 7 (report templates) | `auto` shows the Ties section only if any event exists in `RunRecord.ties[]`. | | **VM-VAR-034** | `frontier_map_enabled` | boolean | `true` | **No** | Doc 5B (Frontier stage), Doc 7 (appendix), FrontierMap | When `false`, skip emitting `frontier_map.json` and hide the appendix. | | **VM-VAR-035** | `sensitivity_analysis_enabled` | boolean | `false` | **No** | Doc 5C (`CompareScenarios`), Doc 7 (appendix) | Runs diagnostic comparisons (does **not** alter `Result`). | --- ### **C) Labeling & language (presentation; non-FID)** These variables influence **labels** and language in outputs. They never alter counts/allocations. | ID | Name | Type / Domain | Default | FID? | Used by | Notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-060** | `majority_label_threshold` | integer % in **0..100** | `55` | **No** | Doc 4C (§Labels), Doc 7 | National (or configured scope) margin ≥ threshold ⇒ “Decisive” if no blocking flags (policy-dependent). | | **VM-VAR-061** | `decisiveness_label_policy` | enum: `fixed` | `dynamic_margin` | `dynamic_margin` | **No** | Doc 4C (§Labels), Doc 7 | `fixed`: label by margin only. `dynamic_margin`: also consider mediation/protected flags when labeling. | | **VM-VAR-062** | `unit_display_language` | `auto` | IETF tag (e.g., `en`, `fr`) | `auto` | **No** | Doc 7 (bilingual handling) | Controls display language for unit names in the rendered report(s). | --- ## **4\) Cross-doc integration map** | Variable(s) | Consumed by | Contract highlights | | ----- | ----- | ----- | | 050, 052 | Doc 4C (Ties), Doc 5C (`ResolveTies`), Doc 6C | Policy drives branch; if `random`, RNG seeded by 052; events captured in `RunRecord.ties[]`. | | 034 | Doc 5B, Doc 7, FrontierMap | If `false`, skip Frontier stage emission and hide appendix; never affects allocations. | | 035 | Doc 5C, Doc 7 | If `true`, run scenario comparisons; results live in report appendix only. | | 032 | Doc 7 | Affects ordering of **sections in the report**; JSON ordering stays canonical (Doc 1A §5). | | 033 | Doc 7 | Show/hide “Ties” section (`auto` when any tie occurred). | | 060–062 | Doc 4C (labels), Doc 7 | Compute and render labels & language; do **not** enter FID. | --- ## **5\) Stability & change policy** * IDs **032–035** and **060–062** are **stable**; they are **never** part of FID. * **050/052** are stable; **050** participates in FID, **052** does not. * Any proposal to move a variable between FID/non-FID classes requires updating **Annex A** and a release decision per Doc 3B. --- ## **6\) Conformance checks** * **C-2B-REF-01**: Engine/renderer **must** ignore these toggles for canonical JSON ordering (Doc 1A §5). * **C-2B-TIE-02**: If `tie_policy = random`, the engine uses `tie_seed` and records seed and events in `RunRecord`. * **C-2B-LBL-03**: Labels rendered per 060/061; allocations and tallies unaffected. * **C-2B-EMIT-04**: `frontier_map_enabled=false` results in no `frontier_map.json`; report omits the appendix. * **C-2B-SCN-05**: `sensitivity_analysis_enabled=true` does not change `Result` or any hashable artifact other than the added appendix. --- ## **7\) ParameterSet example (excerpt)** { "schema\_version": "1.x", "vars": { "VM-VAR-050": "status\_quo", "VM-VAR-052": 0, "VM-VAR-032": "unit\_id", "VM-VAR-033": "auto", "VM-VAR-034": true, "VM-VAR-035": false, "VM-VAR-060": 55, "VM-VAR-061": "dynamic\_margin", "VM-VAR-062": "auto" } } --- ## **8\) Notes** * There is **no variable** for the deterministic tie order key: it is always `Option.order_index` (Doc 1A §5). * Report **decimal precision** is fixed by Doc 7; there is **no** VM-VAR controlling it. * This document supersedes any earlier text that placed tie variables at 032–033 or labeled 050–052 as legacy. # **Doc 2C — Advanced Controls (Updated, Normative)** ## **1\) Purpose & scope** Defines the **expert/outcome-affecting** controls that are not part of everyday operation but must be fixed for reproducibility. These variables are **included in the FID** (Doc 1A) when present because they can change outcomes. Presentation/report toggles remain in Doc 2B and are excluded from FID. This part completes **Doc 2 (A/B/C)** so the engine, pipeline, and tests have a single canonical map of variables. --- ## **2\) FID policy (for 2C variables)** * All variables in this section are **outcome-affecting ⇒ FID \= YES**. * Defaults are declared in **Annex A — VM-VAR Registry** and surfaced in `ParameterSet`. * If a 2C variable is **unset**, the engine uses its Annex A default (still part of FID via the normative manifest). --- ## **3\) Variables — specifications** ### **D) Exceptions & scope refinements** Controls that narrowly refine eligibility, symmetry, or validity guardrails. | ID | Name | Type / Domain (see Annex A for exact domain) | Default | FID? | Used by | Notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-021** | `run_scope` | enum/map (scope selector) | `all_units` | **Yes** | Doc 4A preconditions; Doc 5A | Defines inclusion scope (e.g., all units vs filtered set). Included here for traceability although grouped with “global” in 2A membership. | | **VM-VAR-029** | `symmetry_exceptions` | array of selectors (unit/option patterns) | `[]` | **Yes** | Doc 4B gates; Doc 6B | Narrow, explicit exceptions to otherwise symmetric rules. Engine must match deterministically and only where permitted. | | **VM-VAR-030** | `eligibility_override_list` | array of \`{unit\_id: string, mode: include | exclude}\` | `[]` | **Yes** | Doc 4B gates; Doc 5A | | **VM-VAR-031** | `ballot_integrity_floor` | integer % in **0..100** | `0` | **Yes** | Doc 4B invalidation; Doc 6B | If a unit’s integrity KPI \< floor ⇒ unit invalid/branch per algorithm family. | Rationale: these are rarely used, but when set they can alter eligibility/validity and therefore outcomes. --- ### **E) Frontier tuning (advanced)** Fine-grained controls for band/window behavior beyond the core frontier settings (**040–042** in 2A). | ID | Name | Type / Domain | Default | FID? | Used by | Notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-047** | `frontier_band_window` | number in **\[0,1\]** or enum per Annex A | `0.00` | **Yes** | Doc 4C Frontier; Doc 5B | Expands/contracts the effective band around the core cut(s) in 041\. | | **VM-VAR-048** | `frontier_backoff_policy` | enum: `none` | `soften` | `harden` | `none` | **Yes** | Doc 4C Frontier; Doc 6C | How the engine resolves borderline cases at the edge of bands. | | **VM-VAR-049** | `frontier_strictness` | enum: `strict` | `lenient` | `strict` | **Yes** | Doc 4C Frontier | Coarse toggle that multiplies effects of 047/048 in a defined way. | These do **not** replace **040–042**; they refine them. Annex A formalizes the combination rules (e.g., precedence, clamping). --- ### **F) Algorithm minor variant anchor** A controlled switch for sanctioned micro-variants (use sparingly). | ID | Name | Type / Domain | Default | FID? | Used by | Notes | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | **VM-VAR-073** | `algorithm_variant` | enum (e.g., `v1`) | `v1` | **Yes** | Doc 4A step order; Doc 3B change policy | Locks a documented micro-variant (e.g., rounding tie-break preference within identical formulas). Not a presentation switch. | --- ## **4\) Cross-doc integration map** | Variable(s) | Consumed by | Contract highlights | | ----- | ----- | ----- | | 021, 029–031 | Doc 4A/4B; Doc 5A; Doc 6A/6B | Evaluated before allocation; alter eligibility/validity branches deterministically. | | 047–049 | Doc 4C; Doc 5B; Doc 6C | Modify frontier behavior around the core band selection (040–042). Effects must be fully documented in RunRecord summary if they change gating outcomes. | | 073 | Doc 4A; Doc 3B | Selects a documented micro-variant; any change requires new FID (and Engine Version per Doc 3B). | --- ## **5\) Conformance checks** * **C-2C-SCOPE**: If `run_scope` ≠ `all_units`, the filtered set is recorded in `RunRecord.summary` and applied consistently across inputs. * **C-2C-EXC**: `symmetry_exceptions` are matched deterministically (no regex entropy); unmatched patterns are rejected. * **C-2C-ELIG**: `eligibility_override_list` is applied before threshold gates; conflicts with core rules are resolved per Annex A precedence. * **C-2C-INT**: If `ballot_integrity_floor` causes invalidation, the reason is logged (Doc 7 integrity note). * **C-2C-FRONTIER**: 047–049 tuning cannot invert the meaning of 040–042; only refine within documented bounds. * **C-2C-VARIANT**: `algorithm_variant` MUST be printed in the report footer beside Formula ID and Engine Version. --- ## **6\) ParameterSet example (excerpt)** { "schema\_version": "1.x", "vars": { "VM-VAR-021": "all\_units", "VM-VAR-029": \[\], "VM-VAR-030": \[\], "VM-VAR-031": 0, "VM-VAR-047": 0.00, "VM-VAR-048": "none", "VM-VAR-049": "strict", "VM-VAR-073": "v1", "VM-VAR-040": "banded", // from 2A "VM-VAR-041": 0.10, "VM-VAR-042": "apply\_on\_entry", "VM-VAR-050": "status\_quo", // from 2B (outcome-affecting) "VM-VAR-052": 0, "VM-VAR-060": 55, // presentation (2B) "VM-VAR-061": "dynamic\_margin", "VM-VAR-062": "auto" } } --- ## **7\) Notes for implementers** * Keep 2C switches **well-documented** in Annex A (domains, defaults, precedence). * If your deployment doesn’t need 2C, leave defaults in place; they still contribute to FID via the normative manifest. * Do **not** add new hidden “advanced” toggles in code paths; propose new VM-VARs (and update Annex A) when behavior changes outcomes. *End Doc 2C.* ================================================================================================ FILE: docs/Doc 3 — Technical Platform & Release Policy.md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 70a65613deda315434fad00eefa6c55816873c6a5a7cae823416c8efca207e3e CONTENT_BYTES: 13349 ================================================================================================ # **Doc 3A — Tech Platform & Determinism (Updated)** ## **1\) Purpose & scope** Defines the **execution environment**, **determinism guarantees**, and **build/runtime constraints** for the engine and renderer. Normative where it affects reproducibility. Integrates prior addenda so no separate platform addendum is needed. Outputs from identical inputs \+ ParameterSet (incl. seeds) MUST be **byte-identical** across OS/arch. --- ## **2\) Determinism targets (normative)** * **Offline, pure computation**: no network, no nondeterministic external calls. * **Locale-neutral**: behavior MUST NOT depend on OS locale/timezone. * **Time-agnostic**: wall-clock/timezone MUST NOT affect any computed field (timestamps are metadata only, set in UTC). * **Canonical JSON** and hashing as per Doc 1A §2.1–2.2. * **Stable ordering**: all algorithmic arrays obey Doc 1A §5 (never rely on input or map iteration order). --- ## **3\) Runtime environment constraints** * **Process I/O** * Inputs: file paths to **DivisionRegistry**, **BallotTally**, **ParameterSet**. * Outputs: `result.json`, `run_record.json`, optional `frontier_map.json` (Doc 1A §2.2 / §4). * No temp artifacts may influence output content; temp files are optional and ignored for hashing. * **Filesystem** * Treat paths case-sensitively internally. * Normalize line endings to **LF** for all emitted JSON. * **Concurrency** * Parallelism permitted, but **observable order** MUST match Doc 1A §5. * Reductions/aggregations MUST be order-stable (e.g., sort before fold; avoid nondeterministic hash-map iteration). * No data races that could change floating-point summation order. * **Numeric model** * IEEE-754 semantics. Use deterministic rounding paths; avoid hardware/BLAS paths with nondeterministic reduction. * Percentages & shares formatting controlled by reporting rules (Doc 7). Internal precision is engine-defined but MUST be stable across builds. --- ## **4\) RNG profile for ties (normative)** * **Controls**: `VM-VAR-050 tie_policy`, `VM-VAR-052 tie_seed` (051 reserved). * **Seeding**: Initialize the run’s RNG with **exactly** `VM-VAR-052` (integer ≥ 0). * **Usage**: Consume draws **only** when `tie_policy="random"` and a tie event actually requires resolution. * **Event recording**: Each random tie creates a `RunRecord.ties[]` entry; `RunRecord.determinism.rng_seed` is present iff any random tie occurred (Doc 1A §4.5). * **Reproducibility**: The RNG algorithm/profile is fixed by **Annex B (`rng_profile.json`)** to ensure identical sequences across languages/platforms. Deterministic and deterministic\_order paths MUST NOT consult RNG. --- ## **5\) CLI contract & exit codes** * **CLI** * `vm_cli --registry path --tally path --params path --out dir [--seed N overrides VM-VAR-052]` * MUST refuse unknown flags; MUST error if inputs are missing/invalid. * **Exit codes** * `0` success (all artifacts emitted & hashes verified) * `2` validation error (Doc 1B domains/refs/order) * `3` hash/FID mismatch on self-verify * `4` runtime error (I/O, parse) * `5` spec violation (ordering, determinism, disallowed features) --- ## **6\) Build & release reproducibility (engine)** * **Dependency pinning**: compiler/toolchain and libs MUST be version-pinned (lockfiles or exact versions). * **Reproducible builds**: remove timestamps from binaries where possible; record `engine.build` metadata (e.g., VCS commit) in **RunRecord.engine**. * **Hermeticity**: no optional system-wide plugins that can alter numeric behavior; all runtime feature flags must be explicit. * **Verification**: a release MUST pass the full Doc 6 canonical test pack on all supported platforms before tagging (see Doc 3B for tag policy). --- ## **7\) Hashing, FID & manifest linkage** * **SHA-256** for `result_id`, `run_id`, `frontier_id`, and input digests (Doc 1A §2.2, §4.5). * **FID scope**: only outcome-affecting rules & variables (see **Annex A — Included**). Presentation/report toggles (e.g., **VM-VAR-060..062**) are **excluded** from FID. * **RunRecord.nm\_digest**: MUST include `nm_sha256` over the Normative Manifest used to compute FID, enabling independent recomputation. --- ## **8\) Logging & integrity checks** * **Self-verify**: after emitting each artifact, recompute its sha256 and compare to the embedded ID; fail with code `3` on mismatch. * **Determinism log** (optional JSON): MAY include timing and thread counts, but MUST NOT influence artifacts. * **No network**: engine MUST refuse network I/O unless explicitly running in a non-deterministic debug mode (not for official runs). --- ## **9\) Security & trust boundaries** * Treat all inputs as untrusted: validate schema (Doc 1B) before use. * Sandboxed execution recommended for public data runs. * No code-loading from inputs; ParameterSet and Registry are data only. --- ## **10\) Renderer constraints (Doc 7 interplay)** * Renderer MUST consume **Result** and **RunRecord** only; it MUST NOT re-compute allocations. * Renderer MAY use **FrontierMap** when present. * Section ordering and visibility controlled by **Doc 2B (032–035)**; does **not** affect canonical JSON or FID. --- ## **11\) Conformance checklist** * **C-PLAT-01**: No network calls during official runs. * **C-PLAT-02**: Canonical JSON (UTF-8, LF, sorted keys) for all artifacts. * **C-PLAT-03**: Ordering contract satisfied regardless of parallelism. * **C-PLAT-04**: RNG seeded **only** from `VM-VAR-052`; identical sequences on all supported platforms. * **C-PLAT-05**: Self-verification passes (`result_id`, `run_id`, `frontier_id`, input digests). * **C-PLAT-06**: FID recomputation matches `Result.formula_id` and `RunRecord.formula_id`. --- ## **12\) Minimal example (CLI → artifacts)** vm\_cli \--registry reg.json \--tally tally.json \--params params.json \--out ./run01 \# Emits: \# ./run01/result.json \# ./run01/run\_record.json \# ./run01/frontier\_map.json (only if VM-VAR-034=true and feature used) \# run\_record.json contains: \# engine { vendor, name, version, build } \# inputs { \*\_sha256 } \# nm\_digest { nm\_sha256 } \# determinism { tie\_policy, rng\_seed? } \# ties \[ ... \] // if any random tie occurred *End Doc 3A.* # **Doc 3B — Build & Release Policy (Updated)** ## **1\) Purpose & scope** Defines how we **version**, **tag**, **verify**, and **publish** the engine and renderer so runs are reproducible and auditable. Integrates all former addendum content—no separate addendum is needed. This part is **normative** wherever it governs FID/Engine versioning and release gates. --- ## **2\) Versioning model (two tracks)** * **Formula ID (FID)** — **64-hex** digest of the **Normative Manifest** (rules \+ outcome-affecting defaults). * Printed in `Result.formula_id` and `RunRecord.formula_id`. * Changes **only** when outcome logic or outcome-affecting defaults change. * **Engine Version** — semantic version **vMAJOR.MINOR.PATCH** of the implementation. * Printed in `Result.engine_version` and `RunRecord.engine.version`. * Changes for code changes (including non-normative), build/tooling, or packaging. The **Normative Manifest** content and canonicalization are defined in Doc 1A \+ Annex A. Presentation/report toggles (e.g., **VM-VAR-060..062**) are **excluded** from FID. --- ## **3\) What requires a new FID (and Engine Version)** Any change that can change outcomes across any valid input set: 1. **Algorithmic rules** * Step order, allocation/gate semantics, tie-resolution logic, rounding/denominator rules. 2. **Outcome-affecting VM-VAR set** * Adding/removing a variable in the **Included** list (Annex A). * Changing a default, domain/range, or enumerated value semantics of an **Included** variable. 3. **Advanced/frontier semantics** * Behavior of **040–048**, **045–046**, **029–031**, **073** that alters gating/eligibility/frontier results. 4. **Determinism primitives** * Changing the deterministic tie key (must remain `Option.order_index`). * RNG profile/sequence for ties (when policy \= `random`). 5. **Canonicalization rules** (Doc 1A §2.1) * JSON formatting, key sorting, array ordering, or hash inputs. **Release action:** * Compute a **new FID**, **bump Engine Version** (see §5), update Annex A, and regenerate all golden fixtures (Doc 6). * Update Doc 7 footer rules if display or disclosure changes. --- ## **4\) What does not change the FID (Engine Version only)** * **Performance** improvements; memory usage; parallelization refactors (ordering preserved). * **I/O/CLI UX** changes; logging; error messages; packaging; build toolchain updates. * **Renderer** changes that affect **only presentation** (layout, language selection, section visibility). * Changing **presentation/report variables** (**032–035**, **060–062**) or their defaults (they remain outside FID). * Bug fixes that **do not** alter any computed outcome (verified by the Doc 6 test pack). **Release action:** * **Bump Engine Version** only. No FID change. If a “bug fix” alters any outcome on any supported test, it is **normative** ⇒ **new FID** (and Engine Version). --- ## **5\) Engine Version bump rules (semver)** * **MAJOR**: removal/incompatible behavior in CLI or artifacts; support matrix change; or any normative change shipping **with** new FID. * **MINOR**: new non-breaking features; CLI flags added; report appendices added. * **PATCH**: bug fixes; internal refactors; performance improvements. **Tag example:** `engine/v1.4.2` **Build metadata** recorded in `RunRecord.engine.build` (e.g., `commit:abcd1234`). --- ## **6\) Release gates (must pass before tagging)** 1. **Determinism checks** * Canonical JSON conformance (Doc 1A §2.1). * Cross-OS/arch byte-identical artifacts on the official matrix. 2. **Test pack** (Doc 6\) * All **A/B/C** suites pass; hashes and expected `Result` match exactly. * Random-tie tests repeatability with fixed `VM-VAR-052`. 3. **FID audit** * Independent recomputation of FID from the Normative Manifest equals `Result.formula_id`. 4. **Security/IO policy** * No network I/O; sandboxed run OK. * Inputs validated (Doc 1B); self-hash verification passes. 5. **Annex A alignment** * Included/Excluded lists, domains, and defaults match the code. * Any new VM-VAR IDs registered and documented. Only after all gates pass may the release be tagged and published. --- ## **7\) Publication requirements** **Artifacts to publish per release:** * **Binaries/containers** (pinned toolchain). * **Spec bundle**: Docs 1–7 \+ Annex A/B/C at the release tag. * **Canonical Test Pack** (Annex B): machine-readable fixtures (inputs, expected outputs, hashes). * **Change log**: human-readable summary (see §8 template). * **Provenance**: checksums/signatures for binaries and spec bundle. **Runtime disclosure (renderer/report footer):** * Show **Formula ID (64-hex)**, **Engine Version**, and (if any) `algorithm_variant` (VM-VAR-073). * If any **2B toggles** differ from Annex A defaults, append a **“Non-normative toggles”** note listing key/value pairs. --- ## **8\) Change log template (per release)** Release: engine vX.Y.Z | Formula ID: \<64hex\> (if changed) Date (UTC): YYYY-MM-DD Normative changes (FID): \- \ \[Doc/Section; VM-VAR impact\] \- \ Non-normative changes: \- \ \[perf/UX/build\] Spec & Annex updates: \- Annex A: \ \- Doc 6: \ --- ## **9\) Forks & reproducibility** * Forks MUST set `RunRecord.engine.vendor` and SHOULD rename `engine.name`. * Forks **must** preserve Doc 1A canonicalization, Doc 1A §5 ordering, RNG profile for ties, and Annex A Included/Excluded unless they intentionally create a **new FID**. * Public results SHOULD include the spec bundle commit or URL for independent verification. --- ## **10\) Hotfix protocol** * **PATCH** hotfixes are allowed **only** if Doc 6 passes with **no** output diffs; otherwise it is normative ⇒ new FID and at least **MINOR** bump. * Re-run release gates (§6); republish hashes. --- ## **11\) Deprecation policy (IDs & flags)** * **VM-VAR IDs are stable.** Do not renumber or repurpose. * To retire a variable: mark **Deprecated** in Annex A with a sunset version; keep behavior until the next **MAJOR**. * **VM-VAR-051** remains **reserved** (tie deterministic key is always `order_index`, not a variable). --- ## **12\) CLI compatibility** * New flags require at least **MINOR** bump. * Removing/renaming flags requires **MAJOR**. * `--seed` MAY override `VM-VAR-052` at runtime; this does **not** alter FID (seed is non-FID) but must be echoed in `RunRecord.determinism.rng_seed`. --- ## **13\) Compliance checklist** * **C-REL-FID**: Any outcome change ⇒ new FID; Engine Version bumped. * **C-REL-SEMVER**: Changes categorized per §5. * **C-REL-GATES**: All §6 gates pass on matrix. * **C-REL-PUB**: Required artifacts & checksums published; footer disclosures correct. * **C-REL-ANNEX**: Annex A is the single source of truth for Included/Excluded and domains; bundled with the release. *End Doc 3B.* ================================================================================================ FILE: docs/Doc 4 — Algorithm Specification (Steps, Allocation, Gates & Edge Cases).md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: a6ddb363639ea9864da29a1a2f17682a219365c875de2a7336eeeffb05a5aadc CONTENT_BYTES: 23626 ================================================================================================ # **Doc 4A — Algorithm: Step Order, Tabulation & Global Flow (Updated, Normative)** ## **1\) Purpose & scope** Defines the **end-to-end step order** and tabulation flow the engine MUST follow to produce deterministic, byte-identical results. 4A fixes *when* each rule applies; 4B covers **gates & edge cases**; 4C covers **Frontier, Ties, and Labels**. No legacy numbering. **Inputs:** `DivisionRegistry`, `BallotTally`, `ParameterSet` **Outputs:** `Result`, `RunRecord`, optional `FrontierMap` **Determinism primitives:** Doc 1A §5 (ordering), VM-VARs per Doc 2/Annex A --- ## **2\) Preconditions (must hold before counting)** 1. **Schema/refs valid** (Doc 1B). 2. **ParameterSet** includes all outcome-affecting VM-VARs listed “Included” in Annex A. 3. **Order keys ready:** each Registry unit has unique `option.order_index` (Doc 1B). 4. **Run scope fixed:** apply **VM-VAR-021** to derive the working set of units (default: `all_units`). Record in `RunRecord.summary` if filtered. --- ## **3\) Step order (canonical pipeline)** ### **S0. Normalize & seed (determinism)** * Canonicalize inputs (Doc 1A §2.1); compute input digests for `RunRecord.inputs`. * Bind **Algorithm family & rounding** constants (**VM-VAR-001…007**) and optional **algorithm\_variant** (**VM-VAR-073**). * Initialize RNG **only** if needed later: store **VM-VAR-052** (no draws yet). ### **S1. Per-unit tallies** For each included `unit_id` (iterate in ascending `unit_id`): 1. Load `valid_ballots`, `invalid_ballots`, and per-option `votes`. 2. Compute raw shares (engine precision policy; stable across builds). 3. Compute any base metrics required by 4B/4C (e.g., margins, turnout). ### **S2. Eligibility & validity gates (4B)** Apply gates in a fixed order using **VM-VAR-010…017**, **020…029**, and advanced **029–031** where present: * If a gate marks the unit **invalid**, branch as defined in 4B (result label `Invalid`, allocations empty or per family rule). * Record reasons in `RunRecord.summary`/notes as required by 4B. ### **S3. Frontier model hook (4C)** If **VM-VAR-040** enables Frontier: * Select band/cut params via **041**; apply strategy via **042**. * Optionally refine by **047–049** (advanced). * Emit per-unit diagnostics into `FrontierMap` (if **VM-VAR-034=true**), using `band_met` etc. * Frontier never violates canonical ordering. ### **S4. Core allocation** Using the algorithm family constants **001…007** (and **073** if defined): * Compute per-unit **allocations\[\]** deterministically. * Respect Registry option order (`order_index`) for any rank-sensitive operation. * No randomization at this stage. ### **S5. Tie resolution (4C)** If a tie affects an allocation/ordering decision: * Read **VM-VAR-050 tie\_policy**: * `status_quo`: apply family’s status-quo rule. * `deterministic_order`: break ties by ascending `option.order_index` (no variable; **051 reserved**). * `random`: use deterministic RNG seeded with **VM-VAR-052**; log each event in `RunRecord.ties[]` and set `RunRecord.determinism.rng_seed`. * Never consume RNG draws unless `tie_policy=random` **and** a tie actually occurs. ### **S6. National/aggregate metrics & labels (4C/7)** * Aggregate required national metrics (e.g., national margin). * Compute **Outcome label** per policy: * Threshold **VM-VAR-060** and policy **VM-VAR-061** (“fixed” vs “dynamic\_margin”) influence labeling **only** (presentation). * Labels do not affect allocations; they are excluded from FID. ### **S7. Emit artifacts (Doc 1A)** * Build `Result` (units ordered by `unit_id`; allocations per `order_index`). * Build `RunRecord` (engine info, nm\_digest, vars\_effective, tie log). * Optionally build `FrontierMap` (if enabled and applicable). * Canonicalize JSON and compute IDs (`result_id`, `run_id`, `frontier_id`). * Set `formula_id` from the Normative Manifest (Doc 1A/Annex A). * Self-verify hashes; fail if any mismatch (Doc 3A/3B gates). --- ## **4\) Deterministic ordering (reiterated for algorithm use)** * **Units:** iterate strictly in ascending `unit_id`. * **Options within a unit:** ascending `order_index`; on equal, ascending `option_id`. * **Allocations arrays:** mirror Registry option order. * **No iteration over map/dict order** may influence results. --- ## **5\) Variable touchpoints used in 4A** * **Global & scope:** **001…007**, **021**, **073** * **Gates/thresholds:** **010…017**, **020…029**, **030–031** (if set) * **Frontier (hook only; details in 4C):** **040–042**, **047–049** * **Ties (delegated to 4C):** **050 (policy)**, **052 (seed), 051 reserved** * **Presentation (labels only):** **060–062** (do not alter counts; excluded from FID) --- ## **6\) Pseudocode (normative skeleton)** init\_context(params, registry, tally): assert validate\_all() scope\_units \= select\_units(registry.units, VM\_VAR\_021) bind\_family(VM\_VAR\_001..007, VM\_VAR\_073) rng\_seed \= VM\_VAR\_052 for unit in sort\_by\_unit\_id(scope\_units): u \= prepare\_unit(unit, tally\[unit\]) apply\_gates(u, VM\_VAR\_010..017, VM\_VAR\_020..029, VM\_VAR\_030..031) // 4B if u.invalid: result.units.append(invalid\_record(u)) continue frontier\_ctx \= frontier\_hook(u, VM\_VAR\_040, VM\_VAR\_041, VM\_VAR\_042, VM\_VAR\_047..049) // 4C allocations \= compute\_allocations(u, family\_consts) // deterministic if has\_tie(allocations): allocations \= resolve\_ties(allocations, VM\_VAR\_050, rng\_seed) // 4C; uses 052 only if random label \= compute\_label(u, allocations, VM\_VAR\_060, VM\_VAR\_061) // presentation only emit\_unit\_result(u.unit\_id, allocations, label, frontier\_ctx) finalize\_and\_emit(Result, RunRecord, FrontierMap) // Doc 1A --- ## **7\) Conformance checklist (4A)** * **C-4A-ORDER:** All loops honor Doc 1A ordering; no nondeterministic iteration affects results. * **C-4A-GATES:** Gates applied before allocation, in fixed order, with recorded reasons when invalid. * **C-4A-TIES:** Ties handled strictly per **VM-VAR-050**; RNG used only when required, with events logged. * **C-4A-FRONTIER:** Frontier hook executes when enabled; diagnostics emitted only if **VM-VAR-034=true**. * **C-4A-LABELS:** Labels computed per **060/061**; allocations unaffected. * **C-4A-EMIT:** Artifacts canonicalized; IDs verified; FID matches Normative Manifest. *End Doc 4A.* # **Doc 4B — Gates & Edge Cases (Updated, Normative)** ## **1\) Purpose & scope** Defines **when a unit is valid/invalid** for allocation and how **edge cases** are handled, in a **fixed, deterministic order**. Variables come from **Doc 2A/2C**; exact domains/defaults live in **Annex A**. No legacy numbering. * Gate families (outcome-affecting; **FID \= YES**): **VM-VAR-010…017**, **020…029**, **030–031**. * Interplay with other parts: Frontier hook (4C), Ties (4C), Labels (4C/Doc 7), Protected/Autonomy (2A §4.4). Outputs must be **byte-identical** across OS/arch when inputs \+ ParameterSet match. --- ## **2\) Evaluation order (canonical)** Gates execute **before allocation** (4A S2) in the following fixed order. The first failing stage **does not short-circuit**; record **all** reasons, then branch as defined in §3.1. 1. **Sanity gates** (data plausibility) — uses 010…017 group if defined for sanity. 2. **Eligibility gates** (thresholds & scope) — uses 020…029, 021, 029\. 3. **Validity gates** (integrity floors & overrides) — uses 030–031, 045\. 4. **Frontier pre-check** (if enabled) — consistency with 040–042, 047–049 (4C). Deterministic ordering matters: implementations MUST follow this stage order and, within a stage, evaluate gates in ascending **VM-VAR** ID order. --- ## **3\) Gate behavior (normative patterns)** ### **3.1 Branching rule** * If **any** gate fails for a unit → mark **`unit.invalid=true`** and **do not allocate** in S4. * Emit a **unit result** with: * `allocations`: **empty array** * `label`: `"Invalid"` (Doc 7 will render accordingly) * Optional diagnostic fields in `RunRecord.summary` (see §6) No other branch (e.g., “provisional allocation”) is allowed in v1. ### **3.2 Sanity gates (010…017)** Deterministic checks on tallies and basic ratios (exact set per Annex A). Examples of required behavior (independent of names): * **Non-negativity**: votes/ballots cannot be negative. * **Consistency**: `sum(option.votes) ≤ totals.valid_ballots`. * **Bounds**: any declared percentage thresholds must lie within their domain. **Failure →** record reason(s); continue evaluating remaining gates; final branch per §3.1. ### **3.3 Eligibility gates (020…029, plus scope 021\)** Apply **run scope** (**VM-VAR-021**) first to pick included units (4A S2 precondition). Within an included unit, evaluate thresholds in ascending ID order. Required behavior patterns: * **Minimum participation/turnout** gate(s). * **Minimum share/eligibility** gate(s) for options or unit-level continuation. * **Symmetry exceptions** (**VM-VAR-029**): an explicit, deterministic allow/deny list that **narrowly** overrides a corresponding eligibility rule (never the sanity/validity gates). Matching is deterministic (Annex A defines the selector grammar). **Failure →** record reason(s); final branch per §3.1. ### **3.4 Validity gates (030–031) & overrides** * **Eligibility override list** (**VM-VAR-030**): explicit `{unit_id, mode}` directives applied **before** integrity floors. `mode=include` can re-include a unit that would be excluded by **eligibility** gates; it **cannot** override **sanity** failures. * **Ballot integrity floor** (**VM-VAR-031**): if a unit’s integrity KPI falls **below** the floor, mark invalid. * **Protected-area override** (**VM-VAR-045**, from 2A): when `DivisionRegistry.units[].protected_area=true`, behavior is: * If **045 \= deny** (default): protected status does **not** bypass validity; treat like any unit. * If **045 \= allow**: a protected unit may **bypass an eligibility gate** (020…029) but **never** a sanity failure (010…017) nor the integrity floor (031). All bypasses must be recorded (see §6). **Failure →** record reason(s); final branch per §3.1. ### **3.5 Frontier pre-check (040–042, 047–049)** If Frontier is enabled (4C S3), confirm that required inputs/metrics exist for the unit and that advanced tuning (047–049) is within bounds. Frontier logic itself runs in 4C; this pre-check only detects **configuration errors** (treated as validity failures). --- ## **4\) Edge cases (normative handling)** * **Zero valid ballots**: * Sanity passes (non-negative); eligibility typically fails (share/turnout). * Result: `allocations=[]`, `label="Invalid"`, reasons include the failing gate(s). * **Sum of votes \< valid\_ballots**: Allowed (abstentions/blank). Sanity passes; other gates decide. * **Missing option tallies**: Missing `option_id` entries are treated as **0 votes** only if **explicitly permitted** by Annex A; otherwise it’s a **sanity failure**. * **All options tied with zero**: Not a gate failure. If unit remains valid, allocation yields all zeros; 4C ties do **not** trigger because no rank decision is required. * **Protected area without override**: Protected flag alone has **no effect** unless **045=allow**. Never bypass sanity/integrity. * **Conflicting directives** (e.g., 029 vs 030): Precedence is fixed — **030 (eligibility override) → 029 (symmetry exceptions)**. Implementations must document the applied precedence in `RunRecord.summary`. * **Frontier inputs missing** when Frontier enabled: validity failure with reason “frontier\_missing\_inputs”. --- ## **5\) Deterministic order of recording reasons** When multiple reasons exist, record them in **ascending VM-VAR ID order**, then any symbolic reasons (e.g., `frontier_missing_inputs`) in lexicographic order. This guarantees byte-identical `RunRecord.summary` across platforms. --- ## **6\) RunRecord requirements (per-unit)** For each unit evaluated: { "unit\_id": "U-001", "gate\_status": "valid" | "invalid", "reasons": \["VM-VAR-020:min\_turnout", "VM-VAR-031:integrity\_floor"\], // ordered, see §5 "protected\_bypass": true | false, // present only if 045 allowed a bypass "applied\_exceptions": \["VM-VAR-029:U-001"\], // if any selector matched "frontier\_ready": true | false // pre-check result if Frontier enabled } * `reasons[]` lists **all** failing gates (or empty if none). * `protected_bypass=true` appears **only** if **045=allow** caused an eligibility bypass. * `applied_exceptions[]` lists matched 029 selectors (deterministic string form per Annex A). * This structure may live under `RunRecord.summary.units[]` (producer’s choice), but ordering rules apply (Doc 1A §5). --- ## **7\) Conformance checklist (4B)** * **C-4B-ORDER**: Gates evaluated in stage order **Sanity → Eligibility → Validity → Frontier pre-check**, ascending ID within stage. * **C-4B-BRANCH**: Any failure ⇒ `allocations=[]`, `label="Invalid"`. No silent partial allocations. * **C-4B-PROT**: `protected_area` may bypass **eligibility** only when **045=allow**; never bypasses Sanity or Integrity Floor (031). * **C-4B-EXC**: 030 overrides applied before 029 and recorded. * **C-4B-RR**: All reasons and applied exceptions recorded deterministically (ordered as in §5). * **C-4B-FRONTIER**: Frontier pre-check failures recorded; 4C logic not executed for invalid units. --- ## **8\) Pseudocode (reference)** reasons \= \[\] valid \= true // Sanity (010..017) for v in sort\_ids(010..017): if \!check\_sanity(v, unit, tally): reasons.append(reason(v)); valid \= false // Eligibility scope if \!in\_scope(unit, VM\_VAR\_021): reasons.append("VM-VAR-021:out\_of\_scope"); valid \= false // Eligibility (020..029) for v in sort\_ids(020..029): if \!check\_eligibility(v, unit, tally): if protected(unit) && VM\_VAR\_045 \== "allow" && is\_eligibility\_gate(v): record\_bypass(v); // no reason added else: reasons.append(reason(v)); valid \= false // Overrides & validity (030..031) apply\_overrides(VM\_VAR\_030, unit, reasons) // may flip prior eligibility failure, not sanity if \!check\_integrity\_floor(VM\_VAR\_031, unit): reasons.append(reason(031)); valid \= false // Frontier pre-check if enabled if frontier\_enabled(VM\_VAR\_040): if \!frontier\_ready(unit): reasons.append("frontier\_missing\_inputs"); valid \= false if \!valid: emit\_invalid\_unit(unit\_id, reasons, protected\_bypass, applied\_exceptions) else: proceed\_to\_allocation() *End Doc 4B.* # **Doc 4C — Frontier, Ties & Labels (Updated, Normative)** ## **1\) Purpose & scope** Defines the **frontier model**, **tie resolution**, and **outcome labeling** used by the engine. Frontier and ties are **outcome-affecting** (⇒ included in FID via Doc 2A/2C & Annex A); labels/language are **presentation-only** (⇒ excluded from FID per Doc 1A). **Inputs:** `DivisionRegistry`, `BallotTally`, `ParameterSet` **Consumes VM-VARs:** Frontier **040–042**, advanced **047–049**; Ties **050 (policy)**, **052 (seed)**; Labels **060–062** (presentation) **Emits:** `Result`, `RunRecord`, optional `FrontierMap` (diagnostics) --- ## **2\) Frontier model (outcome-affecting)** ### **2.1 Enablement & selection** * **VM-VAR-040 frontier\_mode** — selects the frontier model (e.g., `none`, `banded`, `ladder`). * **VM-VAR-041 frontier\_band/cut** — primary numeric or enumerated cut parameter(s). * **VM-VAR-042 frontier\_strategy** — how/when the frontier applies (e.g., `apply_on_entry`, `apply_on_exit`, `sticky`). Advanced refinements (still outcome-affecting): * **VM-VAR-047 frontier\_band\_window** — expands/contracts effective band around 041\. * **VM-VAR-048 frontier\_backoff\_policy** — resolves borderline cases (`none`/`soften`/`harden`). * **VM-VAR-049 frontier\_strictness** — coarse multiplier for 047/048 effects. ### **2.2 Deterministic evaluation** For each included unit (Doc 4A S3), compute frontier predicates **before** allocation in a deterministic order: 1. Derive required metrics from `BallotTally` (and any prior stage outputs). 2. Apply **040/041/042** exactly; apply **047–049** per Annex A precedence (047 window → 048 backoff → 049 strictness). 3. Produce a boolean **`band_met`** and optional numeric **`band_value`** used by the algorithm to gate/branch. Rules: * If `frontier_mode = none`, skip all frontier logic (no gating by frontier). * Frontier must **not** mutate array ordering (Doc 1A §5). * If configuration is invalid (missing metrics/out-of-domain value), treat as a **4B validity failure** (unit becomes `Invalid`). ### **2.3 Diagnostics (FrontierMap)** If **VM-VAR-034 \= true** and frontier is enabled: Emit `frontier_map.json` with, for each evaluated unit: { "unit\_id": "...", "band\_met": true|false, "band\_value": \, "notes": "..." } * * Arrays ordered per Doc 1A §5. Field name is **`band_met`** (normalized). * Presence/absence of `frontier_map.json` does **not** affect outcomes. --- ## **3\) Tie resolution (outcome-affecting)** ### **3.1 Controls** * **VM-VAR-050 tie\_policy** ∈ `{ status_quo, deterministic_order, random }`. * **VM-VAR-051** is **reserved** (no variable exists for deterministic order key). * **VM-VAR-052 tie\_seed** ∈ integers ≥ 0; used **only** if `tie_policy = random`. ### **3.2 Where ties apply** Any stage where a **relative order** among options affects allocation or ranking (post-frontier, pre-emit), including: * Winner/seat assignment ties. * Rank ordering ties that drive subsequent algorithm branches. ### **3.3 Deterministic procedures** * **status\_quo** — Apply the family’s fixed rule (e.g., keep prior holder). Must not rely on input file order; any “prior holder” notion must be derived from explicit, deterministic data. * **deterministic\_order** — Break ties by ascending `Option.order_index`; if equal, ascending `option_id`. No variable controls this; **051 remains unused**. * **random** — Use a deterministic RNG seeded with **052**: * For a tie among **k** options, generate a **deterministic permutation** of the tied set: 1. For each tied `option_id`, draw one uniform 64-bit value from the run RNG. 2. Sort the tied options by `(draw_value, option_id)` ascending to get a stable random order. * Consume **exactly k draws** per tie event. Do not draw when no tie exists. * Record an entry in `RunRecord.ties[]` with `unit_id`, tie type (e.g., `winner_tie`/`rank_tie`), `policy="random"`. Set `RunRecord.determinism.rng_seed = VM-VAR-052` iff at least one random tie occurred. Constraints: * RNG algorithm/profile is fixed in Annex B to produce **identical sequences** across platforms. * Ties **never** read presentation VM-VARs. * Random tie resolution must not leak into any ordering beyond the tied subset. --- ## **4\) Outcome labels (presentation-only)** ### **4.1 Controls** * **VM-VAR-060 majority\_label\_threshold** — integer percent (0..100). * **VM-VAR-061 decisiveness\_label\_policy** ∈ `{ fixed, dynamic_margin }`. * **VM-VAR-062 unit\_display\_language** — `auto` or IETF tag (used by renderer; see Doc 7). ### **4.2 Label computation** Compute per-unit label **after** allocation and tie resolution, without altering allocations: * **fixed** policy: * If `national_or_unit_margin ≥ 060` ⇒ `"Decisive"`, else `"Marginal"` (unless the unit is invalid ⇒ `"Invalid"`). * **dynamic\_margin** policy (default): * `"Decisive"` iff `margin ≥ 060` **and** no **blocking flags** are set. * `"Marginal"` if `margin < 060` **or** any blocking flag is set. * Blocking flags are deterministic boolean signals produced elsewhere in the algorithm (e.g., mediation in effect, protected override used). Their exact sources are defined in Docs 4A/4B and Annex A; labels **only** read those booleans. Notes: * Labels and language are **excluded from FID** (Doc 1A). * Renderer obeys Doc 7 visual rules; language selection via **062** does not change JSON ordering/content. --- ## **5\) RunRecord requirements (4C-specific)** * **Frontier**: if enabled, record at least `{ unit_id, frontier_applied: true|false }` per unit in `RunRecord.summary` or equivalent; implementations may also copy `band_met`/`band_value` summary stats. **Ties**: maintain `RunRecord.ties[]` entries in the canonical order of unit evaluation (ascending `unit_id`), each with: { "unit\_id":"...", "type":"winner\_tie|rank\_tie|other", "policy":"status\_quo|deterministic\_order|random" } * Include `"seed": ` only when `policy="random"`. * **Determinism**: `RunRecord.determinism.tie_policy` mirrors **050**; `rng_seed` present iff any random tie event occurred. --- ## **6\) Ordering & determinism (reiterated)** * Evaluate frontier and ties **after** gates (4B) and **before** emit (4A S7). * Never depend on map/dict iteration order; always use Doc 1A §5 canonical ordering. * In random ties, consume **exactly k** RNG draws for a **k-way** tie and **no draws otherwise**. --- ## **7\) Conformance checklist (4C)** * **C-4C-FR-CFG**: Frontier parameters (040–042, 047–049) in domain; invalid config ⇒ validity failure (4B), not undefined behavior. * **C-4C-FR-DET**: Frontier decisions are deterministic for a given ParameterSet; `FrontierMap` (if emitted) matches those decisions. * **C-4C-TIE-POL**: Tie resolution strictly follows **050**; `deterministic_order` uses `order_index`; **051 is unused**. * **C-4C-TIE-RNG**: RNG seeded only from **052**; exactly **k** draws per k-way tie; events logged; seed echoed iff any random tie. * **C-4C-LBL-PRES**: Labels computed per **060/061** and do not affect allocations or FID. * **C-4C-ORDER**: Unit and allocation arrays retain canonical order after ties/frontier. --- ## **8\) Reference pseudocode** // Frontier if VM\_VAR\_040 \!= "none": fm \= compute\_frontier\_metrics(unit, tally) frontier \= apply\_frontier(VM\_VAR\_040, VM\_VAR\_041, VM\_VAR\_042, VM\_VAR\_047..049, fm) if VM\_VAR\_034: record\_frontier\_map(unit\_id, frontier.band\_met, frontier.band\_value) // Allocation already computed (4A S4) // Ties if has\_tie(allocations): switch VM\_VAR\_050: case "status\_quo": allocations \= apply\_status\_quo(allocations) case "deterministic\_order": allocations \= sort\_by(order\_index, option\_id, within\_tied\_groups(allocations)) case "random": draws \= {} for opt in tied\_group(allocations): draws\[opt\] \= rng\_next64() // seeded once at run start from VM\_VAR\_052 allocations \= sort\_tied\_by(draws\[opt\], option\_id) RunRecord.ties.append({unit\_id, type, policy:"random", seed: VM\_VAR\_052}) // Labels (presentation) if unit\_invalid: label \= "Invalid" else: margin \= compute\_margin(unit, allocations) if VM\_VAR\_061 \== "fixed": label \= (margin \>= VM\_VAR\_060) ? "Decisive" : "Marginal" else: flags \= read\_blocking\_flags(unit) // deterministic booleans from earlier stages label \= (margin \>= VM\_VAR\_060 && \!flags.any) ? "Decisive" : "Marginal" emit\_unit\_label(unit\_id, label) *End Doc 4C.* ================================================================================================ FILE: docs/Doc 5 — Processing Pipeline Specification (State Machine & Functions).md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 708baf42eb7fcbd29b0395eb54a5c06526b4de1bf424d8b6054326ed0cfbc664 CONTENT_BYTES: 25745 ================================================================================================ # **Doc 5A — Pipeline: State Machine & Data Exchange (Updated, Normative)** ## **1\) Purpose & scope** Defines the **canonical run pipeline**, its **states**, **transitions**, and the **data exchanged** between stages. This is the engine’s single source of truth for execution order and I/O. Normative wherever it affects reproducibility. Inputs: `DivisionRegistry`, `BallotTally`, `ParameterSet` Outputs: `Result`, `RunRecord`, optional `FrontierMap` Ordering, canonical JSON, RNG, and FID rules: see Docs **1A–1B–3A–3B**, algorithm details in **4A–4C**, variables in **2A–2C**. --- ## **2\) State machine (canonical)** ### **2.1 States & transitions** S0 INIT & LOAD └─\> S1 VALIDATE ├─(fail)-\> E\_VALIDATE └─\> S2 MANIFEST & SEED └─\> S3 PER-UNIT LOOP ├─\> S3.1 GATES (4B) │ ├─invalid→ S3.4 EMIT-UNIT-INVALID │ └─valid→ S3.2 FRONTIER HOOK (4C) │ └─\> S3.3 ALLOCATE (4A) │ ├─tie?→ S3.3a TIES (4C) │ └─\> S3.4 EMIT-UNIT └─(all units done)→ S4 AGGREGATE & LABELS (4C/7) └─\> S5 BUILD ARTIFACTS └─\> S6 SELF-VERIFY ├─(fail)-\> E\_VERIFY └─\> S7 DONE ### **2.2 Stage purposes** * **S0 INIT & LOAD** — Open/read three inputs; normalize to in-memory canonical forms. * **S1 VALIDATE** — Enforce Doc 1B schemas, referential integrity, and ordering preconditions. * **S2 MANIFEST & SEED** — Build **Normative Manifest**, compute **FID**, capture `nm_digest`; stash `VM-VAR-052` (no RNG draws yet). * **S3 PER-UNIT LOOP** — Deterministic iteration over units (ascending `unit_id`): * **S3.1 GATES** (Doc 4B) — sanity → eligibility → validity → frontier pre-check. * **S3.2 FRONTIER HOOK** (Doc 4C) — evaluate 040–042 (+047–049) if enabled. * **S3.3 ALLOCATE** (Doc 4A) — compute allocations; if tie, go to **S3.3a TIES** (Doc 4C with 050/052). * **S3.4 EMIT-UNIT** — append per-unit result record; optional frontier diagnostics. * **S4 AGGREGATE & LABELS** — compute national/aggregate metrics; compute labels with 060/061 (presentation-only). * **S5 BUILD ARTIFACTS** — assemble canonical `Result`, `RunRecord`, optional `FrontierMap`; set IDs and `formula_id`. * **S6 SELF-VERIFY** — recompute hashes/IDs; fail if mismatch. * **S7 DONE** — exit `0`. **Error states** `E_VALIDATE` (exit 2): schema/domain/ref/order errors. `E_VERIFY` (exit 3): any post-emit hash/FID mismatch. Other runtime I/O/parse issues: exit 4; spec violation (e.g., RNG misuse): exit 5 (Doc 3A). --- ## **3\) Pipeline context & data exchange** ### **3.1 RunContext (in-memory, normative fields)** { "registry": { /\* DivisionRegistry canonical \*/ }, "tally": { /\* BallotTally canonical \*/ }, "params": { /\* ParameterSet canonical \*/ }, "normative\_manifest": { /\* Included rules & 2A/2C values \*/ }, "formula\_id": "\<64hex\>", "nm\_digest": { "schema\_version":"1.x", "nm\_sha256":"\<64hex\>" }, "engine": { "vendor":"...", "name":"...", "version":"vX.Y.Z", "build":"commit:..." }, "rng": { "seed": 0, "used": false }, // 052; used=true iff a random tie occurred "frontier\_enabled": true, "frontier\_map\_enabled": true, // 034 "sensitivity\_enabled": false, // 035 (appendix only) "per\_unit": { "U-001": { "gate\_status": "valid|invalid", "reasons": \[ /\* ordered tokens per 4B §5 \*/ \], "frontier": { "band\_met": true, "band\_value": 0.12 }, // if enabled "allocations": \[ /\* ordered by order\_index \*/ \], "label": "Decisive|Marginal|Invalid" } /\* ... \*/ }, "run\_record\_scaffold": { "inputs\_sha256": { "registry":"\<64hex\>", "tally":"\<64hex\>", "params":"\<64hex\>" }, "vars\_effective": { "VM-VAR-\#\#\#": \, /\* all outcome-affecting \*/ }, "determinism": { "tie\_policy":"...", "rng\_seed": 0? }, "ties": \[ /\* events appended in unit order \*/ \] } } ### **3.2 Artifact construction (S5)** * **Result** pulls `formula_id`, `engine_version`, aggregates, and `per_unit[*].allocations/label`. * **RunRecord** pulls `engine`, `inputs_sha256`, `nm_digest`, `vars_effective`, `determinism`, `ties`, and any per-unit gate summaries (4B §6). * **FrontierMap** is emitted iff `frontier_map_enabled=true` **and** frontier evaluated in run; array ordered by `unit_id`. --- ## **4\) Stage contracts (what each stage MUST do)** | Stage | Consumes | Produces | Determinism/notes | | ----- | ----- | ----- | ----- | | **S0 INIT & LOAD** | file paths | `registry`,`tally`,`params` | No network; parse to canonical in-memory forms (Doc 1A §2.1). | | **S1 VALIDATE** | S0 outputs | — | Enforce Doc 1B domains; establish Option `order_index` uniqueness; fail → E\_VALIDATE. | | **S2 MANIFEST & SEED** | S0,S1 | `normative_manifest`,`formula_id`,`nm_digest`,`rng.seed` | FID built from Included set (Annex A); stash **052**; do not draw RNG. | | **S3.1 GATES** | ctx \+ 2A/2C | `gate_status`,`reasons` | Evaluate in fixed order (4B §2); never short-circuit recording of reasons. | | **S3.2 FRONTIER HOOK** | ctx \+ 040–042 (+047–049) | `frontier.*` | If `040!="none"`; invalid config → treat as 4B validity failure. | | **S3.3 ALLOCATE** | ctx \+ family 001–007 (+073) | `allocations[]` | Deterministic; obey option order. | | **S3.3a TIES** | 050,052 | adjusted `allocations[]`, `ties[]`, `rng.used=true` | Consume **k** draws for a **k-way** tie; never draw otherwise. | | **S3.4 EMIT-UNIT** | unit ctx | append to `per_unit` | Unit records ordered by `unit_id`; allocations by `order_index`. | | **S4 AGG & LABELS** | per-unit data | aggregates, labels | Labels via 060/061 (presentation only); do not alter allocations. | | **S5 BUILD** | ctx | `Result`,`RunRecord`,`FrontierMap?` | Canonical JSON (Doc 1A); set IDs. | | **S6 SELF-VERIFY** | artifacts | — | Recompute sha256; verify IDs; verify FID; fail → E\_VERIFY. | --- ## **5\) Canonical functions (IDs reserved; details in 5B)** | VM-FUN | Name | Summary | | ----- | ----- | ----- | | **001** | `LoadInputs` | Read files; normalize JSON. | | **002** | `ValidateInputs` | Doc 1B schema/domain/ref/order checks. | | **003** | `ComputeNormativeManifest` | Build Included set snapshot; hash → FID; fill `nm_digest`. | | **004** | `PrepareUnit` | Assemble unit view (registry+tally). | | **005** | `ApplyGates` | Run gates in order; produce reasons. | | **006** | `FrontierHook` | Evaluate 040–042 (+047–049); per-unit diagnostics. | | **007** | `ComputeAllocations` | Deterministic allocation per family 001–007 (+073). | | **008** | `ResolveTies` | Apply 050 policy; use 052 only when random. | | **009** | `LabelDecisiveness` | Compute label via 060/061 (presentation). | | **010** | `BuildResult` | Assemble canonical Result. | | **011** | `BuildRunRecord` | Assemble canonical RunRecord (vars\_effective, ties, determinism). | | **012** | `EmitFrontierMap` | Optional canonical FrontierMap. | | **013** | `CompareScenarios` | Optional sensitivity appendix when 035=true (report-only). | | **014** | `SelfVerify` | Recompute hashes/IDs; verify FID/engine disclosures. | Function specs (inputs/outputs/pre/postconditions) are defined in **Doc 5B**. --- ## **6\) Determinism requirements (reiterated)** * Iterate **units in ascending `unit_id`**; options **by `order_index`** (ties by `option_id`). * Never depend on map/dict iteration order. * RNG draws occur **only** within `ResolveTies` and **only** when `tie_policy="random"` and a tie exists; exactly **k** draws for a **k-way** tie. * Presentation toggles (032–035, 060–062) **never** change canonical JSON or FID. --- ## **7\) Exit codes & failure mapping** * **2** — Validation failure (Doc 1B): any schema/domain/ref/order violation. * **3** — Self-verification failure: any artifact hash or FID mismatch. * **4** — I/O/parse/runtime error. * **5** — Spec violation (ordering, RNG misuse, non-canonical JSON, network I/O). --- ## **8\) Conformance checklist (5A)** * **C-5A-ORDER**: All loops honor Doc 1A ordering; no nondeterministic aggregation. * **C-5A-FID**: FID built from Included set (Annex A) and equals both artifact fields. * **C-5A-RNG**: RNG seeded from **052**; no draws outside `ResolveTies`; draws counted per tie size. * **C-5A-REC**: `RunRecord` contains `vars_effective`, `inputs_sha256`, `nm_digest`, and `ties[]` in unit order. * **C-5A-PRES**: Labels/language (060–062) affect only presentation; artifacts remain canonical. * **C-5A-VERIFY**: Self-verify passes before exit. --- ## **9\) Minimal pseudocode (reference)** ctx \= LoadInputs(paths) ValidateInputs(ctx) // exit 2 on failure ctx.normative\_manifest, ctx.formula\_id, ctx.nm\_digest \= ComputeNormativeManifest(ctx.params) ctx.rng.seed \= VM\_VAR\_052 for unit in sort\_by\_unit\_id(ctx.registry.units): u \= PrepareUnit(unit, ctx.tally) valid, reasons \= ApplyGates(u, ctx.params) // 4B if \!valid: record\_invalid\_unit(ctx, u, reasons) continue if VM\_VAR\_040 \!= "none": u.frontier \= FrontierHook(u, ctx.params) // 4C u.allocations \= ComputeAllocations(u, ctx.params) // 4A if has\_tie(u.allocations): u.allocations \= ResolveTies(u.allocations, ctx.params, ctx.rng) // 4C u.label \= LabelDecisiveness(u, ctx.params) // 4C (presentation) append\_unit(ctx, u) Result \= BuildResult(ctx) RunRecord \= BuildRunRecord(ctx) if VM\_VAR\_034: FrontierMap \= EmitFrontierMap(ctx) SelfVerify(Result, RunRecord, FrontierMap?) // exit 3 on failure exit 0 *End Doc 5A.* # **Doc 5B — Canonical Function Specs (Updated, Normative)** **Scope.** This part defines each pipeline function’s **inputs**, **outputs**, **pre/postconditions**, **side-effects**, and **determinism** rules. Function IDs are stable. JSON formats & ordering: Doc 1A. Variables: Docs 2A/2B/2C (+ Annex A). Platform & RNG: Doc 3A. Release: Doc 3B. --- ## **VM-FUN-001 `LoadInputs(paths)` *(S0)*** **In:** file paths `{registry, tally, params}` **Out:** in-memory canonical objects `{registry, tally, params}` **Pre:** paths exist; readable **Post:** * Parsed to canonical in-mem forms (UTF-8, LF, sorted keys when re-emitting). * No network I/O. **Fail:** exit 4 on I/O/parse error. **Determinism:** independent of locale/timezone. --- ## **VM-FUN-002 `ValidateInputs(ctx)` *(S1)*** **In:** `{registry, tally, params}` **Out:** none (throws on error) **Pre:** FUN-001 done **Checks (Doc 1B):** schema domains, referential integrity, uniqueness of `order_index` per unit; non-negativity; vote sums ≤ valid ballots. **Fail:** exit 2 with first error code; MUST list **all** per-unit reasons if aggregating. **Determinism:** error listing order \= ascending VM-VAR (if applicable) then lexicographic. --- ## **VM-FUN-003 `ComputeNormativeManifest(ctx)` *(S2)*** **In:** `{params}`, algorithm constants (001..007, 073\) **Out:** `{normative_manifest, formula_id, nm_digest}` **Pre:** FUN-002 passed **Rules:** * Manifest \= outcome-affecting rules \+ Included VM-VARs (Annex A). * Canonicalize then `sha256 → formula_id` (64-hex). * `nm_digest = {schema_version, nm_sha256}` for verifier use. **Determinism:** identical manifest ⇒ identical FID. **Fail:** exit 5 if Included list/values incomplete. --- ## **VM-FUN-004 `PrepareUnit(unit, ctx)` *(S3 loop)*** **In:** `registry.units[unit_id]`, `tally.units[unit_id]` **Out:** per-unit working view `{unit_id, totals, option_rows[], flags}` **Pre:** FUN-002 passed **Rules:** * Build `option_rows[]` in **Registry order** (`order_index`, then `option_id`). * Compute base metrics needed by 4B/4C (e.g., shares, margin scaffolding). **Determinism:** no map-order dependence. --- ## **VM-FUN-005 `ApplyGates(u, params)` *(S3.1)*** **In:** unit view `u`, VM-VARs **010..017, 020..029, 021, 030..031, 045** **Out:** `{valid: bool, reasons[], protected_bypass?: bool, applied_exceptions[]}` **Rules:** stage order **Sanity → Eligibility → Validity → Frontier pre-check**, ascending ID within stage (Doc 4B). * `045=allow` may bypass **eligibility** only; never sanity or integrity floor (031). * `030` overrides applied before `029` exceptions. **Recording:** reasons ordered: ascending VM-VAR ID, then symbolic tokens. **Fail:** none; returns `valid=false` when any gate fails. --- ## **VM-FUN-006 `FrontierHook(u, params)` *(S3.2)*** **In:** `u`, VM-VARs **040–042**, **047–049** **Out:** `{band_met: bool, band_value?: number}` **Rules:** apply 040/041/042; refine 047→048→049 precedence. If `040="none"`, return `{band_met:false}` without side-effects. **Fail:** if config invalid/missing inputs ⇒ treat as **validity failure** per Doc 4B; producer MUST record reason `frontier_missing_inputs`. **Determinism:** pure given inputs/params. --- ## **VM-FUN-007 `ComputeAllocations(u, family)` *(S3.3)*** **In:** `u`, family constants **001..007**, optional **073** **Out:** `allocations[]` (ordered by Registry order) **Rules:** deterministic; no RNG; no presentation vars. **Fail:** exit 5 on under-specified family behavior. **Determinism:** invariant to thread count. --- ## **VM-FUN-008 `ResolveTies(allocations, params, rng)` *(S3.3a)*** **In:** `allocations[]`, VM-VARs **050 (tie\_policy)**, **052 (tie\_seed)**; RNG state `{seed, used}` **Out:** adjusted `allocations[]`; append to `RunRecord.ties[]`; set `rng.used=true` iff random tie occurred **Policy:** * `status_quo` ⇒ apply family rule; no RNG. * `deterministic_order` ⇒ sort tied subset by `order_index`, then `option_id`; **no VM-VAR controls order key**; **051 reserved**. * `random` ⇒ seed RNG with **052** (once per run). For a k-way tie draw exactly **k** 64-bit values, sort tied subset by `(draw, option_id)`. **Side-effects:** add `{unit_id, type, policy, seed?}` to `RunRecord.ties[]` when policy=`random`. **Determinism:** draw counts MUST equal **k per tie**; no draws otherwise. **Fail:** exit 5 if RNG used outside `random` policy or draw count deviates. --- ## **VM-FUN-009 `LabelDecisiveness(u, params)` *(S4)*** **In:** per-unit metrics, `allocations[]`; VM-VARs **060 (threshold)**, **061 (policy)** **Out:** `"Decisive" | "Marginal" | "Invalid"` **Rules:** presentation-only; does not alter allocations or any hash input. * `fixed` ⇒ label by margin ≥ 060\. * `dynamic_margin` ⇒ label by margin & blocking flags (deterministic booleans from earlier stages). **Determinism:** identical inputs ⇒ identical label. **Fail:** none (fallback to `Marginal` if inputs insufficient and unit not invalid). --- ## **VM-FUN-010 `BuildResult(ctx)` *(S5)*** **In:** per-unit records, `formula_id`, `engine.version` **Out:** canonical `Result` JSON object **Rules:** * Units ordered by `unit_id`; allocations by `order_index`. * Include aggregates & label per Doc 4A/4C/7; exclude diagnostics. * Compute `result_id = "RES:"+sha256(canonical(Result))`. **Fail:** exit 5 on ordering/canonicalization violation. --- ## **VM-FUN-011 `BuildRunRecord(ctx)` *(S5)*** **In:** `engine{vendor,name,version,build}`, input digests, `nm_digest`, `formula_id`, `params`, tie events, per-unit gate summaries **Out:** canonical `RunRecord` JSON object **Rules:** * `vars_effective` MUST list **all outcome-affecting** VM-VARs actually used; presentation vars MAY be included. * `determinism.tie_policy` reflects **050**; `determinism.rng_seed` present iff any random tie occurred (value \= **052** used). * Compute `run_id = "RUN:"++"-"+sha256(canonical(RunRecord))`. **Fail:** exit 5 if any required field missing or non-canonical. --- ## **VM-FUN-012 `EmitFrontierMap(ctx)` *(S5, optional)*** **In:** per-unit frontier diagnostics; VM-VAR-034 **Out:** canonical `FrontierMap` JSON (if emitted) **Rules:** emit only when `034=true` **and** frontier evaluated. Use `band_met` field name. * Compute `frontier_id = "FR:"+sha256(canonical(FrontierMap))`. **Fail:** none (skip emission if disabled or unused). --- ## **VM-FUN-013 `CompareScenarios(ctx)` *(S4/S7 appendix, optional)*** **In:** base context; a fixed set of diagnostic scenario deltas (implementation-defined, non-FID) gated by **VM-VAR-035=true** **Out:** report-only appendix data; **must not** alter `Result` or `RunRecord` hashes **Rules:** * Runs as a **separate sandbox** after canonical artifacts are built. * No changes to canonical JSON; renderer may display appendix. **Fail:** non-fatal; appendix omitted on error. --- ## **VM-FUN-014 `SelfVerify(Result, RunRecord, FrontierMap?)` *(S6)*** **In:** artifacts **Out:** none (throws on mismatch) **Checks:** * Recompute sha256 and compare to `result_id`, `run_id`, `frontier_id?`. * Independently recompute FID from `nm_digest`/manifest equals `Result.formula_id` and `RunRecord.formula_id`. **Fail:** exit 3 on any mismatch. --- ## **Shared conventions (all functions)** * **No network** during official runs (Doc 3A). * **Ordering**: arrays must follow Doc 1A §5 (units by `unit_id`; options by `order_index`, then `option_id`). * **RNG**: only FUN-008 may consume draws, and only under `tie_policy="random"`. * **Error classification**: * Spec violation / determinism breach ⇒ exit 5\. * Validation (inputs) ⇒ exit 2\. * Hash/FID mismatch ⇒ exit 3\. * I/O/parse ⇒ exit 4\. --- ## **Minimal I/O signatures (reference)** 001 LoadInputs(paths) \-\> ctx.{registry,tally,params} 002 ValidateInputs(ctx) \-\> void | exit 2 003 ComputeNormativeManifest(ctx) \-\> {manifest, formula\_id, nm\_digest} 004 PrepareUnit(unit, ctx) \-\> unit\_ctx 005 ApplyGates(unit\_ctx, params) \-\> {valid, reasons\[\], protected\_bypass?, applied\_exceptions\[\]} 006 FrontierHook(unit\_ctx, params) \-\> {band\_met, band\_value?} 007 ComputeAllocations(unit\_ctx, family) \-\> allocations\[\] 008 ResolveTies(allocations, params, rng) \-\> allocations'\[\], ties\[\], rng.used? 009 LabelDecisiveness(unit\_ctx, params) \-\> "Decisive"|"Marginal"|"Invalid" 010 BuildResult(ctx) \-\> Result 011 BuildRunRecord(ctx) \-\> RunRecord 012 EmitFrontierMap(ctx) \-\> FrontierMap? 013 CompareScenarios(ctx) \-\> AppendixData (non-canonical) 014 SelfVerify(Result, RunRecord, FrontierMap?) \-\> void | exit 3 *End Doc 5B.* # **Doc 5C — Audit Data, TieLog & Non-Canonical Appendices (Updated, Normative where stated)** ## **1\) Purpose & scope** Completes **Doc 5** by fixing the **audit data model**, **TieLog**, and the **optional diagnostics/appendices** that never affect outcomes. * **Normative**: anything that lands in canonical artifacts (`Result`, `RunRecord`, optional `FrontierMap`) or constrains determinism. * **Informative**: optional diagnostics/appendices emitted outside canonical artifacts. Inputs/outputs, ordering, hashing, FID: Docs **1A–1B–3A–3B**. Algorithm: **4A–4C**. Variables: **2A–2C** (+ Annex A). --- ## **2\) Canonical audit content (lives inside `RunRecord`)** ### **2.1 Determinism block (normative)** "determinism": { "tie\_policy": "status\_quo|deterministic\_order|random", // mirrors VM-VAR-050 "rng\_seed": 424242 // present iff any random tie occurred; value \= VM-VAR-052 } * `rng_seed` MUST be omitted if no random tie occurred. ### **2.2 Effective variables (normative)** "vars\_effective": { "VM-VAR-001": "...", ... "VM-VAR-050": "status\_quo", "VM-VAR-052": 0, /\* all outcome-affecting variables included; presentation (e.g., 060–062) MAY be echoed \*/ } Rules: * MUST include **all outcome-affecting** VM-VARs (Annex A “Included”). * **Presentation/report toggles** (032–035, 060–062) do **not** affect FID; echoing them is optional. ### **2.3 TieLog (normative)** Array ordered by **ascending `unit_id`**, then event creation order within the unit evaluation. Event schema: { "unit\_id": "U-001", "type": "winner\_tie|rank\_tie|other", "policy": "status\_quo|deterministic\_order|random", "seed": 424242 // present only when policy="random" } Rules: * An entry is added **only** when a tie actually affects allocation/ranking (Doc 4C §3). * For `random`, engine consumes **exactly k draws** for a k-way tie and records `seed`. ### **2.4 Gate summary (normative)** Per-unit gate outcome, if producer opts to embed it in `RunRecord`: { "unit\_id": "U-001", "gate\_status": "valid|invalid", "reasons": \[ "VM-VAR-020:min\_turnout", "VM-VAR-031:integrity\_floor" \], "protected\_bypass": true, // only if 045=allow bypassed an eligibility gate "applied\_exceptions": \[ "VM-VAR-029:U-001" \], "frontier\_ready": true // frontier pre-check result if frontier is enabled } Ordering: * `reasons[]` sorted by **VM-VAR numeric ID**, then lexical for symbolic tokens (Doc 4B §5). * The array of these unit records is ordered by **`unit_id`**. ### **2.5 Inputs digest scaffold (normative)** "inputs": { "division\_registry\_sha256": "\<64hex\>", "ballot\_tally\_sha256": "\<64hex\>", "parameter\_set\_sha256": "\<64hex\>" }, "nm\_digest": { "schema\_version": "1.x", "nm\_sha256": "\<64hex\>" } * All digests computed over **canonical JSON** (Doc 1A §2.1). --- ## **3\) `FrontierMap` (optional canonical artifact, recap)** * Emitted **only** if `VM-VAR-034 = true` and frontier executed in the run. * Schema per Doc 1A §4.6; field is **`band_met`**. * Units ordered by `unit_id`. Presence/absence never alters outcomes. --- ## **4\) Non-canonical diagnostics & appendices (informative)** Diagnostics here are **outside** the hashed canonical artifacts. They MUST NOT change `Result`/`RunRecord` IDs or FID. ### **4.1 Sensitivity appendix (gated by `VM-VAR-035`)** * Runs **after** canonical artifacts are finalized. Explores a fixed, documented set of scenario deltas (implementation-defined), e.g.: { "scenarios": \[ { "name": "Turnout+1pp", "deltas": { "counterfactual\_turnout": "+1pp" } }, { "name": "Turnout-1pp", "deltas": { "counterfactual\_turnout": "-1pp" } } \], "results": \[ { "name": "Turnout+1pp", "summary\_diff": { /\* report-only \*/ } } \] } * * Emission location is a renderer concern (appendix PDF/HTML/JSON). * MUST NOT write into canonical `Result` or `RunRecord`. ### **4.2 Debug traces (developer mode)** * Optional JSON/NDJSON with per-stage timings, thread counts, and intermediate metrics. * File naming SHOULD avoid collisions (e.g., `debug_trace.ndjson`). * MUST NOT be read by the renderer for official reports; MUST NOT influence canonical artifacts. --- ## **5\) ParameterSet export & echo policy** * **Input ParameterSet** is hashed into `parameter_set_sha256`. * **Echo rules**: * All **outcome-affecting** VM-VARs MUST be echoed in `vars_effective`. * **Tie controls**: `VM-VAR-050` **and** `VM-VAR-052` are echoed; `051` is **reserved** (no value). * **Presentation VM-VARs** (032–035, 060–062) MAY be echoed for transparency but are **excluded from FID**. * **CLI overrides** (e.g., `--seed N`) MUST be reflected in `vars_effective` and, if used for random ties, in `determinism.rng_seed`. --- ## **6\) Error mapping & exit codes (recap, normative)** * **Validation failure** (Doc 1B): exit **2**; no canonical artifacts emitted. * **Self-verification failure** (hash/FID mismatch): exit **3**. * **I/O or parse** errors: exit **4**. * **Spec violation** (ordering, RNG misuse, network I/O): exit **5**. --- ## **7\) Conformance checklist (5C)** * **C-5C-VARS**: `vars_effective` lists every outcome-affecting VM-VAR actually used (Annex A “Included”); presentation vars optional. * **C-5C-TIELOG**: Each recorded tie corresponds to an actual allocation/ranking tie; `seed` present only for `random`. * **C-5C-GATESUM**: Gate summaries (if emitted) follow ordering and tokenization rules; reasons are complete and deterministic. * **C-5C-FRMAP**: `FrontierMap` uses `band_met`; units ordered by `unit_id`; emission gated by `VM-VAR-034`. * **C-5C-APPX**: Sensitivity/debug outputs do not alter canonical artifacts or their hashes. --- ## **8\) Minimal example fragments** **RunRecord (excerpt)** { "determinism": { "tie\_policy": "random", "rng\_seed": 424242 }, "vars\_effective": { "VM-VAR-050": "random", "VM-VAR-052": 424242, "VM-VAR-040": "banded", "VM-VAR-041": 0.10, "VM-VAR-042": "apply\_on\_entry" }, "ties": \[ { "unit\_id": "U-003", "type": "winner\_tie", "policy": "random", "seed": 424242 } \], "summary\_units": \[ { "unit\_id": "U-003", "gate\_status": "valid", "reasons": \[\], "frontier\_ready": true } \] } **FrontierMap (excerpt)** { "frontier\_id": "FR:\<64hex\>", "units": \[ { "unit\_id": "U-001", "band\_met": true, "band\_value": 0.12, "notes": "within band-1" } \] } *End Doc 5C.* ================================================================================================ FILE: docs/Doc 6 — Test Specifications (Allocation, Gates, Frontier & Determinism).md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 9c8965c209ebfec0040ccdc48138c846d3bd279c4ac8bb0f8b7bed2e78d20bd3 CONTENT_BYTES: 22600 ================================================================================================ # **Doc 6A — Test Harness & Allocation Correctness (Updated, Normative)** ## **1\) Purpose & scope** Defines the **official test harness**, **fixtures format**, and the **allocation-correctness** test set. This part ensures engines implement 4A flow correctly with no reliance on ties, frontier, or presentation toggles. Determinism, ties, gates, and frontier have focused suites in **6B/6C**. Outcomes from these tests must be **byte-identical** across OS/arch when inputs and ParameterSet match. --- ## **2\) Test harness (normative)** ### **2.1 Invocation** Each test case supplies three canonical JSON files and a directory for outputs: vm\_cli \--registry \/registry.json \\ \--tally \/tally.json \\ \--params \/params.json \\ \--out \ No network. Exit codes per Doc 3A/5A. ### **2.2 Required outputs per test** * `result.json` (canonical; Doc 1A §2.1, §4.4) * `run_record.json` (canonical; Doc 1A §4.5) * Optional `frontier_map.json` **only** if frontier is enabled **and** VM-VAR-034=true (Doc 1A §4.6) ### **2.3 Verification workflow** Implement the following assertions for every case: 1. **Canonical form** * UTF-8, LF, sorted keys; arrays ordered per Doc 1A §5. 2. **IDs & hashes** * `result_id == "RES:" + sha256(canonical(result.json))` * `run_id` suffix (after timestamp and hyphen) equals sha256(canonical(run\_record.json)) * If `frontier_map.json` exists: `frontier_id == "FR:" + sha256(canonical(frontier_map.json))` 3. **Referential integrity** (Doc 1B) 4. **FID integrity** * Recompute FID from the **Included** set (Annex A) and confirm it equals both `Result.formula_id` and `RunRecord.formula_id`. 5. **Vars echo** * `RunRecord.vars_effective` lists **all** outcome-affecting VM-VARs actually used; 032–035 and 060–062 may appear but are **non-FID**. 6. **No RNG** * For all 6A cases: `RunRecord.determinism.rng_seed` MUST be absent; `RunRecord.ties[]` MUST be empty. Annex B (Canonical Test Pack) provides machine-readable “expected” for allocations, labels, and selected aggregates. --- ## **3\) Fixture format (normative)** ### **3.1 `registry.json`** See Doc 1B/1C. Must contain: * Stable `unit_id`, `option_id` * Unique `order_index` per unit (determinism primitive) ### **3.2 `tally.json`** * Non-negative integers; `sum(option.votes) ≤ totals.valid_ballots` * Units/options aligned to the Registry ### **3.3 `params.json` (ParameterSet)** * `schema_version` * `vars` map with explicit values for **all** VM-VARs listed “Included” in Annex A **except** tie/advanced/frontier where each 6A case **disables** them: * **Ties**: `VM-VAR-050="deterministic_order"` (051 reserved; 052 ignored) * **Frontier**: `VM-VAR-040="none"` (047–049 irrelevant) * **Presentation** (optional, non-FID): `060=55`, `061="dynamic_margin"`, `062="auto"` * **034/035**: `frontier_map_enabled=false`, `sensitivity_analysis_enabled=false` --- ## **4\) Allocation-correctness test set (normative)** Each case includes **expected allocations** (unit-ordered; options by `order_index`) and **expected labels** (presentation; informative). Hashes for canonical artifacts are provided in Annex B. ### **VM-TST-101 — Simple 2-option majority** * **Intent:** Baseline allocation; no ties; no gates triggered. * **Params:** `050="deterministic_order"`, `040="none"` * **Expect:** Allocations match vote shares; label depends on 060/061 but is non-FID. ### **VM-TST-102 — Three options, strict registry order** * **Intent:** Confirms allocations preserve `order_index` in arrays. * **Expect:** Output `allocations[]` appear in Registry option order even if votes are descending/ascending differently. ### **VM-TST-103 — Zero-vote minor option** * **Intent:** Zero votes do not create ties or invalid states by themselves. * **Expect:** Minor option present with `votes=0`; no ties; valid unit. ### **VM-TST-104 — Multiple units, deterministic iteration** * **Intent:** Confirms units processed in ascending `unit_id`. * **Expect:** `Result.units[]` sorted by `unit_id`; per-unit allocations correct. ### **VM-TST-105 — Rounding policy application** * **Intent:** Verifies family constants **001…007** (and **073** if used) drive rounding deterministically. * **Expect:** Aggregates and per-unit shares match fixtures to engine precision. ### **VM-TST-106 — Large counts stability** * **Intent:** 64-bit safety and stable arithmetic with big tallies. * **Expect:** Correct totals/shares; canonicalization intact. ### **VM-TST-107 — Missing option in tally is not auto-created** * **Intent:** Enforce Doc 1B referential integrity. * **Expect:** **Validation error** (exit 2), not a coerced zero row. ### **VM-TST-108 — Order index uniqueness** * **Intent:** Duplicate `order_index` in a unit is invalid. * **Expect:** **Validation error** (exit 2\) with code `E-DR-ORD-UNIQ`. ### **VM-TST-109 — Sum of votes \> valid\_ballots** * **Intent:** Sanity check per Doc 1B. * **Expect:** **Validation error** (exit 2\) `E-BT-SUM`. ### **VM-TST-110 — FID recomputation lock** * **Intent:** Confirms FID is independent of 060–062 and section ordering. * **Params:** Change `061` (`fixed` ↔ `dynamic_margin`) **only**. * **Expect:** **Same FID**, identical `Result` allocations; only label may differ. --- ## **5\) Per-case acceptance template (normative)** For every **passing** case (those not designed to fail validation): 1. **IDs & hashes** verified (2.3). 2. **Allocations** exactly match Annex B fixture (unit & option ordering). 3. **Labels** match fixture (informative; presentation-only). 4. **RunRecord** * `vars_effective` includes all outcome-affecting VM-VARs * `determinism.tie_policy="deterministic_order"`; no `rng_seed`; `ties=[]` * `inputs.*_sha256` match canonical inputs * `nm_digest.nm_sha256` present and consistent 5. **FID** recomputed equals both artifacts’ `formula_id`. For **validation-error** cases, assert correct **exit code 2** and the specific error token(s). --- ## **6\) Harness conformance (producer & verifier)** * **Producer** (engine) MUST emit only canonical artifacts and exit with codes defined in Doc 3A/5A. * **Verifier** (test runner) MUST: * Re-canonicalize artifacts before hashing. * Recompute FID from the Included set (Annex A). * Compare allocations and labels against Annex B fixtures. * Enforce ordering rules strictly (Doc 1A §5). --- ## **7\) Notes & boundaries** * 6A cases **never** require RNG or frontier; those are covered in **6C** and **6B** respectively. * Presentation variables (032–035, 060–062) may vary without changing FID; 6A uses fixed defaults for consistency. * All fixtures are provided machine-readable in **Annex B — Canonical Test Pack**. *End Doc 6A.* # **Doc 6B — Gates & Frontier Test Suite (Updated, Normative)** ## **1\) Purpose & scope** Defines the **official tests** for **unit gating** (Doc 4B) and the **frontier model** (Doc 4C §2). These tests verify: * Gate **order**, **semantics**, and **reason recording**. * Protected/override logic (**045**, **029**, **030**, **031**). * Frontier enablement (**040–042**), advanced tuning (**047–049**), and **FrontierMap** emission (**034**). This suite is **normative**. Fixtures live in **Annex B — Canonical Test Pack**. Determinism, hashing, and FID rules per Docs **1A/3A/3B**. --- ## **2\) Harness & invariants (reuse of 6A §2–§3)** * Invocation, required outputs, verification workflow, and canonical JSON rules are identical to **Doc 6A §2–§3**. * **Gate failures are not schema errors**: a unit may become `Invalid` but the run still **succeeds** (exit `0`). Only schema/ref/order violations (Doc 1B) yield exit `2`. **ParameterSet conventions for this suite (unless a case overrides):** * **Ties**: `VM-VAR-050="deterministic_order"`; `VM-VAR-052` ignored (no RNG). * **Frontier**: varies per case (`VM-VAR-040`), with **047–049** as needed. * **Presentation** (non-FID): `060=55`, `061="dynamic_margin"`, `062="auto"`. * **034 frontier\_map\_enabled** and **035 sensitivity\_analysis\_enabled** set per case. --- ## **3\) Test cases — Gates (020–031, 045, 029\)** ### **VM-TST-201 — Minimum turnout gate (eligibility)** **Intent:** An eligibility threshold forces `Invalid`. **Setup:** Set a turnout-like threshold (e.g., `VM-VAR-020`) above the unit’s value. **Expect:** * `Result.units[i].label="Invalid"`, `allocations=[]`. * `RunRecord.summary.units[i].reasons` contains a token for **020**. * Exit `0`; hashes/FID valid. ### **VM-TST-202 — Multiple eligibility gates; reason ordering** **Intent:** Multiple failing gates record **all** reasons in **ascending VM-VAR ID**. **Setup:** Make **020** and **022** both fail. **Expect:** `reasons=["VM-VAR-020:…","VM-VAR-022:…"]` in that order; unit `Invalid`. ### **VM-TST-203 — Symmetry exceptions (029) narrow override** **Intent:** **029** selectively exempts a unit from an eligibility failure. **Setup:** Threshold via **020** would fail; `VM-VAR-029` lists this unit. **Expect:** Unit **valid**; `applied_exceptions=["VM-VAR-029:"]`; no **020** reason recorded. ### **VM-TST-204 — Eligibility override list (030) before exceptions** **Intent:** **030** applies **before** **029** per fixed precedence. **Setup:** Same as 203, but also set `VM-VAR-030` to `exclude` the unit. **Expect:** Unit `Invalid`; `reasons` includes **030** token; **029** recorded under `applied_exceptions` only if applicable; precedence documented. ### **VM-TST-205 — Integrity floor (031) cannot be bypassed** **Intent:** **031** invalidates a unit even if 029/030/045 would allow eligibility. **Setup:** Integrity KPI below **031**; other gates pass or are bypassed. **Expect:** `Invalid`; `reasons` includes **031**; no protected bypass allowed. ### **VM-TST-206 — Protected-area override (045=allow) bypasses eligibility only** **Intent:** **045=allow** may bypass an **eligibility** failure but never sanity/integrity. **Setup:** Mark unit `protected_area=true`; make an eligibility gate fail. **Expect:** Unit **valid**; `protected_bypass=true`; **no** reason for that eligibility gate. ### **VM-TST-207 — Protected-area with integrity floor still invalid** **Intent:** **045** cannot bypass **031**. **Setup:** As 206, but integrity KPI below **031**. **Expect:** `Invalid`; `reasons` includes **031**; `protected_bypass` absent/false. ### **VM-TST-208 — Frontier pre-check failure recorded as validity reason** **Intent:** Missing required inputs for frontier triggers a **validity** failure token, not a schema error. **Setup:** Enable frontier (**040≠"none"**), remove a required metric. **Expect:** Unit `Invalid`; `reasons` includes `"frontier_missing_inputs"` (ordered after VM-VAR tokens); exit `0`. --- ## **4\) Test cases — Frontier core (040–042) & diagnostics (034)** ### **VM-TST-210 — Frontier disabled** **Intent:** With `VM-VAR-040="none"`, frontier does not run. **Setup:** Any inputs; `034=true`. **Expect:** No `frontier_map.json` emitted; results unchanged; FID unaffected. ### **VM-TST-211 — Frontier banded (040), cut (041), strategy (042)** **Intent:** Baseline frontier gating is deterministic and reflected in diagnostics. **Setup:** `040="banded"`, `041=`, `042="apply_on_entry"`, `034=true`. **Expect:** `frontier_map.json` present; each unit has `band_met`/`band_value` per fixture; `Result` matches expected gating effect. ### **VM-TST-212 — FrontierMap emission toggle (034)** **Intent:** **Only** toggles presence of the file; allocations & FID unchanged. **Setup:** Same as 211 but run twice with `034=true` then `034=false`. **Expect:** Identical `Result` and FID; `frontier_map.json` emitted only when `034=true`. ### **VM-TST-213 — Advanced window (047) affects band\_met at margins** **Intent:** **047** expands/contracts the effective band around **041**. **Setup:** Units near the cut; compare `047=0.00` vs `047=0.02`. **Expect:** Borderline units flip `band_met` exactly as fixtures specify; deterministic across runs. ### **VM-TST-214 — Backoff policy (048) softens/hardens borderline** **Intent:** **048** resolves edges; compare `none` vs `soften` vs `harden`. **Setup:** Units at the threshold. **Expect:** `band_met` differences per fixture; order and hashes stable. ### **VM-TST-215 — Strictness (049) multiplies effects** **Intent:** **049** coarsely strengthens/weakens 047/048. **Setup:** Fix 047/048; vary `049` between `strict` and `lenient`. **Expect:** Predictable, documented change in `band_met`; allocations follow accordingly. ### **VM-TST-216 — Ladder mode uses autonomy map (046)** **Intent:** In ladder mode, autonomy package selection is deterministic. **Setup:** `040="ladder"`, define **046** map; provide tallies that traverse steps. **Expect:** Selected packages match fixture; stable across OS/arch. --- ## **5\) Per-case acceptance template (normative)** For every **passing** case (non-schema-failure): 1. **Canonical form & IDs** verified (as in 6A §2.3). 2. **Gate behavior** * Units `Invalid` when any gate fails; `allocations=[]`; `label="Invalid"`. * `reasons[]` complete and ordered: **ascending VM-VAR ID**, then symbolic (e.g., `"frontier_missing_inputs"`). * `protected_bypass` appears **only** when 045=allow bypassed **eligibility**. * `applied_exceptions[]` lists **029** matches deterministically. 3. **Frontier** * If `040!="none"` and `034=true`: `frontier_map.json` exists; entries match fixture (`band_met`, `band_value`); units ordered by `unit_id`. * If `034=false`: **no** `frontier_map.json`; `Result`/FID unchanged (compare to `034=true` run). 4. **FID integrity** * Changing **034** or any presentation variables (060–062) does **not** change FID. * Changes to outcome-affecting frontier/gate variables **do** produce the expected allocation differences and FID remains consistent with the Included set. --- ## **6\) Conformance checklist (6B)** * **C-6B-ORDER**: Reasons ordered by VM-VAR ID then symbolic; unit arrays by `unit_id`. * **C-6B-PROT**: 045 can bypass **eligibility** only; cannot bypass sanity or **031**. * **C-6B-PREC**: 030 precedence over 029 is honored and recorded. * **C-6B-FRONTIER**: 040–042 (+047–049) produce deterministic `band_met`; invalid config recorded as `"frontier_missing_inputs"`, not a schema error. * **C-6B-FRMAP**: `frontier_map.json` emitted **only** if `034=true` and frontier executed; FID unaffected by 034\. --- ## **7\) Notes** * Keep ties **off** in this suite (`050="deterministic_order"`) to isolate gate/frontier behavior. * RNG and tie behavior are exercised in **Doc 6C — Determinism & Ties** (next). *End Doc 6B.* # **Doc 6C — Determinism & Ties Test Suite (Updated, Normative)** ## **1\) Purpose & scope** Validates **determinism** and **tie resolution** behavior per Docs **3A**, **4C**, **5A–5C**: * Reproducibility with identical inputs \+ ParameterSet (incl. seed). * Correct application of **`tie_policy`** (**VM-VAR-050**) and **`tie_seed`** (**VM-VAR-052**). * No RNG used unless `tie_policy="random"` **and** a tie actually occurs. * Canonical logging of tie events in `RunRecord.ties[]`. * FID behavior: **050 affects FID; 052 does not** (seed is non-FID). Fixtures live in **Annex B — Canonical Test Pack**. Canonical JSON, hashing, and exit codes per **Docs 1A, 3A, 5A**. --- ## **2\) Harness & invariants (reuse from 6A §2–§3)** Invocation, required outputs, verification workflow, canonical form, IDs/hashes, FID recomputation, and `vars_effective` checks are identical to **Doc 6A §2–§3**. Differences for this suite: * `tie_policy` varies by case. * Some cases require multiple runs (same/different seeds). * Frontier disabled unless a case states otherwise (`VM-VAR-040="none"`). Common ParameterSet defaults unless overridden: 050: varies by case 052: 424242 (or as specified) 040: "none" 034: false 035: false 060: 55 061: "dynamic\_margin" 062: "auto" --- ## **3\) Test cases — determinism (no RNG path)** ### **VM-TST-301 — Full-run reproducibility (no RNG)** **Intent:** Identical runs produce byte-identical artifacts. **Setup:** `050="deterministic_order"`. Execute the same case twice. **Expect:** `result.json`, `run_record.json` identical; same `result_id`, `run_id` (except timestamp prefix is same format), same `formula_id`; `ties=[]`; `rng_seed` **absent**. ### **VM-TST-302 — Deterministic tie by order\_index** **Intent:** Two-way and three-way ties resolved by **Registry order**. **Setup:** Construct ties; `050="deterministic_order"`. **Expect:** Within tied groups, ascending `order_index` then `option_id`; `ties=[]`; `rng_seed` **absent**. ### **VM-TST-303 — Status quo policy path** **Intent:** Uses the family’s status-quo rule; no RNG. **Setup:** Ties exist; `050="status_quo"`. **Expect:** Allocations follow the family rule; `ties[]` entries present with `"policy":"status_quo"`; no `seed` field; `rng_seed` **absent**. --- ## **4\) Test cases — random ties (RNG path)** ### **VM-TST-304 — Random tie with fixed seed (2-way)** **Intent:** Seeded random tie is reproducible. **Setup:** 2-way tie; `050="random"`, `052=424242`. Run twice. **Expect:** Same permutation of the tied pair both runs; `ties[0].policy="random"`, `ties[0].seed=424242`; `RunRecord.determinism.rng_seed=424242`. ### **VM-TST-305 — Random tie with fixed seed (3-way)** **Intent:** k-way permutation is stable and sorted by `(draw, option_id)`. **Setup:** 3-way tie; `050="random"`, `052=424242`. **Expect:** Tied subset ordering exactly matches Annex B fixture (canonical RNG draws); `rng_seed=424242`. ### **VM-TST-306 — Seed variation changes outcome, FID unchanged** **Intent:** Outcomes may differ across seeds; FID stays the same. **Setup:** Same input; run A: `052=111111`, run B: `052=222222`; `050="random"`. **Expect:** * Allocations differ **only** where ties exist. * **Same `formula_id`** in both runs (seed excluded from FID). * `RunRecord.determinism.rng_seed` equals the chosen seed for each run. ### **VM-TST-307 — Random policy but no ties ⇒ no RNG use** **Intent:** Seed recorded only if a random tie actually occurred. **Setup:** No ties; `050="random"`, `052=999`. **Expect:** `ties=[]`; `RunRecord.determinism.rng_seed` **absent**; artifacts identical to a run with `050="deterministic_order"`. ### **VM-TST-308 — Multiple tie events consume exact draws** **Intent:** Exactly **k** draws per k-way tie; subsequent ties use subsequent draws. **Setup:** Two units, first has 3-way tie, second has 2-way tie; `050="random"`, `052=424242`. **Expect:** Permutations match Annex B (which encodes the canonical RNG sequence). A regression in draw counts will flip the second unit’s permutation and fail the fixture. ### **VM-TST-309 — Repeated ties within a unit** **Intent:** Multiple independent tie resolutions within the **same** unit consume draws in event order. **Setup:** One unit, two separate tie points in the algorithm; `050="random"`, `052=424242`. **Expect:** First tie uses first **k1** draws; second tie uses next **k2** draws; permutations match Annex B. ### **VM-TST-310 — Mixed policies across runs don’t collide** **Intent:** Changing policy alters FID; seed remains non-FID. **Setup:** Run A: `050="deterministic_order"`, Run B: `050="random"` (same inputs). **Expect:** **Different `formula_id`** across runs (policy included in FID). `rng_seed` present only for Run B if a random tie occurs. ### **VM-TST-311 — Random ties with frontier disabled/enabled (no interference)** **Intent:** Frontier configuration doesn’t change RNG usage rules. **Setup:** Same tie case; (A) `040="none"`, (B) `040="banded";034=true` (frontier diagnostics on). Both `050="random"`, `052=424242`. **Expect:** Identical allocations and tie permutations in A and B; B may emit `frontier_map.json`. `formula_id` may differ only if frontier variables are outcome-affecting in the case; seed handling unchanged. ### **VM-TST-312 — Invalid unit ⇒ no tie resolution** **Intent:** Gates pre-empt ties. **Setup:** Unit fails a validity gate (e.g., `031`), while a tie would otherwise occur. `050="random"`. **Expect:** Unit is `Invalid`; `allocations=[]`; **no** tie event for that unit; `rng_seed` only present if some **other** unit had a random tie. --- ## **5\) Per-case acceptance template (normative)** For every **passing** case (non-schema-failure): 1. **Canonical form & IDs** verified (as in 6A §2.3). 2. **FID integrity** * Changing **050** (policy) ⇒ FID changes as per Included set. * Changing **052** (seed) alone ⇒ **FID unchanged**. 3. **Tie behavior** * When `050="random"` and a tie occurs: `RunRecord.determinism.rng_seed = <052>`, and each `ties[]` entry has `"policy":"random"` and `"seed":<052>`. * When no random tie occurred (even if `050="random"`): `rng_seed` **absent**; `ties=[]`. * Tied subsets are ordered by `(draw, option_id)` using the canonical RNG; counts of draws match **exactly k per tie**. 4. **Determinism** * Same inputs \+ ParameterSet (incl. seed) ⇒ **byte-identical** artifacts across repeated runs. * Arrays preserve canonical ordering (units by `unit_id`; allocations by `order_index`). 5. **Scope** * Ties only resolved for **valid** units (after gates), post-frontier (Doc 4A S5/S3). --- ## **6\) Conformance checklist (6C)** * **C-6C-RNG-ONLY-WHEN-NEEDED**: RNG used **only** when `050="random"` **and** a tie exists. * **C-6C-SEED-ECHO**: `rng_seed` echoed in `RunRecord` **iff** any random tie occurred; value equals **052**. * **C-6C-DRAWS-K**: Exactly **k** draws per k-way tie; permutations match Annex B. * **C-6C-FID-SEED**: Changing **052** alone does **not** change FID; changing **050** does. * **C-6C-REPRO**: Re-running with the same seed yields byte-identical artifacts. --- ## **7\) Notes** * Annex B fixes the **RNG profile** and provides expected permutations; engines must implement the same RNG to pass. * `VM-VAR-051` remains **reserved**; there is no test that sets it—engines should ignore unknown/non-Included keys for FID while still enforcing Annex A’s Included list. *End Doc 6C.* ================================================================================================ FILE: docs/Doc 7 — Reporting Specification (Structure, Templates & Visual Rules).md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: 7446e59096b30369962d4ae02eb7525807454508d455985ce313f0f6bcc04028 CONTENT_BYTES: 18218 ================================================================================================ # **Doc 7A — Reporting: Structure & Visual Rules (Updated)** ## **1\) Purpose & scope** Defines **how to render** official outputs from the canonical artifacts without changing them. The renderer **must not** re-compute allocations or alter canonical JSON; it only formats and displays data from `Result`, `RunRecord`, and (optionally) `FrontierMap`. * **Outcome-affecting logic** lives in Docs 4A–4C (already executed by the engine). * **Presentation toggles** come from Doc 2B (non-FID): `VM-VAR-032..035`, `060..062`. --- ## **2\) Inputs & may/must rules** **Consumes (read-only):** * `Result` (Doc 1A §4.4) — allocations, labels, aggregates, IDs. * `RunRecord` (Doc 1A §4.5) — engine/version, FID, vars echo, tie log, input digests. * `FrontierMap` (optional; Doc 1A §4.6) — frontier diagnostics when emitted. **Renderer MUST:** * Use only the above artifacts (no recalculation). * Honor **section ordering/visibility** toggles (Doc 2B). * Print required disclosures (FID, Engine Version, etc.). * Treat missing optional artifacts (e.g., `FrontierMap`) as “not applicable” (never error). **Renderer MUST NOT:** * Change array orders or numeric values. * Depend on system locale/timezone for numeric formats (use rules below). * Leak non-canonical diagnostics into canonical artifacts. --- ## **3\) Presentation toggles (Doc 2B recap)** | ID | Name | Effect on report | | ----- | ----- | ----- | | **VM-VAR-032** `unit_sort_order` | Ordering of **unit detail sections**: `unit_id` (default) | `label_priority` | `turnout`. Does **not** change JSON order. | | | **VM-VAR-033** `ties_section_visibility` | `auto` (default: show only if `RunRecord.ties[]` non-empty) | `always` | `never`. | | | **VM-VAR-034** `frontier_map_enabled` | If `true` **and** frontier executed, include **Frontier Appendix** sourced from `FrontierMap`. | | | **VM-VAR-035** `sensitivity_analysis_enabled` | If `true`, include **Sensitivity Appendix** (non-canonical, Doc 5C §4.1). | | | **VM-VAR-060** `majority_label_threshold` | Threshold used **by engine** to derive labels; renderer displays label only. | | | **VM-VAR-061** `decisiveness_label_policy` | `fixed`/`dynamic_margin` — affects label text computed by engine; renderer displays. | | | **VM-VAR-062** `unit_display_language` | `auto` or IETF tag (`en`, `fr`, …) for unit names and static strings. | | All above are **non-FID** (presentation only). --- ## **4\) Document structure (sections)** 1. **Cover & metadata (required)** * Title, run date (`created_at` from `Result`), jurisdiction. * **Disclosures** block (see §7): *Formula ID*, *Engine Version*, optional *Algorithm Variant (VM-VAR-073)*. 2. **Executive summary (required)** * Key national metrics from `Result.summary`. * Aggregate label context (Decisive/Marginal counts). 3. **National overview (required)** * Charts/tables sourced from `Result.summary` (no recompute). * If labels depend on `060/061`, show the policy string (e.g., “dynamic margin, threshold 55%”). 4. **Unit detail sections (required)** * One section per `Result.units[]`. * **Ordering of sections** per `VM-VAR-032` (renderer-only). * Each section shows: unit name/ID, label, allocation table (votes & shares), any gate notes if available in `RunRecord` summary. 5. **Ties section (conditional)** * Visibility per `VM-VAR-033`. * Table from `RunRecord.ties[]`: `{unit_id, type, policy, seed?}`. * If any `policy="random"`, echo `RunRecord.determinism.rng_seed`. 6. **Frontier appendix (conditional)** * Included iff **`VM-VAR-034=true`** and frontier executed. * Table from `FrontierMap.units[]`: `{unit_id, band_met, band_value, notes}`. 7. **Sensitivity appendix (conditional, non-canonical)** * Included iff **`VM-VAR-035=true`** and producer provided data (Doc 5C §4.1). * Clearly marked “diagnostic; does not affect results”. 8. **Integrity & audit (required)** * Display `result_id`, `run_id`, `formula_id`. * Input digests from `RunRecord.inputs.*_sha256`. * Non-normative toggles delta (if any) — see §7.3. --- ## **5\) Numeric & text formatting (visual rules)** * **Percentages**: display with **one decimal place** (e.g., `54.5%`). Rounding: **round half up** (0.05 → 0.1). Do **not** localize decimal separator. * **Shares**: if shown as decimals, show **three** places (e.g., `0.545`). * **Integers**: thousands separator thin space or comma; pick one consistently for the whole doc; do not localize by OS. * **Dates**: render in UTC ISO 8601 or spelled UTC date (e.g., `2025-08-12`). * **Language (VM-VAR-062)**: * `auto`: choose the report bundle language; * explicit tag: use provided IETF tag for unit names and static strings; if a localized name is unavailable, fall back to canonical name. Accessibility: * Provide text equivalents for charts. * Use colorblind-safe palettes; never encode information by color alone. * Minimum font size and contrast per WCAG 2.1 AA. --- ## **6\) Section content mappings (no recomputation)** ### **6.1 Unit detail** * **Header**: `unit_id` \+ localized `name` (per 062\) \+ `label` from `Result.units[i].label`. * **Allocations table** (engine order): * Columns: Option name, `votes`, `share` (from `Result.units[i].allocations[]`). * Do **not** sort by votes; keep registry order. ### **6.2 Gate notes (if present)** If producer embedded per-unit gate summary in `RunRecord` (Doc 5C §2.4), render: * Gate status: Valid / Invalid. * Reasons: ordered tokens as recorded. * Protected bypass indicator and matched exceptions, if any. ### **6.3 Ties** From `RunRecord.ties[]` (Doc 5C §2.3): * Table columns: Unit, Type, Policy, Seed (blank unless policy=`random`). * If empty and `ties_section_visibility=auto`, omit the section. ### **6.4 Frontier appendix** If `FrontierMap` present: * List `{unit_id, band_met, band_value, notes}` in ascending `unit_id`. * Do not back-fill or compute missing metrics. ### **6.5 Sensitivity appendix** Render whatever diagnostic structure producer emitted; clearly marked as **non-canonical**. --- ## **7\) Required disclosures & footers** ### **7.1 Identity & provenance (footer on every page)** * **Formula ID** (64-hex). * **Engine Version** (e.g., `vX.Y.Z`). * **Algorithm Variant** (VM-VAR-073) if not the default. * Page number / total. ### **7.2 Determinism snippet (end matter)** * If any random tie occurred: `Tie policy: random; RNG seed: ; events: `. * Otherwise: `Tie policy: ; no RNG used`. ### **7.3 Non-normative toggles delta** If any **2B toggles** differ from **Annex A defaults**, add a small table: Non-normative toggles (differences from defaults) VM-VAR-032 unit\_sort\_order label\_priority VM-VAR-033 ties\_section\_visibility always VM-VAR-034 frontier\_map\_enabled false ... This is disclosure only; it must not affect canonical artifacts. --- ## **8\) Section ordering logic (renderer-only)** * Default: `VM-VAR-032 = unit_id`. * `label_priority`: sort sections by label rank `Decisive` → `Marginal` → `Invalid`, then `unit_id`. * `turnout`: if available in `Result.summary`/per-unit metrics, sort descending turnout, then `unit_id`. * Sorting here affects **report sections only**; **never** reorders canonical JSON. --- ## **9\) Conformance checklist (7A)** * **C-7A-CANON**: Renderer reads canonical artifacts only; never mutates them. * **C-7A-TOGGLES**: Honors 032–035 and 060–062 exactly as defined; no effect on FID. * **C-7A-NUM**: One-decimal percent with round-half-up; stable thousands separators; no OS locale leakage. * **C-7A-ORDER**: Unit sections ordered per 032; allocation tables in registry order. * **C-7A-TIES**: Ties section per 033; seed shown only for random policy. * **C-7A-APPX**: Frontier appendix shown only if `FrontierMap` exists and 034=true; Sensitivity appendix when 035=true; both non-canonical. * **C-7A-DISCLOSE**: Footer shows FID, Engine Version, (optional) Variant; non-normative toggles delta included when applicable. * **C-7A-A11Y**: Accessibility rules applied (text alternatives, contrast, color-safe). --- ## **10\) Minimal wireframe (illustrative)** \[Cover\] Title Date (UTC) • Formula ID • Engine vX.Y.Z • Variant (if any) \[Executive summary\] • Valid ballots: … • Invalid ballots: … • Decisive units: … / Marginal: … / Invalid: … \[National overview\] Figure 1: Share chart (text alternate) Table 1: National metrics \[Units — ordered by VM-VAR-032\] Unit U-001 — District 1 — Label: Decisive Option Votes Share O-A1 6000 54.5% O-B1 5000 45.5% \[Ties\] (conditional by VM-VAR-033) Unit Type Policy Seed U-003 winner\_tie random 424242 \[Frontier appendix\] (conditional by VM-VAR-034) Unit band\_met band\_value Notes \[Sensitivity appendix\] (conditional by VM-VAR-035) Scenario Summary (diagnostic) \[Integrity & audit\] result\_id: RES:… run\_id: RUN:… inputs: registry sha256=…, tally sha256=…, params sha256=… Non-normative toggles (diffs): … *End Doc 7A.* # **Doc 7B — Reporting Templates, Data Binding & Export Profiles (Updated)** ## **1\) Purpose & scope** Defines the **template system**, **data bindings**, and **export rules** for rendering official reports from canonical artifacts. Templates are **presentation-only** (non-FID). They must **never** recompute allocations or alter canonical JSON. Upstream truths: data & IDs (Doc 1A), variables (Doc 2), algorithm (Doc 4), pipeline (Doc 5), platform/determinism (Doc 3). Visual structure rules live in **Doc 7A**; this part makes them executable. --- ## **2\) Template model (engine-agnostic)** * Any text templating engine is acceptable (Mustache/Handlebars/Jinja/ETC) provided: * **No code execution** inside templates (logicless or restricted logic). * Only **formatting** helpers are allowed (no arithmetic that could change outcomes). * Rendering is locale-neutral unless driven by **VM-VAR-062**. * Canonical artifacts are loaded **read-only** into a **RenderContext** (below). The renderer **must not** write back to canonical files. --- ## **3\) RenderContext (read-only)** Renderer builds a single context object for templates: { "result": { /\* Result (Doc 1A §4.4) \*/ }, "run\_record": { /\* RunRecord (Doc 1A §4.5) \*/ }, "frontier\_map": { /\* optional (Doc 1A §4.6) \*/ }, "toggles": { "unit\_sort\_order": "unit\_id|label\_priority|turnout", // VM-VAR-032 "ties\_section\_visibility": "auto|always|never", // VM-VAR-033 "frontier\_map\_enabled": true|false, // VM-VAR-034 "sensitivity\_analysis\_enabled": true|false, // VM-VAR-035 "label\_threshold": 55, // VM-VAR-060 "label\_policy": "fixed|dynamic\_margin", // VM-VAR-061 "unit\_display\_language": "auto|en|fr|..." // VM-VAR-062 }, "computed": { "units\_ordered": \[ /\* result.units\[\] reordered for display only per 032 \*/ \], "ties\_present": true|false, // run\_record.ties\[\].length \> 0 "frontier\_present": true|false, // toggles.frontier\_map\_enabled && frontier\_map exists "non\_normative\_diffs": \[ { "id":"VM-VAR-033", "from":"auto", "to":"always" }, ... \], "counts": { "decisive": 0, "marginal": 0, "invalid": 0 } // derived from result.units\[\].label } } Rules: * `computed.units_ordered` affects **document section order only**; JSON remains untouched. * `non_normative_diffs` compares Doc 2B toggle values to **Annex A defaults** for disclosure (Doc 7A §7.3). --- ## **4\) Allowed helpers (formatting-only)** Template engines may expose only these pure helpers: | Helper | Input | Output | Notes | | ----- | ----- | ----- | ----- | | `pct1(x)` | number (0..1) | string like `54.5%` | One decimal, round half up (Doc 7A §5). | | `dec3(x)` | number | string like `0.545` | Three decimals; no locale. | | `int(x)` | integer | string | Thousands sep consistent within doc. | | `date_utc(ts)` | RFC3339 | `YYYY-MM-DD` | UTC only. | | `i18n(key, lang)` | key, IETF tag | localized string | Uses 062; fallback to canonical. | **Not allowed:** arithmetic that changes inputs, sorting other than per §5, RNG, network access. --- ## **5\) Section iterators & ordering (render-only)** * **Unit sections iterator** uses `computed.units_ordered`: * `unit_id` (default): ascending `unit_id`. * `label_priority`: `Decisive` → `Marginal` → `Invalid`, then `unit_id`. * `turnout`: descending turnout (if present in `result.summary` or unit metrics), then `unit_id`. If turnout absent, fall back to `unit_id`. * **Allocations tables**: iterate **exactly** in the order of `result.units[i].allocations[]` (registry `order_index`), no resorting. --- ## **6\) Data binding map (normative)** Common tokens (illustrative for Mustache/Handlebars style): ### **6.1 Cover & metadata** * `{{result.created_at}}` * `{{run_record.engine.vendor}} / {{run_record.engine.name}} {{run_record.engine.version}}` * `{{result.formula_id}}`, `{{result.result_id}}`, `{{run_record.run_id}}` ### **6.2 Executive summary** * `{{result.summary.valid_ballots_total}}`, `{{result.summary.invalid_ballots_total}}` * `{{computed.counts.decisive}}`, `{{computed.counts.marginal}}`, `{{computed.counts.invalid}}` * If policy display: `{{toggles.label_policy}}` and `{{toggles.label_threshold}}` ### **6.3 Unit section** Within `{{#computed.units_ordered}} … {{/computed.units_ordered}}`: * Header: `{{unit_id}}`, localized name via `{{i18n name toggles.unit_display_language}}`, `{{label}}` * Table row (iterate `allocations`): * `{{option_id}}` (or localized option name if provided out-of-band) * `{{int votes}}` * `{{pct1 share}}` Optional gate notes if producer embedded them in `run_record` (Doc 5C §2.4): * `{{gate_status}}`, `{{#reasons}}{{.}}{{/reasons}}`, `{{protected_bypass}}`, `{{#applied_exceptions}}{{.}}{{/applied_exceptions}}` ### **6.4 Ties section** Shown per **033**: * Iterate `{{#run_record.ties}}` → `{{unit_id}}`, `{{type}}`, `{{policy}}`, `{{seed}}?` * If any `policy="random"`: echo `{{run_record.determinism.rng_seed}}` ### **6.5 Frontier appendix** Shown iff **034=true** and `frontier_map` exists: * Iterate `{{#frontier_map.units}}` → `{{unit_id}}`, `{{band_met}}`, `{{band_value}}`, `{{notes}}` ### **6.6 Non-normative toggles delta** * Iterate `{{#computed.non_normative_diffs}}` → `{{id}} {{from}} → {{to}}` --- ## **7\) Template packs & file layout** A release must ship a **Template Pack** containing: /templates cover.hbs summary.hbs unit.hbs ties.hbs frontier.hbs appendix\_sensitivity.hbs audit.hbs /locales en.json fr.json /theme base.css print.css Requirements: * **Locales**: key→string maps; no dynamic code. Missing keys fallback to English or canonical strings. * **CSS**: deterministic; no external fonts or network. If fonts are bundled, embed WOFF/WOFF2. --- ## **8\) Export profiles (HTML/PDF)** * **HTML**: single self-contained file (inline CSS and fonts allowed), UTF-8, no external requests. * **PDF**: A4 or Letter; margins ≥ 12 mm; embed fonts; rasterize figures at ≥ 150 DPI. Page footer on every page: `Formula ID • Engine vX.Y.Z • (Variant if any) • Page X/Y` (Doc 7A §7.1). Numeric/text formatting exactly per Doc 7A §5. Timezone must be UTC. --- ## **9\) Sensitivity & debug appendices (non-canonical)** * Render `appendix_sensitivity.hbs` **only** when `toggles.sensitivity_analysis_enabled=true` **and** data provided (Doc 5C §4.1). * Debug traces (if any) must **not** be referenced by official templates. --- ## **10\) Conformance checks (renderer)** * **R-7B-BIND**: Every template token resolves to data from `RenderContext`; no hidden computations. * **R-7B-ORD**: Unit section ordering follows **032**; allocation rows follow engine order. * **R-7B-VIS**: Sections/appendices appear only per **033/034/035** rules. * **R-7B-I18N**: Language selection per **062**; fallback deterministic. * **R-7B-FOOT**: Footer shows Formula ID, Engine Version, (optional) Algorithm Variant. * **R-7B-SELF**: Renderer never writes back to canonical artifacts; exports are reproducible from the same inputs. --- ## **11\) Minimal example snippets** ### **11.1 Unit template (unit.hbs)** \{{unit\_id}} — {{i18n name toggles.unit\_display\_language}} — {{label}}\ \ \\\Option\\Votes\\Share\\\ \ {{\#allocations}} \ \{{option\_id}}\ \{{int votes}}\ \{{pct1 share}}\ \ {{/allocations}} \ \ {{\#gate\_status}} \Status: {{gate\_status}}\ {{\#reasons}}\{{.}}\ {{/reasons}} {{\#protected\_bypass}}\Protected bypass applied.\{{/protected\_bypass}} {{/gate\_status}} ### **11.2 Footer fragment** \ Formula ID {{result.formula\_id}} • Engine {{run\_record.engine.version}} {{\#run\_record.engine}}{{\#build}} • {{.}}{{/build}}{{/run\_record.engine}} \ --- ## **12\) Accessibility & theming** * WCAG 2.1 AA minimum; provide text alternatives for charts; do not encode information by color alone. * Theme may define light/dark palettes; must preserve contrast ratios. * Font choices must support required locales for 062; include fallback stack. --- ## **13\) Change policy** * Template content and theme are **non-FID**. Updating them does **not** change FID. * Any addition of new canonical fields or changes to binding semantics requires updating Doc 7A/7B and **Annex A** (if variables are involved). * Default template pack lives with each release tag (Doc 3B §7). *End Doc 7B.* ================================================================================================ FILE: README.md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: d12eb1e7df35b82e6e76c9e01dc98516c5047ed79faafab51738820d00d4c5cd CONTENT_BYTES: 7781 ================================================================================================ ````markdown # VM-ENGINE v0 — Voting Machine (README) _Component 09/89 • Entry point for developers and reviewers_ > **Purpose**: This engine implements deterministic tabulation/allocation with explicit gates and frontier handling. It runs fully offline, produces canonical artifacts, and is verified by a normative test pack (Annex B). Code behavior is subordinate to the Specs (**Docs 1–7**) and Annexes (**A–C**). --- ## What this is (in 4 bullets) - **Deterministic** pipeline: same inputs → byte-identical outputs across OS/arch. - **Offline by default**: builds and tests run with `--locked` and no network I/O. - **Canonical JSON** everywhere: UTF-8, **LF** line endings, **sorted keys**. - **Ties**: resolved deterministically (policy-driven); when policy is random, a **seeded RNG (ChaCha20)** is used and recorded in `RunRecord` only if a random tie actually occurred. --- ## Quickstart (copy-paste) > Requires Rust (toolchain pinned via `rust-toolchain.toml`) and `cargo`. See **Troubleshooting** for Windows line-ending notes. ### 1) Build the CLI **Bash (Linux/macOS/Git Bash on Windows)** ```bash rustup show cargo build --locked -p vm_cli ```` **PowerShell** ```powershell rustup show cargo build --locked -p vm_cli ``` ### 2) Run a tiny Annex-B fixture > Uses the minimal fixture in `fixtures/annex_b/part_0` (or `VM-TST-001` if you prefer—both are included in Annex B). **Bash** ```bash ./target/release/vm_cli run \ --manifest fixtures/annex_b/part_0/manifest.json \ --output artifacts/run ``` **PowerShell** ```powershell .\target\release\vm_cli run ` --manifest fixtures\annex_b\part_0\manifest.json ` --output artifacts\run ``` Artifacts produced: ``` artifacts/run/ result.json # canonical result (RES:) run_record.json # provenance (RUN:-) frontier_map.json # optional, when enabled by manifest/policy ``` ### 3) Determinism smoke (same seed twice → identical bytes) **Bash** ```bash SEED=1 ./target/release/vm_cli run --manifest fixtures/annex_b/part_0/manifest.json --rng-seed $SEED --output artifacts/run1 ./target/release/vm_cli run --manifest fixtures/annex_b/part_0/manifest.json --rng-seed $SEED --output artifacts/run2 cmp -s artifacts/run1/result.json artifacts/run2/result.json cmp -s artifacts/run1/run_record.json artifacts/run2/run_record.json echo "OK: byte-identical" ``` **PowerShell** ```powershell $SEED=1 .\target\release\vm_cli run --manifest fixtures\annex_b\part_0\manifest.json --rng-seed $SEED --output artifacts\run1 .\target\release\vm_cli run --manifest fixtures\annex_b\part_0\manifest.json --rng-seed $SEED --output artifacts\run2 if ((Get-FileHash artifacts\run1\result.json).Hash -eq (Get-FileHash artifacts\run2\result.json).Hash -and (Get-FileHash artifacts\run1\run_record.json).Hash -eq (Get-FileHash artifacts\run2\run_record.json).Hash) { "OK: byte-identical" } else { throw "Mismatch" } ``` --- ## Determinism & offline guarantees (stated) * **Canonical serialization**: UTF-8, **LF**, **sorted JSON keys** at all object levels; arrays ordered per Doc 1. * **No network I/O** at runtime; builds/tests use `--locked`; Cargo is configured **offline by default** (`.cargo/config.toml`). * **Tie policy** (`VM-VAR-050`) may be deterministic (order-index) or random. Random tie-breaks use a **seed** (`VM-VAR-052`, non-FID) and are echoed in `RunRecord` **only if** a random tie occurred. * **IDs**: `RES:`, `RUN:-`, and optional `FR:` are computed from canonical bytes. * **Reporting** (Doc 7): one-decimal percentages; renderer **never recomputes** outcomes—reads canonical artifacts only. --- ## Repository map (short) ``` crates/ vm_core/ # core types & invariants vm_io/ # canonical I/O, schemas bindings vm_algo/ # allocation, gates, edge cases (Doc 4) vm_pipeline/ # state machine orchestration (Doc 5) vm_report/ # renderers (JSON/HTML); no recomputation vm_cli/ # command-line interface vm_app/ # optional Tauri UI (not built by default) fixtures/ annex_b/ # canonical test pack (Annex B) schemas/ # normative JSON Schemas (Doc 1) artifacts/ # outputs created by runs/tests (ignored by git) dist/ # reproducible release archives (Makefile) Doc 1 — Database Specification (Entities, Fields, Relationships).md Doc 2 — Common Variables Specification (Core, Operational Defaults, Advanced Controls).md Doc 3 — Technical Platform & Release Policy.md Doc 4 — Algorithm Specification (Steps, Allocation, Gates & Edge Cases).md Doc 5 — Processing Pipeline Specification (State Machine & Functions).md Doc 6 — Test Specifications (Allocation, Gates, Frontier & Determinism).md Doc 7 — Reporting Specification (Structure, Templates & Visual Rules).md Annex A — Variable Canonical Reference Table.md Annex B — Canonical Test Pack.md Annex C — Glossary & Definitions.md ``` --- ## Specs are normative If the code and the docs disagree, the **docs win**. See: * **Doc 1** (entities/fields/relationships; canonical JSON rules) * **Doc 2** (variable set & FID membership; Included vs Excluded) * **Doc 4** (algorithmic steps; tie-resolution timing) * **Doc 5** (state machine; step ordering and gates) * **Doc 6** (test matrix, oracle expectations, determinism cases) * **Doc 7** (reporting rules: sections, ordering, one-decimal presentation) * **Annex A/B/C** (IDs & ranges, canonical tests, definitions) --- ## How to run tests **Unit/integration tests** ```bash cargo test --locked --workspace ``` **Canonical fixtures (Annex B)** ```bash # Small sample: ./target/release/vm_cli run --manifest fixtures/annex_b/VM-TST-001/manifest.json --output artifacts/tst001 # Compare with expected (jq pretty-sort is optional): jq -S . fixtures/annex_b/VM-TST-001/expected/result.json > /tmp/exp.json jq -S . artifacts/tst001/result.json > /tmp/got.json diff -u /tmp/exp.json /tmp/got.json ``` **Makefile helpers** ```bash make ci # fmt → lint → build → test → fixtures → verify → hash make fixtures # run a minimal Annex B subset make verify # double-run determinism smoke make dist # reproducible archives in dist/ ``` --- ## Building reports (Doc 7) * Renderers in `vm_report` emit JSON/HTML using **only** canonical inputs; **no recomputation**. * Percentages are shown with **one decimal** (round-half-up once; no chained rounding). * Fonts/assets are bundled or offline; **no remote requests** at render time. --- ## Troubleshooting * **CRLF on Windows**: configure Git with LF policy (repo includes `.gitattributes`); avoid CRLF. ``` git config core.autocrlf false ``` * **First build without `vendor/`**: Cargo is offline by default. Temporarily fetch, then restore offline: ```bash CARGO_NET_OFFLINE=0 cargo fetch # optionally: cargo vendor && commit vendor/ ``` * **RNG seed**: Provide as an integer or hex string. If **no random tie occurs**, changing the seed **must not** change outputs. * **Manifest inputs**: Each run must provide **exactly one** of: *ballots* **or** *precomputed tally*. Missing/extra → validation error. * **jq not installed**: Use byte comparison (`cmp`/`fc`) or Python: ```bash python - <<'PY' ``` import sys, json a=json.load(open('artifacts/run1/result.json')); b=json.load(open('artifacts/run2/result.json')) print(a==b) PY ``` --- ## License & security - License: see **`LICENSE`**. - Security: see **`SECURITY.md`**. No telemetry. No bug bounty. --- ## Contributing Use `pre-commit` if installed (`.pre-commit-config.yaml` provides fast local gates). Submit PRs that reference the relevant sections of **Docs 1–7** and **Annex A/B**. --- ``` ================================================================================================ FILE: SECURITY.md AUTHORITY: reference CONTENT_ROLE: knowledge CONTENT_SHA256: cd7353ea42a1038e648ad4eb8aa7b4e29215ea8b29afea33cac558e90e9daa73 CONTENT_BYTES: 6708 ================================================================================================ ````markdown # SECURITY.md — VM-ENGINE v0 _Component 12/89 • Threat model, reporting, and hard guarantees_ ## 1) Disclosure policy **Where to report** - Email: **** (replace before publishing) - Optional PGP: publish a key in `SECURITY-KEYS.md` and on a public keyserver. Include fingerprint in PR. **What to include** - Affected version/commit SHA, OS/arch, minimal repro manifest/inputs, observed/expected behavior, crash logs (if any), and whether the issue is already public. **Coordinated disclosure** - Acknowledge within **3 business days**. - Initial triage/classification within **7 business days**. - Target fix window **≤ 90 days** from acknowledgment for High/Critical, sooner if exploitation is likely. - No public PoCs or details before a fix is available (unless mutually agreed). We will issue a security release and notes. > If the report concerns a third-party dependency, we may forward relevant details to upstream under similar timelines. --- ## 2) Supported versions - We provide security fixes for the **latest tagged release** and the **main branch**. - Older tags are **EOL** unless explicitly listed in `docs/release_policy.md`. --- ## 3) Threat model (high-level) **In scope** - **Malicious or malformed local inputs** (manifests, ballots, tallies, adjacency/frontier files). - **Path traversal / symlink abuse** via user-provided paths. - **Schema bypass / validation gaps**, including unknown fields when strict mode is enabled. - **Report rendering safety** (HTML/JSON output escaping; no active content). - **Tie-break RNG misuse** (seed handling, recording). - **Determinism breakage** (non-canonical serialization, nondeterministic iteration). - **Supply-chain drift** (toolchain/deps moving under us). **Out of scope** - **Network adversaries at runtime**: the engine is **offline** by design (no network I/O). - **Multi-tenant sandboxing**: CLI is single-user; do not execute untrusted code inside the same process. - **Untrusted plugin execution**: none supported. --- ## 4) Hard guarantees (must hold) - **No network I/O** at runtime. Builds/tests run with `--locked`; default Cargo mode is **offline**. - **Canonical JSON** everywhere: **UTF-8**, **LF** line endings, **sorted object keys**; arrays use spec-defined order. - **Deterministic math**: integer/rational comparisons; no floating-point in outcome logic. - **Ties**: policy-driven. When `tie_policy=random` is configured, use a provided **seed**; record it in `RunRecord` **only if** a random tie actually occurred. Changing the seed without a random tie must not change outputs. - **Byte-identical artifacts** across OS/arch for the same inputs (+seed): `result.json` (RES), `run_record.json` (RUN), optional `frontier_map.json` (FR). --- ## 5) Operator guidance (secure-by-default) - Run with **read-only inputs** and a **separate output directory**: ```bash ./target/release/vm_cli run --manifest /manifest.json --output artifacts/run ```` * Use **locked** dependency resolution: ```bash cargo build --locked cargo test --locked ``` * Keep Cargo **offline** by default; vendor dependencies if needed: ```bash # initial fetch only CARGO_NET_OFFLINE=0 cargo fetch # optional: cargo vendor (ensure vendor/ is tracked) ``` * When `tie_policy=random`, **provide a seed** and retain `run_record.json` for auditability. --- ## 6) Input handling & validation * Enforce **JSON Schema** validation first; fail closed on malformed documents. * Cross-validate invariants per spec (e.g., entity trees, tally magnitudes, unique IDs). * Reject **symlinks** and `..` path traversal in manifest-referenced files; resolve to **canonical paths** before opening. * Apply **maximum file size** and **object depth** guards to prevent DoS (configure in loader; fail fast with clear errors). * Optionally enable **strict mode** to reject unknown fields when required by the spec. --- ## 7) Report rendering safety * Reports are **self-contained**: no remote fonts, scripts, or tiles. * Escape **all** user-derived strings; sanitize HTML where rich text is allowed. * If viewed inside the app, enforce a restrictive **Content-Security-Policy** and disable inline scripts. --- ## 8) Build & supply chain * Pin the toolchain in `rust-toolchain.toml`; use **resolver = "2"** and **--locked** to prevent drift. * Prefer checked-in **vendor/** for air-gapped builds; keep upstream **LICENSE/NOTICE** files. * Release archives in `dist/` should be **signed** and accompanied by **SHA-256** checksums. Provide verification steps in release notes. * Review third-party licenses; avoid dynamic code downloads at build/test time. --- ## 9) Security testing * **Fuzz** parsers/loaders for manifests, ballots, tallies, and schemas (structured fuzzing). * Run `cargo audit` / `cargo deny`; treat advisories seriously. * Keep `clippy` clean with `-D warnings`. * **Determinism test** (must pass): ```bash SEED=42 ./target/release/vm_cli run --manifest fixtures/annex_b/VM-TST-001/manifest.json --rng-seed $SEED --output artifacts/a ./target/release/vm_cli run --manifest fixtures/annex_b/VM-TST-001/manifest.json --rng-seed $SEED --output artifacts/b cmp -s artifacts/a/result.json artifacts/b/result.json cmp -s artifacts/a/run_record.json artifacts/b/run_record.json ``` --- ## 10) Contact & acknowledgments * Primary: **[security@your-domain.example](mailto:security@your-domain.example)** * Please include whether you want public credit after resolution. We maintain an optional **Hall of Thanks** in release notes. * CVEs: if applicable, we can request an ID after triage. --- ## 11) Process (state flow) 1. Reporter sends details via email/PGP. 2. We acknowledge (≤ 3 business days) and triage (≤ 7 business days). 3. Fix developed on supported branches; drafts shared privately if needed. 4. Security release cut; checksums/signatures published; coordinated disclosure. --- ## 12) Determinism & numeric rules (restated) * No floats for comparisons; round-half-to-even only at defined points; reporting rounds **once** to **one decimal**. * Seeded RNG only for random ties; seed recorded in `RunRecord` **iff** used. * Hashes/IDs computed over **canonical bytes**. --- ## 13) Edge cases → fail with explicit error * `tie_policy=random` **without** a seed. * Mixed **CRLF/LF** or unsorted JSON in canonical inputs. * Inputs exceeding configured **size/depth** limits. --- ## 14) Self-checks (operator) * **Air-gap** or firewall the host; confirm zero network connections during runs. * Reproduce the **determinism test** above. * Verify release **signatures/checksums** before deployment. ``` ```