claudeup 6.5.1 → 6.7.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/package.json +4 -4
- package/src/__tests__/active-closure.test.ts +184 -0
- package/src/__tests__/blackbox-active-closure.test.ts +119 -0
- package/src/__tests__/blackbox-convergence.test.ts +334 -0
- package/src/__tests__/blackbox-parity.test.ts +684 -0
- package/src/__tests__/blackbox-plugin-state.test.ts +523 -0
- package/src/__tests__/blackbox-tool-state.test.ts +669 -0
- package/src/__tests__/cli-apply-seams.test.ts +2 -0
- package/src/__tests__/cli-tool-commands.test.ts +1 -1
- package/src/__tests__/cli-tools-adapter.test.ts +294 -0
- package/src/__tests__/cli-update-view.test.ts +142 -2
- package/src/__tests__/content-drift.test.ts +60 -0
- package/src/__tests__/conventions-manager.test.ts +45 -45
- package/src/__tests__/enabled-not-installed.test.ts +2 -3
- package/src/__tests__/fixtures/tool-probe/brew-list-versions-tmux.txt +2 -0
- package/src/__tests__/fixtures/tool-probe/brew-outdated-behind-homebrew-spec.txt +29 -0
- package/src/__tests__/fixtures/tool-probe/brew-outdated-tmux-current.txt +7 -0
- package/src/__tests__/fixtures/tool-probe/brew-outdated-unknown-formula.txt +6 -0
- package/src/__tests__/fixtures/tool-probe/go-version-m-tmux-mcp.txt +27 -0
- package/src/__tests__/fixtures/tool-probe/npm-dist-tags-missing-scoped.txt +4 -0
- package/src/__tests__/fixtures/tool-probe/npm-dist-tags-openai-codex.txt +4 -0
- package/src/__tests__/fixtures/tool-probe/pypi-cowsay.txt +3 -0
- package/src/__tests__/fixtures/tool-probe/uv-receipt-browser-use.toml +10 -0
- package/src/__tests__/fixtures/tool-probe/uv-receipt-cowsay-git.toml +8 -0
- package/src/__tests__/fixtures/tool-probe/uv-receipt-cowsay-pinned.toml +8 -0
- package/src/__tests__/fixtures/tool-probe/uv-receipt-graphifyy.toml +7 -0
- package/src/__tests__/fixtures/tool-probe/uv-receipt-mcp.toml +6 -0
- package/src/__tests__/fixtures/tool-probe/uv-receipt-serena-agent.toml +9 -0
- package/src/__tests__/fixtures/tool-probe/uv-tool-list-outdated-pinned.txt +5 -0
- package/src/__tests__/fixtures/tool-probe/uv-tool-list-outdated.txt +11 -0
- package/src/__tests__/fixtures/tool-probe/uv-tool-list.txt +22 -0
- package/src/__tests__/{gitignore-prerun.test.ts → gitignore-check.test.ts} +8 -6
- package/src/__tests__/models-presets-marketplace.test.ts +141 -0
- package/src/__tests__/plugin-cli-argv.test.ts +1 -1
- package/src/__tests__/plugin-manager-fallback.test.ts +3 -5
- package/src/__tests__/plugin-row-text.test.ts +336 -0
- package/src/__tests__/resolver.test.ts +3 -3
- package/src/__tests__/scope-action.test.ts +69 -19
- package/src/__tests__/shell-script-callers.test.ts +8 -8
- package/src/__tests__/tool-probe.test.ts +1400 -0
- package/src/__tests__/update-apply.test.ts +283 -1
- package/src/__tests__/update-plan.test.ts +773 -31
- package/src/__tests__/version-unknown-state.test.ts +388 -0
- package/src/cli/router.ts +0 -5
- package/src/cli/update-view.ts +92 -12
- package/src/cli/update.ts +114 -38
- package/src/data/models-presets.ts +10 -11
- package/src/data/predefined-profiles.ts +7 -7
- package/src/services/active-closure.ts +117 -0
- package/src/services/catalog-cache-store.ts +6 -2
- package/src/services/claude-settings.ts +2 -174
- package/src/services/community-styles.ts +1 -1
- package/src/services/{gitignore-prerun.ts → gitignore-check.ts} +14 -10
- package/src/services/gitignore-fixer.ts +1 -1
- package/src/services/marketplace-refresh.ts +30 -0
- package/src/services/plugin-manager.ts +200 -283
- package/src/services/resolver.ts +7 -2
- package/src/services/tool-probe.ts +1637 -0
- package/src/services/toolchain.ts +97 -0
- package/src/services/update-engine.ts +220 -32
- package/src/services/update-plan.ts +640 -160
- package/src/services/version-snapshot.ts +1 -1
- package/src/types/bun.d.ts +6 -0
- package/src/ui/App.tsx +2 -27
- package/src/ui/adapters/cliToolsAdapter.ts +176 -0
- package/src/ui/adapters/pluginsAdapter.ts +57 -0
- package/src/ui/components/modals/ModalContainer.tsx +0 -26
- package/src/ui/hooks/index.ts +0 -1
- package/src/ui/hooks/useGitignoreModal.ts +2 -3
- package/src/ui/renderers/cliToolRenderers.tsx +108 -67
- package/src/ui/renderers/pluginRenderers.tsx +157 -98
- package/src/ui/renderers/pluginRowText.ts +70 -0
- package/src/ui/renderers/pluginStatusText.ts +56 -0
- package/src/ui/screens/CliToolsScreen.tsx +154 -280
- package/src/ui/screens/PluginsScreen.tsx +156 -140
- package/src/ui/state/types.ts +0 -7
- package/src/__tests__/dual-write-prevention.test.ts +0 -380
- package/src/__tests__/gap-fill-versions.test.ts +0 -389
- package/src/__tests__/plugin-version-check.test.ts +0 -762
- package/src/cli/claude.ts +0 -21
- package/src/prerunner/index.ts +0 -500
- package/src/services/plugin-version-check.ts +0 -360
- package/src/services/update-cache.ts +0 -78
- package/src/ui/components/modals/VersionMismatchModal.tsx +0 -138
- package/src/ui/hooks/useMismatchModal.ts +0 -89
|
@@ -240,11 +240,11 @@ describe("conventions-manager", () => {
|
|
|
240
240
|
const content = [
|
|
241
241
|
"# Project CLAUDE.md",
|
|
242
242
|
"",
|
|
243
|
-
"<!-- BEGIN magus:code-
|
|
243
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
244
244
|
"## Code Analysis Conventions",
|
|
245
245
|
"",
|
|
246
246
|
"> Managed by plugin",
|
|
247
|
-
"<!-- END magus:code-
|
|
247
|
+
"<!-- END magus:code-search -->",
|
|
248
248
|
"",
|
|
249
249
|
"Other content",
|
|
250
250
|
].join("\n");
|
|
@@ -253,7 +253,7 @@ describe("conventions-manager", () => {
|
|
|
253
253
|
|
|
254
254
|
expect(result.errors).toEqual([]);
|
|
255
255
|
expect(result.sections).toHaveLength(1);
|
|
256
|
-
expect(result.sections[0].section).toBe("code-
|
|
256
|
+
expect(result.sections[0].section).toBe("code-search");
|
|
257
257
|
expect(result.sections[0].version).toBe("1.0.0");
|
|
258
258
|
expect(result.sections[0].content).toContain("Code Analysis Conventions");
|
|
259
259
|
expect(result.sections[0].startLine).toBe(3);
|
|
@@ -262,9 +262,9 @@ describe("conventions-manager", () => {
|
|
|
262
262
|
|
|
263
263
|
it("should parse multiple sections", () => {
|
|
264
264
|
const content = [
|
|
265
|
-
"<!-- BEGIN magus:code-
|
|
265
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
266
266
|
"Section 1 content",
|
|
267
|
-
"<!-- END magus:code-
|
|
267
|
+
"<!-- END magus:code-search -->",
|
|
268
268
|
"",
|
|
269
269
|
"<!-- BEGIN magus:terminal v2.0.0 -->",
|
|
270
270
|
"Section 2 content",
|
|
@@ -275,13 +275,13 @@ describe("conventions-manager", () => {
|
|
|
275
275
|
|
|
276
276
|
expect(result.errors).toEqual([]);
|
|
277
277
|
expect(result.sections).toHaveLength(2);
|
|
278
|
-
expect(result.sections[0].section).toBe("code-
|
|
278
|
+
expect(result.sections[0].section).toBe("code-search");
|
|
279
279
|
expect(result.sections[1].section).toBe("terminal");
|
|
280
280
|
});
|
|
281
281
|
|
|
282
282
|
it("should detect missing END marker", () => {
|
|
283
283
|
const content = [
|
|
284
|
-
"<!-- BEGIN magus:code-
|
|
284
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
285
285
|
"Some content without an end marker",
|
|
286
286
|
].join("\n");
|
|
287
287
|
|
|
@@ -289,18 +289,18 @@ describe("conventions-manager", () => {
|
|
|
289
289
|
|
|
290
290
|
expect(result.errors).toHaveLength(1);
|
|
291
291
|
expect(result.errors[0].type).toBe("missing_end");
|
|
292
|
-
expect(result.errors[0]).toHaveProperty("section", "code-
|
|
292
|
+
expect(result.errors[0]).toHaveProperty("section", "code-search");
|
|
293
293
|
});
|
|
294
294
|
|
|
295
295
|
it("should detect duplicate sections", () => {
|
|
296
296
|
const content = [
|
|
297
|
-
"<!-- BEGIN magus:code-
|
|
297
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
298
298
|
"First",
|
|
299
|
-
"<!-- END magus:code-
|
|
299
|
+
"<!-- END magus:code-search -->",
|
|
300
300
|
"",
|
|
301
|
-
"<!-- BEGIN magus:code-
|
|
301
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
302
302
|
"Second",
|
|
303
|
-
"<!-- END magus:code-
|
|
303
|
+
"<!-- END magus:code-search -->",
|
|
304
304
|
].join("\n");
|
|
305
305
|
|
|
306
306
|
const result = parseClaudeMdContent(content);
|
|
@@ -309,7 +309,7 @@ describe("conventions-manager", () => {
|
|
|
309
309
|
(e) => e.type === "duplicate_section",
|
|
310
310
|
);
|
|
311
311
|
expect(dupError).toBeDefined();
|
|
312
|
-
expect(dupError).toHaveProperty("section", "code-
|
|
312
|
+
expect(dupError).toHaveProperty("section", "code-search");
|
|
313
313
|
});
|
|
314
314
|
|
|
315
315
|
it("should ignore markers inside code blocks", () => {
|
|
@@ -473,9 +473,9 @@ describe("conventions-manager", () => {
|
|
|
473
473
|
const content = [
|
|
474
474
|
"# Project",
|
|
475
475
|
"",
|
|
476
|
-
"<!-- BEGIN magus:code-
|
|
476
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
477
477
|
"Conventions here",
|
|
478
|
-
"<!-- END magus:code-
|
|
478
|
+
"<!-- END magus:code-search -->",
|
|
479
479
|
].join("\n");
|
|
480
480
|
await writeFile(claudeMdPath, content);
|
|
481
481
|
|
|
@@ -505,7 +505,7 @@ describe("conventions-manager", () => {
|
|
|
505
505
|
|
|
506
506
|
const result = await injectClaudeMdSection(
|
|
507
507
|
claudeMdPath,
|
|
508
|
-
"code-
|
|
508
|
+
"code-search",
|
|
509
509
|
"1.0.0",
|
|
510
510
|
"## Code Analysis\n\nPrivate paths here",
|
|
511
511
|
);
|
|
@@ -513,9 +513,9 @@ describe("conventions-manager", () => {
|
|
|
513
513
|
expect(result.action).toBe("inserted");
|
|
514
514
|
|
|
515
515
|
const content = await readFile(claudeMdPath, "utf-8");
|
|
516
|
-
expect(content).toContain("<!-- BEGIN magus:code-
|
|
516
|
+
expect(content).toContain("<!-- BEGIN magus:code-search v1.0.0 -->");
|
|
517
517
|
expect(content).toContain("## Code Analysis");
|
|
518
|
-
expect(content).toContain("<!-- END magus:code-
|
|
518
|
+
expect(content).toContain("<!-- END magus:code-search -->");
|
|
519
519
|
});
|
|
520
520
|
|
|
521
521
|
it("should insert new section into existing file", async () => {
|
|
@@ -524,7 +524,7 @@ describe("conventions-manager", () => {
|
|
|
524
524
|
|
|
525
525
|
const result = await injectClaudeMdSection(
|
|
526
526
|
claudeMdPath,
|
|
527
|
-
"code-
|
|
527
|
+
"code-search",
|
|
528
528
|
"1.0.0",
|
|
529
529
|
"New content",
|
|
530
530
|
);
|
|
@@ -534,7 +534,7 @@ describe("conventions-manager", () => {
|
|
|
534
534
|
const content = await readFile(claudeMdPath, "utf-8");
|
|
535
535
|
expect(content).toContain("# Project");
|
|
536
536
|
expect(content).toContain("Existing content");
|
|
537
|
-
expect(content).toContain("<!-- BEGIN magus:code-
|
|
537
|
+
expect(content).toContain("<!-- BEGIN magus:code-search v1.0.0 -->");
|
|
538
538
|
});
|
|
539
539
|
|
|
540
540
|
it("should update section when version changes", async () => {
|
|
@@ -542,15 +542,15 @@ describe("conventions-manager", () => {
|
|
|
542
542
|
const initial = [
|
|
543
543
|
"# Project",
|
|
544
544
|
"",
|
|
545
|
-
"<!-- BEGIN magus:code-
|
|
545
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
546
546
|
"Old content",
|
|
547
|
-
"<!-- END magus:code-
|
|
547
|
+
"<!-- END magus:code-search -->",
|
|
548
548
|
].join("\n");
|
|
549
549
|
await writeFile(claudeMdPath, initial);
|
|
550
550
|
|
|
551
551
|
const result = await injectClaudeMdSection(
|
|
552
552
|
claudeMdPath,
|
|
553
|
-
"code-
|
|
553
|
+
"code-search",
|
|
554
554
|
"2.0.0",
|
|
555
555
|
"New content",
|
|
556
556
|
);
|
|
@@ -568,15 +568,15 @@ describe("conventions-manager", () => {
|
|
|
568
568
|
it("should skip when version is unchanged", async () => {
|
|
569
569
|
const claudeMdPath = join(testDir, "CLAUDE.md");
|
|
570
570
|
const initial = [
|
|
571
|
-
"<!-- BEGIN magus:code-
|
|
571
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
572
572
|
"Current content",
|
|
573
|
-
"<!-- END magus:code-
|
|
573
|
+
"<!-- END magus:code-search -->",
|
|
574
574
|
].join("\n");
|
|
575
575
|
await writeFile(claudeMdPath, initial);
|
|
576
576
|
|
|
577
577
|
const result = await injectClaudeMdSection(
|
|
578
578
|
claudeMdPath,
|
|
579
|
-
"code-
|
|
579
|
+
"code-search",
|
|
580
580
|
"1.0.0",
|
|
581
581
|
"Different content but same version",
|
|
582
582
|
);
|
|
@@ -598,7 +598,7 @@ describe("conventions-manager", () => {
|
|
|
598
598
|
|
|
599
599
|
const result = await injectClaudeMdSection(
|
|
600
600
|
claudeMdPath,
|
|
601
|
-
"code-
|
|
601
|
+
"code-search",
|
|
602
602
|
"1.0.0",
|
|
603
603
|
"New content",
|
|
604
604
|
);
|
|
@@ -610,13 +610,13 @@ describe("conventions-manager", () => {
|
|
|
610
610
|
it("should refuse when file has duplicate sections", async () => {
|
|
611
611
|
const claudeMdPath = join(testDir, "CLAUDE.md");
|
|
612
612
|
const duplicate = [
|
|
613
|
-
"<!-- BEGIN magus:code-
|
|
613
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
614
614
|
"First",
|
|
615
|
-
"<!-- END magus:code-
|
|
615
|
+
"<!-- END magus:code-search -->",
|
|
616
616
|
"",
|
|
617
|
-
"<!-- BEGIN magus:code-
|
|
617
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
618
618
|
"Second",
|
|
619
|
-
"<!-- END magus:code-
|
|
619
|
+
"<!-- END magus:code-search -->",
|
|
620
620
|
].join("\n");
|
|
621
621
|
await writeFile(claudeMdPath, duplicate);
|
|
622
622
|
|
|
@@ -642,21 +642,21 @@ describe("conventions-manager", () => {
|
|
|
642
642
|
const content = [
|
|
643
643
|
"# Project",
|
|
644
644
|
"",
|
|
645
|
-
"<!-- BEGIN magus:code-
|
|
645
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
646
646
|
"Conventions here",
|
|
647
|
-
"<!-- END magus:code-
|
|
647
|
+
"<!-- END magus:code-search -->",
|
|
648
648
|
"",
|
|
649
649
|
"Other content",
|
|
650
650
|
].join("\n");
|
|
651
651
|
await writeFile(claudeMdPath, content);
|
|
652
652
|
|
|
653
|
-
const result = await removeClaudeMdSection(claudeMdPath, "code-
|
|
653
|
+
const result = await removeClaudeMdSection(claudeMdPath, "code-search");
|
|
654
654
|
|
|
655
655
|
expect(result.removed).toBe(true);
|
|
656
656
|
|
|
657
657
|
const newContent = await readFile(claudeMdPath, "utf-8");
|
|
658
|
-
expect(newContent).not.toContain("BEGIN magus:code-
|
|
659
|
-
expect(newContent).not.toContain("END magus:code-
|
|
658
|
+
expect(newContent).not.toContain("BEGIN magus:code-search");
|
|
659
|
+
expect(newContent).not.toContain("END magus:code-search");
|
|
660
660
|
expect(newContent).toContain("# Project");
|
|
661
661
|
expect(newContent).toContain("Other content");
|
|
662
662
|
});
|
|
@@ -665,7 +665,7 @@ describe("conventions-manager", () => {
|
|
|
665
665
|
const claudeMdPath = join(testDir, "CLAUDE.md");
|
|
666
666
|
await writeFile(claudeMdPath, "# Project\n\nSome content\n");
|
|
667
667
|
|
|
668
|
-
const result = await removeClaudeMdSection(claudeMdPath, "code-
|
|
668
|
+
const result = await removeClaudeMdSection(claudeMdPath, "code-search");
|
|
669
669
|
|
|
670
670
|
expect(result.removed).toBe(false);
|
|
671
671
|
});
|
|
@@ -673,7 +673,7 @@ describe("conventions-manager", () => {
|
|
|
673
673
|
it("should no-op for non-existent file", async () => {
|
|
674
674
|
const claudeMdPath = join(testDir, "CLAUDE.md");
|
|
675
675
|
|
|
676
|
-
const result = await removeClaudeMdSection(claudeMdPath, "code-
|
|
676
|
+
const result = await removeClaudeMdSection(claudeMdPath, "code-search");
|
|
677
677
|
|
|
678
678
|
expect(result.removed).toBe(false);
|
|
679
679
|
});
|
|
@@ -724,9 +724,9 @@ describe("conventions-manager", () => {
|
|
|
724
724
|
it("should preserve other sections when removing one", async () => {
|
|
725
725
|
const claudeMdPath = join(testDir, "CLAUDE.md");
|
|
726
726
|
const content = [
|
|
727
|
-
"<!-- BEGIN magus:code-
|
|
727
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
728
728
|
"First section",
|
|
729
|
-
"<!-- END magus:code-
|
|
729
|
+
"<!-- END magus:code-search -->",
|
|
730
730
|
"",
|
|
731
731
|
"<!-- BEGIN magus:terminal v2.0.0 -->",
|
|
732
732
|
"Second section",
|
|
@@ -734,10 +734,10 @@ describe("conventions-manager", () => {
|
|
|
734
734
|
].join("\n");
|
|
735
735
|
await writeFile(claudeMdPath, content);
|
|
736
736
|
|
|
737
|
-
await removeClaudeMdSection(claudeMdPath, "code-
|
|
737
|
+
await removeClaudeMdSection(claudeMdPath, "code-search");
|
|
738
738
|
|
|
739
739
|
const newContent = await readFile(claudeMdPath, "utf-8");
|
|
740
|
-
expect(newContent).not.toContain("code-
|
|
740
|
+
expect(newContent).not.toContain("code-search");
|
|
741
741
|
expect(newContent).toContain("<!-- BEGIN magus:terminal v2.0.0 -->");
|
|
742
742
|
expect(newContent).toContain("Second section");
|
|
743
743
|
});
|
|
@@ -751,9 +751,9 @@ describe("conventions-manager", () => {
|
|
|
751
751
|
it("should list all managed sections", async () => {
|
|
752
752
|
const claudeMdPath = join(testDir, "CLAUDE.md");
|
|
753
753
|
const content = [
|
|
754
|
-
"<!-- BEGIN magus:code-
|
|
754
|
+
"<!-- BEGIN magus:code-search v1.0.0 -->",
|
|
755
755
|
"First",
|
|
756
|
-
"<!-- END magus:code-
|
|
756
|
+
"<!-- END magus:code-search -->",
|
|
757
757
|
"",
|
|
758
758
|
"<!-- BEGIN magus:terminal v2.1.0 -->",
|
|
759
759
|
"Second",
|
|
@@ -764,7 +764,7 @@ describe("conventions-manager", () => {
|
|
|
764
764
|
const sections = await listClaudeMdSections(claudeMdPath);
|
|
765
765
|
|
|
766
766
|
expect(sections).toHaveLength(2);
|
|
767
|
-
expect(sections[0].section).toBe("code-
|
|
767
|
+
expect(sections[0].section).toBe("code-search");
|
|
768
768
|
expect(sections[0].version).toBe("1.0.0");
|
|
769
769
|
expect(sections[1].section).toBe("terminal");
|
|
770
770
|
expect(sections[1].version).toBe("2.1.0");
|
|
@@ -8,8 +8,7 @@ import type { PluginInfo } from "../services/plugin-manager.js";
|
|
|
8
8
|
*
|
|
9
9
|
* It is also invisible to every update path, because the check is
|
|
10
10
|
* `installedVersion && compare(latest, installedVersion) > 0` — with no
|
|
11
|
-
* installed version that is false, so
|
|
12
|
-
* prerunner's auto-update will ever touch it.
|
|
11
|
+
* installed version that is false, so no update path will ever touch it.
|
|
13
12
|
*/
|
|
14
13
|
|
|
15
14
|
const plugin = (over: Partial<PluginInfo>): PluginInfo =>
|
|
@@ -26,7 +25,7 @@ const plugin = (over: Partial<PluginInfo>): PluginInfo =>
|
|
|
26
25
|
|
|
27
26
|
describe("isEnabledButNotInstalled", () => {
|
|
28
27
|
test("enabled in project scope with no installed version is flagged", () => {
|
|
29
|
-
// The real case: terminal/code-
|
|
28
|
+
// The real case: terminal/code-search are in this project's enabledPlugins
|
|
30
29
|
// but have no registry entry for it and none at user scope.
|
|
31
30
|
expect(
|
|
32
31
|
isEnabledButNotInstalled(
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# NOT from this machine: nothing brew manages here is outdated, so no real non-empty output could be captured read-only.
|
|
2
|
+
# This is Homebrew's OWN expected output for `brew outdated --json=v2`, copied verbatim from
|
|
3
|
+
# /opt/homebrew/Library/Homebrew/test/cmd/outdated_spec.rb ("outputs JSON for outdated formulae and casks")
|
|
4
|
+
# at Homebrew commit 088d2f79849d1b08792459b65026207a91c545d6 (JSON.pretty_generate of that hash).
|
|
5
|
+
# The generator is cmd/outdated.rb json_info: { name: f.full_name, installed_versions, current_version, pinned, pinned_version }.
|
|
6
|
+
{
|
|
7
|
+
"formulae": [
|
|
8
|
+
{
|
|
9
|
+
"name": "testball",
|
|
10
|
+
"installed_versions": [
|
|
11
|
+
"0.0.1"
|
|
12
|
+
],
|
|
13
|
+
"current_version": "0.1",
|
|
14
|
+
"pinned": false,
|
|
15
|
+
"pinned_version": null
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"casks": [
|
|
19
|
+
{
|
|
20
|
+
"name": "local-caffeine",
|
|
21
|
+
"installed_versions": [
|
|
22
|
+
"1.2.2"
|
|
23
|
+
],
|
|
24
|
+
"current_version": "1.2.3",
|
|
25
|
+
"pinned": false,
|
|
26
|
+
"pinned_version": null
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# captured 2026-09-11 23:12 AEST and again 2026-09-12 00:40 AEST on the reporter's machine (Homebrew 6.0.22), read-only:
|
|
2
|
+
# HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_ENV_HINTS=1 NO_COLOR=1 brew outdated --json=v2 tmux
|
|
3
|
+
# exit=0 (tmux 3.7c installed, current)
|
|
4
|
+
{
|
|
5
|
+
"formulae": [],
|
|
6
|
+
"casks": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# captured 2026-09-12 00:40 AEST, read-only:
|
|
2
|
+
# HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_ENV_HINTS=1 NO_COLOR=1 brew outdated --json=v2 cowsay-not-a-formula-xyz
|
|
3
|
+
# exit=1, stdout empty, stderr below. (Assumption A5 was half wrong: a formula brew KNOWS but has not
|
|
4
|
+
# installed — wget was tried before it turned out to be installed — exits 0 with formulae: [], so ownership
|
|
5
|
+
# must be decided before brew's silence is believed.)
|
|
6
|
+
Error: No available formula with the name "cowsay-not-a-formula-xyz".
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# captured 2026-09-12 00:58 AEST, read-only: go version -m /Users/jack/go/bin/tmux-mcp (go 1.27.1, exit=0)
|
|
2
|
+
/Users/jack/go/bin/tmux-mcp: go1.27.1
|
|
3
|
+
path github.com/MadAppGang/tmux-mcp/v2
|
|
4
|
+
mod github.com/MadAppGang/tmux-mcp/v2 v2.0.0 h1:DhieVeG/e6K/+++7XrP9ruhCnywVatf8e+bnjzjMLXE=
|
|
5
|
+
dep github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
|
6
|
+
dep github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
|
7
|
+
dep github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
|
8
|
+
dep github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|
9
|
+
dep github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
|
|
10
|
+
dep github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
|
11
|
+
dep github.com/mark3labs/mcp-go v0.45.0 h1:s0S8qR/9fWaQ3pHxz7pm1uQ0DrswoSnRIxKIjbiQtkc=
|
|
12
|
+
dep github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
|
13
|
+
dep github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
|
14
|
+
dep github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
|
|
15
|
+
dep golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
|
16
|
+
dep gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
17
|
+
build -buildmode=exe
|
|
18
|
+
build -compiler=gc
|
|
19
|
+
build DefaultGODEBUG=tracebacklabels=0,x509sslcertoverrideplatform=0
|
|
20
|
+
build CGO_ENABLED=1
|
|
21
|
+
build CGO_CFLAGS=
|
|
22
|
+
build CGO_CPPFLAGS=
|
|
23
|
+
build CGO_CXXFLAGS=
|
|
24
|
+
build CGO_LDFLAGS=
|
|
25
|
+
build GOARCH=arm64
|
|
26
|
+
build GOOS=darwin
|
|
27
|
+
build GOARM64=v8.0
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# captured 2026-09-12 00:50 AEST, read-only GET: curl -sS 'https://registry.npmjs.org/-/package/%40nope-xyz%2Fdoes-not-exist-zz/dist-tags'
|
|
2
|
+
# http 401 — the registry answers 401, not 404, for a scoped name that does not exist (status trailer removed)
|
|
3
|
+
"Unauthorized"
|
|
4
|
+
# http=401
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# captured 2026-09-12 00:50 AEST, read-only GET (verifies A3: a scoped name with / encoded as %2F answers):
|
|
2
|
+
# curl -sS 'https://registry.npmjs.org/-/package/%40openai%2Fcodex/dist-tags' (http 200; curl's status trailer removed)
|
|
3
|
+
{"beta":"0.1.2505172116","native":"0.1.2505291658","linux-arm64":"0.154.0-linux-arm64","latest":"0.154.0","linux-x64":"0.154.0-linux-x64","win32-arm64":"0.154.0-win32-arm64","darwin-arm64":"0.154.0-darwin-arm64","darwin-x64":"0.154.0-darwin-x64","win32-x64":"0.154.0-win32-x64","alpha-darwin-arm64":"0.155.0-alpha.3.9-darwin-arm64","alpha":"0.155.0-alpha.3.9","alpha-linux-arm64":"0.155.0-alpha.3.9-linux-arm64","alpha-darwin-x64":"0.155.0-alpha.3.9-darwin-x64","alpha-linux-x64":"0.155.0-alpha.3.9-linux-x64","alpha-win32-x64":"0.155.0-alpha.3.9-win32-x64","alpha-win32-arm64":"0.155.0-alpha.3.9-win32-arm64"}
|
|
4
|
+
# http=200
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# captured 2026-09-12 00:42 AEST, read-only: cat ~/.local/share/uv/tools/browser-use/uv-receipt.toml (uv 0.11.15)
|
|
2
|
+
[tool]
|
|
3
|
+
requirements = [{ name = "browser-use" }]
|
|
4
|
+
entrypoints = [
|
|
5
|
+
{ name = "browser", install-path = "/Users/jack/.local/bin/browser", from = "browser-use" },
|
|
6
|
+
{ name = "browser-use", install-path = "/Users/jack/.local/bin/browser-use", from = "browser-use" },
|
|
7
|
+
{ name = "browser-use-tui", install-path = "/Users/jack/.local/bin/browser-use-tui", from = "browser-use" },
|
|
8
|
+
{ name = "browseruse", install-path = "/Users/jack/.local/bin/browseruse", from = "browser-use" },
|
|
9
|
+
{ name = "bu", install-path = "/Users/jack/.local/bin/bu", from = "browser-use" },
|
|
10
|
+
]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# captured 2026-09-12 00:55 AEST: UV_TOOL_DIR=$SESSION/validation/captures/uv-scratch/tools UV_TOOL_BIN_DIR=$SESSION/validation/captures/uv-scratch/bin UV_CACHE_DIR=$SESSION/validation/captures/uv-scratch/cache UV_PYTHON_INSTALL_DIR=$SESSION/validation/captures/uv-scratch/python NO_COLOR=1 uv tool install --force git+https://github.com/VaasuDevanS/cowsay-python@v6.1
|
|
2
|
+
# then: cat $SESSION/validation/captures/uv-scratch/tools/cowsay/uv-receipt.toml
|
|
3
|
+
# $SESSION = claudish worktree update-fix2 ai-docs/sessions/dev-feature-claudeup-unify-20260911-2240 (the user's real uv tools were never touched)
|
|
4
|
+
[tool]
|
|
5
|
+
requirements = [{ name = "cowsay", git = "https://github.com/VaasuDevanS/cowsay-python?rev=v6.1" }]
|
|
6
|
+
entrypoints = [
|
|
7
|
+
{ name = "cowsay", install-path = "/Users/jack/mag/claudish/.claude/worktrees/update-fix2/ai-docs/sessions/dev-feature-claudeup-unify-20260911-2240/validation/captures/uv-scratch/bin/cowsay", from = "cowsay" },
|
|
8
|
+
]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# captured 2026-09-12 00:54 AEST: UV_TOOL_DIR=$SESSION/validation/captures/uv-scratch/tools UV_TOOL_BIN_DIR=$SESSION/validation/captures/uv-scratch/bin UV_CACHE_DIR=$SESSION/validation/captures/uv-scratch/cache UV_PYTHON_INSTALL_DIR=$SESSION/validation/captures/uv-scratch/python NO_COLOR=1 uv tool install 'cowsay==6.0'
|
|
2
|
+
# then: cat $SESSION/validation/captures/uv-scratch/tools/cowsay/uv-receipt.toml
|
|
3
|
+
# $SESSION = claudish worktree update-fix2 ai-docs/sessions/dev-feature-claudeup-unify-20260911-2240 (the user's real uv tools were never touched)
|
|
4
|
+
[tool]
|
|
5
|
+
requirements = [{ name = "cowsay", specifier = "==6.0" }]
|
|
6
|
+
entrypoints = [
|
|
7
|
+
{ name = "cowsay", install-path = "/Users/jack/mag/claudish/.claude/worktrees/update-fix2/ai-docs/sessions/dev-feature-claudeup-unify-20260911-2240/validation/captures/uv-scratch/bin/cowsay", from = "cowsay" },
|
|
8
|
+
]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# captured 2026-09-12 00:42 AEST, read-only: cat ~/.local/share/uv/tools/graphifyy/uv-receipt.toml (uv 0.11.15)
|
|
2
|
+
[tool]
|
|
3
|
+
requirements = [{ name = "graphifyy", extras = ["mcp"] }]
|
|
4
|
+
entrypoints = [
|
|
5
|
+
{ name = "graphify", install-path = "/Users/jack/.local/bin/graphify", from = "graphifyy" },
|
|
6
|
+
{ name = "graphify-mcp", install-path = "/Users/jack/.local/bin/graphify-mcp", from = "graphifyy" },
|
|
7
|
+
]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# captured 2026-09-12 00:42 AEST, read-only: cat ~/.local/share/uv/tools/serena-agent/uv-receipt.toml (uv 0.11.15)
|
|
2
|
+
[tool]
|
|
3
|
+
requirements = [{ name = "serena-agent" }]
|
|
4
|
+
python = "3.13"
|
|
5
|
+
entrypoints = [
|
|
6
|
+
{ name = "serena", install-path = "/Users/jack/.local/bin/serena", from = "serena-agent" },
|
|
7
|
+
{ name = "serena-agent", install-path = "/Users/jack/.local/bin/serena-agent", from = "serena-agent" },
|
|
8
|
+
{ name = "serena-hooks", install-path = "/Users/jack/.local/bin/serena-hooks", from = "serena-agent" },
|
|
9
|
+
]
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# captured 2026-09-12 00:54 AEST: UV_TOOL_DIR=$SESSION/validation/captures/uv-scratch/tools UV_TOOL_BIN_DIR=$SESSION/validation/captures/uv-scratch/bin UV_CACHE_DIR=$SESSION/validation/captures/uv-scratch/cache UV_PYTHON_INSTALL_DIR=$SESSION/validation/captures/uv-scratch/python NO_COLOR=1 uv tool list --outdated (exit=0)
|
|
2
|
+
# cowsay was installed as 'cowsay==6.0' (receipt specifier ==6.0); uv still lists it as outdated.
|
|
3
|
+
# $SESSION = claudish worktree update-fix2 ai-docs/sessions/dev-feature-claudeup-unify-20260911-2240 (the user's real uv tools were never touched)
|
|
4
|
+
cowsay v6.0 [latest: 6.1]
|
|
5
|
+
- cowsay
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# captured 2026-09-12 00:42 AEST on the reporter's machine, read-only: uv tool list --outdated (uv 0.11.15, exit=0)
|
|
2
|
+
# Same text as the 2026-09-11 23:12 baseline. browser-use and mcp are absent: current.
|
|
3
|
+
claude-swap v0.24.1 [latest: 0.26.0]
|
|
4
|
+
- claude-swap
|
|
5
|
+
- cswap
|
|
6
|
+
graphifyy v0.9.50 [latest: 0.9.58]
|
|
7
|
+
- graphify
|
|
8
|
+
- graphify-mcp
|
|
9
|
+
mistral-vibe v2.5.0 [latest: 2.25.3]
|
|
10
|
+
- vibe
|
|
11
|
+
- vibe-acp
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# captured 2026-09-12 00:42 AEST on the reporter's machine, read-only: uv tool list (uv 0.11.15, exit=0)
|
|
2
|
+
browser-use v0.13.10
|
|
3
|
+
- browser
|
|
4
|
+
- browser-use
|
|
5
|
+
- browser-use-tui
|
|
6
|
+
- browseruse
|
|
7
|
+
- bu
|
|
8
|
+
claude-swap v0.24.1
|
|
9
|
+
- claude-swap
|
|
10
|
+
- cswap
|
|
11
|
+
graphifyy v0.9.50
|
|
12
|
+
- graphify
|
|
13
|
+
- graphify-mcp
|
|
14
|
+
mcp v2.2.0
|
|
15
|
+
- mcp
|
|
16
|
+
mistral-vibe v2.5.0
|
|
17
|
+
- vibe
|
|
18
|
+
- vibe-acp
|
|
19
|
+
serena-agent v1.7.0
|
|
20
|
+
- serena
|
|
21
|
+
- serena-agent
|
|
22
|
+
- serena-hooks
|
|
@@ -6,8 +6,8 @@ import { join } from "node:path";
|
|
|
6
6
|
import { BUILTIN_DEFAULTS } from "../data/gitignore-defaults.js";
|
|
7
7
|
import {
|
|
8
8
|
checkGitignore,
|
|
9
|
-
|
|
10
|
-
} from "../services/gitignore-
|
|
9
|
+
formatGitignoreWarning,
|
|
10
|
+
} from "../services/gitignore-check";
|
|
11
11
|
|
|
12
12
|
function git(cwd: string, ...args: string[]): void {
|
|
13
13
|
spawnSync("git", ["-c", "core.excludesFile=/dev/null", ...args], { cwd });
|
|
@@ -17,7 +17,7 @@ describe("checkGitignore", () => {
|
|
|
17
17
|
let projectDir: string;
|
|
18
18
|
|
|
19
19
|
beforeEach(async () => {
|
|
20
|
-
projectDir = await mkdtemp(join(tmpdir(), "gitig-
|
|
20
|
+
projectDir = await mkdtemp(join(tmpdir(), "gitig-check-"));
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
afterEach(async () => {
|
|
@@ -55,13 +55,15 @@ describe("checkGitignore", () => {
|
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
describe("
|
|
58
|
+
describe("formatGitignoreWarning", () => {
|
|
59
59
|
it("returns null when no violations", () => {
|
|
60
|
-
expect(
|
|
60
|
+
expect(
|
|
61
|
+
formatGitignoreWarning({ violationCount: 0, warnings: [] }),
|
|
62
|
+
).toBeNull();
|
|
61
63
|
});
|
|
62
64
|
|
|
63
65
|
it("returns a warning string when violations exist", () => {
|
|
64
|
-
const w =
|
|
66
|
+
const w = formatGitignoreWarning({ violationCount: 3, warnings: [] });
|
|
65
67
|
expect(w).not.toBeNull();
|
|
66
68
|
expect(w).toContain("3 git state");
|
|
67
69
|
expect(w).toContain("Git State tab");
|