Skip to content

Releases

v0.10.0 — Understand the codebase, not just check it

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 30 Jul 18:03

New: codebase-comprehension features

Conformance checking tells you what's wrong. It doesn't help someone dropped
into an unfamiliar repo actually understand what's there. This release adds
that, fully language-agnostic — no framework- or ecosystem-specific parsing.

  • ## Start here in archsteer docs/report — ranks core components
    by how much internal code depends on them, and separately lists likely
    entry points (real exported APIs, nothing internal depends on them).
  • ## Component map — a real file-to-file Mermaid dependency graph,
    capped to the 25 most-connected components. The existing layer diagram
    only ever drew layer-to-layer arrows; this shows the actual edges, e.g.
    two different controllers sharing the same dependency.
  • archsteer graph <path> — one component's direct dependencies and
    dependents. No archsteer init/declared intent required — same posture
    as archsteer xray, built for "I just cloned this and need to orient."
  • MCP: current_architecture() now surfaces core components + entry
    points; new component_neighbors tool for an agent mid-task.

Validated against Spring PetClinic (Java) and Dreamhouse LWC (Apex/LWC) —
no change to conformance scoring, purely additive read-only surfaces.

Full Changelog: v0.9.1...v0.10.0

v0.9.1 — SQL-prose false positives, nested-source-root Python imports

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 25 Jul 01:55

Fixes

  • SQL-literal detection no longer misfires on ordinary prose. Strings like "Select a model", "Explicitly select terminal rendering", or "Could not update detection rule" were being read as raw SQL. The heuristic now requires an UPDATE to have a real SET clause and a SELECT to have a real FROM clause (with the entity extracted from that clause, not guessed from the first token) — bounded to the actual containing string/line, not scanned hundreds of lines ahead. Verified on the PetClinic benchmark: a garbled ptype data-store entity is now correctly PetType; on Dreamhouse LWC, a spurious single-letter a entity is gone and conformance ticks up from 95.3% to 95.9%.
  • Python absolute imports below a nested source root now resolve. tools/python/mypkg/api.py importing mypkg.store (where tools/python is the real sys.path root, common in monorepos) previously stayed unresolved/external. Resolution is conservative: only a unique unambiguous path-suffix match resolves — if two packages could plausibly satisfy the same dotted import, it correctly stays external rather than guessing.
  • Intel macOS installs stay on a working cryptography wheel. Pinned cryptography<49 so pip install archsteer doesn't fall back to a Rust source build on Intel Macs, where a compatible prebuilt wheel exists on the 48.x line.
  • README: clarified the local first-run flow and where to send feedback.

Validation

40 tests (up from 34), all passing. Spring PetClinic and trailheadapps/dreamhouse-lwc benchmarks re-verified — no regressions, and the SQL-prose fix visibly cleans up both.

Full diff: v0.9.0...v0.9.1

v0.9.0 — Fixes a phantom-worktree bug, adds Next.js App Router support

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 24 Jul 19:57

The headline bug fix

Dogfooding archsteer on its own repo surfaced a real, embarrassing bug: .claude/ was never in the ignore list. A Claude Code subagent's git worktree under .claude/worktrees/<id>/ is a full duplicate checkout of the repo — scanning it double-counted every component, and in one sample run, 100% of the reported "raw SQL" violations turned out to be phantom (0% were real). This affects every user running archsteer inside a Claude Code project, not just this repo. .cursor/, .hg/, and .svn/ are now excluded too.

Next.js App Router support (new)

  • New nextjs-app-router starter pack — layers inferred from Next.js's own reserved filenames (page.tsx → page, layout.tsx → layout, route.ts → api, regardless of directory) before falling back to directory names. Rules: data access (Supabase/Prisma/raw SQL) and third-party calls confined to lib/ or a route handler; no hardcoded secrets.
  • init now tells a real Next.js App Router app apart from an Express repo migrating to Next — next + an app/ dir + no express gets the new pack; anything with express still gets the migration-flavored express-to-next pack, even once next shows up as a dependency.
  • Supabase query detection — .from("table").select(/insert/update/upsert/delete)(...), including calls chained across lines, now registers as data access (same as the existing Prisma/SQLAlchemy/raw-SQL detectors).

Two false-positive fixes with broad real-world impact

  • fetch('/api/x') is no longer flagged as an external call. A component calling its own Next.js route handler was previously indistinguishable from fetch('https://stripe.com/...') — same-origin relative-path fetches are now excluded, and absolute URLs get a real hostname as the destination label instead of a generic HTTP_CLIENT_CALL.
  • @/lib/x-style imports now resolve to real internal edges. This is the default alias in every create-next-app project — without tsconfig.json/jsconfig.json paths resolution, every one of these imports was textually indistinguishable from a third-party package, leaving the layer diagram edge-less on most real Next.js/TS repos. (Along the way, fixed a bug in the JSONC comment-stripper itself: it read the / inside the string "@/*" as a block-comment start and corrupted the JSON — fixed with a string-literal-aware tokenizer.)

Validation

Re-ran end to end on archsteer's own web/ app: unassigned components dropped from 52% to 14%, the Mermaid diagram went from zero edges to a real page→lib, page→ui, ui→lib, layout→ui, api→lib picture, and the conformance score is now a genuinely exercised 100% (real Supabase calls and real external calls are present and correctly placed) rather than a vacuous one computed against rules that didn't apply to the repo at all. Spring PetClinic (100%) and trailheadapps/dreamhouse-lwc (95.3%) benchmarks unchanged — no regressions.

Full diff: v0.8.0...v0.9.0

v0.8.0 — Incremental parse cache + pre-push quality-score hook

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 23 Jul 13:26

Faster on real repos

Profiling on nestjs/nest (~1700 TS files) showed archsteer check taking 2.9–7s per run — too slow for something meant to run on every git push. The bottleneck was re-parsing every file on every invocation regardless of what actually changed.

build_model now caches each file's extracted component keyed by a content hash in .archsteer/parse_cache.json (gitignored, machine-local). Unchanged files reuse their cached result; only changed files get re-parsed and re-scanned. Cross-file edge resolution still runs over the full component set every time, since a file's imports can resolve differently when other files change. Measured on nestjs/nest: 2.9s cold → ~1.0s warm, whether nothing changed or a single file did. The remaining ~1s is fixed CLI/interpreter startup overhead this change doesn't touch.

Quality score before every push

archsteer check now prints a one-line readout — conformance %, delta since the last snapshot, and net-new violation count — every time it runs, not just on failure.

New archsteer install-hooks wires check into a local git pre-push hook: same non-blocking-on-existing-debt ratchet already used in CI (blocks only NET-NEW error violations), just earlier feedback than waiting for CI. Won't clobber a hook it didn't write without --force; --uninstall removes it cleanly. Already on husky/pre-commit/lefthook? The README now shows wiring archsteer check into those instead.

Also fixes a dead README reference to a hooks/pre-commit file that didn't actually exist in the repo.

Full diff: v0.7.0...v0.8.0

v0.7.0 — Security baseline: hardcoded secrets, external-call layering

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 23 Jul 13:06

New rule types

  • forbidden_security_finding — flags hardcoded credentials, API keys, and tokens via a language-agnostic regex scan over raw source text: variable-name-shaped assignments (password = "...", api_key: "...") plus high-confidence literal patterns for AWS access keys, GitHub/Slack tokens, and PEM private-key blocks. Runs once per file during archsteer map, independent of per-language parsing — covers every extension archsteer already visits, with env-lookup and placeholder-value exclusions to keep false positives down.
  • required_layer_for_external_call — confines outbound HTTP/SDK calls (and Salesforce Apex callouts) to a declared layer, mirroring the existing required_layer_for_data_access check but over external calls instead of data access.

Security baseline in every starter pack

java-spring, salesforce, python-service, and express-to-next all now ship two additional rules out of the box, each backed by a new ADR:

  • no-hardcoded-secrets (error)
  • external-calls-only-in-service (warn) — callouts confined to the service layer in Salesforce, service layer elsewhere

Validation

Spring PetClinic stays 100% conformant with the new rules active (no false positives). trailheadapps/dreamhouse-lwc's existing violations are unchanged — zero new noise introduced by the security rules. The repo's own dogfooded architecture.yaml now adopts no-hardcoded-secrets too.

Full diff: v0.6.0...v0.7.0

v0.6.0 — ADR drafts for widespread rule violations

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 18 Jul 00:35

New

archsteer adr only ever looked backwards — it diffed the current snapshot against the previous one, so a repo's existing, systemic violations (SOQL scattered across a dozen controllers, say) never surfaced as anything an architect could act on. check/govern just listed them one by one.

Added a second, complementary source: a rule violated across 3+ components in the current snapshot is drafted as its own ADR — a standing architectural question ("ratify this as accepted debt, or the rule is wrong for this codebase") regardless of whether time has passed since the last map. Wired into adr, xray, report, and push alongside the existing diff-based drafts.

  • A single violation isn't a pattern — check/govern already surface those individually; this only fires on genuine repetition.
  • Idempotent: the draft's slug is derived from the rule id, not the violation count, so re-running as counts drift never duplicates a draft already on disk.
  • Distinguishes rules that already have a backing ADR (rule.adr in architecture.yaml) from ones that don't, and tailors the context accordingly.

Validation

Same benchmark pair used for 0.5.0: trailheadapps/dreamhouse-lwc (86.4% conformant) now drafts a real ADR reviewing soql-only-in-selectors against its 6 violating files. Spring PetClinic (100% conformant) and archsteer's own dogfooded repo both stay silent, as they should — no violations, nothing to review.

Full diff: v0.5.0...v0.6.0

v0.5.0 — Java + Salesforce Apex support

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 18 Jul 00:21

New languages

The engine parsed JS/TS and Python only — Java and Salesforce repos x-rayed to zero components. Both are now first-class:

  • Java (.java) — layers inferred from Spring annotations first (@RestController/@Controller → controller, @Service → service, @Repository → repository, @Entity → model), then Spring Data repository interfaces (extends JpaRepository/CrudRepository/...), then class-name-suffix fallback (*Controller, *Service, *Repository/*Dao). Imports resolve to internal dependency edges; JDBC/JPA calls register as data access.
  • Salesforce Apex (.cls, .trigger) — since Apex has no imports, dependency edges come from resolving type references (new X(), extends, implements, static calls) against the org's own class names. SOQL registers as a read, DML as a write/delete. Layers come from Salesforce naming convention (*TriggerHandler → handler, *Controller → controller, *Service → service, *Selector → repository, *Domain → model, *Batch/*Queueable/*Schedulable → job, triggers get their own layer).

Starter packs + auto-detection

archsteer init now inspects the repo for build manifests (pom.xml/build.gradle → java-spring, sfdx-project.json/force-app → salesforce, pyproject.toml/setup.py/requirements.txt → python-service, else express-to-next) and seeds a matching baseline architecture.yaml + ADRs — real rules on first run, not a blank slate. Override with --pack if the guess is wrong.

  • java-spring: persistence only in repositories; controllers must not touch repositories directly
  • salesforce: SOQL only in selectors; no DML in triggers or controllers
  • python-service: persistence only in repositories; API layer must not touch repositories directly

Validation

Benchmarked against real repos: Spring PetClinic scores 100% conformant on the java-spring pack (reference app — any violation there means a broken heuristic). trailheadapps/dreamhouse-lwc genuinely violates the salesforce pack (~29 SOQL-in-controller findings) — a positive control confirming the rules fire correctly on real code.

Full diff: v0.4.2...v0.5.0

v0.4.2

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 18 Jul 00:21

Fixes

  • archsteer steer crashed on real repos that already had a .cursor/rules/ directory (Cursor's own convention) — the CLI tried to write a file where a directory existed. Steering now targets .cursor/rules/archsteer.mdc directly and injects proper frontmatter (alwaysApply: true) into empty or frontmatter-less .mdc files.
  • MCP registry server.json used a deprecated schema (2025-07-09 snake_case) — the live registry validates against 2025-12-11 camelCase. Fixed field names and trimmed the description under the registry's 100-char limit.

0.4.1 (rolled into this release — no separate tag was pushed)

  • Python dependency resolution was broken: relative imports (from .x, from ..pkg.mod) and same-package absolute imports (from mypkg import mod) were never resolved to internal edges — only JS/TS relative imports were. Every Python repo's model.json showed zero internal dependencies. Fixed.
  • Manifest dependency extraction now reads project.dependencies (runtime only) via tomllib instead of a regex that swept up dev-tooling strings and license identifiers.
  • mcp promoted from an optional extra to a base dependency — uvx/registry runners can't express extras, so archsteer mcp was failing on a plain install for exactly the agentic audience the MCP listing targets.
  • archsteer now dogfoods itself: ships its own architecture.yaml (engine must not import cli/steer/docs/mcp; stays network-free) and passes archsteer check clean.
  • Listed on the official MCP registry (io.github.einvoice-dev1/archsteer).

Full diff: v0.4.0...v0.4.2

v0.4.0

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 02 Jul 23:09

ArchSteer CLI 0.4.0

  • New: archsteer mcp — a local MCP server so agents (Claude Code, Cursor, etc.) query the live model + declared intent mid-edit. Runs over stdio, spawned by your own editor — no cloud, no auth, no account. Free with the CLI.
    • current_architecture — component/layer counts, conformance/drift, target.
    • get_target_pattern — the invariants for a file, before you write to it.
    • check_file — whether a file conforms, without waiting for CI.
  • Optional dependency: pip install "archsteer[mcp]".

Install: pipx install --upgrade archsteer && pipx inject archsteer mcp
Docs: see the README's "Using with AI agents (MCP)" section.

v0.3.0

Choose a tag to compare

@einvoice-dev1 einvoice-dev1 released this 02 Jul 22:18

ArchSteer CLI 0.3.0

  • archsteer push now reports your repo URL (auto-detected from the git remote) so the situation room deep-links to each repo's committed living docs.
  • report.html now has a footer linking back to the situation room.

Install: pipx install --upgrade archsteer