trackfw 6.10.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -3
- package/bin/trackfw +38 -1
- package/package.json +1 -1
- package/src/branch/prune.js +450 -0
- package/src/branch/runner.js +33 -20
- package/src/changelog/index.js +114 -0
- package/src/commands/branch.js +59 -9
- package/src/commands/changelog.js +29 -0
- package/src/commands/commit.js +60 -0
- package/src/commands/discover.js +75 -0
- package/src/commands/doctor.js +32 -0
- package/src/commands/index.js +23 -4
- package/src/commands/integrations.js +23 -1
- package/src/commands/serve.js +52 -4
- package/src/commands/ship.js +4 -3
- package/src/commands/thirdparty.js +384 -0
- package/src/commands/update-harness.js +320 -12
- package/src/commands/update.js +3 -1
- package/src/commit/runner.js +352 -0
- package/src/config/index.js +27 -0
- package/src/generators/hooks.js +925 -6
- package/src/generators/init.js +28 -6
- package/src/i18n/locales/en-US.json +0 -21
- package/src/i18n/locales/es-ES.json +0 -21
- package/src/i18n/locales/pt-BR.json +0 -21
- package/src/integrations/doctor.js +0 -0
- package/src/integrations/index.js +19 -2
- package/src/integrations/manager.js +133 -19
- package/src/lib/fatal-error.js +64 -0
- package/src/lib/unknown-command.js +82 -0
- package/src/ship/runner.js +259 -95
- package/src/thirdparty/fetch.js +140 -0
- package/src/thirdparty/markers.js +207 -0
- package/src/thirdparty/provenance.js +114 -0
- package/src/thirdparty/quarantine.js +113 -0
- package/src/thirdparty/references.js +194 -0
- package/src/validator/index.js +1060 -27
- package/src/commands/plugins.js +0 -184
|
@@ -6,7 +6,7 @@ const path = require('path')
|
|
|
6
6
|
const identityStore = require('../identity')
|
|
7
7
|
const { catalog, buildPlans, IntegrationManager, globalGroupPath } = require('../integrations')
|
|
8
8
|
const { tildeify, validateTargets, buildDocument, humanReport, silenceConsole } = require('../lib/update-engine')
|
|
9
|
-
const { mergeClaudeHookArray, mergeSimpleCommandArray, mergeCopilotHookArray, generateGlobalCredentialGuardScript } = require('../generators/hooks')
|
|
9
|
+
const { mergeClaudeHookArray, mergeSimpleCommandArray, mergeCopilotHookArray, generateGlobalCredentialGuardScript, generateGlobalGitBranchGuardScript } = require('../generators/hooks')
|
|
10
10
|
|
|
11
11
|
// `trackfw update harness` is the global counterpart to `trackfw update` —
|
|
12
12
|
// see docs/cli-parity.md, "`trackfw update` vs `trackfw update harness`".
|
|
@@ -462,6 +462,288 @@ function credentialGuardTargetKiro(homeRoot, { dryRun, installMissing }) {
|
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
+
// ---------------------------------------------------------------------------
|
|
466
|
+
// git-branch-guard global-scope wiring (ROADMAP-2026-08-17 Wave 2/ML-2A).
|
|
467
|
+
// Mirrors the six credentialGuardTarget<Tool> functions above, entry-for-
|
|
468
|
+
// entry — same 4-state contract, same displayPath per tool, same reuse of
|
|
469
|
+
// mergeClaudeHookArray/mergeSimpleCommandArray/mergeCopilotHookArray (those
|
|
470
|
+
// helpers only need a scriptPath, which here is trackfw-git-branch-guard.sh
|
|
471
|
+
// instead of trackfw-credential-guard.sh). Mirrors
|
|
472
|
+
// internal/generators/update.go:harnessGitBranchGuardTarget<Tool>.
|
|
473
|
+
//
|
|
474
|
+
// Kiro is the one structural exception: credentialGuardTargetKiro rewrites
|
|
475
|
+
// ~/.kiro/hooks/trackfw-credential-guard.json WHOLESALE every run (never
|
|
476
|
+
// merges), so sharing that file with a second wholesale writer would make
|
|
477
|
+
// the two targets flap between each other's desired 2-entry document forever
|
|
478
|
+
// (idempotency failure). gitBranchGuardTargetKiro therefore writes its OWN
|
|
479
|
+
// dedicated file, ~/.kiro/hooks/trackfw-git-branch-guard.json, same
|
|
480
|
+
// {"version":"v1","hooks":[pre,post]} schema, hook names
|
|
481
|
+
// "trackfw-git-branch-guard-global-pre"/"-global-post".
|
|
482
|
+
// ---------------------------------------------------------------------------
|
|
483
|
+
|
|
484
|
+
function gitBranchGuardTargetClaude(homeRoot, { dryRun, installMissing }) {
|
|
485
|
+
const id = 'claude-git-branch-guard'
|
|
486
|
+
const filePath = path.join(homeRoot, '.claude', 'settings.json')
|
|
487
|
+
const displayPath = tildeify(homeRoot, filePath)
|
|
488
|
+
const scriptPath = path.join(homeRoot, '.trackfw', 'scripts', 'trackfw-git-branch-guard.sh')
|
|
489
|
+
|
|
490
|
+
let root
|
|
491
|
+
let raw = null
|
|
492
|
+
try {
|
|
493
|
+
if (fs.existsSync(filePath)) {
|
|
494
|
+
raw = fs.readFileSync(filePath, 'utf8')
|
|
495
|
+
root = raw.length ? JSON.parse(raw) : {}
|
|
496
|
+
} else {
|
|
497
|
+
if (!installMissing) return { id, state: 'missing', path: displayPath }
|
|
498
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
499
|
+
root = {}
|
|
500
|
+
if (!root.hooks) root.hooks = {}
|
|
501
|
+
root.hooks.PreToolUse = mergeClaudeHookArray(root.hooks.PreToolUse, 'Bash', scriptPath)
|
|
502
|
+
root.hooks.PostToolUse = mergeClaudeHookArray(root.hooks.PostToolUse, 'Bash', scriptPath)
|
|
503
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
504
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
505
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
506
|
+
return { id, state: 'updated', path: displayPath }
|
|
507
|
+
}
|
|
508
|
+
} catch (e) {
|
|
509
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
try {
|
|
513
|
+
if (!root.hooks) root.hooks = {}
|
|
514
|
+
root.hooks.PreToolUse = mergeClaudeHookArray(root.hooks.PreToolUse, 'Bash', scriptPath)
|
|
515
|
+
root.hooks.PostToolUse = mergeClaudeHookArray(root.hooks.PostToolUse, 'Bash', scriptPath)
|
|
516
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
517
|
+
if (desired === raw) return { id, state: 'skipped', path: displayPath }
|
|
518
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
519
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
520
|
+
return { id, state: 'updated', path: displayPath }
|
|
521
|
+
} catch (e) {
|
|
522
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
function gitBranchGuardTargetCodex(homeRoot, { dryRun, installMissing }) {
|
|
527
|
+
const id = 'codex-git-branch-guard'
|
|
528
|
+
const filePath = path.join(homeRoot, '.codex', 'hooks.json')
|
|
529
|
+
const displayPath = tildeify(homeRoot, filePath)
|
|
530
|
+
const scriptPath = path.join(homeRoot, '.trackfw', 'scripts', 'trackfw-git-branch-guard.sh')
|
|
531
|
+
|
|
532
|
+
let root
|
|
533
|
+
let raw = null
|
|
534
|
+
try {
|
|
535
|
+
if (fs.existsSync(filePath)) {
|
|
536
|
+
raw = fs.readFileSync(filePath, 'utf8')
|
|
537
|
+
root = raw.length ? JSON.parse(raw) : {}
|
|
538
|
+
} else {
|
|
539
|
+
if (!installMissing) return { id, state: 'missing', path: displayPath }
|
|
540
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
541
|
+
root = {}
|
|
542
|
+
if (!root.hooks) root.hooks = {}
|
|
543
|
+
root.hooks.PreToolUse = mergeClaudeHookArray(root.hooks.PreToolUse, 'Bash', scriptPath)
|
|
544
|
+
root.hooks.PostToolUse = mergeClaudeHookArray(root.hooks.PostToolUse, 'Bash', scriptPath)
|
|
545
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
546
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
547
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
548
|
+
return { id, state: 'updated', path: displayPath }
|
|
549
|
+
}
|
|
550
|
+
} catch (e) {
|
|
551
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
try {
|
|
555
|
+
if (!root.hooks) root.hooks = {}
|
|
556
|
+
root.hooks.PreToolUse = mergeClaudeHookArray(root.hooks.PreToolUse, 'Bash', scriptPath)
|
|
557
|
+
root.hooks.PostToolUse = mergeClaudeHookArray(root.hooks.PostToolUse, 'Bash', scriptPath)
|
|
558
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
559
|
+
if (desired === raw) return { id, state: 'skipped', path: displayPath }
|
|
560
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
561
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
562
|
+
return { id, state: 'updated', path: displayPath }
|
|
563
|
+
} catch (e) {
|
|
564
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function gitBranchGuardTargetGemini(homeRoot, { dryRun, installMissing }) {
|
|
569
|
+
const id = 'gemini-git-branch-guard'
|
|
570
|
+
const filePath = path.join(homeRoot, '.gemini', 'settings.json')
|
|
571
|
+
const displayPath = tildeify(homeRoot, filePath)
|
|
572
|
+
const scriptPath = path.join(homeRoot, '.trackfw', 'scripts', 'trackfw-git-branch-guard.sh')
|
|
573
|
+
|
|
574
|
+
let root
|
|
575
|
+
let raw = null
|
|
576
|
+
try {
|
|
577
|
+
if (fs.existsSync(filePath)) {
|
|
578
|
+
raw = fs.readFileSync(filePath, 'utf8')
|
|
579
|
+
root = raw.length ? JSON.parse(raw) : {}
|
|
580
|
+
} else {
|
|
581
|
+
if (!installMissing) return { id, state: 'missing', path: displayPath }
|
|
582
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
583
|
+
root = {}
|
|
584
|
+
if (!root.hooks) root.hooks = {}
|
|
585
|
+
root.hooks.BeforeTool = mergeClaudeHookArray(root.hooks.BeforeTool, 'run_shell_command', scriptPath)
|
|
586
|
+
root.hooks.AfterTool = mergeClaudeHookArray(root.hooks.AfterTool, 'run_shell_command', scriptPath)
|
|
587
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
588
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
589
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
590
|
+
return { id, state: 'updated', path: displayPath }
|
|
591
|
+
}
|
|
592
|
+
} catch (e) {
|
|
593
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
try {
|
|
597
|
+
if (!root.hooks) root.hooks = {}
|
|
598
|
+
root.hooks.BeforeTool = mergeClaudeHookArray(root.hooks.BeforeTool, 'run_shell_command', scriptPath)
|
|
599
|
+
root.hooks.AfterTool = mergeClaudeHookArray(root.hooks.AfterTool, 'run_shell_command', scriptPath)
|
|
600
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
601
|
+
if (desired === raw) return { id, state: 'skipped', path: displayPath }
|
|
602
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
603
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
604
|
+
return { id, state: 'updated', path: displayPath }
|
|
605
|
+
} catch (e) {
|
|
606
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function gitBranchGuardTargetCursor(homeRoot, { dryRun, installMissing }) {
|
|
611
|
+
const id = 'cursor-git-branch-guard'
|
|
612
|
+
const filePath = path.join(homeRoot, '.cursor', 'hooks.json')
|
|
613
|
+
const displayPath = tildeify(homeRoot, filePath)
|
|
614
|
+
const scriptPath = path.join(homeRoot, '.trackfw', 'scripts', 'trackfw-git-branch-guard.sh')
|
|
615
|
+
|
|
616
|
+
let root
|
|
617
|
+
let raw = null
|
|
618
|
+
try {
|
|
619
|
+
if (fs.existsSync(filePath)) {
|
|
620
|
+
raw = fs.readFileSync(filePath, 'utf8')
|
|
621
|
+
root = raw.length ? JSON.parse(raw) : {}
|
|
622
|
+
} else {
|
|
623
|
+
if (!installMissing) return { id, state: 'missing', path: displayPath }
|
|
624
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
625
|
+
root = {}
|
|
626
|
+
if (typeof root.version === 'undefined') root.version = 1
|
|
627
|
+
if (!root.hooks) root.hooks = {}
|
|
628
|
+
root.hooks.beforeShellExecution = mergeSimpleCommandArray(root.hooks.beforeShellExecution, scriptPath)
|
|
629
|
+
root.hooks.afterShellExecution = mergeSimpleCommandArray(root.hooks.afterShellExecution, scriptPath)
|
|
630
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
631
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
632
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
633
|
+
return { id, state: 'updated', path: displayPath }
|
|
634
|
+
}
|
|
635
|
+
} catch (e) {
|
|
636
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
try {
|
|
640
|
+
if (typeof root.version === 'undefined') root.version = 1
|
|
641
|
+
if (!root.hooks) root.hooks = {}
|
|
642
|
+
root.hooks.beforeShellExecution = mergeSimpleCommandArray(root.hooks.beforeShellExecution, scriptPath)
|
|
643
|
+
root.hooks.afterShellExecution = mergeSimpleCommandArray(root.hooks.afterShellExecution, scriptPath)
|
|
644
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
645
|
+
if (desired === raw) return { id, state: 'skipped', path: displayPath }
|
|
646
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
647
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
648
|
+
return { id, state: 'updated', path: displayPath }
|
|
649
|
+
} catch (e) {
|
|
650
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
function gitBranchGuardTargetCopilot(homeRoot, { dryRun, installMissing }) {
|
|
655
|
+
const id = 'copilot-git-branch-guard'
|
|
656
|
+
const filePath = path.join(homeRoot, '.copilot', 'settings.json')
|
|
657
|
+
const displayPath = tildeify(homeRoot, filePath)
|
|
658
|
+
const scriptPath = path.join(homeRoot, '.trackfw', 'scripts', 'trackfw-git-branch-guard.sh')
|
|
659
|
+
|
|
660
|
+
let root
|
|
661
|
+
let raw = null
|
|
662
|
+
try {
|
|
663
|
+
if (fs.existsSync(filePath)) {
|
|
664
|
+
raw = fs.readFileSync(filePath, 'utf8')
|
|
665
|
+
root = raw.length ? JSON.parse(raw) : {}
|
|
666
|
+
} else {
|
|
667
|
+
if (!installMissing) return { id, state: 'missing', path: displayPath }
|
|
668
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
669
|
+
root = {}
|
|
670
|
+
if (!root.hooks) root.hooks = {}
|
|
671
|
+
root.hooks.preToolUse = mergeCopilotHookArray(root.hooks.preToolUse, scriptPath)
|
|
672
|
+
root.hooks.postToolUse = mergeCopilotHookArray(root.hooks.postToolUse, scriptPath)
|
|
673
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
674
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
675
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
676
|
+
return { id, state: 'updated', path: displayPath }
|
|
677
|
+
}
|
|
678
|
+
} catch (e) {
|
|
679
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
try {
|
|
683
|
+
if (!root.hooks) root.hooks = {}
|
|
684
|
+
root.hooks.preToolUse = mergeCopilotHookArray(root.hooks.preToolUse, scriptPath)
|
|
685
|
+
root.hooks.postToolUse = mergeCopilotHookArray(root.hooks.postToolUse, scriptPath)
|
|
686
|
+
const desired = JSON.stringify(root, null, 2) + '\n'
|
|
687
|
+
if (desired === raw) return { id, state: 'skipped', path: displayPath }
|
|
688
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
689
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
690
|
+
return { id, state: 'updated', path: displayPath }
|
|
691
|
+
} catch (e) {
|
|
692
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// gitBranchGuardTargetKiro writes a DEDICATED file,
|
|
697
|
+
// ~/.kiro/hooks/trackfw-git-branch-guard.json — deliberately NOT
|
|
698
|
+
// credentialGuardTargetKiro's file. See this section's header comment for
|
|
699
|
+
// why sharing would break idempotency.
|
|
700
|
+
function gitBranchGuardTargetKiro(homeRoot, { dryRun, installMissing }) {
|
|
701
|
+
const id = 'kiro-git-branch-guard'
|
|
702
|
+
const filePath = path.join(homeRoot, '.kiro', 'hooks', 'trackfw-git-branch-guard.json')
|
|
703
|
+
const displayPath = tildeify(homeRoot, filePath)
|
|
704
|
+
const scriptPath = path.join(homeRoot, '.trackfw', 'scripts', 'trackfw-git-branch-guard.sh')
|
|
705
|
+
|
|
706
|
+
const desired = JSON.stringify(
|
|
707
|
+
{
|
|
708
|
+
version: 'v1',
|
|
709
|
+
hooks: [
|
|
710
|
+
{
|
|
711
|
+
name: 'trackfw-git-branch-guard-global-pre',
|
|
712
|
+
description: 'Blocks branch-creation git subcommands issued outside trackfw branch new (global, all trackfw projects)',
|
|
713
|
+
trigger: 'PreToolUse',
|
|
714
|
+
matcher: 'shell',
|
|
715
|
+
action: { type: 'command', command: scriptPath },
|
|
716
|
+
},
|
|
717
|
+
{
|
|
718
|
+
name: 'trackfw-git-branch-guard-global-post',
|
|
719
|
+
description: 'Warns on branch-creation git subcommands issued outside trackfw branch new (global, all trackfw projects)',
|
|
720
|
+
trigger: 'PostToolUse',
|
|
721
|
+
matcher: 'shell',
|
|
722
|
+
action: { type: 'command', command: scriptPath },
|
|
723
|
+
},
|
|
724
|
+
],
|
|
725
|
+
},
|
|
726
|
+
null,
|
|
727
|
+
2
|
|
728
|
+
) + '\n'
|
|
729
|
+
|
|
730
|
+
try {
|
|
731
|
+
const exists = fs.existsSync(filePath)
|
|
732
|
+
const actual = exists ? fs.readFileSync(filePath, 'utf8') : null
|
|
733
|
+
|
|
734
|
+
if (!exists && !installMissing) return { id, state: 'missing', path: displayPath }
|
|
735
|
+
if (exists && actual === desired) return { id, state: 'skipped', path: displayPath }
|
|
736
|
+
|
|
737
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
738
|
+
|
|
739
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
740
|
+
fs.writeFileSync(filePath, desired, 'utf8')
|
|
741
|
+
return { id, state: 'updated', path: displayPath }
|
|
742
|
+
} catch (e) {
|
|
743
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
465
747
|
// catalogBundleTarget — one target per (tool, kind) pair at global scope.
|
|
466
748
|
// Uses IntegrationManager.inspect (read-only) to classify every catalog
|
|
467
749
|
// item under that pair, then only calls manager.update() for the subset
|
|
@@ -506,18 +788,20 @@ function catalogBundleTarget(toolId, kind, homeRoot, identityConfig, { dryRun, i
|
|
|
506
788
|
}
|
|
507
789
|
|
|
508
790
|
// HARNESS_TARGET_IDS — mirrors internal/generators/update.go:HarnessTargetIDs.
|
|
509
|
-
// "codex-credential-guard"/"
|
|
510
|
-
//
|
|
511
|
-
//
|
|
512
|
-
//
|
|
513
|
-
//
|
|
514
|
-
|
|
791
|
+
// "codex-credential-guard"/"codex-git-branch-guard",
|
|
792
|
+
// "gemini-credential-guard"/"gemini-git-branch-guard", etc. are each
|
|
793
|
+
// inserted immediately BEFORE their tool's "-agents"/"-skills" pair (same
|
|
794
|
+
// relative position as claude-credential-guard/claude-git-branch-guard,
|
|
795
|
+
// which precede claude-agents/claude-skills), with credential-guard always
|
|
796
|
+
// preceding git-branch-guard within a tool — see buildHarnessTargetIDs's
|
|
797
|
+
// comment in update.go for the full rationale.
|
|
798
|
+
const HARNESS_TARGET_IDS = ['claude-skill', 'claude-credential-guard', 'claude-git-branch-guard']
|
|
515
799
|
for (const target of catalog.targets) {
|
|
516
|
-
if (target.id === 'codex') HARNESS_TARGET_IDS.push('codex-credential-guard')
|
|
517
|
-
if (target.id === 'gemini') HARNESS_TARGET_IDS.push('gemini-credential-guard')
|
|
518
|
-
if (target.id === 'cursor') HARNESS_TARGET_IDS.push('cursor-credential-guard')
|
|
519
|
-
if (target.id === 'copilot') HARNESS_TARGET_IDS.push('copilot-credential-guard')
|
|
520
|
-
if (target.id === 'kiro') HARNESS_TARGET_IDS.push('kiro-credential-guard')
|
|
800
|
+
if (target.id === 'codex') HARNESS_TARGET_IDS.push('codex-credential-guard', 'codex-git-branch-guard')
|
|
801
|
+
if (target.id === 'gemini') HARNESS_TARGET_IDS.push('gemini-credential-guard', 'gemini-git-branch-guard')
|
|
802
|
+
if (target.id === 'cursor') HARNESS_TARGET_IDS.push('cursor-credential-guard', 'cursor-git-branch-guard')
|
|
803
|
+
if (target.id === 'copilot') HARNESS_TARGET_IDS.push('copilot-credential-guard', 'copilot-git-branch-guard')
|
|
804
|
+
if (target.id === 'kiro') HARNESS_TARGET_IDS.push('kiro-credential-guard', 'kiro-git-branch-guard')
|
|
521
805
|
HARNESS_TARGET_IDS.push(`${target.id}-agents`, `${target.id}-skills`)
|
|
522
806
|
}
|
|
523
807
|
|
|
@@ -531,22 +815,38 @@ function buildHarnessTargets(homeRoot, identityConfig, { dryRun, installMissing
|
|
|
531
815
|
const targets = []
|
|
532
816
|
if (include('claude-skill')) targets.push(claudeSkillTarget(homeRoot, { dryRun, installMissing }))
|
|
533
817
|
if (include('claude-credential-guard')) targets.push(credentialGuardTargetClaude(homeRoot, { dryRun, installMissing }))
|
|
818
|
+
if (include('claude-git-branch-guard')) targets.push(gitBranchGuardTargetClaude(homeRoot, { dryRun, installMissing }))
|
|
534
819
|
for (const target of catalog.targets) {
|
|
535
820
|
if (target.id === 'codex' && include('codex-credential-guard')) {
|
|
536
821
|
targets.push(credentialGuardTargetCodex(homeRoot, { dryRun, installMissing }))
|
|
537
822
|
}
|
|
823
|
+
if (target.id === 'codex' && include('codex-git-branch-guard')) {
|
|
824
|
+
targets.push(gitBranchGuardTargetCodex(homeRoot, { dryRun, installMissing }))
|
|
825
|
+
}
|
|
538
826
|
if (target.id === 'gemini' && include('gemini-credential-guard')) {
|
|
539
827
|
targets.push(credentialGuardTargetGemini(homeRoot, { dryRun, installMissing }))
|
|
540
828
|
}
|
|
829
|
+
if (target.id === 'gemini' && include('gemini-git-branch-guard')) {
|
|
830
|
+
targets.push(gitBranchGuardTargetGemini(homeRoot, { dryRun, installMissing }))
|
|
831
|
+
}
|
|
541
832
|
if (target.id === 'cursor' && include('cursor-credential-guard')) {
|
|
542
833
|
targets.push(credentialGuardTargetCursor(homeRoot, { dryRun, installMissing }))
|
|
543
834
|
}
|
|
835
|
+
if (target.id === 'cursor' && include('cursor-git-branch-guard')) {
|
|
836
|
+
targets.push(gitBranchGuardTargetCursor(homeRoot, { dryRun, installMissing }))
|
|
837
|
+
}
|
|
544
838
|
if (target.id === 'copilot' && include('copilot-credential-guard')) {
|
|
545
839
|
targets.push(credentialGuardTargetCopilot(homeRoot, { dryRun, installMissing }))
|
|
546
840
|
}
|
|
841
|
+
if (target.id === 'copilot' && include('copilot-git-branch-guard')) {
|
|
842
|
+
targets.push(gitBranchGuardTargetCopilot(homeRoot, { dryRun, installMissing }))
|
|
843
|
+
}
|
|
547
844
|
if (target.id === 'kiro' && include('kiro-credential-guard')) {
|
|
548
845
|
targets.push(credentialGuardTargetKiro(homeRoot, { dryRun, installMissing }))
|
|
549
846
|
}
|
|
847
|
+
if (target.id === 'kiro' && include('kiro-git-branch-guard')) {
|
|
848
|
+
targets.push(gitBranchGuardTargetKiro(homeRoot, { dryRun, installMissing }))
|
|
849
|
+
}
|
|
550
850
|
const agentsId = `${target.id}-agents`
|
|
551
851
|
const skillsId = `${target.id}-skills`
|
|
552
852
|
if (include(agentsId)) targets.push(catalogBundleTarget(target.id, 'agents', homeRoot, identityConfig, { dryRun, installMissing }))
|
|
@@ -589,8 +889,10 @@ function run(options) {
|
|
|
589
889
|
if (!dryRun) {
|
|
590
890
|
if (options.json) {
|
|
591
891
|
silenceConsole(() => generateGlobalCredentialGuardScript(homeRoot))
|
|
892
|
+
silenceConsole(() => generateGlobalGitBranchGuardScript(homeRoot))
|
|
592
893
|
} else {
|
|
593
894
|
generateGlobalCredentialGuardScript(homeRoot)
|
|
895
|
+
generateGlobalGitBranchGuardScript(homeRoot)
|
|
594
896
|
}
|
|
595
897
|
}
|
|
596
898
|
|
|
@@ -625,4 +927,10 @@ module.exports = {
|
|
|
625
927
|
credentialGuardTargetCursor,
|
|
626
928
|
credentialGuardTargetCopilot,
|
|
627
929
|
credentialGuardTargetKiro,
|
|
930
|
+
gitBranchGuardTargetClaude,
|
|
931
|
+
gitBranchGuardTargetCodex,
|
|
932
|
+
gitBranchGuardTargetGemini,
|
|
933
|
+
gitBranchGuardTargetCursor,
|
|
934
|
+
gitBranchGuardTargetCopilot,
|
|
935
|
+
gitBranchGuardTargetKiro,
|
|
628
936
|
}
|
package/src/commands/update.js
CHANGED
|
@@ -207,7 +207,7 @@ function buildProjectTargets(cwd, cfg, identityConfig, { dryRun, installMissing
|
|
|
207
207
|
|
|
208
208
|
if (include('agent-hooks')) targets.push(runFileTarget({
|
|
209
209
|
id: 'agent-hooks',
|
|
210
|
-
path: '.claude/settings.json, .codex/hooks.json, .gemini/settings.json, .kiro/hooks/trackfw-attention.json, .github/hooks/trackfw-attention.json, .cursor/hooks.json, scripts/trackfw-attention-*.sh, scripts/trackfw-credential-guard.sh',
|
|
210
|
+
path: '.claude/settings.json, .codex/hooks.json, .gemini/settings.json, .kiro/hooks/trackfw-attention.json, .github/hooks/trackfw-attention.json, .cursor/hooks.json, scripts/trackfw-attention-*.sh, scripts/trackfw-credential-guard.sh, scripts/trackfw-git-branch-guard.sh',
|
|
211
211
|
root: cwd,
|
|
212
212
|
relPaths: [
|
|
213
213
|
'.claude/settings.json',
|
|
@@ -219,11 +219,13 @@ function buildProjectTargets(cwd, cfg, identityConfig, { dryRun, installMissing
|
|
|
219
219
|
'scripts/trackfw-attention-signal.sh',
|
|
220
220
|
'scripts/trackfw-attention-cleanup.sh',
|
|
221
221
|
'scripts/trackfw-credential-guard.sh',
|
|
222
|
+
'scripts/trackfw-git-branch-guard.sh',
|
|
222
223
|
],
|
|
223
224
|
apply: (root) => {
|
|
224
225
|
hooksGen.injectHooksDetected(root);
|
|
225
226
|
hooksGen.generateAttentionScripts(cfg, root);
|
|
226
227
|
hooksGen.generateCredentialGuardScript(root);
|
|
228
|
+
hooksGen.generateGitBranchGuardScript(root);
|
|
227
229
|
},
|
|
228
230
|
dryRun,
|
|
229
231
|
installMissing,
|