sensez 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +163 -181
  2. package/package.json +5 -5
package/README.md CHANGED
@@ -1,219 +1,181 @@
1
- ### Why can't coding agents detect code smells? Because they don't have a `noze`.
1
+ # Sensez
2
2
 
3
- Coding agents are very good at producing code. They are also very good at
4
- producing the same helper three times, gently ignoring your architecture notes,
5
- and using `dict[str, Any]` when you ask for type safety. You ask it to complete
6
- a task like "a staff software engineer", you ask it to follow SOLID principles
7
- and use strong type safety. It happily agrees, and starts working on the task.
8
- The vibes are immaculate. You come back a few minutes later to a slopocalypse
9
- that looks nothing like what your AGENTS.md says and you spend hours trying to
10
- understand where to start.
3
+ [![PyPI](https://img.shields.io/pypi/v/sensez?logo=pypi&logoColor=white)](https://pypi.org/project/sensez/) [![npm](https://img.shields.io/npm/v/sensez?logo=npm&logoColor=white)](https://www.npmjs.com/package/sensez) [![CI](https://github.com/popov95s/sensez/actions/workflows/ci.yml/badge.svg)](https://github.com/popov95s/sensez/actions/workflows/ci.yml) [![Website](https://img.shields.io/badge/website-sensez.dev-222222?logo=googlechrome&logoColor=white)](https://sensez.dev) [![Documentation](https://img.shields.io/badge/docs-latest-222222?logo=readthedocs&logoColor=white)](https://popov95s.github.io/sensez/latest/) [![License: MIT](https://img.shields.io/badge/license-MIT-2ea44f)](https://github.com/popov95s/sensez/blob/main/LICENSE.MD)
11
4
 
12
- Sensez is a suite of Rust CLIs with an MCP server for maintenance before tech debt
13
- accumulates. It runs beside your linter and type-checker and looks for cross-file
14
- problems they usually do not own: duplication, dead code, import cycles, boundary
15
- violations, and design smells. It is designed to give your coding agent the
16
- `noze` to detect code smells, the `bonez` to respect architectural boundaries,
17
- and the `spine` to do it fast.
5
+ **Structural maintainability checks for coding agents and teams.**
18
6
 
19
- Supported language profiles currently include Python, JavaScript, TypeScript, and Rust (for dogfooding primarily).
7
+ Sensez is a suite of Rust CLIs and an MCP server that runs alongside your linter
8
+ and type-checker. It finds cross-file problems that those tools do not usually
9
+ own: duplication, dead code, import cycles, architecture-boundary violations,
10
+ and design smells.
20
11
 
21
- Docs: https://popov95s.github.io/sensez/latest/
12
+ It gives coding agents the `noze` to detect code smells, the `bonez` to respect
13
+ architectural boundaries, and the `spine` to do it fast. Python, JavaScript,
14
+ TypeScript/TSX, and Rust profiles are supported (Rust primarily for dogfooding).
22
15
 
23
- ## Quick Start
24
- ### Python
25
- ```Bash
26
- # Add as a project dev dependency; run it with `uv run sensez ...`
27
- uv add --dev sensez
28
- uv run sensez init
29
-
30
- # Install as a global CLI so `sensez ...` works directly
31
- uv tool install sensez
32
- sensez init
33
-
34
- # or run a one-off scan with uv
35
- uvx sensez noze .
36
- ```
37
-
38
- ### JS/TS
39
- ```Bash
40
- # Add as a dev dependency
41
- npm install --save-dev sensez
42
- # Generate a sensez.toml starter config
43
- npx sensez init .
16
+ **[Website](https://sensez.dev)** ·
17
+ **[Documentation](https://popov95s.github.io/sensez/latest/)** ·
18
+ **[MCP and agent guide](https://popov95s.github.io/sensez/latest/usage/mcp-and-agents/)** ·
19
+ **[Configuration reference](https://popov95s.github.io/sensez/latest/reference/configuration/)** ·
20
+ **[Report a security issue](https://github.com/popov95s/sensez/blob/main/SECURITY.md)**
44
21
 
45
- # Run a one-off scan with npx
46
- npx sensez noze .
47
- ```
48
-
49
- `sensez .` and `sensez noze .` both run the default scan. The verbose form is
50
- still available as `sensez noze sniff .`.
22
+ ## Why Sensez?
51
23
 
52
- ## Performance Snapshot
24
+ Coding agents are excellent at producing code—and, occasionally, at producing
25
+ the same helper three times, gently ignoring architecture notes, and replacing
26
+ type-safe models with `dict[str, Any]`. The vibes are immaculate; the result
27
+ can still be a slopocalypse that takes hours to untangle.
53
28
 
54
- ```mermaid
55
- xychart-beta
56
- title "pylint benchmark seconds"
57
- x-axis ["sensez", "vulture", "repowise", "symilar"]
58
- y-axis "seconds" 0 --> 20
59
- bar [0.27, 1.29, 17.26, 20]
60
- ```
29
+ Sensez closes that feedback loop while an edit is still fresh. It gives agents
30
+ short, structured feedback on the repository's shape, so problems can be fixed
31
+ before they become load-bearing.
61
32
 
62
- `sensez` scans all structural pillars in one pass (`0.27s`). `vulture` checks
63
- Python dead code (`1.29s`). `repowise` uses a custom ranking mechanism, including dead code (`17.26s`).
64
- `symilar` checks line-based duplication (`234.12s`; chart capped at `20s`).
33
+ The gap is especially visible in agent-driven work:
65
34
 
66
- ### JS/TS
35
+ - **Context rots.** Architecture guidance fades across long, summarized turns.
36
+ - **CI is too late.** Small, non-blocking structural warnings are easy to defer.
37
+ - **Slow checks do not fit the turn.** If a check takes minutes, it cannot run
38
+ in every feedback loop—and debt has time to accumulate.
67
39
 
68
- ```mermaid
69
- xychart-beta
70
- title "zod benchmark seconds"
71
- x-axis ["sensez", "fallow", "repowise"]
72
- y-axis "seconds" 0 --> 6
73
- bar [0.16, 0.48, 5.75]
40
+ ```text
41
+ [Agent proposes turn finish] ──> [Sensez MCP sniff] ──> [Finds cycle / clone / smell]
42
+ │
43
+ └──> Immediate, actionable feedback
74
44
  ```
75
45
 
76
- `sensez` scans all structural pillars in one pass (`0.16s`). `fallow` checks
77
- JS/TS structural dead-code and dependency findings (`0.48s`). `repowise` checks
78
- repo intelligence signals, including dead code (`5.75s`).
79
-
80
- `sensez` tries to lower dead code noise and allows for configuration of what gets reported. It also includes a few more Python and TS/JS opinionated smells, apart from overall structural consistency metrics.
46
+ Sensez complements—not replaces—Ruff, ty, mypy, ESLint, TypeScript, `rustc`,
47
+ and Clippy. Use those tools for local correctness; use Sensez for the structural
48
+ relationships across the codebase.
81
49
 
82
- ## Agent Impact
83
-
84
- We gave the same coding agent 70 real-world Python tasks from SWE-PolyBench and
85
- SWE-bench Verified, plus 21 synthetic tasks designed to trigger specific
86
- maintainability traps. Both variants received SOLID/DRY principles. The Sensez
87
- variant additionally used the `noze_sniff` MCP tool in a mandatory feedback loop
88
- before declaring each task complete.
89
-
90
- | | New quality issues | Clone tokens | New clones | Lines written | Tokens used |
91
- |---|---|---|---|---|---|
92
- | Without Sensez | 14 | 1,251 | 129 | 2,080 | 1.23M |
93
- | With Sensez | 2 | 126 | 0 | 682 | 1.34M |
94
- | **Reduction** | **86%** | **90%** | **100%** | **67%** | **+8.7% overhead** |
50
+ ## Quick start
95
51
 
96
- Sensez agents produced structurally cleaner code with 67% fewer lines.
52
+ ### Python
97
53
 
98
- Benchmarks used: SWE-PolyBench_500, SWE-bench Verified, and synthetic pillar tests.
99
- Full methodology and per-benchmark results in [`evals/`](evals/).
54
+ ```bash
55
+ # Add to a project; run it with `uv run sensez ...`
56
+ uv add --dev sensez
57
+ uv run sensez init
100
58
 
101
- ## The Problem
59
+ # Or install a global CLI
60
+ uv tool install sensez
61
+ sensez init
102
62
 
103
- Coding agents drift. Not due to bad intentions, but because their loop is leaky.
63
+ # Or run a one-off scan
64
+ uvx sensez noze .
65
+ ```
104
66
 
105
- 1. Context rots.
106
- You told the agent to respect boundaries, follow SOLID, and think like a
107
- staff engineer. Six turns later, the context has been summarized twice and
108
- the agent is confidently rewriting the same csv file parser your colleague
109
- wrote two weeks ago.
67
+ ### JavaScript and TypeScript
110
68
 
111
- 2. CI is too late.
112
- CI is great at saying "absolutely not." It is much worse at saying "hm, this
113
- duplication is small but suspicious." Non-blocking warnings have a natural
114
- habitat: ignored forever.
69
+ ```bash
70
+ # Add as a development dependency
71
+ npm install --save-dev sensez
115
72
 
116
- 3. Slow checks do not fit the turn.
117
- If a check takes minutes, it should not run every agent turn. If it does not
118
- run every turn, the slop has time to ferment.
119
- ```text
120
- [Agent Proposes Turn Finish] ──> [ 👃 Sensez MCP Sniff ] ──> [ Catches Import Cycle / Duplication ]
121
- │
122
- └──> (Immediate Agent Feedback: "Loose typing violation on line 40 of code.py. Replace loose collections with dataclass/model.")
73
+ # Generate a starter config and scan
74
+ npx sensez init .
75
+ npx sensez noze .
123
76
  ```
124
77
 
125
- Sensez provides short, structured feedback directly to the agent while the edit is still fresh. Less archaeology, more "fix it before it becomes load-bearing."
78
+ `sensez .` and `sensez noze .` both run the default scan. The explicit form
79
+ `sensez noze sniff .` remains available for agent-oriented workflows.
126
80
 
127
- ## noze
128
-
129
- `noze` takes care of the gorgonzola coding agents love so much:
81
+ ## What it finds
130
82
 
131
83
  | Area | Output key | What it catches |
132
- |---|---|---|
133
- | Duplication | `duplication` | Structural clones, including local rename copies. |
84
+ | --- | --- | --- |
85
+ | Duplication | `duplication` | Structural clones, including local-rename copies. |
134
86
  | Dead code | `dead_code` | Unreferenced symbols with confidence tiers. |
135
87
  | Cycles | `cycles` | Import loops and load-order tangles. |
136
- | Boundaries | `boundaries` | Imports crossing configured architecture rules. |
88
+ | Boundaries | `boundaries` | Imports that cross configured architecture rules. |
137
89
  | Smells | `smells` | Design pressure inside functions, classes, modules, and the graph. |
138
90
 
139
- Some smell examples:
91
+ Some examples of the included smells:
140
92
 
141
- | Smell | Why noze flags it |
142
- |---|---|
143
- | `tuple_packing` | Positional tuples hide meaning. `tuple[int, str, int]` is not a data model. |
144
- | `loose_typing` | `Any` and vague containers erase the contract callers need. |
145
- | `boolean_blindness` | `do_thing(True, False)` is a guessing game with arguments. |
146
- | `implicit_schema` | Repeated string-key access usually means a real shape is hiding in a dict. |
147
- | `mutated_parameter` | You pass a parameter and the function you sent it to returns it all chewed up. Disgusting. |
148
- | `feature_envy` | A method that mostly uses another object's data may belong somewhere else. |
93
+ | Smell | Why Sensez flags it |
94
+ | --- | --- |
95
+ | `tuple_packing` | Positional tuples hide meaning; `tuple[int, str, int]` is not a data model. |
96
+ | `loose_typing` | `Any`, schema-erasing maps, and primitive containers erase caller contracts. |
97
+ | `boolean_blindness` | `do_thing(True, False)` makes argument meaning a guessing game. |
98
+ | `implicit_schema` | Repeated string-key access often means a real shape is hiding in a dict. |
99
+ | `mutated_parameter` | A function returns a parameter after chewing it up. |
100
+ | `feature_envy` | A method that mostly uses another object's data may belong elsewhere. |
149
101
  | `message_chain` | Long `a.b.c.d` chains couple callers to deep object plumbing. |
150
102
  | `god_module` | One module has become the place everything depends on. |
151
- | `magic_string_default` | Trying to lie to the type checker by adding an `\|\| ""` or `or ""` to hide a string that should be required. |
152
- | `split_variable` | Multiple reassignments of the same variable within the same scope. Set to 1 to keep them constant within the scope and enforce helper functions for complex assignment logic. |
153
- | `nested_loops` | [BETA, can be noisy] Nested iterations may blow up exponentially if not handled properly |
154
- | `n_plus_one_call` | [BETA, can be noisy] Making external calls 1 by 1 (e.g. to a database) instead of using a batched approach. |
155
-
156
-
157
- `noze` is not a formatter, linter, or type-checker. Keep using Ruff, ty, mypy,
158
- ESLint, TypeScript, rustc, and Clippy. `noze` sits next to them and watches the
159
- repo-level shape.
103
+ | `magic_string_default` | <code>&#124;&#124; ""</code> or <code>or ""</code> hides a string that should be required. |
104
+ | `split_variable` | Multiple reassignments of a variable in one scope add hidden state. |
105
+ | `nested_loop` | **Beta, opt-in:** nested iteration may have unintended complexity. |
106
+ | `n_plus_one_call` | **Beta, opt-in:** one-by-one external calls may need batching. |
160
107
 
161
- The default report is intentionally fixable in one screen: each pillar shows
162
- only its top 5 offenders, each smell kind shows its own total plus top 3
163
- examples, and dead-code output includes high-confidence findings only. Use
164
- `--all` to print every finding, or `--max N` to choose a different cap.
165
-
166
- For CI, filter to the pillars you care about:
108
+ The default report is intentionally fixable in one screen: each pillar shows its
109
+ top five offenders, each smell kind shows its total plus its top three examples,
110
+ and dead-code output includes high-confidence findings only. Use `--all` for
111
+ every finding, or `--max N` to set another cap.
167
112
 
168
113
  ```bash
114
+ # Focus a CI check on the pillars you care about
169
115
  sensez noze . --duplicates
170
116
  sensez noze . --duplicates --dead-code --json
171
117
  ```
172
118
 
173
- ## MCP
119
+ ## Performance
174
120
 
175
- MCP is the default integration path for agents. Use it when Sensez should run
176
- repeatedly during a coding session instead of shelling out for one-off scans.
121
+ Sensez evaluates all structural pillars in one pass.
177
122
 
178
- ```bash
179
- sensez mcp serve
180
- ```
123
+ ### Python: pylint benchmark
181
124
 
182
- The MCP tools are themed but explicit:
125
+ ![Python benchmark: Sensez 0.27 s, Vulture 1.29 s, Repowise 17.26 s, Symilar 234.12 s](https://raw.githubusercontent.com/popov95s/sensez/main/docs/assets/benchmark-python.svg)
183
126
 
184
- | Tool | Use |
185
- |---|---|
186
- | `noze_sniff` | Scan the repo for smells and structure issues. |
187
- | `noze_gate` | End-of-turn diff gate for agent hooks; experimental and can be noisy on short/Q&A turns. |
188
- | `noze_explain` | Explain a finding category. |
189
- | `brainz_report` | Summarize local usage and resolution metrics. |
190
- | `brainz_triage` | Record user-approved debt or false-positive verdicts. |
191
- | `eyez_search_docs` | [disabled] Search docstrings/comments when `eyez` is enabled. |
127
+ | Tool | Time | Scope |
128
+ | --- | ---: | --- |
129
+ | **sensez** | **0.27 s** | All structural pillars in one pass |
130
+ | vulture | 1.29 s | Python dead code |
131
+ | repowise | 17.26 s | Repository intelligence, including dead code |
132
+ | symilar | 234.12 s | Line-based duplication |
192
133
 
193
- You can also use the `sensez noze` CLI standalone in GitHub Actions.
134
+ ### JavaScript / TypeScript: zod benchmark
194
135
 
195
- ## brainz
136
+ ![JavaScript and TypeScript benchmark: Sensez 0.16 s, Fallow 0.48 s, Repowise 5.75 s](https://raw.githubusercontent.com/popov95s/sensez/main/docs/assets/benchmark-javascript.svg)
196
137
 
197
- `brainz` is local-only memory. It records scans, gate blocks, triage decisions,
198
- resolved findings, regressions, detector precision, and usage reports.
138
+ | Tool | Time | Scope |
139
+ | --- | ---: | --- |
140
+ | **sensez** | **0.16 s** | All structural pillars in one pass |
141
+ | fallow | 0.48 s | JS/TS structural dead-code and dependency findings |
142
+ | repowise | 5.75 s | Repository intelligence, including dead code |
199
143
 
200
- ```bash
201
- sensez brainz report .
202
- sensez brainz report . --json
203
- ```
144
+ ## Agent impact
204
145
 
205
- Everything stays under:
146
+ The same coding agent completed 70 real-world Python tasks from SWE-PolyBench
147
+ and SWE-bench Verified, plus 21 synthetic tasks designed to trigger specific
148
+ maintainability traps. Both variants received SOLID/DRY principles. The Sensez
149
+ variant additionally had to call `noze_sniff` in a feedback loop before it could
150
+ declare a task complete.
206
151
 
207
- ```text
208
- .sensez/local-metrics/
209
- ```
152
+ | | New quality issues | Clone tokens | New clones | Lines written | Tokens used |
153
+ | --- | ---: | ---: | ---: | ---: | ---: |
154
+ | Without Sensez | 14 | 1,251 | 129 | 2,080 | 1.23M |
155
+ | With Sensez | 2 | 126 | 0 | 682 | 1.34M |
156
+ | **Reduction** | **86%** | **90%** | **100%** | **67%** | **+8.7% overhead** |
210
157
 
211
- No telemetry. No source upload. Disable it per repo:
158
+ Sensez agents produced structurally cleaner code with 67% fewer lines.
159
+ Benchmarks used SWE-PolyBench_500, SWE-bench Verified, and synthetic pillar
160
+ tests. See [the evaluation suite](https://github.com/popov95s/sensez/tree/main/evals)
161
+ for the methodology and per-benchmark results.
212
162
 
213
- ```toml
214
- [self_improvement]
215
- enabled = false
216
- ```
163
+ ## MCP for agents
164
+
165
+ MCP is the recommended integration when Sensez should run repeatedly during a
166
+ coding session rather than as a one-off shell command. The `init` command would set this up automatically on agent start.
167
+
168
+ | Tool | Use |
169
+ | --- | --- |
170
+ | `noze_sniff` | Scan the repository for smells and structural issues. |
171
+ | `noze_gate` | Experimental end-of-turn diff gate; may be noisy for short or Q&A turns. |
172
+ | `noze_explain` | Explain a finding category. |
173
+ | `brainz_report` | Summarize local usage and resolution metrics. |
174
+ | `brainz_triage` | Record user-approved debt or false-positive verdicts. |
175
+ | `eyez_search_docs` | Disabled unless `eyez` is enabled; searches docstrings and comments. |
176
+
177
+ Sensez can also run standalone in GitHub Actions. See the
178
+ [GitHub Action guide](https://popov95s.github.io/sensez/latest/usage/github-action/).
217
179
 
218
180
  ## Configuration
219
181
 
@@ -221,21 +183,19 @@ Sensez reads `sensez.toml` from the project root, or `[tool.sensez]` from
221
183
  `pyproject.toml` when `sensez.toml` is absent.
222
184
 
223
185
  ```bash
224
- sensez init . --yes
186
+ sensez init
225
187
  ```
226
188
 
227
- Main knobs:
189
+ The main configuration areas are:
228
190
 
229
191
  - `[duplication]` for clone thresholds
230
- - `[dead_code]` for dynamic entrypoints
192
+ - `[dead_code]` for dynamic entry points
231
193
  - `[smells]` for smell toggles and thresholds
232
194
  - `[[boundaries.forbidden]]` for architecture contracts
233
- - `[action]` for how strongly agents/gates treat each pillar
195
+ - `[action]` for how strongly agents and gates treat each pillar
234
196
  - `[accept]` for shared accepted findings
235
197
  - `[self_improvement]` for local metrics
236
198
 
237
- Small example:
238
-
239
199
  ```toml
240
200
  [duplication]
241
201
  threshold = 50
@@ -246,25 +206,47 @@ entrypoint_names = ["register", "main", "setup"]
246
206
  [smells.rules.long_function]
247
207
  max_lines = 80
248
208
  action = "warning"
209
+
210
+ # The beta performance heuristics are disabled by default.
211
+ [smells.rules.nested_loop]
212
+ enabled = true
213
+
214
+ [smells.rules.n_plus_one_call]
215
+ enabled = true
249
216
  ```
250
217
 
251
- ## Project Anatomy
218
+ ## Local-only metrics and privacy
219
+
220
+ `brainz` records scans, gate blocks, triage decisions, resolved findings,
221
+ regressions, detector precision, and usage reports locally.
222
+
223
+ ```bash
224
+ sensez brainz report .
225
+ sensez brainz report . --json
226
+ ```
227
+
228
+ Everything remains under `.sensez/local-metrics/`. Sensez sends no telemetry
229
+ and uploads no source code. Disable local metrics for a repository with:
230
+
231
+ ```toml
232
+ [self_improvement]
233
+ enabled = false
234
+ ```
235
+
236
+ ## Project anatomy
252
237
 
253
238
  - `spine`: file discovery, parsing, shared IR, and dependency graph.
254
239
  - `profiles`: language adapters for Python, JS/TS, TSX, and Rust.
255
240
  - `noze`: duplication, dead code, cycles, and design smells.
256
- - `bonez`: architecture boundary auditing. Not yet enabled.
241
+ - `bonez`: architecture-boundary auditing; not yet enabled.
257
242
  - `brainz`: local-only metrics and feedback memory.
258
- - `eyez`: optional doc/comment search. Not yet enabled.
243
+ - `eyez`: optional doc/comment search; not yet enabled.
259
244
  - `mcp`: JSON-RPC/MCP surface for agent integration.
260
245
  - `reporter`: terminal and JSON output.
261
- - `setup`: `sensez init`, starter config, MCP registration, and hook setup.
262
-
263
- ## Privacy
264
-
265
- Sensez does not send telemetry or source code anywhere. Local metrics stay under
266
- `.sensez/local-metrics/`.
246
+ - `setup`: starter configuration, MCP registration, and hook setup.
267
247
 
268
- ---
248
+ ## Disclaimer
269
249
 
270
- Disclaimer: [DISCLAIMER.md](DISCLAIMER.md)
250
+ Please review
251
+ [DISCLAIMER.md](https://github.com/popov95s/sensez/blob/main/DISCLAIMER.md) for
252
+ the project disclaimer.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sensez",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Sensez CLI launcher for structural maintainability checks",
5
5
  "license": "MIT",
6
6
  "readme": "README.md",
@@ -18,10 +18,10 @@
18
18
  "README.md"
19
19
  ],
20
20
  "optionalDependencies": {
21
- "sensez-darwin-arm64": "0.2.0",
22
- "sensez-darwin-x64": "0.2.0",
23
- "sensez-linux-arm64-gnu": "0.2.0",
24
- "sensez-linux-x64-gnu": "0.2.0"
21
+ "sensez-darwin-arm64": "0.2.2",
22
+ "sensez-darwin-x64": "0.2.2",
23
+ "sensez-linux-arm64-gnu": "0.2.2",
24
+ "sensez-linux-x64-gnu": "0.2.2"
25
25
  },
26
26
  "publishConfig": {
27
27
  "provenance": true