projscan 3.0.6 → 3.0.7

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 CHANGED
@@ -9,9 +9,9 @@
9
9
 
10
10
  **Agent-first code intelligence.** An MCP server that lets AI coding agents (Claude Code, Codex, Cursor, Gemini, Windsurf, Cline, Continue, Zed — any MCP-aware client) query your codebase — with a CLI for humans and a local plugin layer for team-specific policy and reporting.
11
11
 
12
- [AI Agent Quick Start](#ai-agent-integration-mcp) · [CLI Quick Start](#quick-start) · [Commands](#commands) · [Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/GUIDE.md) · [Roadmap](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/ROADMAP.md)
12
+ [AI Agent Quick Start](#ai-agent-integration-mcp) · [CLI Quick Start](#quick-start) · [Commands](#commands) · [Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/GUIDE.md) · [Roadmap](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/ROADMAP.md)
13
13
 
14
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/projscan-reporter-plugin.png" alt="projscan reporter plugin running in a macOS-style terminal window with a team health summary" width="700">
14
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/projscan-reporter-plugin.png" alt="projscan reporter plugin running in a macOS-style terminal window with a team health summary" width="700">
15
15
 
16
16
  </div>
17
17
 
@@ -25,7 +25,7 @@ AI coding agents are becoming the primary interface to code. Today, when you ask
25
25
 
26
26
  The stable local plugin platform turns that same pipeline into a team substrate: analyzer plugins add project-specific findings, and reporter plugins render `doctor`, `analyze`, and `ci` in your team's own voice without changing the underlying scan.
27
27
 
28
- The 3.0.6 loop focuses on the first useful team PR and measured repeat use: `projscan init team` creates policy, CI, ownership, and baseline memory; `projscan evidence-pack --pr-comment` posts a compact verdict with trust calibration, top risks, a First Fix, owner routing, baseline trend memory, reviewer feedback prompts, and exact next commands; `projscan dogfood` checks whether that loop is ready across real repos.
28
+ The 3.0.7 loop focuses on the first useful team PR and measured repeat use: `projscan init team` creates policy, CI, ownership, and baseline memory; `projscan evidence-pack --pr-comment` posts a compact verdict with trust calibration, top risks, a First Fix, owner routing, baseline trend memory, reviewer feedback prompts, and exact next commands; `projscan dogfood` checks whether that loop is ready across real repos. `projscan trial` rolls those signals into an adoption verdict with first-fix, repeat-use, and website-proof follow-ups.
29
29
 
30
30
  Humans get the same thing through the CLI.
31
31
 
@@ -35,7 +35,7 @@ Humans get the same thing through the CLI.
35
35
  npx projscan
36
36
  ```
37
37
 
38
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/projscan-reporter-plugin.gif" alt="projscan doctor rendered through a local reporter plugin in a macOS-style terminal window" width="700">
38
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/projscan-reporter-plugin.gif" alt="projscan doctor rendered through a local reporter plugin in a macOS-style terminal window" width="700">
39
39
 
40
40
  Run `projscan doctor` for a focused health check:
41
41
 
@@ -43,7 +43,7 @@ Run `projscan doctor` for a focused health check:
43
43
  npx projscan doctor
44
44
  ```
45
45
 
46
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/npx%20projscan%20doctor.gif" alt="npx projscan doctor" width="700">
46
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/npx%20projscan%20doctor.gif" alt="npx projscan doctor" width="700">
47
47
 
48
48
  ## Install
49
49
 
@@ -78,7 +78,9 @@ projscan quality-scorecard --format json # Dimensioned quality view
78
78
  projscan release-train --format json # Product readiness plan
79
79
  projscan evidence-pack --website-prompt # Approval packet with product evidence
80
80
  projscan evidence-pack --pr-comment # PR comment with trust calibration + First Fix
81
+ projscan feedback init --output .projscan-feedback.json # Create reviewer feedback evidence
81
82
  projscan dogfood --repo ../api --repo ../web --format json # Multi-repo adoption proof loop
83
+ projscan trial --repo ../api --repo ../web --feedback .projscan-feedback.json --format json # Executive adoption-readiness report
82
84
  projscan regression-plan --level full # Risk-based verification matrix
83
85
  projscan handoff # Concise next-agent handoff
84
86
  projscan handoff --write docs/agent-handoff.md # Persist next-agent handoff artifact
@@ -107,9 +109,9 @@ projscan plugin test .projscan-plugins/policy.projscan-plugin.json
107
109
  PROJSCAN_PLUGINS_PREVIEW=1 projscan doctor --reporter team-radar
108
110
  ```
109
111
 
110
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/npx%20projscan%20--help.gif" alt="npx projscan --help" width="700">
112
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/npx%20projscan%20--help.gif" alt="npx projscan --help" width="700">
111
113
 
112
- For a comprehensive walkthrough, see the **[Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/GUIDE.md)**.
114
+ For a comprehensive walkthrough, see the **[Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/GUIDE.md)**.
113
115
 
114
116
  ## Commands
115
117
 
@@ -130,6 +132,8 @@ For a comprehensive walkthrough, see the **[Full Guide](https://github.com/abhiy
130
132
  | `projscan quality-scorecard` | Dimensioned quality view with health, security, tests, maintainability, coordination, and top risks |
131
133
  | `projscan release-train` | Plan upcoming product lines with readiness evidence |
132
134
  | `projscan evidence-pack` | Assemble approval evidence from planning, bug-hunt, workplan, preflight, trust calibration, First Fix, owner routing, and baseline trend memory |
135
+ | `projscan trial` | Produce one adoption-readiness report from onboarding, dogfood, feedback, trust signals, and website proof |
136
+ | `projscan feedback` | Capture measured reviewer feedback: minutes saved, prevented bad edits, false positives, and repeat PR use |
133
137
  | `projscan dogfood` | Evaluate 1+ real repos for PR-comment readiness, repeat-use readiness, MCP readiness, and reviewer feedback prompts |
134
138
  | `projscan regression-plan` | Build a smoke, focused, or full regression matrix from product risk signals |
135
139
  | `projscan handoff` | Concise next-agent handoff from the current workplan |
@@ -171,31 +175,31 @@ projscan --help
171
175
  <details>
172
176
  <summary><strong>projscan structure</strong> - Directory tree with file counts</summary>
173
177
 
174
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/npx%20projscan%20structure.gif" alt="npx projscan structure" width="700">
178
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/npx%20projscan%20structure.gif" alt="npx projscan structure" width="700">
175
179
  </details>
176
180
 
177
181
  <details>
178
182
  <summary><strong>projscan diagram</strong> - Architecture visualization</summary>
179
183
 
180
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/npx%20projscan%20diagram.gif" alt="npx projscan diagram" width="700">
184
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/npx%20projscan%20diagram.gif" alt="npx projscan diagram" width="700">
181
185
  </details>
182
186
 
183
187
  <details>
184
188
  <summary><strong>projscan dependencies</strong> - Dependency analysis</summary>
185
189
 
186
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/npx%20projscan%20dependencies.gif" alt="npx projscan dependencies" width="700">
190
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/npx%20projscan%20dependencies.gif" alt="npx projscan dependencies" width="700">
187
191
  </details>
188
192
 
189
193
  <details>
190
194
  <summary><strong>projscan explain</strong> - File explanation</summary>
191
195
 
192
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/npx%20projscan%20explain.gif" alt="npx projscan explain" width="700">
196
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/npx%20projscan%20explain.gif" alt="npx projscan explain" width="700">
193
197
  </details>
194
198
 
195
199
  <details>
196
200
  <summary><strong>projscan badge</strong> - Health badge generation</summary>
197
201
 
198
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/npx%20projscan%20badge.gif" alt="npx projscan badge" width="700">
202
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/npx%20projscan%20badge.gif" alt="npx projscan badge" width="700">
199
203
  </details>
200
204
 
201
205
  ### Output Formats
@@ -217,7 +221,7 @@ Run `projscan help` for the generated command-by-command support matrix.
217
221
 
218
222
  projscan can load local plugins from `.projscan-plugins/` when `PROJSCAN_PLUGINS_PREVIEW=1` is set. The environment flag is kept for explicit local-code opt-in. Analyzer plugins emit normal projscan issues; reporter plugins render supported CLI commands with team-specific output.
219
223
 
220
- **2.0 upgrade notes:** migrating from 1.x or authoring plugins? Start with the [2.0 Migration Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/2.0-MIGRATION.md), then use [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/PLUGIN-AUTHORING.md), the [Plugin Gallery](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/PLUGIN-GALLERY.md), and the [manifest schema](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/plugin.schema.json) as the stable contract.
224
+ **2.0 upgrade notes:** migrating from 1.x or authoring plugins? Start with the [2.0 Migration Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/2.0-MIGRATION.md), then use [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/PLUGIN-AUTHORING.md), the [Plugin Gallery](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/PLUGIN-GALLERY.md), and the [manifest schema](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/plugin.schema.json) as the stable contract.
221
225
 
222
226
  ```bash
223
227
  projscan plugin list
@@ -226,9 +230,9 @@ PROJSCAN_PLUGINS_PREVIEW=1 projscan doctor --reporter team-radar
226
230
  PROJSCAN_PLUGINS_PREVIEW=1 projscan ci --reporter team-radar --min-score 80
227
231
  ```
228
232
 
229
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/projscan-reporter-plugin.gif" alt="projscan local reporter plugin rendering a team health report" width="700">
233
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/projscan-reporter-plugin.gif" alt="projscan local reporter plugin rendering a team health report" width="700">
230
234
 
231
- Reporter plugins are intentionally CLI-only. MCP tools keep returning structured JSON-compatible payloads so agents can reason over stable data, while humans can get a polished local report for their team. Custom presentation, team-branded summaries, and white-label reports belong in reporter plugins rather than new core HTML theming flags. See [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/PLUGIN-AUTHORING.md) for manifest shape, `render(context)`, validation, and the trust model.
235
+ Reporter plugins are intentionally CLI-only. MCP tools keep returning structured JSON-compatible payloads so agents can reason over stable data, while humans can get a polished local report for their team. Custom presentation, team-branded summaries, and white-label reports belong in reporter plugins rather than new core HTML theming flags. See [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/PLUGIN-AUTHORING.md) for manifest shape, `render(context)`, validation, and the trust model.
232
236
 
233
237
  ### Options
234
238
 
@@ -389,7 +393,7 @@ If you read projscan's [Socket report](https://socket.dev/npm/package/projscan),
389
393
  ### Audit it yourself
390
394
 
391
395
  - **Source is open** at [github.com/abhiyoheswaran1/projscan](https://github.com/abhiyoheswaran1/projscan). The npm tarball matches the `dist/` produced by `npm run build` at the matching tag.
392
- - **Public API surface is locked** by `scripts/check-stability.mjs`, which runs in CI on every PR and fails on any rename or removal of an MCP tool, CLI command, or exit code. See [`docs/STABILITY.md`](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/STABILITY.md).
396
+ - **Public API surface is locked** by `scripts/check-stability.mjs`, which runs in CI on every PR and fails on any rename or removal of an MCP tool, CLI command, or exit code. See [`docs/STABILITY.md`](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/STABILITY.md).
393
397
  - **Run it offline:** `npm install -g projscan` followed by anything except `audit` and `--mode semantic` works without network.
394
398
  - **Drop privilege further:** in CI, run projscan in a sandbox that disallows network egress; everything except `audit` will pass.
395
399
 
@@ -417,11 +421,14 @@ The `--min-score 90` threshold is deliberately tight: a regression that drops th
417
421
  For adoption proof, run the product against multiple real repos and capture first-PR feedback:
418
422
 
419
423
  ```sh
420
- projscan dogfood --repo ../api --repo ../web --repo ../worker --format json
421
424
  projscan evidence-pack --pr-comment
425
+ projscan feedback init --output .projscan-feedback.json
426
+ projscan feedback add --file .projscan-feedback.json --repo api --pr https://github.com/acme/api/pull/42 --reviewer @alice --useful true --minutes-saved 10
427
+ projscan dogfood --repo ../api --repo ../web --repo ../worker --feedback .projscan-feedback.json --format json
428
+ projscan trial --repo ../api --repo ../web --repo ../worker --feedback .projscan-feedback.json --format json
422
429
  ```
423
430
 
424
- The dogfood report checks PR-comment readiness, repeat-use commands, MCP readiness, and the exact feedback questions a reviewer should answer before rollout.
431
+ The dogfood report checks PR-comment readiness, repeat-use commands, MCP readiness, measured minutes saved, prevented bad edits, false positives, and repeat PR usage before rollout.
425
432
 
426
433
  The hotspots projscan finds in itself are real signals — the reporters in particular have grown organically across releases and are candidates for a 2.0-era refactor (tracked in `docs/ROADMAP.md` "Under consideration"). We choose to ship the signal honestly rather than tune the score to hide it.
427
434
 
@@ -436,7 +443,7 @@ projscan ci --changed-only # Gate only on this PR's diff
436
443
  projscan ci --format sarif > projscan.sarif # SARIF for Code Scanning
437
444
  ```
438
445
 
439
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/npx%20projscan%20ci%20--min-score%2070.gif" alt="npx projscan ci --min-score 70" width="700">
446
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/npx%20projscan%20ci%20--min-score%2070.gif" alt="npx projscan ci --min-score 70" width="700">
440
447
 
441
448
  ### GitHub Action (recommended)
442
449
 
@@ -505,7 +512,7 @@ Fields:
505
512
  - `hotspots.limit` / `hotspots.since` - defaults for the `hotspots` command
506
513
  - `monorepo.importPolicy` - cross-package import allow/deny rules in monorepos *(0.14+)*
507
514
 
508
- See [`docs/GUIDE.md` → Configuration](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/GUIDE.md#configuration-projscanrc) for the full reference (field types, validation behavior, embedding config in `package.json`, monorepo `importPolicy` semantics).
515
+ See [`docs/GUIDE.md` → Configuration](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/GUIDE.md#configuration-projscanrc) for the full reference (field types, validation behavior, embedding config in `package.json`, monorepo `importPolicy` semantics).
509
516
 
510
517
  ## Tracking Health Over Time
511
518
 
@@ -518,7 +525,7 @@ projscan diff # Compare against baseline
518
525
  projscan diff --format markdown # Markdown diff for PRs
519
526
  ```
520
527
 
521
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/npx%20projscan%20diff%20--save-baseline.gif" alt="npx projscan diff --save-baseline" width="700">
528
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/npx%20projscan%20diff%20--save-baseline.gif" alt="npx projscan diff --save-baseline" width="700">
522
529
 
523
530
  ## Hotspots - Where to Fix First
524
531
 
@@ -607,7 +614,7 @@ Coverage is also automatically joined into `projscan hotspots` when one of those
607
614
 
608
615
  **This is the primary way to use projscan.** `projscan mcp` starts an [MCP](https://modelcontextprotocol.io) server over stdio so AI coding agents can query your codebase with real structural accuracy - not regex, not grep.
609
616
 
610
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.6/docs/projscan-agent-demo.gif" alt="projscan answering two agent questions: what breaks if I rename buildCodeGraph (impact analysis with definitions, direct callers, transitive reach), and where should I fix first (ranked hotspots with cyclomatic complexity)" width="700">
617
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.7/docs/projscan-agent-demo.gif" alt="projscan answering two agent questions: what breaks if I rename buildCodeGraph (impact analysis with definitions, direct callers, transitive reach), and where should I fix first (ranked hotspots with cyclomatic complexity)" width="700">
611
618
 
612
619
  Two questions an agent asks; structural answers in milliseconds. *"What breaks if I rename `buildCodeGraph`?"* → 31 direct callers, 97 files reachable. *"Where should I fix first?"* → ranked hotspots with AST cyclomatic complexity, churn, and ownership signals.
613
620
 
@@ -804,7 +811,7 @@ Capability is advertised under `experimental.fileChanged` on `initialize` so cli
804
811
  - **`projscan_apply_fix`** *(1.6)* - mechanically execute the safe fix templates. Default is dry-run; pass `confirm: true` to write. Atomic writes, per-apply rollback record at `.projscan-cache/rollbacks/<id>.json`. Reverse with `action: "rollback", rollback_id: ...`. Six templates supported at this release: `unused-dependency-*`, `missing-test-framework`, `missing-eslint`, `missing-prettier`, `missing-editorconfig`, `missing-readme`.
805
812
  - **`projscan_taint`** *(1.6)* - source-to-sink reachability over the per-function call graph. Built-in defaults cover common JS / Python sources (`process.env`, `req.body`, etc.) and sinks (`exec`, `eval`, `db.query`, etc.). Project-specific names go in `.projscanrc.json` `taint`. `projscan_review` automatically diffs taint flows between base and head and **blocks any PR that introduces a new flow**. In 3.0.2, review surfaces hardened `newDataflowRisks`, compact `graphEvidence`, and graph-readiness gates for safer handoff.
806
813
 
807
- Analyzer plugins can optionally read graph/dataflow context through `check(rootPath, files, context)` while staying on manifest schema v1. The packaged `graph-context` example shows `context.getSemanticGraph()` and `context.getDataflow()` in a real analyzer. For analyzer and reporter plugin authoring, manifest validation, `--reporter <name>`, and the trust model, see [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.6/docs/PLUGIN-AUTHORING.md).
814
+ Analyzer plugins can optionally read graph/dataflow context through `check(rootPath, files, context)` while staying on manifest schema v1. The packaged `graph-context` example shows `context.getSemanticGraph()` and `context.getDataflow()` in a real analyzer. For analyzer and reporter plugin authoring, manifest validation, `--reporter <name>`, and the trust model, see [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.7/docs/PLUGIN-AUTHORING.md).
808
815
 
809
816
  ### Context-window budgeting
810
817
 
@@ -0,0 +1 @@
1
+ export declare function registerFeedback(): void;
@@ -0,0 +1,176 @@
1
+ import path from 'node:path';
2
+ import chalk from 'chalk';
3
+ import { addFeedbackResponse, createFeedbackTemplate, summarizeFeedbackFile, } from '../../core/feedback.js';
4
+ import { assertFormatSupported, getRootPath, maybeCompactBanner, program, setupLogLevel, } from '../_shared.js';
5
+ const DEFAULT_FEEDBACK_FILE = '.projscan-feedback.json';
6
+ export function registerFeedback() {
7
+ const feedback = program
8
+ .command('feedback')
9
+ .description('Capture reviewer usefulness feedback for dogfood and market validation')
10
+ .action(async () => {
11
+ await runSummary({ file: DEFAULT_FEEDBACK_FILE }, 'feedback');
12
+ });
13
+ feedback
14
+ .command('init')
15
+ .description('Create a reusable .projscan-feedback.json artifact')
16
+ .option('--output <path>', 'feedback file to write', DEFAULT_FEEDBACK_FILE)
17
+ .option('--force', 'overwrite an existing feedback file')
18
+ .action(async (cmdOpts) => {
19
+ await runInit(cmdOpts);
20
+ });
21
+ feedback
22
+ .command('add')
23
+ .description('Append one real PR reviewer response to the feedback artifact')
24
+ .requiredOption('--repo <name>', 'repo name or path the feedback belongs to')
25
+ .requiredOption('--pr <url>', 'PR URL or stable PR id')
26
+ .requiredOption('--reviewer <handle>', 'reviewer handle or role')
27
+ .option('--file <path>', 'feedback file to update', DEFAULT_FEEDBACK_FILE)
28
+ .option('--useful <bool>', 'whether the PR comment was useful')
29
+ .option('--minutes-saved <count>', 'measured minutes saved by the PR comment', parseNonNegativeNumber)
30
+ .option('--prevented-bad-edit', 'record that projscan prevented a risky edit or missed review step')
31
+ .option('--owner-routing-clear <bool>', 'whether owner routing was clear')
32
+ .option('--next-command-clear <bool>', 'whether the next command was clear')
33
+ .option('--false-positive-rule <rule>', 'false-positive/noisy rule id, repeatable', collectString, [])
34
+ .option('--missing-signal <signal>', 'missing signal reviewers expected, repeatable', collectString, [])
35
+ .option('--noisy-finding <finding>', 'noisy finding description, repeatable', collectString, [])
36
+ .option('--note <text>', 'optional reviewer note')
37
+ .action(async (cmdOpts) => {
38
+ await runAdd(cmdOpts);
39
+ });
40
+ feedback
41
+ .command('summary')
42
+ .description('Summarize reviewer feedback evidence before dogfood')
43
+ .option('--file <path>', 'feedback file to read', DEFAULT_FEEDBACK_FILE)
44
+ .action(async (cmdOpts) => {
45
+ await runSummary(cmdOpts, 'feedback summary');
46
+ });
47
+ }
48
+ async function runInit(cmdOpts) {
49
+ setupLogLevel();
50
+ maybeCompactBanner();
51
+ const format = assertFormatSupported('feedback init');
52
+ try {
53
+ const result = await createFeedbackTemplate(resolveFromRoot(cmdOpts.output), { force: cmdOpts.force === true });
54
+ if (format === 'json') {
55
+ console.log(JSON.stringify(result, null, 2));
56
+ return;
57
+ }
58
+ console.log(chalk.green('Created feedback artifact: ') + result.path);
59
+ console.log(chalk.dim('Next: projscan feedback add --file ' + result.path + ' --repo <repo> --pr <url> --reviewer <handle> --useful true --minutes-saved 10'));
60
+ }
61
+ catch (error) {
62
+ printError(error);
63
+ }
64
+ }
65
+ async function runAdd(cmdOpts) {
66
+ setupLogLevel();
67
+ maybeCompactBanner();
68
+ const format = assertFormatSupported('feedback add');
69
+ try {
70
+ const filePath = resolveFromRoot(asString(cmdOpts.file) ?? DEFAULT_FEEDBACK_FILE);
71
+ const response = {
72
+ repo: requiredString(cmdOpts.repo, '--repo'),
73
+ pr: requiredString(cmdOpts.pr, '--pr'),
74
+ reviewer: requiredString(cmdOpts.reviewer, '--reviewer'),
75
+ useful: parseOptionalBool(cmdOpts.useful, '--useful'),
76
+ minutesSaved: typeof cmdOpts.minutesSaved === 'number' ? cmdOpts.minutesSaved : undefined,
77
+ preventedBadEdit: cmdOpts.preventedBadEdit === true,
78
+ ownerRoutingClear: parseOptionalBool(cmdOpts.ownerRoutingClear, '--owner-routing-clear'),
79
+ nextCommandClear: parseOptionalBool(cmdOpts.nextCommandClear, '--next-command-clear'),
80
+ falsePositiveRules: asStringArray(cmdOpts.falsePositiveRule),
81
+ missingSignals: asStringArray(cmdOpts.missingSignal),
82
+ noisyFindings: asStringArray(cmdOpts.noisyFinding),
83
+ note: asString(cmdOpts.note),
84
+ };
85
+ const artifact = await addFeedbackResponse(filePath, response);
86
+ if (format === 'json') {
87
+ console.log(JSON.stringify(artifact, null, 2));
88
+ return;
89
+ }
90
+ console.log(chalk.green('Recorded feedback response ') + chalk.bold(String(artifact.responses.length)));
91
+ console.log(chalk.dim('Next: projscan feedback summary --file ' + filePath + ' --format json'));
92
+ }
93
+ catch (error) {
94
+ printError(error);
95
+ }
96
+ }
97
+ async function runSummary(cmdOpts, commandName) {
98
+ setupLogLevel();
99
+ maybeCompactBanner();
100
+ const format = assertFormatSupported(commandName);
101
+ try {
102
+ const filePath = resolveFromRoot(cmdOpts.file ?? DEFAULT_FEEDBACK_FILE);
103
+ const report = await summarizeFeedbackFile(filePath);
104
+ if (format === 'json') {
105
+ console.log(JSON.stringify(report, null, 2));
106
+ return;
107
+ }
108
+ printSummary(report);
109
+ }
110
+ catch (error) {
111
+ printError(error);
112
+ }
113
+ }
114
+ function printSummary(report) {
115
+ console.log('');
116
+ console.log(chalk.bold('Reviewer Feedback'));
117
+ console.log(chalk.dim('────────────────────────────────────────'));
118
+ console.log(' responses: ' + report.responses);
119
+ console.log(' useful: ' + report.usefulResponses);
120
+ console.log(' repos / PRs: ' + report.distinctRepos + ' / ' + report.distinctPrs);
121
+ console.log(' repeated repos: ' + report.repeatUse.repeatedRepos + ' ' + (report.repeatUse.ready ? chalk.green('(ready)') : chalk.yellow('(needs repeat PRs)')));
122
+ console.log(' minutes saved: ' + report.minutesSaved.total + ' total, ' + report.minutesSaved.average + ' avg');
123
+ console.log(' bad edits saved: ' + report.preventedBadEdits);
124
+ console.log(' false positives: ' + report.falsePositive.totalReports);
125
+ console.log('');
126
+ console.log(chalk.bold('Next command'));
127
+ console.log(' ' + chalk.cyan(report.nextDogfoodCommand));
128
+ }
129
+ function resolveFromRoot(value) {
130
+ return path.isAbsolute(value) ? value : path.resolve(getRootPath(), value);
131
+ }
132
+ function collectString(value, previous) {
133
+ return [...previous, value];
134
+ }
135
+ function parseNonNegativeNumber(value) {
136
+ const parsed = Number(value);
137
+ if (!Number.isFinite(parsed) || parsed < 0)
138
+ throw new Error('Expected a non-negative number, got ' + value);
139
+ return parsed;
140
+ }
141
+ function parseOptionalBool(value, optionName) {
142
+ if (typeof value === 'undefined')
143
+ return undefined;
144
+ if (typeof value === 'boolean')
145
+ return value;
146
+ if (typeof value !== 'string')
147
+ throw new Error(optionName + ' expects true or false');
148
+ const normalized = value.trim().toLowerCase();
149
+ if (['true', 'yes', '1'].includes(normalized))
150
+ return true;
151
+ if (['false', 'no', '0'].includes(normalized))
152
+ return false;
153
+ throw new Error(optionName + ' expects true or false');
154
+ }
155
+ function requiredString(value, optionName) {
156
+ const result = asString(value);
157
+ if (!result)
158
+ throw new Error(optionName + ' is required');
159
+ return result;
160
+ }
161
+ function asString(value) {
162
+ if (typeof value !== 'string')
163
+ return undefined;
164
+ const trimmed = value.trim();
165
+ return trimmed.length > 0 ? trimmed : undefined;
166
+ }
167
+ function asStringArray(value) {
168
+ if (!Array.isArray(value))
169
+ return [];
170
+ return value.filter((item) => typeof item === 'string');
171
+ }
172
+ function printError(error) {
173
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
174
+ process.exit(1);
175
+ }
176
+ //# sourceMappingURL=feedback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.js","sourceRoot":"","sources":["../../../src/cli/commands/feedback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function registerTrial(): void;
@@ -0,0 +1,81 @@
1
+ import chalk from 'chalk';
2
+ import { assertFormatSupported, getRootPath, maybeCompactBanner, program, setupLogLevel, } from '../_shared.js';
3
+ import { readFeedbackFile } from '../../core/feedback.js';
4
+ import { computeTrialReport } from '../../core/trial.js';
5
+ export function registerTrial() {
6
+ program
7
+ .command('trial')
8
+ .description('Run the end-to-end local adoption trial report for a team or product')
9
+ .option('--repo <path>', 'repo path to evaluate, repeatable (default: current repo)', collectRepo, [])
10
+ .option('--target-repos <count>', 'target number of repos before adoption is considered proven', parsePositiveInt)
11
+ .option('--feedback <path>', 'JSON feedback artifact from projscan feedback')
12
+ .action(async (cmdOpts) => {
13
+ setupLogLevel();
14
+ maybeCompactBanner();
15
+ const format = assertFormatSupported('trial');
16
+ try {
17
+ const feedback = cmdOpts.feedback ? await readFeedbackFile(cmdOpts.feedback) : undefined;
18
+ const report = await computeTrialReport(getRootPath(), {
19
+ repos: cmdOpts.repo,
20
+ targetRepoCount: cmdOpts.targetRepos,
21
+ feedback,
22
+ feedbackPath: cmdOpts.feedback,
23
+ });
24
+ if (format === 'json') {
25
+ console.log(JSON.stringify(report, null, 2));
26
+ return;
27
+ }
28
+ printTrial(report);
29
+ }
30
+ catch (error) {
31
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
32
+ process.exit(1);
33
+ }
34
+ });
35
+ }
36
+ function printTrial(report) {
37
+ console.log('');
38
+ console.log(chalk.bold('projscan trial'));
39
+ console.log(chalk.dim('────────────────────────────────────────'));
40
+ console.log(' verdict: ' + colorVerdict(report.verdict)(report.verdict));
41
+ console.log(' summary: ' + report.summary);
42
+ console.log(' activation: ' + report.activation.status + ' (health ' + report.activation.healthScore + ', MCP ' + bool(report.activation.mcpReady) + ')');
43
+ console.log(' repos: ' + report.dogfood.totals.reposEvaluated + '/' + report.dogfood.targetRepoCount);
44
+ console.log(' feedback: ' + (report.feedback ? report.feedback.responses + ' response(s)' : 'not captured'));
45
+ console.log(' market: ' + report.dogfood.marketValidation.status);
46
+ console.log(' repeat PRs: ' + report.dogfood.marketValidation.repeatUse.distinctPrs + ' PR(s), ' + report.dogfood.marketValidation.repeatUse.repeatedRepos + ' repeated repo(s)');
47
+ console.log(' value: avg ' + report.dogfood.marketValidation.value.averageMinutesSaved + ' min, ' + report.dogfood.marketValidation.value.preventedBadEdits + ' risky edit(s) prevented');
48
+ if (report.decision.reasons.length > 0) {
49
+ console.log('');
50
+ console.log(chalk.bold('Decision reasons'));
51
+ for (const reason of report.decision.reasons)
52
+ console.log(' - ' + reason);
53
+ }
54
+ console.log('');
55
+ console.log(chalk.bold('Next commands'));
56
+ for (const action of report.nextCommands) {
57
+ console.log(' - ' + action.label + ': ' + chalk.cyan(action.command ?? action.tool ?? ''));
58
+ }
59
+ }
60
+ function collectRepo(value, previous) {
61
+ return [...previous, value];
62
+ }
63
+ function parsePositiveInt(value) {
64
+ const parsed = Number(value);
65
+ if (!Number.isInteger(parsed) || parsed < 1)
66
+ throw new Error('Expected a positive integer, got ' + value);
67
+ return parsed;
68
+ }
69
+ function colorVerdict(verdict) {
70
+ if (verdict === 'adopt')
71
+ return chalk.green;
72
+ if (verdict === 'setup')
73
+ return chalk.red;
74
+ if (verdict === 'tune')
75
+ return chalk.yellow;
76
+ return chalk.cyan;
77
+ }
78
+ function bool(value) {
79
+ return value ? 'ready' : 'not ready';
80
+ }
81
+ //# sourceMappingURL=trial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trial.js","sourceRoot":"","sources":["../../../src/cli/commands/trial.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -42,11 +42,13 @@ import { registerReleaseTrain } from './commands/releaseTrain.js';
42
42
  import { registerBugHunt } from './commands/bugHunt.js';
43
43
  import { registerEvidencePack } from './commands/evidencePack.js';
44
44
  import { registerDogfood } from './commands/dogfood.js';
45
+ import { registerFeedback } from './commands/feedback.js';
45
46
  import { registerRegressionPlan } from './commands/regressionPlan.js';
46
47
  import { registerAgentBrief } from './commands/agentBrief.js';
47
48
  import { registerQualityScorecard } from './commands/qualityScorecard.js';
48
49
  import { registerFirstRun, registerRecipes } from './commands/recipes.js';
49
50
  import { registerStart } from './commands/start.js';
51
+ import { registerTrial } from './commands/trial.js';
50
52
  import { registerHelp } from './commands/help.js';
51
53
  registerAnalyze();
52
54
  registerDoctor();
@@ -90,10 +92,12 @@ registerReleaseTrain();
90
92
  registerBugHunt();
91
93
  registerEvidencePack();
92
94
  registerDogfood();
95
+ registerFeedback();
93
96
  registerRegressionPlan();
94
97
  registerAgentBrief();
95
98
  registerQualityScorecard();
96
99
  registerStart();
100
+ registerTrial();
97
101
  registerRecipes();
98
102
  registerFirstRun();
99
103
  registerHelp();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}