diff --git a/RSR-PHILOSOPHY.adoc b/RSR-PHILOSOPHY.adoc index 020250482..9ebdf9008 100644 --- a/RSR-PHILOSOPHY.adoc +++ b/RSR-PHILOSOPHY.adoc @@ -5,11 +5,14 @@ :icons: font [.lead] -This is the *canonical* statement of the operating principles every hyperpolymath -repository is worked under. It is the source that `rsr-template-repo` operationalises -and that the estate arrival-pack projects, in summary form, into the top of every -`CLAUDE.md`. The owner's `manifesto` states the same doctrine in its own voice; -where wording must be reconciled, the manifesto prevails. +This is the *canonical* statement of the ratified operating principles every +hyperpolymath repository is worked under. It is the source that +`rsr-template-repo` operationalises and that the estate arrival-pack projects, in +summary form, into the top of every `CLAUDE.md`. The owner's `manifesto` states the +same doctrine in its own voice; where wording must be reconciled, the manifesto +prevails. The _Elegance by default_ section below is an explicitly non-canonical +proposal and is excluded from that projection until its recorded ratification is +complete. Material explicitly marked *PROVISIONAL* is a proposal within this otherwise canonical document. It is not operating doctrine and must not be projected into @@ -45,9 +48,12 @@ own, a change gated on owner ratification — remediate the downstream *and* rec the source fix as the real work still owed. Silently patching the symptom as if it were the cure is itself a soundness hole (see _fail loudly_). -This principle stands beside its two canonical siblings: *holes before goals* and -*always fail loudly*. A proposed fourth principle, *elegance by default*, is recorded -below pending ratification. +This principle stands beside its two ratified siblings: *holes before goals* and +*always fail loudly*. Together they govern the order of work (holes first), the +manner of work (loudly, never silently green), and the locus of work (at the source, +never the symptom). A proposed fourth principle, *elegance by default*, follows; +it has no canonical force unless and until the proposal record shows completed +ratification. == Holes before goals @@ -66,16 +72,17 @@ not assumed. Prefer a build that breaks to a build that lies. [IMPORTANT] ==== -*Status: PROVISIONAL — not canonical policy.* - -* Owner decision: pending; the 2026-09-14 instruction authorised this proposal, - but no completed ratification decision is recorded. -* Dissent: not yet recorded. -* Effective version/hash: none. - -Before this principle becomes canonical or is propagated into `CLAUDE.md`, the -ratification record must replace all three pending values with the owner decision, -recorded dissent (including an explicit `none`), and an effective version or hash. +*Proposal status — not canonical.* + +* *Owner decision:* Pending ratification. The 2026-09-14 owner instruction + authorised drafting this proposal, not its adoption as permanent policy. +* *Dissent:* Pending the required contest and review period; no completed dissent + record exists yet. +* *Effective version/hash:* Not assigned. +* *Propagation:* This principle MUST NOT be treated as canonical or added to the + estate-common `CLAUDE.md` policy until the owner decision, dissent, effective + version/hash, superseded material, and migration limits are recorded under + `constitution/CHANGE-PROCEDURE.adoc`. ==== *Treat the most elegant and correct long-term solution as the default choice — and say @@ -90,12 +97,13 @@ justified by the construction that produced it. Three obligations follow, and none is optional: -. *Label it.* Mark exactly one option as the elegant and correct long-term arm unless - options genuinely tie. In a genuine tie, mark every tied option with the exact label - `Elegant-arm tie`; do not give that label to an option outside the tie. Elegance is - judged on long-run grounds alone — correctness, no deferred breakage, no special - cases, fixing the generator rather than the instance — and never on effort, speed, or - convenience. A tie must be stated with the label; silence is not a tie. +. *Label it.* When there is one elegant and correct long-term arm, mark exactly that + option *Elegant arm*. If two or more options genuinely tie, mark every tied option + *Elegant arm (tie)* and state explicitly that they are co-equal on the long-run + criteria; do not give any tied option the unqualified label. Elegance is judged on + long-run grounds alone — correctness, no deferred breakage, no special cases, fixing + the generator rather than the instance — and never on effort, speed, or convenience. + A close call is not a tie, and silence is never a tie. . *Justify any departure.* A recommendation that is not the elegant arm must name both arms and state, in the offer itself, why the departure is made on this occasion — an irreversible step already taken, a live outage, a precondition still gated. An @@ -113,13 +121,14 @@ in ignorance that it was the expedient one. The complete, always-current operating Doctrine is maintained as estate-common content in the arrival-pack and projected into every repository's `CLAUDE.md`. In -addition to the three canonical principles above it holds: ground-truth by running the tool, -not trusting status docs; distrust the neural for exactness (licences, invariants, -equivalence belong to PLASMA, not an LLM); squabble, don't bypass (reach green by -satisfying the gate, never by admin-override); no automated licence edits; no -deletion by access-recency; wire first; always sign; report faithfully (no -overclaim); stop-first on costly or outward-facing actions; boundaries are real; -and equivalence as identity. +addition to the three ratified principles above it holds: ground-truth by running +the tool, not trusting status docs; distrust the neural for exactness (licences, +invariants, equivalence belong to PLASMA, not an LLM); squabble, don't bypass +(reach green by satisfying the gate, never by admin-override); no automated +licence edits; no deletion by access-recency; wire first; always sign; report +faithfully (no overclaim); stop-first on costly or outward-facing actions; +boundaries are real; and equivalence as identity. _Elegance by default_ joins +this list only after the proposal record above is complete. == See also diff --git a/docs/DEBTFILE-SPEC.adoc b/docs/DEBTFILE-SPEC.adoc index 7cc8239e2..9b2661157 100644 --- a/docs/DEBTFILE-SPEC.adoc +++ b/docs/DEBTFILE-SPEC.adoc @@ -105,15 +105,19 @@ Location: `.machine_readable/Debtfile.a2ml`, one per repository. - policy: remediable | flag-only - tri: eliminate | substitute | control (optional, Safety Triangle) - tracking: (optional) -- taxonomy-default-arm: (required for a taxonomy choice) -- taxonomy-selected-arm: (required for a taxonomy choice) -- taxonomy-departure-reason: - (required for a taxonomy choice) +- taxonomy-choice: non-default (required for a testing-taxonomy departure) +- taxonomy-default-arm: +- taxonomy-non-default-arm: +- taxonomy-departure-reason: - accepted-until: YYYY-MM-DD ---- `##
` headings group entries and are otherwise ignored. +The four `taxonomy-*` fields are required together only when an entry records a +departure under `testing-and-benchmarking/TESTING-TAXONOMY.adoc`; otherwise omit +all four. + === Fields `probe`:: A shell command emitting one non-negative integer on stdout. This is @@ -154,6 +158,23 @@ fields continue to describe the debt and point to its external work item. holding under its ceiling. Debt without an expiry is debt nobody revisits — the 697-issue pile is what that looks like. +[[testing-taxonomy-choice]] +=== Testing-taxonomy choice encoding + +A Debtfile entry that tolerates the non-default arm of a testing-taxonomy choice +MUST use the dedicated `taxonomy-*` fields shown above. `taxonomy-choice` is the +literal `non-default`; `taxonomy-default-arm` names the elegant, long-term-correct +arm; `taxonomy-non-default-arm` names the different arm actually chosen; and +`taxonomy-departure-reason` states why that departure is being tolerated now. + +These values MUST NOT be hidden in `description` or `tracking`: those fields +describe the debt and point to its work item, respectively, and neither identifies +the rejected arm unambiguously. The structural validator rejects a partial choice +record, an unknown `taxonomy-choice` value, empty arm or reason values, and identical +default and non-default arms. The runner does not interpret this governance +metadata; its `--write` pass preserves it unchanged while updating only `count` and +`ceiling`. + [[probe-discipline]] == Probe discipline diff --git a/scripts/check-debtfile-structure.sh b/scripts/check-debtfile-structure.sh index bd5e7a2ba..bbfac55df 100755 --- a/scripts/check-debtfile-structure.sh +++ b/scripts/check-debtfile-structure.sh @@ -45,8 +45,7 @@ entries=0 seen_ids=" " name="" probe="" count="" ceiling="" severity="" policy="" accepted="" -taxonomy_default="" taxonomy_selected="" taxonomy_reason="" -taxonomy_default_seen=0 taxonomy_selected_seen=0 taxonomy_reason_seen=0 +taxonomy_seen=0 taxonomy_choice="" taxonomy_default="" taxonomy_non_default="" taxonomy_reason="" note() { printf ' %s\n' "$*"; } bad() { printf ' ❌ %s\n' "$*"; fail=1; } @@ -93,28 +92,17 @@ validate() { *) bad "'$name' policy '$policy' is not one of remediable|flag-only" ;; esac - if [ "$taxonomy_default_seen" -ne 0 ] || [ "$taxonomy_selected_seen" -ne 0 ] || [ "$taxonomy_reason_seen" -ne 0 ]; then - if [ "$taxonomy_default_seen" -eq 0 ] || [ -z "$taxonomy_default" ]; then - bad "'$name' has a partial taxonomy choice: missing '- taxonomy-default-arm:'" - fi - if [ "$taxonomy_selected_seen" -eq 0 ] || [ -z "$taxonomy_selected" ]; then - bad "'$name' has a partial taxonomy choice: missing '- taxonomy-selected-arm:'" - fi - if [ "$taxonomy_reason_seen" -eq 0 ] || ! has_nonspace "$taxonomy_reason"; then - bad "'$name' has a partial taxonomy choice: missing '- taxonomy-departure-reason:'" - fi - - case "$taxonomy_default" in - ''|*[!a-z0-9._-]*|[!a-z0-9]*) - [ -n "$taxonomy_default" ] && bad "'$name' taxonomy-default-arm '$taxonomy_default' is not a stable arm id" ;; - esac - case "$taxonomy_selected" in - ''|*[!a-z0-9._-]*|[!a-z0-9]*) - [ -n "$taxonomy_selected" ] && bad "'$name' taxonomy-selected-arm '$taxonomy_selected' is not a stable arm id" ;; + if [ "$taxonomy_seen" -ne 0 ]; then + case "$taxonomy_choice" in + non-default) ;; + '') bad "'$name' has taxonomy choice fields but no '- taxonomy-choice: non-default'" ;; + *) bad "'$name' taxonomy-choice '$taxonomy_choice' is not 'non-default'" ;; esac - - if [ -n "$taxonomy_default" ] && [ "$taxonomy_default" = "$taxonomy_selected" ]; then - bad "'$name' taxonomy-selected-arm must differ from taxonomy-default-arm when recording a departure" + [ -n "$taxonomy_default" ] || bad "'$name' has no '- taxonomy-default-arm:'" + [ -n "$taxonomy_non_default" ] || bad "'$name' has no '- taxonomy-non-default-arm:'" + [ -n "$taxonomy_reason" ] || bad "'$name' has no '- taxonomy-departure-reason:'" + if [ -n "$taxonomy_default" ] && [ "$taxonomy_default" = "$taxonomy_non_default" ]; then + bad "'$name' taxonomy-default-arm and taxonomy-non-default-arm must name different arms" fi fi @@ -130,8 +118,7 @@ validate() { reset_block() { name="$1"; probe=""; count=""; ceiling=""; severity=""; policy=""; accepted="" - taxonomy_default=""; taxonomy_selected=""; taxonomy_reason="" - taxonomy_default_seen=0; taxonomy_selected_seen=0; taxonomy_reason_seen=0 + taxonomy_seen=0; taxonomy_choice=""; taxonomy_default=""; taxonomy_non_default=""; taxonomy_reason="" } while IFS= read -r raw || [ -n "$raw" ]; do @@ -143,21 +130,14 @@ while IFS= read -r raw || [ -n "$raw" ]; do '- ceiling: '*) ceiling="${line#- ceiling: }" ;; '- severity: '*) severity="${line#- severity: }" ;; '- policy: '*) policy="${line#- policy: }" ;; + '- taxonomy-choice:'*) + taxonomy_seen=1; taxonomy_choice="${line#- taxonomy-choice:}"; taxonomy_choice="${taxonomy_choice# }" ;; '- taxonomy-default-arm:'*) - [ "$taxonomy_default_seen" -eq 0 ] || bad "'$name' repeats '- taxonomy-default-arm:'" - taxonomy_default_seen=1 - taxonomy_default="${line#- taxonomy-default-arm:}" - taxonomy_default="${taxonomy_default# }" ;; - '- taxonomy-selected-arm:'*) - [ "$taxonomy_selected_seen" -eq 0 ] || bad "'$name' repeats '- taxonomy-selected-arm:'" - taxonomy_selected_seen=1 - taxonomy_selected="${line#- taxonomy-selected-arm:}" - taxonomy_selected="${taxonomy_selected# }" ;; + taxonomy_seen=1; taxonomy_default="${line#- taxonomy-default-arm:}"; taxonomy_default="${taxonomy_default# }" ;; + '- taxonomy-non-default-arm:'*) + taxonomy_seen=1; taxonomy_non_default="${line#- taxonomy-non-default-arm:}"; taxonomy_non_default="${taxonomy_non_default# }" ;; '- taxonomy-departure-reason:'*) - [ "$taxonomy_reason_seen" -eq 0 ] || bad "'$name' repeats '- taxonomy-departure-reason:'" - taxonomy_reason_seen=1 - taxonomy_reason="${line#- taxonomy-departure-reason:}" - taxonomy_reason="${taxonomy_reason# }" ;; + taxonomy_seen=1; taxonomy_reason="${line#- taxonomy-departure-reason:}"; taxonomy_reason="${taxonomy_reason# }" ;; '- accepted-until: '*) accepted="${line#- accepted-until: }" ;; esac done < "$DEBT" diff --git a/scripts/tests/debtfile-structure-test.sh b/scripts/tests/debtfile-structure-test.sh index a38dee391..d9e078759 100755 --- a/scripts/tests/debtfile-structure-test.sh +++ b/scripts/tests/debtfile-structure-test.sh @@ -144,6 +144,65 @@ expect 0 "count below ceiling is fine (debt paid down, ceiling not yet lowered)" - accepted-until: 2030-01-01 EOF +expect 0 "a complete testing-taxonomy departure records both arms and its reason" <<'EOF' +### alpha +- description: a temporary local test is tolerated +- probe: echo 2 +- count: 2 +- ceiling: 4 +- severity: high +- policy: remediable +- taxonomy-choice: non-default +- taxonomy-default-arm: adapt the proven Idris2 test +- taxonomy-non-default-arm: retain the temporary local test +- taxonomy-departure-reason: upstream fixture is gated on the next release +- accepted-until: 2030-01-01 +EOF + +expect 1 "a partial testing-taxonomy choice record is rejected" <<'EOF' +### alpha +- description: a temporary local test is tolerated +- probe: echo 2 +- count: 2 +- ceiling: 4 +- severity: high +- policy: remediable +- taxonomy-choice: non-default +- taxonomy-default-arm: adapt the proven Idris2 test +- taxonomy-non-default-arm: retain the temporary local test +- accepted-until: 2030-01-01 +EOF + +expect 1 "testing-taxonomy default and non-default arms must differ" <<'EOF' +### alpha +- description: a temporary local test is tolerated +- probe: echo 2 +- count: 2 +- ceiling: 4 +- severity: high +- policy: remediable +- taxonomy-choice: non-default +- taxonomy-default-arm: retain the local test +- taxonomy-non-default-arm: retain the local test +- taxonomy-departure-reason: no actual departure was named +- accepted-until: 2030-01-01 +EOF + +expect 1 "an unknown taxonomy-choice selector is rejected" <<'EOF' +### alpha +- description: a temporary local test is tolerated +- probe: echo 2 +- count: 2 +- ceiling: 4 +- severity: high +- policy: remediable +- taxonomy-choice: convenient +- taxonomy-default-arm: adapt the proven Idris2 test +- taxonomy-non-default-arm: retain the temporary local test +- taxonomy-departure-reason: upstream fixture is gated on the next release +- accepted-until: 2030-01-01 +EOF + expect 1 "a non-integer count is rejected" <<'EOF' ### alpha - description: d diff --git a/scripts/tests/run-debtfile-test.sh b/scripts/tests/run-debtfile-test.sh index f14a6f124..e1887da32 100755 --- a/scripts/tests/run-debtfile-test.sh +++ b/scripts/tests/run-debtfile-test.sh @@ -87,6 +87,25 @@ else fail=$((fail+1)); echo " FAIL --write did not ratchet down"; sed -n '1,20p' Debtfile.a2ml fi +# Governance metadata validated by check-debtfile-structure.sh is opaque to the +# runner and must survive its targeted count/ceiling rewrite unchanged. +entry 'echo 2' 4 4 > Debtfile.a2ml +cat >> Debtfile.a2ml <<'EOF' +- taxonomy-choice: non-default +- taxonomy-default-arm: adapt the proven Idris2 test +- taxonomy-non-default-arm: retain the temporary local test +- taxonomy-departure-reason: upstream fixture is gated on the next release +EOF +bash "$SCRIPT" --write Debtfile.a2ml >/dev/null 2>&1 || true +if grep -q '^- taxonomy-choice: non-default$' Debtfile.a2ml \ + && grep -q '^- taxonomy-default-arm: adapt the proven Idris2 test$' Debtfile.a2ml \ + && grep -q '^- taxonomy-non-default-arm: retain the temporary local test$' Debtfile.a2ml \ + && grep -q '^- taxonomy-departure-reason: upstream fixture is gated on the next release$' Debtfile.a2ml; then + pass=$((pass+1)); echo " ok --write preserves testing-taxonomy choice metadata" +else + fail=$((fail+1)); echo " FAIL --write changed testing-taxonomy choice metadata"; sed -n '1,24p' Debtfile.a2ml +fi + entry 'echo 9' 4 4 > Debtfile.a2ml bash "$SCRIPT" --write Debtfile.a2ml >/dev/null 2>&1 || true if grep -q '^- ceiling: 4$' Debtfile.a2ml; then diff --git a/testing-and-benchmarking/TESTING-TAXONOMY.adoc b/testing-and-benchmarking/TESTING-TAXONOMY.adoc index e94dc061a..9d08cebad 100644 --- a/testing-and-benchmarking/TESTING-TAXONOMY.adoc +++ b/testing-and-benchmarking/TESTING-TAXONOMY.adoc @@ -81,12 +81,13 @@ owner. Judge elegance on long-run grounds only: correctness, absence of deferred breakage, no special cases, and a fix at the generator rather than at the instance. Never on how quickly a category can be marked satisfied. Where the other arm is taken, record both -arms and the reason for departing — using `taxonomy-default-arm`, -`taxonomy-selected-arm`, and `taxonomy-departure-reason` in the `Debtfile` where a -shortfall is being tolerated, and in the N/A justification where the category is -being declined. An -unlabelled choice between a sound test and a convenient one is how a suite quietly -becomes evidence for something nobody checked. +arms and the reason for departing — in the `Debtfile` where a shortfall is being +tolerated, using the required `taxonomy-choice`, `taxonomy-default-arm`, +`taxonomy-non-default-arm`, and `taxonomy-departure-reason` encoding defined in +link:../docs/DEBTFILE-SPEC.adoc#testing-taxonomy-choice[Debtfile Specification: +Testing-taxonomy choice encoding]; or in the N/A justification where the category +is being declined. An unlabelled choice between a sound test and a convenient one is +how a suite quietly becomes evidence for something nobody checked. This is the proposed estate doctrine _elegance by default_ applied to testing; it remains provisional until the ratification record in