@eduardbar/drift 1.2.0 → 1.4.0
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/.gga +50 -0
- package/.github/actions/drift-review/README.md +60 -0
- package/.github/actions/drift-review/action.yml +131 -0
- package/.github/actions/drift-scan/README.md +28 -32
- package/.github/actions/drift-scan/action.yml +78 -14
- package/.github/workflows/publish-vscode.yml +3 -3
- package/.github/workflows/publish.yml +3 -3
- package/.github/workflows/review-pr.yml +94 -9
- package/AGENTS.md +75 -245
- package/CHANGELOG.md +28 -0
- package/README.md +308 -51
- package/ROADMAP.md +6 -5
- package/dist/analyzer.d.ts +2 -2
- package/dist/analyzer.js +420 -159
- package/dist/benchmark.d.ts +2 -0
- package/dist/benchmark.js +204 -0
- package/dist/cli.js +693 -67
- package/dist/config.js +16 -2
- package/dist/diff.js +66 -10
- package/dist/doctor.d.ts +5 -0
- package/dist/doctor.js +133 -0
- package/dist/format.d.ts +17 -0
- package/dist/format.js +45 -0
- package/dist/git.js +12 -0
- package/dist/guard-types.d.ts +57 -0
- package/dist/guard-types.js +2 -0
- package/dist/guard.d.ts +14 -0
- package/dist/guard.js +239 -0
- package/dist/index.d.ts +12 -3
- package/dist/index.js +6 -1
- package/dist/init.d.ts +15 -0
- package/dist/init.js +273 -0
- package/dist/map-cycles.d.ts +2 -0
- package/dist/map-cycles.js +34 -0
- package/dist/map-svg.d.ts +19 -0
- package/dist/map-svg.js +97 -0
- package/dist/map.js +78 -138
- package/dist/metrics.js +70 -55
- package/dist/output-metadata.d.ts +13 -0
- package/dist/output-metadata.js +17 -0
- package/dist/plugins-capabilities.d.ts +4 -0
- package/dist/plugins-capabilities.js +21 -0
- package/dist/plugins-messages.d.ts +10 -0
- package/dist/plugins-messages.js +16 -0
- package/dist/plugins-rules.d.ts +9 -0
- package/dist/plugins-rules.js +137 -0
- package/dist/plugins.d.ts +2 -1
- package/dist/plugins.js +80 -28
- package/dist/printer.js +4 -0
- package/dist/reporter-constants.d.ts +16 -0
- package/dist/reporter-constants.js +39 -0
- package/dist/reporter.d.ts +3 -3
- package/dist/reporter.js +35 -55
- package/dist/review.d.ts +2 -1
- package/dist/review.js +4 -3
- package/dist/rules/comments.js +2 -2
- package/dist/rules/complexity.js +2 -7
- package/dist/rules/nesting.js +3 -13
- package/dist/rules/phase0-basic.js +10 -10
- package/dist/rules/phase3-configurable.js +23 -15
- package/dist/rules/shared.d.ts +2 -0
- package/dist/rules/shared.js +27 -3
- package/dist/saas/constants.d.ts +15 -0
- package/dist/saas/constants.js +48 -0
- package/dist/saas/dashboard.d.ts +8 -0
- package/dist/saas/dashboard.js +132 -0
- package/dist/saas/errors.d.ts +19 -0
- package/dist/saas/errors.js +37 -0
- package/dist/saas/helpers.d.ts +21 -0
- package/dist/saas/helpers.js +110 -0
- package/dist/saas/ingest.d.ts +3 -0
- package/dist/saas/ingest.js +249 -0
- package/dist/saas/organization.d.ts +5 -0
- package/dist/saas/organization.js +82 -0
- package/dist/saas/plan-change.d.ts +10 -0
- package/dist/saas/plan-change.js +15 -0
- package/dist/saas/store.d.ts +21 -0
- package/dist/saas/store.js +159 -0
- package/dist/saas/types.d.ts +191 -0
- package/dist/saas/types.js +2 -0
- package/dist/saas.d.ts +8 -82
- package/dist/saas.js +7 -320
- package/dist/sarif.d.ts +74 -0
- package/dist/sarif.js +122 -0
- package/dist/trust-advanced.d.ts +14 -0
- package/dist/trust-advanced.js +65 -0
- package/dist/trust-kpi-fs.d.ts +3 -0
- package/dist/trust-kpi-fs.js +141 -0
- package/dist/trust-kpi-parse.d.ts +7 -0
- package/dist/trust-kpi-parse.js +186 -0
- package/dist/trust-kpi-types.d.ts +16 -0
- package/dist/trust-kpi-types.js +2 -0
- package/dist/trust-kpi.d.ts +7 -0
- package/dist/trust-kpi.js +185 -0
- package/dist/trust-policy.d.ts +32 -0
- package/dist/trust-policy.js +160 -0
- package/dist/trust-render.d.ts +9 -0
- package/dist/trust-render.js +54 -0
- package/dist/trust-scoring.d.ts +9 -0
- package/dist/trust-scoring.js +208 -0
- package/dist/trust.d.ts +37 -0
- package/dist/trust.js +168 -0
- package/dist/types/app.d.ts +30 -0
- package/dist/types/app.js +2 -0
- package/dist/types/config.d.ts +25 -0
- package/dist/types/config.js +2 -0
- package/dist/types/core.d.ts +100 -0
- package/dist/types/core.js +2 -0
- package/dist/types/diff.d.ts +55 -0
- package/dist/types/diff.js +2 -0
- package/dist/types/plugin.d.ts +41 -0
- package/dist/types/plugin.js +2 -0
- package/dist/types/trust.d.ts +120 -0
- package/dist/types/trust.js +2 -0
- package/dist/types.d.ts +8 -211
- package/docs/PRD.md +187 -109
- package/docs/plugin-contract.md +61 -0
- package/docs/release-notes-draft.md +40 -0
- package/docs/rules-catalog.md +49 -0
- package/docs/trust-core-release-checklist.md +87 -0
- package/package.json +6 -3
- package/packages/vscode-drift/src/code-actions.ts +1 -1
- package/schemas/drift-ai-output.v1.json +162 -0
- package/schemas/drift-report.v1.json +151 -0
- package/schemas/drift-trust.v1.json +131 -0
- package/scripts/smoke-repo.mjs +394 -0
- package/src/analyzer.ts +484 -155
- package/src/benchmark.ts +266 -0
- package/src/cli.ts +840 -85
- package/src/config.ts +19 -2
- package/src/diff.ts +84 -10
- package/src/doctor.ts +173 -0
- package/src/format.ts +81 -0
- package/src/git.ts +16 -0
- package/src/guard-types.ts +64 -0
- package/src/guard.ts +324 -0
- package/src/index.ts +83 -0
- package/src/init.ts +298 -0
- package/src/map-cycles.ts +38 -0
- package/src/map-svg.ts +124 -0
- package/src/map.ts +111 -142
- package/src/metrics.ts +78 -59
- package/src/output-metadata.ts +30 -0
- package/src/plugins-capabilities.ts +36 -0
- package/src/plugins-messages.ts +35 -0
- package/src/plugins-rules.ts +296 -0
- package/src/plugins.ts +148 -27
- package/src/printer.ts +4 -0
- package/src/reporter-constants.ts +46 -0
- package/src/reporter.ts +64 -65
- package/src/review.ts +6 -4
- package/src/rules/comments.ts +2 -2
- package/src/rules/complexity.ts +2 -7
- package/src/rules/nesting.ts +3 -13
- package/src/rules/phase0-basic.ts +11 -12
- package/src/rules/phase3-configurable.ts +39 -26
- package/src/rules/shared.ts +31 -3
- package/src/saas/constants.ts +56 -0
- package/src/saas/dashboard.ts +172 -0
- package/src/saas/errors.ts +45 -0
- package/src/saas/helpers.ts +140 -0
- package/src/saas/ingest.ts +278 -0
- package/src/saas/organization.ts +99 -0
- package/src/saas/plan-change.ts +19 -0
- package/src/saas/store.ts +172 -0
- package/src/saas/types.ts +216 -0
- package/src/saas.ts +49 -433
- package/src/sarif.ts +232 -0
- package/src/trust-advanced.ts +99 -0
- package/src/trust-kpi-fs.ts +169 -0
- package/src/trust-kpi-parse.ts +219 -0
- package/src/trust-kpi-types.ts +19 -0
- package/src/trust-kpi.ts +210 -0
- package/src/trust-policy.ts +246 -0
- package/src/trust-render.ts +61 -0
- package/src/trust-scoring.ts +231 -0
- package/src/trust.ts +260 -0
- package/src/types/app.ts +30 -0
- package/src/types/config.ts +27 -0
- package/src/types/core.ts +105 -0
- package/src/types/diff.ts +61 -0
- package/src/types/plugin.ts +46 -0
- package/src/types/trust.ts +134 -0
- package/src/types.ts +78 -238
- package/tests/cli-sarif.test.ts +92 -0
- package/tests/diff.test.ts +124 -0
- package/tests/format.test.ts +157 -0
- package/tests/new-features.test.ts +80 -1
- package/tests/phase1-init-doctor-guard.test.ts +199 -0
- package/tests/plugins.test.ts +219 -0
- package/tests/rules.test.ts +23 -1
- package/tests/saas-foundation.test.ts +358 -1
- package/tests/sarif.test.ts +160 -0
- package/tests/trust-kpi.test.ts +147 -0
- package/tests/trust.test.ts +602 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
3
|
# drift
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
AI Code Audit CLI for AI-assisted PRs. Drift turns static signals into merge trust decisions before you merge.
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|

|
|
@@ -20,7 +20,7 @@ AI coding tools ship code fast. They also leave behind consistent, predictable s
|
|
|
20
20
|
|
|
21
21
|
GitClear's 2024 analysis of 211M lines of code found a **39.9% drop in refactoring activity** and an **8x increase in duplicated code blocks** since AI tools became mainstream. A senior engineer on r/vibecoding put it plainly: _"The code looks reviewed. It isn't. Nobody's reading 400-line files the AI dumped in one shot."_
|
|
22
22
|
|
|
23
|
-
drift gives you
|
|
23
|
+
drift gives you debt signals (`scan`, `review`) and a trust decision layer (`trust`) so teams can merge with confidence instead of guesswork.
|
|
24
24
|
|
|
25
25
|
**How drift compares to existing tools:**
|
|
26
26
|
|
|
@@ -50,12 +50,62 @@ npm install --save-dev @eduardbar/drift
|
|
|
50
50
|
## Product Docs
|
|
51
51
|
|
|
52
52
|
- Product requirements and roadmap: [`docs/PRD.md`](./docs/PRD.md)
|
|
53
|
+
- Trust core release checklist: [`docs/trust-core-release-checklist.md`](./docs/trust-core-release-checklist.md)
|
|
54
|
+
- Rules catalog (source-of-truth snapshot): [`docs/rules-catalog.md`](./docs/rules-catalog.md)
|
|
53
55
|
- Contributor/agent workflow guide: [`docs/AGENTS.md`](./docs/AGENTS.md)
|
|
54
56
|
|
|
55
57
|
---
|
|
56
58
|
|
|
57
59
|
## Commands
|
|
58
60
|
|
|
61
|
+
### `drift init`
|
|
62
|
+
|
|
63
|
+
Scaffold first-run setup for drift in an existing repository.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
drift init
|
|
67
|
+
drift init --preset node-backend
|
|
68
|
+
drift init --preset react-app --ci --baseline
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
| Flag | Description |
|
|
72
|
+
|------|-------------|
|
|
73
|
+
| `--preset <type>` | Generate `drift.config.ts` using one of: `node-backend`, `react-app`, `hexagonal`, `monorepo` |
|
|
74
|
+
| `--ci` | Generate `.github/workflows/drift-review.yml` |
|
|
75
|
+
| `--baseline` | Generate `drift-baseline.json` from the current scan |
|
|
76
|
+
|
|
77
|
+
`drift init` is non-destructive for pre-existing targets: drift skips generation when an output file already exists and prints a warning.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### `drift doctor`
|
|
82
|
+
|
|
83
|
+
Run environment diagnostics for Node/runtime and project readiness.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
drift doctor
|
|
87
|
+
drift doctor --json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| Flag | Description |
|
|
91
|
+
|------|-------------|
|
|
92
|
+
| `--json` | Output structured doctor report JSON |
|
|
93
|
+
|
|
94
|
+
Checks include Node major version support (`>=18`), `package.json`, ESM mode, `tsconfig.json`, source file count, optional `--low-memory` recommendation, and `drift.config.*` detection.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### Repository smoke (local source CLI)
|
|
99
|
+
|
|
100
|
+
Run a non-destructive end-to-end smoke suite against any repository path using local source commands (`node --import tsx ./src/cli.ts ...`).
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm run smoke:repo -- ../target-repo --base origin/main
|
|
104
|
+
npm run smoke:repo -- ../target-repo --dry-run
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The script writes JSON + Markdown summaries and command logs under `.drift-smoke/<repo>-<timestamp>/`.
|
|
108
|
+
|
|
59
109
|
### `drift scan [path]`
|
|
60
110
|
|
|
61
111
|
Scan a directory and print a scored report to stdout.
|
|
@@ -68,6 +118,7 @@ drift scan ./src --json
|
|
|
68
118
|
drift scan ./src --ai
|
|
69
119
|
drift scan ./src --fix
|
|
70
120
|
drift scan ./src --min-score 50
|
|
121
|
+
drift scan ./src --low-memory --max-file-size-kb 1024
|
|
71
122
|
```
|
|
72
123
|
|
|
73
124
|
**Options:**
|
|
@@ -75,10 +126,18 @@ drift scan ./src --min-score 50
|
|
|
75
126
|
| Flag | Description |
|
|
76
127
|
|------|-------------|
|
|
77
128
|
| `--output <file>` | Write Markdown report to a file instead of stdout |
|
|
129
|
+
| `--format <type>` | Output format: `console\|json\|markdown\|ai\|sarif` |
|
|
78
130
|
| `--json` | Output raw `DriftReport` JSON |
|
|
79
131
|
| `--ai` | Output structured JSON optimized for LLM consumption (Claude, GPT, etc.) |
|
|
80
132
|
| `--fix` | Print inline fix suggestions for each detected issue |
|
|
81
|
-
| `--min-score <n>` | Exit with code 1 if the overall score
|
|
133
|
+
| `--min-score <n>` | Exit with code 1 if the overall score strictly exceeds this threshold |
|
|
134
|
+
| `--low-memory` | Analyze files in bounded chunks to reduce peak RAM |
|
|
135
|
+
| `--chunk-size <n>` | Files per chunk in low-memory mode (default: 40) |
|
|
136
|
+
| `--max-files <n>` | Soft cap on analyzed files; extra files are skipped with diagnostics |
|
|
137
|
+
| `--max-file-size-kb <n>` | Skip oversized files with diagnostics to avoid OOM |
|
|
138
|
+
| `--with-semantic-duplication` | Keep semantic duplication rule enabled in low-memory mode |
|
|
139
|
+
|
|
140
|
+
`--min-score` currently fails when `totalScore > n` (strictly greater than), matching CLI behavior.
|
|
82
141
|
|
|
83
142
|
**Example output:**
|
|
84
143
|
|
|
@@ -106,6 +165,33 @@ drift scan ./src --min-score 50
|
|
|
106
165
|
|
|
107
166
|
---
|
|
108
167
|
|
|
168
|
+
### `drift guard [path]`
|
|
169
|
+
|
|
170
|
+
Evaluate drift regression guardrails against a git diff (`--base`) or a baseline file/object.
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
drift guard ./src --base origin/main
|
|
174
|
+
drift guard ./src --baseline drift-baseline.json
|
|
175
|
+
drift guard ./src --base origin/main --budget 3 --by-severity error=0,warning=2,info=5
|
|
176
|
+
drift guard ./src --base origin/main --json
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
| Flag | Description |
|
|
180
|
+
|------|-------------|
|
|
181
|
+
| `--base <ref>` | Diff mode: compare current state vs git ref |
|
|
182
|
+
| `--baseline <file>` | Baseline mode: compare against baseline JSON (default file name: `drift-baseline.json`) |
|
|
183
|
+
| `--budget <n>` | Maximum allowed score delta |
|
|
184
|
+
| `--by-severity <spec>` | Severity thresholds as CSV `key=value` pairs (`error`, `warning`, `info`) |
|
|
185
|
+
| `--json` | Output full `GuardResult` JSON |
|
|
186
|
+
| `--low-memory` / `--chunk-size <n>` / `--max-files <n>` / `--max-file-size-kb <n>` / `--with-semantic-duplication` | Analysis resource controls shared with scan/diff/report/badge/ci/trust |
|
|
187
|
+
|
|
188
|
+
Behavior:
|
|
189
|
+
- With `--base`, guard enforces no-regression checks for score and total issues, then applies optional budget/severity thresholds.
|
|
190
|
+
- Without `--base`, guard requires a baseline (inline or file) and compares only against available baseline anchors.
|
|
191
|
+
- Exit code is `1` when any guard check fails.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
109
195
|
### `drift diff [ref]`
|
|
110
196
|
|
|
111
197
|
Compare the current project state against any git ref. Defaults to `HEAD~1`.
|
|
@@ -115,6 +201,7 @@ drift diff # HEAD vs HEAD~1
|
|
|
115
201
|
drift diff HEAD~3 # HEAD vs 3 commits ago
|
|
116
202
|
drift diff main # HEAD vs branch main
|
|
117
203
|
drift diff abc1234 # HEAD vs a specific commit
|
|
204
|
+
drift diff --format sarif # Output SARIF for code scanning
|
|
118
205
|
drift diff --json # Output raw JSON diff
|
|
119
206
|
```
|
|
120
207
|
|
|
@@ -122,6 +209,7 @@ drift diff --json # Output raw JSON diff
|
|
|
122
209
|
|
|
123
210
|
| Flag | Description |
|
|
124
211
|
|------|-------------|
|
|
212
|
+
| `--format <type>` | Output format: `console\|json\|sarif` |
|
|
125
213
|
| `--json` | Output raw JSON diff |
|
|
126
214
|
|
|
127
215
|
Shows score delta, issues introduced, and issues resolved since the given ref.
|
|
@@ -136,16 +224,105 @@ Review drift against a git base ref and output a PR-ready markdown comment.
|
|
|
136
224
|
drift review --base origin/main
|
|
137
225
|
drift review --base main --comment
|
|
138
226
|
drift review --base HEAD~3 --json
|
|
227
|
+
drift review --base origin/main --format sarif
|
|
139
228
|
drift review --base origin/main --fail-on 5
|
|
140
229
|
```
|
|
141
230
|
|
|
142
231
|
| Flag | Description |
|
|
143
232
|
|------|-------------|
|
|
144
233
|
| `--base <ref>` | Git base ref to compare against (default: `origin/main`) |
|
|
234
|
+
| `--format <type>` | Output format: `console\|json\|markdown\|sarif` |
|
|
145
235
|
| `--json` | Output structured review JSON |
|
|
146
236
|
| `--comment` | Print only the markdown body for PR comments |
|
|
147
237
|
| `--fail-on <n>` | Exit code 1 when score delta is greater than or equal to `n` |
|
|
148
238
|
|
|
239
|
+
`drift review` is best used as supplementary diff context alongside `drift trust` in pull-request workflows.
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
### `drift trust [path]`
|
|
244
|
+
|
|
245
|
+
Compute merge trust baseline for local checks and CI merge gates.
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
drift trust
|
|
249
|
+
drift trust ./src
|
|
250
|
+
drift trust ./src --json
|
|
251
|
+
drift trust ./src --base origin/main
|
|
252
|
+
drift trust ./src --base origin/main --markdown
|
|
253
|
+
drift trust ./src --format sarif
|
|
254
|
+
drift trust ./src --markdown --output trust.md
|
|
255
|
+
drift trust ./src --min-trust 45
|
|
256
|
+
drift trust ./src --max-risk HIGH
|
|
257
|
+
drift trust ./src --branch main
|
|
258
|
+
drift trust ./src --branch release/v1.4.0 --policy-pack strict --explain-policy
|
|
259
|
+
drift trust ./src --advanced-trust
|
|
260
|
+
drift trust ./src --advanced-trust --previous-trust ./artifacts/prev-trust.json
|
|
261
|
+
drift trust ./src --advanced-trust --history-file ./drift-history.json --markdown
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
| Flag | Description |
|
|
265
|
+
|------|-------------|
|
|
266
|
+
| `--base <ref>` | Compare against a git base ref and include deterministic diff-aware penalties/bonuses |
|
|
267
|
+
| `--format <type>` | Output format: `console\|json\|markdown\|sarif` |
|
|
268
|
+
| `--json` | Output structured trust JSON (`trust_score`, `merge_risk`, `top_reasons`, `fix_priorities`, optional `diff_context`) |
|
|
269
|
+
| `--markdown` | Output PR-ready markdown trust summary |
|
|
270
|
+
| `--output <file>` | Write selected trust output format to file |
|
|
271
|
+
| `--min-trust <n>` | Exit code 1 when trust score is below `n` |
|
|
272
|
+
| `--max-risk <level>` | Exit code 1 when computed merge risk exceeds `LOW`, `MEDIUM`, `HIGH`, or `CRITICAL` |
|
|
273
|
+
| `--branch <name>` | Branch used for `drift.config` trust policy matching (falls back to CI env vars) |
|
|
274
|
+
| `--policy-pack <name>` | Optional trust policy pack from `trustGate.policyPacks` in `drift.config.*` |
|
|
275
|
+
| `--explain-policy` | Print base/pack/branch/override resolution and effective gate policy to stderr |
|
|
276
|
+
| `--advanced-trust` | Enable optional advanced trust layer (historical comparison + team guidance metadata) |
|
|
277
|
+
| `--previous-trust <file>` | Compare current trust against a prior trust JSON file in advanced mode |
|
|
278
|
+
| `--history-file <file>` | Use a specific `drift-history.json` file for advanced historical fallback |
|
|
279
|
+
|
|
280
|
+
When `trustGate` policy is configured in `drift.config.*`, branch-based thresholds are applied automatically. CLI flags still override policy values.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
### `drift trust-gate <trust-json-file>`
|
|
285
|
+
|
|
286
|
+
Evaluate trust gate thresholds from a previously generated trust JSON file. This is ideal for CI workflows that already produced `drift-trust.json` and want a single source of truth for gate logic.
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
drift trust-gate drift-trust.json --min-trust 45 --max-risk HIGH
|
|
290
|
+
drift trust-gate drift-trust.json --branch release/v1.2.0
|
|
291
|
+
drift trust-gate drift-trust.json --branch main --policy-pack balanced --explain-policy
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
| Flag | Description |
|
|
295
|
+
|------|-------------|
|
|
296
|
+
| `--min-trust <n>` | Exit code 1 when trust score in JSON is below `n` |
|
|
297
|
+
| `--max-risk <level>` | Exit code 1 when merge risk in JSON exceeds `LOW`, `MEDIUM`, `HIGH`, or `CRITICAL` |
|
|
298
|
+
| `--branch <name>` | Branch used for `drift.config` trust policy matching (falls back to CI env vars) |
|
|
299
|
+
| `--policy-pack <name>` | Optional trust policy pack from `trustGate.policyPacks` in `drift.config.*` |
|
|
300
|
+
| `--explain-policy` | Print base/pack/branch/override resolution and effective gate policy to stderr |
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
### `drift kpi <path>`
|
|
305
|
+
|
|
306
|
+
Aggregate trust KPI evidence from local artifacts (directory or glob). Prints a compact console summary to stderr and structured KPI JSON to stdout.
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
drift kpi ./artifacts/trust
|
|
310
|
+
drift kpi "./artifacts/**/drift-trust-*.json"
|
|
311
|
+
drift kpi ./artifacts/trust --no-summary
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
| Flag | Description |
|
|
315
|
+
|------|-------------|
|
|
316
|
+
| `--no-summary` | Disable stderr console summary and output JSON only |
|
|
317
|
+
|
|
318
|
+
Computed KPI fields include:
|
|
319
|
+
- PRs evaluated count
|
|
320
|
+
- Merge risk distribution (`LOW`, `MEDIUM`, `HIGH`, `CRITICAL`)
|
|
321
|
+
- Trust score average/median/min/max
|
|
322
|
+
- High-risk ratio (`HIGH` + `CRITICAL`)
|
|
323
|
+
- Diff trend aggregates when `diff_context` exists (`scoreDelta`, new/resolved issues, status distribution)
|
|
324
|
+
- Diagnostics for malformed/missing/invalid JSON artifacts
|
|
325
|
+
|
|
149
326
|
---
|
|
150
327
|
|
|
151
328
|
### `drift map [path]`
|
|
@@ -216,6 +393,7 @@ Emit GitHub Actions annotations and a step summary. Designed to run inside a CI
|
|
|
216
393
|
```bash
|
|
217
394
|
drift ci # scan current directory
|
|
218
395
|
drift ci ./src
|
|
396
|
+
drift ci ./src --format sarif
|
|
219
397
|
drift ci ./src --min-score 60
|
|
220
398
|
```
|
|
221
399
|
|
|
@@ -223,7 +401,8 @@ drift ci ./src --min-score 60
|
|
|
223
401
|
|
|
224
402
|
| Flag | Description |
|
|
225
403
|
|------|-------------|
|
|
226
|
-
| `--
|
|
404
|
+
| `--format <type>` | Output format: `console\|json\|sarif` |
|
|
405
|
+
| `--min-score <n>` | Exit with code 1 if the overall score strictly exceeds this threshold |
|
|
227
406
|
|
|
228
407
|
Outputs `::error` and `::warning` annotations visible in the PR diff. Writes a markdown summary to `$GITHUB_STEP_SUMMARY`.
|
|
229
408
|
|
|
@@ -290,11 +469,18 @@ drift fix ./src --dry-run # alias of --preview
|
|
|
290
469
|
|
|
291
470
|
### `drift cloud`
|
|
292
471
|
|
|
293
|
-
Local
|
|
472
|
+
Local multi-tenant foundations backed by `.drift-cloud/store.json`.
|
|
294
473
|
|
|
295
474
|
```bash
|
|
296
|
-
drift cloud ingest ./src --
|
|
475
|
+
drift cloud ingest ./src --org acme --workspace core --user u-123 --role owner --plan sponsor --repo webapp
|
|
297
476
|
drift cloud summary
|
|
477
|
+
drift cloud summary --org acme --workspace core
|
|
478
|
+
drift cloud summary --org acme --workspace core --actor u-owner
|
|
479
|
+
drift cloud ingest ./src --org acme --workspace core --user u-member --actor u-owner
|
|
480
|
+
drift cloud ingest ./src --org acme --workspace core --user u-member --actor u-member # strict actor mode ready
|
|
481
|
+
drift cloud plan-set --org acme --plan team --actor u-owner --reason "annual upgrade"
|
|
482
|
+
drift cloud plan-changes --org acme --actor u-owner
|
|
483
|
+
drift cloud usage --org acme --actor u-owner
|
|
298
484
|
drift cloud summary --json
|
|
299
485
|
drift cloud dashboard --output drift-cloud-dashboard.html
|
|
300
486
|
```
|
|
@@ -303,46 +489,53 @@ drift cloud dashboard --output drift-cloud-dashboard.html
|
|
|
303
489
|
|
|
304
490
|
| Command | Description |
|
|
305
491
|
|---------|-------------|
|
|
306
|
-
| `drift cloud ingest [path] --workspace <id> --user <id> [--repo <name>] [--store <file>]` | Scans the path and stores one
|
|
307
|
-
| `drift cloud summary [--json] [--store <file>]` | Shows users/workspaces/repos usage and runs per month |
|
|
492
|
+
| `drift cloud ingest [path] --org <id> --workspace <id> --user <id> [--role <owner\|member\|viewer>] [--plan <free\|sponsor\|team\|business>] [--repo <name>] [--actor <user>] [--store <file>]` | Scans the path and stores one tenant-scoped snapshot (`--actor` optional by default, required only when `saas.strictActorEnforcement=true`) |
|
|
493
|
+
| `drift cloud summary [--json] [--org <id>] [--workspace <id>] [--actor <user>] [--store <file>]` | Shows users/workspaces/repos usage and runs per month; in strict mode, scoped reads (`--org`/`--workspace`) require `--actor` |
|
|
494
|
+
| `drift cloud plan-set --org <id> --plan <free\|sponsor\|team\|business> --actor <user> [--reason <text>] [--store <file>]` | Updates organization plan and writes an audited plan-change event (owner-gated by actor) |
|
|
495
|
+
| `drift cloud plan-changes --org <id> --actor <user> [--json] [--store <file>]` | Lists audited plan lifecycle events for the organization |
|
|
496
|
+
| `drift cloud usage --org <id> --actor <user> [--month <yyyy-mm>] [--json] [--store <file>]` | Shows organization usage plus effective limits for current plan |
|
|
308
497
|
| `drift cloud dashboard [--output <file>] [--store <file>]` | Generates an HTML dashboard with trends and hotspots |
|
|
309
498
|
|
|
310
|
-
`drift cloud` ships with
|
|
499
|
+
`drift cloud` ships with tenant identity boundaries (`organizationId` + `workspaceId`), role primitives (`owner`/`member`/`viewer`), and plan placeholders (`free`/`sponsor`/`team`/`business`). It is an infrastructure foundation, not a full auth/billing platform.
|
|
500
|
+
|
|
501
|
+
By default, local guardrails enforce one plan-based limit: max workspaces per organization (`free:20`, `sponsor:50`, `team:200`, `business:1000`), plus existing free-phase limits (runs per workspace, repos per workspace, retention window).
|
|
502
|
+
|
|
503
|
+
To require actor identity on scoped cloud operations, enable strict actor mode in `drift.config.*`:
|
|
504
|
+
|
|
505
|
+
```ts
|
|
506
|
+
export default {
|
|
507
|
+
saas: {
|
|
508
|
+
strictActorEnforcement: true,
|
|
509
|
+
},
|
|
510
|
+
}
|
|
511
|
+
```
|
|
311
512
|
|
|
312
513
|
---
|
|
313
514
|
|
|
314
515
|
## Rules
|
|
315
516
|
|
|
316
|
-
|
|
517
|
+
drift currently defines **35 rule IDs** in `RULE_WEIGHTS` (`src/analyzer.ts`): core detections, configurable architecture checks, AI/meta aggregation, plugin diagnostics, and analysis guardrail diagnostics.
|
|
518
|
+
|
|
519
|
+
For the complete up-to-date catalog (id, severity, weight, phase/origin, note), see [`docs/rules-catalog.md`](./docs/rules-catalog.md).
|
|
520
|
+
|
|
521
|
+
Highlights:
|
|
317
522
|
|
|
318
523
|
| Rule | Severity | Weight | What it detects |
|
|
319
524
|
|------|----------|--------|-----------------|
|
|
320
|
-
| `large-file` | error | 20 | Files exceeding 300 lines
|
|
321
|
-
| `
|
|
322
|
-
| `
|
|
323
|
-
| `
|
|
324
|
-
| `
|
|
325
|
-
| `
|
|
326
|
-
| `
|
|
327
|
-
| `
|
|
328
|
-
| `
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
331
|
-
| `
|
|
332
|
-
| `
|
|
333
|
-
| `
|
|
334
|
-
| `promise-style-mix` | warning | 7 | `async/await` and `.then()` / `.catch()` used together in the same file — AI combines styles inconsistently |
|
|
335
|
-
| `unused-export` | warning | 8 | Named exports that are never imported anywhere in the project — cross-file dead code ESLint cannot detect |
|
|
336
|
-
| `dead-file` | warning | 10 | Files never imported by any other file in the project — invisible dead code |
|
|
337
|
-
| `unused-dependency` | warning | 6 | Packages listed in `package.json` with no corresponding import in source files |
|
|
338
|
-
| `cross-boundary-import` | warning | 10 | Imports that cross module boundaries outside the allowed list — requires `drift.config.ts` |
|
|
339
|
-
| `hardcoded-config` | warning | 10 | Hardcoded URLs, IP addresses, secrets, or connection strings — AI skips environment variable abstraction |
|
|
340
|
-
| `inconsistent-error-handling` | warning | 8 | Mixed `try/catch` and `.catch()` patterns in the same file — AI combines approaches without a consistent strategy |
|
|
341
|
-
| `unnecessary-abstraction` | warning | 7 | Wrapper functions or helpers that add no logic over what they wrap — AI over-engineers simple calls |
|
|
342
|
-
| `naming-inconsistency` | warning | 6 | Mixed `camelCase` and `snake_case` in the same module — AI forgets project conventions mid-generation |
|
|
343
|
-
| `semantic-duplication` | warning | 12 | Functions with structurally identical logic despite different names — detected via AST fingerprinting, not text comparison |
|
|
344
|
-
| `no-return-type` | info | 5 | Functions missing an explicit return type annotation |
|
|
345
|
-
| `magic-number` | info | 3 | Numeric literals used directly in logic without a named constant |
|
|
525
|
+
| `large-file` | error | 20 | Files exceeding 300 lines |
|
|
526
|
+
| `duplicate-function-name` | error | 18 | Same function name repeated across a file |
|
|
527
|
+
| `high-complexity` | error | 15 | Cyclomatic complexity above threshold |
|
|
528
|
+
| `layer-violation` | error | 16 | Invalid layer import direction (requires `layers` config) |
|
|
529
|
+
| `cross-boundary-import` | warning | 10 | Invalid module boundary import (requires `modules`/legacy boundaries config) |
|
|
530
|
+
| `controller-no-db` | warning | 11 | Controller touching DB directly (configurable architecture rule) |
|
|
531
|
+
| `service-no-http` | warning | 11 | Service layer coupled to HTTP concerns (configurable architecture rule) |
|
|
532
|
+
| `max-function-lines` | warning | 9 | Function line cap enforced by `architectureRules.maxFunctionLines` |
|
|
533
|
+
| `semantic-duplication` | warning | 12 | AST-level semantic function duplication |
|
|
534
|
+
| `ai-code-smell` | warning | 12 | Aggregated AI-smell signal from multiple heuristics in a file |
|
|
535
|
+
| `plugin-error` | warning | 4 | Plugin load/contract/runtime failure surfaced as issue |
|
|
536
|
+
| `plugin-warning` | info | 0 | Non-fatal plugin validation warning |
|
|
537
|
+
| `analysis-skip-max-files` | info | 0 | File skipped by `maxFiles` guardrail |
|
|
538
|
+
| `analysis-skip-file-size` | info | 0 | File skipped by `maxFileSizeKb` guardrail |
|
|
346
539
|
|
|
347
540
|
---
|
|
348
541
|
|
|
@@ -362,39 +555,63 @@ drift cloud dashboard --output drift-cloud-dashboard.html
|
|
|
362
555
|
|
|
363
556
|
## Configuration
|
|
364
557
|
|
|
365
|
-
drift runs with zero configuration. Architectural rules (`layer-violation`, `cross-boundary-import`)
|
|
558
|
+
drift runs with zero configuration. Architectural rules (`layer-violation`, `cross-boundary-import`) and configurable architecture checks use `drift.config.ts` (or `.js` / `.json`) at project root:
|
|
366
559
|
|
|
367
560
|
```typescript
|
|
368
561
|
import type { DriftConfig } from '@eduardbar/drift'
|
|
369
562
|
|
|
370
563
|
export default {
|
|
371
564
|
plugins: ['drift-plugin-example'],
|
|
565
|
+
performance: {
|
|
566
|
+
lowMemory: true,
|
|
567
|
+
chunkSize: 40,
|
|
568
|
+
maxFiles: 8000,
|
|
569
|
+
maxFileSizeKb: 1024,
|
|
570
|
+
includeSemanticDuplication: false,
|
|
571
|
+
},
|
|
372
572
|
architectureRules: {
|
|
373
573
|
controllerNoDb: true,
|
|
374
574
|
serviceNoHttp: true,
|
|
375
575
|
maxFunctionLines: 80,
|
|
376
576
|
},
|
|
577
|
+
trustGate: {
|
|
578
|
+
minTrust: 45,
|
|
579
|
+
maxRisk: 'HIGH',
|
|
580
|
+
presets: [
|
|
581
|
+
{ branch: 'main', minTrust: 70, maxRisk: 'MEDIUM' },
|
|
582
|
+
{ branch: 'release/*', minTrust: 80, maxRisk: 'LOW' },
|
|
583
|
+
{ branch: 'legacy/*', enabled: false },
|
|
584
|
+
],
|
|
585
|
+
},
|
|
377
586
|
layers: [
|
|
378
587
|
{ name: 'domain', patterns: ['src/domain/**'], canImportFrom: [] },
|
|
379
588
|
{ name: 'app', patterns: ['src/app/**'], canImportFrom: ['domain'] },
|
|
380
589
|
{ name: 'infra', patterns: ['src/infra/**'], canImportFrom: ['domain', 'app'] },
|
|
381
590
|
],
|
|
382
|
-
|
|
591
|
+
modules: [
|
|
383
592
|
{ name: 'auth', root: 'src/modules/auth', allowedExternalImports: ['src/shared'] },
|
|
384
593
|
{ name: 'billing', root: 'src/modules/billing', allowedExternalImports: ['src/shared'] },
|
|
385
594
|
],
|
|
386
|
-
exclude: [
|
|
387
|
-
'src/generated/**',
|
|
388
|
-
'**/*.spec.ts',
|
|
389
|
-
],
|
|
390
|
-
rules: {
|
|
391
|
-
'large-file': { threshold: 400 }, // override default 300
|
|
392
|
-
'magic-number': 'off', // disable a rule
|
|
393
|
-
},
|
|
394
595
|
} satisfies DriftConfig
|
|
395
596
|
```
|
|
396
597
|
|
|
397
|
-
|
|
598
|
+
For backwards compatibility, `moduleBoundaries` and `boundaries` are normalized to `modules`.
|
|
599
|
+
|
|
600
|
+
Without a config file, `layer-violation`, `cross-boundary-import`, and configurable architecture checks (`controller-no-db`, `service-no-http`, `max-function-lines`) are skipped. All other rules run with defaults.
|
|
601
|
+
|
|
602
|
+
### Memory guardrails (recommended for large repos)
|
|
603
|
+
|
|
604
|
+
If your repository is large or your machine has limited RAM, start with:
|
|
605
|
+
|
|
606
|
+
```bash
|
|
607
|
+
drift scan . --low-memory --max-file-size-kb 1024 --max-files 8000
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
Practical tuning:
|
|
611
|
+
- Lower `--chunk-size` to reduce peak memory further (slower but safer).
|
|
612
|
+
- Keep `includeSemanticDuplication: false` in low-memory mode for the lowest memory footprint.
|
|
613
|
+
- Set `maxFileSizeKb` to skip generated/vendor files that can explode AST memory usage.
|
|
614
|
+
- Set `maxFiles` to protect CI runners from worst-case monorepo scans.
|
|
398
615
|
|
|
399
616
|
---
|
|
400
617
|
|
|
@@ -419,7 +636,7 @@ jobs:
|
|
|
419
636
|
run: npx @eduardbar/drift scan ./src --min-score 60
|
|
420
637
|
```
|
|
421
638
|
|
|
422
|
-
Exit code is `1` if the score
|
|
639
|
+
Exit code is `1` if the score is strictly greater than `--min-score`. Exit code `0` otherwise.
|
|
423
640
|
|
|
424
641
|
### Annotations and step summary with `drift ci`
|
|
425
642
|
|
|
@@ -445,10 +662,50 @@ jobs:
|
|
|
445
662
|
### Auto PR comment with `drift review`
|
|
446
663
|
|
|
447
664
|
The repository includes `.github/workflows/review-pr.yml`, which:
|
|
448
|
-
- generates a PR-ready markdown comment
|
|
665
|
+
- generates a PR-ready markdown comment with `drift trust --markdown` first and `drift review --comment` as supplementary context
|
|
449
666
|
- updates a single sticky comment (`<!-- drift-review -->`) on non-fork PRs
|
|
450
667
|
- falls back to `$GITHUB_STEP_SUMMARY` for fork PRs
|
|
451
|
-
- enforces a
|
|
668
|
+
- enforces a trust baseline gate with `drift trust-gate drift-trust.json --min-trust 45 --max-risk HIGH`
|
|
669
|
+
- uploads `drift trust --json` as `drift-trust-json-pr-<PR_NUMBER>-run-<RUN_ATTEMPT>` for manual KPI tracking
|
|
670
|
+
- publishes a compact trust KPI summary in `$GITHUB_STEP_SUMMARY` (score, merge risk, new/resolved issues when diff context is available)
|
|
671
|
+
- generates `drift.sarif` via `drift scan --format sarif`, uploads it to GitHub Code Scanning on non-fork PRs, and stores the SARIF file as workflow artifact for traceability
|
|
672
|
+
|
|
673
|
+
Quick local SARIF export:
|
|
674
|
+
|
|
675
|
+
```bash
|
|
676
|
+
drift scan ./src --format sarif > drift.sarif
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
Example GitHub Code Scanning upload with SARIF:
|
|
680
|
+
|
|
681
|
+
```yaml
|
|
682
|
+
- name: Generate drift SARIF
|
|
683
|
+
run: npx @eduardbar/drift scan ./src --format sarif > drift.sarif
|
|
684
|
+
|
|
685
|
+
- name: Upload SARIF to Code Scanning
|
|
686
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
687
|
+
with:
|
|
688
|
+
sarif_file: drift.sarif
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
Default gate behavior in this repo:
|
|
692
|
+
- fail when trust is below 45
|
|
693
|
+
- fail when merge risk is above `HIGH` (that means `CRITICAL` is blocked)
|
|
694
|
+
|
|
695
|
+
### GitHub Action contract (v2)
|
|
696
|
+
|
|
697
|
+
This repo also ships reusable local composite actions:
|
|
698
|
+
|
|
699
|
+
- `./.github/actions/drift-scan`: score-focused scan gate using `npx @eduardbar/drift@<version>` (no global install).
|
|
700
|
+
- `./.github/actions/drift-review`: trust/review/gate flow for PRs, aligned with `.github/workflows/review-pr.yml`.
|
|
701
|
+
|
|
702
|
+
`drift-scan` exposes machine-friendly outputs for CI composition:
|
|
703
|
+
- `score`, `grade`, `errors`, `warnings`, `infos`, `total-issues`, `files-affected`, `top-rules`
|
|
704
|
+
|
|
705
|
+
`drift-review` exposes:
|
|
706
|
+
- `trust-score`, `merge-risk`, `new-issues`, `resolved-issues`, `trust-json`, `trust-markdown`, `review-markdown`
|
|
707
|
+
|
|
708
|
+
See `.github/actions/drift-scan/README.md` and `.github/actions/drift-review/README.md` for usage details.
|
|
452
709
|
|
|
453
710
|
---
|
|
454
711
|
|
package/ROADMAP.md
CHANGED
|
@@ -21,19 +21,20 @@ drift's goal is to be the tool that sits between ESLint and SonarQube — lightw
|
|
|
21
21
|
**What drift is not:**
|
|
22
22
|
- Not an ESLint replacement for style or correctness rules
|
|
23
23
|
- Not a SonarQube replacement for security scanning
|
|
24
|
-
- Not a cloud product
|
|
24
|
+
- Not a cloud-only product or mandatory hosted backend
|
|
25
25
|
|
|
26
26
|
**What drift is:**
|
|
27
27
|
- A zero-config static analysis CLI that scores your TypeScript project's structural health
|
|
28
|
-
-
|
|
28
|
+
- An AI code audit CLI that helps teams decide merge trust on AI-assisted PRs
|
|
29
|
+
- A CI gate that blocks risky merges using trust thresholds
|
|
29
30
|
- A shared language for teams to talk about code quality: "our drift score went from 40 to 18 this sprint"
|
|
30
|
-
-
|
|
31
|
+
- Core CLI is free and MIT; premium governance/sponsor tiers are a product direction for teams
|
|
31
32
|
|
|
32
33
|
---
|
|
33
34
|
|
|
34
35
|
## Principles that don't change
|
|
35
36
|
|
|
36
|
-
- **
|
|
37
|
+
- **Core stays free for developers.** MIT for the OSS CLI, no backend lock-in for the core workflow.
|
|
37
38
|
- **Zero config to start.** One command, one number. Config is optional and additive.
|
|
38
39
|
- **Fast.** Results in under 3 seconds on any normal project.
|
|
39
40
|
- **One actionable number, not 400 warnings nobody reads.**
|
|
@@ -153,7 +154,7 @@ A score of 45 means nothing without context. A score that went from 80 to 45 ove
|
|
|
153
154
|
|
|
154
155
|
- **26 rules active** across 9 detection categories
|
|
155
156
|
- **Self-scan score: 14/100 (LOW)**
|
|
156
|
-
- Published on npm as `@eduardbar/drift` — MIT,
|
|
157
|
+
- Published on npm as `@eduardbar/drift` — MIT core CLI, optional premium direction documented in PRD
|
|
157
158
|
- Cross-platform: Windows / Linux / macOS via `npx`
|
|
158
159
|
|
|
159
160
|
---
|
package/dist/analyzer.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DriftIssue, FileReport, DriftConfig, LoadedPlugin } from './types.js';
|
|
1
|
+
import type { DriftIssue, FileReport, DriftConfig, DriftAnalysisOptions, LoadedPlugin } from './types.js';
|
|
2
2
|
export { TrendAnalyzer } from './git/trend.js';
|
|
3
3
|
export { BlameAnalyzer } from './git/blame.js';
|
|
4
4
|
export declare const RULE_WEIGHTS: Record<string, {
|
|
@@ -10,5 +10,5 @@ export declare function analyzeFile(file: import('ts-morph').SourceFile, options
|
|
|
10
10
|
loadedPlugins?: LoadedPlugin[];
|
|
11
11
|
projectRoot?: string;
|
|
12
12
|
}): FileReport;
|
|
13
|
-
export declare function analyzeProject(targetPath: string, config?: DriftConfig): FileReport[];
|
|
13
|
+
export declare function analyzeProject(targetPath: string, config?: DriftConfig, options?: DriftAnalysisOptions): FileReport[];
|
|
14
14
|
//# sourceMappingURL=analyzer.d.ts.map
|