trackfw 7.5.0 → 7.6.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/package.json +1 -1
- package/src/commands/barrier.js +104 -34
- package/src/commands/branch.js +4 -2
- package/src/commands/commit.js +4 -2
- package/src/commands/req.js +3 -2
- package/src/commands/roadmap.js +3 -2
- package/src/commands/serve.js +124 -17
- package/src/commands/update-harness.js +78 -16
- package/src/config/index.js +21 -0
- package/src/generators/hooks.js +1 -0
- package/src/generators/init.js +31 -6
- package/src/generators/req.js +11 -2
- package/src/generators/roadmap.js +79 -13
- package/src/integrations/index.js +22 -0
- package/src/integrations/register-agent.js +106 -0
- package/src/push/runner.js +5 -2
- package/src/serve/api_file.js +48 -11
- package/src/ship/runner.js +3 -2
- package/src/validator/index.js +52 -8
package/src/validator/index.js
CHANGED
|
@@ -414,18 +414,33 @@ function listReqMdFiles(dir) {
|
|
|
414
414
|
} catch (_) { return [] }
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
+
// resolveAgentForWrite — ponto único de resolução do agente de escrita em modo by_agent.
|
|
418
|
+
// Regra (AC5, AC10, KG 2026-08-29):
|
|
419
|
+
// - explicitAgent fornecido → usa-o (AC4/AC5b: valor fora de agents: é permitido, produz violação de namespace)
|
|
420
|
+
// - agents: com UM namespace → usa aquele, sem erro (AC14: projeto single-agent nunca vê o erro)
|
|
421
|
+
// - agents: vazio → usa "default"
|
|
422
|
+
// - agents: com VÁRIOS → lança erro nomeando todas as opções (AC5: silêncio de agents[0] deixa de existir)
|
|
423
|
+
// Nomes vazios em agents: não contam (agents: ["", "zeus"] é UM namespace) — filter antes de contar.
|
|
424
|
+
function resolveAgentForWrite(cfg, explicitAgent) {
|
|
425
|
+
if (explicitAgent) return explicitAgent
|
|
426
|
+
const agents = (cfg.agents || []).filter(a => a)
|
|
427
|
+
if (agents.length === 0) return 'default'
|
|
428
|
+
if (agents.length === 1) return agents[0]
|
|
429
|
+
throw new Error(`by_agent project has multiple agent namespaces (${agents.join(', ')}): use --agent to specify one`)
|
|
430
|
+
}
|
|
431
|
+
|
|
417
432
|
// reqWriteDir é o PONTO ÚNICO que decide ONDE uma REQ nova é gravada (ADR-2026-09-03, D2/D4):
|
|
418
433
|
// flat → req_dir/
|
|
419
|
-
// by_agent → req_dir/<agente>/ (
|
|
434
|
+
// by_agent → req_dir/<agente>/ (agente resolvido via resolveAgentForWrite — AC4/AC5/AC10)
|
|
420
435
|
// Consumido pelo gerador (newREQ); a união de leitura abaixo contém este diretório por construção.
|
|
421
|
-
|
|
436
|
+
// Lança Error em by_agent com múltiplos namespaces e sem agente explícito (AC5).
|
|
437
|
+
function reqWriteDir(cfg, agent) {
|
|
422
438
|
const reqDir = cfg.reqDir || cfg.req_dir || ''
|
|
423
439
|
if (!reqDir) return ''
|
|
424
440
|
const namespacing = cfg.roadmapNamespacing || cfg.roadmap_namespacing || ''
|
|
425
441
|
if (namespacing === 'by_agent') {
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
return path.join(reqDir, agent)
|
|
442
|
+
const resolvedAgent = resolveAgentForWrite(cfg, agent)
|
|
443
|
+
return path.join(reqDir, resolvedAgent)
|
|
429
444
|
}
|
|
430
445
|
return reqDir
|
|
431
446
|
}
|
|
@@ -1500,12 +1515,37 @@ function branchSlugMatchesRoadmap(branchSlug, wipDirs, doneDirs) {
|
|
|
1500
1515
|
return { matched, candidates }
|
|
1501
1516
|
}
|
|
1502
1517
|
|
|
1518
|
+
// isMultiAgentByAgent returns {multi: bool, agents: string[]} — parity with Go's IsMultiAgentByAgent.
|
|
1519
|
+
// multi is true only when roadmap_namespacing is "by_agent" AND there are 2+ non-empty agent names.
|
|
1520
|
+
function isMultiAgentByAgent(cfg) {
|
|
1521
|
+
const ns = cfg.roadmapNamespacing || cfg.roadmap_namespacing || ''
|
|
1522
|
+
if (ns !== 'by_agent') return { multi: false, agents: [] }
|
|
1523
|
+
const nonEmpty = (cfg.agents || []).filter(a => a)
|
|
1524
|
+
if (nonEmpty.length < 2) return { multi: false, agents: nonEmpty }
|
|
1525
|
+
return { multi: true, agents: nonEmpty }
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
// reqNewLine returns the correct `trackfw req new` command for the project — parity with Go's ReqNewLine.
|
|
1529
|
+
function reqNewLine(cfg) {
|
|
1530
|
+
const { multi, agents } = isMultiAgentByAgent(cfg)
|
|
1531
|
+
if (multi) return `trackfw req new --agent <agent> "title" # agents: ${agents.join(', ')}`
|
|
1532
|
+
return 'trackfw req new "title"'
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
// roadmapNewLine returns the correct `trackfw roadmap new` command — parity with Go's RoadmapNewLine.
|
|
1536
|
+
function roadmapNewLine(cfg) {
|
|
1537
|
+
const { multi } = isMultiAgentByAgent(cfg)
|
|
1538
|
+
if (multi) return 'trackfw roadmap new --agent <agent> "title"'
|
|
1539
|
+
return 'trackfw roadmap new "title"'
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1503
1542
|
// branchGovernanceOrientation is the guidance message printed when a feat/fix/refactor branch has
|
|
1504
1543
|
// no roadmap in wip/ nor done/ at all (candidates is empty). Shared by validateBranchHasWIPRoadmap
|
|
1505
1544
|
// and `trackfw branch new` — never duplicate this string. Byte-identical to Go's
|
|
1506
1545
|
// BranchGovernanceOrientation.
|
|
1507
|
-
function branchGovernanceOrientation(branch) {
|
|
1508
|
-
|
|
1546
|
+
function branchGovernanceOrientation(branch, cfg) {
|
|
1547
|
+
const cfgObj = cfg || {}
|
|
1548
|
+
return `branch "${branch}" is a feat/fix/refactor branch but no roadmap is in wip/ nor done/ — create governance artifacts first:\n ${reqNewLine(cfgObj)}\n ${roadmapNewLine(cfgObj)}\n trackfw roadmap move <name> wip`
|
|
1509
1549
|
}
|
|
1510
1550
|
|
|
1511
1551
|
// branchNoMatchingRoadmapMessage is the guidance message printed when roadmaps exist in wip/ or
|
|
@@ -1548,7 +1588,7 @@ function validateBranchHasWIPRoadmap() {
|
|
|
1548
1588
|
if (matched) return []
|
|
1549
1589
|
|
|
1550
1590
|
if (candidates.length === 0) {
|
|
1551
|
-
return [branchGovernanceOrientation(branch)]
|
|
1591
|
+
return [branchGovernanceOrientation(branch, cfg)]
|
|
1552
1592
|
}
|
|
1553
1593
|
return [branchNoMatchingRoadmapMessage(branch, candidates)]
|
|
1554
1594
|
}
|
|
@@ -3962,6 +4002,7 @@ module.exports = {
|
|
|
3962
4002
|
tryListDir,
|
|
3963
4003
|
resolveReqFiles,
|
|
3964
4004
|
reqWriteDir,
|
|
4005
|
+
resolveAgentForWrite,
|
|
3965
4006
|
resolveStateDirs,
|
|
3966
4007
|
resolveWIPDirs,
|
|
3967
4008
|
resolveDoneDirs,
|
|
@@ -3980,6 +4021,9 @@ module.exports = {
|
|
|
3980
4021
|
validateBranchHasWIPRoadmap,
|
|
3981
4022
|
// novas funções — trackfw branch new (extraídas do gate branch_has_wip_roadmap)
|
|
3982
4023
|
branchSlugMatchesRoadmap,
|
|
4024
|
+
isMultiAgentByAgent,
|
|
4025
|
+
reqNewLine,
|
|
4026
|
+
roadmapNewLine,
|
|
3983
4027
|
branchGovernanceOrientation,
|
|
3984
4028
|
branchNoMatchingRoadmapMessage,
|
|
3985
4029
|
normalizeBranchSlug,
|