Skip to content

Commit 830b0f6

Browse files
Estate audit — Waves 5 + 6: per-language testing standard, canonical-names guard, DYADT residual fix (#459)
Two cohesive commits closing out the estate audit-and-optimization program (umbrella #460). Both fully tested; generated artifacts in sync. ## Commit 1 — Wave 5: per-language testing depth You flagged this directly: the estate's only per-language testing *depth* was a single Julia guide from **2024** (no MUST/SHOULD, Rust+Julia only) next to a **byte-identical duplicate**. - `language-testing-standards.md` → **v2.0.0**: RFC-2119 requirements **R1–R9** mapped to the CRG test taxonomy; an anti-theatre rule (no `continue-on-error` on a MUST check; coverage reported-with-artifact, not asserted). - `templates/language-testing-guide-TEMPLATE.md`: the skeleton every guide follows — requirement-mapping table (tool or **visible** `none`), tools, SHA-pinned CI, and a **mandatory honest "Known gaps"** section. - `affinescript-testing-guide.md`: your primary language, previously with **zero** testing standard — authored honestly (most SHOULD rows are tracked gaps; R3 notes `affinescript-verify.yml` is advisory). SSOT migrates to `hyperpolymath/affinescript` prospectively. - `scripts/check-language-guide.sh` (wired into `just validate`) + `wave5-language-guides-test.sh` (7/7). Deleted the duplicate snapshot. ## Commit 2 — Wave 6: guard, DYADT residual fix, licence record - **DYADT residual (#461):** an adversarial review confirmed 16 bypasses in the Wave-4 verifier; 15 were fixed in #458, and this closes the last — an always-matching `contains:` regex (`.*`, `^`, `$`, …) no longer confirms vacuously (`unverifiable trivial-pattern`). Spec pins the `contains:` dialect to POSIX ERE; conformance vector + assertion added (10 vectors, 15 assertions). - **Canonical-names guard** (`check-canonical-names.sh`): blocks *reintroduction* of the deprecated names (`6a2`→descriptiles, `agent_instructions`→bot_directives) in **added** diff lines only (chartered bulk migration untouched). Wired into `just validate` + the pre-commit hook; `wave6-canonical-names-test.sh` (4/4). - **`audits/licence-flags-2026-07.adoc`**: flag-only record — the whole program made no SPDX edits and no auto licence PRs; DYADT treats licence claims as `manual-only` end to end. ## Verification All six wave suites pass; DYADT conformance 10/10 + dogfood all-confirmed; registry + scorecard dashboard in sync. ## Program status (umbrella #460) Waves 0/1/3/4 + hardening **merged** (#453, #454, #457, #458). This lands Waves 5 + 6. Remaining estate-wide work is chartered: #461 (verifier residual — **fixed here**), #462 (DYADT production verifier), #463 (per-language guides completion). Licence rows `manual-only` throughout (flag-only policy). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0d76543 commit 830b0f6

17 files changed

Lines changed: 596 additions & 316 deletions

.machine_readable/REGISTRY.a2ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ name = "DYADT — Did-You-Actually-Do-That"
234234
stream = "governance"
235235
home = "did-you-actually-do-that/"
236236
canonical_doc = "did-you-actually-do-that/README.adoc"
237-
source_hash = "sha256:2ae635b9ede51e76781cb7c171108f2a4505b0aae9ac97fb05c910915141eb2a"
237+
source_hash = "sha256:453bf00d0dfac71576b5e7b4068fb8987abc3337d4bc3bf75c081e0332ae1dff"
238238
route = "post-action agent-claim verification (Tier 4 accountability)"
239239

240240
[[spec]]

Justfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,24 @@ dyadt-conformance:
8585
dyadt-test:
8686
@bash scripts/tests/wave4-dyadt-test.sh
8787

88+
# Structural lint for per-language testing guides (required sections + R1..R9)
89+
language-guides-check:
90+
@bash scripts/check-language-guide.sh
91+
92+
# Block reintroduction of deprecated names (6a2, agent_instructions) in new diff
93+
canonical-names-check base="origin/main":
94+
@bash scripts/check-canonical-names.sh "{{base}}"
95+
8896
# Aggregate compliance gate: registry drift is the HARD gate (registry-check,
8997
# a hard dep). The RSR self-audit is INFORMATIONAL — a monorepo is not expected
9098
# to score Gold — but a *broken* audit (exit 4 / unexpected) must fail loudly
9199
# rather than pass silently under a blanket `|| true` (Wave-0 false-green fix).
92100
validate: registry-check
93101
@echo "=== validate: registry drift (HARD GATE) — passed as a dependency above ==="
102+
@echo "=== validate: per-language testing guides (structural, HARD GATE) ==="
103+
@bash scripts/check-language-guide.sh
104+
@echo "=== validate: canonical-names reintroduction guard (vs origin/main) ==="
105+
@bash scripts/check-canonical-names.sh origin/main || bash scripts/check-canonical-names.sh HEAD
94106
@echo "=== validate: RSR self-audit (INFORMATIONAL grade; errors fail loudly) ==="
95107
@bash scripts/rsr-selfaudit.sh .
96108
@echo "=== validate: done ==="

audits/licence-flags-2026-07.adoc

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// SPDX-License-Identifier: CC-BY-SA-4.0
2+
// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3+
= Licence Flags — Estate Audit & Optimization (2026-07)
4+
:icons: font
5+
6+
[.lead]
7+
Flag-only record for the estate audit-and-optimization program (umbrella
8+
`hyperpolymath/standards#460`). Per the Manual-Only licence policy
9+
(`.claude/CLAUDE.md`), this program made **no** licence/SPDX edits and generated
10+
**no** automated licence-change PRs. This document records that discipline and
11+
flags — for owner review only — anything licence-adjacent that surfaced.
12+
13+
== Discipline upheld
14+
15+
* No SPDX headers were added, changed, or swept in any wave (0, 1, 3, 4, 5, 6).
16+
* New files created by the program carry the SPDX identifier matching the
17+
repo's classification at birth (authoring, not relicensing): scripts →
18+
`MPL-2.0`, prose/specs → `CC-BY-SA-4.0`. This is consistent with the estate
19+
policy that new files may carry the correct SPDX from birth.
20+
* The DYADT verifier (`did-you-actually-do-that/`) treats any licence/SPDX claim
21+
as `manual-only` end to end — it returns `unverifiable`, never auto-`confirmed`,
22+
and the consequence ledger's confirmation rate is explicitly unaffected by
23+
licence verdicts. The Manual-Only policy is preserved *by construction* in the
24+
new tooling.
25+
26+
== Flags for owner review (no action taken)
27+
28+
None of the following were edited; they are surfaced for the owner to rule on.
29+
30+
[cols="1,3", options="header"]
31+
|===
32+
| Location | Observation (flag-only)
33+
34+
| `rhodium-standard-repositories/rsr-audit.sh`
35+
| Header carries a dual `SPDX-License-Identifier: MPL-2.0 AND Palimpsest-0.8`.
36+
Palimpsest is a carve-out family; whether this file should carry a
37+
Palimpsest component is an owner ruling, not an audit action. Left untouched.
38+
39+
| `SECURITY-ADVISORIES.adoc`
40+
| A standing deferred `rand < 0.9.3` advisory is recorded. Not a licence matter,
41+
but flagged alongside release hygiene: renew with an expiry date or bump.
42+
(Tracked under the umbrella's release-hygiene item.)
43+
|===
44+
45+
== No sweep, no auto-PR
46+
47+
This program did not run, and must not be read as licensing, any bulk SPDX
48+
normalisation. Licence drift findings remain FLAG-ONLY and owner-gated, per the
49+
neurophone#99 precedent and the estate licence-policy umbrella.

did-you-actually-do-that/spec/CLAIM-FORMAT.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ A verifier MUST reject (`unverifiable`) a claim whose `verifier` is not listed
106106
as compatible with its `claim_class` in VERIFICATION-PROTOCOL — an
107107
agent MUST NOT be able to choose a weaker verifier than the claim class warrants.
108108

109+
=== `contains:` regex dialect (normative)
110+
111+
The `contains:<regex>` predicate uses **POSIX Extended Regular Expressions
112+
(ERE)**, matched case-sensitively against the whole file (`grep -E`). A pattern
113+
that contains no literal character — i.e. is trivially always-matching (`.*`,
114+
`.`, `^`, `$`, `.+`, and the like) — is NOT evidence and MUST be rejected as
115+
`unverifiable` (reason `trivial-pattern`); it would otherwise confirm any
116+
non-empty file. `stdout-contains:<s>` is a fixed-string (non-regex) substring
117+
match.
118+
109119
== Honesty constraints (normative)
110120

111121
. A claim's verdict MUST be derived from primary evidence re-collected by the
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[claims]
2+
schema = "dyadt/claim@1"
3+
actor = "conformance"
4+
[[claim]]
5+
id = "C1"
6+
claim_class = "file-changed"
7+
statement = "a vacuous always-matching contains pattern"
8+
target = "README.adoc"
9+
expect = "contains:.*"
10+
verifier = "git-diff"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
C1 unverifiable

hooks/pre-commit

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,17 @@ if [ -f scripts/build-registry.sh ]; then
9191
fi
9292
fi
9393

94+
# Canonical-names guard: block reintroduction of the deprecated names listed in
95+
# CANONICAL-NAMES.adoc within the staged diff. Only added lines are checked, so
96+
# not-yet-migrated existing occurrences do not trip it.
97+
if [ -f scripts/check-canonical-names.sh ]; then
98+
if ! bash scripts/check-canonical-names.sh HEAD >/dev/null 2>&1; then
99+
echo -e "${RED}✗ Deprecated name reintroduced (see CANONICAL-NAMES.adoc):${NC}"
100+
bash scripts/check-canonical-names.sh HEAD 2>&1 | grep '' || true
101+
ERRORS=$((ERRORS + 1))
102+
fi
103+
fi
104+
94105
# Final result
95106
echo ""
96107
if [ $ERRORS -gt 0 ]; then

scripts/check-canonical-names.sh

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
#
4+
# check-canonical-names.sh — block REINTRODUCTION of deprecated names.
5+
#
6+
# CANONICAL-NAMES.adoc (owner mandate 2026-06-30) deprecates:
7+
# * 6a2 -> descriptiles
8+
# * agent_instructions -> bot_directives
9+
# The bulk migration of existing occurrences is chartered separately; this guard
10+
# stops NEW occurrences from landing in the meantime. It inspects only the
11+
# ADDED lines of a diff (grandfathered existing text is untouched), so it can be
12+
# wired into pre-commit and CI without tripping on the not-yet-migrated files.
13+
#
14+
# Usage: check-canonical-names.sh [base-ref]
15+
# base-ref default: origin/main (CI) then HEAD (pre-commit staged diff).
16+
# Exit: 0 no new deprecated tokens · 1 a deprecated token was added · 2 usage
17+
18+
set -uo pipefail
19+
cd "$(git rev-parse --show-toplevel)"
20+
21+
BASE="${1:-}"
22+
if [ -z "$BASE" ]; then
23+
if git rev-parse --verify -q origin/main >/dev/null 2>&1; then BASE="origin/main"; else BASE="HEAD"; fi
24+
fi
25+
26+
# Deprecated token -> canonical replacement (for the error message).
27+
declare -A REPL=( ["6a2"]="descriptiles" ["agent_instructions"]="bot_directives" )
28+
29+
# Files that legitimately NAME the deprecated tokens (the mandate itself, this
30+
# guard, migration/charter docs). Excluded from the check.
31+
is_excluded() {
32+
case "$1" in
33+
CANONICAL-NAMES.adoc|scripts/check-canonical-names.sh|scripts/tests/*|\
34+
*MIGRATION*|*migration*|*CHANGELOG*|*/6a2/*|.machine_readable/6a2/*) return 0 ;;
35+
esac
36+
return 1
37+
}
38+
39+
# Added lines in the working diff vs BASE, per file.
40+
added_diff() { git diff "$BASE" -- . 2>/dev/null; }
41+
42+
rc=0
43+
current_file=""
44+
while IFS= read -r line; do
45+
case "$line" in
46+
"+++ b/"*) current_file="${line#+++ b/}" ;;
47+
"+"*)
48+
is_excluded "$current_file" && continue
49+
body="${line#+}"
50+
# Skip a line that is DESCRIBING the deprecation rather than using the old
51+
# name — it also mentions the canonical replacement or the mandate itself
52+
# (e.g. tooling comments, this guard's own wiring, docs about the rename).
53+
if printf '%s' "$body" | grep -Eqi 'deprecat|canonical|reintroduc|descriptiles|bot_directives'; then
54+
continue
55+
fi
56+
for tok in "${!REPL[@]}"; do
57+
# word-ish boundary so e.g. 'v6a2ml' style false hits are limited
58+
if printf '%s' "$body" | grep -Eq "(^|[^A-Za-z0-9])$tok([^A-Za-z0-9]|$)"; then
59+
echo "$current_file: reintroduces deprecated '$tok' — use '${REPL[$tok]}' (CANONICAL-NAMES.adoc)"
60+
echo " + $body"
61+
rc=1
62+
fi
63+
done ;;
64+
esac
65+
done < <(added_diff)
66+
67+
if [ "$rc" -eq 0 ]; then
68+
echo "✅ no deprecated names reintroduced (vs $BASE)"
69+
fi
70+
exit $rc

scripts/check-language-guide.sh

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
#
4+
# check-language-guide.sh — structural lint for per-language testing guides.
5+
#
6+
# Every guide built from templates/language-testing-guide-TEMPLATE.md MUST carry
7+
# the required sections and the R1–R9 requirement-mapping table. A guide that
8+
# silently omits a section (e.g. "Known gaps") is a false-completeness hole —
9+
# this fails loudly instead.
10+
#
11+
# Usage: check-language-guide.sh [guide.md ...]
12+
# With no args, checks every standards/*-testing-guide.md.
13+
# Exit: 0 all valid · 1 a guide is missing a required section
14+
15+
set -uo pipefail
16+
17+
ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
18+
19+
REQUIRED_SECTIONS=(
20+
"## Requirement mapping"
21+
"## Tools"
22+
"## Recommended CI pipeline"
23+
"## Best practices"
24+
"## Known gaps"
25+
"## Resources"
26+
)
27+
28+
check_one() { # file
29+
local f="$1" rc=0 sec
30+
if [ ! -f "$f" ]; then echo "$f: not found"; return 1; fi
31+
for sec in "${REQUIRED_SECTIONS[@]}"; do
32+
grep -Fqx "$sec" "$f" || { echo "$(basename "$f"): missing section '$sec'"; rc=1; }
33+
done
34+
# The requirement mapping MUST reference the R1..R9 rows (at least R1 and R9).
35+
grep -Eq '\bR1\b' "$f" && grep -Eq '\bR9\b' "$f" || { echo "$(basename "$f"): requirement mapping does not reference R1..R9"; rc=1; }
36+
# A SPDX header is required.
37+
head -3 "$f" | grep -q 'SPDX-License-Identifier' || { echo "$(basename "$f"): missing SPDX header"; rc=1; }
38+
[ "$rc" -eq 0 ] && echo "$(basename "$f")"
39+
return $rc
40+
}
41+
42+
if [ "$#" -gt 0 ]; then
43+
files=("$@")
44+
else
45+
mapfile -t files < <(ls "$ROOT"/standards/*-testing-guide.md 2>/dev/null)
46+
fi
47+
48+
if [ "${#files[@]}" -eq 0 ]; then
49+
echo "no language testing guides found (standards/*-testing-guide.md)"; exit 0
50+
fi
51+
52+
rc=0
53+
echo "Language testing guides:"
54+
for f in "${files[@]}"; do check_one "$f" || rc=1; done
55+
exit $rc

scripts/tests/wave4-dyadt-test.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ target = "echo marker >&2; true"
166166
expect = "stdout-contains:marker"
167167
verifier = "command-transcript"'
168168
[[ "$(reason_of "$TMP/se.a2ml" C1)" == REFUTED* ]] && ok "stderr does not satisfy stdout-contains" || bad "stderr false-confirmed stdout claim"
169+
# an always-matching contains: regex is not evidence (#461)
170+
mk am.a2ml '[claims]
171+
[[claim]]
172+
id = "C1"
173+
claim_class = "file-changed"
174+
target = "README.adoc"
175+
expect = "contains:.*"
176+
verifier = "git-diff"'
177+
[[ "$(reason_of "$TMP/am.a2ml" C1)" == unverifiable*trivial-pattern ]] && ok "always-matching contains: -> unverifiable" || bad "always-match pattern confirmed vacuously"
178+
169179
# licence claim phrased only in the statement is still manual-only
170180
mk lic.a2ml '[claims]
171181
[[claim]]

0 commit comments

Comments
 (0)