projscan 4.12.1 → 4.14.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/README.md +76 -12
- package/dist/cli/commands/prove.d.ts +3 -0
- package/dist/cli/commands/prove.js +379 -0
- package/dist/cli/commands/prove.js.map +1 -0
- package/dist/cli/commands/startMissionBundle.js +38 -0
- package/dist/cli/commands/startMissionBundle.js.map +1 -1
- package/dist/cli/registerCommands.js +2 -0
- package/dist/cli/registerCommands.js.map +1 -1
- package/dist/core/evidenceComment.js +31 -0
- package/dist/core/evidenceComment.js.map +1 -1
- package/dist/core/feedback.js +18 -0
- package/dist/core/feedback.js.map +1 -1
- package/dist/core/intentRouterCatalog.js +34 -0
- package/dist/core/intentRouterCatalog.js.map +1 -1
- package/dist/core/intentRouterKeywordToolGuards.js +10 -0
- package/dist/core/intentRouterKeywordToolGuards.js.map +1 -1
- package/dist/core/intentRouterWorkflowKeywordWeights.js +29 -0
- package/dist/core/intentRouterWorkflowKeywordWeights.js.map +1 -1
- package/dist/core/proofLedger.d.ts +9 -0
- package/dist/core/proofLedger.js +144 -0
- package/dist/core/proofLedger.js.map +1 -0
- package/dist/core/prove.d.ts +20 -0
- package/dist/core/prove.js +1121 -0
- package/dist/core/prove.js.map +1 -0
- package/dist/core/releaseEvidence.js +48 -0
- package/dist/core/releaseEvidence.js.map +1 -1
- package/dist/core/startFixedRouteCriteria.js +4 -0
- package/dist/core/startFixedRouteCriteria.js.map +1 -1
- package/dist/core/startRouteActions.js +5 -0
- package/dist/core/startRouteActions.js.map +1 -1
- package/dist/mcp/toolCatalog.js +2 -0
- package/dist/mcp/toolCatalog.js.map +1 -1
- package/dist/mcp/tools/prove.d.ts +2 -0
- package/dist/mcp/tools/prove.js +93 -0
- package/dist/mcp/tools/prove.js.map +1 -0
- package/dist/projscan-sbom.cdx.json +6 -6
- package/dist/publicCore.d.ts +1 -0
- package/dist/publicCore.js +1 -0
- package/dist/publicCore.js.map +1 -1
- package/dist/tool-manifest.json +68 -3
- package/dist/types/dogfood.d.ts +4 -0
- package/dist/types/evidencePack.d.ts +13 -0
- package/dist/types/proofLedger.d.ts +30 -0
- package/dist/types/proofLedger.js +2 -0
- package/dist/types/proofLedger.js.map +1 -0
- package/dist/types/prove.d.ts +123 -0
- package/dist/types/prove.js +2 -0
- package/dist/types/prove.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/utils/formatSupport.d.ts +1 -0
- package/dist/utils/formatSupport.js +1 -0
- package/dist/utils/formatSupport.js.map +1 -1
- package/docs/GUIDE.md +54 -1
- package/docs/demos/projscan-4-1-demo.html +24 -24
- package/docs/projscan-mission-control.gif +0 -0
- package/docs/projscan-mission-control.png +0 -0
- package/docs/projscan-mission-proof.gif +0 -0
- package/docs/projscan-proof-router.png +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,9 +24,9 @@ Use projscan when an agent asks one of these questions:
|
|
|
24
24
|
- Which files should I read before changing this feature?
|
|
25
25
|
- Which proof commands should I run before handoff?
|
|
26
26
|
- Which risks need fixes, reviewer attention, or release sign-off?
|
|
27
|
-
-
|
|
27
|
+
- Which risk should I fix first?
|
|
28
28
|
|
|
29
|
-
projscan runs core scans on your machine. It respects `.gitignore`, keeps `.env` values out of scans unless you opt in, and exposes the same evidence through a CLI and a
|
|
29
|
+
projscan runs core scans on your machine. It respects `.gitignore`, keeps `.env` values out of scans unless you opt in, and exposes the same evidence through a CLI and a 48-tool MCP server. The language layer uses 11 AST adapters covering 12 named languages.
|
|
30
30
|
|
|
31
31
|
```text
|
|
32
32
|
Your agent / engineer
|
|
@@ -36,11 +36,14 @@ Your agent / engineer
|
|
|
36
36
|
+----------------------------------------------------------------+
|
|
37
37
|
| projscan (runs locally, source stays on this machine) |
|
|
38
38
|
| ------------------------------------------------------------ |
|
|
39
|
-
| Mission Control
|
|
40
|
-
| |
|
|
41
|
-
| |
|
|
42
|
-
| |
|
|
43
|
-
| |
|
|
39
|
+
| Mission Control -> assess Cards -> simulate risk -> prove |
|
|
40
|
+
| | | | |
|
|
41
|
+
| | | +- allowed files
|
|
42
|
+
| | | +- forbidden files
|
|
43
|
+
| | | +- proof receipt
|
|
44
|
+
| | +- bounded extraction |
|
|
45
|
+
| | +- regression test first |
|
|
46
|
+
| | +- leave unchanged |
|
|
44
47
|
| +- evidence strength |
|
|
45
48
|
| +- trust memory |
|
|
46
49
|
| +- AgentLoopKit handoff |
|
|
@@ -76,20 +79,41 @@ projscan start --intent "does projscan read .env values?"
|
|
|
76
79
|
|
|
77
80
|
## Daily workflows
|
|
78
81
|
|
|
79
|
-
Use these
|
|
82
|
+
Use these four workflows before scanning the full command catalog.
|
|
80
83
|
|
|
81
84
|
### Before editing a feature
|
|
82
85
|
|
|
83
86
|
```bash
|
|
84
87
|
projscan start --intent "what files do I need to change for auth?"
|
|
85
88
|
projscan start --intent "what should we build next?" # Routes to a before-edit implementation workplan
|
|
89
|
+
projscan start --intent "is my agent allowed to change billing retry logic?"
|
|
86
90
|
projscan understand --view change --intent "add auth token refresh" --format json
|
|
91
|
+
projscan prove --intent "is my agent allowed to change billing retry logic?"
|
|
87
92
|
projscan preflight --mode before_edit --format json
|
|
88
93
|
```
|
|
89
94
|
|
|
90
|
-
You get a cited change map, read-first files, likely touched files, blocked inputs, and a before-edit proof gate.
|
|
95
|
+
You get a cited change map, read-first files, likely touched files, blocked inputs, an executable Proof Contract, and a before-edit proof gate. Agent-permission intents route to `projscan prove`, so `start` can hand the next agent a contract path instead of a broad checklist.
|
|
91
96
|
|
|
92
|
-
Success criteria: the agent can name the files to read first, the likely files to touch, and the proof
|
|
97
|
+
Success criteria: the agent can name the files to read first, the likely files to touch, the forbidden files to avoid, and the proof commands to run before editing.
|
|
98
|
+
|
|
99
|
+
### Verified change workflow
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
projscan start --intent "is my agent allowed to change billing retry logic?"
|
|
103
|
+
projscan prove --intent "is my agent allowed to change billing retry logic?" --save-contract .projscan/proof-contract.json
|
|
104
|
+
projscan prove --run -- npm test -- tests/billing/retry.test.ts
|
|
105
|
+
projscan prove --changed --contract .projscan/proof-contract.json --format markdown
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The path is `start -> prove -> run -> changed`. `start` chooses the contract workflow. `prove --intent` writes the contract only when `--save-contract` is present. `prove --run -- <command...>` executes a local proof command, records the exit code, captures a redacted log, and fingerprints the current changed files. `prove --record-command` remains available for imported CI or external evidence when projscan did not run the command. `prove --changed` checks the current working tree against the contract and local ledger.
|
|
109
|
+
|
|
110
|
+
You get a Proof Contract before edits and a Proof Receipt after edits. The contract names allowed files, forbidden files, risky contracts, likely tests, missing regression-test evidence, proof commands, safe change shape, rollback, confidence, and reviewer guidance. The receipt checks the real working tree against that contract and classifies changed files as allowed production, expected tests, documentation, generated proof artifacts, config/security drift, forbidden touches, or unexpected production. It also reports proof replay status, risk delta, commit readiness, and a reviewer checklist.
|
|
111
|
+
|
|
112
|
+
Proof Replay records command, exit code, duration, changed-file fingerprint, redacted summary, log path, and source in `.projscan/proof-ledger.jsonl`. Executed proof logs stay under `.projscan/proof-logs/`. `prove --changed` marks proof as passed, missing, failed, partial, or stale. If the agent edits new files after proof ran, the receipt says the proof is stale before a reviewer reads the diff.
|
|
113
|
+
|
|
114
|
+
Every `prove` report includes `verifiedWorkflow`, a compact JSON summary for agents and MCP clients. It names the phase, next action, next command, scope status, proof status, risk delta direction, reviewer decision, and stale/missing/failed proof flags.
|
|
115
|
+
|
|
116
|
+
Success criteria: the reviewer sees whether the agent stayed inside the contract, whether the right proof ran, and whether that proof is still fresh.
|
|
93
117
|
|
|
94
118
|
### Before handoff or commit
|
|
95
119
|
|
|
@@ -173,6 +197,43 @@ npm run docs:screenshots
|
|
|
173
197
|
npm run docs:demos
|
|
174
198
|
```
|
|
175
199
|
|
|
200
|
+
## 4.14.0 Notes
|
|
201
|
+
|
|
202
|
+
4.14.0 ships the Verified Change Workflow and Executed Proof Runner:
|
|
203
|
+
|
|
204
|
+
- `projscan prove --intent "<change>"` creates a local Proof Contract before
|
|
205
|
+
editing. It names allowed files, forbidden files, risky contracts, likely
|
|
206
|
+
tests, missing regression-test evidence, proof commands, rollback, confidence,
|
|
207
|
+
Trust Memory signals, evidence gaps, and reviewer guidance. Noisy feedback or
|
|
208
|
+
missing-signal feedback lowers the confidence reason instead of hiding it.
|
|
209
|
+
- `projscan start --intent "is my agent allowed to change billing retry logic?"`
|
|
210
|
+
routes directly to `projscan prove`, so agent-permission prompts start with a
|
|
211
|
+
bounded contract instead of a broad checklist.
|
|
212
|
+
- `projscan prove --run -- <command...>` executes an explicit local proof
|
|
213
|
+
command with shell execution disabled, writes a redacted log under
|
|
214
|
+
`.projscan/proof-logs/`, appends a `prove-run` ledger row, and lets
|
|
215
|
+
`prove --changed` replay executed proof instead of self-reported evidence.
|
|
216
|
+
- `projscan prove --changed` validates the current working tree against a saved
|
|
217
|
+
contract and emits a Proof Receipt for PRs, agents, and CI. Its changed-file
|
|
218
|
+
classes separate allowed production edits, expected tests, documentation,
|
|
219
|
+
generated proof artifacts, config/security drift, forbidden touches, and
|
|
220
|
+
unexpected production changes before giving a copyable reviewer decision.
|
|
221
|
+
- `projscan prove --record-command "<command>" --exit-code <code>` appends a
|
|
222
|
+
local Proof Ledger row with command, duration, changed-file fingerprint,
|
|
223
|
+
redacted output summary, and optional log path when importing proof from CI or
|
|
224
|
+
another trusted runner.
|
|
225
|
+
- Every `prove` JSON report includes `verifiedWorkflow`, so agents can read the
|
|
226
|
+
next action, next command, scope status, proof status, reviewer decision, and
|
|
227
|
+
stale/missing/failed proof flags without parsing Markdown.
|
|
228
|
+
- Saved Mission Control bundles append Proof Ledger rows while `mission.sh`
|
|
229
|
+
runs the existing proof queue. The script still writes proof logs and status
|
|
230
|
+
JSONL for humans.
|
|
231
|
+
- `projscan evidence-pack --pr-comment` includes the latest Proof Receipt
|
|
232
|
+
summary when a contract and ledger are available, so PR comments show proof
|
|
233
|
+
status, reviewer decision, scope, stale proof, failed proof, and the replay
|
|
234
|
+
command.
|
|
235
|
+
- MCP now includes `projscan_prove`, bringing the MCP surface to 48 tools.
|
|
236
|
+
|
|
176
237
|
## 4.12.1 Notes
|
|
177
238
|
|
|
178
239
|
4.12.1 is the simulator precision patch for the Proof Cards V2 release:
|
|
@@ -255,6 +316,8 @@ npx -y projscan mcp --watch
|
|
|
255
316
|
| What should I fix first? | `projscan bug-hunt --format json` |
|
|
256
317
|
| What is risky and worth fixing this week? | `projscan assess --goal "make this repo safer to ship this week"` |
|
|
257
318
|
| Is this refactor worth doing? | `projscan simulate --plan "split bugHunt.ts into ranking, evidence, and output modules"` |
|
|
319
|
+
| Is my agent allowed to make this change? | `projscan start --intent "is my agent allowed to change billing retry logic?"` |
|
|
320
|
+
| Did the change stay inside scope? | `projscan prove --changed --contract .projscan/proof-contract.json --format markdown` |
|
|
258
321
|
| Which files have high risk and low coverage? | `projscan coverage --format json` |
|
|
259
322
|
| What should my agent do next? | `projscan workplan --format json` |
|
|
260
323
|
| Which proof belongs in this PR? | `projscan evidence-pack --pr-comment` |
|
|
@@ -269,6 +332,7 @@ npx -y projscan mcp --watch
|
|
|
269
332
|
| `projscan preflight` | proceed, caution, or block gate for edit, commit, or merge |
|
|
270
333
|
| `projscan assess` | proof-first assessment with Proof Cards, risk delta, and fix-first guidance |
|
|
271
334
|
| `projscan simulate` | risk delta simulator for a proposed change plan before editing |
|
|
335
|
+
| `projscan prove` | executable Proof Contracts, Verified Workflow JSON, and Proof Receipts |
|
|
272
336
|
| `projscan evidence-pack` | PR-ready proof with risks, owners, and next commands |
|
|
273
337
|
| `projscan bug-hunt` | ranked fix queue from health, hotspots, session, and preflight evidence |
|
|
274
338
|
| `projscan workplan` | ordered agent tasks with proof and handoff text |
|
|
@@ -458,7 +522,7 @@ Supply-chain scanners may flag package strings or APIs used by `git`, `npm audit
|
|
|
458
522
|
|
|
459
523
|
## Install Notes
|
|
460
524
|
|
|
461
|
-
`projscan@4.
|
|
525
|
+
`projscan@4.14.0` has seven direct runtime dependencies:
|
|
462
526
|
|
|
463
527
|
- `@babel/parser`
|
|
464
528
|
- `@babel/types`
|
|
@@ -468,7 +532,7 @@ Supply-chain scanners may flag package strings or APIs used by `git`, `npm audit
|
|
|
468
532
|
- `ora`
|
|
469
533
|
- `web-tree-sitter`
|
|
470
534
|
|
|
471
|
-
If npm prints `allow-scripts` warnings during a global install, check which package names it lists. projscan core does not need `node-gyp` grammar builds at runtime in 4.
|
|
535
|
+
If npm prints `allow-scripts` warnings during a global install, check which package names it lists. projscan core does not need `node-gyp` grammar builds at runtime in 4.14.0. Open an issue with the warning text if npm reports install scripts from `projscan@latest`, or run `projscan feedback intake --text "<warning text>" --format json` to turn it into a focused setup-trust task.
|
|
472
536
|
|
|
473
537
|
The grammar packages are build-time sources, not global-install dependencies. Published grammar assets include `tree-sitter-python.wasm` and `tree-sitter-c_sharp.wasm`.
|
|
474
538
|
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { assertFormatSupported, getRootPath, maybeCompactBanner, program, setupLogLevel, } from '../_shared.js';
|
|
3
|
+
import { computeProve } from '../../core/prove.js';
|
|
4
|
+
export function registerProve() {
|
|
5
|
+
program
|
|
6
|
+
.command('prove')
|
|
7
|
+
.description('Create or validate an executable Proof Contract for a change')
|
|
8
|
+
.option('--intent <text>', 'plain-language change intent to constrain before editing')
|
|
9
|
+
.option('--changed', 'validate the current working tree against a Proof Contract')
|
|
10
|
+
.option('--contract <path>', 'Proof Contract JSON path for --changed')
|
|
11
|
+
.option('--save-contract <path>', 'write the generated Proof Contract JSON in --intent mode')
|
|
12
|
+
.option('--max-files <count>', 'maximum likely touched files to include', parsePositiveInt)
|
|
13
|
+
.option('--feedback <path>', 'local projscan feedback artifact to apply as trust memory')
|
|
14
|
+
.option('--base-ref <ref>', 'base ref for changed-file detection')
|
|
15
|
+
.option('--record-command <command>', 'record a proof command outcome without executing it')
|
|
16
|
+
.option('--exit-code <code>', 'exit code for --record-command', parseExitCode)
|
|
17
|
+
.option('--duration-ms <ms>', 'duration in milliseconds for --record-command', parseDurationMs)
|
|
18
|
+
.option('--summary <text>', 'safe proof output summary for --record-command')
|
|
19
|
+
.option('--log <path>', 'redacted proof log path for --record-command')
|
|
20
|
+
.option('--run', 'execute a local proof command supplied after -- and record the outcome')
|
|
21
|
+
.option('--run-timeout-ms <ms>', 'timeout in milliseconds for --run commands', parseDurationMs)
|
|
22
|
+
.option('--ledger <path>', 'proof ledger JSONL path')
|
|
23
|
+
.argument('[runCommand...]', 'command vector for --run after --')
|
|
24
|
+
.action(async (runCommand, cmdOpts) => {
|
|
25
|
+
setupLogLevel();
|
|
26
|
+
maybeCompactBanner();
|
|
27
|
+
const format = assertFormatSupported('prove');
|
|
28
|
+
try {
|
|
29
|
+
const runArgs = Array.isArray(runCommand) ? runCommand : [];
|
|
30
|
+
const selectedModes = [cmdOpts.intent, cmdOpts.changed, cmdOpts.recordCommand, cmdOpts.run].filter(Boolean);
|
|
31
|
+
if (selectedModes.length > 1) {
|
|
32
|
+
throw new Error('prove accepts either --intent, --changed, --record-command, or --run');
|
|
33
|
+
}
|
|
34
|
+
if (selectedModes.length === 0) {
|
|
35
|
+
throw new Error('prove requires --intent "<change>", --changed, --record-command, or --run -- <command>');
|
|
36
|
+
}
|
|
37
|
+
if (!cmdOpts.run && runArgs.length > 0) {
|
|
38
|
+
throw new Error('prove command arguments require --run before the -- delimiter');
|
|
39
|
+
}
|
|
40
|
+
if (cmdOpts.run && runArgs.length === 0) {
|
|
41
|
+
throw new Error('prove --run requires a command after --, for example: projscan prove --run -- npm test');
|
|
42
|
+
}
|
|
43
|
+
const report = await computeProve(getRootPath(), {
|
|
44
|
+
intent: cmdOpts.intent,
|
|
45
|
+
changed: Boolean(cmdOpts.changed),
|
|
46
|
+
contractPath: cmdOpts.contract,
|
|
47
|
+
saveContractPath: cmdOpts.saveContract,
|
|
48
|
+
maxFiles: cmdOpts.maxFiles,
|
|
49
|
+
feedbackPath: cmdOpts.feedback,
|
|
50
|
+
baseRef: cmdOpts.baseRef,
|
|
51
|
+
ledgerPath: cmdOpts.ledger,
|
|
52
|
+
recordCommand: cmdOpts.recordCommand,
|
|
53
|
+
exitCode: cmdOpts.exitCode,
|
|
54
|
+
durationMs: cmdOpts.durationMs,
|
|
55
|
+
summary: cmdOpts.summary,
|
|
56
|
+
logPath: cmdOpts.log,
|
|
57
|
+
runCommand: cmdOpts.run ? runArgs : undefined,
|
|
58
|
+
runTimeoutMs: cmdOpts.runTimeoutMs,
|
|
59
|
+
});
|
|
60
|
+
if (format === 'json') {
|
|
61
|
+
console.log(JSON.stringify(report, null, 2));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (format === 'markdown') {
|
|
65
|
+
console.log(renderProveMarkdown(report));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
printProveConsole(report);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
console.error(chalk.red(err instanceof Error ? err.message : String(err)));
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function printProveConsole(report) {
|
|
77
|
+
const color = report.verdict === 'blocked'
|
|
78
|
+
? chalk.red
|
|
79
|
+
: report.verdict === 'needs-review'
|
|
80
|
+
? chalk.yellow
|
|
81
|
+
: chalk.green;
|
|
82
|
+
console.log(color(`Projscan Prove: ${report.verdict}`));
|
|
83
|
+
console.log(report.summary);
|
|
84
|
+
console.log('');
|
|
85
|
+
printVerifiedWorkflowConsole(report.verifiedWorkflow);
|
|
86
|
+
console.log('');
|
|
87
|
+
if (report.contract && report.mode === 'intent') {
|
|
88
|
+
printContractConsole(report.contract);
|
|
89
|
+
}
|
|
90
|
+
if (report.ledgerRecord) {
|
|
91
|
+
console.log(chalk.bold(report.ledgerRecord.source === 'prove-run' ? 'Executed Proof' : 'Recorded Proof'));
|
|
92
|
+
console.log(`- ${report.ledgerRecord.status}: ${report.ledgerRecord.command}`);
|
|
93
|
+
console.log(`- source: ${report.ledgerRecord.source}`);
|
|
94
|
+
console.log(`- ${report.ledgerRecord.changedFiles.length} changed file(s) fingerprinted`);
|
|
95
|
+
}
|
|
96
|
+
if (report.receipt) {
|
|
97
|
+
printReceiptConsole(report.receipt);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function printVerifiedWorkflowConsole(workflow) {
|
|
101
|
+
console.log(chalk.bold('Verified Workflow'));
|
|
102
|
+
console.log(`- next action: ${workflow.nextAction}`);
|
|
103
|
+
console.log(`- next command: ${workflow.nextCommand}`);
|
|
104
|
+
console.log(`- stale proof: ${workflow.staleProof ? 'yes' : 'no'}`);
|
|
105
|
+
console.log(`- missing proof: ${workflow.missingProof ? 'yes' : 'no'}`);
|
|
106
|
+
console.log(`- failed proof: ${workflow.failedProof ? 'yes' : 'no'}`);
|
|
107
|
+
}
|
|
108
|
+
function printContractConsole(contract) {
|
|
109
|
+
console.log(chalk.bold('Allowed Files'));
|
|
110
|
+
printList(contract.allowedFiles, 'No concrete allowed files inferred');
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log(chalk.bold('Forbidden Files'));
|
|
113
|
+
printList(contract.forbiddenFiles.slice(0, 8), 'No forbidden files inferred');
|
|
114
|
+
console.log('');
|
|
115
|
+
console.log(chalk.bold('Proof Commands'));
|
|
116
|
+
printList(contract.proofCommands.slice(0, 8), 'No proof commands inferred');
|
|
117
|
+
}
|
|
118
|
+
function printReceiptConsole(receipt) {
|
|
119
|
+
console.log(chalk.bold('Scope Decision'));
|
|
120
|
+
console.log(`- ${receipt.scope.status}`);
|
|
121
|
+
console.log('');
|
|
122
|
+
console.log(chalk.bold('Changed Files'));
|
|
123
|
+
printList(receipt.scope.changedFiles, 'No changed files detected');
|
|
124
|
+
console.log('');
|
|
125
|
+
console.log(chalk.bold('Allowed production'));
|
|
126
|
+
printList(receipt.scope.allowedProduction, 'No allowed production files touched');
|
|
127
|
+
console.log('');
|
|
128
|
+
console.log(chalk.bold('Expected tests'));
|
|
129
|
+
printList(receipt.scope.expectedTests, 'No expected tests touched');
|
|
130
|
+
if (receipt.scope.forbiddenTouched.length > 0) {
|
|
131
|
+
console.log('');
|
|
132
|
+
console.log(chalk.bold('Forbidden Touched'));
|
|
133
|
+
printList(receipt.scope.forbiddenTouched, 'No forbidden files touched');
|
|
134
|
+
}
|
|
135
|
+
console.log('');
|
|
136
|
+
console.log(chalk.bold('Proof Commands'));
|
|
137
|
+
printList(receipt.proofStatus.commandsRequired.slice(0, 8), 'No proof commands required');
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log(chalk.bold('Proof Replay'));
|
|
140
|
+
console.log(`- status: ${receipt.proofStatus.status}`);
|
|
141
|
+
console.log(`- reviewer decision: ${receipt.reviewerDecision}`);
|
|
142
|
+
}
|
|
143
|
+
export function renderProveMarkdown(report) {
|
|
144
|
+
if (report.receipt)
|
|
145
|
+
return renderReceiptMarkdown(report, report.receipt);
|
|
146
|
+
if (report.ledgerRecord)
|
|
147
|
+
return renderLedgerRecordMarkdown(report);
|
|
148
|
+
return renderContractMarkdown(report);
|
|
149
|
+
}
|
|
150
|
+
function renderLedgerRecordMarkdown(report) {
|
|
151
|
+
const record = report.ledgerRecord;
|
|
152
|
+
const lines = [
|
|
153
|
+
record?.source === 'prove-run' ? '# Projscan Executed Proof' : '# Projscan Recorded Proof',
|
|
154
|
+
'',
|
|
155
|
+
`- **Verdict:** ${report.verdict}`,
|
|
156
|
+
`- **Summary:** ${report.summary}`,
|
|
157
|
+
];
|
|
158
|
+
if (!record)
|
|
159
|
+
return lines.join('\n');
|
|
160
|
+
lines.push(`- **Source:** ${record.source}`);
|
|
161
|
+
lines.push(`- **Status:** ${record.status}`);
|
|
162
|
+
lines.push(`- **Command:** \`${record.command}\``);
|
|
163
|
+
lines.push(`- **Exit code:** ${record.exitCode}`);
|
|
164
|
+
lines.push(`- **Duration:** ${record.durationMs}ms`);
|
|
165
|
+
lines.push(`- **Completed:** ${record.completedAt}`);
|
|
166
|
+
lines.push(`- **Changed-file fingerprint:** ${record.changedFileFingerprint}`);
|
|
167
|
+
if (record.logPath)
|
|
168
|
+
lines.push(`- **Log:** \`${record.logPath}\``);
|
|
169
|
+
lines.push('');
|
|
170
|
+
pushVerifiedWorkflow(lines, report.verifiedWorkflow);
|
|
171
|
+
lines.push('');
|
|
172
|
+
lines.push('## Output Summary');
|
|
173
|
+
lines.push(record.outputSummary);
|
|
174
|
+
lines.push('');
|
|
175
|
+
lines.push('## Changed Files');
|
|
176
|
+
pushList(lines, record.changedFiles, 'No changed files were fingerprinted.');
|
|
177
|
+
lines.push('');
|
|
178
|
+
lines.push('## Replay');
|
|
179
|
+
lines.push('Run `projscan prove --changed --contract .projscan/proof-contract.json --format markdown` after the edit to replay this proof against the current diff.');
|
|
180
|
+
return lines.join('\n');
|
|
181
|
+
}
|
|
182
|
+
function renderContractMarkdown(report) {
|
|
183
|
+
const contract = report.contract;
|
|
184
|
+
const lines = ['# Projscan Proof Contract', ''];
|
|
185
|
+
lines.push(`- **Verdict:** ${report.verdict}`);
|
|
186
|
+
lines.push(`- **Summary:** ${report.summary}`);
|
|
187
|
+
if (!contract)
|
|
188
|
+
return lines.join('\n');
|
|
189
|
+
lines.push(`- **Intent:** ${contract.intent}`);
|
|
190
|
+
lines.push(`- **Confidence:** ${contract.confidence}`);
|
|
191
|
+
lines.push(`- **Evidence strength:** ${contract.evidenceStrength.level} (${contract.evidenceStrength.score})`);
|
|
192
|
+
lines.push('');
|
|
193
|
+
pushVerifiedWorkflow(lines, report.verifiedWorkflow);
|
|
194
|
+
lines.push('');
|
|
195
|
+
lines.push('## Allowed Files');
|
|
196
|
+
pushList(lines, contract.allowedFiles, 'No concrete allowed files inferred.');
|
|
197
|
+
lines.push('');
|
|
198
|
+
lines.push('## Forbidden Files');
|
|
199
|
+
pushList(lines, contract.forbiddenFiles, 'No forbidden files inferred.');
|
|
200
|
+
lines.push('');
|
|
201
|
+
lines.push('## Risky Contracts');
|
|
202
|
+
pushList(lines, contract.riskyContracts, 'No public contract inferred.');
|
|
203
|
+
lines.push('');
|
|
204
|
+
lines.push('## Likely Tests');
|
|
205
|
+
pushList(lines, contract.likelyTests, 'Add or identify a regression test first.');
|
|
206
|
+
lines.push('');
|
|
207
|
+
lines.push('## Proof Commands');
|
|
208
|
+
pushCodeList(lines, contract.proofCommands);
|
|
209
|
+
lines.push('');
|
|
210
|
+
lines.push('## Reviewer Guidance');
|
|
211
|
+
lines.push(contract.reviewerGuidance);
|
|
212
|
+
return lines.join('\n');
|
|
213
|
+
}
|
|
214
|
+
function renderReceiptMarkdown(report, receipt) {
|
|
215
|
+
const lines = ['# Projscan Proof Receipt', ''];
|
|
216
|
+
lines.push(`- **Verdict:** ${report.verdict}`);
|
|
217
|
+
lines.push(`- **Summary:** ${receipt.summary}`);
|
|
218
|
+
lines.push(`- **Commit readiness:** ${receipt.commitReadiness}`);
|
|
219
|
+
lines.push(`- **Scope:** ${receipt.scope.status}`);
|
|
220
|
+
lines.push(`- **Proof status:** ${receipt.proofStatus.status}`);
|
|
221
|
+
lines.push(`- **Reviewer decision:** ${receipt.reviewerDecision}`);
|
|
222
|
+
lines.push('');
|
|
223
|
+
pushVerifiedWorkflow(lines, report.verifiedWorkflow);
|
|
224
|
+
lines.push('');
|
|
225
|
+
lines.push('## Scope Decision');
|
|
226
|
+
lines.push(`- **Status:** ${receipt.scope.status}`);
|
|
227
|
+
lines.push(`- **Allowed production:** ${receipt.scope.allowedProduction.length}`);
|
|
228
|
+
lines.push(`- **Expected tests:** ${receipt.scope.expectedTests.length}`);
|
|
229
|
+
lines.push(`- **Unexpected production:** ${receipt.scope.unexpectedProduction.length}`);
|
|
230
|
+
lines.push(`- **Forbidden touched:** ${receipt.scope.forbiddenTouched.length}`);
|
|
231
|
+
lines.push('');
|
|
232
|
+
lines.push('## Changed File Classes');
|
|
233
|
+
lines.push('');
|
|
234
|
+
lines.push('### Allowed production');
|
|
235
|
+
pushList(lines, receipt.scope.allowedProduction, 'No allowed production files touched.');
|
|
236
|
+
lines.push('');
|
|
237
|
+
lines.push('### Expected tests');
|
|
238
|
+
pushList(lines, receipt.scope.expectedTests, 'No expected tests touched.');
|
|
239
|
+
lines.push('');
|
|
240
|
+
lines.push('### Unexpected production');
|
|
241
|
+
pushList(lines, receipt.scope.unexpectedProduction, 'No unexpected production files touched.');
|
|
242
|
+
lines.push('');
|
|
243
|
+
lines.push('### Config and security');
|
|
244
|
+
pushList(lines, unique([...receipt.scope.configTouched, ...receipt.scope.securitySensitiveTouched]), 'No config or security-sensitive files touched.');
|
|
245
|
+
lines.push('');
|
|
246
|
+
lines.push('### Documentation and generated artifacts');
|
|
247
|
+
pushList(lines, unique([...receipt.scope.documentationTouched, ...receipt.scope.generatedTouched]), 'No documentation or generated artifacts touched.');
|
|
248
|
+
lines.push('');
|
|
249
|
+
lines.push('## Changed Files');
|
|
250
|
+
pushList(lines, receipt.scope.changedFiles, 'No changed files detected.');
|
|
251
|
+
lines.push('');
|
|
252
|
+
lines.push('## Forbidden Touched');
|
|
253
|
+
pushList(lines, receipt.scope.forbiddenTouched, 'No forbidden files touched.');
|
|
254
|
+
lines.push('');
|
|
255
|
+
lines.push('## Outside Allowed Scope');
|
|
256
|
+
pushList(lines, receipt.scope.outsideAllowed, 'No changed files outside allowed scope.');
|
|
257
|
+
lines.push('');
|
|
258
|
+
lines.push('## Proof Commands');
|
|
259
|
+
pushCodeList(lines, receipt.proofStatus.commandsRequired);
|
|
260
|
+
lines.push('');
|
|
261
|
+
lines.push('## Proof Replay');
|
|
262
|
+
lines.push(`- **Proof status:** ${receipt.proofStatus.status}`);
|
|
263
|
+
lines.push(`- **Reviewer decision:** ${receipt.reviewerDecision}`);
|
|
264
|
+
lines.push(`- **Risk delta:** ${receipt.riskDeltaDirection} (${receipt.riskDelta.delta})`);
|
|
265
|
+
lines.push(`- **Commands required:** ${receipt.proofStatus.commandsRequired.length}`);
|
|
266
|
+
lines.push(`- **Commands recorded:** ${receipt.proofStatus.commandsRun.length}`);
|
|
267
|
+
lines.push('');
|
|
268
|
+
lines.push('### Command Evidence');
|
|
269
|
+
pushCommandEvidence(lines, receipt.proofStatus.commandEvidence);
|
|
270
|
+
lines.push('');
|
|
271
|
+
lines.push('### Missing Commands');
|
|
272
|
+
pushCodeList(lines, receipt.proofStatus.missingCommands);
|
|
273
|
+
lines.push('');
|
|
274
|
+
lines.push('### Failed Commands');
|
|
275
|
+
pushCodeList(lines, receipt.proofStatus.failedCommands);
|
|
276
|
+
lines.push('');
|
|
277
|
+
lines.push('### Stale Commands');
|
|
278
|
+
pushCodeList(lines, receipt.proofStatus.staleCommands);
|
|
279
|
+
lines.push('');
|
|
280
|
+
lines.push('## Evidence Gaps');
|
|
281
|
+
pushList(lines, receipt.evidenceGaps, 'No evidence gaps reported.');
|
|
282
|
+
lines.push('');
|
|
283
|
+
lines.push('## Reviewer Guidance');
|
|
284
|
+
lines.push(receipt.reviewerGuidance);
|
|
285
|
+
lines.push('');
|
|
286
|
+
lines.push('## Reviewer Checklist');
|
|
287
|
+
lines.push('- [ ] Confirm unexpected production/config/security files are intentional or removed.');
|
|
288
|
+
lines.push('- [ ] Confirm expected tests or a documented regression-test gap cover the change.');
|
|
289
|
+
lines.push('- [ ] Run every required proof command before approval.');
|
|
290
|
+
lines.push('- [ ] Confirm new risks and evidence gaps are acceptable for this commit.');
|
|
291
|
+
lines.push('');
|
|
292
|
+
lines.push('## Copyable Decision');
|
|
293
|
+
lines.push(`projscan prove: ${receipt.commitReadiness} (${receipt.scope.status}); proof ${receipt.proofStatus.status}; reviewer decision ${receipt.reviewerDecision}.`);
|
|
294
|
+
return lines.join('\n');
|
|
295
|
+
}
|
|
296
|
+
function pushVerifiedWorkflow(lines, workflow) {
|
|
297
|
+
lines.push('## Verified Workflow');
|
|
298
|
+
lines.push(`- **phase:** ${workflow.phase}`);
|
|
299
|
+
lines.push(`- **status:** ${workflow.status}`);
|
|
300
|
+
lines.push(`- **next action:** ${workflow.nextAction}`);
|
|
301
|
+
lines.push(`- **next command:** \`${workflow.nextCommand}\``);
|
|
302
|
+
if (workflow.scopeStatus)
|
|
303
|
+
lines.push(`- **scope:** ${workflow.scopeStatus}`);
|
|
304
|
+
if (workflow.proofStatus)
|
|
305
|
+
lines.push(`- **proof:** ${workflow.proofStatus}`);
|
|
306
|
+
if (workflow.reviewerDecision)
|
|
307
|
+
lines.push(`- **reviewer decision:** ${workflow.reviewerDecision}`);
|
|
308
|
+
if (workflow.riskDeltaDirection)
|
|
309
|
+
lines.push(`- **risk delta:** ${workflow.riskDeltaDirection}`);
|
|
310
|
+
lines.push(`- **stale proof:** ${workflow.staleProof ? 'yes' : 'no'}`);
|
|
311
|
+
lines.push(`- **missing proof:** ${workflow.missingProof ? 'yes' : 'no'}`);
|
|
312
|
+
lines.push(`- **failed proof:** ${workflow.failedProof ? 'yes' : 'no'}`);
|
|
313
|
+
}
|
|
314
|
+
function printList(values, empty) {
|
|
315
|
+
if (values.length === 0) {
|
|
316
|
+
console.log(`- ${empty}`);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
for (const value of values)
|
|
320
|
+
console.log(`- ${value}`);
|
|
321
|
+
}
|
|
322
|
+
function pushList(lines, values, empty) {
|
|
323
|
+
if (values.length === 0) {
|
|
324
|
+
lines.push(`- ${empty}`);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
for (const value of values)
|
|
328
|
+
lines.push(`- ${value}`);
|
|
329
|
+
}
|
|
330
|
+
function pushCodeList(lines, values) {
|
|
331
|
+
if (values.length === 0) {
|
|
332
|
+
lines.push('- No proof commands required.');
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
for (const value of values)
|
|
336
|
+
lines.push(`- \`${value}\``);
|
|
337
|
+
}
|
|
338
|
+
function pushCommandEvidence(lines, values) {
|
|
339
|
+
if (values.length === 0) {
|
|
340
|
+
lines.push('- No proof command evidence recorded.');
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
for (const value of values)
|
|
344
|
+
lines.push(formatCommandEvidence(value));
|
|
345
|
+
}
|
|
346
|
+
function formatCommandEvidence(value) {
|
|
347
|
+
const state = value.fresh ? 'fresh' : value.staleReason ? 'stale' : value.status;
|
|
348
|
+
const exit = typeof value.exitCode === 'number' ? ` exit ${value.exitCode}` : ' no exit code';
|
|
349
|
+
const duration = typeof value.durationMs === 'number' ? `, ${value.durationMs}ms` : '';
|
|
350
|
+
const log = value.logPath ? `, log ${value.logPath}` : '';
|
|
351
|
+
const summary = value.outputSummary ? ` - ${value.outputSummary}` : '';
|
|
352
|
+
const stale = value.staleReason ? ` (${value.staleReason})` : '';
|
|
353
|
+
return `- **${value.status} ${state}:** \`${value.command}\` (${exit}${duration}${log})${stale}${summary}`;
|
|
354
|
+
}
|
|
355
|
+
function unique(values) {
|
|
356
|
+
return [...new Set(values)];
|
|
357
|
+
}
|
|
358
|
+
function parsePositiveInt(value) {
|
|
359
|
+
const parsed = Number.parseInt(value, 10);
|
|
360
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
361
|
+
throw new Error('value must be a positive integer');
|
|
362
|
+
}
|
|
363
|
+
return parsed;
|
|
364
|
+
}
|
|
365
|
+
function parseExitCode(value) {
|
|
366
|
+
const parsed = Number(value);
|
|
367
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
368
|
+
throw new Error('exit code must be a non-negative integer');
|
|
369
|
+
}
|
|
370
|
+
return parsed;
|
|
371
|
+
}
|
|
372
|
+
function parseDurationMs(value) {
|
|
373
|
+
const parsed = Number(value);
|
|
374
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
375
|
+
throw new Error('duration-ms must be a non-negative number');
|
|
376
|
+
}
|
|
377
|
+
return parsed;
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=prove.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prove.js","sourceRoot":"","sources":["../../../src/cli/commands/prove.ts"],"names":[],"mappings":"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"}
|
|
@@ -115,13 +115,16 @@ function missionUnsafeCommandBlock() {
|
|
|
115
115
|
function missionProofLogSetup(report) {
|
|
116
116
|
return [
|
|
117
117
|
'MISSION_DIR=$(CDPATH= cd "$(dirname "$0")" && pwd)',
|
|
118
|
+
'PROJSCAN_ROOT=$(git -C "$MISSION_DIR" rev-parse --show-toplevel 2>/dev/null || pwd)',
|
|
118
119
|
'PROOF_LOG_DIR="${MISSION_DIR}/proof-logs"',
|
|
119
120
|
'PROOF_STATUS_FILE="${PROOF_LOG_DIR}/status.jsonl"',
|
|
120
121
|
'PROOF_REPORT_FILE="${PROOF_LOG_DIR}/run-report.md"',
|
|
121
122
|
'PROOF_SUMMARY_FILE="${PROOF_LOG_DIR}/summary.json"',
|
|
123
|
+
'PROOF_LEDGER_FILE="${PROJSCAN_ROOT}/.projscan/proof-ledger.jsonl"',
|
|
122
124
|
'mkdir -p "$PROOF_LOG_DIR"',
|
|
123
125
|
': > "$PROOF_STATUS_FILE"',
|
|
124
126
|
': > "$PROOF_REPORT_FILE"',
|
|
127
|
+
...scriptAppendProofLedgerFunction(),
|
|
125
128
|
...scriptInitRunReport(report),
|
|
126
129
|
scriptWriteSummaryJson('running'),
|
|
127
130
|
scriptPrintExpanded('Proof logs: ${PROOF_LOG_DIR}'),
|
|
@@ -523,6 +526,7 @@ function scriptCommandBlock(label, command, logTarget) {
|
|
|
523
526
|
'status=$?',
|
|
524
527
|
'set -e',
|
|
525
528
|
scriptAppendStatusJsonl(logTarget.id, label, logTarget.logName, command),
|
|
529
|
+
scriptAppendProofLedgerJsonl(logTarget.id, label, logTarget.logName, command),
|
|
526
530
|
scriptAppendReportRow(logTarget.id, label, logTarget.logName),
|
|
527
531
|
'if [ "$status" -ne 0 ]; then',
|
|
528
532
|
` ${scriptPrintError(`Command failed. See proof-logs/${logTarget.logName}.`)}`,
|
|
@@ -549,6 +553,40 @@ function scriptAppendStatusJsonl(id, label, logName, command) {
|
|
|
549
553
|
}).replace(/}$/, ',"exitCode":');
|
|
550
554
|
return `printf '%s%s%s\\n' ${shellQuote(prefix)} "$status" '}' >> "$PROOF_STATUS_FILE"`;
|
|
551
555
|
}
|
|
556
|
+
function scriptAppendProofLedgerFunction() {
|
|
557
|
+
return [
|
|
558
|
+
'append_proof_ledger_row() {',
|
|
559
|
+
' mkdir -p "$(dirname "$PROOF_LEDGER_FILE")" 2>/dev/null || true',
|
|
560
|
+
' node - "$PROJSCAN_ROOT" "$MISSION_DIR" "$1" "$2" "$3" "$4" "$5" <<\'NODE\' >> "$PROOF_LEDGER_FILE" 2>/dev/null || true',
|
|
561
|
+
'const crypto = require("node:crypto");',
|
|
562
|
+
'const path = require("node:path");',
|
|
563
|
+
'const { execFileSync } = require("node:child_process");',
|
|
564
|
+
'const [root, missionDir, id, label, logName, command, exitCodeRaw] = process.argv.slice(2);',
|
|
565
|
+
'function normalize(value) { return String(value || "").split(path.sep).join("/").replace(/^\\.\\//, ""); }',
|
|
566
|
+
'function changedFiles() {',
|
|
567
|
+
' try {',
|
|
568
|
+
' const output = execFileSync("git", ["-C", root, "status", "--porcelain", "--untracked-files=all"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });',
|
|
569
|
+
' return [...new Set(output.split("\\n").map((line) => line.slice(3).trim()).filter(Boolean).map((file) => file.includes(" -> ") ? file.split(" -> ").pop() : file).map(normalize).filter((file) => !file.startsWith(".projscan/")))].sort();',
|
|
570
|
+
' } catch {',
|
|
571
|
+
' return [];',
|
|
572
|
+
' }',
|
|
573
|
+
'}',
|
|
574
|
+
'const files = changedFiles();',
|
|
575
|
+
'const fingerprint = crypto.createHash("sha256").update(files.join("\\n")).digest("hex");',
|
|
576
|
+
'const completedAt = new Date().toISOString();',
|
|
577
|
+
'const exitCode = Number.parseInt(exitCodeRaw, 10);',
|
|
578
|
+
'const logPath = normalize(path.relative(root, path.join(missionDir, "proof-logs", logName)));',
|
|
579
|
+
'const digest = crypto.createHash("sha256").update(`${command}\\n${completedAt}\\n${exitCode}`).digest("hex").slice(0, 12);',
|
|
580
|
+
'const record = { schemaVersion: 1, id: `proof-ledger-${digest}`, command, normalizedCommand: command.trim().replace(/\\s+/g, " "), cwd: normalize(path.relative(root, missionDir) || "."), exitCode, status: exitCode === 0 ? "passed" : "failed", startedAt: completedAt, completedAt, durationMs: 0, changedFileFingerprint: fingerprint, changedFiles: files, outputSummary: `Mission proof ${label} exited ${exitCode}.`, source: "mission", logPath };',
|
|
581
|
+
'process.stdout.write(`${JSON.stringify(record)}\\n`);',
|
|
582
|
+
'NODE',
|
|
583
|
+
'}',
|
|
584
|
+
'',
|
|
585
|
+
];
|
|
586
|
+
}
|
|
587
|
+
function scriptAppendProofLedgerJsonl(id, label, logName, command) {
|
|
588
|
+
return `append_proof_ledger_row ${shellQuote(id)} ${shellQuote(label)} ${shellQuote(logName)} ${shellQuote(command)} "$status"`;
|
|
589
|
+
}
|
|
552
590
|
function scriptInitRunReport(report) {
|
|
553
591
|
const mission = report.missionControl;
|
|
554
592
|
return [
|