@eduardbar/drift 1.2.0 → 1.3.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/.github/workflows/publish-vscode.yml +3 -3
- package/.github/workflows/publish.yml +3 -3
- package/.github/workflows/review-pr.yml +98 -6
- package/AGENTS.md +6 -0
- package/README.md +160 -10
- 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 +185 -0
- package/dist/cli.js +453 -62
- package/dist/diff.js +74 -10
- package/dist/git.js +12 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -1
- package/dist/plugins.d.ts +2 -1
- package/dist/plugins.js +177 -28
- package/dist/printer.js +4 -0
- package/dist/review.js +2 -2
- 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/shared.d.ts +2 -0
- package/dist/rules/shared.js +27 -3
- package/dist/saas.d.ts +143 -7
- package/dist/saas.js +478 -37
- package/dist/trust-kpi.d.ts +9 -0
- package/dist/trust-kpi.js +445 -0
- package/dist/trust.d.ts +65 -0
- package/dist/trust.js +571 -0
- package/dist/types.d.ts +154 -0
- package/docs/PRD.md +187 -109
- package/docs/plugin-contract.md +61 -0
- package/docs/trust-core-release-checklist.md +55 -0
- package/package.json +5 -3
- package/src/analyzer.ts +484 -155
- package/src/benchmark.ts +244 -0
- package/src/cli.ts +562 -79
- package/src/diff.ts +75 -10
- package/src/git.ts +16 -0
- package/src/index.ts +48 -0
- package/src/plugins.ts +354 -26
- package/src/printer.ts +4 -0
- package/src/review.ts +2 -2
- 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/shared.ts +31 -3
- package/src/saas.ts +641 -43
- package/src/trust-kpi.ts +518 -0
- package/src/trust.ts +774 -0
- package/src/types.ts +171 -0
- package/tests/diff.test.ts +124 -0
- package/tests/new-features.test.ts +71 -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/trust-kpi.test.ts +120 -0
- package/tests/trust.test.ts +584 -0
|
@@ -24,14 +24,14 @@ jobs:
|
|
|
24
24
|
|
|
25
25
|
steps:
|
|
26
26
|
- name: Checkout
|
|
27
|
-
uses: actions/checkout@
|
|
27
|
+
uses: actions/checkout@v5
|
|
28
28
|
with:
|
|
29
29
|
ref: ${{ github.event_name == 'release' && github.ref || github.event.repository.default_branch }}
|
|
30
30
|
|
|
31
31
|
- name: Setup Node.js
|
|
32
|
-
uses: actions/setup-node@
|
|
32
|
+
uses: actions/setup-node@v5
|
|
33
33
|
with:
|
|
34
|
-
node-version: '
|
|
34
|
+
node-version: '22'
|
|
35
35
|
cache: 'npm'
|
|
36
36
|
cache-dependency-path: packages/vscode-drift/package-lock.json
|
|
37
37
|
|
|
@@ -18,14 +18,14 @@ jobs:
|
|
|
18
18
|
runs-on: ubuntu-latest
|
|
19
19
|
steps:
|
|
20
20
|
- name: Checkout
|
|
21
|
-
uses: actions/checkout@
|
|
21
|
+
uses: actions/checkout@v5
|
|
22
22
|
with:
|
|
23
23
|
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/v{0}', inputs.tag) || github.ref }}
|
|
24
24
|
|
|
25
25
|
- name: Setup Node.js
|
|
26
|
-
uses: actions/setup-node@
|
|
26
|
+
uses: actions/setup-node@v5
|
|
27
27
|
with:
|
|
28
|
-
node-version: '
|
|
28
|
+
node-version: '22'
|
|
29
29
|
registry-url: 'https://registry.npmjs.org'
|
|
30
30
|
cache: 'npm'
|
|
31
31
|
|
|
@@ -13,21 +13,105 @@ jobs:
|
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
steps:
|
|
15
15
|
- name: Checkout
|
|
16
|
-
uses: actions/checkout@
|
|
16
|
+
uses: actions/checkout@v5
|
|
17
17
|
with:
|
|
18
18
|
fetch-depth: 0
|
|
19
19
|
|
|
20
20
|
- name: Setup Node.js
|
|
21
|
-
uses: actions/setup-node@
|
|
21
|
+
uses: actions/setup-node@v5
|
|
22
22
|
with:
|
|
23
|
-
node-version: '
|
|
23
|
+
node-version: '22'
|
|
24
24
|
cache: 'npm'
|
|
25
25
|
|
|
26
26
|
- name: Install dependencies
|
|
27
27
|
run: npm ci
|
|
28
28
|
|
|
29
|
+
# Run directly from TypeScript source in this PR to avoid stale dist artifacts.
|
|
29
30
|
- name: Generate drift review markdown
|
|
30
|
-
run: npx
|
|
31
|
+
run: npx --no-install tsx ./src/cli.ts review --base "origin/${{ github.base_ref }}" --comment > drift-review.md
|
|
32
|
+
|
|
33
|
+
- name: Generate drift trust markdown
|
|
34
|
+
run: npx --no-install tsx ./src/cli.ts trust . --base "origin/${{ github.base_ref }}" --markdown --json-output drift-trust.json > drift-trust.md
|
|
35
|
+
|
|
36
|
+
- name: Extract trust KPI values
|
|
37
|
+
id: trust_kpi
|
|
38
|
+
run: |
|
|
39
|
+
node --input-type=module -e "
|
|
40
|
+
import fs from 'node:fs'
|
|
41
|
+
const payload = JSON.parse(fs.readFileSync('drift-trust.json', 'utf8'))
|
|
42
|
+
const score = payload.trust_score ?? 'n/a'
|
|
43
|
+
const risk = payload.merge_risk ?? 'n/a'
|
|
44
|
+
const diff = payload.diff_context ?? {}
|
|
45
|
+
const newIssues = diff.newIssues ?? 'n/a'
|
|
46
|
+
const resolvedIssues = diff.resolvedIssues ?? 'n/a'
|
|
47
|
+
fs.appendFileSync(process.env.GITHUB_OUTPUT, [
|
|
48
|
+
'trust_score=' + score,
|
|
49
|
+
'merge_risk=' + risk,
|
|
50
|
+
'new_issues=' + newIssues,
|
|
51
|
+
'resolved_issues=' + resolvedIssues,
|
|
52
|
+
].join('\\n') + '\\n')
|
|
53
|
+
"
|
|
54
|
+
|
|
55
|
+
- name: Publish trust KPI step summary
|
|
56
|
+
run: |
|
|
57
|
+
{
|
|
58
|
+
echo "## drift trust KPI"
|
|
59
|
+
echo
|
|
60
|
+
echo "- Trust score: **${{ steps.trust_kpi.outputs.trust_score }}**"
|
|
61
|
+
echo "- Merge risk: **${{ steps.trust_kpi.outputs.merge_risk }}**"
|
|
62
|
+
echo "- New issues vs base: **${{ steps.trust_kpi.outputs.new_issues }}**"
|
|
63
|
+
echo "- Resolved issues vs base: **${{ steps.trust_kpi.outputs.resolved_issues }}**"
|
|
64
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
65
|
+
|
|
66
|
+
- name: Validate trust gate from generated JSON
|
|
67
|
+
run: |
|
|
68
|
+
set -euo pipefail
|
|
69
|
+
npx --no-install tsx ./src/cli.ts trust-gate drift-trust.json --min-trust 40 --max-risk HIGH | tee drift-trust-gate.txt
|
|
70
|
+
|
|
71
|
+
- name: Aggregate trust KPI from trust JSON artifact
|
|
72
|
+
run: npx --no-install tsx ./src/cli.ts kpi drift-trust.json --no-summary > drift-trust-kpi.json
|
|
73
|
+
|
|
74
|
+
- name: Extract aggregated KPI values
|
|
75
|
+
id: trust_kpi_aggregate
|
|
76
|
+
run: |
|
|
77
|
+
node --input-type=module -e "
|
|
78
|
+
import fs from 'node:fs'
|
|
79
|
+
const payload = JSON.parse(fs.readFileSync('drift-trust-kpi.json', 'utf8'))
|
|
80
|
+
const files = payload.files ?? {}
|
|
81
|
+
const trustScore = payload.trustScore ?? {}
|
|
82
|
+
const highRiskRatio = payload.highRiskRatio
|
|
83
|
+
fs.appendFileSync(process.env.GITHUB_OUTPUT, [
|
|
84
|
+
'matched=' + (files.matched ?? 'n/a'),
|
|
85
|
+
'parsed=' + (files.parsed ?? 'n/a'),
|
|
86
|
+
'malformed=' + (files.malformed ?? 'n/a'),
|
|
87
|
+
'prs=' + (payload.prsEvaluated ?? 'n/a'),
|
|
88
|
+
'avg=' + (trustScore.average ?? 'n/a'),
|
|
89
|
+
'high_risk_ratio=' + (highRiskRatio == null ? 'n/a' : Number(highRiskRatio * 100).toFixed(2) + '%'),
|
|
90
|
+
].join('\\n') + '\\n')
|
|
91
|
+
"
|
|
92
|
+
|
|
93
|
+
- name: Publish trust KPI aggregate summary
|
|
94
|
+
run: |
|
|
95
|
+
{
|
|
96
|
+
echo
|
|
97
|
+
echo "## drift trust KPI aggregate"
|
|
98
|
+
echo
|
|
99
|
+
echo "- Files matched/parsed/malformed: **${{ steps.trust_kpi_aggregate.outputs.matched }} / ${{ steps.trust_kpi_aggregate.outputs.parsed }} / ${{ steps.trust_kpi_aggregate.outputs.malformed }}**"
|
|
100
|
+
echo "- PR samples evaluated: **${{ steps.trust_kpi_aggregate.outputs.prs }}**"
|
|
101
|
+
echo "- Aggregate trust score avg: **${{ steps.trust_kpi_aggregate.outputs.avg }}**"
|
|
102
|
+
echo "- High-risk ratio (HIGH+CRITICAL): **${{ steps.trust_kpi_aggregate.outputs.high_risk_ratio }}**"
|
|
103
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
104
|
+
|
|
105
|
+
- name: Upload drift trust JSON artifact
|
|
106
|
+
uses: actions/upload-artifact@v4
|
|
107
|
+
with:
|
|
108
|
+
name: drift-trust-json-pr-${{ github.event.pull_request.number }}-run-${{ github.run_attempt }}
|
|
109
|
+
path: |
|
|
110
|
+
drift-trust.json
|
|
111
|
+
drift-trust-gate.txt
|
|
112
|
+
drift-trust-kpi.json
|
|
113
|
+
if-no-files-found: error
|
|
114
|
+
retention-days: 14
|
|
31
115
|
|
|
32
116
|
- name: Post or update PR comment (non-fork only)
|
|
33
117
|
if: github.event.pull_request.head.repo.fork == false
|
|
@@ -38,7 +122,13 @@ jobs:
|
|
|
38
122
|
run: |
|
|
39
123
|
COMMENT_BODY="<!-- drift-review -->"
|
|
40
124
|
COMMENT_BODY+=$'\n'
|
|
125
|
+
COMMENT_BODY+="## drift trust"$'\n\n'
|
|
126
|
+
COMMENT_BODY+="$(cat drift-trust.md)"
|
|
127
|
+
COMMENT_BODY+=$'\n\n'
|
|
128
|
+
COMMENT_BODY+="## drift review"$'\n\n'
|
|
41
129
|
COMMENT_BODY+="$(cat drift-review.md)"
|
|
130
|
+
COMMENT_BODY+=$'\n\n'
|
|
131
|
+
COMMENT_BODY+="<!-- drift-trust-kpi score=${{ steps.trust_kpi.outputs.trust_score }} risk=${{ steps.trust_kpi.outputs.merge_risk }} new=${{ steps.trust_kpi.outputs.new_issues }} resolved=${{ steps.trust_kpi.outputs.resolved_issues }} -->"
|
|
42
132
|
|
|
43
133
|
EXISTING_ID=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.user.login == "github-actions[bot]") | select(.body | contains("<!-- drift-review -->")) | .id' | sed -n '1p')
|
|
44
134
|
|
|
@@ -52,10 +142,12 @@ jobs:
|
|
|
52
142
|
if: github.event.pull_request.head.repo.fork == true
|
|
53
143
|
run: |
|
|
54
144
|
{
|
|
145
|
+
echo "## drift trust"
|
|
146
|
+
echo
|
|
147
|
+
cat drift-trust.md
|
|
148
|
+
echo
|
|
55
149
|
echo "## drift review"
|
|
56
150
|
echo
|
|
57
151
|
cat drift-review.md
|
|
58
152
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
59
153
|
|
|
60
|
-
- name: Enforce drift threshold
|
|
61
|
-
run: npx @eduardbar/drift review --base "origin/${{ github.base_ref }}" --fail-on 5 --comment > /dev/null
|
package/AGENTS.md
CHANGED
|
@@ -106,6 +106,11 @@ npm run test:watch # vitest (watch mode)
|
|
|
106
106
|
| `--ai` | boolean | JSON optimizado para LLMs (`AIOutput`) |
|
|
107
107
|
| `--fix` | boolean | Muestra sugerencias de fix en consola |
|
|
108
108
|
| `--min-score <n>` | number | Exit code 1 si score supera umbral (CI) |
|
|
109
|
+
| `--low-memory` | boolean | Activa análisis por chunks para bajar el pico de RAM |
|
|
110
|
+
| `--chunk-size <n>` | number | Cantidad de archivos por chunk en low-memory mode |
|
|
111
|
+
| `--max-files <n>` | number | Límite blando de archivos analizados (el resto se reporta como skip) |
|
|
112
|
+
| `--max-file-size-kb <n>` | number | Saltea archivos grandes y agrega diagnóstico de skip |
|
|
113
|
+
| `--with-semantic-duplication` | boolean | Rehabilita semantic-duplication en low-memory mode |
|
|
109
114
|
|
|
110
115
|
**Uso básico:**
|
|
111
116
|
```bash
|
|
@@ -114,6 +119,7 @@ npx @eduardbar/drift scan ./src --min-score 60
|
|
|
114
119
|
npx @eduardbar/drift scan ./src --ai | pbcopy # pegar en Claude/GPT
|
|
115
120
|
npx @eduardbar/drift scan ./src --fix # ver sugerencias inline
|
|
116
121
|
npx @eduardbar/drift scan ./src -o report.md # exportar Markdown
|
|
122
|
+
npx @eduardbar/drift scan ./src --low-memory --max-file-size-kb 1024
|
|
117
123
|
```
|
|
118
124
|
|
|
119
125
|
---
|
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,6 +50,7 @@ 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)
|
|
53
54
|
- Contributor/agent workflow guide: [`docs/AGENTS.md`](./docs/AGENTS.md)
|
|
54
55
|
|
|
55
56
|
---
|
|
@@ -68,6 +69,7 @@ drift scan ./src --json
|
|
|
68
69
|
drift scan ./src --ai
|
|
69
70
|
drift scan ./src --fix
|
|
70
71
|
drift scan ./src --min-score 50
|
|
72
|
+
drift scan ./src --low-memory --max-file-size-kb 1024
|
|
71
73
|
```
|
|
72
74
|
|
|
73
75
|
**Options:**
|
|
@@ -79,6 +81,11 @@ drift scan ./src --min-score 50
|
|
|
79
81
|
| `--ai` | Output structured JSON optimized for LLM consumption (Claude, GPT, etc.) |
|
|
80
82
|
| `--fix` | Print inline fix suggestions for each detected issue |
|
|
81
83
|
| `--min-score <n>` | Exit with code 1 if the overall score meets or exceeds this threshold |
|
|
84
|
+
| `--low-memory` | Analyze files in bounded chunks to reduce peak RAM |
|
|
85
|
+
| `--chunk-size <n>` | Files per chunk in low-memory mode (default: 40) |
|
|
86
|
+
| `--max-files <n>` | Soft cap on analyzed files; extra files are skipped with diagnostics |
|
|
87
|
+
| `--max-file-size-kb <n>` | Skip oversized files with diagnostics to avoid OOM |
|
|
88
|
+
| `--with-semantic-duplication` | Keep semantic duplication rule enabled in low-memory mode |
|
|
82
89
|
|
|
83
90
|
**Example output:**
|
|
84
91
|
|
|
@@ -146,6 +153,91 @@ drift review --base origin/main --fail-on 5
|
|
|
146
153
|
| `--comment` | Print only the markdown body for PR comments |
|
|
147
154
|
| `--fail-on <n>` | Exit code 1 when score delta is greater than or equal to `n` |
|
|
148
155
|
|
|
156
|
+
`drift review` is best used as supplementary diff context alongside `drift trust` in pull-request workflows.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### `drift trust [path]`
|
|
161
|
+
|
|
162
|
+
Compute merge trust baseline for local checks and CI merge gates.
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
drift trust
|
|
166
|
+
drift trust ./src
|
|
167
|
+
drift trust ./src --json
|
|
168
|
+
drift trust ./src --base origin/main
|
|
169
|
+
drift trust ./src --base origin/main --markdown
|
|
170
|
+
drift trust ./src --markdown --output trust.md
|
|
171
|
+
drift trust ./src --min-trust 45
|
|
172
|
+
drift trust ./src --max-risk HIGH
|
|
173
|
+
drift trust ./src --branch main
|
|
174
|
+
drift trust ./src --branch release/v1.4.0 --policy-pack strict --explain-policy
|
|
175
|
+
drift trust ./src --advanced-trust
|
|
176
|
+
drift trust ./src --advanced-trust --previous-trust ./artifacts/prev-trust.json
|
|
177
|
+
drift trust ./src --advanced-trust --history-file ./drift-history.json --markdown
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
| Flag | Description |
|
|
181
|
+
|------|-------------|
|
|
182
|
+
| `--base <ref>` | Compare against a git base ref and include deterministic diff-aware penalties/bonuses |
|
|
183
|
+
| `--json` | Output structured trust JSON (`trust_score`, `merge_risk`, `top_reasons`, `fix_priorities`, optional `diff_context`) |
|
|
184
|
+
| `--markdown` | Output PR-ready markdown trust summary |
|
|
185
|
+
| `--output <file>` | Write selected trust output format to file |
|
|
186
|
+
| `--min-trust <n>` | Exit code 1 when trust score is below `n` |
|
|
187
|
+
| `--max-risk <level>` | Exit code 1 when computed merge risk exceeds `LOW`, `MEDIUM`, `HIGH`, or `CRITICAL` |
|
|
188
|
+
| `--branch <name>` | Branch used for `drift.config` trust policy matching (falls back to CI env vars) |
|
|
189
|
+
| `--policy-pack <name>` | Optional trust policy pack from `trustGate.policyPacks` in `drift.config.*` |
|
|
190
|
+
| `--explain-policy` | Print base/pack/branch/override resolution and effective gate policy to stderr |
|
|
191
|
+
| `--advanced-trust` | Enable optional advanced trust layer (historical comparison + team guidance metadata) |
|
|
192
|
+
| `--previous-trust <file>` | Compare current trust against a prior trust JSON file in advanced mode |
|
|
193
|
+
| `--history-file <file>` | Use a specific `drift-history.json` file for advanced historical fallback |
|
|
194
|
+
|
|
195
|
+
When `trustGate` policy is configured in `drift.config.*`, branch-based thresholds are applied automatically. CLI flags still override policy values.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### `drift trust-gate <trust-json-file>`
|
|
200
|
+
|
|
201
|
+
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.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
drift trust-gate drift-trust.json --min-trust 45 --max-risk HIGH
|
|
205
|
+
drift trust-gate drift-trust.json --branch release/v1.2.0
|
|
206
|
+
drift trust-gate drift-trust.json --branch main --policy-pack balanced --explain-policy
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
| Flag | Description |
|
|
210
|
+
|------|-------------|
|
|
211
|
+
| `--min-trust <n>` | Exit code 1 when trust score in JSON is below `n` |
|
|
212
|
+
| `--max-risk <level>` | Exit code 1 when merge risk in JSON exceeds `LOW`, `MEDIUM`, `HIGH`, or `CRITICAL` |
|
|
213
|
+
| `--branch <name>` | Branch used for `drift.config` trust policy matching (falls back to CI env vars) |
|
|
214
|
+
| `--policy-pack <name>` | Optional trust policy pack from `trustGate.policyPacks` in `drift.config.*` |
|
|
215
|
+
| `--explain-policy` | Print base/pack/branch/override resolution and effective gate policy to stderr |
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
### `drift kpi <path>`
|
|
220
|
+
|
|
221
|
+
Aggregate trust KPI evidence from local artifacts (directory or glob). Prints a compact console summary to stderr and structured KPI JSON to stdout.
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
drift kpi ./artifacts/trust
|
|
225
|
+
drift kpi "./artifacts/**/drift-trust-*.json"
|
|
226
|
+
drift kpi ./artifacts/trust --no-summary
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
| Flag | Description |
|
|
230
|
+
|------|-------------|
|
|
231
|
+
| `--no-summary` | Disable stderr console summary and output JSON only |
|
|
232
|
+
|
|
233
|
+
Computed KPI fields include:
|
|
234
|
+
- PRs evaluated count
|
|
235
|
+
- Merge risk distribution (`LOW`, `MEDIUM`, `HIGH`, `CRITICAL`)
|
|
236
|
+
- Trust score average/median/min/max
|
|
237
|
+
- High-risk ratio (`HIGH` + `CRITICAL`)
|
|
238
|
+
- Diff trend aggregates when `diff_context` exists (`scoreDelta`, new/resolved issues, status distribution)
|
|
239
|
+
- Diagnostics for malformed/missing/invalid JSON artifacts
|
|
240
|
+
|
|
149
241
|
---
|
|
150
242
|
|
|
151
243
|
### `drift map [path]`
|
|
@@ -290,11 +382,18 @@ drift fix ./src --dry-run # alias of --preview
|
|
|
290
382
|
|
|
291
383
|
### `drift cloud`
|
|
292
384
|
|
|
293
|
-
Local
|
|
385
|
+
Local multi-tenant foundations backed by `.drift-cloud/store.json`.
|
|
294
386
|
|
|
295
387
|
```bash
|
|
296
|
-
drift cloud ingest ./src --
|
|
388
|
+
drift cloud ingest ./src --org acme --workspace core --user u-123 --role owner --plan sponsor --repo webapp
|
|
297
389
|
drift cloud summary
|
|
390
|
+
drift cloud summary --org acme --workspace core
|
|
391
|
+
drift cloud summary --org acme --workspace core --actor u-owner
|
|
392
|
+
drift cloud ingest ./src --org acme --workspace core --user u-member --actor u-owner
|
|
393
|
+
drift cloud ingest ./src --org acme --workspace core --user u-member --actor u-member # strict actor mode ready
|
|
394
|
+
drift cloud plan-set --org acme --plan team --actor u-owner --reason "annual upgrade"
|
|
395
|
+
drift cloud plan-changes --org acme --actor u-owner
|
|
396
|
+
drift cloud usage --org acme --actor u-owner
|
|
298
397
|
drift cloud summary --json
|
|
299
398
|
drift cloud dashboard --output drift-cloud-dashboard.html
|
|
300
399
|
```
|
|
@@ -303,11 +402,26 @@ drift cloud dashboard --output drift-cloud-dashboard.html
|
|
|
303
402
|
|
|
304
403
|
| Command | Description |
|
|
305
404
|
|---------|-------------|
|
|
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 |
|
|
405
|
+
| `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`) |
|
|
406
|
+
| `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` |
|
|
407
|
+
| `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) |
|
|
408
|
+
| `drift cloud plan-changes --org <id> --actor <user> [--json] [--store <file>]` | Lists audited plan lifecycle events for the organization |
|
|
409
|
+
| `drift cloud usage --org <id> --actor <user> [--month <yyyy-mm>] [--json] [--store <file>]` | Shows organization usage plus effective limits for current plan |
|
|
308
410
|
| `drift cloud dashboard [--output <file>] [--store <file>]` | Generates an HTML dashboard with trends and hotspots |
|
|
309
411
|
|
|
310
|
-
`drift cloud` ships with
|
|
412
|
+
`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.
|
|
413
|
+
|
|
414
|
+
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).
|
|
415
|
+
|
|
416
|
+
To require actor identity on scoped cloud operations, enable strict actor mode in `drift.config.*`:
|
|
417
|
+
|
|
418
|
+
```ts
|
|
419
|
+
export default {
|
|
420
|
+
saas: {
|
|
421
|
+
strictActorEnforcement: true,
|
|
422
|
+
},
|
|
423
|
+
}
|
|
424
|
+
```
|
|
311
425
|
|
|
312
426
|
---
|
|
313
427
|
|
|
@@ -369,11 +483,27 @@ import type { DriftConfig } from '@eduardbar/drift'
|
|
|
369
483
|
|
|
370
484
|
export default {
|
|
371
485
|
plugins: ['drift-plugin-example'],
|
|
486
|
+
performance: {
|
|
487
|
+
lowMemory: true,
|
|
488
|
+
chunkSize: 40,
|
|
489
|
+
maxFiles: 8000,
|
|
490
|
+
maxFileSizeKb: 1024,
|
|
491
|
+
includeSemanticDuplication: false,
|
|
492
|
+
},
|
|
372
493
|
architectureRules: {
|
|
373
494
|
controllerNoDb: true,
|
|
374
495
|
serviceNoHttp: true,
|
|
375
496
|
maxFunctionLines: 80,
|
|
376
497
|
},
|
|
498
|
+
trustGate: {
|
|
499
|
+
minTrust: 45,
|
|
500
|
+
maxRisk: 'HIGH',
|
|
501
|
+
presets: [
|
|
502
|
+
{ branch: 'main', minTrust: 70, maxRisk: 'MEDIUM' },
|
|
503
|
+
{ branch: 'release/*', minTrust: 80, maxRisk: 'LOW' },
|
|
504
|
+
{ branch: 'legacy/*', enabled: false },
|
|
505
|
+
],
|
|
506
|
+
},
|
|
377
507
|
layers: [
|
|
378
508
|
{ name: 'domain', patterns: ['src/domain/**'], canImportFrom: [] },
|
|
379
509
|
{ name: 'app', patterns: ['src/app/**'], canImportFrom: ['domain'] },
|
|
@@ -396,6 +526,20 @@ export default {
|
|
|
396
526
|
|
|
397
527
|
Without a config file, `layer-violation` and `cross-boundary-import` are silently skipped. All other rules run with their defaults.
|
|
398
528
|
|
|
529
|
+
### Memory guardrails (recommended for large repos)
|
|
530
|
+
|
|
531
|
+
If your repository is large or your machine has limited RAM, start with:
|
|
532
|
+
|
|
533
|
+
```bash
|
|
534
|
+
drift scan . --low-memory --max-file-size-kb 1024 --max-files 8000
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
Practical tuning:
|
|
538
|
+
- Lower `--chunk-size` to reduce peak memory further (slower but safer).
|
|
539
|
+
- Keep `includeSemanticDuplication: false` in low-memory mode for the lowest memory footprint.
|
|
540
|
+
- Set `maxFileSizeKb` to skip generated/vendor files that can explode AST memory usage.
|
|
541
|
+
- Set `maxFiles` to protect CI runners from worst-case monorepo scans.
|
|
542
|
+
|
|
399
543
|
---
|
|
400
544
|
|
|
401
545
|
## CI Integration
|
|
@@ -445,10 +589,16 @@ jobs:
|
|
|
445
589
|
### Auto PR comment with `drift review`
|
|
446
590
|
|
|
447
591
|
The repository includes `.github/workflows/review-pr.yml`, which:
|
|
448
|
-
- generates a PR-ready markdown comment
|
|
592
|
+
- generates a PR-ready markdown comment with `drift trust --markdown` first and `drift review --comment` as supplementary context
|
|
449
593
|
- updates a single sticky comment (`<!-- drift-review -->`) on non-fork PRs
|
|
450
594
|
- falls back to `$GITHUB_STEP_SUMMARY` for fork PRs
|
|
451
|
-
- enforces a
|
|
595
|
+
- enforces a trust baseline gate with `drift trust-gate drift-trust.json --min-trust 45 --max-risk HIGH`
|
|
596
|
+
- uploads `drift trust --json` as `drift-trust-json-pr-<PR_NUMBER>-run-<RUN_ATTEMPT>` for manual KPI tracking
|
|
597
|
+
- publishes a compact trust KPI summary in `$GITHUB_STEP_SUMMARY` (score, merge risk, new/resolved issues when diff context is available)
|
|
598
|
+
|
|
599
|
+
Default gate behavior in this repo:
|
|
600
|
+
- fail when trust is below 45
|
|
601
|
+
- fail when merge risk is above `HIGH` (that means `CRITICAL` is blocked)
|
|
452
602
|
|
|
453
603
|
---
|
|
454
604
|
|
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
|