trackfw 6.7.0 → 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 +1 -1
- package/src/generators/hooks.js +43 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trackfw",
|
|
3
|
-
"version": "6.7.
|
|
3
|
+
"version": "6.7.1",
|
|
4
4
|
"description": "Governance CLI for AI-native software delivery and AI coding agents. Enforces traceability: ADR → REQ → ROADMAP → kanban. Native support for Codex, Claude Code, Gemini CLI, Cursor, Copilot, Windsurf, Amazon Q, OpenCode, and Kiro.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
package/src/generators/hooks.js
CHANGED
|
@@ -85,6 +85,24 @@ function mergeClaudeHookArray(existing, matcher, command) {
|
|
|
85
85
|
return arr
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
// migrateClaudeHookCommand rewrites a legacy hook command to a new one, in place, for every entry
|
|
89
|
+
// matching the given matcher inside a Claude PreToolUse/PostToolUse array. Used to fix
|
|
90
|
+
// .claude/settings.json files already written by an older trackfw before a command string changes
|
|
91
|
+
// -- without this, re-running `trackfw init`/`update` only ever appends the new (fixed) command
|
|
92
|
+
// alongside the stale one (merge dedup in mergeClaudeHookArray keys on the exact command string, so
|
|
93
|
+
// it can't tell "same guard, new path" from "a different hook"), leaving the broken entry in place
|
|
94
|
+
// to keep firing and failing forever.
|
|
95
|
+
function migrateClaudeHookCommand(existing, matcher, oldCommand, newCommand) {
|
|
96
|
+
const arr = Array.isArray(existing) ? existing : []
|
|
97
|
+
for (const item of arr) {
|
|
98
|
+
if (!item || item.matcher !== matcher) continue
|
|
99
|
+
const innerHooks = Array.isArray(item.hooks) ? item.hooks : []
|
|
100
|
+
for (const h of innerHooks) {
|
|
101
|
+
if (h && h.command === oldCommand) h.command = newCommand
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
88
106
|
// ---------------------------------------------------------------------------
|
|
89
107
|
// Scripts content
|
|
90
108
|
// ---------------------------------------------------------------------------
|
|
@@ -419,6 +437,16 @@ function generateGlobalCredentialGuardScript(home) {
|
|
|
419
437
|
const SIGNAL_CMD = 'scripts/trackfw-attention-signal.sh'
|
|
420
438
|
const CLEANUP_CMD = 'scripts/trackfw-attention-cleanup.sh'
|
|
421
439
|
const GUARD_CMD = 'scripts/trackfw-credential-guard.sh'
|
|
440
|
+
// Claude Code only (2026-08-09 fix, reported in production against the CMDB project): Claude Code
|
|
441
|
+
// resolves a bare relative hook command against the hook's *dynamic* cwd (tracks `cd`s the agent
|
|
442
|
+
// runs during the session), not the project root -- confirmed against
|
|
443
|
+
// https://code.claude.com/docs/en/hooks: "Handlers run in the current directory... cwd is dynamic".
|
|
444
|
+
// Any Bash/Read/Write/Edit call after the agent `cd`s into a subdirectory (e.g. a monorepo package)
|
|
445
|
+
// made the hook fail with "No such file or directory". $CLAUDE_PROJECT_DIR is the env var Claude
|
|
446
|
+
// Code guarantees stays pinned to the project root regardless of cwd drift (same doc) -- used here
|
|
447
|
+
// instead of GUARD_CMD, matching the pattern this project's own custom hooks already relied on
|
|
448
|
+
// successfully in practice.
|
|
449
|
+
const GUARD_CMD_CLAUDE = '$CLAUDE_PROJECT_DIR/scripts/trackfw-credential-guard.sh'
|
|
422
450
|
|
|
423
451
|
// ---------------------------------------------------------------------------
|
|
424
452
|
// Global credential-guard dedup (ROADMAP-2026-08-06 Wave 3/ML-3A)
|
|
@@ -552,21 +580,30 @@ function injectClaudeHooks(cwd) {
|
|
|
552
580
|
|
|
553
581
|
if (!data.hooks) data.hooks = {}
|
|
554
582
|
data.hooks.PreToolUse = mergeClaudeHookArray(data.hooks.PreToolUse, 'AskUserQuestion', SIGNAL_CMD)
|
|
583
|
+
|
|
584
|
+
// Rewrite any stale relative-path credential-guard command from an older trackfw run before
|
|
585
|
+
// merging the fixed one below, so upgrading doesn't just append a second, still-broken entry
|
|
586
|
+
// alongside the new one (see GUARD_CMD_CLAUDE comment for the "No such file or directory" bug).
|
|
587
|
+
for (const matcher of ['Bash', 'Read', 'Write|Edit']) {
|
|
588
|
+
migrateClaudeHookCommand(data.hooks.PreToolUse, matcher, GUARD_CMD, GUARD_CMD_CLAUDE)
|
|
589
|
+
migrateClaudeHookCommand(data.hooks.PostToolUse, matcher, GUARD_CMD, GUARD_CMD_CLAUDE)
|
|
590
|
+
}
|
|
591
|
+
|
|
555
592
|
// Dedup (ROADMAP-2026-08-06 Wave 3/ML-3A, extended ADR-2026-08-06 emenda 7/ROADMAP-2026-08-08
|
|
556
593
|
// Wave 2 to Read/Write|Edit): skip project-scope credential-guard when the global one is
|
|
557
594
|
// already installed for this CLI.
|
|
558
595
|
if (!globalCredentialGuardInstalledClaude()) {
|
|
559
|
-
data.hooks.PreToolUse = mergeClaudeHookArray(data.hooks.PreToolUse, 'Bash',
|
|
596
|
+
data.hooks.PreToolUse = mergeClaudeHookArray(data.hooks.PreToolUse, 'Bash', GUARD_CMD_CLAUDE)
|
|
560
597
|
// ADR-2026-08-06 emenda 7 (2026-08-08): Read/Write/Edit coverage — extraction via direct
|
|
561
598
|
// file read, or materialization via write/edit, never went through the hook before.
|
|
562
|
-
data.hooks.PreToolUse = mergeClaudeHookArray(data.hooks.PreToolUse, 'Read',
|
|
563
|
-
data.hooks.PreToolUse = mergeClaudeHookArray(data.hooks.PreToolUse, 'Write|Edit',
|
|
599
|
+
data.hooks.PreToolUse = mergeClaudeHookArray(data.hooks.PreToolUse, 'Read', GUARD_CMD_CLAUDE)
|
|
600
|
+
data.hooks.PreToolUse = mergeClaudeHookArray(data.hooks.PreToolUse, 'Write|Edit', GUARD_CMD_CLAUDE)
|
|
564
601
|
}
|
|
565
602
|
data.hooks.PostToolUse = mergeClaudeHookArray(data.hooks.PostToolUse, 'AskUserQuestion', CLEANUP_CMD)
|
|
566
603
|
if (!globalCredentialGuardInstalledClaude()) {
|
|
567
|
-
data.hooks.PostToolUse = mergeClaudeHookArray(data.hooks.PostToolUse, 'Bash',
|
|
568
|
-
data.hooks.PostToolUse = mergeClaudeHookArray(data.hooks.PostToolUse, 'Read',
|
|
569
|
-
data.hooks.PostToolUse = mergeClaudeHookArray(data.hooks.PostToolUse, 'Write|Edit',
|
|
604
|
+
data.hooks.PostToolUse = mergeClaudeHookArray(data.hooks.PostToolUse, 'Bash', GUARD_CMD_CLAUDE)
|
|
605
|
+
data.hooks.PostToolUse = mergeClaudeHookArray(data.hooks.PostToolUse, 'Read', GUARD_CMD_CLAUDE)
|
|
606
|
+
data.hooks.PostToolUse = mergeClaudeHookArray(data.hooks.PostToolUse, 'Write|Edit', GUARD_CMD_CLAUDE)
|
|
570
607
|
}
|
|
571
608
|
|
|
572
609
|
writeJSON(filePath, data)
|