From df667b40f0029aea749e0989b9db9e5b130353d8 Mon Sep 17 00:00:00 2001 From: Kevin Longe <273747162+kvlonge@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:54:35 +0000 Subject: [PATCH 1/3] docs(readme): add restrained SQLStack branding Amp-Thread-ID: https://ampcode.com/threads/T-01a1970c-7c44-7042-b987-dc3926e29427 --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 93091018..7317575b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@
-
+
+
+ by SQLStack
@@ -378,3 +385,11 @@ for the complete API and configuration.
The quickstart, architecture model, configuration reference, adoption guide, and
CLI reference live at [docs.fensu.dev](https://docs.fensu.dev).
+
+## Part of SQLStack
+
+
-
+
+
by SQLStack
- Keeping Python, TypeScript, JavaScript, Svelte, and Rust repos from turning into spaghetti. -
- -Fensu means "fence" in Japanese.
- -**Most linters catch bad code inside files. Fensu catches architectural drift: -code crossing the wrong boundary, living in the wrong module, or growing into the -wrong shape.** - -As a repository grows, code moves, lessons get forgotten, and the mental map -decays. Tests preserve behavior and types preserve interfaces. Fensu makes the -repository's architectural expectations executable. - -Fensu enforces: +Fensu checks repository architecture: **import boundaries, module roles, and function +shape** for Python, Rust, TypeScript, JavaScript, and Svelte. -- which layers may import which; -- what each module or role file may contain; -- whether orchestrator functions stay small; -- whether dataflow and mutation are explicit; -- whether names such as `validate_*` mean what they claim. +- **Boundaries:** stop one domain from importing another domain’s private helpers. +- **Roles:** keep entry points, helpers, models, and types in their owning modules. +- **Function shape:** keep orchestrators small, dataflow explicit, and signatures clear. -It ships a coherent default architecture rather than a blank rule framework, then -lets projects disable, extend, or replace parts deliberately. +Fensu is pre-release and self-hosting. It ships an opinionated default architecture, +not a blank rule framework; tune or replace policies deliberately. -Fensu is functional and self-hosting, but remains pre-release. +## Get started -## Installation +Requires **Python 3.12+**. Install in your project’s Python environment: ```bash pip install fensu ``` -The authoring/API distribution is `fensu`. It installs the lockstep -`fensu-cli` binary package, which exclusively owns the `fensu` command. -Core-only `check`, `dupes`, `init`, `rule`, `map`, `skills`, and `--version` -execution is native. Configured Python custom rules launch one compatible Python -host only for the policy metadata or callbacks they require. - -Built-in commands are available only through the native `fensu` executable; -`python -m fensu` is retired. Installing `fensu-cli` from its source -distribution requires Rust 1.95 or newer. - -Fensu requires Python 3.12+ and includes a compiled analysis core. Prebuilt -wheels cover Linux (x86_64, aarch64), macOS (Intel, Apple silicon), and Windows -(x86_64). On other platforms, `pip` builds from source and requires a Rust -toolchain at version 1.95 or newer. - -## Quick Start - -From the directory containing an existing repository's `pyproject.toml`, detect -the layout, write a validated configuration with the full ruleset enabled, run an -initial check, and install repository-local agent guidance: +From an existing Python repository’s `pyproject.toml` directory: ```bash fensu init --yes -``` - -For an empty repository, provide the package name to scaffold `src/` and `tests/`: - -```bash -fensu init --yes --name my_package -``` - -Pass `--no-skills` only when automation explicitly requires configuration without -repository-local guidance. Do not call onboarding complete until this succeeds: - -```bash fensu skills --check -``` - -Then run: - -```bash fensu check ``` -To configure manually instead, add a minimal `fensu.toml` at the repository root: +`init` detects the layout, writes `fensu.toml`, measures current drift, and installs +repository-local agent guidance. It detects complete SvelteKit projects too; see +[web targets](https://fensu.io/docs/concepts/analyzers/typescript-sveltekit/). +For an empty repository, use `fensu init --yes --name my_package` instead. -```toml -roots = ["src/my_package"] -``` +Already configured? `init` leaves existing configuration unchanged. Run +`fensu skills` to install or refresh guidance, then verify it with `--check`. +Unmanaged skill files are preserved unless you explicitly pass `--force`. +Use `init --no-skills` only for deliberate configuration-only automation. -`tests` defaults to `["tests"]`, `tooling` is optional, caching is enabled by -default, and every rule family is on by default. Install and verify agent guidance -after writing configuration manually: +`check` exits **0** with no blocking faults, **1** when it finds faults, and **2** +for setup/configuration errors. Put `fensu check` in CI to enforce the policy. -```bash -fensu skills -fensu skills --check -fensu check -``` - -Product roots and tooling receive structural rules; tests receive test-convention -and annotation rules. - -### Rust workspaces - -Rust rules run directly in the `fensu-rust` analyzer through the normal Fensu CLI. -Configure a Cargo workspace in `fensu.toml`: - -```toml -[targets.rust] -analyzer = "rust" -roots = ["crates"] -tests = [] -tooling = [] -rule_packs = ["rust"] -select = ["FPRS"] -``` +New and small repositories are the easiest starting point. On established codebases, +expect drift: use [adoption boundaries and explicit exceptions](https://fensu.io/docs/adoption/) +rather than making unsafe structural changes just to reach zero. +Rust projects use [Cargo-aware target configuration](https://fensu.io/docs/concepts/analyzers/rust/). +See [installation details](https://fensu.io/docs/quickstart/#1-install) for wheels and source builds. -Run `fensu check --target rust`. Cargo discovers workspace members, package names, and targets; -use `roots = ["src"]` for a single-package repository. The Rust pack enables all 120 `FPRS*` -rules, covering layout, imports, dependency boundaries, naming, function shape, hygiene, and -test conventions. Existing structural thresholds are the defaults. +## A finding and its fix -Adjust individual rules in the same file: +An order entry point importing inventory’s private helper crosses a domain boundary: -```toml -[targets.rust.rule_options.FPRSS010] -max_arguments = 8 +```python +# src/shop/orders/main/submit.py +from shop.inventory._helpers.reserve import reserve ``` -Selection, warnings, ignores, file exceptions, and caching use the usual Fensu settings. -Cargo manifests, the lockfile when present, Rust sources, and target configuration participate -in cache identity. Analysis does not create or update a lockfile. -See [Rust analyzer configuration](docs/rust.md) for rule options and tooling boundaries. - -Python projects can opt into [production dead-code enforcement](docs/dead-code.md) with -`[dead_code] enabled = true`. Reachability faults cover module-level definitions and modules; -reasoned roots describe dynamic entry mechanisms. Tests and `main/` placement are not roots. - -## Default Structure - -The default architecture follows SQLBuild Compiler Rules v0.101.1. - -Product code uses domain, optional subdomain, then role. Every leaf domain or -subdomain owns meaningful behavior through a direct `main/` containing at least one -entry module. Branch-domain parents do not need their own `main/`; their leaf -subdomains do. Tests mirror the code they cover; tooling uses one ownership level -because `scripts/` already establishes the outer boundary. +Excerpt from a real `fensu check --no-color` run with `FFL102` selected: ```text -src/my_package/ -└── domain/ - └── subdomain/ - ├── main/ - │ └── run.py - ├── _helpers/ - ├── classes/ - ├── models.py - ├── types.py - ├── constants.py - └── exceptions.py -tests/unit/src/my_package/domain/subdomain/ -├── _test_types.py -└── test_run.py -scripts/ -├── run_tool.py -└── tool_name/ - ├── main/ - ├── _helpers/ - └── classes/ +FFL102 import 'shop.inventory._helpers.reserve' reaches into internal structure of 'shop.inventory' + --> src/shop/orders/main/submit.py:1:0 + = help: Import from classes, models, types, constants, exceptions, or a thin main/ entry. ``` -Do not create an empty or initializer-only `main/` to satisfy the layout. If a -package contains only passive models, types, constants, exceptions, or classes, -move those declarations into the closest domain or subdomain whose `main/` behavior -owns and uses them. Fixed role files are siblings of `_helpers/`, never descendants -such as `_helpers/entry/models.py`. - -Direct `scripts/*.py` files are thin command adapters. Supporting logic belongs -under `scripts/]`, and checks read the validated current value through
-`ctx.option()`. Rules can also use `ctx.facts`, `ctx.project`, `ctx.text`, `ctx.syntax`, and
-`ctx.relations`; these are the same backend-neutral analysis zones used by Fensu's
-built-in rules. Project and filesystem reads made through `ctx.project` are tracked
-for cache invalidation. Raw `ast.Module` access remains available for checks that need
-unrestricted Python syntax traversal. Semantic fact contracts and author-facing models
-are public Python APIs, while their production extraction has one native Rust owner;
-raw AST, syntax, and relation artifacts remain lazy CPython capabilities. Keep
-project-owned checks in the canonical
-`scripts/fensu_policy/rules/` tooling role and load them explicitly:
-
-```toml
-tooling = ["scripts"]
-rule_paths = ["scripts/fensu_policy/rules"]
-```
-
-See the [custom-rule guide](https://docs.fensu.dev/concepts/custom-rules)
-for the complete API and configuration.
+src/shop/
+└── inventory/
+ ├── main/ # public entry points and orchestration
+ │ └── reserve.py
+ ├── _helpers/ # private implementation phases
+ ├── classes/ # one class per module
+ ├── models.py # data models
+ ├── types.py # type declarations
+ ├── constants.py
+ └── exceptions.py
+```
+
+A leaf needs meaningful `main/` behavior, not an empty placeholder. Domains can
+split into named subdomains; tests mirror the code they cover. Tooling has its own
+scope. See the [architecture model](https://fensu.io/docs/concepts/architecture-model/)
+for complete role contracts, layouts, and defaults.
+
+## Explore the repository
+
+| Command | Purpose |
+| --- | --- |
+| `fensu rule FFL102` | Explain a rule and its effective settings. |
+| `fensu map submit --root src --depth 2` | Show proven static Python calls, without running the program. |
+| `fensu dupes --since origin/main --diff` | Review changed duplicated-code clusters; advisory, not a blocking check. |
+| `fensu skills --check` | Verify installed guidance matches the current policy. |
+
+Call mapping needs neither Fensu configuration nor rule adoption. It marks
+unresolved calls, cycles, and depth limits instead of guessing dynamic targets.
+See the [map reference](https://fensu.io/docs/cli/map/) and
+[duplicated-code guide](https://fensu.io/docs/concepts/duplicated-code/).
## Documentation
-The quickstart, architecture model, configuration reference, adoption guide, and
-CLI reference live at [docs.fensu.dev](https://docs.fensu.dev).
+[fensu.io/docs](https://fensu.io/docs/) is the full manual; the README is the starting point.
+
+| Start here | Reference |
+| --- | --- |
+| [Quickstart](https://fensu.io/docs/quickstart/) | Installation, initialization, and reading diagnostics. |
+| [Adoption](https://fensu.io/docs/adoption/) | Roll out enforcement safely on existing code. |
+| [Configuration](https://fensu.io/docs/concepts/configuration/) | Targets, ownership roots, selection, thresholds, exceptions, and ignores. |
+| [Architecture](https://fensu.io/docs/concepts/architecture-model/) | Roles, domain boundaries, tooling, and test layout. |
+| [Rust](https://fensu.io/docs/concepts/analyzers/rust/) · [Web](https://fensu.io/docs/concepts/analyzers/typescript-sveltekit/) | Analyzer-specific setup and rule packs. |
+| [CLI](https://fensu.io/docs/cli/) · [Agent guidance](https://fensu.io/docs/cli/skills/) | Commands, execution, and skill update safety. |
+| [Caching](https://fensu.io/docs/concepts/caching/) | Cache identities, controls, and safe cleanup. |
+| [Custom rules](https://fensu.io/docs/concepts/custom-rules/) · [RuleContext API](https://fensu.io/docs/reference/rule-context/) | Author, configure, and test project-specific policies. |
+
+[Python dead-code enforcement](docs/dead-code.md) has a separate repository guide
+covering reachability, explicit dynamic roots, and adoption caveats.
## Part of SQLStack
diff --git a/website/src/content/docs/docs/cli/index.mdx b/website/src/content/docs/docs/cli/index.mdx
index 0429c29d..abfbc52c 100644
--- a/website/src/content/docs/docs/cli/index.mdx
+++ b/website/src/content/docs/docs/cli/index.mdx
@@ -38,6 +38,13 @@ Commands:
Run `fensu --help` for command-specific options.
+## Execution model
+
+Core-only `check`, `dupes`, `init`, `rule`, `map`, `skills`, and `--version`
+execution is native. Configured Python custom rules launch one compatible Python
+host only for the policy metadata or callbacks they require. The native executable
+remains the command owner; Python hosting is not a second CLI implementation.
+
## Version
Both help forms exit `0`:
diff --git a/website/src/content/docs/docs/concepts/analyzers/rust.mdx b/website/src/content/docs/docs/concepts/analyzers/rust.mdx
index 6950b1d9..622a5c58 100644
--- a/website/src/content/docs/docs/concepts/analyzers/rust.mdx
+++ b/website/src/content/docs/docs/concepts/analyzers/rust.mdx
@@ -46,7 +46,7 @@ domains begin below additional structural grouping directories.
## What it checks
-The `rust` pack exposes all 117 implemented rules under `FPRS`. The rules cover:
+The `rust` pack exposes all implemented rules under `FPRS`. The rules cover:
- Cargo workspace and dependency policy;
- module ownership, visibility, layout, and import boundaries;
@@ -62,9 +62,20 @@ warn = []
ignore = ["FPRSH001"]
```
-Exact file exceptions and path-scoped ignores work as they do for other analyzers.
-Rust exceptions name a Rust source file or `Cargo.toml`; they do not use Python
-definition selectors. Inspect any rule and its effective settings with:
+Exact file exceptions and path-scoped ignores use the normal configuration keys.
+Rust exceptions name an exact `.rs` file or `Cargo.toml`. An exception without
+`symbols` covers the file, including findings owned by items; `Cargo.toml`
+exceptions must always be file-level.
+
+To narrow a Rust exception, use syntactic item paths within the source file:
+`parse`, `Record`, `Record::load`, or `inner::parse`, not Python-style dotted
+definition selectors. Modules and macro-generated items are not addressable;
+missing or ambiguous names are configuration errors. Each listed symbol must
+suppress a fault or the exception is stale. The
+[repository guide](https://github.com/sqlstack-io/fensu/blob/main/docs/rust.md#symbol-scoped-exceptions)
+details item spans, trait and implementation paths, and ambiguity restrictions.
+
+Inspect any rule and its effective settings with:
```bash
fensu rule FPRSS010 --target rust
diff --git a/website/src/content/docs/docs/concepts/architecture-model.mdx b/website/src/content/docs/docs/concepts/architecture-model.mdx
index ceba160a..b2cba0fb 100644
--- a/website/src/content/docs/docs/concepts/architecture-model.mdx
+++ b/website/src/content/docs/docs/concepts/architecture-model.mdx
@@ -121,7 +121,7 @@ accidental public surfaces.
## Domains: leaf or branch
Fensu's default layout for product code is **domains built from roles**, not a
-flat top level.
+flat top level. The default architecture follows SQLBuild Compiler Rules v0.101.1.
- An ownership root (by default the package root, for example
`src/my_package/`) holds only its package protocol modules, deliberate public
@@ -140,6 +140,14 @@ parts. There is no mandatory subdomain level and no conventional `core/`
ceremony. Loose non-role modules directly at the domain level fault too
(`FFR307`).
+Every leaf domain or subdomain requires a direct `main/` boundary containing at
+least one meaningful entry module. Branch-domain parents do not need their own
+`main/`; their leaf subdomains do. An empty or initializer-only `main/` is not a
+substitute for behavior. Move passive-only models, types, constants, exceptions,
+or classes into the closest domain whose `main/` behavior owns and uses them.
+Fixed role files are siblings of `_helpers/`, not descendants such as
+`_helpers/entry/models.py`.
+
```text
src/my_package/
├── __init__.py # public re-export surface only
diff --git a/website/src/content/docs/docs/concepts/configuration.mdx b/website/src/content/docs/docs/concepts/configuration.mdx
index 0a1c5e86..df4ee4d4 100644
--- a/website/src/content/docs/docs/concepts/configuration.mdx
+++ b/website/src/content/docs/docs/concepts/configuration.mdx
@@ -339,7 +339,7 @@ symbols = ["ProgressCollector.update"]
reason = "The external API invokes this callback positionally."
```
-Omit `symbols` only for an ownerless file-level finding:
+Omit `symbols` to accept matching-rule findings throughout the exact file:
```toml
[[rule_exceptions]]
@@ -348,14 +348,18 @@ path = "src/my_package/integrations/compatibility.py"
reason = "This file remains a direct module while the external integration is supported."
```
-Omitting `symbols` does not suppress findings owned by functions in that file. If
-`symbols` is present, it must be non-empty; `symbols = []` is rejected rather than
-silently broadening the exception to file scope.
+This file-level form also suppresses matching findings owned by functions or
+items in that file, for every analyzer. Include `symbols` when only particular
+owners should be exempt. If present, it must be non-empty; `symbols = []` is
+rejected rather than silently broadening the exception to file scope.
The rule, repository-relative analyzer source file, and any qualified symbols are exact:
globs, directories, line numbers, and rule prefixes are not accepted. The path and
symbols must exist, and `fensu check` fails if either form becomes stale and
-suppresses no fault.
+suppresses no fault. Each listed symbol must suppress a fault; missing or ambiguous
+symbols are configuration errors. Rust uses item paths such as `Record::load`;
+`Cargo.toml` exceptions cannot name symbols. See
+[Rust exception selectors](/concepts/analyzers/rust#what-it-checks).
## Path-scoped rule ignores
diff --git a/website/src/content/docs/docs/quickstart.mdx b/website/src/content/docs/docs/quickstart.mdx
index 069a646d..5c5349f0 100644
--- a/website/src/content/docs/docs/quickstart.mdx
+++ b/website/src/content/docs/docs/quickstart.mdx
@@ -24,6 +24,16 @@ fensu --version
Fensu needs Python 3.12 or newer.
+The `fensu` distribution provides the Python authoring/API surface and installs the
+lockstep `fensu-cli` binary distribution, which owns the `fensu` command. Use that
+executable for built-in commands; `python -m fensu` is retired. See the
+[CLI execution model](/cli#execution-model) for native commands and custom-rule hosting.
+
+Fensu includes a compiled analysis core. Prebuilt wheels cover Linux (x86_64 and
+aarch64), macOS (Intel and Apple silicon), and Windows (x86_64). Where no compatible
+wheel is available, `pip` builds from source; this requires Rust 1.95 or newer,
+including when installing `fensu-cli` from its source distribution.
+
## 2. Initialize
[`fensu init`](/cli/init) is the fastest way to start. It detects your layout,
diff --git a/website/src/content/docs/docs/reference/rule-context.mdx b/website/src/content/docs/docs/reference/rule-context.mdx
index bbd3e142..6fb0c4e6 100644
--- a/website/src/content/docs/docs/reference/rule-context.mdx
+++ b/website/src/content/docs/docs/reference/rule-context.mdx
@@ -24,6 +24,11 @@ and configuration. Legacy Python callbacks may ignore the context and walk their
Backend-neutral semantic facts for the current file, computed once and shared by all
rules through a single traversal.
+The semantic fact contracts and author-facing models are public Python APIs;
+production fact extraction is owned by the native Rust implementation. Raw Python
+AST, syntax, and relation artifacts remain lazy CPython capabilities, materialized
+only when a custom rule needs those surfaces.
+
| Call | Returns | Purpose |
| --- | --- | --- |
| `annotations()` | `AnnotationFacts` | Missing parameter, return, local, and variable annotations. |
From 424d8563ec42c5cd80483b7533ce256bfede8e03 Mon Sep 17 00:00:00 2001
From: Kevin Longe <273747162+kvlonge@users.noreply.github.com>
Date: Sun, 1 Nov 2026 14:17:08 +0000
Subject: [PATCH 3/3] docs(readme): simplify onboarding copy
Amp-Thread-ID: https://ampcode.com/threads/T-01a1970c-7c44-7042-b987-dc3926e29427
---
README.md | 26 +++++---------------
website/src/content/docs/docs/quickstart.mdx | 7 ++++++
2 files changed, 13 insertions(+), 20 deletions(-)
diff --git a/README.md b/README.md
index 628c9f87..5f743dd5 100644
--- a/README.md
+++ b/README.md
@@ -13,9 +13,6 @@ shape** for Python, Rust, TypeScript, JavaScript, and Svelte.
- **Roles:** keep entry points, helpers, models, and types in their owning modules.
- **Function shape:** keep orchestrators small, dataflow explicit, and signatures clear.
-Fensu is pre-release and self-hosting. It ships an opinionated default architecture,
-not a blank rule framework; tune or replace policies deliberately.
-
## Get started
Requires **Python 3.12+**. Install in your project’s Python environment:
@@ -28,28 +25,17 @@ From an existing Python repository’s `pyproject.toml` directory:
```bash
fensu init --yes
-fensu skills --check
fensu check
```
-`init` detects the layout, writes `fensu.toml`, measures current drift, and installs
-repository-local agent guidance. It detects complete SvelteKit projects too; see
-[web targets](https://fensu.io/docs/concepts/analyzers/typescript-sveltekit/).
-For an empty repository, use `fensu init --yes --name my_package` instead.
-
-Already configured? `init` leaves existing configuration unchanged. Run
-`fensu skills` to install or refresh guidance, then verify it with `--check`.
-Unmanaged skill files are preserved unless you explicitly pass `--force`.
-Use `init --no-skills` only for deliberate configuration-only automation.
+`fensu init --yes` detects your project, creates `fensu.toml`, runs an initial check,
+and installs agent guidance. Existing configuration is preserved.
-`check` exits **0** with no blocking faults, **1** when it finds faults, and **2**
-for setup/configuration errors. Put `fensu check` in CI to enforce the policy.
+Run `fensu check` locally and in CI to enforce your policy. For established
+repositories, [adopt rules incrementally using explicit boundaries and exceptions](https://fensu.io/docs/adoption/).
-New and small repositories are the easiest starting point. On established codebases,
-expect drift: use [adoption boundaries and explicit exceptions](https://fensu.io/docs/adoption/)
-rather than making unsafe structural changes just to reach zero.
-Rust projects use [Cargo-aware target configuration](https://fensu.io/docs/concepts/analyzers/rust/).
-See [installation details](https://fensu.io/docs/quickstart/#1-install) for wheels and source builds.
+See the [quickstart](https://fensu.io/docs/quickstart/) for empty repositories,
+existing configuration, and language-specific setup.
## A finding and its fix
diff --git a/website/src/content/docs/docs/quickstart.mdx b/website/src/content/docs/docs/quickstart.mdx
index 5c5349f0..06b7042b 100644
--- a/website/src/content/docs/docs/quickstart.mdx
+++ b/website/src/content/docs/docs/quickstart.mdx
@@ -49,6 +49,13 @@ run `fensu init --yes --name my_package`; init scaffolds a `src/` package and
`tests/` directory. Pass `--no-skills` only when automation explicitly needs
configuration without repository-local agent guidance.
+Existing configuration is preserved: `init` changes nothing when `fensu.toml`
+already exists. Use [`fensu skills`](/cli/skills) to install or refresh guidance
+for a configured project. See [`fensu init`](/cli/init) for detection and setup
+options, or the [Rust](/concepts/analyzers/rust) and
+[TypeScript/SvelteKit](/concepts/analyzers/typescript-sveltekit) guides for
+language-specific configuration.
+
Verify that every generated local skill is present and current before calling
onboarding complete: