Releases: Cranot/roam-code
v13.2
v13.1 — Pattern-2 propagation + shared YAML helper + 3 flagship silent-fallback seals
PyPI: https://pypi.org/project/roam-code/13.1/
Install: `pip install roam-code==13.1`
See CHANGELOG.md for the full v13.1 release notes.
Highlights:
- 3 flagship Pattern-2 silent-fallback bugs sealed (cmd_taint security-critical, cmd_health CI-gate-critical, cmd_doctor)
- Shared YAML config-loader helper (load_yaml_with_warnings); 5 of 7 callsites migrated; net ~125 LOC removed
- 5 new smell detectors (type-switch, speculative-generality, empty-catch, rename-invariant-clone, cross-layer-clone, parallel-hierarchy)
- @detector registry consolidation (Gate-1 closure)
- 14 cargo-cult `or ""` cleanups + 3 helpers None-guarded
- 26 SQL LIKE wildcard patterns hardened with ESCAPE discipline
- 30+ behavioral Pattern-2 fixes across alerts / smells / pr-risk / taint / health / doctor / suppression / sarif
- Empty-corpus smoke sweep covering 25+ detectors
No persisted-data breaks. Hash-stability mandate held.
SBOM: CycloneDX 1.5 SBOM attached as `roam-code-13.1.cdx.json`.
v13.0 — Agent-OS substrate + Laravel idioms + Vue SFC
PyPI: https://pypi.org/project/roam-code/13.0/ — see CHANGELOG.md. SBOM backfilled 2026-05-15 (v13.0 release initially shipped without a GitHub Release object due to publish.yml bug fixed by W1047).
v12.47 — internal cleanup + anti-drift CI gates
[12.47] - 2026-05-08
Internal cleanup + anti-drift CI gates
A maintenance release that scrubs internal session shorthand from source
comments, docstrings, CHANGELOG entries, and template files; aligns
surface counts across documentation; and lands four CI gates that
prevent regression.
Anti-drift CI gates (new)
tests/test_no_internal_language.py— fails any commit that
re-introduces 16 forbidden patterns: session-pass numbering, letter-
coded date markers (R5/W3/X14/etc.), "Phase X of v2 monetization plan",
internal-doc cross-references, dogfood-notes session markers, personal
Windows paths, day-job customer names, claude-memory paths, the old
cranot.github.io docs URL, CFO-objection sales-pitch language,
Greek-vendor exclusion clauses.scripts/sync_surface_counts.py— single source of truth via
roam.surface_counts+roam.languages.registry. Dry-run reports
drift;--writerewrites README + llms-install + server.json.scripts/linkcheck.py— walks every tracked landing-page HTML and
asserts every internal href + #anchor resolves.--externaloptional.scripts/strip_metadata.py— scans every tracked PDF / PNG / SVG
for identifying metadata; dry-run reports leaks,--writerewrites
files with neutral metadata.- All four wired into
.github/workflows/roam-ci.ymlas a new
doc-hygienejob that runs on every PR.
Source comments + tests
- Bulk-scrubbed ~110 source files of internal session prefixes
(numbered "Pass" comments, letter-coded date markers, "Phase-N
polish", "Python-pivot dogfood" annotations). cmd_audit.py+cmd_audit_trail_export.py+cmd_postmortem.py+
cmd_article_12_check.py+cmd_permit.pydocstrings rewritten as
neutral product descriptions.- Restored
if not include_tooling:guard +excluded_tooling = 0
initializer +from roam.output.file_role_hints import is_excluded_path
incmd_smells.py(fixed an indentation regression caught by the
test suite). - Renamed regression-FP corpus fixtures to neutral names; per-entry
description prefixes scrubbed.
Documentation + product naming
- Audit deliverable name reframed: "AI Agent Readiness Audit" →
"PR Replay" on landing-page upsell + "Codebase Architecture Audit"
on legal templates and the audit-report template/sample/PDF. - DPA + SOW master template generalized: dropped Stripe-Atlas /
Greek-IKE entity-structure language; tier rows replaced with
bracketed placeholders. templates/legal/security-procurement-packet.md— links into
docs/strategy/...replaced with public roam-code.com/pricing URL.templates/email/customer-journey.md— hard-coded "— Dimitris"
signature replaced with[YOUR_NAME]placeholder.- README + llms-install + server.json + mcp-server-card.json
surface counts: 194 → 202 commands, 27 → 28 languages,
5 → 6 cross-language bridges (Django bridge added). - Old
cranot.github.iodocumentation URL replaced with
roam-code.com/docs/across 9 tracked files (config, source,
tests, docs).
History rewrites
- Six force-pushes during the cleanup sweep, each documented in the
newinternal/runbook-history-rewrite.md(gitignored). Removed from
history: 27 strategic / internal docs (docs/strategy/*,
docs/products/*,dev/REPORT-*.md,dev/CODE-BACKLOG.md,
dev/COMPETITOR-WATCH-*.md,templates/distribution/landing-page-spec.md,
Greek-vendor-exclusion templates), 5 session-named regression-FP
fixtures (renamed to neutralcorpus_*.jsonpaths). - Author rewrite: 389 commits authored as "CosmoHac" + 11 commits
authored as "Claude" rewritten to "Cranot" so GitHub Insights shows
uniform attribution. Third-party contributors (Chuck Jewell, holive,
Mark Ramsell, Livio Ravetto) untouched.
pyproject.toml
authorsupdated toCranot(wasCosmoHac).
v12.28 — detector quality round: 14 FP fixes + suppression mechanism
Patch on top of 12.27
Detector quality pass driven by user feedback after running roam math / over-fetch / missing-index / auth-gaps on a real multi-tenant Laravel + Vue 3 codebase. 14 systematic false-positive patterns fixed, plus a three-path suppression mechanism so verified FPs stop showing up on every run.
Math (`roam math` / `algo`)
- M1 — findings now point at the exact AST node, not the enclosing function. User: "highest single-leverage UX fix on its own — cuts triage time in half."
- M2 — `if (depth > limit) return` early-return guards now recognised as bounded recursion (was only matching `<` continue form). Plus Set/Map/WeakSet param detection. Real-world: `deepEqual` no longer flagged as O(2^n) when guarded.
- M3 — cache-vs-IO distinction expanded: Apollo (`client.readQuery` / `cache.modify`), SWR (`mutate`), TanStack lifecycle (`invalidateQueries` / `removeQueries` / `cancelQueries`), native collections (`Map.has` / `Set.delete` / `WeakMap.set`).
- M4 — DEV-only block recognition: `import.meta.env.DEV` / `DEV` / `process.env.NODE_ENV !== 'production'` / `if (DEBUG)` / `console.assert` demote findings inside them.
- M5 — sort-then-subscript with full iteration → demoted (display-order pattern, not min/max).
- M6 — every finding carries a `to_suppress` evidence block.
- M8 — confidence floor: `branching-recursion` + `sort-to-select` cap at "medium" unless runtime-hot.
Missing-index (`roam missing-index`)
- M9 — `protected $table = '...'` now read cross-file as source of truth. Eliminates 6/6 high-confidence FPs from `advances`/`payments`/`reminders` model overrides.
- M13 — multi-tenant per-schema migrations recognised: `Schema::connection('payroll')->create("{$schema}.payroll_advances", ...)` now matched + table prefix normalised.
Auth-gaps (`roam auth-gaps`)
- M10 — non-auth route guards (`throttle` / `signed` / `verified` / `can` / `scope`) flagged at "low" with "intentional public-but-protected" note instead of high-confidence "missing auth".
- M11 — tenant-scoped controllers (`officeScoped()` / `multiTenant()` / `Resource::for(...)` / `forTenant()` / `belongsToCurrentUser()` / `currentTeam()`) recognised as authorization-equivalent. Real-world: ~115 FPs eliminated.
Over-fetch (`roam over-fetch`)
- M12 — direct-return scan is now method-body-scoped, not file-level. Previously: any controller importing `LedgerAccount` could be flagged for over-fetching it just because `return $aadeService->getDocs()` matched the generic `return $var;` pattern. Now: model must actually be USED in the same method body.
Suppression mechanism (M7) — three layered paths
- Inline annotation — `# roam: ignore-math[branching-recursion]` on the symbol line. Bare `# roam: ignore-math` covers all task-ids on that line. `[*]` covers all. Supported across all four detector commands.
- `.roamignore-findings` — repo-level YAML/JSON with `task_id` + `path_glob` rules.
- `.roam/suppressions.json` via new `roam suppress --reason "…"` command. Each finding now carries a deterministic `finding_id` (sha256 truncated to 16 chars) so suppressions survive reindex.
Suppressed findings stay in the JSON envelope (under `finding["suppressed"]`) so consumers can detect over-suppression. Text output filters them by default.
M14 — verdict line truth
When suppressions fire, the verdict reads "N unsuppressed candidates surfaced; M suppressed via .roamignore-findings / inline annotation / suppressions.json" instead of just "N findings".
Surface counts
- CLI: 186 → 187 (+1: `suppress`)
- MCP tools: 136 (unchanged)
- Core preset: 49 (unchanged)
Tests
198 detector tests pass (+72 new across `test_math_fp_fixes.py` (22), `test_finding_suppress.py` (20), `test_laravel_fp_fixes.py` (16)). 405 v2 tests still pass — no regressions.
Install
```bash
pip install roam-code==12.28
```
Full changelog
See CHANGELOG.md.
v12.27 — round-5 polish: 15 v2 improvements, no surface bump
Patch on top of 12.26.1
Round-5 polish + dogfood pass. 15 small-to-medium improvements, no new top-level commands, no surface count changes (still 186 / 136 / 49). First release shipped end-to-end via the new tag-triggered Trusted Publishing workflow — no manual twine.
New flags + features
- `roam pr-analyze --diff-from-pr URL` — fetch GitHub PR diff via `gh pr diff`. Smoke-tested against fastapi#15482.
- `roam pr-analyze --watch SECONDS` — poll diff source; re-run on change. Local dogfood mode for refactor sessions.
- `roam pr-analyze --batch --stream-jsonl` — emit per-file rows as JSONL lines as soon as they complete. Long batches feel responsive.
- `roam pr-analyze --audit-trail` auto-runs conformance check — Article 12 score attached to envelope on every emission. Surfaced inline as `conformance: NN/100`.
- `roam audit-trail-export --top-actors N` — procurement-friendly hot list ranked by BLOCK count.
- `roam rules-validate --fix` — auto-coerce safe schema mistakes (severity casing, glob whitespace). Skips real typos.
- `metrics-push --include-pr-analysis` now includes conformance score — Cloud Lite Growth dashboard input.
- `_compute_drift` per-rule breakdown — distinguishes "rule fired this PR for the first time" from "existing rule's violation count changed".
Content additions
- `templates/rules/kotlin/.roam-rules.yml` — 12-rule Kotlin starter pack (Android + Spring lanes).
- `templates/rules/rust/.roam-rules.yml` — 12-rule Rust starter pack.
Total starter packs now: 6 (Python, TypeScript, Go, Java, Kotlin, Rust).
CI hardening
- publish.yml triggers on tag push + release + workflow_dispatch
- `skip-existing: true` for idempotency (manual twine no longer collides)
- Build job verifies wheel contains ≥8 v2 command files before PyPI sees it
Internal
- `_build_rationale` cc=39 → <23 split into per-concern collectors + `_compose_next_steps` + `_extract_suggested_reviewers`
- `_emit_batch` cc=48 → 26 split into `_run_batch_serial` + `_run_batch_parallel`
- 17 new unit tests in `tests/test_pr_analyze_helpers.py` covering the small helpers
- README v2 quickstart subsection — `git diff | roam pr-analyze` now in main Quick Start
Tests
405 v2 + adjacent tests pass (was 386 in 12.26.1). +19 new tests across 4 files.
Install
```bash
pip install roam-code==12.27
roam --version
roam dogfood
```
Full changelog
See CHANGELOG.md.
v12.26.1 — Go/Java rule packs, dogfood CI, conformance --sarif
Patch on top of 12.26
No new CLI commands, no surface count changes (still 186 / 136 / 49). Three real improvements driven by integration testing this round:
Added
audit-trail-conformance-check --sarif— emit SARIF 2.1.0 envelope with failed checks as findings. Drops directly into GitHub Code Scanning UI. Each rule'shelpUripoints at https://artificialintelligenceact.eu/article/12/.templates/rules/go/.roam-rules.yml— 12-rule starter pack: no-unsafe, no-cgo, no-md5/sha1, no-panic, no-init-funcs, hallucinated imports, layer violations.templates/rules/java/.roam-rules.yml— 12-rule starter pack: no-Runtime.exec, no-System.exit-in-libs, no-ObjectInputStream (deserialization RCE), no-printStackTrace, no-raw-types, no-Thread.stop, layer violations..github/workflows/dogfood.yml— self-CI workflow for roam-code itself. Runsroam dogfoodon every PR + push, posts a sticky PR comment viaroam pr-comment-render, uploads the audit trail as a workflow artifact. Eat our own cooking publicly.
Fixed
_save_baselinenow stamps_meta.timestampat save time. Without this,pr-comment-render --from-baselinesilently couldn't compute baseline age (the "saved X days ago" line never fired). Caught by the new end-to-end integration test.
Internal
- Cognitive complexity reductions (continued from 12.26):
_build_payloadcc=49 → split into_extract_metrics+_extract_hotspots+_build_last_pr_blockhelperspr_analyze(the command coordinator) cc=38 → extracted_serve_from_cache+_apply_drift+_emit_audit_trail
- New
tests/test_v2_integration.py— 3 end-to-end tests exercise the whole v2 pipeline. Catches schema drift across the chain. - Cache stress-test on a 30-real-commit batch: 54.7× warm-cache speedup (60s cold → 1.1s warm) sequentially; 2.55× cold speedup with
--parallel 4. - Real-OSS validation: ran pr-analyze on 3 small human-written PRs (fastapi#15482, requests#7401, httpx#3773); all SAFE with AI-likelihood 13-23. Confirms scorer doesn't false-positive on legitimate human work.
Install
pip install roam-code==12.26.1
roam --version
roam dogfoodFull changelog
See CHANGELOG.md.
v12.26 — Roam Agent Review + Cloud Lite engines + EU AI Act audit-trail toolkit
What's new
8 new CLI commands + 8 new MCP tools shipping the v2 monetization layer.
Roam Agent Review (PR-bot engine)
roam pr-analyze— agent-aware PR risk verdict (INTENTIONAL / SAFE / REVIEW / BLOCK). 9-signal AI-likelihood scoring (add/remove ratio, comment density, test coverage, function-size variance, generic naming, orphan imports, placeholder density, LLM-phrase fingerprints, suspicious imports). Language-aware weights..roam/rules.ymlenforcement (4 pattern types). Drift detection.--gate,--audit-trail,--batch DIR --parallel N,--cache,--quiet,--rules-strict.roam pr-comment-render— markdown PR comment from the envelope. Before-after drift rendering, regression banners, plain-English signal explanations, baseline-age line.
Roam Cloud Lite (metrics-history engine)
roam metrics-push— push metrics-only summary (no source code) to Roam Cloud Lite.--anonymizeSHA-256 hashes paths.--include-pr-analysisfolds last-PR verdict + age + stale fields.--dry-rundefault-safe.
EU AI Act Article 12 audit-trail toolkit
roam audit-trail-verify— SHA-256 chain integrity verifier.--gateexits 5 on broken chain.roam audit-trail-export— markdown / JSON / CSV export with date / verdict filters.--aggregatefor procurement summary tables.--finalizewrites a closing AuditIntegritySummary record.roam audit-trail-conformance-check— score the trail against an Article 12 6-check checklist.--gateexits 5 on score < 100. Triage signal — not legal advice.
Production tooling
roam rules-validate— lint a.roam/rules.ymlfor typos, schema mistakes, unknown patterns, duplicate IDs, unbalanced glob brackets.--against DIFFdry-runs.--strict+--gatefor CI.--explainprints pattern reference.roam dogfood— one-shot v2 stack runner: audit + pr-analyze + audit-trail + conformance in one envelope.
Distribution surface
templates/rules/{python,typescript}/.roam-rules.yml— 14-rule starter packs each, validated clean.templates/examples/.roam-rules.yml— example pack covering all 4 pattern types.src/roam/templates/ci/agent-review.yml— drop-in GitHub Actions workflow.- README.md gains dedicated "Roam Agent Review" + "Roam Cloud Lite" sections.
Internal
- Shared
git_helpers+audit_trail_helpersmodules eliminate ~120 lines of duplicated subprocess + JSONL-loading code. - 5 functions refactored to drop cognitive complexity below the project's 99-cc gate (
_compute_ai_likelihood110→<28,_render_github_markdown101→<28,_load_rules_yaml71→<23,_emit_batch48→26,_build_rationale39→<23). - Cache speedup measured: 24.5× cold→warm on a 5-real-commit batch.
Surface counts
- CLI commands: 178 → 186
- MCP tools: 128 → 136
- Core MCP preset: 41 → 49
Tests
- +280 new tests across 14 new test files. 383 pass in the targeted v2 sweep.
Install
pip install roam-code==12.26
roam --version
roam dogfoodLicense
Apache 2.0 (unchanged from 12.23).
Full changelog
See CHANGELOG.md.
v12.25 — QueryCursor shim for tree-sitter < 0.24
12.24 narrowed the fastmcp marker so 3.9 stopped failing at install. The next failure: from tree_sitter import QueryCursor in query_engine.py — QueryCursor was added in tree-sitter 0.24 but Python 3.9 pins to 0.23.x (newer versions need >= 3.10).
This was also a real runtime bug — any Python 3.9 user installing roam-code from PyPI would have hit ImportError on first index of a YAML-extractor language.
Fix
try:
from tree_sitter import QueryCursor
except ImportError:
# tree-sitter 0.23 exposes .matches/.captures on Query directly
class QueryCursor:
def __init__(self, query): self._query = query
def matches(self, root): return self._query.matches(root)
def captures(self, root): return self._query.captures(root)Once 3.9 support drops the shim can go.
Install: pip install --upgrade roam-code
v12.24 — narrow fastmcp marker for Python 3.9
12.23 added fastmcp>=2.0 to [dev] without a Python-version marker, but fastmcp >= 2.0 requires Python >= 3.10. The 3.9 CI lane therefore failed at pip install. Marker is now fastmcp>=2.0; python_version >= '3.10' so 3.9 skips the install. The MCP-runtime test already guards on _HAS_FASTMCP (12.23) so 3.9 simply skips that single assertion.
Install: pip install --upgrade roam-code