@eduardbar/drift 1.1.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 +153 -0
- package/AGENTS.md +6 -0
- package/README.md +192 -4
- 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 +509 -23
- package/dist/diff.js +74 -10
- package/dist/git.js +12 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -0
- package/dist/map.d.ts +3 -2
- package/dist/map.js +98 -10
- 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 +219 -0
- package/dist/saas.js +762 -0
- 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 +160 -0
- package/docs/PRD.md +199 -172
- package/docs/plugin-contract.md +61 -0
- package/docs/trust-core-release-checklist.md +55 -0
- package/package.json +5 -3
- package/packages/vscode-drift/src/code-actions.ts +53 -0
- package/packages/vscode-drift/src/extension.ts +11 -0
- package/src/analyzer.ts +484 -155
- package/src/benchmark.ts +244 -0
- package/src/cli.ts +628 -36
- package/src/diff.ts +75 -10
- package/src/git.ts +16 -0
- package/src/index.ts +63 -0
- package/src/map.ts +112 -10
- 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 +1031 -0
- package/src/trust-kpi.ts +518 -0
- package/src/trust.ts +774 -0
- package/src/types.ts +177 -0
- package/tests/diff.test.ts +124 -0
- package/tests/new-features.test.ts +98 -0
- package/tests/plugins.test.ts +219 -0
- package/tests/rules.test.ts +23 -1
- package/tests/saas-foundation.test.ts +464 -0
- package/tests/trust-kpi.test.ts +120 -0
- package/tests/trust.test.ts +584 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Trust Core Tonight - Release Checklist
|
|
2
|
+
|
|
3
|
+
Use this checklist before releasing the trust-core milestone.
|
|
4
|
+
|
|
5
|
+
## 1) Local validation
|
|
6
|
+
|
|
7
|
+
- [x] `npm ci`
|
|
8
|
+
- [x] `npm test`
|
|
9
|
+
- [x] `npx --no-install tsx ./src/cli.ts trust . --base origin/master --markdown`
|
|
10
|
+
- [x] `npx --no-install tsx ./src/cli.ts trust . --base origin/master --json-output drift-trust.json`
|
|
11
|
+
- [x] `npx --no-install tsx ./src/cli.ts trust-gate drift-trust.json --min-trust 40 --max-risk HIGH`
|
|
12
|
+
- [x] `npx --no-install tsx ./src/cli.ts review --base origin/master --comment`
|
|
13
|
+
|
|
14
|
+
## 2) CI workflow validation
|
|
15
|
+
|
|
16
|
+
- [x] Open or update a non-fork PR and confirm `.github/workflows/review-pr.yml` runs successfully.
|
|
17
|
+
- [x] Confirm sticky PR comment is updated once (marker: `<!-- drift-review -->`).
|
|
18
|
+
- [x] Confirm PR comment includes both sections in this order: `drift trust` then `drift review`.
|
|
19
|
+
- [x] E2E: `trust-gate` runs from generated `drift-trust.json` in `review-pr` workflow.
|
|
20
|
+
- [x] E2E: `kpi` aggregates over generated trust JSON artifact (`drift-trust-kpi.json`).
|
|
21
|
+
- [x] E2E: `drift-trust-json-pr-<PR_NUMBER>-run-<RUN_ATTEMPT>` artifact now bundles:
|
|
22
|
+
- `drift-trust.json`
|
|
23
|
+
- `drift-trust-gate.txt`
|
|
24
|
+
- `drift-trust-kpi.json`
|
|
25
|
+
- [x] Confirm step summary shows trust KPI values: trust score, merge risk, new issues, resolved issues.
|
|
26
|
+
- [x] E2E: step summary includes aggregate KPI block (matched/parsed/malformed, PR samples, avg trust, high-risk ratio).
|
|
27
|
+
|
|
28
|
+
Smoke PR runbook:
|
|
29
|
+
|
|
30
|
+
- [x] Create a short-lived branch (for example `chore/trust-ci-smoke`) with a docs-only change.
|
|
31
|
+
- [x] Open a PR against `master` and wait for `review-pr` workflow to complete.
|
|
32
|
+
- [x] Verify gate behavior and comment rendering, then close or merge the PR.
|
|
33
|
+
- [x] Delete the short-lived branch after validation.
|
|
34
|
+
|
|
35
|
+
## 3) Gate behavior acceptance
|
|
36
|
+
|
|
37
|
+
Default trust gate for this milestone:
|
|
38
|
+
|
|
39
|
+
- `--min-trust 40`
|
|
40
|
+
- `--max-risk HIGH`
|
|
41
|
+
|
|
42
|
+
Checks:
|
|
43
|
+
|
|
44
|
+
- [x] PR fails when trust score is below 40.
|
|
45
|
+
- [x] PR fails when merge risk is `CRITICAL`.
|
|
46
|
+
- [x] PR passes when trust score is 40+ and merge risk is `LOW`, `MEDIUM`, or `HIGH`.
|
|
47
|
+
|
|
48
|
+
Calibration evidence from docs-only smoke runs: trust score 49 (PR #11), 46 (PR #12), 41 (PR #13). Gate floor set to 40 to avoid false negatives while still blocking `CRITICAL` risk.
|
|
49
|
+
|
|
50
|
+
## 4) Narrative and docs acceptance
|
|
51
|
+
|
|
52
|
+
- [x] `README.md` positions drift as an AI Code Audit CLI for merge trust in AI-assisted PRs.
|
|
53
|
+
- [x] `package.json` description matches the same positioning.
|
|
54
|
+
- [x] `src/cli.ts` program description matches the same positioning.
|
|
55
|
+
- [x] `ROADMAP.md` no longer contradicts PRD on core vs premium direction.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eduardbar/drift",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "AI Code Audit CLI for merge trust in AI-assisted PRs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"prepublishOnly": "npm run build",
|
|
15
15
|
"test": "vitest run",
|
|
16
16
|
"test:watch": "vitest",
|
|
17
|
-
"test:coverage": "vitest run --coverage"
|
|
17
|
+
"test:coverage": "vitest run --coverage",
|
|
18
|
+
"benchmark": "node --import tsx src/benchmark.ts"
|
|
18
19
|
},
|
|
19
20
|
"keywords": [
|
|
20
21
|
"vibe-coding",
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"@types/node": "^25.3.0",
|
|
44
45
|
"@vitest/coverage-v8": "^4.0.18",
|
|
46
|
+
"tsx": "^4.21.0",
|
|
45
47
|
"typescript": "^5.9.3",
|
|
46
48
|
"vitest": "^4.0.18"
|
|
47
49
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as vscode from 'vscode'
|
|
2
|
+
|
|
3
|
+
function buildRemoveLineEdit(document: vscode.TextDocument, line: number): vscode.WorkspaceEdit {
|
|
4
|
+
const edit = new vscode.WorkspaceEdit()
|
|
5
|
+
const targetLine = document.lineAt(line)
|
|
6
|
+
const start = targetLine.range.start
|
|
7
|
+
const end = line < document.lineCount - 1
|
|
8
|
+
? document.lineAt(line + 1).range.start
|
|
9
|
+
: targetLine.range.end
|
|
10
|
+
edit.delete(document.uri, new vscode.Range(start, end))
|
|
11
|
+
return edit
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function buildCatchTodoEdit(document: vscode.TextDocument, line: number): vscode.WorkspaceEdit {
|
|
15
|
+
const edit = new vscode.WorkspaceEdit()
|
|
16
|
+
const targetLine = document.lineAt(line)
|
|
17
|
+
const baseIndent = targetLine.text.match(/^\s*/)?.[0] ?? ''
|
|
18
|
+
const indent = `${baseIndent} `
|
|
19
|
+
edit.insert(document.uri, new vscode.Position(line + 1, 0), `${indent}// TODO: handle error\n`)
|
|
20
|
+
return edit
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class DriftCodeActionProvider implements vscode.CodeActionProvider {
|
|
24
|
+
provideCodeActions(
|
|
25
|
+
document: vscode.TextDocument,
|
|
26
|
+
_range: vscode.Range,
|
|
27
|
+
context: vscode.CodeActionContext,
|
|
28
|
+
): vscode.CodeAction[] {
|
|
29
|
+
const actions: vscode.CodeAction[] = []
|
|
30
|
+
|
|
31
|
+
for (const diagnostic of context.diagnostics) {
|
|
32
|
+
if (diagnostic.source !== 'drift') continue
|
|
33
|
+
const rule = String(diagnostic.code ?? '')
|
|
34
|
+
const line = diagnostic.range.start.line
|
|
35
|
+
|
|
36
|
+
if (rule === 'debug-leftover') {
|
|
37
|
+
const quickFix = new vscode.CodeAction('drift: remove debug leftover line', vscode.CodeActionKind.QuickFix)
|
|
38
|
+
quickFix.diagnostics = [diagnostic]
|
|
39
|
+
quickFix.edit = buildRemoveLineEdit(document, line)
|
|
40
|
+
actions.push(quickFix)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (rule === 'catch-swallow') {
|
|
44
|
+
const quickFix = new vscode.CodeAction('drift: add TODO in empty catch', vscode.CodeActionKind.QuickFix)
|
|
45
|
+
quickFix.diagnostics = [diagnostic]
|
|
46
|
+
quickFix.edit = buildCatchTodoEdit(document, line)
|
|
47
|
+
actions.push(quickFix)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return actions
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -5,6 +5,7 @@ import { analyzeFilePath } from './analyzer'
|
|
|
5
5
|
import { DriftDiagnosticsProvider } from './diagnostics'
|
|
6
6
|
import { DriftTreeProvider } from './treeview'
|
|
7
7
|
import { DriftStatusBarItem } from './statusbar'
|
|
8
|
+
import { DriftCodeActionProvider } from './code-actions'
|
|
8
9
|
import type { FileReport } from '@eduardbar/drift'
|
|
9
10
|
|
|
10
11
|
const SUPPORTED_LANGUAGES = ['typescript', 'typescriptreact', 'javascript', 'javascriptreact']
|
|
@@ -87,6 +88,7 @@ export function activate(context: vscode.ExtensionContext): void {
|
|
|
87
88
|
const diagnostics = new DriftDiagnosticsProvider()
|
|
88
89
|
const treeProvider = new DriftTreeProvider()
|
|
89
90
|
const statusBar = new DriftStatusBarItem()
|
|
91
|
+
const codeActions = new DriftCodeActionProvider()
|
|
90
92
|
|
|
91
93
|
const treeView = vscode.window.createTreeView('driftIssues', {
|
|
92
94
|
treeDataProvider: treeProvider,
|
|
@@ -121,6 +123,14 @@ export function activate(context: vscode.ExtensionContext): void {
|
|
|
121
123
|
}
|
|
122
124
|
)
|
|
123
125
|
|
|
126
|
+
const codeActionRegistration = vscode.languages.registerCodeActionsProvider(
|
|
127
|
+
SUPPORTED_LANGUAGES.map((language) => ({ language })),
|
|
128
|
+
codeActions,
|
|
129
|
+
{
|
|
130
|
+
providedCodeActionKinds: [vscode.CodeActionKind.QuickFix],
|
|
131
|
+
},
|
|
132
|
+
)
|
|
133
|
+
|
|
124
134
|
context.subscriptions.push(
|
|
125
135
|
{ dispose: () => diagnostics.dispose() },
|
|
126
136
|
{ dispose: () => statusBar.dispose() },
|
|
@@ -129,6 +139,7 @@ export function activate(context: vscode.ExtensionContext): void {
|
|
|
129
139
|
scanCmd,
|
|
130
140
|
clearCmd,
|
|
131
141
|
goToCmd,
|
|
142
|
+
codeActionRegistration,
|
|
132
143
|
)
|
|
133
144
|
}
|
|
134
145
|
|