policy: Deno is to go, Bun goes first — correct the governing document - #655
Conversation
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.
|
Warning Review limit reachedNext included review available in 53 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Up to standards ✅🟢 Issues
|
There was a problem hiding this comment.
Pull Request Overview
This PR successfully codifies the 2026-08-26 owner ruling to transition from Deno to Bun as the Tier 1 JS/TS runtime. The updates to the enforcement rules—specifically mandating 'package.json' and 'bun.lock'—resolve critical buildability issues in downstream consumers.
While the core requirements are addressed, two primary areas for improvement were identified to ensure policy effectiveness:
- AI Agent Compatibility: The use of strikethroughs in the Language Policy table may be ignored by LLM-based parsers. Relocating Deno to a 'BANNED' section ensures unambiguous enforcement by agents.
- Systemic Inconsistency: The document retains Nix as a fallback on line 208, which contradicts the broader move toward Guix as specified in ADR-2026-STACK-MIGRATION.
Codacy quality standards are met, and the implementation aligns with the mandated dependency management rules.
About this PR
- There is a systemic inconsistency on line 208, which still lists Nix as a fallback. This contradicts ADR-2026-STACK-MIGRATION, which favors Guix for the infrastructure stack. It is recommended to align this line with the current migration strategy.
Test suggestions
- Verify the Language Policy table reflects Deno's removal and the migration mandate.
- Verify the Enforcement Rules section (Rule 2 and 3) requires manifests and production locks.
- Verify the Package Management section lists Bun as the source for JS deps.
- Verify the presence of the explanatory blockquote regarding the 2026-08-26 ruling.
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
| | **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. | |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Suggestion: The inclusion of Deno in the 'ALLOWED' table (even with strikethrough) poses a risk for AI agents that may fail to parse markdown formatting like ~~. Additionally, the policy requires documenting Bun exceptions; to ensure consistency with the estate's machine-readable standards, this should be explicitly pointed to .machine_readable/META.a2ml. It is recommended to move Deno to the 'BANNED' table and update the migration documentation accordingly.
| 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.) |
There was a problem hiding this comment.
⚪ LOW RISK
Nitpick: Remove historical commentary (e.g., 'This line previously said...') from the enforcement rule. This context is already appropriately captured in the superseding note at line 129; keeping the rule concise improves clarity for agent consumption.
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 <tool>` 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 <tool>`. 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.
|
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.
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.
This branch and #655 both modified .claude/CLAUDE.md, which would conflict on merge and would also overwrite #655's much richer correction (the owner-ruling blockquote, the Deno row moved out of ALLOWED into BANNED, and the TypeScript tightening) with this sweep's mechanical row edits. Reverted to main's version here. #655 is the single owner of the governing document; this PR now carries only the two subdirectory copies, which #655 does not touch: lol/.claude/CLAUDE.md meta-a2ml/.claude/CLAUDE.md
…ay 'grandfathered' (#816) Completes the 2026-08-26 owner ruling recorded in #655 (*"deno is to go and bun is the way we are going, put it first everywhere unless not possible and explain why if not"*). #655 was closed after correcting `.claude/CLAUDE.md` — the file agents read first. But the two **published policy tables** were never updated and still teach the repudiated rule verbatim: | file | line | still says | |---|---|---| | `LANGUAGE-POLICY.adoc` | 29–31 | "Existing Deno projects are *grandfathered* and need not migrate" | | `docs/JS-RUNTIME-POLICY.adoc` | 43–46 | same row, same wording | Downstream drift is already observable: `rsr-template-repo`'s `CLAUDE.md` carried "Deno (grandfathered)" while its own `runtime-policy.yml` enforced "BEING REMOVED, not grandfathered (canon standards#655)" — the contradiction filed as rsr-template-repo#70 (companion PR there fixes the template side; merge together). New wording mirrors #655's own correction table: **BEING REMOVED**; existing projects must migrate to Bun; where Bun genuinely cannot be used, the reason must be documented. The rank-2 listing is kept (the estate migration is in flight and `runtime-policy.yml` emits a warning, not an error, until it completes) but explicitly marked *not a safe harbour*. ## Escalated in the companion PR, deliberately NOT touched here (owner calls) 1. `rhodium-standard-repositories/spec/LANGUAGE-POLICY.adoc` — the RSR spec, v1.5.0, **revdate 2026-08-31, five days AFTER the ruling** — still encodes the *inverse* policy: Deno ALLOWED "Replaces Node/npm/Bun" (:70–72); Node.js banned → replacement Deno (:193–194); **"npm/Bun/pnpm/yarn" banned → replacement Deno (:227–228)**. Correcting a versioned spec needs a revnumber bump + Amendments entry. 2. `ai-instruction/opus.adoc:92,170`, `sonnet.adoc:85–86,118` — briefing-template examples still teach "Deno first" / "no npm/bun/yarn". Refs rsr-template-repo#70. Co-authored-by: Arena Agent (triage patches) <arena-agent@arena.ai>
Owner ruling 2026-09-22: "should be no deno, it's deprecated in standards,
and rsr-template-repo, and we are all bun and bunx now."
rhodium-standard-repositories/ is plain tracked content of this repo — no
.gitmodules, no nested .git, 1121 x 100644 + 17 x 100755 index entries — so
it is in scope for that ruling, not a separate repo's problem.
Its spec/LANGUAGE-POLICY.adoc had frozen the 2026-04-10 reach order, and was
not merely permissive about Deno: it BANNED Bun outright.
| *Bun*
| Deno, then pnpm (as Node fallback only)
| ... Bun is too young and moves too fast for policy-level adoption.
and its ratified reach order read "1. Deno first, always." with "`Bun` — too
young, moves too fast" in the explicitly-banned list. The ALLOWED table
carried "| *Deno* | Runtime & package management | Replaces Node/npm/Bun"
and had NO Bun row at all. That is the exact inversion the root
.claude/CLAUDE.md corrected on 2026-08-07, left standing in the seed.
It matters because RSR is a seed: scripts/check-package-policy.sh:12 names
rhodium-standard-repositories/spec/ as its canonical source, so every repo
graded against RSR inherited a spec telling it to migrate off the estate's
tier-1 runtime and onto a banned one. The repo also carried TWO
LANGUAGE-POLICY.adoc files asserting opposite orderings.
Six normative sites corrected, plus a v1.6.0 Amendments entry recording the
supersession with the ruling quoted verbatim, in the file's existing dated
house style:
1. ALLOWED — the *Deno* row becomes the *Bun* tier-1 row
2. BANNED — *Node.js* replacement Deno -> Bun
3. BANNED — *npm/Bun/pnpm/yarn* -> *npm/yarn*, replacement Deno -> Bun,
npm restated as tier 4 (permitted, never preferred)
4. BANNED — the *Bun* row WITHDRAWN and removed, not struck through: a
struck row in a policy table is ambiguous to the agents
that read it, which is what codacy raised on #655
5. Pkg mgmt — *JS deps*: deno.json imports -> package.json + bun.lock
6. JS/Node — reach order now Bun -> pnpm -> npm, Deno in the banned list
Verified: asciidoctor --failure-level=WARN parses clean (rc=0, no warnings),
6 table delimiters still paired, no double blank lines, and Bun now appears
in the BANNED table only as a replacement cell.
Deliberately left as history, not treated as residue: the dated "Done
2026-05-31" migration record, the project_estate_npm_to_deno_2026_05_28.md
tracker filenames, and the */bindings/{deno,ts,typescript}/ and **/.deno/**
carve-out globs — those name interop targets and compiled output, not a
runtime choice, and the matching hypatia rules still key on them.
NOT touching rhodium-standard-repositories/CLAUDE.md, and this is a
deliberate refusal rather than an oversight. That file is 877 lines with 13
ReScript mentions, 13 Deno mentions, and ZERO Bun or bunx. It still directs
agents "For frontend: Convert to ReScript" — banned 2026-04-30, destination
AffineScript. Its last commit, c46026e "retire ReScript guidance ->
AffineScript (#73)", was itself a partial sweep that left those 13 mentions
standing. A Deno-only edit would be the third partial pass on a document
stale against three separate bans, leaving it still wrong while looking
freshly reviewed; and rewriting its CADRE architecture sections to say "Bun"
would describe a design that was never built. It needs an owner authoring
decision, and is reported instead.
Also reported, not fixed: the seed .github/workflows/language-policy.yml has
13 deno hits, but 12 are path-exclusion globs (/bindings/(deno|ts)/,
affinescript-deno-test/, **/.deno/ output) and its error message already
says "Use Bun (tier 1)". It never installs or runs Deno, so the executable
surface is correct; only the stale comment at :116 ("npm banned, replacement:
Deno") is wrong.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ji1bq3TypfycfUPAR7hSxR



Owner ruling, 2026-08-26:
This file is what agents read first, and it currently says the opposite. Correcting it before touching any repo, because otherwise every future agent re-derives the wrong conclusion from the governing document.
What was wrong
package.jsonfor runtime deps" — usedeno.jsonimportspackage.json+bun.lock; Bun is npm-compatible and a manifest is requirednode_modulesin production" — Deno caches automaticallybun install --production, pinned viabun.lockdeno.jsonimports)package.json+bun.lock),bunxfor one-off toolingWhy line 187 matters most
"No
package.jsonfor runtime deps" did not merely express a preference — it told repos not to declare their dependencies at all.hyperpolymath/ubicityis the worked example: its sources importzodandglob, it had no manifest of any kind, and it therefore could not build under any toolchain — not Bun, not Node, not Deno. That was fixed in ubicity#107 by deriving a manifest from the imports. The rule that caused it is fixed here.Scope
Policy text only. No code, no workflows. 16 insertions, 5 deletions; the policy table (30 rows) and blockquote structure are intact.
Noted, not changed
Line 197 still reads "Fallback: Nix (
flake.nix)". Nix was deprecated in favour of Guix byADR-2026-STACK-MIGRATION, so that line looks stale too — but that is a separate ruling and I have not folded it into a Deno/Bun correction. Flagging for a decision.Follow-on
30 repos carry a live
deno.json— these are not orphaned config but working task runners (deno run -A npm:affinescript,deno test --allow-read). Migrating them to Bun is tracked separately, with a documented justification for any that genuinely cannot move.