trackfw 7.5.0 → 7.5.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trackfw",
|
|
3
|
-
"version": "7.5.
|
|
3
|
+
"version": "7.5.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",
|
|
@@ -7,7 +7,7 @@ const identityStore = require('../identity')
|
|
|
7
7
|
const projectConfig = require('../config')
|
|
8
8
|
const { catalog, buildPlans, IntegrationManager, globalGroupPath } = require('../integrations')
|
|
9
9
|
const { tildeify, validateTargets, buildDocument, humanReport, silenceConsole } = require('../lib/update-engine')
|
|
10
|
-
const { mergeClaudeHookArray, mergeSimpleCommandArray, mergeCopilotHookArray,
|
|
10
|
+
const { mergeClaudeHookArray, mergeSimpleCommandArray, mergeCopilotHookArray, GIT_BRANCH_GUARD_SCRIPT, GLOBAL_CREDENTIAL_GUARD_SCRIPT } = require('../generators/hooks')
|
|
11
11
|
const { homedir } = require('../homedir')
|
|
12
12
|
|
|
13
13
|
// `trackfw update harness` is the global counterpart to `trackfw update` —
|
|
@@ -73,6 +73,72 @@ Cadeia: **ADR → REQ → ROADMAP** · Estados: \`backlog / wip / blocked / done
|
|
|
73
73
|
`
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
// gitBranchGuardScriptTarget — evaluates (and, unless --dry-run, applies) the
|
|
77
|
+
// global git-branch-guard shell script at
|
|
78
|
+
// ~/.trackfw/scripts/trackfw-git-branch-guard.sh.
|
|
79
|
+
//
|
|
80
|
+
// This target OWNS the script file. It compares content before writing so that
|
|
81
|
+
// an already up-to-date script reports "skipped" and its mtime is left unchanged
|
|
82
|
+
// (REQ-2026-09-09 AC3). Creation does not require --install-missing because
|
|
83
|
+
// ~/.trackfw/scripts/ is 100% trackfw-owned.
|
|
84
|
+
function gitBranchGuardScriptTarget(homeRoot, { dryRun }) {
|
|
85
|
+
const id = 'git-branch-guard-script'
|
|
86
|
+
const filePath = path.join(homeRoot, '.trackfw', 'scripts', 'trackfw-git-branch-guard.sh')
|
|
87
|
+
const displayPath = tildeify(homeRoot, filePath)
|
|
88
|
+
const desired = GIT_BRANCH_GUARD_SCRIPT
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const exists = fs.existsSync(filePath)
|
|
92
|
+
const actual = exists ? fs.readFileSync(filePath, 'utf8') : null
|
|
93
|
+
|
|
94
|
+
if (exists && actual === desired) {
|
|
95
|
+
// Content identical — skip write, repair execute bit without touching mtime.
|
|
96
|
+
try { fs.chmodSync(filePath, 0o755) } catch (_) { /* best-effort */ }
|
|
97
|
+
return { id, state: 'skipped', path: displayPath }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
101
|
+
|
|
102
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
103
|
+
fs.writeFileSync(filePath, desired, { encoding: 'utf8', mode: 0o755 })
|
|
104
|
+
return { id, state: 'updated', path: displayPath }
|
|
105
|
+
} catch (e) {
|
|
106
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// credentialGuardScriptTarget — evaluates (and, unless --dry-run, applies) the
|
|
111
|
+
// global credential-guard shell script at
|
|
112
|
+
// ~/.trackfw/scripts/trackfw-credential-guard.sh.
|
|
113
|
+
//
|
|
114
|
+
// Mirrors gitBranchGuardScriptTarget — same ownership model, same idempotency
|
|
115
|
+
// contract, same absence of --install-missing gate.
|
|
116
|
+
function credentialGuardScriptTarget(homeRoot, { dryRun }) {
|
|
117
|
+
const id = 'credential-guard-script'
|
|
118
|
+
const filePath = path.join(homeRoot, '.trackfw', 'scripts', 'trackfw-credential-guard.sh')
|
|
119
|
+
const displayPath = tildeify(homeRoot, filePath)
|
|
120
|
+
const desired = GLOBAL_CREDENTIAL_GUARD_SCRIPT
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const exists = fs.existsSync(filePath)
|
|
124
|
+
const actual = exists ? fs.readFileSync(filePath, 'utf8') : null
|
|
125
|
+
|
|
126
|
+
if (exists && actual === desired) {
|
|
127
|
+
// Content identical — skip write, repair execute bit without touching mtime.
|
|
128
|
+
try { fs.chmodSync(filePath, 0o755) } catch (_) { /* best-effort */ }
|
|
129
|
+
return { id, state: 'skipped', path: displayPath }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (dryRun) return { id, state: 'updated', path: displayPath }
|
|
133
|
+
|
|
134
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
135
|
+
fs.writeFileSync(filePath, desired, { encoding: 'utf8', mode: 0o755 })
|
|
136
|
+
return { id, state: 'updated', path: displayPath }
|
|
137
|
+
} catch (e) {
|
|
138
|
+
return { id, state: 'failed', path: displayPath, message: e.message }
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
76
142
|
function claudeSkillTarget(homeRoot, { dryRun, installMissing }) {
|
|
77
143
|
const id = 'claude-skill'
|
|
78
144
|
const filePath = path.join(homeRoot, '.claude', 'skills', 'trackfw', 'SKILL.md')
|
|
@@ -799,7 +865,10 @@ function catalogBundleTarget(toolId, kind, homeRoot, identityConfig, { dryRun, i
|
|
|
799
865
|
// which precede claude-agents/claude-skills), with credential-guard always
|
|
800
866
|
// preceding git-branch-guard within a tool — see buildHarnessTargetIDs's
|
|
801
867
|
// comment in update.go for the full rationale.
|
|
802
|
-
|
|
868
|
+
// Script targets precede every wiring target that references them so that even
|
|
869
|
+
// a --targets-filtered run that only requests a wiring target still finds the
|
|
870
|
+
// script already in place from a prior full run.
|
|
871
|
+
const HARNESS_TARGET_IDS = ['claude-skill', 'git-branch-guard-script', 'credential-guard-script', 'claude-credential-guard', 'claude-git-branch-guard']
|
|
803
872
|
for (const target of catalog.targets) {
|
|
804
873
|
if (target.id === 'codex') HARNESS_TARGET_IDS.push('codex-credential-guard', 'codex-git-branch-guard')
|
|
805
874
|
if (target.id === 'gemini') HARNESS_TARGET_IDS.push('gemini-credential-guard', 'gemini-git-branch-guard')
|
|
@@ -818,6 +887,8 @@ function buildHarnessTargets(homeRoot, identityConfig, { dryRun, installMissing
|
|
|
818
887
|
const include = (id) => !wanted || wanted.includes(id)
|
|
819
888
|
const targets = []
|
|
820
889
|
if (include('claude-skill')) targets.push(claudeSkillTarget(homeRoot, { dryRun, installMissing }))
|
|
890
|
+
if (include('git-branch-guard-script')) targets.push(gitBranchGuardScriptTarget(homeRoot, { dryRun }))
|
|
891
|
+
if (include('credential-guard-script')) targets.push(credentialGuardScriptTarget(homeRoot, { dryRun }))
|
|
821
892
|
if (include('claude-credential-guard')) targets.push(credentialGuardTargetClaude(homeRoot, { dryRun, installMissing }))
|
|
822
893
|
if (include('claude-git-branch-guard')) targets.push(gitBranchGuardTargetClaude(homeRoot, { dryRun, installMissing }))
|
|
823
894
|
for (const target of catalog.targets) {
|
|
@@ -885,20 +956,11 @@ function run(options) {
|
|
|
885
956
|
const dryRun = Boolean(options.dryRun)
|
|
886
957
|
const installMissing = Boolean(options.installMissing)
|
|
887
958
|
|
|
888
|
-
//
|
|
889
|
-
//
|
|
890
|
-
//
|
|
891
|
-
//
|
|
892
|
-
//
|
|
893
|
-
if (!dryRun) {
|
|
894
|
-
if (options.json) {
|
|
895
|
-
silenceConsole(() => generateGlobalCredentialGuardScript(homeRoot))
|
|
896
|
-
silenceConsole(() => generateGlobalGitBranchGuardScript(homeRoot))
|
|
897
|
-
} else {
|
|
898
|
-
generateGlobalCredentialGuardScript(homeRoot)
|
|
899
|
-
generateGlobalGitBranchGuardScript(homeRoot)
|
|
900
|
-
}
|
|
901
|
-
}
|
|
959
|
+
// NOTE: the script files are now first-class targets ("git-branch-guard-script",
|
|
960
|
+
// "credential-guard-script") positioned before the wiring targets in
|
|
961
|
+
// HARNESS_TARGET_IDS. The pre-loop unconditional writes that used to live here
|
|
962
|
+
// have been removed — the target functions handle creation and idempotency.
|
|
963
|
+
// (REQ-2026-09-09, ML-1A)
|
|
902
964
|
|
|
903
965
|
// Identidade resolvida do disco antes de buildPlans — pular esta etapa
|
|
904
966
|
// reverteria silenciosamente os nomes customizados para os defaults
|