projscan 4.14.0 → 4.15.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 +71 -21
- package/dist/cli/commands/evidencePack.js +2 -0
- package/dist/cli/commands/evidencePack.js.map +1 -1
- package/dist/cli/commands/prove.js +172 -23
- package/dist/cli/commands/prove.js.map +1 -1
- package/dist/cli/commands/startConsole.d.ts +2 -2
- package/dist/cli/commands/startConsole.js +2 -260
- package/dist/cli/commands/startConsole.js.map +1 -1
- package/dist/cli/commands/startConsoleExecution.d.ts +5 -0
- package/dist/cli/commands/startConsoleExecution.js +108 -0
- package/dist/cli/commands/startConsoleExecution.js.map +1 -0
- package/dist/cli/commands/startConsoleMission.d.ts +6 -0
- package/dist/cli/commands/startConsoleMission.js +157 -0
- package/dist/cli/commands/startConsoleMission.js.map +1 -0
- package/dist/cli/commands/startMissionBundle.js +24 -27
- package/dist/cli/commands/startMissionBundle.js.map +1 -1
- package/dist/core/adoption.d.ts +8 -81
- package/dist/core/adoption.js +4 -549
- package/dist/core/adoption.js.map +1 -1
- package/dist/core/adoptionFirstRunDiagnostics.d.ts +20 -0
- package/dist/core/adoptionFirstRunDiagnostics.js +240 -0
- package/dist/core/adoptionFirstRunDiagnostics.js.map +1 -0
- package/dist/core/adoptionMcpConfig.d.ts +27 -0
- package/dist/core/adoptionMcpConfig.js +123 -0
- package/dist/core/adoptionMcpConfig.js.map +1 -0
- package/dist/core/adoptionMcpDoctor.d.ts +23 -0
- package/dist/core/adoptionMcpDoctor.js +87 -0
- package/dist/core/adoptionMcpDoctor.js.map +1 -0
- package/dist/core/adoptionWorkflowRecipes.d.ts +14 -0
- package/dist/core/adoptionWorkflowRecipes.js +110 -0
- package/dist/core/adoptionWorkflowRecipes.js.map +1 -0
- package/dist/core/bugHunt.js +26 -255
- package/dist/core/bugHunt.js.map +1 -1
- package/dist/core/bugHuntPreflightFindings.d.ts +2 -1
- package/dist/core/bugHuntPreflightFindings.js +20 -0
- package/dist/core/bugHuntPreflightFindings.js.map +1 -1
- package/dist/core/bugHuntReportAssembly.d.ts +20 -0
- package/dist/core/bugHuntReportAssembly.js +179 -0
- package/dist/core/bugHuntReportAssembly.js.map +1 -0
- package/dist/core/bugHuntSourceFindings.d.ts +3 -0
- package/dist/core/bugHuntSourceFindings.js +61 -0
- package/dist/core/bugHuntSourceFindings.js.map +1 -0
- package/dist/core/dogfood.js +4 -393
- package/dist/core/dogfood.js.map +1 -1
- package/dist/core/dogfoodMarketValidation.d.ts +5 -0
- package/dist/core/dogfoodMarketValidation.js +265 -0
- package/dist/core/dogfoodMarketValidation.js.map +1 -0
- package/dist/core/dogfoodRepoEvaluation.d.ts +4 -0
- package/dist/core/dogfoodRepoEvaluation.js +137 -0
- package/dist/core/dogfoodRepoEvaluation.js.map +1 -0
- package/dist/core/evidenceComment.js +50 -13
- package/dist/core/evidenceComment.js.map +1 -1
- package/dist/core/feedback.js +2 -252
- package/dist/core/feedback.js.map +1 -1
- package/dist/core/feedbackIntakeClassifier.d.ts +2 -0
- package/dist/core/feedbackIntakeClassifier.js +255 -0
- package/dist/core/feedbackIntakeClassifier.js.map +1 -0
- package/dist/core/intentRouterKeywordToolGuards.js +1 -55
- package/dist/core/intentRouterKeywordToolGuards.js.map +1 -1
- package/dist/core/intentRouterKeywordWeights.js +13 -28
- package/dist/core/intentRouterKeywordWeights.js.map +1 -1
- package/dist/core/intentRouterProductGuardSignals.d.ts +3 -0
- package/dist/core/intentRouterProductGuardSignals.js +59 -0
- package/dist/core/intentRouterProductGuardSignals.js.map +1 -0
- package/dist/core/markdownSafety.d.ts +3 -0
- package/dist/core/markdownSafety.js +14 -0
- package/dist/core/markdownSafety.js.map +1 -0
- package/dist/core/preflight.d.ts +2 -0
- package/dist/core/preflight.js.map +1 -1
- package/dist/core/preflightChangedFiles.d.ts +2 -0
- package/dist/core/preflightChangedFiles.js +1 -1
- package/dist/core/preflightChangedFiles.js.map +1 -1
- package/dist/core/preflightInputs.d.ts +2 -0
- package/dist/core/preflightInputs.js +5 -2
- package/dist/core/preflightInputs.js.map +1 -1
- package/dist/core/proofLedger.d.ts +5 -1
- package/dist/core/proofLedger.js +161 -12
- package/dist/core/proofLedger.js.map +1 -1
- package/dist/core/proofReplay.d.ts +9 -0
- package/dist/core/proofReplay.js +164 -0
- package/dist/core/proofReplay.js.map +1 -0
- package/dist/core/proofSufficiency.d.ts +19 -0
- package/dist/core/proofSufficiency.js +425 -0
- package/dist/core/proofSufficiency.js.map +1 -0
- package/dist/core/prove.d.ts +6 -0
- package/dist/core/prove.js +277 -87
- package/dist/core/prove.js.map +1 -1
- package/dist/core/qualityScorecard.js +8 -238
- package/dist/core/qualityScorecard.js.map +1 -1
- package/dist/core/qualityScorecardDimensions.d.ts +14 -0
- package/dist/core/qualityScorecardDimensions.js +99 -0
- package/dist/core/qualityScorecardDimensions.js.map +1 -0
- package/dist/core/qualityScorecardRisks.d.ts +8 -0
- package/dist/core/qualityScorecardRisks.js +107 -0
- package/dist/core/qualityScorecardRisks.js.map +1 -0
- package/dist/core/qualityScorecardSignals.d.ts +20 -0
- package/dist/core/qualityScorecardSignals.js +59 -0
- package/dist/core/qualityScorecardSignals.js.map +1 -0
- package/dist/core/releaseEvidence.d.ts +1 -0
- package/dist/core/releaseEvidence.js +15 -40
- package/dist/core/releaseEvidence.js.map +1 -1
- package/dist/core/releaseEvidenceBaseline.js +4 -1
- package/dist/core/releaseEvidenceBaseline.js.map +1 -1
- package/dist/core/releaseEvidenceProofReceipt.d.ts +6 -0
- package/dist/core/releaseEvidenceProofReceipt.js +140 -0
- package/dist/core/releaseEvidenceProofReceipt.js.map +1 -0
- package/dist/core/releaseEvidenceVerdict.d.ts +5 -2
- package/dist/core/releaseEvidenceVerdict.js +39 -1
- package/dist/core/releaseEvidenceVerdict.js.map +1 -1
- package/dist/core/repositoryScanner.d.ts +1 -0
- package/dist/core/repositoryScanner.js +5 -4
- package/dist/core/repositoryScanner.js.map +1 -1
- package/dist/core/sessionResources.d.ts +14 -2
- package/dist/core/sessionResources.js +3 -3
- package/dist/core/sessionResources.js.map +1 -1
- package/dist/core/startInputs.d.ts +1 -1
- package/dist/core/startIntentTargets.d.ts +1 -1
- package/dist/core/startIntentTargets.js +1 -16
- package/dist/core/startIntentTargets.js.map +1 -1
- package/dist/core/startMissionInputStatusPolicy.d.ts +7 -0
- package/dist/core/startMissionInputStatusPolicy.js +74 -0
- package/dist/core/startMissionInputStatusPolicy.js.map +1 -0
- package/dist/core/startMissionPolicy.d.ts +6 -15
- package/dist/core/startMissionPolicy.js +4 -305
- package/dist/core/startMissionPolicy.js.map +1 -1
- package/dist/core/startMissionProofPolicy.d.ts +6 -0
- package/dist/core/startMissionProofPolicy.js +84 -0
- package/dist/core/startMissionProofPolicy.js.map +1 -0
- package/dist/core/startMissionRiskPolicy.d.ts +4 -0
- package/dist/core/startMissionRiskPolicy.js +85 -0
- package/dist/core/startMissionRiskPolicy.js.map +1 -0
- package/dist/core/startMissionRoutingPolicy.d.ts +6 -0
- package/dist/core/startMissionRoutingPolicy.js +67 -0
- package/dist/core/startMissionRoutingPolicy.js.map +1 -0
- package/dist/core/startMode.d.ts +1 -2
- package/dist/core/startMode.js +4 -151
- package/dist/core/startMode.js.map +1 -1
- package/dist/core/startModeIntentPolicy.d.ts +12 -0
- package/dist/core/startModeIntentPolicy.js +41 -0
- package/dist/core/startModeIntentPolicy.js.map +1 -0
- package/dist/core/startModeRoutingPolicy.d.ts +4 -0
- package/dist/core/startModeRoutingPolicy.js +117 -0
- package/dist/core/startModeRoutingPolicy.js.map +1 -0
- package/dist/core/startSearchQueryTargets.d.ts +1 -0
- package/dist/core/startSearchQueryTargets.js +17 -0
- package/dist/core/startSearchQueryTargets.js.map +1 -0
- package/dist/core/workplan.d.ts +3 -2
- package/dist/core/workplan.js +11 -585
- package/dist/core/workplan.js.map +1 -1
- package/dist/core/workplanCoordinationTasks.d.ts +3 -0
- package/dist/core/workplanCoordinationTasks.js +82 -0
- package/dist/core/workplanCoordinationTasks.js.map +1 -0
- package/dist/core/workplanModeTasks.d.ts +2 -0
- package/dist/core/workplanModeTasks.js +192 -0
- package/dist/core/workplanModeTasks.js.map +1 -0
- package/dist/core/workplanPreflightTasks.d.ts +2 -0
- package/dist/core/workplanPreflightTasks.js +126 -0
- package/dist/core/workplanPreflightTasks.js.map +1 -0
- package/dist/core/workplanQualitySignals.d.ts +7 -0
- package/dist/core/workplanQualitySignals.js +63 -0
- package/dist/core/workplanQualitySignals.js.map +1 -0
- package/dist/core/workplanReport.d.ts +4 -0
- package/dist/core/workplanReport.js +79 -0
- package/dist/core/workplanReport.js.map +1 -0
- package/dist/core/workplanRiskOwnership.d.ts +5 -0
- package/dist/core/workplanRiskOwnership.js +97 -0
- package/dist/core/workplanRiskOwnership.js.map +1 -0
- package/dist/core/workplanSuggestedActions.d.ts +2 -0
- package/dist/core/workplanSuggestedActions.js +43 -0
- package/dist/core/workplanSuggestedActions.js.map +1 -0
- package/dist/mcp/tools/prove.js +23 -17
- package/dist/mcp/tools/prove.js.map +1 -1
- package/dist/projscan-sbom.cdx.json +6 -6
- package/dist/tool-manifest.json +2 -2
- package/dist/types/config.d.ts +15 -0
- package/dist/types/evidencePack.d.ts +21 -0
- package/dist/types/prove.d.ts +79 -0
- package/dist/utils/changedFiles.js +57 -16
- package/dist/utils/changedFiles.js.map +1 -1
- package/dist/utils/config.js +2 -0
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/configProofRecipes.d.ts +2 -0
- package/dist/utils/configProofRecipes.js +91 -0
- package/dist/utils/configProofRecipes.js.map +1 -0
- package/docs/GUIDE.md +120 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,19 +101,25 @@ Success criteria: the agent can name the files to read first, the likely files t
|
|
|
101
101
|
```bash
|
|
102
102
|
projscan start --intent "is my agent allowed to change billing retry logic?"
|
|
103
103
|
projscan prove --intent "is my agent allowed to change billing retry logic?" --save-contract .projscan/proof-contract.json
|
|
104
|
+
# Make the bounded edit, then run the proof command.
|
|
104
105
|
projscan prove --run -- npm test -- tests/billing/retry.test.ts
|
|
105
106
|
projscan prove --changed --contract .projscan/proof-contract.json --format markdown
|
|
106
107
|
```
|
|
107
108
|
|
|
108
|
-
The path is `start -> prove -> run -> changed`. `start` chooses the contract workflow. `prove --intent` writes
|
|
109
|
+
The command path is `start -> prove -> run -> changed`. Make the bounded edit after the contract exists and before `prove --run`. `start` chooses the contract workflow. `prove --intent` writes `.projscan/proof-contract.json` 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
|
|
|
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
|
|
111
|
+
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, reviewer guidance, and `proofRequirements` for each risk surface. 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. The receipt reports proof replay status, Proof Sufficiency, risk delta, commit readiness, and a reviewer checklist.
|
|
111
112
|
|
|
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
|
+
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. The receipt JSON includes `proofReplay` with a replay timeline, `changedAfterProof`, replay command, and local receipt fingerprint. If the agent edits new files after proof ran, the receipt says the proof is stale before a reviewer reads the diff.
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
Proof Sufficiency estimates whether the local ledger covers each changed surface. `proofSufficiency` marks rows as strong, adequate, weak, missing, stale, or failed, then lists the exact gaps reviewers need to resolve.
|
|
115
116
|
|
|
116
|
-
|
|
117
|
+
Team Proof Recipes let a repo encode required proof for sensitive paths in `proofRecipes`; when a matching recipe is configured, `prove --intent` adds that recipe's commands, reviewers, and forbidden files to the Proof Contract. `prove --changed` and `projscan evidence-pack --pr-comment` then show missing recipe proof, required reviewers, and recipe drift in the Proof Receipt. The recipe does not run proof commands by itself; use `prove --run -- <command...>` or `prove --record-command` to add evidence to the local ledger.
|
|
118
|
+
Saved contracts are the source of truth for `prove --changed`; update the contract when a team recipe changes.
|
|
119
|
+
|
|
120
|
+
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, proof sufficiency status, risk delta direction, reviewer decision, and stale/missing/failed proof flags.
|
|
121
|
+
|
|
122
|
+
Success criteria: the reviewer sees scope, proof execution, proof freshness, and sufficiency for the changed risk surface.
|
|
117
123
|
|
|
118
124
|
### Before handoff or commit
|
|
119
125
|
|
|
@@ -124,7 +130,7 @@ projscan preflight --mode before_commit --format json
|
|
|
124
130
|
projscan evidence-pack --pr-comment
|
|
125
131
|
```
|
|
126
132
|
|
|
127
|
-
You get
|
|
133
|
+
You get changed-file risk, one or two ranked next actions, manual review gates, owner routing, baseline trend memory, and exact proof commands for the reviewer. Use `projscan bug-hunt --format json` when you want the raw fix queue behind the assessment.
|
|
128
134
|
|
|
129
135
|
Success criteria: the reviewer sees the top fix, the remaining proof, and any manual sign-off gate without reading the full scan output.
|
|
130
136
|
|
|
@@ -197,15 +203,15 @@ npm run docs:screenshots
|
|
|
197
203
|
npm run docs:demos
|
|
198
204
|
```
|
|
199
205
|
|
|
200
|
-
## 4.
|
|
206
|
+
## 4.15.0 Notes
|
|
201
207
|
|
|
202
|
-
4.
|
|
208
|
+
4.15.0 strengthens the proof-first change loop:
|
|
203
209
|
|
|
204
210
|
- `projscan prove --intent "<change>"` creates a local Proof Contract before
|
|
205
211
|
editing. It names allowed files, forbidden files, risky contracts, likely
|
|
206
212
|
tests, missing regression-test evidence, proof commands, rollback, confidence,
|
|
207
|
-
Trust Memory signals, evidence gaps,
|
|
208
|
-
|
|
213
|
+
Trust Memory signals, evidence gaps, reviewer guidance, and
|
|
214
|
+
`proofRequirements` for each risk surface.
|
|
209
215
|
- `projscan start --intent "is my agent allowed to change billing retry logic?"`
|
|
210
216
|
routes directly to `projscan prove`, so agent-permission prompts start with a
|
|
211
217
|
bounded contract instead of a broad checklist.
|
|
@@ -218,22 +224,51 @@ npm run docs:demos
|
|
|
218
224
|
classes separate allowed production edits, expected tests, documentation,
|
|
219
225
|
generated proof artifacts, config/security drift, forbidden touches, and
|
|
220
226
|
unexpected production changes before giving a copyable reviewer decision.
|
|
227
|
+
The receipt also includes `proofReplay` with replay status, timeline events,
|
|
228
|
+
`changedAfterProof`, replay command, and receipt fingerprint. Proof
|
|
229
|
+
Sufficiency shows whether each `proofRequirements` row has strong, adequate,
|
|
230
|
+
weak, missing, stale, or failed proof.
|
|
231
|
+
- Team Proof Recipes let a repo add path-matched `proofRecipes` to
|
|
232
|
+
`.projscanrc.json`. Matching recipes add required commands, reviewers, and
|
|
233
|
+
forbidden drift to the Proof Contract and Proof Receipt.
|
|
221
234
|
- `projscan prove --record-command "<command>" --exit-code <code>` appends a
|
|
222
235
|
local Proof Ledger row with command, duration, changed-file fingerprint,
|
|
223
236
|
redacted output summary, and optional log path when importing proof from CI or
|
|
224
|
-
another
|
|
237
|
+
another runner.
|
|
225
238
|
- Every `prove` JSON report includes `verifiedWorkflow`, so agents can read the
|
|
226
|
-
next action, next command, scope status, proof status,
|
|
227
|
-
stale/missing/failed proof flags without
|
|
239
|
+
next action, next command, scope status, proof status, `proofSufficiency`
|
|
240
|
+
status, reviewer decision, and stale/missing/failed proof flags without
|
|
241
|
+
parsing Markdown.
|
|
228
242
|
- Saved Mission Control bundles append Proof Ledger rows while `mission.sh`
|
|
229
243
|
runs the existing proof queue. The script still writes proof logs and status
|
|
230
244
|
JSONL for humans.
|
|
231
245
|
- `projscan evidence-pack --pr-comment` includes the latest Proof Receipt
|
|
232
246
|
summary when a contract and ledger are available, so PR comments show proof
|
|
233
|
-
status, reviewer decision, scope, stale proof, failed proof,
|
|
234
|
-
|
|
247
|
+
status, proof replay, reviewer decision, scope, stale proof, failed proof,
|
|
248
|
+
proof sufficiency, recipe gaps, required reviewers, changed-after-proof files,
|
|
249
|
+
receipt fingerprint, and the replay command.
|
|
250
|
+
- Proof artifacts are harder to spoof: Proof Contract and Proof Ledger reads
|
|
251
|
+
reject symlink escapes, proof logs redact more standalone token/key shapes,
|
|
252
|
+
and generated mission scripts reject shell control syntax before running.
|
|
253
|
+
- The codebase behind the proof workflow is smaller and easier to review:
|
|
254
|
+
source hotspots in Mission Control, bug-hunt, quality-scorecard, workplan,
|
|
255
|
+
adoption, start-mode routing, and intent routing were split into focused
|
|
256
|
+
helpers with architecture tests.
|
|
235
257
|
- MCP now includes `projscan_prove`, bringing the MCP surface to 48 tools.
|
|
236
258
|
|
|
259
|
+
## 4.14.0 Notes
|
|
260
|
+
|
|
261
|
+
4.14.0 ships the Verified Change Workflow and Executed Proof Runner:
|
|
262
|
+
|
|
263
|
+
- `projscan prove --intent "<change>"` creates a local Proof Contract before
|
|
264
|
+
editing.
|
|
265
|
+
- `projscan prove --run -- <command...>` executes an explicit local proof
|
|
266
|
+
command with shell execution disabled and writes a redacted Proof Ledger row.
|
|
267
|
+
- `projscan prove --changed` emits a Proof Receipt for PRs, agents, and CI.
|
|
268
|
+
- `projscan evidence-pack --pr-comment` includes the latest Proof Receipt
|
|
269
|
+
summary when a contract and ledger are available.
|
|
270
|
+
- MCP includes `projscan_prove`, bringing the MCP surface to 48 tools.
|
|
271
|
+
|
|
237
272
|
## 4.12.1 Notes
|
|
238
273
|
|
|
239
274
|
4.12.1 is the simulator precision patch for the Proof Cards V2 release:
|
|
@@ -264,7 +299,7 @@ npm run docs:demos
|
|
|
264
299
|
|
|
265
300
|
- Added a dedicated Proof Cards screenshot for `projscan assess` and
|
|
266
301
|
`projscan simulate`.
|
|
267
|
-
- Regenerated README screenshots so public media
|
|
302
|
+
- Regenerated README screenshots so public media showed the 47-tool MCP
|
|
268
303
|
surface.
|
|
269
304
|
- Updated website handoff guidance to use immutable `v4.11.1` media URLs.
|
|
270
305
|
|
|
@@ -333,7 +368,7 @@ npx -y projscan mcp --watch
|
|
|
333
368
|
| `projscan assess` | proof-first assessment with Proof Cards, risk delta, and fix-first guidance |
|
|
334
369
|
| `projscan simulate` | risk delta simulator for a proposed change plan before editing |
|
|
335
370
|
| `projscan prove` | executable Proof Contracts, Verified Workflow JSON, and Proof Receipts |
|
|
336
|
-
| `projscan evidence-pack` |
|
|
371
|
+
| `projscan evidence-pack` | review evidence with risks, owners, proof receipts, and next commands |
|
|
337
372
|
| `projscan bug-hunt` | ranked fix queue from health, hotspots, session, and preflight evidence |
|
|
338
373
|
| `projscan workplan` | ordered agent tasks with proof and handoff text |
|
|
339
374
|
| `projscan doctor` | project health, tooling gaps, dead code, and supply-chain signals |
|
|
@@ -400,6 +435,15 @@ Create a `.projscanrc.json` when repo defaults should live in source control:
|
|
|
400
435
|
"severityOverrides": {
|
|
401
436
|
"missing-prettier": "info"
|
|
402
437
|
},
|
|
438
|
+
"proofRecipes": [
|
|
439
|
+
{
|
|
440
|
+
"id": "billing-critical",
|
|
441
|
+
"matches": ["src/billing/**"],
|
|
442
|
+
"requiredCommands": ["npm test -- tests/billing/retry.test.ts"],
|
|
443
|
+
"requiredReviewers": ["@platform"],
|
|
444
|
+
"forbiddenFiles": ["src/auth/**"]
|
|
445
|
+
}
|
|
446
|
+
],
|
|
403
447
|
"reportPolicies": {
|
|
404
448
|
"apiEvidence": {
|
|
405
449
|
"reportScope": ["src/api", "packages/backend"],
|
|
@@ -416,6 +460,12 @@ the rule everywhere. For one line, add an inline directive next to the value:
|
|
|
416
460
|
const firebaseKey = 'AIza...'; // projscan-ignore-line hardcoded-secret -- Firebase web keys are public identifiers
|
|
417
461
|
```
|
|
418
462
|
|
|
463
|
+
Use `proofRecipes` when a path needs team-specific proof; when a matching recipe
|
|
464
|
+
is configured, `projscan prove` adds its proof commands, reviewers, and forbidden
|
|
465
|
+
files to the contract and receipt. It does not run proof commands by itself.
|
|
466
|
+
Recipes without `requiredCommands` are skipped, and duplicate recipe IDs keep the
|
|
467
|
+
first valid recipe.
|
|
468
|
+
|
|
419
469
|
Config docs live in [docs/GUIDE.md](docs/GUIDE.md#configuration-projscanrc).
|
|
420
470
|
|
|
421
471
|
## CI
|
|
@@ -491,7 +541,7 @@ Plugin docs:
|
|
|
491
541
|
|
|
492
542
|
## Supported Repos
|
|
493
543
|
|
|
494
|
-
projscan reads TypeScript, JavaScript, Python, Go, Java, Ruby, Rust, PHP, C#, Kotlin, Swift,
|
|
544
|
+
projscan reads TypeScript, JavaScript, Python, Go, Java, Ruby, Rust, PHP, C#, Kotlin, Swift, and C++ with AST-aware adapters where available. It also detects file-level signals for C, Shell, CSS, HTML, SQL, Dart, Lua, Scala, R, and related project files.
|
|
495
545
|
|
|
496
546
|
Framework signals cover React, Next.js, Vue, Nuxt, Svelte, Angular, Express, Fastify, NestJS, Vite, Tailwind CSS, Prisma, Remix, SvelteKit, Astro, Hono, Koa, and common monorepo layouts.
|
|
497
547
|
|
|
@@ -507,7 +557,7 @@ JavaScript and TypeScript use `@babel/parser`. Non-JS languages use packaged tre
|
|
|
507
557
|
| Network | `audit`, registry checks, opt-in telemetry, and optional semantic model download can contact the network. |
|
|
508
558
|
| Telemetry | Off until you run `projscan telemetry enable` or accept the `init team` prompt. |
|
|
509
559
|
| Plugins | Local plugin code runs after `PROJSCAN_PLUGINS_PREVIEW=1` and an execution path such as `doctor`, `ci`, `analyze`, or `plugin test --execute`. |
|
|
510
|
-
| Repo writes | Source writes require explicit fix commands.
|
|
560
|
+
| Repo writes | Source writes require explicit fix commands. Caches, saved missions, Proof Contracts, Proof Ledger rows, and proof logs stay under `.projscan*` local directories. |
|
|
511
561
|
|
|
512
562
|
Audit helpers:
|
|
513
563
|
|
|
@@ -522,7 +572,7 @@ Supply-chain scanners may flag package strings or APIs used by `git`, `npm audit
|
|
|
522
572
|
|
|
523
573
|
## Install Notes
|
|
524
574
|
|
|
525
|
-
`projscan@4.
|
|
575
|
+
`projscan@4.15.0` has seven direct runtime dependencies:
|
|
526
576
|
|
|
527
577
|
- `@babel/parser`
|
|
528
578
|
- `@babel/types`
|
|
@@ -532,7 +582,7 @@ Supply-chain scanners may flag package strings or APIs used by `git`, `npm audit
|
|
|
532
582
|
- `ora`
|
|
533
583
|
- `web-tree-sitter`
|
|
534
584
|
|
|
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.
|
|
585
|
+
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.15.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.
|
|
536
586
|
|
|
537
587
|
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`.
|
|
538
588
|
|
|
@@ -8,6 +8,7 @@ export function registerEvidencePack() {
|
|
|
8
8
|
.option('--line <line>', 'product line to include, repeatable (default: next six minor lines)', collectLine, [])
|
|
9
9
|
.option('--website-prompt', 'include website-update prompt text')
|
|
10
10
|
.option('--pr-comment', 'print a GitHub PR comment markdown artifact')
|
|
11
|
+
.option('--base-ref <ref>', 'explicit git base ref for review evidence')
|
|
11
12
|
.option('--max-findings <count>', 'maximum bug-hunt findings to include', parsePositiveInt)
|
|
12
13
|
.action(async (cmdOpts) => {
|
|
13
14
|
setupLogLevel();
|
|
@@ -18,6 +19,7 @@ export function registerEvidencePack() {
|
|
|
18
19
|
lines: cmdOpts.line,
|
|
19
20
|
includeWebsitePrompt: cmdOpts.websitePrompt === true,
|
|
20
21
|
includePrComment: cmdOpts.prComment === true,
|
|
22
|
+
baseRef: cmdOpts.baseRef,
|
|
21
23
|
maxFindings: cmdOpts.maxFindings,
|
|
22
24
|
});
|
|
23
25
|
if (format === 'json') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evidencePack.js","sourceRoot":"","sources":["../../../src/cli/commands/evidencePack.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"evidencePack.js","sourceRoot":"","sources":["../../../src/cli/commands/evidencePack.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { assertFormatSupported, getRootPath, maybeCompactBanner, program, setupLogLevel, } from '../_shared.js';
|
|
2
|
+
import { assertFormatSupported, getRootPath, maybeCompactBanner, program, loadProjectConfig, setupLogLevel, } from '../_shared.js';
|
|
3
3
|
import { computeProve } from '../../core/prove.js';
|
|
4
|
+
import { escapeMarkdownText, markdownInlineCode, markdownInlineList, } from '../../core/markdownSafety.js';
|
|
4
5
|
export function registerProve() {
|
|
5
6
|
program
|
|
6
7
|
.command('prove')
|
|
@@ -17,6 +18,7 @@ export function registerProve() {
|
|
|
17
18
|
.option('--duration-ms <ms>', 'duration in milliseconds for --record-command', parseDurationMs)
|
|
18
19
|
.option('--summary <text>', 'safe proof output summary for --record-command')
|
|
19
20
|
.option('--log <path>', 'redacted proof log path for --record-command')
|
|
21
|
+
.option('--record-source <source>', 'source for --record-command evidence', parseProofLedgerSource)
|
|
20
22
|
.option('--run', 'execute a local proof command supplied after -- and record the outcome')
|
|
21
23
|
.option('--run-timeout-ms <ms>', 'timeout in milliseconds for --run commands', parseDurationMs)
|
|
22
24
|
.option('--ledger <path>', 'proof ledger JSONL path')
|
|
@@ -40,6 +42,10 @@ export function registerProve() {
|
|
|
40
42
|
if (cmdOpts.run && runArgs.length === 0) {
|
|
41
43
|
throw new Error('prove --run requires a command after --, for example: projscan prove --run -- npm test');
|
|
42
44
|
}
|
|
45
|
+
if (cmdOpts.recordSource && !cmdOpts.recordCommand) {
|
|
46
|
+
throw new Error('prove --record-source requires --record-command');
|
|
47
|
+
}
|
|
48
|
+
const config = await loadProjectConfig();
|
|
43
49
|
const report = await computeProve(getRootPath(), {
|
|
44
50
|
intent: cmdOpts.intent,
|
|
45
51
|
changed: Boolean(cmdOpts.changed),
|
|
@@ -54,8 +60,10 @@ export function registerProve() {
|
|
|
54
60
|
durationMs: cmdOpts.durationMs,
|
|
55
61
|
summary: cmdOpts.summary,
|
|
56
62
|
logPath: cmdOpts.log,
|
|
63
|
+
recordSource: cmdOpts.recordSource,
|
|
57
64
|
runCommand: cmdOpts.run ? runArgs : undefined,
|
|
58
65
|
runTimeoutMs: cmdOpts.runTimeoutMs,
|
|
66
|
+
proofRecipes: cmdOpts.changed ? undefined : config.proofRecipes,
|
|
59
67
|
});
|
|
60
68
|
if (format === 'json') {
|
|
61
69
|
console.log(JSON.stringify(report, null, 2));
|
|
@@ -116,6 +124,8 @@ function printContractConsole(contract) {
|
|
|
116
124
|
printList(contract.proofCommands.slice(0, 8), 'No proof commands inferred');
|
|
117
125
|
}
|
|
118
126
|
function printReceiptConsole(receipt) {
|
|
127
|
+
const proofReplay = proofReplayForReceipt(receipt);
|
|
128
|
+
const proofSufficiency = proofSufficiencyForReceipt(receipt);
|
|
119
129
|
console.log(chalk.bold('Scope Decision'));
|
|
120
130
|
console.log(`- ${receipt.scope.status}`);
|
|
121
131
|
console.log('');
|
|
@@ -135,10 +145,28 @@ function printReceiptConsole(receipt) {
|
|
|
135
145
|
console.log('');
|
|
136
146
|
console.log(chalk.bold('Proof Commands'));
|
|
137
147
|
printList(receipt.proofStatus.commandsRequired.slice(0, 8), 'No proof commands required');
|
|
148
|
+
if (receipt.teamProofRecipes?.length) {
|
|
149
|
+
console.log('');
|
|
150
|
+
console.log(chalk.bold('Team Proof Recipes'));
|
|
151
|
+
for (const recipe of receipt.teamProofRecipes) {
|
|
152
|
+
const reviewers = recipe.requiredReviewers?.length ? recipe.requiredReviewers.join(', ') : 'none';
|
|
153
|
+
const drift = recipe.forbiddenTouched?.length ? recipe.forbiddenTouched.join(', ') : 'none';
|
|
154
|
+
console.log(`- ${recipe.id}: reviewers ${reviewers}; recipe drift ${drift}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
138
157
|
console.log('');
|
|
139
158
|
console.log(chalk.bold('Proof Replay'));
|
|
140
|
-
console.log(`- status: ${
|
|
159
|
+
console.log(`- replay status: ${proofReplay.status}`);
|
|
160
|
+
console.log(`- proof status: ${receipt.proofStatus.status}`);
|
|
141
161
|
console.log(`- reviewer decision: ${receipt.reviewerDecision}`);
|
|
162
|
+
console.log(`- changed after proof: ${inlineList(proofReplay.changedAfterProof)}`);
|
|
163
|
+
console.log(`- receipt fingerprint: ${proofReplay.receiptFingerprint}`);
|
|
164
|
+
console.log('');
|
|
165
|
+
console.log(chalk.bold('Proof Sufficiency'));
|
|
166
|
+
console.log(`- status: ${proofSufficiency.status}`);
|
|
167
|
+
for (const gap of proofSufficiency.gaps.slice(0, 3)) {
|
|
168
|
+
console.log(`- gap: ${gap}`);
|
|
169
|
+
}
|
|
142
170
|
}
|
|
143
171
|
export function renderProveMarkdown(report) {
|
|
144
172
|
if (report.receipt)
|
|
@@ -153,24 +181,24 @@ function renderLedgerRecordMarkdown(report) {
|
|
|
153
181
|
record?.source === 'prove-run' ? '# Projscan Executed Proof' : '# Projscan Recorded Proof',
|
|
154
182
|
'',
|
|
155
183
|
`- **Verdict:** ${report.verdict}`,
|
|
156
|
-
`- **Summary:** ${report.summary}`,
|
|
184
|
+
`- **Summary:** ${escapeMarkdownText(report.summary)}`,
|
|
157
185
|
];
|
|
158
186
|
if (!record)
|
|
159
187
|
return lines.join('\n');
|
|
160
188
|
lines.push(`- **Source:** ${record.source}`);
|
|
161
189
|
lines.push(`- **Status:** ${record.status}`);
|
|
162
|
-
lines.push(`- **Command:**
|
|
190
|
+
lines.push(`- **Command:** ${markdownInlineCode(record.command)}`);
|
|
163
191
|
lines.push(`- **Exit code:** ${record.exitCode}`);
|
|
164
192
|
lines.push(`- **Duration:** ${record.durationMs}ms`);
|
|
165
193
|
lines.push(`- **Completed:** ${record.completedAt}`);
|
|
166
194
|
lines.push(`- **Changed-file fingerprint:** ${record.changedFileFingerprint}`);
|
|
167
195
|
if (record.logPath)
|
|
168
|
-
lines.push(`- **Log:**
|
|
196
|
+
lines.push(`- **Log:** ${markdownInlineCode(record.logPath)}`);
|
|
169
197
|
lines.push('');
|
|
170
198
|
pushVerifiedWorkflow(lines, report.verifiedWorkflow);
|
|
171
199
|
lines.push('');
|
|
172
200
|
lines.push('## Output Summary');
|
|
173
|
-
lines.push(record.outputSummary);
|
|
201
|
+
lines.push(escapeMarkdownText(record.outputSummary));
|
|
174
202
|
lines.push('');
|
|
175
203
|
lines.push('## Changed Files');
|
|
176
204
|
pushList(lines, record.changedFiles, 'No changed files were fingerprinted.');
|
|
@@ -183,10 +211,10 @@ function renderContractMarkdown(report) {
|
|
|
183
211
|
const contract = report.contract;
|
|
184
212
|
const lines = ['# Projscan Proof Contract', ''];
|
|
185
213
|
lines.push(`- **Verdict:** ${report.verdict}`);
|
|
186
|
-
lines.push(`- **Summary:** ${report.summary}`);
|
|
214
|
+
lines.push(`- **Summary:** ${escapeMarkdownText(report.summary)}`);
|
|
187
215
|
if (!contract)
|
|
188
216
|
return lines.join('\n');
|
|
189
|
-
lines.push(`- **Intent:** ${contract.intent}`);
|
|
217
|
+
lines.push(`- **Intent:** ${escapeMarkdownText(contract.intent)}`);
|
|
190
218
|
lines.push(`- **Confidence:** ${contract.confidence}`);
|
|
191
219
|
lines.push(`- **Evidence strength:** ${contract.evidenceStrength.level} (${contract.evidenceStrength.score})`);
|
|
192
220
|
lines.push('');
|
|
@@ -208,13 +236,15 @@ function renderContractMarkdown(report) {
|
|
|
208
236
|
pushCodeList(lines, contract.proofCommands);
|
|
209
237
|
lines.push('');
|
|
210
238
|
lines.push('## Reviewer Guidance');
|
|
211
|
-
lines.push(contract.reviewerGuidance);
|
|
239
|
+
lines.push(escapeMarkdownText(contract.reviewerGuidance));
|
|
212
240
|
return lines.join('\n');
|
|
213
241
|
}
|
|
214
242
|
function renderReceiptMarkdown(report, receipt) {
|
|
243
|
+
const proofReplay = proofReplayForReceipt(receipt);
|
|
244
|
+
const proofSufficiency = proofSufficiencyForReceipt(receipt);
|
|
215
245
|
const lines = ['# Projscan Proof Receipt', ''];
|
|
216
246
|
lines.push(`- **Verdict:** ${report.verdict}`);
|
|
217
|
-
lines.push(`- **Summary:** ${receipt.summary}`);
|
|
247
|
+
lines.push(`- **Summary:** ${escapeMarkdownText(receipt.summary)}`);
|
|
218
248
|
lines.push(`- **Commit readiness:** ${receipt.commitReadiness}`);
|
|
219
249
|
lines.push(`- **Scope:** ${receipt.scope.status}`);
|
|
220
250
|
lines.push(`- **Proof status:** ${receipt.proofStatus.status}`);
|
|
@@ -258,12 +288,34 @@ function renderReceiptMarkdown(report, receipt) {
|
|
|
258
288
|
lines.push('## Proof Commands');
|
|
259
289
|
pushCodeList(lines, receipt.proofStatus.commandsRequired);
|
|
260
290
|
lines.push('');
|
|
291
|
+
lines.push('## Team Proof Recipes');
|
|
292
|
+
pushTeamProofRecipes(lines, receipt);
|
|
293
|
+
lines.push('');
|
|
261
294
|
lines.push('## Proof Replay');
|
|
262
|
-
lines.push(`- **
|
|
295
|
+
lines.push(`- **replay status:** ${proofReplay.status}`);
|
|
296
|
+
lines.push(`- **summary:** ${escapeMarkdownText(proofReplay.summary)}`);
|
|
297
|
+
lines.push(`- **proof status:** ${receipt.proofStatus.status}`);
|
|
263
298
|
lines.push(`- **Reviewer decision:** ${receipt.reviewerDecision}`);
|
|
264
|
-
lines.push(`- **
|
|
265
|
-
lines.push(`- **
|
|
266
|
-
lines.push(`- **
|
|
299
|
+
lines.push(`- **risk delta:** ${receipt.riskDeltaDirection} (${receipt.riskDelta.delta})`);
|
|
300
|
+
lines.push(`- **commands required:** ${receipt.proofStatus.commandsRequired.length}`);
|
|
301
|
+
lines.push(`- **commands recorded:** ${receipt.proofStatus.commandsRun.length}`);
|
|
302
|
+
lines.push(`- **changed after proof:** ${markdownInlineList(proofReplay.changedAfterProof)}`);
|
|
303
|
+
lines.push(`- **replay command:** ${markdownInlineCode(proofReplay.replayCommand)}`);
|
|
304
|
+
lines.push(`- **receipt fingerprint:** ${markdownInlineCode(proofReplay.receiptFingerprint)}`);
|
|
305
|
+
lines.push('');
|
|
306
|
+
lines.push('### Replay Timeline');
|
|
307
|
+
pushReplayEvents(lines, proofReplay.events);
|
|
308
|
+
lines.push('');
|
|
309
|
+
lines.push('## Proof Sufficiency');
|
|
310
|
+
lines.push(`- **sufficiency status:** ${proofSufficiency.status}`);
|
|
311
|
+
lines.push(`- **summary:** ${escapeMarkdownText(proofSufficiency.summary)}`);
|
|
312
|
+
lines.push(`- **weak requirements:** ${proofSufficiency.weakRequirements.length}`);
|
|
313
|
+
lines.push(`- **missing requirements:** ${proofSufficiency.missingRequirements.length}`);
|
|
314
|
+
lines.push(`- **stale requirements:** ${proofSufficiency.staleRequirements.length}`);
|
|
315
|
+
lines.push(`- **failed requirements:** ${proofSufficiency.failedRequirements.length}`);
|
|
316
|
+
lines.push('');
|
|
317
|
+
lines.push('### Requirement Evidence');
|
|
318
|
+
pushRequirementEvidence(lines, proofSufficiency.requirements);
|
|
267
319
|
lines.push('');
|
|
268
320
|
lines.push('### Command Evidence');
|
|
269
321
|
pushCommandEvidence(lines, receipt.proofStatus.commandEvidence);
|
|
@@ -281,7 +333,7 @@ function renderReceiptMarkdown(report, receipt) {
|
|
|
281
333
|
pushList(lines, receipt.evidenceGaps, 'No evidence gaps reported.');
|
|
282
334
|
lines.push('');
|
|
283
335
|
lines.push('## Reviewer Guidance');
|
|
284
|
-
lines.push(receipt.reviewerGuidance);
|
|
336
|
+
lines.push(escapeMarkdownText(receipt.reviewerGuidance));
|
|
285
337
|
lines.push('');
|
|
286
338
|
lines.push('## Reviewer Checklist');
|
|
287
339
|
lines.push('- [ ] Confirm unexpected production/config/security files are intentional or removed.');
|
|
@@ -297,12 +349,15 @@ function pushVerifiedWorkflow(lines, workflow) {
|
|
|
297
349
|
lines.push('## Verified Workflow');
|
|
298
350
|
lines.push(`- **phase:** ${workflow.phase}`);
|
|
299
351
|
lines.push(`- **status:** ${workflow.status}`);
|
|
300
|
-
lines.push(`- **next action:** ${workflow.nextAction}`);
|
|
301
|
-
lines.push(`- **next command:**
|
|
352
|
+
lines.push(`- **next action:** ${escapeMarkdownText(workflow.nextAction)}`);
|
|
353
|
+
lines.push(`- **next command:** ${markdownInlineCode(workflow.nextCommand)}`);
|
|
302
354
|
if (workflow.scopeStatus)
|
|
303
355
|
lines.push(`- **scope:** ${workflow.scopeStatus}`);
|
|
304
356
|
if (workflow.proofStatus)
|
|
305
357
|
lines.push(`- **proof:** ${workflow.proofStatus}`);
|
|
358
|
+
if (workflow.proofSufficiencyStatus) {
|
|
359
|
+
lines.push(`- **proof sufficiency:** ${workflow.proofSufficiencyStatus}`);
|
|
360
|
+
}
|
|
306
361
|
if (workflow.reviewerDecision)
|
|
307
362
|
lines.push(`- **reviewer decision:** ${workflow.reviewerDecision}`);
|
|
308
363
|
if (workflow.riskDeltaDirection)
|
|
@@ -325,7 +380,7 @@ function pushList(lines, values, empty) {
|
|
|
325
380
|
return;
|
|
326
381
|
}
|
|
327
382
|
for (const value of values)
|
|
328
|
-
lines.push(`- ${value}`);
|
|
383
|
+
lines.push(`- ${escapeMarkdownText(value)}`);
|
|
329
384
|
}
|
|
330
385
|
function pushCodeList(lines, values) {
|
|
331
386
|
if (values.length === 0) {
|
|
@@ -333,7 +388,37 @@ function pushCodeList(lines, values) {
|
|
|
333
388
|
return;
|
|
334
389
|
}
|
|
335
390
|
for (const value of values)
|
|
336
|
-
lines.push(`-
|
|
391
|
+
lines.push(`- ${markdownInlineCode(value)}`);
|
|
392
|
+
}
|
|
393
|
+
function pushTeamProofRecipes(lines, receipt) {
|
|
394
|
+
const recipes = receipt.teamProofRecipes ?? [];
|
|
395
|
+
if (recipes.length === 0) {
|
|
396
|
+
lines.push('- No Team Proof Recipes matched this receipt.');
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
for (const recipe of recipes) {
|
|
400
|
+
lines.push(`- **recipe:** ${markdownInlineCode(recipe.id)}`);
|
|
401
|
+
lines.push(` - matched files: ${markdownInlineList(recipe.matchedFiles)}`);
|
|
402
|
+
lines.push(` - required reviewers: ${markdownInlineList(recipe.requiredReviewers ?? [])}`);
|
|
403
|
+
lines.push(` - recipe drift: ${markdownInlineList(recipe.forbiddenTouched ?? [])}`);
|
|
404
|
+
lines.push(` - recipe proof gaps: ${markdownInlineList(recipeGapsForRecipe(recipe))}`);
|
|
405
|
+
}
|
|
406
|
+
if (receipt.requiredReviewers?.length) {
|
|
407
|
+
lines.push(`- **required reviewers:** ${markdownInlineList(receipt.requiredReviewers)}`);
|
|
408
|
+
}
|
|
409
|
+
if (receipt.recipeDrift?.length) {
|
|
410
|
+
lines.push(`- **recipe drift:** ${markdownInlineList(receipt.recipeDrift)}`);
|
|
411
|
+
}
|
|
412
|
+
if (receipt.recipeGaps?.length) {
|
|
413
|
+
lines.push(`- **recipe gaps:** ${markdownInlineList(receipt.recipeGaps)}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
function recipeGapsForRecipe(recipe) {
|
|
417
|
+
return [
|
|
418
|
+
...(recipe.missingCommands ?? []).map((command) => `missing: ${command}`),
|
|
419
|
+
...(recipe.failedCommands ?? []).map((command) => `failed: ${command}`),
|
|
420
|
+
...(recipe.staleCommands ?? []).map((command) => `stale: ${command}`),
|
|
421
|
+
];
|
|
337
422
|
}
|
|
338
423
|
function pushCommandEvidence(lines, values) {
|
|
339
424
|
if (values.length === 0) {
|
|
@@ -343,14 +428,72 @@ function pushCommandEvidence(lines, values) {
|
|
|
343
428
|
for (const value of values)
|
|
344
429
|
lines.push(formatCommandEvidence(value));
|
|
345
430
|
}
|
|
431
|
+
function pushRequirementEvidence(lines, values) {
|
|
432
|
+
if (values.length === 0) {
|
|
433
|
+
lines.push('- No proof requirements were evaluated.');
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
for (const value of values)
|
|
437
|
+
lines.push(formatRequirementEvidence(value));
|
|
438
|
+
}
|
|
439
|
+
function pushReplayEvents(lines, values) {
|
|
440
|
+
if (values.length === 0) {
|
|
441
|
+
lines.push('- No proof replay events recorded.');
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
for (const value of values)
|
|
445
|
+
lines.push(formatReplayEvent(value));
|
|
446
|
+
}
|
|
447
|
+
function formatReplayEvent(value) {
|
|
448
|
+
const command = value.command ? ` ${markdownInlineCode(value.command)}` : '';
|
|
449
|
+
const source = value.source ? ` source: ${value.source}.` : '';
|
|
450
|
+
const changedAfter = value.changedAfterProof && value.changedAfterProof.length > 0
|
|
451
|
+
? ` changed after proof: ${markdownInlineList(value.changedAfterProof)}.`
|
|
452
|
+
: '';
|
|
453
|
+
const completedAt = value.completedAt ? ` completed: ${escapeMarkdownText(value.completedAt)}.` : '';
|
|
454
|
+
return `- **${value.status} ${value.kind}:**${command} ${escapeMarkdownText(value.summary)}${source}${changedAfter}${completedAt}`;
|
|
455
|
+
}
|
|
456
|
+
function formatRequirementEvidence(value) {
|
|
457
|
+
const files = value.files.length > 0 ? value.files.join(', ') : 'contract-only';
|
|
458
|
+
const commands = value.requiredCommands.length > 0 ? value.requiredCommands.join('; ') : 'no command required';
|
|
459
|
+
const matched = value.matchedCommands.length > 0 ? value.matchedCommands.join('; ') : 'none';
|
|
460
|
+
const gaps = value.gaps.length > 0 ? ` gaps: ${value.gaps.join('; ')}` : '';
|
|
461
|
+
return `- **${value.status} ${value.surface}:** ${escapeMarkdownText(files)}; required: ${escapeMarkdownText(commands)}; matched: ${escapeMarkdownText(matched)}.${escapeMarkdownText(gaps)}`;
|
|
462
|
+
}
|
|
346
463
|
function formatCommandEvidence(value) {
|
|
347
464
|
const state = value.fresh ? 'fresh' : value.staleReason ? 'stale' : value.status;
|
|
348
465
|
const exit = typeof value.exitCode === 'number' ? ` exit ${value.exitCode}` : ' no exit code';
|
|
349
466
|
const duration = typeof value.durationMs === 'number' ? `, ${value.durationMs}ms` : '';
|
|
350
|
-
const
|
|
351
|
-
const
|
|
352
|
-
const
|
|
353
|
-
|
|
467
|
+
const source = value.source ? `, source ${value.source}` : '';
|
|
468
|
+
const log = value.logPath ? `, log ${markdownInlineCode(value.logPath)}` : '';
|
|
469
|
+
const summary = value.outputSummary ? ` - ${escapeMarkdownText(value.outputSummary)}` : '';
|
|
470
|
+
const stale = value.staleReason ? ` (${escapeMarkdownText(value.staleReason)})` : '';
|
|
471
|
+
return `- **${value.status} ${state}:** ${markdownInlineCode(value.command)} (${exit}${duration}${source}${log})${stale}${summary}`;
|
|
472
|
+
}
|
|
473
|
+
function inlineList(values) {
|
|
474
|
+
return values.length > 0 ? values.join(', ') : 'none';
|
|
475
|
+
}
|
|
476
|
+
function proofReplayForReceipt(receipt) {
|
|
477
|
+
return (receipt.proofReplay ?? {
|
|
478
|
+
status: 'needs-proof',
|
|
479
|
+
summary: 'No proof replay evidence recorded.',
|
|
480
|
+
events: [],
|
|
481
|
+
changedAfterProof: [],
|
|
482
|
+
replayCommand: 'projscan prove --changed --format markdown',
|
|
483
|
+
receiptFingerprint: 'missing',
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
function proofSufficiencyForReceipt(receipt) {
|
|
487
|
+
return (receipt.proofSufficiency ?? {
|
|
488
|
+
status: 'missing',
|
|
489
|
+
summary: 'No proof sufficiency evidence recorded.',
|
|
490
|
+
requirements: [],
|
|
491
|
+
gaps: ['No proof sufficiency evidence recorded.'],
|
|
492
|
+
weakRequirements: [],
|
|
493
|
+
missingRequirements: [],
|
|
494
|
+
staleRequirements: [],
|
|
495
|
+
failedRequirements: [],
|
|
496
|
+
});
|
|
354
497
|
}
|
|
355
498
|
function unique(values) {
|
|
356
499
|
return [...new Set(values)];
|
|
@@ -376,4 +519,10 @@ function parseDurationMs(value) {
|
|
|
376
519
|
}
|
|
377
520
|
return parsed;
|
|
378
521
|
}
|
|
522
|
+
function parseProofLedgerSource(value) {
|
|
523
|
+
if (value === 'prove-record' || value === 'prove-run' || value === 'mission' || value === 'external') {
|
|
524
|
+
return value;
|
|
525
|
+
}
|
|
526
|
+
throw new Error('record-source must be prove-record, prove-run, mission, or external');
|
|
527
|
+
}
|
|
379
528
|
//# sourceMappingURL=prove.js.map
|