@hublo/sentinel 1.5.1-alpha.0 → 1.5.1-alpha.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/dist/index.js CHANGED
@@ -6,10 +6,10 @@ import {
6
6
  registerAdapters,
7
7
  resolve,
8
8
  setDefaultRunner
9
- } from "./chunk-CL7HOHTU.js";
9
+ } from "./chunk-JHLNNIZC.js";
10
10
  import {
11
11
  BaseAdapter
12
- } from "./chunk-I2WDZNPR.js";
12
+ } from "./chunk-P7NYSMLS.js";
13
13
  import "./chunk-JRZI5IIN.js";
14
14
  import "./chunk-WBDBRGLV.js";
15
15
  import "./chunk-O7REVMOC.js";
@@ -7,7 +7,7 @@ import {
7
7
  readTestAdoption,
8
8
  resolveVitest,
9
9
  suiteOf
10
- } from "./chunk-I2WDZNPR.js";
10
+ } from "./chunk-P7NYSMLS.js";
11
11
  import "./chunk-JRZI5IIN.js";
12
12
  import "./chunk-O7REVMOC.js";
13
13
  import "./chunk-QXFCZON7.js";
@@ -14,7 +14,8 @@ npx --yes @hublo/sentinel@<version> --init --preset <react|nest|node|svelte>
14
14
  pnpm install
15
15
  ```
16
16
 
17
- `--init` with no target adopts every role, and that is the intended order: lint fixes what it
17
+ `--init` with no target adopts every role on a module that has adopted none (on one that has,
18
+ it re-inits the roles it has), and that is the intended order: lint fixes what it
18
19
  can, then the formatter runs **last** and formats everything every role wrote.
19
20
 
20
21
  **Format and lint are adopted together.** `--init --format`, `--init --lint` and
@@ -106,6 +107,15 @@ declared is reported as drift, because nobody said this module should format dif
106
107
 
107
108
  `ignorePatterns` and `overrides` are always yours and never need declaring.
108
109
 
110
+ `sortImports` is yours as soon as you set it: a team that sorts its imports (with ESLint's
111
+ `import/order` groups, say) turns it on with its own groups, and a re-`init` keeps the value and
112
+ declares it in `local` itself, rather than taking it back as drift. Since 1.5.1.
113
+
114
+ `$sentinel.version` is the release the file's CONTENT came from. A re-`init` that would write the
115
+ same content keeps it, so a version bump is not a diff in every module; one that changes anything,
116
+ the preset or a carried ignore pattern included, stamps the release that wrote it. Since 1.5.1;
117
+ before it, the stamp could stay behind content a later release had rewritten.
118
+
109
119
  A setting is carried only if oxfmt accepts the **value**, not just the key: what it rejects is
110
120
  dropped and named in the adoption output (see "What did not survive the move"). The check asks
111
121
  oxfmt's own shipped schema, so it stays true across oxfmt releases.
@@ -270,6 +280,22 @@ expect most of the module to be touched.
270
280
  The gap is reported rather than warned on every run: it is a state of the module, not an
271
281
  event. A message that fires on every `pnpm run lint` is a message people stop reading.
272
282
 
283
+ ### Imports whose order is deliberate
284
+
285
+ Some files need an import to come first: Datadog's `dd-trace` has to load before the modules it
286
+ instruments, `reflect-metadata` before the decorators that read it. Sorting would move them, and
287
+ nothing fails when it does, the service just ships with tracing initialized too late. That is what
288
+ happened to `libs/nest/tracer` in monorepo#23314.
289
+
290
+ So when the module sorts imports, `--init` looks, before the formatter runs, for files where the
291
+ order is deliberate: an `eslint-disable` naming an import-order rule (`import/order`,
292
+ `import/first`, `simple-import-sort/*`), or an import of a module that has to load first
293
+ (`dd-trace`, `reflect-metadata`, `source-map-support/register`, the OpenTelemetry SDK, `core-js`).
294
+ Both lists are data, in `src/roles/format/presets/deliberate-import-order.json`. When the sort
295
+ would move one of those imports past another, it gets a `// oxfmt-ignore` above it, which oxfmt
296
+ honours: the sort then works between the pinned imports and never across them. The init report
297
+ names the files. A file the sort would not change is left alone, so a re-init adds nothing.
298
+
273
299
  ### The one grouping difference, and why it stands
274
300
 
275
301
  `import/order` explicitly listed this repo's 14 workspace scopes (`@hublo/**`, `@shared/**`,
@@ -17,7 +17,8 @@ pnpm install
17
17
 
18
18
  Then run `pnpm run lint`.
19
19
 
20
- `--init` with no target adopts **every role sentinel ships**, and for lint that is the
20
+ `--init` with no target on a module that has adopted nothing adopts **every role sentinel
21
+ ships** (on a module that has, it re-inits the roles it has), and for lint that is the
21
22
  intended way round: it runs the linter's autofix, then writes the format config and formats
22
23
  the module, so the files it generated are already in your module's style.
23
24
 
@@ -172,6 +173,66 @@ whatever `extends` it finds, so a layer already there survives and is respected
172
173
  that follows. Added afterwards, the autofix has already run, and nothing undoes what it
173
174
  rewrote. One team met this as twelve rewritten files.
174
175
 
176
+ ### Where a team puts its own guards
177
+
178
+ Lint is always migrated, so a guard your ESLint carried and the preset does not is yours to add,
179
+ in your own config. A re-`init` keeps all of it (since 1.5.1): your `extends` layers in their
180
+ order after sentinel's preset, and in `.oxlintrc.json` your `rules`, `plugins`, `jsPlugins`,
181
+ `settings` and `overrides`. `--init` prints one line per block it kept.
182
+
183
+ `console` keeps two rules the react preset does not configure, directly in its stub:
184
+
185
+ ```json
186
+ {
187
+ "extends": ["./node_modules/@hublo/sentinel/lint/react.json"],
188
+ "rules": {
189
+ "import/no-cycle": "error",
190
+ "oxc/no-barrel-file": ["error", { "threshold": 0 }]
191
+ }
192
+ }
193
+ ```
194
+
195
+ A local plugin and file-scoped rules, the shape a planning layer takes:
196
+
197
+ ```json
198
+ {
199
+ "extends": ["./node_modules/@hublo/sentinel/lint/react.json"],
200
+ "jsPlugins": [{ "name": "planning", "specifier": "./lint/planning-plugin.mjs" }],
201
+ "overrides": [
202
+ {
203
+ "files": ["src/modules/planning/**/*.tsx"],
204
+ "rules": { "planning/no-raw-date": "error", "max-depth": ["error", 3] }
205
+ }
206
+ ]
207
+ }
208
+ ```
209
+
210
+ Two limits, both the preset's governance:
211
+
212
+ - **An entry the preset already has is the preset's.** A rule it configures (top level or in one
213
+ of its overrides, at any severity), a `jsPlugins` entry it registers under the same name, a
214
+ `settings` key it sets: written in the stub, it would override sentinel's, so a re-`init` drops
215
+ it and names it. That includes `no-console` and `no-restricted-imports` in the react preset. To
216
+ set one of those for your module, put it in an `extends` layer after the preset (above): a
217
+ layer is reviewed as yours and `--inspect` shows it.
218
+ - **"The same rule" is the rule oxlint runs, not the name you wrote** (since 1.5.1). Oxlint
219
+ accepts several names for one rule: `eslint/x` is `x`, `typescript/x` is the eslint rule `x`
220
+ for 18 rules that typescript-eslint extends (`no-restricted-imports`, `no-unused-vars`,
221
+ `no-unused-expressions`, ...), `@typescript-eslint/` is `typescript/`, `react-hooks/` is
222
+ `react/`, `jsx-a11y/` is `jsx_a11y/`, `import-x/` is `import/`, `eslint-plugin-` prefixes are
223
+ dropped, and a bare name belongs to the first built-in rule of that name. Measured on 1.77.0, a
224
+ react stub setting `typescript/no-restricted-imports` beside console's two rules linted with
225
+ its own patterns and none of the preset's, so `@nestjs/*` imports passed. A re-`init` now drops
226
+ an alias like the name it stands for, and says which preset rule it is:
227
+ `typescript/no-restricted-imports (oxlint runs it as no-restricted-imports)`.
228
+ - **Your `overrides` blocks are kept as written**, with their `files`, and their rules go through
229
+ the same filter. Two of your blocks with the same `files` are merged into one on re-`init`; a
230
+ block is never merged into a preset override, which lives behind `extends` where the stub
231
+ cannot write. Measured on oxlint 1.77.0, the version sentinel ships: an `overrides` block in an
232
+ extended file DOES apply, and `plugins` and `jsPlugins` in the stub add to the extended ones
233
+ rather than replace them. The planning layer's notes say overrides do not cross `extends`; that
234
+ is not what 1.77.0 does.
235
+
175
236
  ## What a preset does not enforce
176
237
 
177
238
  Every unenforced rule carries a reason, readable with `sentinel --inspect --lint`:
@@ -232,7 +293,12 @@ things follow, and they are the point:
232
293
  - your own config stays `extends` + `ignorePatterns`, so a rule **you** change by hand is
233
294
  still reported as drift and is never confused with a hold sentinel made;
234
295
  - `--init` says what it held and how many violations each hold covers, so the debt is
235
- announced rather than discovered.
296
+ announced rather than discovered;
297
+ - a hold is written under the **preset's** name for the rule (since 1.5.1). Oxlint reports
298
+ `eslint(no-unused-expressions)` for a rule the nest preset configures as
299
+ `typescript/no-unused-expressions`, and a hold keyed `no-unused-expressions` did not hold:
300
+ measured on 1.77.0, the violation stayed an `error` on react and nest, because oxlint keeps the
301
+ two names side by side and picks one by hash order.
236
302
 
237
303
  Do not edit `.oxlintrc.baseline.json` by hand. Commit it: it is part of the adoption, and it
238
304
  is what makes the promise above true on the day you adopt rather than on the day the preset
@@ -225,5 +225,9 @@ visible. Closing it in one action is [issue #17](https://github.com/hublo/sentin
225
225
  today it is one command per module.
226
226
 
227
227
  **Upgrading:** bump the pin, `pnpm install`, then `sentinel --init` in the module and commit
228
- what changes. `--init` is idempotent, so on a version that changed nothing relevant it reports
229
- nothing to change.
228
+ what changes. On a module that has already adopted a role, a bare `--init` re-inits only the roles
229
+ it has adopted, the ones `sentinel --inspect` reports, and names them in one line. It does not
230
+ adopt a new role on the way: adopting the test role, for instance, is a migration of its own, so
231
+ it is asked for by name (`sentinel --init --test`), or every role at once with `--init --all`.
232
+ `--init` is idempotent, so on a version that changed nothing relevant it reports nothing to
233
+ change.
@@ -135,6 +135,177 @@ majority of the migration, and only a sweep over every real module found it.
135
135
 
136
136
  ---
137
137
 
138
+ ## The `--init` matrix for 1.5.1, 29 October 2026
139
+
140
+ Six fixes, then a seventh (below) found by the alpha.1 validation. Found by re-initializing the monorepo's 63 adopted modules with 1.5.1-alpha.0. Every
141
+ cell below is a test in this repo, against the built CLI unless it says unit, and every fix has a
142
+ negative control: the fix reverted in the source, the cells run again, and the cells that must
143
+ fail do. No existing cell changed: against the alpha, the test tree gains lines and loses none
144
+ (`git diff --numstat` on `tests/`: 0 deletions), in 10 new files and 3 existing ones.
145
+
146
+ ### 1. a bare `--init` re-inits the roles a module has (`init-bare-on-adopted`)
147
+
148
+ | module state | from the module | from the root, `--module` |
149
+ | ---------------------------- | -------------------------------- | ------------------------- |
150
+ | nothing adopted | every role | every role |
151
+ | typescript adopted | typescript only | typescript only |
152
+ | lint adopted | lint and format | (pairing, same rule) |
153
+ | typescript adopted, `--all` | every role | |
154
+ | typescript adopted, real run | no lint or format config written | |
155
+
156
+ ### 2. the lint baseline runs the lint script's leading commands (`init-lint-baseline-runs-script-prefix`)
157
+
158
+ | lint script | baseline |
159
+ | --------------------------------------- | ------------------------------------------ |
160
+ | `eslint .` (control) | holds `typescript/tsconfig-error` |
161
+ | `node generate.mjs && eslint .` | nothing held, the command is named |
162
+ | `node -e "process.exit(3)" && eslint .` | nothing written, says the command exited 3 |
163
+
164
+ Unit (`leading-commands`): `&&` chains only; `;`, `||` and a script that never reaches sentinel
165
+ return nothing.
166
+
167
+ ### 3. the `$sentinel` stamp follows the content (unit, `format-adoption`)
168
+
169
+ | re-init | stamp |
170
+ | --------------------------------- | ------------------------ |
171
+ | same content | kept (no diff on a bump) |
172
+ | preset changed (`base` to `nest`) | this release |
173
+ | a carried ignore pattern added | this release |
174
+
175
+ ### 4. two re-init messages (unit `build-init`, e2e `init-tools-defers-every-role`)
176
+
177
+ | case | said |
178
+ | --------------------------------------------------- | ---------------------------------------------------- |
179
+ | vite config rewritten, format adopted / not adopted | the format line, naming the rewritten files |
180
+ | vite config already adopted | no format line |
181
+ | lint config declares `tools`, `--init --typescript` | deferred, naming the lint config, tsconfig untouched |
182
+ | same module, bare `--init` | every role deferred |
183
+ | same module, `--preset node` | not deferred, the explicit preset decides |
184
+
185
+ ### 5. a deliberate import order survives the sort (`init-format-import-order-matrix`, `init-format-keeps-deliberate-import-order`)
186
+
187
+ Each file is one cell, run on a first adoption AND on a re-init, nest preset:
188
+
189
+ | signal in the file | order kept | pins |
190
+ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | -------------------------------------------------------- |
191
+ | `eslint-disable-next-line import/order` | yes | 1 |
192
+ | `eslint-disable import/order` region, then `eslint-enable` | inside yes, after it sorted | 2 |
193
+ | file-wide `/* eslint-disable import/order */` | yes | 3 |
194
+ | `eslint-disable-line import/first` | yes | 1 |
195
+ | `eslint-disable-next-line simple-import-sort/imports` | yes | 1 |
196
+ | first import: `dd-trace` (value) | yes | 1 |
197
+ | first import: `@opentelemetry/sdk-node` (value) | yes | 1 |
198
+ | first import, side effect: `dd-trace/init`, `reflect-metadata`, `source-map-support/register`, `core-js/stable`, `regenerator-runtime/runtime` | yes | 0: oxfmt 0.63.0 does not move a first side-effect import |
199
+ | side-effect `reflect-metadata` with an import the sort crosses | yes | 1 |
200
+ | two signals in one file, normal imports between them | pinned yes, the rest sorted | 2 |
201
+ | a `.tsx` file | yes | 1 |
202
+ | the tracer file of monorepo#23314 | yes | 3 |
203
+ | no signal at all (two files) | byte-identical to oxfmt alone | 0 |
204
+
205
+ And: the report names exactly the pinned files; `format:fix` then the format check keep every
206
+ order; a second re-init changes no file and adds no pin; a module that does not sort (react
207
+ preset) gets no pin. Unit (`deliberate-import-order`): a type-only import is never pinned, an
208
+ `eslint-disable` naming no order rule is ignored.
209
+
210
+ Negative control, `keepDeliberateImportOrder` disabled: 14 cells fail, the ten pinned files in
211
+ both modes, the report, `format:fix` and the tracer cells. The five first-position side-effect
212
+ cells pass without the fix, which is what the measurement above says.
213
+
214
+ ### 6. a re-init keeps what a team added (`init-keeps-team-config-matrix`, `init-keeps-team-lint-config`)
215
+
216
+ | block in the module's config | after re-init |
217
+ | -------------------------------------------------------------------------------- | ---------------------------------------------------------- |
218
+ | a rule outside the preset | kept |
219
+ | a rule the preset configures | dropped, named |
220
+ | `jsPlugins`: a local path and a package entry | kept |
221
+ | `jsPlugins` under a name the preset registers | dropped, named |
222
+ | `overrides` on files no preset override names | kept |
223
+ | `overrides` on the preset override's own files | kept as the module block, governed rules dropped and named |
224
+ | `plugins` | kept, minus the preset's own |
225
+ | `settings` | kept |
226
+ | a second `extends` entry | kept, in order, after sentinel's |
227
+ | `.oxfmtrc.json` `sortImports` false / true / a groups object (nest) | kept, declared in `local`, stamp moves |
228
+ | `.oxfmtrc.json` module `ignorePatterns` | kept, stamp unchanged |
229
+ | every block at once | all kept; a second re-init is a no-op |
230
+ | every block at once, bare `--init` | re-inits lint and format only, all kept |
231
+ | the same from the workspace root, `--module` | the same |
232
+ | fixes 5 and 6 together: tracer imports, a team `sortImports`, a second `extends` | all three kept |
233
+
234
+ Unit (`lint-module-own-config`, `format-adoption`, `extends-preservation`): two module blocks
235
+ with the same `files` merge; a block left with only `files` is not written; a `sortImports`
236
+ equal to what the RECORDED preset sets is sentinel's, so the async-api-types libs corrected from
237
+ base to nest take nest's sort.
238
+
239
+ Negative controls, one per block, each reverting one read-back: plugins 5 cells fail, jsPlugins
240
+ 6, settings 5, overrides 6, extends 5, rules 6, sortImports 7, format `ignorePatterns` 1. Each
241
+ fails its own cells plus the every-block cells, and nothing else.
242
+
243
+ ### 7. an alias of a governed rule is governed (`init-drops-governed-aliases`, unit `lint-governed-aliases`, `lint-rule-name`)
244
+
245
+ Oxlint 1.77.0 runs several names as one rule, and sentinel compared names. Proven first, outside
246
+ sentinel, react preset, a file importing `@nestjs/common` and one importing `lodash`:
247
+
248
+ | stub `rules` beside the preset | what fires |
249
+ | ------------------------------------------------------------------------------------- | ------------------------------ |
250
+ | five unrelated rules (control) | the preset's `@nestjs/*` ban |
251
+ | the same, plus `typescript/no-restricted-imports` with a lodash pattern | the lodash ban only |
252
+ | `typescript/no-restricted-imports` alone | the preset's ban only |
253
+ | `eslint/no-restricted-imports` alone | the lodash ban only, every run |
254
+ | baseline `no-unused-expressions: warn` over nest's `typescript/no-unused-expressions` | still an `error` |
255
+
256
+ The `typescript/` outcome moves with the rest of the rule set because oxlint keeps both names
257
+ through the `extends` merge and picks one by hash order; `eslint/` collapses with the canonical
258
+ name in the merge, where the stub wins. The canonical form is ported from oxc at
259
+ `oxlint_v1.77.0` (`parse_rule_key`, `normalize_plugin_name`, `unalias_plugin_name`,
260
+ `TYPESCRIPT_COMPATIBLE_ESLINT_RULES`), with the bare-name owners taken from `oxlint --rules -f json`.
261
+
262
+ | cell | result |
263
+ | ----------------------------------------------------------------------------------------- | ----------------------------------------------------- |
264
+ | re-init, react, console's rules + `typescript/no-restricted-imports` / `eslint/...` | alias dropped and named, the two team rules kept |
265
+ | the same, then a file importing `@nestjs/common`, `--run --lint` | fails on the preset's ban |
266
+ | control: the canonical `no-restricted-imports` | dropped, message unchanged |
267
+ | nest module violating `no-unused-expressions` at adoption | holds `typescript/no-unused-expressions`, lints green |
268
+ | team layer `no-unused-vars` over nest's `typescript/no-unused-vars`, `--inspect` | rule count unchanged |
269
+ | unit: `@typescript-eslint/`, bare `no-unused-vars`, `react/rules-of-hooks`, an override | dropped (override named with the preset rule) |
270
+ | unit: `typescript/require-await`, `unicorn/no-nested-ternary`, `typescript/no-namespace` | kept: different rules to oxlint too |
271
+ | every governed built-in rule of every preset, in every spelling, through `--print-config` | resolves where sentinel says |
272
+ | a preset rule set naming one rule twice | refused at build |
273
+
274
+ Negative control, `canonicalRuleName` made the identity: 31 of the 48 new cells fail, the 17 that
275
+ pass are the negative ones (the non-aliases, the preset-builds, the owners file, the canonical
276
+ control). With the source fix reverted (`git checkout` of the five files, new files kept), 6 of
277
+ the 7 e2e cells fail, the canonical control passes, and the `--run --lint` cell lints the
278
+ `@nestjs/common` import clean. No existing cell changed.
279
+
280
+ Checked in the monorepo at 7177eb86038: none of the 66 committed `.oxlintrc*.json` files and
281
+ team layers spells a governed rule under another name, so no adopted module carries the gap
282
+ today.
283
+
284
+ ### against the consumer, the 63 adopted modules
285
+
286
+ The packed branch, through a pnpm `file:` override, on a fresh worktree of the monorepo at
287
+ 7177eb86038, nx graph built first, a BARE `--init` in each module:
288
+
289
+ | | result |
290
+ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
291
+ | `--init` exit 0 | 63 of 63 |
292
+ | roles re-inited = roles the alpha was given by name | 63 of 63 |
293
+ | files differing from the alpha's explicit-roles run | 8, all `.oxfmtrc.json` stamps (fix 3) |
294
+ | files differing from the fixes 1 to 4 run | 0 |
295
+ | the ten planning modules' second `extends` | byte for byte |
296
+ | lint / format / typecheck / build | 62 / 59 / 63 / 31, all green |
297
+ | test | 43 projects, 7 red under `--parallel=3`: the 4 environment reds known on origin/main (the `/private` checkout path in 3 jest suites, no Redis for bff-planning), host-admin's French-locale date, and two load reds that are green run alone (bff-worker, a jest worker SIGSEGV; regulation-balance, 15 s timeouts) |
298
+
299
+ Run with `--skip-nx-cache` from the workspace root after every `prisma:gen:*`, career's
300
+ `prepare-runtime-artifacts`, `svelte-kit sync` and `VITE_BRAND_ID=hublo`. Run alone, host-admin
301
+ fails only the locale test (1 806 of 1 807 files).
302
+
303
+ The two PR heads the fixes came from, each in a throwaway worktree, nothing pushed:
304
+ `libs/nest/tracer` at monorepo#23314's head keeps its import order byte for byte, and with the
305
+ pre-adoption `index.ts` restored, the bare `--init` pins it (3 pins) and the format check passes.
306
+ host-admin at monorepo#23342's head now adopts lint with its other roles, which is the rule:
307
+ ESLint is removed, and the guards the react preset does not carry are the team's to add.
308
+
138
309
  ## The static analysis role's validation matrix, 19 October 2026
139
310
 
140
311
  Re-run from scratch because **53 commits landed on the role since 13 October**, and three of them
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hublo/sentinel",
3
- "version": "1.5.1-alpha.0",
3
+ "version": "1.5.1-alpha.2",
4
4
  "description": "One CLI that guards code health across Hublo repos: shared lint/typescript/build/test presets, static & dynamic analysis, and architecture checks.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -12,6 +12,7 @@
12
12
  "engines": {
13
13
  "node": ">=24.15.0"
14
14
  },
15
+ "packageManager": "pnpm@10.26.0",
15
16
  "bin": {
16
17
  "sentinel": "./dist/bin/sentinel.js"
17
18
  },
@@ -107,6 +108,28 @@
107
108
  "oxlint",
108
109
  "plugins"
109
110
  ],
111
+ "scripts": {
112
+ "build": "tsup && tsx scripts/build-presets.ts",
113
+ "dev": "tsup --watch",
114
+ "typecheck": "tsc --noEmit",
115
+ "lint": "node dist/bin/sentinel.js --run --lint && node dist/bin/sentinel.js --run --format",
116
+ "lint:fix": "node dist/bin/sentinel.js --run --lint --fix && node dist/bin/sentinel.js --run --format --fix",
117
+ "format": "node dist/bin/sentinel.js --run --format",
118
+ "test": "vitest run",
119
+ "test:watch": "vitest",
120
+ "test:e2e": "vitest run tests/e2e",
121
+ "test:coverage": "vitest run --coverage --testTimeout=60000",
122
+ "cli": "node --import tsx bin/sentinel.ts",
123
+ "docs:traces": "pnpm build && bash scripts/gen-traces.sh",
124
+ "docs:traces:check": "pnpm build && bash scripts/gen-traces.sh --check",
125
+ "format:fix": "node dist/bin/sentinel.js --run --format --fix",
126
+ "bench": "node scripts/bench.mjs",
127
+ "deps:trust": "tsx scripts/check-trust-policy.ts",
128
+ "prepack": "tsx scripts/prune-sourcemaps.ts",
129
+ "static-analysis": "sentinel --run --static-analysis",
130
+ "static-analysis:json": "sentinel --run --static-analysis --output json",
131
+ "static-analysis:html": "sentinel --run --static-analysis --output html"
132
+ },
110
133
  "dependencies": {
111
134
  "@nx/eslint-plugin": "23.0.1",
112
135
  "@tailwindcss/vite": "4.1.18",
@@ -155,6 +178,11 @@
155
178
  "tsup": "^8.3.0",
156
179
  "tsx": "^4.19.0"
157
180
  },
181
+ "pnpm": {
182
+ "onlyBuiltDependencies": [
183
+ "esbuild"
184
+ ]
185
+ },
158
186
  "publishConfig": {
159
187
  "registry": "https://registry.npmjs.org",
160
188
  "access": "public"
@@ -191,26 +219,5 @@
191
219
  "nx": {
192
220
  "optional": true
193
221
  }
194
- },
195
- "scripts": {
196
- "build": "tsup && tsx scripts/build-presets.ts",
197
- "dev": "tsup --watch",
198
- "typecheck": "tsc --noEmit",
199
- "lint": "node dist/bin/sentinel.js --run --lint && node dist/bin/sentinel.js --run --format",
200
- "lint:fix": "node dist/bin/sentinel.js --run --lint --fix && node dist/bin/sentinel.js --run --format --fix",
201
- "format": "node dist/bin/sentinel.js --run --format",
202
- "test": "vitest run",
203
- "test:watch": "vitest",
204
- "test:e2e": "vitest run tests/e2e",
205
- "test:coverage": "vitest run --coverage --testTimeout=60000",
206
- "cli": "node --import tsx bin/sentinel.ts",
207
- "docs:traces": "pnpm build && bash scripts/gen-traces.sh",
208
- "docs:traces:check": "pnpm build && bash scripts/gen-traces.sh --check",
209
- "format:fix": "node dist/bin/sentinel.js --run --format --fix",
210
- "bench": "node scripts/bench.mjs",
211
- "deps:trust": "tsx scripts/check-trust-policy.ts",
212
- "static-analysis": "sentinel --run --static-analysis",
213
- "static-analysis:json": "sentinel --run --static-analysis --output json",
214
- "static-analysis:html": "sentinel --run --static-analysis --output html"
215
222
  }
216
- }
223
+ }