From 9bdd559da48fd53c72cefa5abaeaf8c7c3ee20a2 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 27 Aug 2026 14:26:18 +0100 Subject: [PATCH 1/7] fix(ci): the invisible-character gate never matched anything MEASURED 2026-08-27: this gate's pattern caught 0 OF 6 invisible-character test cases. It has never detected an NBSP, zero-width space, BOM, soft hyphen, bidi override or word joiner. ROOT CAUSE: the pattern used UTF-8 BYTE sequences (\xc2\xa0) while grep -P matches CHARACTERS. Bytes c2 a0 are ONE character U+00A0; \xc2\xa0 asks for TWO characters, U+00C2 then U+00A0, which is never present. grep -P '\xc2\xa0' -> miss grep -P '\x{a0}' -> MATCH Only \x00 worked, being single-byte in both readings. FIXED: codepoint escapes; C0 control characters \x01-\x08,\x0B,\x0C,\x0E-\x1F added (TAB/LF/CR excluded); and grep -a, without which grep skips any NUL-bearing file as binary. The C0 range matters: a stray BACKSPACE byte made a workflow unparseable in developer-ecosystem, so it never ran, and this linter called it clean. Canonical fix: hyperpolymath/empty-linter#70. 1 file(s) here. VERIFIED: YAML re-parsed, and the corrected pattern was confirmed to catch a real NBSP before the change was kept. --- .github/workflows/dogfood-gate.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dogfood-gate.yml b/.github/workflows/dogfood-gate.yml index bfe74e6a..cb96abca 100644 --- a/.github/workflows/dogfood-gate.yml +++ b/.github/workflows/dogfood-gate.yml @@ -149,7 +149,7 @@ jobs: # Checks for: zero-width spaces, zero-width joiners, BOM, soft hyphens, # non-breaking spaces, null bytes, and other invisible Unicode in source files. set +e - PATTERNS='\xc2\xa0|\xe2\x80\x8b|\xe2\x80\x8c|\xe2\x80\x8d|\xef\xbb\xbf|\xc2\xad|\xe2\x80\x8e|\xe2\x80\x8f|\xe2\x80\xaa|\xe2\x80\xab|\xe2\x80\xac|\xe2\x80\xad|\xe2\x80\xae|\x00' + PATTERNS='\x00|[\x01-\x08\x0B\x0C\x0E-\x1F]|\x{a0}|\x{ad}|\x{200b}|\x{200c}|\x{200d}|\x{200e}|\x{200f}|\x{202a}|\x{202b}|\x{202c}|\x{202d}|\x{202e}|\x{2060}|\x{feff}' find "$GITHUB_WORKSPACE" \ -not -path '*/.git/*' -not -path '*/node_modules/*' \ -not -path '*/.deno/*' -not -path '*/target/*' \ @@ -160,7 +160,7 @@ jobs: -o -name '*.yml' -o -name '*.yaml' -o -name '*.md' -o -name '*.adoc' \ -o -name '*.idr' -o -name '*.zig' -o -name '*.v' -o -name '*.jl' \ -o -name '*.gleam' -o -name '*.hs' -o -name '*.ml' -o -name '*.sh' \) \ - -exec grep -Prl "$PATTERNS" {} \; > /tmp/empty-lint-results.txt 2>/dev/null + -exec grep -aPrl "$PATTERNS" {} \; > /tmp/empty-lint-results.txt 2>/dev/null EL_EXIT=$? set -e From d5eaa17664f1d529b5965bd71ee64dddeeaf13a4 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:09:19 +0100 Subject: [PATCH 2/7] fix(ci): make invisible-character PCRE locale-independent --- .github/workflows/dogfood-gate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dogfood-gate.yml b/.github/workflows/dogfood-gate.yml index cb96abca..0250e3a0 100644 --- a/.github/workflows/dogfood-gate.yml +++ b/.github/workflows/dogfood-gate.yml @@ -149,7 +149,7 @@ jobs: # Checks for: zero-width spaces, zero-width joiners, BOM, soft hyphens, # non-breaking spaces, null bytes, and other invisible Unicode in source files. set +e - PATTERNS='\x00|[\x01-\x08\x0B\x0C\x0E-\x1F]|\x{a0}|\x{ad}|\x{200b}|\x{200c}|\x{200d}|\x{200e}|\x{200f}|\x{202a}|\x{202b}|\x{202c}|\x{202d}|\x{202e}|\x{2060}|\x{feff}' + PATTERNS='(*UTF)[\x00-\x08\x0B\x0C\x0E-\x1F\x{a0}\x{ad}\x{200b}-\x{200f}\x{202a}-\x{202f}\x{2060}\x{2066}-\x{2069}\x{feff}]' find "$GITHUB_WORKSPACE" \ -not -path '*/.git/*' -not -path '*/node_modules/*' \ -not -path '*/.deno/*' -not -path '*/target/*' \ From 83dc35555d3d0f0b9245dcbfd6f1c36e5810542c Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sat, 29 Aug 2026 04:03:16 +0100 Subject: [PATCH 3/7] Update .github/workflows/dogfood-gate.yml Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com> Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com> --- .github/workflows/dogfood-gate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dogfood-gate.yml b/.github/workflows/dogfood-gate.yml index 0250e3a0..156c10e0 100644 --- a/.github/workflows/dogfood-gate.yml +++ b/.github/workflows/dogfood-gate.yml @@ -160,7 +160,7 @@ jobs: -o -name '*.yml' -o -name '*.yaml' -o -name '*.md' -o -name '*.adoc' \ -o -name '*.idr' -o -name '*.zig' -o -name '*.v' -o -name '*.jl' \ -o -name '*.gleam' -o -name '*.hs' -o -name '*.ml' -o -name '*.sh' \) \ - -exec grep -aPrl "$PATTERNS" {} \; > /tmp/empty-lint-results.txt 2>/dev/null + -exec grep -aPl "$PATTERNS" {} + > /tmp/empty-lint-results.txt 2>/dev/null EL_EXIT=$? set -e From 9e014703e77d15c9e6c08477180a01cd3681ae15 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:24:29 +0100 Subject: [PATCH 4/7] fix(ci): make invisible scan byte-safe --- .github/workflows/dogfood-gate.yml | 100 +++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 27 deletions(-) diff --git a/.github/workflows/dogfood-gate.yml b/.github/workflows/dogfood-gate.yml index 156c10e0..4c1529b1 100644 --- a/.github/workflows/dogfood-gate.yml +++ b/.github/workflows/dogfood-gate.yml @@ -148,38 +148,84 @@ jobs: # Inline invisible character detection (from empty-linter's core patterns). # Checks for: zero-width spaces, zero-width joiners, BOM, soft hyphens, # non-breaking spaces, null bytes, and other invisible Unicode in source files. - set +e - PATTERNS='(*UTF)[\x00-\x08\x0B\x0C\x0E-\x1F\x{a0}\x{ad}\x{200b}-\x{200f}\x{202a}-\x{202f}\x{2060}\x{2066}-\x{2069}\x{feff}]' - find "$GITHUB_WORKSPACE" \ - -not -path '*/.git/*' -not -path '*/node_modules/*' \ - -not -path '*/.deno/*' -not -path '*/target/*' \ - -not -path '*/_build/*' -not -path '*/deps/*' \ - -not -path '*/external_corpora/*' -not -path '*/.lake/*' \ - -type f \( -name '*.rs' -o -name '*.ex' -o -name '*.exs' -o -name '*.res' \ - -o -name '*.js' -o -name '*.ts' -o -name '*.json' -o -name '*.toml' \ - -o -name '*.yml' -o -name '*.yaml' -o -name '*.md' -o -name '*.adoc' \ - -o -name '*.idr' -o -name '*.zig' -o -name '*.v' -o -name '*.jl' \ - -o -name '*.gleam' -o -name '*.hs' -o -name '*.ml' -o -name '*.sh' \) \ - -exec grep -aPl "$PATTERNS" {} + > /tmp/empty-lint-results.txt 2>/dev/null - EL_EXIT=$? - set -e - - FINDINGS=$(wc -l < /tmp/empty-lint-results.txt 2>/dev/null || echo 0) - echo "findings=$FINDINGS" >> "$GITHUB_OUTPUT" - echo "exit_code=$EL_EXIT" >> "$GITHUB_OUTPUT" - echo "ready=true" >> "$GITHUB_OUTPUT" - - # Emit annotations for each file with invisible chars - while IFS= read -r filepath; do - [ -z "$filepath" ] && continue - REL_PATH="${filepath#$GITHUB_WORKSPACE/}" - echo "::warning file=${REL_PATH}::Invisible Unicode characters detected (zero-width space, BOM, NBSP, etc.)" - done < /tmp/empty-lint-results.txt + python3 - <<'PY' + import os + from pathlib import Path + + root = Path(os.environ["GITHUB_WORKSPACE"]) + skipped_dirs = { + ".git", ".deno", ".lake", "_build", "deps", + "external_corpora", "node_modules", "target", + } + source_suffixes = { + ".adoc", ".ex", ".exs", ".gleam", ".hs", ".idr", ".jl", + ".js", ".json", ".md", ".ml", ".res", ".rs", ".sh", + ".toml", ".ts", ".v", ".yaml", ".yml", ".zig", + } + invisible_codepoints = { + 0x00A0, 0x00AD, 0x2060, 0xFEFF, + *range(0x200B, 0x2010), + *range(0x202A, 0x2030), + *range(0x2066, 0x206A), + } + + def annotation_escape(value): + return str(value).replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A") + + findings = [] + errors = [] + for path in root.rglob("*"): + relative = path.relative_to(root) + if ( + path.is_symlink() + or not path.is_file() + or path.suffix.lower() not in source_suffixes + or any(part in skipped_dirs for part in relative.parts[:-1]) + ): + continue + try: + data = path.read_bytes() + except OSError as error: + errors.append((relative, f"could not read file: {error}")) + continue + + reasons = set() + if data.startswith(b"\xef\xbb\xbf"): + reasons.add("leading UTF-8 BOM") + if any(byte <= 0x08 or byte in (0x0B, 0x0C) or 0x0E <= byte <= 0x1F for byte in data): + reasons.add("C0 control character") + try: + text_content = data.decode("utf-8", errors="strict") + except UnicodeDecodeError as error: + errors.append((relative, f"invalid UTF-8 at byte {error.start}")) + continue + if any(ord(character) in invisible_codepoints for character in text_content): + reasons.add("invisible Unicode code point") + if reasons: + findings.append((relative, ", ".join(sorted(reasons)))) + + with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as output: + output.write(f"findings={len(findings)}\n") + output.write(f"exit_code={2 if errors else 0}\n") + output.write("ready=true\n") + + for relative, reasons in findings: + print(f"::warning file={annotation_escape(relative)}::Invisible characters detected: {reasons}") + for relative, reason in errors: + print(f"::error file={annotation_escape(relative)}::Invisible-character scan failed: {annotation_escape(reason)}") + PY - name: Write summary run: | if [ "${{ steps.lint.outputs.ready }}" = "true" ]; then FINDINGS="${{ steps.lint.outputs.findings }}" + EXIT_CODE="${{ steps.lint.outputs.exit_code }}" + if [ "$EXIT_CODE" -ne 0 ] 2>/dev/null; then + echo "## Empty-Linter Results" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo ":x: Scanner execution failed; see error annotations above." >> "$GITHUB_STEP_SUMMARY" + exit 1 + fi if [ "$FINDINGS" -gt 0 ] 2>/dev/null; then echo "## Empty-Linter Results" >> "$GITHUB_STEP_SUMMARY" echo "" >> "$GITHUB_STEP_SUMMARY" From 3bbe087dfbd90935626788518ceff8d975334c37 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:47:17 +0100 Subject: [PATCH 5/7] fix(ci): enforce invisible-character findings --- .../path-reference-drift/TYPOLOGY.adoc | 2 +- .audittraining/release-candidates/REPORT.adoc | 2 +- .github/workflows/dogfood-gate.yml | 93 ++++++++++++------- .hypatia-exemptions.adoc | 2 +- docs/proof-debt.adoc | 2 +- docs/proofs/HANDOVER-neural-convergence.adoc | 2 +- docs/status/handover-2026-06-20.adoc | 2 +- docs/tech-debt-2026-05-26.adoc | 2 +- src/ui/gossamer/BURBLE-DEFERRAL.adoc | 2 +- 9 files changed, 65 insertions(+), 44 deletions(-) diff --git a/.audittraining/path-reference-drift/TYPOLOGY.adoc b/.audittraining/path-reference-drift/TYPOLOGY.adoc index 3d284ea8..4788910c 100644 --- a/.audittraining/path-reference-drift/TYPOLOGY.adoc +++ b/.audittraining/path-reference-drift/TYPOLOGY.adoc @@ -44,7 +44,7 @@ tree, prose, table |lexical |*TP_self_drift* |the repo’s OWN manifest/doc asserts a layout that contradicts its tree |TRUE positive |fix the doc -|*TP_real* |a real non-path defect (e.g. workflow missing +|*TP_real* |a real non-path defect (e.g. workflow missing `+timeout-minutes+`) |TRUE positive |fix the source |*FP_relative* |path is real but unanchored — diff --git a/.audittraining/release-candidates/REPORT.adoc b/.audittraining/release-candidates/REPORT.adoc index 5021c8e7..a666b168 100644 --- a/.audittraining/release-candidates/REPORT.adoc +++ b/.audittraining/release-candidates/REPORT.adoc @@ -143,7 +143,7 @@ file in subdirectory) * Consider publishing to crates.io (for Rust) . *For bunsenite (existing releases):* * Check commits since v1.0.2 -* Review for breaking changes vs. patches +* Review for breaking changes vs. patches * Follow semver for version bump . *Manual verification needed:* * supernorma - check deno.json diff --git a/.github/workflows/dogfood-gate.yml b/.github/workflows/dogfood-gate.yml index 4c1529b1..53c73d24 100644 --- a/.github/workflows/dogfood-gate.yml +++ b/.github/workflows/dogfood-gate.yml @@ -154,12 +154,20 @@ jobs: root = Path(os.environ["GITHUB_WORKSPACE"]) skipped_dirs = { - ".git", ".deno", ".lake", "_build", "deps", - "external_corpora", "node_modules", "target", + ".cache", ".deno", ".elixir_ls", ".git", ".lake", ".zig-cache", + "_build", "build", "coverage", "deps", "dist", "external_corpora", + "node_modules", "out", "target", "vendor", "zig-cache", "zig-out", + } + intentional_fixture_dirs = { + ("tests", "fixtures", "bom-detection"), + ("tests", "fixtures", "empty-linter"), } source_suffixes = { - ".adoc", ".ex", ".exs", ".gleam", ".hs", ".idr", ".jl", - ".js", ".json", ".md", ".ml", ".res", ".rs", ".sh", + ".adoc", ".adb", ".ads", ".agda", ".c", ".cc", ".clj", ".cljs", + ".cpp", ".erl", ".ex", ".exs", ".fs", ".fsi", ".fsx", ".gleam", + ".h", ".hh", ".hpp", ".hrl", ".hs", ".idr", ".java", ".jl", + ".js", ".json", ".kt", ".kts", ".lean", ".lua", ".md", ".ml", + ".php", ".r", ".rb", ".res", ".rs", ".scala", ".sh", ".swift", ".toml", ".ts", ".v", ".yaml", ".yml", ".zig", } invisible_codepoints = { @@ -169,40 +177,52 @@ jobs: *range(0x2066, 0x206A), } - def annotation_escape(value): + def command_escape(value): return str(value).replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A") + def property_escape(value): + return command_escape(value).replace(":", "%3A").replace(",", "%2C") + + # Runtime regression for GitHub workflow-command property delimiters. + assert property_escape("docs/a,b::c.md") == "docs/a%2Cb%3A%3Ac.md" + + def intentionally_invalid_fixture(relative): + return any(relative.parts[:len(prefix)] == prefix for prefix in intentional_fixture_dirs) + findings = [] errors = [] - for path in root.rglob("*"): - relative = path.relative_to(root) - if ( - path.is_symlink() - or not path.is_file() - or path.suffix.lower() not in source_suffixes - or any(part in skipped_dirs for part in relative.parts[:-1]) - ): - continue - try: - data = path.read_bytes() - except OSError as error: - errors.append((relative, f"could not read file: {error}")) - continue - - reasons = set() - if data.startswith(b"\xef\xbb\xbf"): - reasons.add("leading UTF-8 BOM") - if any(byte <= 0x08 or byte in (0x0B, 0x0C) or 0x0E <= byte <= 0x1F for byte in data): - reasons.add("C0 control character") - try: - text_content = data.decode("utf-8", errors="strict") - except UnicodeDecodeError as error: - errors.append((relative, f"invalid UTF-8 at byte {error.start}")) - continue - if any(ord(character) in invisible_codepoints for character in text_content): - reasons.add("invisible Unicode code point") - if reasons: - findings.append((relative, ", ".join(sorted(reasons)))) + for directory, dirnames, filenames in os.walk(root, topdown=True): + dirnames[:] = [name for name in dirnames if name not in skipped_dirs] + directory_path = Path(directory) + for filename in filenames: + path = directory_path / filename + relative = path.relative_to(root) + if ( + path.is_symlink() + or path.suffix.lower() not in source_suffixes + or intentionally_invalid_fixture(relative) + ): + continue + try: + data = path.read_bytes() + except OSError as error: + errors.append((relative, f"could not read file: {error}")) + continue + + reasons = set() + if data.startswith(b"\xef\xbb\xbf"): + reasons.add("leading UTF-8 BOM") + if any(byte <= 0x08 or byte in (0x0B, 0x0C) or 0x0E <= byte <= 0x1F for byte in data): + reasons.add("C0 control character") + try: + text_content = data.decode("utf-8", errors="strict") + except UnicodeDecodeError as error: + errors.append((relative, f"invalid UTF-8 at byte {error.start}")) + continue + if any(ord(character) in invisible_codepoints for character in text_content): + reasons.add("invisible Unicode code point") + if reasons: + findings.append((relative, ", ".join(sorted(reasons)))) with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as output: output.write(f"findings={len(findings)}\n") @@ -210,9 +230,9 @@ jobs: output.write("ready=true\n") for relative, reasons in findings: - print(f"::warning file={annotation_escape(relative)}::Invisible characters detected: {reasons}") + print(f"::warning file={property_escape(relative)}::Invisible characters detected: {command_escape(reasons)}") for relative, reason in errors: - print(f"::error file={annotation_escape(relative)}::Invisible-character scan failed: {annotation_escape(reason)}") + print(f"::error file={property_escape(relative)}::Invisible-character scan failed: {command_escape(reason)}") PY - name: Write summary @@ -230,6 +250,7 @@ jobs: echo "## Empty-Linter Results" >> "$GITHUB_STEP_SUMMARY" echo "" >> "$GITHUB_STEP_SUMMARY" echo "Found **${FINDINGS}** invisible character issue(s). See annotations above." >> "$GITHUB_STEP_SUMMARY" + exit 1 else echo "## Empty-Linter Results" >> "$GITHUB_STEP_SUMMARY" echo "" >> "$GITHUB_STEP_SUMMARY" diff --git a/.hypatia-exemptions.adoc b/.hypatia-exemptions.adoc index e839c8a1..05d13f19 100644 --- a/.hypatia-exemptions.adoc +++ b/.hypatia-exemptions.adoc @@ -39,7 +39,7 @@ They are accepted as a category, not enumerated row-by-row: * `+.audittraining/**+` — training corpus. * `+scripts/fix-scripts/**+` — remediation scripts. * `+test/**+` and `+**/tests/**+` — test fixtures -(e.g. `+password: "test123"+`). +(e.g. `+password: "test123"+`). Findings against these paths under `+security_errors/secret_detected+` are kept in `+.hypatia-baseline.json+` and should remain there. diff --git a/docs/proof-debt.adoc b/docs/proof-debt.adoc index 945fe7c2..461aeffe 100644 --- a/docs/proof-debt.adoc +++ b/docs/proof-debt.adoc @@ -17,7 +17,7 @@ is the worst-case local-tree value the seed should accept without flagging. *Marker count (canonical / tracked):* 5. *Marker count (local-tree max, -incl. agent worktrees):* 15. +incl. agent worktrees):* 15. This file is the *initial seed* — every marker starts in §(d) DEBT and the maintainer triages each into §(a) / §(b) / §(c) / §(d) as diff --git a/docs/proofs/HANDOVER-neural-convergence.adoc b/docs/proofs/HANDOVER-neural-convergence.adoc index f8ae36c0..c1d2e056 100644 --- a/docs/proofs/HANDOVER-neural-convergence.adoc +++ b/docs/proofs/HANDOVER-neural-convergence.adoc @@ -58,7 +58,7 @@ assertion; Agda retired) |✅ |parser totality |`+verification/proofs/lean4/ParserTotality.lean+` |✅ |ABI package + verify package |`+src/abi/*.idr+` -(incl. `+RuleEngine.idr+`), `+verify/src/*.idr+` |✅ +(incl. `+RuleEngine.idr+`), `+verify/src/*.idr+` |✅ |*Neural convergence — PageRank* |`+verification/proofs/lean4/PageRankInvariants.lean+` |⛔ preconditions diff --git a/docs/status/handover-2026-06-20.adoc b/docs/status/handover-2026-06-20.adoc index 29da026d..2042dbc9 100644 --- a/docs/status/handover-2026-06-20.adoc +++ b/docs/status/handover-2026-06-20.adoc @@ -70,7 +70,7 @@ backlog, 71-alert code-scanning backlog. 4 low). Needs the repo’s Dependabot security tab or a `+security_events+`-scoped token; no MCP tool exposes Dependabot vulnerability alerts in-session. 0 open Dependabot PRs currently; -action-group bumps (e.g. #294) have merged since the issue was filed, so +action-group bumps (e.g. #294) have merged since the issue was filed, so some lows may already be cleared. === Fresh-thread items diff --git a/docs/tech-debt-2026-05-26.adoc b/docs/tech-debt-2026-05-26.adoc index ec890d77..1874f4e6 100644 --- a/docs/tech-debt-2026-05-26.adoc +++ b/docs/tech-debt-2026-05-26.adoc @@ -30,7 +30,7 @@ soundness-relevant escape hatches in Haskell/Rust source. *Recommended next move:* triage each finding into one of: (a) discharge by proof, (b) cover with property-tests + a documented refutation -budget, or (c) annotate as a known/necessary axiom (e.g. `+funExt+`) in +budget, or (c) annotate as a known/necessary axiom (e.g. `+funExt+`) in `+docs/proof-debt.md+`. === 2. Licence debt diff --git a/src/ui/gossamer/BURBLE-DEFERRAL.adoc b/src/ui/gossamer/BURBLE-DEFERRAL.adoc index a989b204..e84d31e5 100644 --- a/src/ui/gossamer/BURBLE-DEFERRAL.adoc +++ b/src/ui/gossamer/BURBLE-DEFERRAL.adoc @@ -32,7 +32,7 @@ lands: dashboard expects Hypatia to emit findings/dispatches via a Burble session rather than via a direct HTTP read of the harness endpoints. . *Multi-operator session.* Two or more operators need to share Hypatia -state (e.g. a review seat watching the safety triangle live while +state (e.g. a review seat watching the safety triangle live while another operator drives dispatches). . *Voice control reaches the GUI.* Burble’s voice-control plane wants to fire `+Msg.Navigate(Department.Verification)+` or similar from outside From de48e210cce849c478d5fe24bdc331bd10c3d2d2 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:56:42 +0100 Subject: [PATCH 6/7] docs(security): avoid credential-shaped exemption example --- .hypatia-exemptions.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.hypatia-exemptions.adoc b/.hypatia-exemptions.adoc index 05d13f19..4e740579 100644 --- a/.hypatia-exemptions.adoc +++ b/.hypatia-exemptions.adoc @@ -38,8 +38,8 @@ They are accepted as a category, not enumerated row-by-row: * `+.audittraining/**+` — training corpus. * `+scripts/fix-scripts/**+` — remediation scripts. -* `+test/**+` and `+**/tests/**+` — test fixtures -(e.g. `+password: "test123"+`). +* `+test/**+` and `+**/tests/**+` — test fixtures containing deliberately + credential-shaped sample data. Findings against these paths under `+security_errors/secret_detected+` are kept in `+.hypatia-baseline.json+` and should remain there. From 1ee3865525a2d02fbafb2908769b1b80a1a27535 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sat, 29 Aug 2026 14:02:38 +0100 Subject: [PATCH 7/7] fix(governance): update permissionless allowlist gate --- .github/workflows/governance.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index 3710eb92..8317b550 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -15,4 +15,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@d5fe075a50ab3ce4f41614d66ed77f152fda134f + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@6b38eb50104901e2fec80f9455a972bc3eced813