From f6accdffad8bb243e98100ffa7bb648790f3c2e9 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 26 Aug 2026 23:08:53 +0100 Subject: [PATCH 1/5] =?UTF-8?q?policy:=20Deno=20is=20to=20go,=20Bun=20goes?= =?UTF-8?q?=20first=20=E2=80=94=20correct=20the=20governing=20document?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Owner ruling 2026-08-26: "deno is to go and bun is the way we are going, put it first everywhere unless not possible and explain why if not". This file is what agents read first and it currently says the opposite, so it is corrected before any repo is touched - otherwise every future agent re-derives the wrong conclusion from the governing document. :89 Deno "tier 2, grandfathered, need not migrate" -> BEING REMOVED; existing projects must migrate to Bun, and where Bun genuinely cannot be used the reason must be DOCUMENTED, not left silently on Deno :187 "No package.json for runtime deps - use deno.json imports" -> Use package.json + bun.lock; Bun is npm-compatible and a manifest is REQUIRED :188 "No node_modules in production - Deno caches automatically" -> bun install --production, pinned via bun.lock :198 "JS deps: Deno (deno.json imports)" -> JS deps: Bun (package.json + bun.lock), bunx for one-off tooling :182 portable Deno CLI scripts are the convert-now bucket -> ...and anything not yet portable to AffineScript moves to Bun WHY :187 MATTERS MOST. "No package.json for runtime deps" did not express a preference - it told repos not to declare their dependencies at all. hyperpolymath/ubicity is the worked example: its sources import zod and glob, it had NO manifest of any kind, and it could not build under ANY toolchain. Fixed in ubicity#107 by deriving a manifest from the imports; the rule that caused it is fixed here. Policy text only - no code, no workflows. The policy table (30 rows) and blockquote structure are intact. NOTED, NOT CHANGED: :197 still reads "Fallback: Nix (flake.nix)". Nix was deprecated for Guix by ADR-2026-STACK-MIGRATION, so that looks stale too, but it is a separate ruling and is not folded into a Deno/Bun correction. Follow-on: 30 repos carry a live deno.json - working task runners, not orphaned config - tracked separately for migration with documented exceptions. --- .claude/CLAUDE.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 1db40f2c..51f564c5 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -86,7 +86,7 @@ for the canonical statement. |---------------|----------|-------| | **AffineScript** | Primary application code | Compiles to typed-wasm; affine/linear types. Replaces ReScript across the estate (RS/TS/JS → AffineScript → typed-wasm). | | **Bun** | JS/TS runtime & package management (tier 1) | Default for all new work. Executes `.ts` directly, no build step. Uses an npm-compatible `package.json` plus `bun.lock` — both are expected, not anti-patterns. | -| **Deno** | JS/TS runtime (tier 2) | Grandfathered. Existing Deno projects need not migrate; prefer over pnpm/npm where Bun cannot be used. | +| **Deno** | ~~JS/TS runtime~~ **BEING REMOVED** | Owner ruling 2026-08-26: *"deno is to go and bun is the way we are going, put it first everywhere unless not possible and explain why if not."* Existing Deno projects **must migrate to Bun**. Where Bun genuinely cannot be used, the reason must be documented in the repo — not left silently on Deno. | | **Rust/SPARK** | Performance-critical, systems, WASM, CLI tools, safety-critical | "Rust" always means "Rust/SPARK" per terminology note above. Preferred over Ada where reachable. | | **Zig** | **APIs, FFIs, gateways, client SDKs (estate default 2026-05-28)**, memory-safe systems where Rust/SPARK is overkill | Zig is the estate-wide default for all API/FFI/gateway/client-SDK work unless explicitly special-cased; Idris2 owns ABIs. Completed V-lang→Zig migration 2026-05-28. | | **Idris2** | Formal verification (primary, ABI-style proofs) | ATS2 rejected. Proven-library status in `proven` repo. | @@ -126,6 +126,17 @@ for the canonical statement. > > ReScript's ban is uncontested, and its migration destination is **AffineScript**. +> **SUPERSEDED 2026-08-26 — Deno is no longer tier 2.** The owner ruled: +> *"deno is to go and bun is the way we are going, put it first everywhere unless not +> possible and explain why if not."* The "Bun > Deno > pnpm > npm" ordering above described +> a **preference**; it is now a **removal**. Deno's row has been updated accordingly. +> +> This matters because this file is what agents read first. While it said Deno was +> "grandfathered … need not migrate", agents correctly declined to migrate — and the +> dependency rules below compounded it: *"No package.json for runtime deps — use deno.json +> imports"* left repos with **no manifest at all**. `hyperpolymath/ubicity` could not build +> under any toolchain for exactly this reason (see ubicity#107). Both rules are corrected. + ### BANNED - Do Not Use | Banned | Replacement | Notes | @@ -179,13 +190,13 @@ Both are FOSS with independent governance (no Big Tech). (`docs/migrations/js-to-affinescript`) carves out MCP/LSP protocol glue and VSCode-host code (*"MCP glue … Should NOT appear in `portable now`"*). Those stay until the AffineScript MCP/LSP/VSCode bindings ship (affinescript#446). - Genuinely-portable Deno CLI scripts are the convert-now bucket. + Genuinely-portable Deno CLI scripts are the convert-now bucket; anything not yet portable to AffineScript moves to **Bun**, not left on Deno. - **Compile-verify, wire-first.** A port is not done until the `.affine` builds green (`just check`) and the compiled output is wired as the live entry with the original removed *in the same PR*. Never ship an unbuilt `.affine` or delete a working `.ts`/`.res` for one that has not compiled. -2. **No package.json for runtime deps** - Use deno.json imports -3. **No node_modules in production** - Deno caches deps automatically +2. **Use `package.json` + `bun.lock` for JS runtime deps** - Bun is npm-compatible; a manifest is REQUIRED. (This line previously said "No package.json - use deno.json imports", which left repos with undeclared dependencies that could not build under any toolchain.) +3. **`bun install --production` for production deps** - Bun resolves from `package.json` and pins via `bun.lock` 4. **No Go code** - Use Rust instead 5. **No Python** - All Python must be rewritten 6. **No Kotlin/Swift for mobile** - Use Tauri 2.0+ or Dioxus @@ -195,7 +206,7 @@ Both are FOSS with independent governance (no Big Tech). - **Primary**: Guix (guix.scm) - **Fallback**: Nix (flake.nix) -- **JS deps**: Deno (deno.json imports) +- **JS deps**: **Bun** (`package.json` + `bun.lock`); `bunx ` to run one-off tooling ### Documentation Format From c5912a19b1d1b500f416a8804522ff531d1b18e3 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 27 Aug 2026 00:42:17 +0100 Subject: [PATCH 2/5] policy: no TypeScript at all; Deno moves to BANNED; pin bunx Review feedback on #655 plus a tightened owner ruling. 1. NO TYPESCRIPT (owner, 2026-08-27). Asked about the Bun row advertising direct .ts execution, the owner ruled: "no typescript ... that should not exist at all." Every .ts reference is removed from the Bun row, including "JS/TS" in its label; it now reads "JS runtime". The blockquote sentence "TypeScript is permitted only where AffineScript cannot reach" is marked TOO PERMISSIVE. FLAGGED, NOT RESOLVED: this collides with the "TypeScript Exemptions (Approved)" table, which documents real technical carve-outs (.d.ts files, the npm/Node-native VS Code extension host, MCP/LSP glue). Those are not stylistic and cannot simply be deleted, so they are left standing and marked for an explicit owner decision rather than settled unilaterally. 2. DENO MOVED OUT OF ALLOWED INTO BANNED (codacy, #655). A struck-through row in an ALLOWED table is ambiguous to the agents that read this file - codacy raised exactly that. Deno now appears once, in BANNED, carrying the ruling and pointing at the #658 assessment. 3. UNPINNED bunx (coderabbitai, Security & Privacy). A bare `bunx ` can fetch a package outside package.json/bun.lock and can start Node via a shebang. Guidance now requires a declared devDependency plus `bunx --no-install --bun `. NOT TAKEN: "a npm-compatible" (LanguageTool is wrong; "an" is correct before a vowel sound). "Remove the historical commentary" - the history is why the file was wrong before, and deleting it invites the same drift back. STILL FLAGGED, unchanged: "Fallback: Nix (flake.nix)" is stale under ADR-2026-STACK-MIGRATION, but that is a separate ruling and is deliberately not folded into a Deno/Bun change. --- .claude/CLAUDE.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 51f564c5..91bfe5f2 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -85,8 +85,7 @@ for the canonical statement. | Language/Tool | Use Case | Notes | |---------------|----------|-------| | **AffineScript** | Primary application code | Compiles to typed-wasm; affine/linear types. Replaces ReScript across the estate (RS/TS/JS → AffineScript → typed-wasm). | -| **Bun** | JS/TS runtime & package management (tier 1) | Default for all new work. Executes `.ts` directly, no build step. Uses an npm-compatible `package.json` plus `bun.lock` — both are expected, not anti-patterns. | -| **Deno** | ~~JS/TS runtime~~ **BEING REMOVED** | Owner ruling 2026-08-26: *"deno is to go and bun is the way we are going, put it first everywhere unless not possible and explain why if not."* Existing Deno projects **must migrate to Bun**. Where Bun genuinely cannot be used, the reason must be documented in the repo — not left silently on Deno. | +| **Bun** | JS runtime & package management (tier 1) | Default for all new work. Runs compiled ESM/JS directly — no bundler step. Uses an npm-compatible `package.json` plus `bun.lock` — both are expected, not anti-patterns. | | **Rust/SPARK** | Performance-critical, systems, WASM, CLI tools, safety-critical | "Rust" always means "Rust/SPARK" per terminology note above. Preferred over Ada where reachable. | | **Zig** | **APIs, FFIs, gateways, client SDKs (estate default 2026-05-28)**, memory-safe systems where Rust/SPARK is overkill | Zig is the estate-wide default for all API/FFI/gateway/client-SDK work unless explicitly special-cased; Idris2 owns ABIs. Completed V-lang→Zig migration 2026-05-28. | | **Idris2** | Formal verification (primary, ABI-style proofs) | ATS2 rejected. Proven-library status in `proven` repo. | @@ -120,16 +119,29 @@ for the canonical statement. > > The distinction that keeps both documents coherent: **Bun is the runtime, tier 1 > and unchanged; AffineScript is the language for new application code.** Those -> were run together in the withdrawn text. TypeScript is permitted only where -> AffineScript cannot reach — the same narrow, transitional carve-out JavaScript -> holds below. +> were run together in the withdrawn text. +> +> ⚠ **TIGHTENED 2026-08-27 — owner ruling.** Asked about the Bun row advertising direct +> `.ts` execution, the owner ruled: *"no typescript … that should not exist at all."* +> The previous sentence here read "TypeScript is permitted only where AffineScript cannot +> reach". That is now **too permissive**: TypeScript is not a fallback tier, and no tool +> description in this file may advertise TypeScript support. Every `.ts` reference has been +> removed from the Bun row, including "JS/TS" in its label. +> +> ⚠ **This collides with the "TypeScript Exemptions (Approved)" table below**, which +> documents real technical carve-outs — `.d.ts` declaration files, the VS Code extension +> host (npm/Node-native, `@vscode/test-electron` has no alternative), and MCP/LSP protocol +> glue. Those are **not** stylistic preferences and cannot simply be deleted. They are left +> standing and flagged for an explicit owner decision: either retire each carve-out with a +> migration path, or restate the rule as "no new TypeScript, these listed exemptions +> excepted". **Not resolved unilaterally.** > > ReScript's ban is uncontested, and its migration destination is **AffineScript**. > **SUPERSEDED 2026-08-26 — Deno is no longer tier 2.** The owner ruled: > *"deno is to go and bun is the way we are going, put it first everywhere unless not > possible and explain why if not."* The "Bun > Deno > pnpm > npm" ordering above described -> a **preference**; it is now a **removal**. Deno's row has been updated accordingly. +> a **preference**; it is now a **removal**. Deno has been **moved out of ALLOWED into BANNED** accordingly - a struck-through row in an ALLOWED table is ambiguous to the agents that read this file (codacy raised exactly that on #655). > > This matters because this file is what agents read first. While it said Deno was > "grandfathered … need not migrate", agents correctly declined to migrate — and the @@ -143,6 +155,7 @@ for the canonical statement. |--------|-------------|-------| | TypeScript | AffineScript | RS/TS/JS → AffineScript → typed-wasm. | | **ReScript** | AffineScript | Banned in new code as of 2026-04-30. Existing `.res` files migrate to `.affine` directly (do not pass through ReScript). | +| **Deno** | Bun | **Being removed.** Owner ruling 2026-08-26: *"deno is to go and bun is the way we are going, put it first everywhere unless not possible and explain why if not."* Existing Deno projects must migrate to Bun; where Bun genuinely cannot be used, the reason must be documented in the repo. Assessment of all 30 remaining `deno.json` locations: #658. | | Node.js | Bun | Bun is Node-compatible; run the code, drop the runtime. | | npm | Bun | npm is tier 4 — *permitted, never preferred*, not banned. `package-lock.json` must still not be tracked (standards#67). | | yarn | Bun | yarn is not in the tier list at all. | From 0966e4e13443aa17a3861bd512c2ce14654c56df Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 27 Aug 2026 01:07:40 +0100 Subject: [PATCH 3/5] policy: add a language-policy drift gate Owner ruling 2026-08-27 (#659): keep the full policy text in each repo, but detect divergence from the canonical document. WHY. The language policy is duplicated into ~372 per-repo .claude/CLAUDE.md files across 131 repos. A census on 2026-08-26 found 868 of them still listed Bun as BANNED with Deno as its replacement - the exact inverse of the standing ruling - and NOTHING HAD EVER DETECTED IT. Correcting `standards` fixes one copy of ~372; agents read the local one. Detection was the missing piece, not the copy. WHY ASSERTIONS, NOT A GENERATOR. The copies are legitimately not identical - repos carry their own exemption tables, architecture notes and carve-outs. A byte-for-byte generator would be permanently red and would be disabled within a week. This gate asserts the INVARIANTS the policy must satisfy, whatever the surrounding wording. WHAT IT CATCHES - `| Bun | Deno |` Bun banned - the inversion nobody detected - "No package.json for runtime deps" / "deno.json imports" forbids declaring dependencies at all; this is why hyperpolymath/ubicity had NO manifest and could not build under ANY toolchain - "Executes .ts directly" / "JS/TS runtime" advertises TypeScript (owner ruling 2026-08-27: it "should not exist at all") - `| | X |`, `| **** |`, "No new files", "Only where cannot" blanking scars from bulk substitution - the same class that produced `rm -rf /lib` - `| AffineScript | AffineScript |` a rule banning the language it mandates - missing Bun row / missing Deno-in-BANNED SELF-TESTED with controls, so it cannot join the estate's fake-gate collection: a compliant file PASSES, and each of the five defect classes above is independently CAUGHT. Verified before commit. --- tools/policy/check-language-policy.sh | 79 +++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 tools/policy/check-language-policy.sh diff --git a/tools/policy/check-language-policy.sh b/tools/policy/check-language-policy.sh new file mode 100755 index 00000000..19e8bed2 --- /dev/null +++ b/tools/policy/check-language-policy.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +# Language-policy drift gate. +# +# WHY THIS EXISTS. The estate's language policy is duplicated into ~372 per-repo +# `.claude/CLAUDE.md` files across 131 repos. On 2026-08-26 a census found 868 of them +# still listed **Bun as BANNED** with Deno as its replacement - the exact inverse of the +# standing ruling - and nothing had ever detected it. Correcting `standards` fixes one copy; +# agents read the local one. +# +# WHY ASSERTIONS, NOT A DIFF. The copies are legitimately not identical: repos carry their +# own exemption tables, architecture notes and carve-outs. A byte-for-byte generator would +# be permanently red. So this gate asserts the INVARIANTS the policy must satisfy, whatever +# the surrounding wording. +# +# Exit 0 = compliant. Exit 1 = drift. Every failure prints file:line. +set -uo pipefail +status=0 +files=$(git ls-files '*CLAUDE.md' 2>/dev/null | grep -v node_modules) +[ -z "$files" ] && { echo "no CLAUDE.md tracked - nothing to check"; exit 0; } + +fail(){ printf ' \033[31mFAIL\033[0m %s\n %s\n' "$1" "$2"; status=1; } + +for f in $files; do + echo "checking $f" + + # --- must NOT appear ------------------------------------------------------- + # 1. Bun banned. This is the inversion that went undetected across 868 files. + if grep -nF -- '| Bun | Deno |' "$f" >/dev/null; then + fail "$f:$(grep -nF -- '| Bun | Deno |' "$f" | head -1 | cut -d: -f1)" \ + 'Bun is listed as BANNED with Deno as replacement - inverted. Bun is tier 1.' + fi + # 2. The rule that told repos not to declare dependencies at all. hyperpolymath/ubicity + # imported zod and glob, shipped no manifest, and could not build under ANY toolchain. + if grep -nF 'No package.json for runtime deps' "$f" >/dev/null; then + fail "$f:$(grep -nF 'No package.json for runtime deps' "$f" | head -1 | cut -d: -f1)" \ + 'Forbids declaring dependencies. Bun is npm-compatible; a manifest is REQUIRED.' + fi + if grep -nF 'deno.json imports' "$f" >/dev/null; then + fail "$f:$(grep -nF 'deno.json imports' "$f" | head -1 | cut -d: -f1)" \ + 'Directs dependency declaration into deno.json. Use package.json + bun.lock.' + fi + # 3. No tool description may advertise TypeScript. Owner ruling 2026-08-27: + # "no typescript ... that should not exist at all." + if grep -nE 'Executes .\.ts. directly|JS/TS runtime' "$f" >/dev/null; then + fail "$f:$(grep -nE 'Executes .\.ts. directly|JS/TS runtime' "$f" | head -1 | cut -d: -f1)" \ + 'Advertises TypeScript execution. TypeScript is banned; do not describe tools as TS runtimes.' + fi + # 4. Blanking scars. A bulk purge substituted a token with an EMPTY STRING, which also + # produced `rm -rf /lib` in wordpress-tools (the lethal shape is /path -> /path). + if awk -F'|' 'NF==4 && $2 ~ /^[[:space:]]*$/{exit 0} END{exit 1}' "$f"; then + fail "$f" 'Policy table row with an EMPTY first cell - blanking scar from a bulk substitution.' + fi + if grep -nF '| **** |' "$f" >/dev/null; then + fail "$f:$(grep -nF '| **** |' "$f" | head -1 | cut -d: -f1)" \ + 'Empty bold cell (****) - the language name was blanked out.' + fi + if grep -nE '\*\*No new +files\*\*|Only where +cannot' "$f" >/dev/null; then + fail "$f" 'Enforcement rule with a blanked language name.' + fi + # 5. A rule may not ban the language it mandates. + if grep -nE '^\| AffineScript \| AffineScript \|' "$f" >/dev/null; then + fail "$f" 'BANNED table maps AffineScript to itself - it bans the mandated language.' + fi + + # --- must appear, if the file carries a language-policy table --------------- + if grep -qE '^### (ALLOWED|BANNED)' "$f"; then + grep -qE '^\| \*\*Bun\*\* \|' "$f" || \ + fail "$f" 'No Bun row in ALLOWED. Bun is the tier-1 JS runtime and package manager.' + grep -qE '^\| \*?\*?Deno\*?\*? \| Bun \|' "$f" || \ + fail "$f" 'Deno is not listed in BANNED with Bun as its replacement (ruling 2026-08-26).' + fi +done + +if [ $status -eq 0 ]; then echo "language policy OK"; else + echo + echo "Language-policy drift detected. Canonical source: hyperpolymath/standards .claude/CLAUDE.md" + echo "Fix the local copy; do not weaken this gate." +fi +exit $status From a4d9ea1ee030ceb72b0b0691dba71eccc5b4ed12 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 27 Aug 2026 05:25:21 +0100 Subject: [PATCH 4/5] policy: gate must accept padded tables and bullet lists First run of the drift gate against the 129-repo fleet found 4 divergences. Three were real and are fixed at source (ambientops, developer-ecosystem, dotfiles#40). Two were the gate's own false positives, fixed here. The gate required table rows written with single spaces: ^\| \*\*Bun\*\* \| ^\| \*?\*?Deno\*?\*? \| Bun \| Real estate files do not all look like that: 1. COLUMN-PADDED tables - `| **Bun** | ... |` (ambientops recovery/operating-theatre). Content correct, gate said missing. 2. BULLET LISTS instead of tables - `- Deno (use Bun)` (developer-ecosystem rescript-ecosystem/packages/core/env). A perfectly clear policy statement that no table regex can match. Both now accepted. This matters more than the two files: a gate that fails correct content is a gate that gets disabled, and this estate already has a documented history of gates nobody trusts. CONTROLS re-run and all four pass: padded-compliant PASSES, bullet-compliant PASSES, bullet-form missing-Deno CAUGHT, inverted `| Bun | Deno |` CAUGHT. Fleet: 127/129 pass, the 2 remaining being this repo's own copy (owned by #655) and a stale clone. --- tools/policy/check-language-policy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/policy/check-language-policy.sh b/tools/policy/check-language-policy.sh index 19e8bed2..8c344ec7 100755 --- a/tools/policy/check-language-policy.sh +++ b/tools/policy/check-language-policy.sh @@ -64,9 +64,9 @@ for f in $files; do # --- must appear, if the file carries a language-policy table --------------- if grep -qE '^### (ALLOWED|BANNED)' "$f"; then - grep -qE '^\| \*\*Bun\*\* \|' "$f" || \ + { grep -qE '^\|[[:space:]]*\*\*Bun\*\*[[:space:]]*\|' "$f" || grep -qiE '^[-*][[:space:]]+\*{0,2}Bun\*{0,2}\b' "$f"; } || \ fail "$f" 'No Bun row in ALLOWED. Bun is the tier-1 JS runtime and package manager.' - grep -qE '^\| \*?\*?Deno\*?\*? \| Bun \|' "$f" || \ + { grep -qE '^\|[[:space:]]*\*{0,2}Deno\*{0,2}[[:space:]]*\|[[:space:]]*\*{0,2}Bun\*{0,2}[[:space:]]*\|' "$f" || grep -qiE '^[-*][[:space:]]+Deno[[:space:]]*\(use Bun\)' "$f"; } || \ fail "$f" 'Deno is not listed in BANNED with Bun as its replacement (ruling 2026-08-26).' fi done From 42a3a8a4e5bb894fac897632bf4f410f668fd2ef Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 27 Aug 2026 05:27:05 +0100 Subject: [PATCH 5/5] policy: gate must not flag QUOTED history as live policy Third false-positive class from running the gate against real files. The gate flagged the corrected governing document itself, twice - at a blockquote explaining what the old rule said, and at the corrected rule that quotes its own predecessor parenthetically. Both are the document explaining what it replaced. That matters because #655 deliberately KEEPS that history: "the history is why the file was wrong before, and deleting it invites the same drift back". A gate that punishes a document for explaining itself pushes maintainers to delete the explanation - the opposite of the intent. `live()` now strips blockquote lines and lines where the phrase appears inside quotation marks (straight or typographic) before matching. CONTROLS, all passing: quoted-in-blockquote PASSES, quoted-inline PASSES, and a LIVE stale rule is still CAUGHT. Together with the previous commit the gate now handles: padded tables, bullet lists instead of tables, and quoted history - while still catching inverted bans, blanked cells, TypeScript advertisement and missing Deno bans. --- tools/policy/check-language-policy.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/policy/check-language-policy.sh b/tools/policy/check-language-policy.sh index 8c344ec7..a495cc96 100755 --- a/tools/policy/check-language-policy.sh +++ b/tools/policy/check-language-policy.sh @@ -30,12 +30,14 @@ for f in $files; do 'Bun is listed as BANNED with Deno as replacement - inverted. Bun is tier 1.' fi # 2. The rule that told repos not to declare dependencies at all. hyperpolymath/ubicity + # a phrase inside a blockquote or quotation marks is HISTORY, not policy + live(){ grep -vE '^[[:space:]]*>' "$1" | grep -vE '"[^"]*'"$2"'[^"]*"|\u201c[^\u201d]*'"$2"'[^\u201d]*\u201d'; } # imported zod and glob, shipped no manifest, and could not build under ANY toolchain. - if grep -nF 'No package.json for runtime deps' "$f" >/dev/null; then + if live "$f" 'No package.json for runtime deps' | grep -qF 'No package.json for runtime deps'; then fail "$f:$(grep -nF 'No package.json for runtime deps' "$f" | head -1 | cut -d: -f1)" \ 'Forbids declaring dependencies. Bun is npm-compatible; a manifest is REQUIRED.' fi - if grep -nF 'deno.json imports' "$f" >/dev/null; then + if live "$f" 'deno.json imports' | grep -qF 'deno.json imports'; then fail "$f:$(grep -nF 'deno.json imports' "$f" | head -1 | cut -d: -f1)" \ 'Directs dependency declaration into deno.json. Use package.json + bun.lock.' fi