@0xcraft/powershot 1.1.1 → 1.1.3
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/README.md +37 -25
- package/dist/cli/reports.js +4 -3
- package/dist/cli/review-command.js +4 -1
- package/dist/cli/session-command.js +6 -0
- package/dist/config.js +5 -0
- package/dist/github/api.js +198 -0
- package/dist/github/inline-comments.js +3 -154
- package/dist/github/summary-comment.js +149 -0
- package/dist/ground.js +61 -8
- package/dist/lang/packs.js +97 -14
- package/dist/lang/parse-worker.js +15 -0
- package/dist/lang/python-deps.js +21 -8
- package/dist/manifest.js +32 -0
- package/dist/package-smoke.js +4 -0
- package/dist/plan.js +7 -0
- package/dist/report/markdown.js +31 -3
- package/dist/report/summary.js +103 -0
- package/dist/report/terminal.js +19 -1
- package/dist/report/viewer.js +22 -3
- package/dist/review.js +39 -18
- package/dist/selftest.js +665 -10
- package/dist/session.js +7 -1
- package/dist/verifiers/foreign-phantom-dep.js +8 -2
- package/docs/architecture.md +38 -11
- package/docs/ci.md +45 -12
- package/examples/github-actions/action.yml +4 -5
- package/examples/github-actions/cli.yml +1 -1
- package/examples/gitlab/.gitlab-ci.yml +1 -1
- package/package.json +1 -1
package/dist/session.js
CHANGED
|
@@ -105,7 +105,13 @@ export class Session {
|
|
|
105
105
|
verified: findings.filter((f) => f.class === 'verified').length,
|
|
106
106
|
judged: findings.filter((f) => f.class === 'judged').length,
|
|
107
107
|
state: verdict.state,
|
|
108
|
-
notLookedAt: verdict.notLookedAt,
|
|
108
|
+
notLookedAt: [...verdict.notLookedAt],
|
|
109
|
+
coverage: verdict.coverage,
|
|
110
|
+
verifyOnly: verdict.verifyOnly,
|
|
111
|
+
minSeverity: verdict.minSeverity,
|
|
112
|
+
filesReviewed: verdict.filesReviewed,
|
|
113
|
+
deterministicChecks: verdict.deterministicChecks,
|
|
114
|
+
scopeDetails: verdict.scopeDetails ? [...verdict.scopeDetails] : undefined,
|
|
109
115
|
};
|
|
110
116
|
this.save();
|
|
111
117
|
}
|
|
@@ -47,13 +47,19 @@ function pythonFindings(g) {
|
|
|
47
47
|
const python = g.foreign.filter((f) => f.pack.name === 'python');
|
|
48
48
|
if (python.length === 0)
|
|
49
49
|
return [];
|
|
50
|
-
const local = localModules(g.root);
|
|
51
50
|
const findings = [];
|
|
51
|
+
const modules = new Map();
|
|
52
52
|
for (const file of python) {
|
|
53
53
|
// the manifests governing this file, not just the repository's own
|
|
54
|
-
const
|
|
54
|
+
const fileDir = dirname(join(g.root, file.path));
|
|
55
|
+
const manifest = pythonManifest(g.root, fileDir);
|
|
55
56
|
if (!manifest)
|
|
56
57
|
continue;
|
|
58
|
+
let local = modules.get(fileDir);
|
|
59
|
+
if (!local) {
|
|
60
|
+
local = localModules(g.root, fileDir);
|
|
61
|
+
modules.set(fileDir, local);
|
|
62
|
+
}
|
|
57
63
|
for (const imported of file.pack.imports?.(file.tree.rootNode) ?? []) {
|
|
58
64
|
const line = imported.node.startPosition.row + 1;
|
|
59
65
|
if (!file.changed.added.has(line))
|
package/docs/architecture.md
CHANGED
|
@@ -64,8 +64,9 @@ engine. The engine does not depend on a workflow provider or terminal layout.
|
|
|
64
64
|
| `src/manifest.ts` | Completion state and the authoritative run record | Rendering |
|
|
65
65
|
| `src/verifiers/` | Deterministic check implementations | Model calls |
|
|
66
66
|
| `src/judges/` | Prompt data, bounded model loop, tool adapter | Git target selection |
|
|
67
|
-
| `src/lang/` | Language-pack data
|
|
67
|
+
| `src/lang/` | Language-pack data, isolated parser workers, optional language oracles | Cross-run policy |
|
|
68
68
|
| `src/report/` | Pure output adapters | Re-running or reinterpreting a review |
|
|
69
|
+
| `src/github/` | GitHub REST transport and pull-request publication reconciliation | Review decisions or report rendering |
|
|
69
70
|
| `src/bench.ts` | Historical and labelled evaluation | Production command dispatch |
|
|
70
71
|
| `src/session.ts`, `src/cache.ts` | Reuse of completed judge work | Completion decisions |
|
|
71
72
|
|
|
@@ -107,7 +108,7 @@ sequenceDiagram
|
|
|
107
108
|
Plan->>Judge: bounded related-file bundles
|
|
108
109
|
Judge-->>Manifest: judged findings + usage
|
|
109
110
|
end
|
|
110
|
-
Manifest->>Manifest: compute
|
|
111
|
+
Manifest->>Manifest: compute full or portable completion / partial / failed
|
|
111
112
|
Manifest->>Report: one result, many formats
|
|
112
113
|
Report-->>User: terminal, Markdown, SARIF, JSON
|
|
113
114
|
```
|
|
@@ -126,6 +127,12 @@ A run can contain a typed TypeScript file beside a Python file or a TypeScript f
|
|
|
126
127
|
excluded from `tsconfig`. Capabilities therefore live on each selected file. A checker
|
|
127
128
|
available somewhere in the run is not evidence that it inspected every file.
|
|
128
129
|
|
|
130
|
+
The policy decides what an absent capability means. Under default `portable` coverage,
|
|
131
|
+
self-contained syntax and manifest oracles remain a complete verdict while unavailable
|
|
132
|
+
`types`, `references`, and `python-types` are recorded as optional depth. Under
|
|
133
|
+
`strict` coverage, or when a check is named explicitly, the same gap is required and
|
|
134
|
+
makes the review partial.
|
|
135
|
+
|
|
129
136
|
### Monorepo grounding follows the change
|
|
130
137
|
|
|
131
138
|
For each changed TypeScript or JavaScript file, grounding inspects only its ancestor
|
|
@@ -140,21 +147,40 @@ exists, only changed files are parsed and type-dependent capabilities remain abs
|
|
|
140
147
|
That keeps a configless or mixed-language monorepo proportional to the review rather
|
|
141
148
|
than to the repository.
|
|
142
149
|
|
|
150
|
+
Python dependency grounding follows the same rule. Local modules are discovered from
|
|
151
|
+
direct entries on each changed file's ancestor chain and conventional `src`, `lib`, or
|
|
152
|
+
`python` roots. It never recursively crawls an unrelated monorepo tree.
|
|
153
|
+
|
|
154
|
+
### Grammar memory is isolated by language
|
|
155
|
+
|
|
156
|
+
Tree-sitter WASM compilation outlives its JavaScript parser objects. Keeping every
|
|
157
|
+
declared grammar in one process pushed measured RSS past 690MB. Production parsing
|
|
158
|
+
therefore groups changed files by language, sends at most 128 files or 8MB of source to
|
|
159
|
+
one disposable worker, hydrates plain AST data in the parent, and terminates the worker.
|
|
160
|
+
Compiled-grammar memory is bounded by one language batch rather than by the
|
|
161
|
+
repository's language count; hydrated AST data remains proportional to the selected
|
|
162
|
+
diff, not the whole repository. A parser failure for a declared language fails
|
|
163
|
+
selection instead of quietly waiving the file.
|
|
164
|
+
|
|
143
165
|
### The manifest owns completion
|
|
144
166
|
|
|
145
167
|
Findings alone cannot distinguish a clean review from an interrupted or unsupported
|
|
146
|
-
one. `RunManifest` accounts for selected files, executed checks, judge
|
|
147
|
-
limits, and skips.
|
|
148
|
-
|
|
168
|
+
one. `RunManifest` accounts for selected files, executed and unavailable checks, judge
|
|
169
|
+
units, failures, limits, and skips. `state` answers whether required work completed;
|
|
170
|
+
`coverage` separately says `full` or `portable`. Renderers and the CLI consume that
|
|
171
|
+
record instead of deriving their own verdict.
|
|
149
172
|
|
|
150
173
|
```mermaid
|
|
151
174
|
stateDiagram-v2
|
|
152
175
|
[*] --> Selected
|
|
153
|
-
Selected -->
|
|
154
|
-
Selected -->
|
|
176
|
+
Selected --> Full: every file, unit, and enriched oracle accounted for
|
|
177
|
+
Selected --> Portable: required work complete; enriched gaps named
|
|
178
|
+
Selected --> Partial: required oracle, budget, or cancellation gap
|
|
155
179
|
Selected --> Failed: required stage or file failed
|
|
156
|
-
|
|
157
|
-
|
|
180
|
+
Full --> Exit0: no findings
|
|
181
|
+
Full --> Exit1: findings
|
|
182
|
+
Portable --> Exit0: no findings
|
|
183
|
+
Portable --> Exit1: findings
|
|
158
184
|
Partial --> Exit3
|
|
159
185
|
Failed --> Exit3
|
|
160
186
|
```
|
|
@@ -178,8 +204,9 @@ and duplicated runs waste both time and tokens.
|
|
|
178
204
|
### Add a language pack
|
|
179
205
|
|
|
180
206
|
Add grammar data and conventions in `src/lang/packs.ts`, then add a dedicated fixture
|
|
181
|
-
to `src/langtest.ts
|
|
182
|
-
|
|
207
|
+
to `src/langtest.ts` and include it in the all-languages review regression. Development
|
|
208
|
+
fixtures and production parsing both isolate grammars by process, so no supported pack
|
|
209
|
+
shares one unbounded WASM heap with the rest.
|
|
183
210
|
|
|
184
211
|
### Add a report format
|
|
185
212
|
|
package/docs/ci.md
CHANGED
|
@@ -16,6 +16,11 @@ There are two independent decisions:
|
|
|
16
16
|
2. Do findings block the change? Set this per repository. Exit `1` is a complete
|
|
17
17
|
verdict with findings, not an engine failure.
|
|
18
18
|
|
|
19
|
+
A completed verdict has a separate coverage level. `full` means every applicable
|
|
20
|
+
configured oracle ran. `portable` means every self-contained oracle ran while missing
|
|
21
|
+
compiler/reference depth was named. Set `"coverage": "strict"` in
|
|
22
|
+
`powershot.config.json` when portable depth must become exit `3` instead.
|
|
23
|
+
|
|
19
24
|
| Exit | Meaning | Recommended CI handling |
|
|
20
25
|
|---:|---|---|
|
|
21
26
|
| `0` | Complete, no findings | Pass |
|
|
@@ -36,6 +41,10 @@ name: PowerShot
|
|
|
36
41
|
on:
|
|
37
42
|
pull_request:
|
|
38
43
|
|
|
44
|
+
concurrency:
|
|
45
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
|
46
|
+
cancel-in-progress: true
|
|
47
|
+
|
|
39
48
|
permissions:
|
|
40
49
|
contents: read
|
|
41
50
|
pull-requests: write
|
|
@@ -49,8 +58,6 @@ jobs:
|
|
|
49
58
|
with:
|
|
50
59
|
fetch-depth: 0
|
|
51
60
|
|
|
52
|
-
- run: npm ci --ignore-scripts
|
|
53
|
-
|
|
54
61
|
- uses: xcrft/powershot@v1
|
|
55
62
|
with:
|
|
56
63
|
verify-only: 'true'
|
|
@@ -60,16 +67,41 @@ jobs:
|
|
|
60
67
|
fail-on-findings: 'true'
|
|
61
68
|
```
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
Portable coverage deliberately needs no repository install. This keeps fork and
|
|
71
|
+
private-monorepo pull requests free of registry credentials while still running each
|
|
72
|
+
declared language's syntax-backed oracles. When a trusted job already has dependencies,
|
|
73
|
+
PowerShot uses the available declarations and can reach `full` coverage. Do not pass a
|
|
74
|
+
private package token into a pull-request job merely to enrich review depth.
|
|
75
|
+
|
|
76
|
+
PowerShot finds nested `tsconfig.json` and `tsconfig.*.json` files along changed-file
|
|
77
|
+
ancestor chains; the workflow does not list projects. Python local-module discovery is
|
|
78
|
+
bounded the same way. Foreign-language grammars run in disposable per-language workers
|
|
79
|
+
and bounded batches, so all declared languages can coexist in one monorepo review.
|
|
69
80
|
|
|
70
81
|
Set `upload-sarif: 'false'` and omit `security-events: write` when GitHub code scanning
|
|
71
82
|
is unavailable or the workflow should not publish SARIF.
|
|
72
83
|
|
|
84
|
+
`comment: 'true'` maintains one summary through a hidden marker scoped to the caller's
|
|
85
|
+
workflow file and job. Reruns update only that exact `github-actions[bot]` comment, so
|
|
86
|
+
another workflow or job using the same bot identity is left alone. Each candidate also
|
|
87
|
+
records its pull-request head. A new head gets a new candidate, which means an old run
|
|
88
|
+
never patches or retires the current head's comment. The first scoped run replaces the
|
|
89
|
+
newest unmarked legacy `## PowerShot` summary from v1.1.2 or older without claiming the
|
|
90
|
+
ambiguous legacy comment through `PATCH`.
|
|
91
|
+
|
|
92
|
+
The comment leads with the verdict, effective severity threshold, review mode, and
|
|
93
|
+
aggregate file/check counts. Portable gaps and files outside parser coverage stay
|
|
94
|
+
visible under a collapsed coverage section without filling the timeline with paths.
|
|
95
|
+
The generated `powershot.manifest.json` keeps the per-file accounting for workflows
|
|
96
|
+
that want to persist it as an artifact.
|
|
97
|
+
|
|
98
|
+
PowerShot checks the target head throughout reconciliation and removes its own
|
|
99
|
+
just-created candidate if it observes a changed head. Simultaneous same-head runs
|
|
100
|
+
relist and converge on one scoped candidate when they complete. Keep the example's
|
|
101
|
+
`concurrency` block to reduce overlap and canceled stale work. GitHub's issue-comment
|
|
102
|
+
REST API has no atomic create-if-absent operation, and cancellation cannot stop a REST
|
|
103
|
+
request already in flight, so concurrency reduces but cannot eliminate that window.
|
|
104
|
+
|
|
73
105
|
`inline-comments: 'true'` requires `pull-requests: write`. It publishes at most ten
|
|
74
106
|
findings as one review. Only deterministic `verified` findings with `proven`
|
|
75
107
|
confidence, severity `medium` or higher, and a GitHub-confirmed added line qualify.
|
|
@@ -94,10 +126,10 @@ lives at [`examples/github-actions/action.yml`](../examples/github-actions/actio
|
|
|
94
126
|
| `comment` | `true` | Maintain a pull-request comment |
|
|
95
127
|
| `inline-comments` | `false` | Post up to ten proven verified findings as one inline review |
|
|
96
128
|
| `fail-on-findings` | `false` | Turn a complete finding verdict into a failed job |
|
|
97
|
-
| `approve` | `false` | Approve only a complete, clean review |
|
|
129
|
+
| `approve` | `false` | Approve only a complete, clean, full-coverage review |
|
|
98
130
|
|
|
99
|
-
The outputs are `findings` and `
|
|
100
|
-
|
|
131
|
+
The outputs are `findings`, `complete`, and `coverage`. Gate infrastructure on
|
|
132
|
+
`complete`; use `coverage == 'full'` for decisions that require semantic depth.
|
|
101
133
|
|
|
102
134
|
## Direct CLI on GitHub Actions
|
|
103
135
|
|
|
@@ -108,7 +140,7 @@ step inside a larger quality job. The complete example is
|
|
|
108
140
|
The core pattern is:
|
|
109
141
|
|
|
110
142
|
```bash
|
|
111
|
-
npm install --global --ignore-scripts @0xcraft/powershot@1.1.
|
|
143
|
+
npm install --global --ignore-scripts @0xcraft/powershot@1.1.2
|
|
112
144
|
|
|
113
145
|
STATUS=0
|
|
114
146
|
psh review --verify-only \
|
|
@@ -156,6 +188,7 @@ and artifact declaration.
|
|
|
156
188
|
- Run `--verify-only` as the fast required check; add model judges only where their
|
|
157
189
|
cost and latency are intentional.
|
|
158
190
|
- Treat exit `2`, `3`, and `130` as infrastructure or completeness failures.
|
|
191
|
+
- Read the manifest or Action `coverage` output before treating portable depth as full.
|
|
159
192
|
- Generate every report from one invocation.
|
|
160
193
|
- Publish the Markdown report for humans and SARIF or Code Quality for annotations.
|
|
161
194
|
- Pin the PowerShot source version in protected workflows.
|
|
@@ -3,6 +3,10 @@ name: PowerShot
|
|
|
3
3
|
on:
|
|
4
4
|
pull_request:
|
|
5
5
|
|
|
6
|
+
concurrency:
|
|
7
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
|
8
|
+
cancel-in-progress: true
|
|
9
|
+
|
|
6
10
|
permissions:
|
|
7
11
|
contents: read
|
|
8
12
|
pull-requests: write
|
|
@@ -16,11 +20,6 @@ jobs:
|
|
|
16
20
|
with:
|
|
17
21
|
fetch-depth: 0
|
|
18
22
|
|
|
19
|
-
# Type-aware checks need the repository's declared types. Keep lifecycle
|
|
20
|
-
# scripts disabled when pull-request code is not trusted. In a monorepo,
|
|
21
|
-
# install at the workspace root or set working-directory to the package root.
|
|
22
|
-
- run: npm ci --ignore-scripts
|
|
23
|
-
|
|
24
23
|
- uses: xcrft/powershot@v1
|
|
25
24
|
with:
|
|
26
25
|
verify-only: 'true'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xcraft/powershot",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Oracle-first code review for machine-written code, with deterministic verification and CI-ready reports.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "aglumova <alina.glumova@gmail.com>",
|