projscan 4.2.0 → 4.3.1
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 +93 -26
- package/dist/cli/commands/missionProof.d.ts +1 -0
- package/dist/cli/commands/missionProof.js +478 -0
- package/dist/cli/commands/missionProof.js.map +1 -0
- package/dist/cli/commands/start.js +18 -0
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/missionOutcome.d.ts +2 -0
- package/dist/core/missionOutcome.js +219 -0
- package/dist/core/missionOutcome.js.map +1 -0
- package/dist/core/missionProof.d.ts +6 -0
- package/dist/core/missionProof.js +92 -0
- package/dist/core/missionProof.js.map +1 -0
- package/dist/core/missionProofBaseline.d.ts +10 -0
- package/dist/core/missionProofBaseline.js +131 -0
- package/dist/core/missionProofBaseline.js.map +1 -0
- package/dist/core/missionProofMarkdown.d.ts +2 -0
- package/dist/core/missionProofMarkdown.js +80 -0
- package/dist/core/missionProofMarkdown.js.map +1 -0
- package/dist/core/missionProofSummary.d.ts +2 -0
- package/dist/core/missionProofSummary.js +16 -0
- package/dist/core/missionProofSummary.js.map +1 -0
- package/dist/core/start.d.ts +1 -0
- package/dist/core/start.js +9 -4
- package/dist/core/start.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools/start.js +5 -0
- package/dist/mcp/tools/start.js.map +1 -1
- package/dist/projscan-sbom.cdx.json +6 -6
- package/dist/tool-manifest.json +6 -2
- package/dist/types.d.ts +91 -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 +23 -1
- package/docs/demos/projscan-4-1-demo.html +78 -94
- package/docs/demos/projscan-mission-control.tape +13 -0
- package/docs/demos/projscan-mission-proof.tape +25 -0
- 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 +9 -2
- package/scripts/capture-vhs-demos.mjs +80 -0
|
@@ -422,34 +422,34 @@
|
|
|
422
422
|
<section class="hero" aria-label="projscan Mission Control">
|
|
423
423
|
<div class="intro">
|
|
424
424
|
<div>
|
|
425
|
-
<p class="eyebrow">
|
|
426
|
-
<h1>
|
|
425
|
+
<p class="eyebrow">Mission Outcome Loop</p>
|
|
426
|
+
<h1>Resume from real proof.</h1>
|
|
427
427
|
<p class="lead">
|
|
428
|
-
projscan routes a developer goal
|
|
429
|
-
|
|
430
|
-
|
|
428
|
+
projscan routes a developer goal, saves the mission, reads the
|
|
429
|
+
proof state, and tells the next agent what changed, what remains,
|
|
430
|
+
and whether the work is ready for version review.
|
|
431
431
|
</p>
|
|
432
432
|
<div class="pills" aria-label="Product capabilities">
|
|
433
433
|
<span class="pill">Mission Control</span>
|
|
434
434
|
<span class="pill">Local-first</span>
|
|
435
435
|
<span class="pill">MCP-ready</span>
|
|
436
|
-
<span class="pill">
|
|
437
|
-
<span class="pill">
|
|
436
|
+
<span class="pill">Outcome resume</span>
|
|
437
|
+
<span class="pill">Proof report</span>
|
|
438
438
|
</div>
|
|
439
439
|
</div>
|
|
440
440
|
|
|
441
441
|
<div class="metric-row" aria-label="Release candidate signals">
|
|
442
442
|
<div class="metric">
|
|
443
|
-
<strong>1
|
|
444
|
-
<span>
|
|
443
|
+
<strong>1 bundle</strong>
|
|
444
|
+
<span>mission plus proof</span>
|
|
445
445
|
</div>
|
|
446
446
|
<div class="metric">
|
|
447
|
-
<strong>
|
|
448
|
-
<span>
|
|
447
|
+
<strong>45</strong>
|
|
448
|
+
<span>MCP tools</span>
|
|
449
449
|
</div>
|
|
450
450
|
<div class="metric">
|
|
451
|
-
<strong>
|
|
452
|
-
<span>
|
|
451
|
+
<strong>11 / 12</strong>
|
|
452
|
+
<span>AST adapters / languages</span>
|
|
453
453
|
</div>
|
|
454
454
|
</div>
|
|
455
455
|
</div>
|
|
@@ -459,83 +459,68 @@
|
|
|
459
459
|
<span class="dot red"></span>
|
|
460
460
|
<span class="dot amber"></span>
|
|
461
461
|
<span class="dot green"></span>
|
|
462
|
-
<span class="terminal-title">projscan start
|
|
462
|
+
<span class="terminal-title">projscan start --mission</span>
|
|
463
463
|
</div>
|
|
464
464
|
<div class="terminal-body">
|
|
465
465
|
<span class="line"
|
|
466
466
|
><span class="prompt">$</span>
|
|
467
467
|
<span class="cmd"
|
|
468
|
-
>projscan start --
|
|
469
|
-
token loader"</span
|
|
468
|
+
>projscan start --mission .projscan/mission</span
|
|
470
469
|
></span
|
|
471
470
|
>
|
|
472
471
|
<span class="line dim">ProjScan Mission Control</span>
|
|
473
|
-
<span class="line">
|
|
474
|
-
<span class="line">Status: <span class="
|
|
472
|
+
<span class="line">Mission: .projscan/mission</span>
|
|
473
|
+
<span class="line">Status: <span class="success">passed</span></span>
|
|
475
474
|
<span class="line"
|
|
476
|
-
>
|
|
477
|
-
<span class="notice">
|
|
475
|
+
>Outcome:
|
|
476
|
+
<span class="notice">proof passed after 3 commands</span></span
|
|
478
477
|
>
|
|
479
478
|
<span class="line dim"
|
|
480
|
-
>
|
|
479
|
+
>read proof-logs/summary.json and status.jsonl</span
|
|
481
480
|
>
|
|
482
481
|
|
|
483
482
|
<div class="term-section">
|
|
484
|
-
<span class="line term-heading">
|
|
483
|
+
<span class="line term-heading">What Changed</span>
|
|
485
484
|
<span class="line"
|
|
486
|
-
|
|
487
|
-
json</span
|
|
485
|
+
>- Mission proof passed after 3 command(s).</span
|
|
488
486
|
>
|
|
489
487
|
<span class="line"
|
|
490
|
-
|
|
488
|
+
>- 1 reviewer decision recorded.</span
|
|
491
489
|
>
|
|
492
|
-
<span class="line"
|
|
490
|
+
<span class="line">- 0 failed gates remain.</span>
|
|
493
491
|
</div>
|
|
494
492
|
|
|
495
493
|
<div class="term-section">
|
|
496
|
-
<span class="line term-heading">
|
|
494
|
+
<span class="line term-heading">What Remains</span>
|
|
497
495
|
<span class="line success"
|
|
498
|
-
>
|
|
496
|
+
>Run ./review.sh and choose a reviewer reply.</span
|
|
499
497
|
>
|
|
500
498
|
<span class="line success"
|
|
501
|
-
>
|
|
502
|
-
>
|
|
503
|
-
<span class="line success"
|
|
504
|
-
>projscan start --next-tool-call --intent "..."</span
|
|
505
|
-
>
|
|
506
|
-
<span class="line success"
|
|
507
|
-
>projscan start --task-card --intent "..."</span
|
|
499
|
+
>Version candidate: review_candidate</span
|
|
508
500
|
>
|
|
501
|
+
</div>
|
|
502
|
+
|
|
503
|
+
<div class="term-section">
|
|
504
|
+
<span class="line term-heading">Outcome Commands</span>
|
|
509
505
|
<span class="line success"
|
|
510
|
-
>projscan start --mission
|
|
506
|
+
>projscan start --mission .projscan/mission</span
|
|
511
507
|
>
|
|
512
508
|
<span class="line success"
|
|
513
|
-
>projscan
|
|
509
|
+
>projscan mission-proof --mission .projscan/mission</span
|
|
514
510
|
>
|
|
515
511
|
<span class="line success"
|
|
516
|
-
>projscan
|
|
517
|
-
"..."</span
|
|
512
|
+
>projscan mission-proof --baseline manual-runs.json</span
|
|
518
513
|
>
|
|
519
|
-
<span class="line dim">
|
|
514
|
+
<span class="line dim">all source stays local</span>
|
|
520
515
|
</div>
|
|
521
516
|
|
|
522
517
|
<div class="term-section">
|
|
523
|
-
<span class="line term-heading">
|
|
518
|
+
<span class="line term-heading">Proof Evidence</span>
|
|
524
519
|
<span class="line success"
|
|
525
|
-
|
|
520
|
+
>proof-logs/summary.json: passed</span
|
|
526
521
|
>
|
|
527
522
|
<span class="line success"
|
|
528
|
-
|
|
529
|
-
>
|
|
530
|
-
</div>
|
|
531
|
-
|
|
532
|
-
<div class="term-section">
|
|
533
|
-
<span class="line term-heading">Done When</span>
|
|
534
|
-
<span class="line"
|
|
535
|
-
>- Search returns an exact symbol or file path</span
|
|
536
|
-
>
|
|
537
|
-
<span class="line"
|
|
538
|
-
>- Impact is reviewed before code edits</span
|
|
523
|
+
>proof-logs/status.jsonl: 3 rows</span
|
|
539
524
|
>
|
|
540
525
|
</div>
|
|
541
526
|
|
|
@@ -543,8 +528,8 @@
|
|
|
543
528
|
<span class="line term-heading">Review Gate</span>
|
|
544
529
|
<span class="line">capture: git status --short</span>
|
|
545
530
|
<span class="line">capture: git diff --stat</span>
|
|
546
|
-
<span class="line success">reply:
|
|
547
|
-
<span class="line warn">
|
|
531
|
+
<span class="line success">reply: review version candidate</span>
|
|
532
|
+
<span class="line warn">do not publish until approved</span>
|
|
548
533
|
</div>
|
|
549
534
|
</div>
|
|
550
535
|
</section>
|
|
@@ -553,7 +538,7 @@
|
|
|
553
538
|
<section class="grid" aria-label="New developer workflows">
|
|
554
539
|
<article class="card">
|
|
555
540
|
<span class="label green">Goal routing</span>
|
|
556
|
-
<h2>Ask in
|
|
541
|
+
<h2>Ask in plain language.</h2>
|
|
557
542
|
<p>
|
|
558
543
|
Route privacy, merge readiness, refactor risk, local setup,
|
|
559
544
|
ownership, dependency, release, and handoff questions to the right
|
|
@@ -561,21 +546,21 @@
|
|
|
561
546
|
</p>
|
|
562
547
|
</article>
|
|
563
548
|
<article class="card">
|
|
564
|
-
<span class="label blue">
|
|
565
|
-
<h2>Start from
|
|
549
|
+
<span class="label blue">Outcome resume</span>
|
|
550
|
+
<h2>Start from saved proof.</h2>
|
|
566
551
|
<p>
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
552
|
+
<code>projscan start --mission</code> reads the bundle proof state
|
|
553
|
+
and gives the next agent a focused "what changed / what remains"
|
|
554
|
+
handoff.
|
|
570
555
|
</p>
|
|
571
556
|
</article>
|
|
572
557
|
<article class="card">
|
|
573
|
-
<span class="label amber">
|
|
574
|
-
<h2>
|
|
558
|
+
<span class="label amber">Proof report</span>
|
|
559
|
+
<h2>Measure the saved work.</h2>
|
|
575
560
|
<p>
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
561
|
+
<code>projscan mission-proof</code> reports proof completion,
|
|
562
|
+
reviewer approvals, reruns, failed gates, time saved, and local
|
|
563
|
+
risk avoided.
|
|
579
564
|
</p>
|
|
580
565
|
</article>
|
|
581
566
|
</section>
|
|
@@ -583,13 +568,13 @@
|
|
|
583
568
|
<section class="proof" id="proof" aria-label="Proof and dependency view">
|
|
584
569
|
<div class="proof-header">
|
|
585
570
|
<div>
|
|
586
|
-
<p class="eyebrow">
|
|
587
|
-
<h2>
|
|
571
|
+
<p class="eyebrow">Proof, review, and adoption evidence</p>
|
|
572
|
+
<h2>Close the loop.</h2>
|
|
588
573
|
</div>
|
|
589
574
|
<p>
|
|
590
|
-
Developers and agents can
|
|
591
|
-
|
|
592
|
-
|
|
575
|
+
Developers and agents can resume from a saved mission bundle,
|
|
576
|
+
summarize pass/fail evidence, and compare local proof against a
|
|
577
|
+
manual baseline without sending source code anywhere.
|
|
593
578
|
</p>
|
|
594
579
|
</div>
|
|
595
580
|
|
|
@@ -599,33 +584,32 @@
|
|
|
599
584
|
<span class="dot red"></span>
|
|
600
585
|
<span class="dot amber"></span>
|
|
601
586
|
<span class="dot green"></span>
|
|
602
|
-
<span class="terminal-title">projscan
|
|
587
|
+
<span class="terminal-title">projscan mission-proof</span>
|
|
603
588
|
</div>
|
|
604
589
|
<div class="terminal-body">
|
|
605
590
|
<span class="line"
|
|
606
591
|
><span class="prompt">$</span>
|
|
607
592
|
<span class="cmd"
|
|
608
|
-
>projscan
|
|
609
|
-
|
|
593
|
+
>projscan mission-proof --mission .projscan/mission --format
|
|
594
|
+
json</span
|
|
610
595
|
></span
|
|
611
596
|
>
|
|
612
|
-
<span class="line dim">
|
|
597
|
+
<span class="line dim">Local proof summary</span>
|
|
613
598
|
<span class="line"> </span>
|
|
614
|
-
<span class="line term-heading">{"
|
|
599
|
+
<span class="line term-heading">{"passed":1,"failed":0,</span>
|
|
615
600
|
<span class="line success"
|
|
616
|
-
> "
|
|
601
|
+
> "reruns":0,"reviewerApprovals":1}</span
|
|
617
602
|
>
|
|
618
603
|
<span class="line"> </span>
|
|
619
|
-
<span class="line term-heading">
|
|
604
|
+
<span class="line term-heading">Risk avoided</span>
|
|
620
605
|
<span class="line success"
|
|
621
|
-
>-
|
|
606
|
+
>- proof gate passed before release</span
|
|
622
607
|
>
|
|
623
608
|
<span class="line success"
|
|
624
|
-
>-
|
|
609
|
+
>- version review is safe to request</span
|
|
625
610
|
>
|
|
626
|
-
<span class="line success">- [ready] run_proof proof-2</span>
|
|
627
611
|
<span class="line notice"
|
|
628
|
-
>
|
|
612
|
+
>Next: projscan start --mission .projscan/mission</span
|
|
629
613
|
>
|
|
630
614
|
</div>
|
|
631
615
|
</section>
|
|
@@ -634,33 +618,33 @@
|
|
|
634
618
|
<div class="signal">
|
|
635
619
|
<span class="tag green">Verify</span>
|
|
636
620
|
<span>
|
|
637
|
-
<strong>
|
|
638
|
-
<code>--
|
|
639
|
-
|
|
621
|
+
<strong>Outcome resume</strong>
|
|
622
|
+
<code>--mission</code> reads <code>summary.json</code>, status
|
|
623
|
+
rows, and reviewer decisions.
|
|
640
624
|
</span>
|
|
641
625
|
</div>
|
|
642
626
|
<div class="signal">
|
|
643
627
|
<span class="tag blue">MCP</span>
|
|
644
628
|
<span>
|
|
645
|
-
<strong>MCP
|
|
646
|
-
<code
|
|
647
|
-
|
|
629
|
+
<strong>MCP start input</strong>
|
|
630
|
+
<code>mission_dir</code> carries the same proof outcome to
|
|
631
|
+
agent clients.
|
|
648
632
|
</span>
|
|
649
633
|
</div>
|
|
650
634
|
<div class="signal">
|
|
651
635
|
<span class="tag amber">List</span>
|
|
652
636
|
<span>
|
|
653
|
-
<strong>
|
|
654
|
-
<code
|
|
655
|
-
|
|
637
|
+
<strong>Proof summary</strong>
|
|
638
|
+
<code>mission-proof</code> reports completion, reruns, failed
|
|
639
|
+
gates, and approvals.
|
|
656
640
|
</span>
|
|
657
641
|
</div>
|
|
658
642
|
<div class="signal">
|
|
659
643
|
<span class="tag red">Gate</span>
|
|
660
644
|
<span>
|
|
661
|
-
<strong>
|
|
662
|
-
|
|
663
|
-
|
|
645
|
+
<strong>Version review</strong>
|
|
646
|
+
Outcome data says whether to request review or keep fixing
|
|
647
|
+
failed proof.
|
|
664
648
|
</span>
|
|
665
649
|
</div>
|
|
666
650
|
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Output docs/projscan-mission-control.gif
|
|
2
|
+
|
|
3
|
+
Set Shell "bash"
|
|
4
|
+
Set FontSize 16
|
|
5
|
+
Set Width 1200
|
|
6
|
+
Set Height 720
|
|
7
|
+
Set Theme "Catppuccin Mocha"
|
|
8
|
+
Set TypingSpeed 35ms
|
|
9
|
+
Set Padding 16
|
|
10
|
+
|
|
11
|
+
Type "projscan start --shortcuts --intent 'is it safe to commit this change?'"
|
|
12
|
+
Enter
|
|
13
|
+
Sleep 12s
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Output docs/projscan-mission-proof.gif
|
|
2
|
+
|
|
3
|
+
Set Shell "bash"
|
|
4
|
+
Set FontSize 16
|
|
5
|
+
Set Width 1200
|
|
6
|
+
Set Height 720
|
|
7
|
+
Set Theme "Catppuccin Mocha"
|
|
8
|
+
Set TypingSpeed 35ms
|
|
9
|
+
Set Padding 16
|
|
10
|
+
|
|
11
|
+
Type "rm -rf .projscan/vhs-mission"
|
|
12
|
+
Enter
|
|
13
|
+
Sleep 500ms
|
|
14
|
+
|
|
15
|
+
Type "projscan start --save-mission .projscan/vhs-mission --intent 'is it safe to commit this change?'"
|
|
16
|
+
Enter
|
|
17
|
+
Sleep 10s
|
|
18
|
+
|
|
19
|
+
Type "projscan mission-proof --mission .projscan/vhs-mission --format markdown | sed -n '1,38p'"
|
|
20
|
+
Enter
|
|
21
|
+
Sleep 8s
|
|
22
|
+
|
|
23
|
+
Type "projscan start --mission .projscan/vhs-mission --handoff-prompt | sed -n '1,8p'"
|
|
24
|
+
Enter
|
|
25
|
+
Sleep 16s
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projscan",
|
|
3
3
|
"mcpName": "io.github.abhiyoheswaran1/projscan",
|
|
4
|
-
"version": "4.
|
|
5
|
-
"description": "Agent-first code intelligence. MCP server (2025-03-26) with AST
|
|
4
|
+
"version": "4.3.1",
|
|
5
|
+
"description": "Agent-first code intelligence. MCP server (2025-03-26) with 11 AST adapters covering 12 named languages: JavaScript, TypeScript, Python, Go, Java, Ruby, Rust, PHP, C#, Kotlin, Swift, and C++; repo understanding maps (projscan_understand), stable v3 semantic graph (projscan_semantic_graph), dataflow risk engine with bridge-helper detection (projscan_dataflow), code graph, file + per-function AST cyclomatic complexity, per-function fan-in + fan-out, coupling + cycle detection, structural PR diff with HTML reporter, coverage report with HTML reporter, intent-grounded one-call PR review (projscan_review with optional `intent` arg, new taint flows, contract changes, and newDataflowRisks) and long-running PR-watch mode with structured per-bucket deltas (projscan_review_watch), first-60-seconds workflow orientation (projscan_start), agent workplans (projscan_workplan), bug-hunt queues (projscan_bug_hunt), product-line planning (projscan_release_train), evidence packs (projscan_evidence_pack), regression planning (projscan_regression_plan), agent briefs (projscan_agent_brief), quality scorecards (projscan_quality_scorecard), and preflight with supply-chain IOC evidence, rule-driven fix suggestions + mechanical apply layer with rollback (projscan_apply_fix, projscan_fix_suggest, projscan_explain_issue), source-to-sink taint analysis (projscan_taint) with truncation reporting, transitive blast-radius analysis with cross-repo mode (projscan_impact for files and symbols), cross-repo workspace registration + intelligence (projscan_workspace_graph), per-function semantic search chunks (sub-file embeddings), per-rule confidence + severity drift + cost-summary analytics with live streaming (projscan_cost_summary), stable local analyzer + reporter plugin API (projscan_plugin, CLI --reporter, opt-in via PROJSCAN_PLUGINS_PREVIEW=1), monorepo workspace awareness with cross-package import policy + per-package dependencies / outdated / audit, BM25 + optional semantic search, cursor pagination, progress notifications, context-budgeted output, and a stable-surface CI guard. CLI on the side.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
@@ -18,11 +18,16 @@
|
|
|
18
18
|
"docs/PLUGIN-GALLERY.md",
|
|
19
19
|
"docs/ROADMAP.md",
|
|
20
20
|
"docs/demos/projscan-4-1-demo.html",
|
|
21
|
+
"docs/demos/projscan-mission-control.tape",
|
|
22
|
+
"docs/demos/projscan-mission-proof.tape",
|
|
21
23
|
"docs/plugin.schema.json",
|
|
22
24
|
"docs/projscan-mission-control.png",
|
|
25
|
+
"docs/projscan-mission-control.gif",
|
|
23
26
|
"docs/projscan-proof-router.png",
|
|
27
|
+
"docs/projscan-mission-proof.gif",
|
|
24
28
|
"docs/examples/plugins",
|
|
25
29
|
"scripts/capture-readme-assets.mjs",
|
|
30
|
+
"scripts/capture-vhs-demos.mjs",
|
|
26
31
|
"public/brand/baseframe-labs",
|
|
27
32
|
"public/.well-known/security.txt",
|
|
28
33
|
"CONTRIBUTING.md",
|
|
@@ -44,6 +49,8 @@
|
|
|
44
49
|
"bench": "node scripts/bench.mjs",
|
|
45
50
|
"bench:references": "node scripts/bench-references.mjs",
|
|
46
51
|
"docs:screenshots": "node scripts/capture-readme-assets.mjs",
|
|
52
|
+
"docs:demos": "npm run build && node scripts/capture-vhs-demos.mjs",
|
|
53
|
+
"docs:assets": "npm run docs:screenshots && npm run docs:demos",
|
|
47
54
|
"smoke:packed-install": "node scripts/packed-install-smoke.mjs",
|
|
48
55
|
"check:stability": "node scripts/check-stability.mjs",
|
|
49
56
|
"release:check": "node scripts/release-check.mjs",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
7
|
+
const cliPath = path.join(repoRoot, 'dist', 'cli', 'index.js');
|
|
8
|
+
const vhsBinDir = path.join(repoRoot, '.projscan', 'vhs-bin');
|
|
9
|
+
const vhsShimPath = path.join(vhsBinDir, 'projscan');
|
|
10
|
+
const vhsMissionDir = path.join(repoRoot, '.projscan', 'vhs-mission');
|
|
11
|
+
|
|
12
|
+
const tapes = [
|
|
13
|
+
{
|
|
14
|
+
name: 'Mission Control terminal demo',
|
|
15
|
+
tape: path.join(repoRoot, 'docs', 'demos', 'projscan-mission-control.tape'),
|
|
16
|
+
output: path.join(repoRoot, 'docs', 'projscan-mission-control.gif'),
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'Mission Proof terminal demo',
|
|
20
|
+
tape: path.join(repoRoot, 'docs', 'demos', 'projscan-mission-proof.tape'),
|
|
21
|
+
output: path.join(repoRoot, 'docs', 'projscan-mission-proof.gif'),
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const quoteForShell = (value) => `'${value.replaceAll("'", "'\"'\"'")}'`;
|
|
26
|
+
|
|
27
|
+
const fail = (message, status = 1) => {
|
|
28
|
+
console.error(message);
|
|
29
|
+
process.exit(status);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
if (!existsSync(cliPath)) {
|
|
33
|
+
fail('Missing dist/cli/index.js. Run `npm run build` before capturing VHS demos.');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const vhsVersion = spawnSync('vhs', ['--version'], { cwd: repoRoot, encoding: 'utf8' });
|
|
37
|
+
if (vhsVersion.status !== 0) {
|
|
38
|
+
fail('Missing `vhs`. Install it with `brew install vhs`, then run `npm run docs:demos`.');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const tape of tapes) {
|
|
42
|
+
if (!existsSync(tape.tape)) {
|
|
43
|
+
fail(`Missing VHS tape: ${path.relative(repoRoot, tape.tape)}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
mkdirSync(vhsBinDir, { recursive: true });
|
|
48
|
+
writeFileSync(vhsShimPath, `#!/usr/bin/env sh\nexec node ${quoteForShell(cliPath)} "$@"\n`);
|
|
49
|
+
chmodSync(vhsShimPath, 0o755);
|
|
50
|
+
|
|
51
|
+
const env = {
|
|
52
|
+
...process.env,
|
|
53
|
+
PATH: `${vhsBinDir}${path.delimiter}${process.env.PATH ?? ''}`,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
rmSync(vhsMissionDir, { recursive: true, force: true });
|
|
58
|
+
|
|
59
|
+
for (const tape of tapes) {
|
|
60
|
+
console.log(`Capturing ${tape.name} -> ${path.relative(repoRoot, tape.output)}`);
|
|
61
|
+
const result = spawnSync('vhs', [path.relative(repoRoot, tape.tape)], {
|
|
62
|
+
cwd: repoRoot,
|
|
63
|
+
env,
|
|
64
|
+
stdio: 'inherit',
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (result.status !== 0) {
|
|
68
|
+
fail(`VHS capture failed for ${path.relative(repoRoot, tape.tape)}`, result.status ?? 1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!existsSync(tape.output)) {
|
|
72
|
+
fail(`VHS did not write expected output: ${path.relative(repoRoot, tape.output)}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} finally {
|
|
76
|
+
rmSync(vhsMissionDir, { recursive: true, force: true });
|
|
77
|
+
rmSync(vhsBinDir, { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log('VHS demos captured.');
|