@drkmttr/adhere 0.18.0 → 0.21.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drkmttr/adhere",
3
- "version": "0.18.0",
3
+ "version": "0.21.2",
4
4
  "private": false,
5
5
  "description": "Lints a repository against the rules in .adhere/, judged by Jev.",
6
6
  "license": "MIT",
@@ -38,32 +38,32 @@
38
38
  "prepare": "vp config"
39
39
  },
40
40
  "dependencies": {
41
- "effect": "4.0.0-rc.118"
41
+ "effect": "4.0.3"
42
42
  },
43
43
  "devDependencies": {
44
- "@effect/platform-bun": "4.0.0-rc.118",
44
+ "@effect/platform-bun": "4.0.3",
45
45
  "@types/bun": "^1.4.2",
46
- "@types/node": "^24.13.6",
46
+ "@types/node": "^26.0.0",
47
47
  "release-it": "^21.1.0",
48
- "typescript": "7.1.0-dev.20261009.1",
48
+ "typescript": "7.1.0-dev.20261012.1",
49
49
  "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
50
50
  "vite-plus": "1.1.0",
51
- "vitest": "5.0.3"
51
+ "vitest": "5.0.5"
52
52
  },
53
53
  "overrides": {
54
- "@effect/platform-node-shared": "4.0.0-rc.118",
54
+ "@effect/platform-node-shared": "4.0.3",
55
55
  "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
56
- "vitest": "5.0.3"
56
+ "vitest": "5.0.5"
57
57
  },
58
58
  "devEngines": {
59
59
  "packageManager": {
60
60
  "name": "bun",
61
- "version": "1.4.2",
61
+ "version": "1.4.3",
62
62
  "onFail": "download"
63
63
  },
64
64
  "runtime": {
65
65
  "name": "node",
66
- "version": "24.21.0",
66
+ "version": "26.11.1",
67
67
  "onFail": "download"
68
68
  }
69
69
  },
@@ -90,10 +90,10 @@
90
90
  "--force"
91
91
  ],
92
92
  "optionalDependencies": {
93
- "@drkmttr/adhere-darwin-arm64": "0.18.0",
94
- "@drkmttr/adhere-darwin-x64": "0.18.0",
95
- "@drkmttr/adhere-linux-arm64": "0.18.0",
96
- "@drkmttr/adhere-linux-x64": "0.18.0",
97
- "@drkmttr/adhere-win32-x64": "0.18.0"
93
+ "@drkmttr/adhere-darwin-arm64": "0.21.2",
94
+ "@drkmttr/adhere-darwin-x64": "0.21.2",
95
+ "@drkmttr/adhere-linux-arm64": "0.21.2",
96
+ "@drkmttr/adhere-linux-x64": "0.21.2",
97
+ "@drkmttr/adhere-win32-x64": "0.21.2"
98
98
  }
99
99
  }
@@ -0,0 +1,132 @@
1
+ # Presets
2
+
3
+ Every rule in adhere's built-in presets is listed below, with a one-line
4
+ summary. Each id links to the full rule, and is the id that reports,
5
+ `overrides`, and `adhere-ignore` comments use. [Presets](../README.md#presets)
6
+ says how to name a preset or one of its topics.
7
+
8
+ ## typescript
9
+
10
+ - **Source.** The TypeScript Handbook and the Google TypeScript Style Guide.
11
+ - **Checked by a linter instead.** The preset has no rules for these, since
12
+ typescript-eslint and ESLint check them exactly: unhandled promises
13
+ (`no-floating-promises`), throwing non-errors (`only-throw-error`), `any`
14
+ (`no-explicit-any`), exhaustive switches (`switch-exhaustiveness-check`), a
15
+ lost `cause` (`preserve-caught-error`), and empty catch blocks (`no-empty`).
16
+
17
+ - [`typescript/async/concurrent-independent-work`](./typescript/async/concurrent-independent-work/RULE.md): Independent awaited calls run concurrently, not one after another.
18
+ - [`typescript/async/network-calls-have-timeouts`](./typescript/async/network-calls-have-timeouts/RULE.md): HTTP requests carry a timeout or an abort signal.
19
+ - [`typescript/design/no-argument-mutation`](./typescript/design/no-argument-mutation/RULE.md): Functions return changed copies instead of mutating arguments.
20
+ - [`typescript/errors/no-swallowed-errors`](./typescript/errors/no-swallowed-errors/RULE.md): Caught errors are handled, rethrown, or returned as failures.
21
+ - [`typescript/errors/release-on-every-path`](./typescript/errors/release-on-every-path/RULE.md): Acquired resources are released on every path, including errors.
22
+ - [`typescript/testing/assert-outcomes`](./typescript/testing/assert-outcomes/RULE.md): Tests assert results and effects, not only that code ran.
23
+ - [`typescript/testing/independent-tests`](./typescript/testing/independent-tests/RULE.md): Each test sets up its own state and relies on no other test.
24
+ - [`typescript/types/assertions-only-when-proven`](./typescript/types/assertions-only-when-proven/RULE.md): Type assertions claim only what surrounding code has proven.
25
+ - [`typescript/types/derive-dont-restate`](./typescript/types/derive-dont-restate/RULE.md): Types are derived from their source instead of restated by hand.
26
+ - [`typescript/types/unrepresentable-invalid-states`](./typescript/types/unrepresentable-invalid-states/RULE.md): Types make invalid field combinations unrepresentable.
27
+ - [`typescript/types/validate-external-data`](./typescript/types/validate-external-data/RULE.md): Data from outside is checked at runtime before use.
28
+
29
+ ## react
30
+
31
+ - **Source.** react.dev, mostly
32
+ [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect)
33
+ and
34
+ [Choosing the State Structure](https://react.dev/learn/choosing-the-state-structure).
35
+ - **Checked by a linter instead.** The preset has no rules for these, since
36
+ the React Compiler's lint rules check them, in
37
+ [eslint-plugin-react-hooks](https://react.dev/reference/eslint-plugin-react-hooks)'s
38
+ recommended set and in Oxlint: pure render (`purity`), props and state
39
+ never mutated (`immutability`), refs not read during render (`refs`), no
40
+ `setState` in render or synchronously in an effect (`set-state-in-render`,
41
+ `set-state-in-effect`), which covers state derived in an effect, and no
42
+ component defined inside another (`static-components`).
43
+
44
+ - [`react/effects/clean-up-what-they-start`](./react/effects/clean-up-what-they-start/RULE.md): Effects return cleanup that undoes what they started.
45
+ - [`react/effects/event-logic-in-handlers`](./react/effects/event-logic-in-handlers/RULE.md): Code responding to a user action runs in its event handler.
46
+ - [`react/effects/external-stores-use-sync-external-store`](./react/effects/external-stores-use-sync-external-store/RULE.md): External stores are read with `useSyncExternalStore`.
47
+ - [`react/effects/fetches-ignore-stale-responses`](./react/effects/fetches-ignore-stale-responses/RULE.md): Effects that fetch ignore or abort stale responses.
48
+ - [`react/effects/notify-parents-in-handlers`](./react/effects/notify-parents-in-handlers/RULE.md): Parents are notified in the handler that makes the change.
49
+ - [`react/server/no-private-data-to-client`](./react/server/no-private-data-to-client/RULE.md): Client Components receive only the fields they show.
50
+ - [`react/server/server-functions-authorize-and-validate`](./react/server/server-functions-authorize-and-validate/RULE.md): Server Functions authorize callers and validate arguments.
51
+ - [`react/state/no-contradictory-state`](./react/state/no-contradictory-state/RULE.md): One status value replaces booleans that can contradict.
52
+ - [`react/state/no-props-copied-into-state`](./react/state/no-props-copied-into-state/RULE.md): Props are read during render, not copied into state.
53
+ - [`react/state/store-ids-not-copies`](./react/state/store-ids-not-copies/RULE.md): State holds a selected item's id, not a copy of the item.
54
+
55
+ ## security
56
+
57
+ - **Source.** OWASP's cheat sheets.
58
+
59
+ - [`security/constant-time-secret-compare`](./security/constant-time-secret-compare/RULE.md): Received secrets are compared in constant time.
60
+ - [`security/no-secrets-in-output`](./security/no-secrets-in-output/RULE.md): Secrets stay out of logs, errors, and HTTP responses.
61
+ - [`security/no-untrusted-input-in-commands-or-paths`](./security/no-untrusted-input-in-commands-or-paths/RULE.md): Untrusted input stays out of command strings and unchecked paths.
62
+ - [`security/parameterized-queries`](./security/parameterized-queries/RULE.md): SQL values from outside are passed as bound parameters.
63
+
64
+ ## effect
65
+
66
+ - **Source.** The
67
+ [effect-solutions](https://github.com/kitlangton/effect-solutions) docs and
68
+ the [effect/platform](https://effect.website/docs/platform/introduction/)
69
+ docs.
70
+
71
+ - [`effect/basics/gen-for-sequencing`](./effect/basics/gen-for-sequencing/RULE.md): Sequential effectful steps use `Effect.gen` and `yield*`.
72
+ - [`effect/basics/instrument-with-pipe`](./effect/basics/instrument-with-pipe/RULE.md): Timeouts, retries, logging, and spans attach with `.pipe`.
73
+ - [`effect/config/business-logic-depends-on-config-service`](./effect/config/business-logic-depends-on-config-service/RULE.md): Business logic depends on a config service, not Config reads.
74
+ - [`effect/config/secrets-are-redacted`](./effect/config/secrets-are-redacted/RULE.md): Tokens, passwords, and keys are read with `Config.Redacted`.
75
+ - [`effect/config/tests-provide-values-directly`](./effect/config/tests-provide-values-directly/RULE.md): Tests supply config with `Layer.succeed` on the config service.
76
+ - [`effect/config/validate-with-schema`](./effect/config/validate-with-schema/RULE.md): Constrained config values are validated as they are read.
77
+ - [`effect/data/brand-meaningful-primitives`](./effect/data/brand-meaningful-primitives/RULE.md): Meaningful primitives in domain types are branded schemas.
78
+ - [`effect/data/variants-are-tagged-unions`](./effect/data/variants-are-tagged-unions/RULE.md): Domain variants are tagged schemas in a union.
79
+ - [`effect/errors/catch-defects-at-boundaries-only`](./effect/errors/catch-defects-at-boundaries-only/RULE.md): Defects are caught only at system boundaries.
80
+ - [`effect/errors/defects-for-bugs`](./effect/errors/defects-for-bugs/RULE.md): Bugs and invariant violations are defects, not typed errors.
81
+ - [`effect/errors/wrap-external-errors`](./effect/errors/wrap-external-errors/RULE.md): External errors are wrapped in tagged errors.
82
+ - [`effect/services/dependencies-through-layers`](./effect/services/dependencies-through-layers/RULE.md): Service dependencies are yielded inside the service's Layer.
83
+ - [`effect/services/fresh-layer-per-test`](./effect/services/fresh-layer-per-test/RULE.md): Each `it.effect` test provides its own layer.
84
+ - [`effect/services/memoize-parameterized-layers`](./effect/services/memoize-parameterized-layers/RULE.md): Parameterized layers are built once and stored in a constant.
85
+ - [`effect/services/no-mutable-state`](./effect/services/no-mutable-state/RULE.md): Service interfaces expose only readonly members.
86
+ - [`effect/testing/test-clock-for-time`](./effect/testing/test-clock-for-time/RULE.md): Tests that depend on time use `TestClock`.
87
+
88
+ ## alchemy
89
+
90
+ - **Source.** alchemy's docs and blog.
91
+
92
+ - [`alchemy/apis/match-remote-errors-by-tag`](./alchemy/apis/match-remote-errors-by-tag/RULE.md): Remote errors are matched by tag and data, not `instanceof`.
93
+ - [`alchemy/apis/schemas-at-trust-boundaries`](./alchemy/apis/schemas-at-trust-boundaries/RULE.md): Outside input is schema-validated at trust boundaries.
94
+ - [`alchemy/data/commit-migrations-then-deploy`](./alchemy/data/commit-migrations-then-deploy/RULE.md): Migrations are committed ahead of time and applied as committed.
95
+ - [`alchemy/data/hyperdrive-direct-origin`](./alchemy/data/hyperdrive-direct-origin/RULE.md): Hyperdrive points at the database's direct endpoint.
96
+ - [`alchemy/data/migrations-use-direct-url`](./alchemy/data/migrations-use-direct-url/RULE.md): Migration runners connect with the database's direct URL.
97
+ - [`alchemy/data/never-disable-tls-verification`](./alchemy/data/never-disable-tls-verification/RULE.md): Database connections verify the server's TLS certificate.
98
+ - [`alchemy/data/private-endpoint-at-runtime`](./alchemy/data/private-endpoint-at-runtime/RULE.md): Service code reaches its database through the private binding.
99
+ - [`alchemy/data/single-migration-owner`](./alchemy/data/single-migration-owner/RULE.md): Each database has exactly one migration owner.
100
+ - [`alchemy/durable/idempotent-event-handlers`](./alchemy/durable/idempotent-event-handlers/RULE.md): Handlers for at-least-once events are idempotent.
101
+ - [`alchemy/durable/io-inside-steps`](./alchemy/durable/io-inside-steps/RULE.md): Workflow I/O runs inside steps; replayed code stays deterministic.
102
+ - [`alchemy/durable/no-self-triggering-bucket-writes`](./alchemy/durable/no-self-triggering-bucket-writes/RULE.md): Bucket handlers filter out events from their own writes.
103
+ - [`alchemy/durable/stable-step-names`](./alchemy/durable/stable-step-names/RULE.md): Workflow step names stay stable across replays.
104
+ - [`alchemy/durable/webhook-state-is-truth`](./alchemy/durable/webhook-state-is-truth/RULE.md): Paid access depends on webhook-recorded state, not success URLs.
105
+ - [`alchemy/providers/diff-guards-unresolved-props`](./alchemy/providers/diff-guards-unresolved-props/RULE.md): Provider diffs guard unresolved props with `isResolved`.
106
+ - [`alchemy/providers/idempotent-delete`](./alchemy/providers/idempotent-delete/RULE.md): Provider delete treats an already-gone resource as success.
107
+ - [`alchemy/providers/lazy-layer-construction`](./alchemy/providers/lazy-layer-construction/RULE.md): Provider layers defer credentials and connections until use.
108
+ - [`alchemy/providers/reconcile-from-observed-state`](./alchemy/providers/reconcile-from-observed-state/RULE.md): Provider reconcile converges from the resource's live state.
109
+ - [`alchemy/resources/anchor-paths-with-import-meta`](./alchemy/resources/anchor-paths-with-import-meta/RULE.md): Path props of resources declared outside the run directory use `import.meta`.
110
+ - [`alchemy/resources/idempotent-actions-and-seeds`](./alchemy/resources/idempotent-actions-and-seeds/RULE.md): Actions and seed files are safe to run again.
111
+ - [`alchemy/resources/previews-reference-shared-resources`](./alchemy/resources/previews-reference-shared-resources/RULE.md): Preview stages reference shared resources and add cheap pieces.
112
+ - [`alchemy/resources/protect-irreplaceable-data`](./alchemy/resources/protect-irreplaceable-data/RULE.md): Buckets and databases with irreplaceable data are retained.
113
+ - [`alchemy/resources/remote-state-for-ci`](./alchemy/resources/remote-state-for-ci/RULE.md): CI and multi-machine stacks use a shared state store.
114
+ - [`alchemy/resources/stable-logical-ids`](./alchemy/resources/stable-logical-ids/RULE.md): Resource logical ids stay the same across deploys.
115
+ - [`alchemy/resources/stage-unique-physical-names`](./alchemy/resources/stage-unique-physical-names/RULE.md): Global physical names are derived per stage.
116
+ - [`alchemy/runtime/bind-tag-not-implementation`](./alchemy/runtime/bind-tag-not-implementation/RULE.md): Other runtimes bind the Tag; only the Stack provides the Layer.
117
+ - [`alchemy/runtime/deterministic-config-defaults`](./alchemy/runtime/deterministic-config-defaults/RULE.md): Config defaults and fallbacks are deterministic.
118
+ - [`alchemy/runtime/disposables-in-request-scope`](./alchemy/runtime/disposables-in-request-scope/RULE.md): Disposables are acquired inside handlers, within request scope.
119
+ - [`alchemy/runtime/lambda-no-post-response-work`](./alchemy/runtime/lambda-no-post-response-work/RULE.md): Lambda handlers write durable work before responding.
120
+ - [`alchemy/runtime/no-per-request-work-at-construction`](./alchemy/runtime/no-per-request-work-at-construction/RULE.md): Construction builds resources and handlers, not per-request work.
121
+ - [`alchemy/runtime/resolve-config-and-bindings-at-construction`](./alchemy/runtime/resolve-config-and-bindings-at-construction/RULE.md): Config and bindings are resolved at construction, not in handlers.
122
+ - [`alchemy/secrets/let-alchemy-mint-infra-secrets`](./alchemy/secrets/let-alchemy-mint-infra-secrets/RULE.md): Infrastructure tokens are minted once by alchemy, not hardcoded.
123
+ - [`alchemy/secrets/none-in-browser-env`](./alchemy/secrets/none-in-browser-env/RULE.md): Browser-inlined env values hold only public configuration.
124
+ - [`alchemy/secrets/redacted-until-use`](./alchemy/secrets/redacted-until-use/RULE.md): Secrets stay `Redacted` until the call that needs the raw string.
125
+ - [`alchemy/secrets/unwrap-before-compare-or-send`](./alchemy/secrets/unwrap-before-compare-or-send/RULE.md): `Redacted` values are unwrapped before compare, send, or serialize.
126
+ - [`alchemy/security/authorize-public-endpoints`](./alchemy/security/authorize-public-endpoints/RULE.md): Public handlers authenticate and authorize every caller.
127
+ - [`alchemy/security/github-secret-not-variable`](./alchemy/security/github-secret-not-variable/RULE.md): Sensitive CI values use `GitHub.Secret`, not `GitHub.Variable`.
128
+ - [`alchemy/security/identity-from-verified-session`](./alchemy/security/identity-from-verified-session/RULE.md): The acting user comes from the verified session or token.
129
+ - [`alchemy/security/keep-auth-protections-on`](./alchemy/security/keep-auth-protections-on/RULE.md): Auth checks and protections stay enabled.
130
+ - [`alchemy/security/least-privilege-bindings`](./alchemy/security/least-privilege-bindings/RULE.md): Runtimes bind the narrowest capability their calls need.
131
+ - [`alchemy/security/least-privilege-ci-credentials`](./alchemy/security/least-privilege-ci-credentials/RULE.md): CI credentials are scoped to what the stack deploys.
132
+ - [`alchemy/security/lookup-failure-is-not-anonymous`](./alchemy/security/lookup-failure-is-not-anonymous/RULE.md): A failed session lookup is an error, not an anonymous user.
@@ -23,10 +23,12 @@ adhere init [--force] # .adhere/config.ts, two example rules, and the
23
23
  adhere init --shared org/repo # a repo of rules other repos install, with CI and an alchemy stack
24
24
  adhere login # save a TypeSafe AI API key; TYPESAFE_API_KEY takes precedence
25
25
  adhere validate # rule wording, rules a linter could check, contradictions
26
+ adhere rules create [idea] # wizard: claude, codex, or omp drafts a RULE.md or RULE.ts from excerpts you judge; org rules pushed for a PR
26
27
  adhere lint # judge the working directory; exit 1 on an error finding
27
28
  adhere lint --limit 0 # compiler-free counts/cache plan; no budgeting
28
29
  adhere lint --limit 100 # first 100 files needing requests; all pending rules per file
29
30
  adhere lint --yes # send without asking, as in CI
31
+ adhere lint --type-aware # opt in to both compiler symbols and declaration references
30
32
  adhere lint --preset effect # add a built-in rule set; the config becomes optional
31
33
  adhere lint --filter 'src/**' # read only matching files; repeat, and ! to leave out
32
34
  adhere lint --threshold 0.9 # report at another threshold from the cache; judges nothing again
@@ -38,8 +40,9 @@ adhere skill [docs|setup|fix] # print a skill
38
40
 
39
41
  `adhere <command> --help` lists every flag. Version, help, skills, `validate`,
40
42
  and planning with `--limit 0` do not start the native compiler. Default `lint`
41
- starts it only during execution, after confirmation, for pending judgments or
42
- cached findings still needing location.
43
+ is compiler-free. With `typeAware: true` or `--type-aware`, it starts the compiler
44
+ only during execution, after confirmation, for pending judgments or cached
45
+ findings still needing location.
43
46
 
44
47
  `--limit` now counts files, not rule checks; use the same flag without an extra
45
48
  unit selector. Each request-bearing file consumes one slot for all its pending
@@ -127,7 +130,7 @@ rule takes:
127
130
  `description`, `must`, `never`, and the rest. Its `appendState(state, file, Bun)`
128
131
  runs right before each request for the rule, and what it returns is spread
129
132
  over the request's state: `code`, the file's sections as Jev reads them,
130
- plus the shared context selected by the config's `reads`. Use it to give Jev what the file cannot show, such
133
+ plus the shared context enabled by the config's `reads` and `typeAware`. Use it to give Jev what the file cannot show, such
131
134
  as a schema another file holds, and name the key it adds in the description.
132
135
  Nothing it returns is checked, so it can break its own rule. The rule gets
133
136
  requests of its own, repeating the shared context. Hook-owned external data
@@ -153,7 +156,8 @@ export default defineConfig({
153
156
  presets: ["typescript", "security"], // built-in rule sets, or topics such as "effect/basics"
154
157
  threshold: 0.8, // default 0.8
155
158
  sufficiencyThreshold: 0.6, // below it, a finding warns the file and shared context may not show enough
156
- reads: ["workspacePackages", "symbols", "references"], // default; omitting this field keeps all three
159
+ reads: ["workspacePackages"], // default; [] omits workspace context
160
+ typeAware: false, // default; true or --type-aware enables both symbols and references
157
161
  exclude: ["**/generated/**"], // files no rule judges
158
162
  includeComments: false, // true only for rules about comments
159
163
  overrides: {
@@ -163,14 +167,16 @@ export default defineConfig({
163
167
  });
164
168
  ```
165
169
 
166
- Top-level `reads` selects shared context for every audited file and all its
167
- rules, including presets. `resolveConfig` defaults to
168
- `["workspacePackages", "symbols", "references"]` when the field is omitted,
169
- even without a config file. An explicit array replaces the default: `reads: []`
170
- is the code-only opt-out, and a subset limits context to those readers. Presets
171
- do not own or override this selection. Rule-level `reads`, in Markdown front
172
- matter, `defineRule`, or inline rules, is rejected with guidance to move it to
173
- the config. The available names are:
170
+ Top-level `reads` chooses workspace context for every audited file and all its
171
+ rules, including presets. It defaults to `["workspacePackages"]`, even without
172
+ a config file; `reads: []` omits that map. `typeAware` defaults to `false`.
173
+ Opting in with `typeAware: true` or `--type-aware` enables both `symbols` and
174
+ `references`, regardless of `reads`. Legacy native-reader entries in `reads`
175
+ alone do not enable the compiler; leaving them out does not disable it when
176
+ type awareness is on. Code alone requires `reads: []` and type awareness off.
177
+ Presets do not own or override this selection. A rule-level `reads`, in
178
+ Markdown front matter, `defineRule`, or an inline rule, has no effect. The
179
+ context maps are:
174
180
 
175
181
  - `workspacePackages`: only packages matched by this file's literal imports,
176
182
  as `{ canonicalPackageName: directory }`. Subpaths match the owning package;
@@ -184,10 +190,14 @@ the config. The available names are:
184
190
  and narrowing types stay distinct; docs/tags appear once per canonical symbol
185
191
  per file. This is not literal IDE hover text: there are no IDE labels or
186
192
  selected-call overload presentation. Unused local declarations may have type
187
- blocks too. Library types/docs can appear even when their source is excluded
188
- from snippets.
189
- - `references`: `{ Name: { pathname: declarationSnippet } }` for used symbols'
190
- canonical outgoing alias-target declarations. Each snippet is the smallest
193
+ blocks too. Standard-library and Node/Bun built-ins and their methods are
194
+ omitted; project and third-party symbols remain, including built-in-name
195
+ shadows. Built-in type names can still appear inside meaningful signatures.
196
+ - `references`: a flat `Record<string, string>`, as
197
+ `{ "Name:path/to/file.ts": "declarationSnippet" }`, for declarations of symbols
198
+ used by the target code, not incoming call sites. Keys retain names as used,
199
+ including import aliases, and repository-relative pathname casing; alias targets
200
+ are resolved canonically. Each snippet is the smallest
191
201
  complete AST declaration scope, with no extra surrounding lines: full function
192
202
  bodies; whole arrow/object initializer variable statements, including
193
203
  `export const` and semicolons; whole methods/getters/setters, not their classes;
@@ -201,8 +211,10 @@ the config. The available names are:
201
211
  exclusions remain. There are no counts, incoming callers, structured locations,
202
212
  unresolved lists, full-file collection, or completeness metadata.
203
213
 
204
- Default npm-installed lint uses `symbols` and `references` with adhere's pinned
205
- native TypeScript compiler through the npm/Bun launcher. No root `tsconfig.json`
214
+ When type awareness is enabled, npm-installed lint uses both `symbols` and
215
+ `references` with adhere's pinned native TypeScript compiler through the npm/Bun
216
+ launcher. Enabled context maps include a self-describing `__comment` in Jev's
217
+ state; top-level guidance identifies only `code` as the audit target. No root `tsconfig.json`
206
218
  or root file-list membership is required. During execution, native TypeScript
207
219
  opens files with pending judgments or cached findings needing location and
208
220
  discovers each file's configured project, including package
@@ -243,27 +255,32 @@ program graphs can still consume substantial time/memory. Bounding active
243
255
  documents/snapshots does not make total memory or model payload size constant,
244
256
  and oversized contexts are still possible. Context is queried just
245
257
  before judge/locate and reused locally. Planning never calls `SourceReads`.
246
- Source checkouts use their development compiler dependency. Raw GitHub
247
- binaries still have no compiler resources: their lint requires explicit config
248
- `reads: []` or `reads: ["workspacePackages"]` for execution; use the package
249
- launcher for the full default. Plan-only `--limit 0` needs no compiler or API key.
258
+ Type-aware source checkouts use their development compiler dependency. Raw
259
+ GitHub binaries have no compiler resources, but run the default compiler-free
260
+ audit with workspace context without special configuration. Use `reads: []`
261
+ for code alone, with type awareness off; use the package launcher or a checkout
262
+ for type-aware execution. Plan-only `--limit 0` needs no compiler or API key.
250
263
 
251
264
  Rules without `appendState` share requests and pay for shared input context
252
265
  once per request, not once per rule. Context repeats on request splitting,
253
266
  locating findings, and hook requests. Compiler documentation and complete declaration
254
- scopes add default token/privacy cost, including source from files not judged.
267
+ scopes add token/privacy cost only when type awareness is enabled, including
268
+ source from files not judged.
255
269
  Complete scopes may contain substantially more source/tokens than fixed-line
256
270
  excerpts; function bodies are not peeked or capped to seven lines.
257
271
  Compiler-provided docs and JSDoc tags can remain present with ordinary comments
258
- stripped. Omit `symbols` to disable type/docs context, `references` to disable
259
- snippets, or use `reads: []` for code-only built-in context.
272
+ stripped. Keep `typeAware` off to omit both native maps; `reads` controls only
273
+ workspace context. Use `reads: []` with type awareness off for code alone.
260
274
  Plan token/cost estimates include code and cheap workspace metadata only, not
261
275
  native context or hook-added data. Actual cost and request splits may therefore
262
276
  be higher. Shared state plus any one question must fit 32k tokens, and state
263
277
  plus all questions in a request must fit 64k, with 1k reserved for overhead.
264
- Execution splits question batches, checks full budgets before HTTP, and skips
265
- oversized files instead of silently truncating type/docs strings or complete scopes. Only
266
- `appendState` forces a private rule request group.
278
+ Execution splits question batches and checks full budgets before HTTP. On
279
+ context overflow, it retries once without `references` when that map is present,
280
+ keeping target code and `symbols` intact; a further overflow skips the file.
281
+ Complete declaration scopes are not shortened to fit. Symbol strings have
282
+ configurable `maxSymbolLength` and `maxSymbolDocumentationLength` limits, both
283
+ 256 by default. Only `appendState` forces a private rule request group.
267
284
 
268
285
  `overrides` changes any rule by the id the report shows, a preset's with the
269
286
  preset first, without copying it; an id no rule has refuses the run. `rules`
@@ -330,8 +347,8 @@ re-judges that rule; a threshold change re-judges nothing.
330
347
 
331
348
  Dependencies, related source, reader selection, shared read-context contents,
332
349
  and hook-owned external data are deliberately not fingerprinted. If `A.ts` imports
333
- `B.ts`, changing `B.ts` does not invalidate `A.ts`. Changing config `reads` does
334
- not refresh its cached answers either. This keeps planning cheap but accepts
350
+ `B.ts`, changing `B.ts` does not invalidate `A.ts`. Changing config `reads` or
351
+ `typeAware` does not refresh its cached answers either. This keeps planning cheap but accepts
335
352
  stale dependency/context judgments.
336
353
 
337
354
  `planAudit` reads/counts/hashes code, checks the cache, and makes code plus cheap
@@ -344,8 +361,8 @@ budgeting, native reads, and HTTP execution.
344
361
  Source reload/hash work is bounded to 8 files; plans retain compact metadata and
345
362
  estimates, not all file contents. Only sampled-linter files need a planning
346
363
  reread. After confirmation, execution reloads request-bearing files and cached
347
- finding excerpts, preparing full native context only for pending or
348
- cached-unlocated files just before judge/locate. Every reload validates normalized
364
+ finding excerpts, preparing native context only when type awareness is enabled,
365
+ for pending or cached-unlocated files just before judge/locate. Every reload validates normalized
349
366
  code and ignore directives against the active plan; changes refuse with rerun
350
367
  guidance, without adding persistent-cache keys. A fully cached and located run
351
368
  starts no compiler and needs no API key or Jev requests.
@@ -390,7 +407,8 @@ the file breaks the rule. On a terminal it is amber near its rule's
390
407
  threshold, within a quarter of the room above it (0.80 to 0.84 at a threshold
391
408
  of 0.80), and green above that: a rule whose findings are mostly amber turns
392
409
  on where its threshold sits. `context` is its probability that the file and
393
- shared context show enough to decide; all three readers are included by default.
410
+ shared context show enough to decide. Default context is `workspacePackages`;
411
+ `symbols` and `references` require `typeAware: true` or `--type-aware`.
394
412
  It is colored the same way around the sufficiency threshold, 0.6
395
413
  by default: amber from 0.50 to 0.69, red below. Below 0.6 the finding also
396
414
  carries `warning: this file may not show enough to check this rule`. It turns
@@ -25,10 +25,10 @@ the `packageManager` field in `package.json` names it; with neither, **Ask**.
25
25
 
26
26
  | Manager | Add adhere | Run adhere |
27
27
  | ------- | -------------------------------- | ------------------ |
28
- | bun | `bun add -D @drkmttr/adhere` | `bunx adhere` |
28
+ | bun | `bun add -D @drkmttr/adhere` | `bun run adhere` |
29
29
  | pnpm | `pnpm add -D @drkmttr/adhere` | `pnpm exec adhere` |
30
30
  | yarn | `yarn add -D @drkmttr/adhere` | `yarn adhere` |
31
- | npm | `npm install -D @drkmttr/adhere` | `npx adhere` |
31
+ | npm | `npm install -D @drkmttr/adhere` | `npm exec adhere` |
32
32
 
33
33
  In a repo with a `package.json`, add adhere as a dev dependency with its
34
34
  manager, so the repo pins the version the team and CI run. From then on,
@@ -37,30 +37,38 @@ wherever this skill says `adhere`, run it the manager's way, as in
37
37
 
38
38
  With pnpm, at a workspace root, add `--ignore-workspace-root-check`.
39
39
 
40
- Default lint enables `workspacePackages`, `symbols`, and `references`, and
41
- starts native TypeScript only during execution, after confirmation, when
42
- pending judgments or cached findings needing location require context. It discovers each
43
- file's configured project, including package projects under solution roots,
44
- and falls back to inferred context for unconfigured or excluded files. No root
45
- `tsconfig.json` or literal root file-list membership is required; do not block
46
- setup on either. `.adhere/tsconfig.json` only types the config and rules.
47
- Planning, `--limit 0`, version, help, skills, and validate do not start the
48
- compiler.
40
+ Default lint reads code and `workspacePackages` without starting a compiler.
41
+ `typeAware` defaults to `false`; `typeAware: true` or `--type-aware` opts into
42
+ both `symbols` and `references`, regardless of `reads`. `reads` now controls
43
+ workspace context only, defaulting to `["workspacePackages"]`; legacy native
44
+ reader entries alone do not opt in. Code alone uses `reads: []` with type
45
+ awareness off. Explain the extra context/cost and **Ask** before opting in.
46
+
47
+ With type awareness enabled, native TypeScript starts only during execution,
48
+ after confirmation, when pending judgments or cached findings needing location
49
+ require context. It discovers each file's configured project, including package
50
+ projects under solution roots, and falls back to inferred context for
51
+ unconfigured or excluded files. No root `tsconfig.json` or literal root file-list
52
+ membership is required; do not block setup on either. `.adhere/tsconfig.json`
53
+ only types the config and rules. Planning, `--limit 0`, version, help, skills,
54
+ and validate do not start the compiler.
49
55
 
50
56
  In a repo without a `package.json`, inspect any `adhere` on PATH with
51
57
  `adhere --version`, then **Ask** whether to use the npm/Bun package launcher
52
- for the full default or a raw executable with deliberately reduced context.
53
- The raw release (`adhere-Windows-x86_64.exe` on Windows) needs no Node or
54
- package manager, but its lint requires explicit config `reads: []` or
55
- `reads: ["workspacePackages"]`. Do not silently disable readers to make it
56
- work. Only fetch it after the user chooses that alternative:
58
+ or a raw executable for the same default compiler-free audit. The raw release
59
+ needs no Node or package manager and runs with workspace context without
60
+ special configuration. It cannot run a type-aware audit: use the package
61
+ launcher or a checkout if the user opts in. Do not silently turn off an
62
+ explicitly chosen `typeAware` setting. Only fetch the raw release after the
63
+ user chooses that alternative. On macOS and Linux:
57
64
 
58
65
  ```sh
59
- curl -fsSL --create-dirs -o ~/.local/bin/adhere \
60
- https://github.com/darkmatter/adhere/releases/latest/download/adhere-$(uname -s)-$(uname -m)
61
- chmod +x ~/.local/bin/adhere
66
+ curl -fsSL https://github.com/darkmatter/adhere/raw/main/scripts/install.sh | sh
62
67
  ```
63
68
 
69
+ On Windows, download `adhere-Windows-x86_64.exe` from
70
+ https://github.com/darkmatter/adhere/releases/latest.
71
+
64
72
  Validate and lint's paid requests need a TypeSafe AI API key: `TYPESAFE_API_KEY`,
65
73
  or one saved by `adhere login`, which the user runs; never ask for the key in
66
74
  chat or print it. Compiler-free planning with `--limit 0` needs no key.
@@ -139,10 +147,11 @@ the wording of any. Revise drafts the user wants changed and show them again.
139
147
  - Copy each chosen draft to `.adhere/rules/<topic>/<slug>/RULE.md`.
140
148
  - Add chosen presets, or topics, to `presets` in `.adhere/config.ts`. Presets
141
149
  use the audit-wide readers; they do not own or override `reads`.
142
- - Leave `reads` omitted for the full default. Do not add `reads: []` to the
143
- normal setup recommendation or as a workaround for missing compiler
144
- resources. Only set an explicit replacement array if the user chooses to
145
- disable or limit readers.
150
+ - Leave `reads` omitted for default workspace context and `typeAware` off
151
+ unless the user explicitly chooses type-aware execution. `reads: []` omits
152
+ workspace context, not native maps. Only replace `reads` if the user chooses
153
+ to limit workspace context. If requested type awareness lacks compiler resources,
154
+ use the package launcher or a checkout; do not silently turn it off.
146
155
  - Install chosen shared rules: `adhere install org/repo/<id>` for each, or
147
156
  `adhere install org/repo` for all of them. They land in `.adhere/rules/org/repo/`.
148
157
  - Add `exclude` globs for generated or vendored code the default skips miss.
@@ -177,19 +186,21 @@ cost, and request splits may be higher. Source reload/hash work is bounded to
177
186
  for execution; if normalized code or ignore
178
187
  directives changed since planning, rerun rather than using the old plan.
179
188
 
180
- Tell the user that compiler type/docs strings and outgoing declaration snippets add
181
- source/documentation sharing and token cost by default, including complete
182
- scopes from files outside the audit filter. Whole declaration bodies can use more
183
- tokens than fixed-line excerpts; budget overflow skips the file instead of
184
- capping bodies to seven lines or silently truncating them. Compiler-provided
185
- documentation and JSDoc tags can remain even when ordinary code comments are
186
- stripped; omitting `symbols` disables type/docs context and omitting
187
- `references` disables snippets. The global workspace catalog is not sent: only
188
- this file's matched literal imports appear under canonical package keys.
189
- Offer an explicit reader subset or code-only opt-out if they want less context;
190
- never apply one silently. Neither reader selection nor dependency/shared-context
191
- changes invalidate cached judgments. If they want fresh answers under changed
192
- context, **Ask** before clearing `.adhere/cache/`; do not clear it automatically.
189
+ If the user opts into type awareness, explain that both compiler type/docs
190
+ strings and outgoing declaration snippets add source/documentation sharing and
191
+ token cost, including complete scopes from files outside the audit filter.
192
+ Whole declaration bodies can use more tokens than fixed-line excerpts. Context
193
+ overflow gets one retry without `references`, keeping target code and `symbols`
194
+ intact; it can still overflow and skip the file. Declaration bodies are not
195
+ shortened to fit. Compiler documentation and JSDoc tags can remain even when
196
+ ordinary code comments are stripped, subject to the configured symbol limits.
197
+ The global workspace catalog is not sent: only this file's matched literal
198
+ imports appear under canonical package keys.
199
+ Offer type awareness only as an explicit opt-in, or `reads: []` with type
200
+ awareness off for code alone; never apply either silently. Neither `reads`,
201
+ `typeAware`, nor dependency/shared-context changes invalidate cached judgments.
202
+ If they want fresh answers under changed context, **Ask** before clearing
203
+ `.adhere/cache/`; do not clear it automatically.
193
204
 
194
205
  On a large repo, offer a subtree such as `--filter 'src/**'`, or a file cap
195
206
  such as `--limit 100`: the first 100 files needing requests in path order, with
@@ -201,7 +212,9 @@ or HTTP-size skips after selection consume a slot without runtime refill.
201
212
 
202
213
  Explain that a file cap is not an HTTP-request or token/cost cap: each file can
203
214
  produce judge, locate, split-batch, and private hook requests. **Ask** before
204
- sending, then run the command below with only the user's chosen filter/file cap:
215
+ sending, then run the command below with only the user's chosen filter/file cap
216
+ and `--type-aware` if they explicitly opted in, or retain `typeAware: true` in
217
+ their config:
205
218
 
206
219
  ```sh
207
220
  adhere lint --yes
@@ -209,11 +222,14 @@ adhere lint --yes
209
222
 
210
223
  `SourceReads.prepare(paths)` registers eligible-path metadata only, with no
211
224
  file I/O, compiler/SDK import, spawn, snapshot, or semantic query, even for a large list.
212
- Only after confirmation do pending judgments or cached findings still needing
213
- location trigger actual per-file native reads just before judge/locate. Native
225
+ Only with type awareness enabled, and after confirmation, do pending judgments
226
+ or cached findings still needing location trigger actual per-file native reads
227
+ just before judge/locate. Native
214
228
  transactions are serial through one permit; HTTP execution remains concurrent
215
229
  at 8. Returned context is reused locally and full budgets are enforced before
216
- HTTP, with oversized files skipped and no silent truncation. Shared state plus
230
+ HTTP. Oversized context gets one retry without references when present, then
231
+ skips the file if it still does not fit; code and declaration bodies are not
232
+ shortened to fit. Shared state plus
217
233
  one question must fit 32k tokens and state plus all questions must fit 64k per
218
234
  request, with 1k reserved for overhead. The SDK may still parse a full selected
219
235
  project, and additional monorepo programs may increase startup time and memory.
@@ -223,9 +239,13 @@ blocks for same-name binding/narrowing contexts, with compiler documentation
223
239
  and JSDoc tags once per canonical symbol per file. It does not promise literal
224
240
  IDE labels or selected-call overload presentation. Symbol/type queries are
225
241
  batched, and independent SDK requests are chunked to at most 8 within the single
226
- active native document/snapshot; HTTP work remains concurrent at 8. `references` maps used names to canonical outgoing declarations
227
- by pathname, selecting the smallest complete AST scope without extra surrounding
228
- lines. Functions include full bodies; arrow/object initializer variables include
242
+ active native document/snapshot; HTTP work remains concurrent at 8. Standard-library
243
+ and Node/Bun built-ins are omitted, but project and third-party names remain.
244
+ `references` is a flat `Record<string, string>` keyed by
245
+ `symbol:repository-relative pathname`, retaining import alias names and original
246
+ pathname casing. Values are declarations of symbols used by the target code,
247
+ not incoming call sites, selecting the smallest complete AST scope without extra
248
+ surrounding lines. Functions include full bodies; arrow/object initializer variables include
229
249
  whole variable statements with `export const` and semicolons. Methods, getters,
230
250
  and setters include their whole member, not the entire class; classes,
231
251
  interfaces, and type aliases include the whole declaration. Repeated/overlapping
@@ -235,7 +255,10 @@ not automatically expanded. Scopes preserve indentation and the comment/directiv
235
255
  policy, including associated JSDoc when `includeComments` is true; compiler
236
256
  docs/tags in `symbols` remain available regardless. Current-file, declaration-file, `node_modules`, and
237
257
  outside-root exclusions are unchanged. There are no incoming callers, counts, structured locations,
238
- unresolved lists, full-file collection, or completeness markers.
258
+ unresolved lists, full-file collection, or completeness markers. Enabled context
259
+ maps include a self-describing `__comment`; top-level guidance identifies only
260
+ `code` as the audit target. Both native maps require the same type-awareness
261
+ opt-in; `reads` cannot select or disable them individually.
239
262
 
240
263
  The first actual read lazily starts one native TypeScript LSP process with its
241
264
  public SDK API pipe; both are pinned to exactly `7.1.0-dev.20261009.1` and must
@@ -332,15 +355,16 @@ jobs:
332
355
  Pin the versions the repo already uses: bun's `bun-version`, Node's
333
356
  `node-version` from `.nvmrc` or `engines`, and pnpm's from `packageManager`,
334
357
  which `pnpm/action-setup` reads. Keep optional dependencies enabled so adhere's
335
- platform package and its compiler dependency are installed. Existing project
336
- configs and dependencies supply configured context when available; files with
337
- no configured project or excluded from one use inferred context. Do not require
338
- or generate a root `tsconfig.json` merely to make default lint run. In a repo
339
- without a `package.json`, use the package launcher for the full default.
340
- Only skip setup/install and fetch the raw executable if the user explicitly
341
- chose and committed `reads: []` or `reads: ["workspacePackages"]` locally.
342
- That is a reduced-context alternative, not an equivalent default installation.
343
- Fetch the executable at the version the user ran:
358
+ platform package and its compiler dependency are installed. For type-aware audits,
359
+ existing project configs and dependencies supply configured context when available;
360
+ files with no configured project or excluded from one use inferred context. Do not
361
+ require or generate a root `tsconfig.json` merely to make default lint run. Both
362
+ package launchers and raw executables support the default compiler-free audit,
363
+ including in repos without a `package.json`; no `reads` override is required.
364
+ If the user explicitly chose type-aware execution, use the package launcher or a
365
+ checkout; do not silently turn it off. For the default compiler-free audit, you can
366
+ instead skip runtime setup/install and fetch the raw executable at the version
367
+ the user ran:
344
368
 
345
369
  ```yaml
346
370
  - run: |