Repository navigation
Commit 03cdb68
fix: [#830] address re-review — split gitAvailable from isRepo + Set-based degraded + test isolation
Third pass on PR #831 after multi-reviewer re-review (Claude + CodeRabbit
+ cubic-ai). Three reviewers independently flagged the same MAJOR
regression.
1. MAJOR — `detectGit` masked "git missing" as "not a repo"
The previous commit made detectGit fail-safe by routing through
safeSpawnSync, but both "git binary missing" and "valid git but
cwd is not a repo" produced an identical `{ isRepo: false }`.
Because detectGit no longer threw, the .catch() at the call site
never fired — so the very telemetry signature this PR exists to
fix (437 users with no git) NEVER recorded "git" in the degraded
list. The PR's headline contract was broken.
Fix: add `gitAvailable` to the GitInfo interface. detectGit
returns `{ isRepo: false, gitAvailable: false }` when
safeSpawnSync returns null (binary missing), and
`{ isRepo: false, gitAvailable: true }` for the genuine non-repo
case. The execute() handler reads gitAvailable and explicitly
adds "git" to the degraded set, with a different output line
("✗ git binary not found in PATH (install git or add it to PATH)"
vs "✗ Not a git repository") so the LLM/user can act
differently.
2. MINOR — degraded list never deduplicated
Was `string[]` with `.push()` at every site. Each push was unique
by construction, but any future refactor that wraps a Dispatcher
call at two layers (or the new explicit "git" add() above
colliding with the .catch() backstop) would push twice. Changed
to `Set<string>` with `.add()` semantics. Idempotent.
3. MINOR — degraded metadata shape inconsistency
Was `degraded: string[] | undefined` — empty meant `undefined`.
Dashboard queries had to coalesce. Changed to always emit
`degraded: string[]` (empty array means "no degradation"), with
stable sort order for human-readable output. The output
"## Degraded Detections" section header now includes a count.
4. MAJOR (review #2) — test mutated process.env.PATH + process.cwd
The previous test set `process.env.PATH = empty-dir` to force
the missing-binary code path. Two hazards:
- `originalPath` can be undefined (env unset); restoring with
`process.env.PATH = undefined` sets PATH to literal "undefined".
- process.chdir is process-global; any concurrent test in the
same `bun test` run that reads cwd sees the empty tmp dir.
Replaced with a direct safeSpawnSync(["nonexistent-binary..."])
call — exercises the exact same code path (Bun.spawnSync throws
on missing binary, safeSpawnSync catches and returns null) with
zero global state mutation. Added a second test asserting
gitAvailable === true for the normal case.
Validation
- `tsgo --noEmit`: pass.
- `bun test test/tool/project-scan.test.ts`: 83 pass / 0 fail.
- Marker check: pass.
Reviewer notes
- CodeRabbit and cubic-ai both flagged the gitAvailable issue
inline on commit 7074b6c — three independent reviewers
converged on the same root cause.
- Gemini-3.1-pro and Minimax-m2.7 second opinions hung on
OpenRouter (kilo CLI queue saturation from prior session's
jobs). Substituted PR-resident bot reviewers (CodeRabbit +
cubic-ai) for the consensus signal.
Closes review feedback for PR #831 (third pass).
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>1 parent 7074b6c commit 03cdb68
2 files changed
Lines changed: 81 additions & 49 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
17 | 26 | | |
18 | 27 | | |
19 | 28 | | |
| |||
93 | 102 | | |
94 | 103 | | |
95 | 104 | | |
96 | | - | |
97 | | - | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
98 | 116 | | |
99 | 117 | | |
100 | 118 | | |
| |||
107 | 125 | | |
108 | 126 | | |
109 | 127 | | |
110 | | - | |
| 128 | + | |
111 | 129 | | |
112 | 130 | | |
113 | 131 | | |
| |||
491 | 509 | | |
492 | 510 | | |
493 | 511 | | |
494 | | - | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
495 | 519 | | |
496 | 520 | | |
497 | 521 | | |
498 | 522 | | |
499 | 523 | | |
500 | 524 | | |
501 | | - | |
| 525 | + | |
502 | 526 | | |
503 | 527 | | |
504 | 528 | | |
505 | | - | |
| 529 | + | |
506 | 530 | | |
507 | 531 | | |
508 | 532 | | |
509 | | - | |
| 533 | + | |
510 | 534 | | |
511 | 535 | | |
512 | 536 | | |
513 | | - | |
| 537 | + | |
514 | 538 | | |
515 | 539 | | |
516 | 540 | | |
517 | | - | |
| 541 | + | |
518 | 542 | | |
519 | 543 | | |
520 | 544 | | |
| |||
525 | 549 | | |
526 | 550 | | |
527 | 551 | | |
528 | | - | |
| 552 | + | |
529 | 553 | | |
530 | 554 | | |
531 | 555 | | |
532 | 556 | | |
533 | 557 | | |
534 | 558 | | |
535 | | - | |
| 559 | + | |
536 | 560 | | |
537 | 561 | | |
538 | 562 | | |
| |||
541 | 565 | | |
542 | 566 | | |
543 | 567 | | |
544 | | - | |
| 568 | + | |
545 | 569 | | |
546 | 570 | | |
547 | 571 | | |
| |||
550 | 574 | | |
551 | 575 | | |
552 | 576 | | |
553 | | - | |
| 577 | + | |
554 | 578 | | |
555 | 579 | | |
556 | 580 | | |
557 | 581 | | |
558 | | - | |
| 582 | + | |
559 | 583 | | |
560 | 584 | | |
561 | 585 | | |
562 | 586 | | |
563 | 587 | | |
564 | | - | |
| 588 | + | |
565 | 589 | | |
566 | 590 | | |
567 | 591 | | |
| |||
588 | 612 | | |
589 | 613 | | |
590 | 614 | | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
591 | 623 | | |
592 | 624 | | |
593 | 625 | | |
| |||
628 | 660 | | |
629 | 661 | | |
630 | 662 | | |
631 | | - | |
| 663 | + | |
632 | 664 | | |
633 | 665 | | |
634 | 666 | | |
| |||
737 | 769 | | |
738 | 770 | | |
739 | 771 | | |
740 | | - | |
| 772 | + | |
741 | 773 | | |
742 | 774 | | |
743 | 775 | | |
| |||
754 | 786 | | |
755 | 787 | | |
756 | 788 | | |
757 | | - | |
| 789 | + | |
758 | 790 | | |
759 | 791 | | |
760 | 792 | | |
| |||
791 | 823 | | |
792 | 824 | | |
793 | 825 | | |
794 | | - | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
795 | 831 | | |
796 | | - | |
| 832 | + | |
797 | 833 | | |
798 | 834 | | |
799 | 835 | | |
800 | | - | |
| 836 | + | |
801 | 837 | | |
802 | 838 | | |
803 | 839 | | |
804 | 840 | | |
805 | 841 | | |
806 | 842 | | |
807 | 843 | | |
| 844 | + | |
| 845 | + | |
808 | 846 | | |
809 | | - | |
810 | | - | |
811 | | - | |
| 847 | + | |
812 | 848 | | |
813 | 849 | | |
814 | | - | |
| 850 | + | |
815 | 851 | | |
816 | 852 | | |
817 | 853 | | |
| |||
831 | 867 | | |
832 | 868 | | |
833 | 869 | | |
834 | | - | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
835 | 874 | | |
836 | 875 | | |
837 | 876 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
123 | | - | |
| 123 | + | |
124 | 124 | | |
125 | 125 | | |
126 | 126 | | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
149 | 142 | | |
150 | 143 | | |
151 | 144 | | |
| |||
0 commit comments