devflow-kit 2.4.0 → 3.0.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.
Files changed (213) hide show
  1. package/CHANGELOG.md +229 -0
  2. package/README.md +111 -18
  3. package/dist/agents/git.md +822 -0
  4. package/dist/cli/commands/agents.js +6 -1
  5. package/dist/cli/commands/ambient.js +160 -145
  6. package/dist/cli/commands/attribution-prompts.js +1 -1
  7. package/dist/cli/commands/capture.js +29 -55
  8. package/dist/cli/commands/compliance-prompts.js +1 -1
  9. package/dist/cli/commands/compliance.js +48 -55
  10. package/dist/cli/commands/context.js +17 -32
  11. package/dist/cli/commands/debug.js +65 -26
  12. package/dist/cli/commands/flags.js +3 -3
  13. package/dist/cli/commands/hud.js +34 -10
  14. package/dist/cli/commands/init-seed.js +61 -27
  15. package/dist/cli/commands/init.js +649 -240
  16. package/dist/cli/commands/install-report.js +200 -0
  17. package/dist/cli/commands/knowledge/index.js +2 -2
  18. package/dist/cli/commands/knowledge/toggle.js +35 -37
  19. package/dist/cli/commands/learning.js +79 -57
  20. package/dist/cli/commands/legacy-hooks.js +11 -14
  21. package/dist/cli/commands/memory.js +134 -135
  22. package/dist/cli/commands/prompt-io.js +4 -4
  23. package/dist/cli/commands/proxy.js +23 -41
  24. package/dist/cli/commands/security.js +81 -29
  25. package/dist/cli/commands/skills.js +71 -7
  26. package/dist/cli/commands/tracker-prompts.js +145 -0
  27. package/dist/cli/commands/tracker.js +277 -0
  28. package/dist/cli/commands/uninstall.js +520 -169
  29. package/dist/cli.js +2 -0
  30. package/dist/commands/bug-analysis.md +58 -14
  31. package/dist/commands/code-review.md +110 -32
  32. package/dist/commands/debug.md +55 -11
  33. package/dist/commands/dynamic-build.md +344 -73
  34. package/dist/commands/dynamic-plan.md +77 -27
  35. package/dist/commands/dynamic-profile.md +25 -11
  36. package/dist/commands/dynamic-tickets.md +76 -15
  37. package/dist/commands/explore.md +37 -7
  38. package/dist/commands/implement.md +314 -62
  39. package/dist/commands/plan.md +146 -32
  40. package/dist/commands/release.md +64 -17
  41. package/dist/commands/research.md +34 -8
  42. package/dist/commands/resolve.md +196 -68
  43. package/dist/commands/self-review.md +45 -9
  44. package/dist/core/agent-models.js +55 -12
  45. package/dist/core/assets.js +58 -2
  46. package/dist/core/compliance-compose.js +27 -27
  47. package/dist/core/evidence-policy.js +363 -0
  48. package/dist/core/feature-config.js +200 -65
  49. package/dist/core/feature-switch.js +112 -0
  50. package/dist/core/flags.js +34 -6
  51. package/dist/core/fs-atomic.js +27 -0
  52. package/dist/core/hook-log-dirs.js +104 -0
  53. package/dist/core/learning-tuning-config.js +5 -3
  54. package/dist/core/ledger-root.js +102 -0
  55. package/dist/core/manifest.js +38 -10
  56. package/dist/core/mds-variants.js +798 -0
  57. package/dist/core/migrations.js +49 -23
  58. package/dist/core/model-discovery.js +12 -1
  59. package/dist/core/plugins.js +361 -12
  60. package/dist/core/project-paths.js +1 -18
  61. package/dist/core/proxy-log.js +8 -6
  62. package/dist/core/proxy-state.js +11 -8
  63. package/dist/core/reference-sweep.js +136 -0
  64. package/dist/core/same-location.js +25 -0
  65. package/dist/core/tracker.js +494 -0
  66. package/dist/hud/components/config-counts.js +15 -4
  67. package/dist/hud/components/learning-counts.js +14 -0
  68. package/dist/hud/config.js +2 -1
  69. package/dist/hud/cost-history.js +2 -4
  70. package/dist/hud/git.js +52 -7
  71. package/dist/hud/index.js +7 -9
  72. package/dist/skills/git/references/decision-markers.md +19 -0
  73. package/dist/skills/git/references/learn-conventions.md +56 -0
  74. package/dist/skills/git/references/pr/check-ci-status.md +14 -0
  75. package/dist/skills/git/references/pr/check-merge-readiness.md +28 -0
  76. package/dist/skills/git/references/pr/ensure-pr-ready.md +24 -0
  77. package/dist/skills/git/references/pr/fetch-review-threads.md +22 -0
  78. package/dist/skills/git/references/pr/post-resolution-summary.md +40 -0
  79. package/dist/skills/git/references/pr/post-review-summary.md +42 -0
  80. package/dist/skills/git/references/pr/resolve-review-threads.md +35 -0
  81. package/dist/skills/git/references/pr/update-pr-evidence.md +14 -0
  82. package/dist/skills/git/references/pr/validate-branch.md +18 -0
  83. package/dist/skills/git/references/publication-gate.md +13 -0
  84. package/dist/skills/git/references/tracker/_mcp.md +153 -0
  85. package/dist/skills/git/references/tracker/github/associate-release.md +18 -0
  86. package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +40 -0
  87. package/dist/skills/git/references/tracker/github/create-release.md +11 -0
  88. package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +16 -0
  89. package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +69 -0
  90. package/dist/skills/git/references/tracker/github/fetch-issue.md +32 -0
  91. package/dist/skills/git/references/tracker/github/fetch-issues-batch.md +17 -0
  92. package/dist/skills/git/references/tracker/github/gather-release-evidence.md +19 -0
  93. package/dist/skills/git/references/tracker/github/manage-debt.md +101 -0
  94. package/dist/skills/git/references/tracker/github/post-wave-report.md +28 -0
  95. package/dist/skills/git/references/tracker/github/setup-task.md +26 -0
  96. package/dist/skills/git/references/tracker/jira/associate-release.md +18 -0
  97. package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +49 -0
  98. package/dist/skills/git/references/tracker/jira/create-release.md +17 -0
  99. package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +22 -0
  100. package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +53 -0
  101. package/dist/skills/git/references/tracker/jira/fetch-issue.md +14 -0
  102. package/dist/skills/git/references/tracker/jira/fetch-issues-batch.md +15 -0
  103. package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +18 -0
  104. package/dist/skills/git/references/tracker/jira/manage-debt.md +37 -0
  105. package/dist/skills/git/references/tracker/jira/post-wave-report.md +33 -0
  106. package/dist/skills/git/references/tracker/jira/setup-task.md +31 -0
  107. package/dist/skills/git/references/tracker/linear/associate-release.md +18 -0
  108. package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +53 -0
  109. package/dist/skills/git/references/tracker/linear/create-release.md +17 -0
  110. package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +22 -0
  111. package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +53 -0
  112. package/dist/skills/git/references/tracker/linear/fetch-issue.md +14 -0
  113. package/dist/skills/git/references/tracker/linear/fetch-issues-batch.md +15 -0
  114. package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +18 -0
  115. package/dist/skills/git/references/tracker/linear/manage-debt.md +37 -0
  116. package/dist/skills/git/references/tracker/linear/post-wave-report.md +33 -0
  117. package/dist/skills/git/references/tracker/linear/setup-task.md +32 -0
  118. package/dist/skills/git/references/trust-rule.md +7 -0
  119. package/dist/targets/claude-code/claude-paths.js +59 -57
  120. package/dist/targets/claude-code/compliance-install.js +49 -65
  121. package/dist/targets/claude-code/hooks.js +108 -3
  122. package/dist/targets/claude-code/installer.js +1187 -32
  123. package/dist/targets/claude-code/legacy.js +5 -0
  124. package/dist/targets/claude-code/post-install.js +366 -151
  125. package/dist/targets/claude-code/tracker-install.js +134 -0
  126. package/package.json +8 -6
  127. package/src/assets/agents/code.md +45 -6
  128. package/src/assets/agents/design.md +2 -1
  129. package/src/assets/agents/git.mds +825 -0
  130. package/src/assets/agents/knowledge.md +3 -3
  131. package/src/assets/agents/learning.md +11 -0
  132. package/src/assets/agents/review.md +3 -1
  133. package/src/assets/agents/synthesize.md +1 -1
  134. package/src/assets/agents/test.md +16 -5
  135. package/src/assets/agents/tracker.md +474 -0
  136. package/src/assets/agents/validate.md +7 -5
  137. package/src/assets/commands/_partials/_compliance.mds +19 -1
  138. package/src/assets/commands/_partials/_decisions.mds +15 -3
  139. package/src/assets/commands/_partials/_docs_root.mds +35 -0
  140. package/src/assets/commands/_partials/_engine.mds +13 -11
  141. package/src/assets/commands/_partials/_evidence_policy.mds +30 -0
  142. package/src/assets/commands/_partials/_factory.mds +1 -1
  143. package/src/assets/commands/_partials/_knowledge.mds +27 -9
  144. package/src/assets/commands/_partials/_plan_contract.mds +22 -7
  145. package/src/assets/commands/_partials/_preamble.mds +2 -2
  146. package/src/assets/commands/_partials/_publication.mds +8 -2
  147. package/src/assets/commands/_partials/_settings.mds +28 -0
  148. package/src/assets/commands/_partials/_ticket_template.mds +3 -2
  149. package/src/assets/commands/_partials/_tracker.mds +18 -0
  150. package/src/assets/commands/_partials/_wave.mds +16 -10
  151. package/src/assets/commands/bug-analysis.mds +31 -19
  152. package/src/assets/commands/code-review.mds +67 -41
  153. package/src/assets/commands/debug.mds +13 -7
  154. package/src/assets/commands/dynamic-build.mds +274 -66
  155. package/src/assets/commands/dynamic-plan.mds +50 -23
  156. package/src/assets/commands/dynamic-profile.mds +24 -11
  157. package/src/assets/commands/dynamic-tickets.mds +63 -16
  158. package/src/assets/commands/explore.mds +4 -5
  159. package/src/assets/commands/implement.mds +234 -67
  160. package/src/assets/commands/plan.mds +91 -33
  161. package/src/assets/commands/release.md +64 -17
  162. package/src/assets/commands/research.mds +11 -9
  163. package/src/assets/commands/resolve.mds +150 -78
  164. package/src/assets/commands/self-review.mds +24 -25
  165. package/src/assets/mds/git/_pr.mds +331 -0
  166. package/src/assets/mds/git/_references.mds +135 -0
  167. package/src/assets/mds/tracker/_common.mds +156 -0
  168. package/src/assets/mds/tracker/_github.mds +472 -0
  169. package/src/assets/mds/tracker/_jira.mds +407 -0
  170. package/src/assets/mds/tracker/_linear.mds +449 -0
  171. package/src/assets/mds/tracker/_mcp.mds +305 -0
  172. package/src/assets/scripts/hooks/assets/orchestrator-charter.md +5 -8
  173. package/src/assets/scripts/hooks/background-memory-update +40 -19
  174. package/src/assets/scripts/hooks/capture-prompt +18 -8
  175. package/src/assets/scripts/hooks/capture-question +18 -8
  176. package/src/assets/scripts/hooks/capture-turn +27 -13
  177. package/src/assets/scripts/hooks/debug-trace +11 -6
  178. package/src/assets/scripts/hooks/ensure-devflow-init +33 -6
  179. package/src/assets/scripts/hooks/ensure-proxy +9 -8
  180. package/src/assets/scripts/hooks/ensure-root-gitignore +236 -60
  181. package/src/assets/scripts/hooks/git-marker +48 -0
  182. package/src/assets/scripts/hooks/hook-log-init +3 -1
  183. package/src/assets/scripts/hooks/json-helper.cjs +228 -5
  184. package/src/assets/scripts/hooks/lib/project-paths.cjs +1 -20
  185. package/src/assets/scripts/hooks/log-paths +80 -0
  186. package/src/assets/scripts/hooks/memory-worker +22 -13
  187. package/src/assets/scripts/hooks/pre-compact-memory +44 -15
  188. package/src/assets/scripts/hooks/preamble +1 -4
  189. package/src/assets/scripts/hooks/queue-append +146 -28
  190. package/src/assets/scripts/hooks/resolve-project-root +101 -7
  191. package/src/assets/scripts/hooks/session-start-context +534 -20
  192. package/src/assets/scripts/hooks/session-start-memory +38 -15
  193. package/src/assets/scripts/lib/project-config.cjs +633 -0
  194. package/src/assets/scripts/pr-evidence.cjs +1961 -0
  195. package/src/assets/scripts/redact-secrets.cjs +490 -62
  196. package/src/assets/scripts/release-trace.cjs +1143 -0
  197. package/src/assets/scripts/resolve-evidence-policy.cjs +1145 -0
  198. package/src/assets/scripts/resolve-settings.cjs +1054 -0
  199. package/src/assets/scripts/verify-evidence.cjs +1822 -0
  200. package/src/assets/skills/compliance/SKILL.md +4 -2
  201. package/src/assets/skills/docs-framework/SKILL.md +11 -10
  202. package/src/assets/skills/docs-framework/references/patterns.md +10 -17
  203. package/src/assets/skills/gap-analysis/SKILL.md +2 -2
  204. package/src/assets/skills/git/SKILL.md +8 -78
  205. package/src/assets/skills/git/references/github-api.md +179 -141
  206. package/src/assets/skills/git/references/patterns.md +11 -6
  207. package/src/assets/skills/review-methodology/SKILL.md +1 -1
  208. package/src/assets/skills/review-methodology/references/patterns.md +6 -61
  209. package/src/assets/skills/review-methodology/references/violations.md +14 -22
  210. package/src/assets/skills/worktree-support/SKILL.md +1 -1
  211. package/src/assets/skills/worktree-support/references/roots.md +29 -0
  212. package/src/targets/claude-code/templates/managed-settings.json +25 -9
  213. package/src/assets/agents/git.md +0 -938
@@ -0,0 +1,277 @@
1
+ /**
2
+ * devflow tracker — Show or set the machine's issue tracker provider.
3
+ *
4
+ * D-TRACKER-PAIR [DR-25]: `src/core/tracker.ts` (domain) +
5
+ * `src/cli/commands/tracker.ts` (CLI) mirrors the `compliance.ts` pair
6
+ * exactly; ADR-013's pure-core / I/O-target split is the reason both names
7
+ * exist. A reviewer meeting several `tracker*` files in one commit otherwise
8
+ * has no signal that the duplication is deliberate.
9
+ *
10
+ * Applies ADR-013: CLI-layer module; the provider domain, the strict parser and
11
+ * the ~/.devflow file lifecycle all live in src/core/tracker.ts.
12
+ * The manifest holds the MACHINE default. A repository may select its own
13
+ * provider in its committed `.devflow/project.json` (resolved by
14
+ * resolve-settings.cjs); `--status` names it on an `Effective:` line when one
15
+ * does, and `--set` never touches it.
16
+ * Avoids PF-015: --set converges the sentinel in BOTH directions, so flipping
17
+ * back to github removes what flipping away wrote.
18
+ * Avoids PF-009: a failed re-arm or sentinel step warns, it never aborts.
19
+ */
20
+ import { Command } from 'commander';
21
+ import { promises as fs } from 'fs';
22
+ import * as path from 'path';
23
+ import * as p from '@clack/prompts';
24
+ import color from 'picocolors';
25
+ import { DEFAULT_TRACKER_PROVIDER, TRACKER_ATTEMPTS_MAX, TRACKER_CONVENTIONS_READ_BYTES, TRACKER_PROVIDERS, applyTrackerSentinel, describeTrackerValue, parseTrackerFrontmatter, parseTrackerId, readBoundedHead, rearmTrackerInference, trackerConventionsPath, } from '../../core/tracker.js';
26
+ import { readManifest, syncManifestFeature } from '../../core/manifest.js';
27
+ import { loadSettingsModule, personalConfigTrackedWarning, repoTrackerSelection } from '../../core/evidence-policy.js';
28
+ import { getClaudeDirectory, getDevFlowDirectory } from '../../targets/claude-code/claude-paths.js';
29
+ import { SKILL_REFS_SKILL_NAME, installedReferenceManifest } from '../../core/mds-variants.js';
30
+ import { prefixSkillName } from '../../core/plugins.js';
31
+ /**
32
+ * Read the provenance header of `~/.devflow/tracker/{provider}.md`.
33
+ *
34
+ * Never throws (PF-014): an absent, unreadable, or non-regular path is `absent`.
35
+ * Only the bounded head of the file is read and only the leading frontmatter
36
+ * block is scanned — through the one frontmatter parser the migration also uses —
37
+ * and nothing read here is trusted: every value is rendered through
38
+ * `describeTrackerValue`, because the file is hand-editable and machine-wide, so
39
+ * its content is third-party input at every sink.
40
+ */
41
+ export async function readTrackerProvenance(devflowDir, provider) {
42
+ const head = await readBoundedHead(trackerConventionsPath(devflowDir, provider), TRACKER_CONVENTIONS_READ_BYTES);
43
+ if (head === undefined)
44
+ return { kind: 'absent' };
45
+ const { provider: named, inferredFrom } = parseTrackerFrontmatter(head);
46
+ return { kind: 'present', provider: named, inferredFrom };
47
+ }
48
+ /**
49
+ * Count the installed tracker mechanics.
50
+ *
51
+ * Counts what is PRESENT against the install manifest — every provider's, since
52
+ * every install carries them all (D-INSTALL-ALL-PROVIDERS) — rather than listing
53
+ * the directory: the question a user asks `--status` is "can the agent load what
54
+ * it is told to load?", and a stray file in the tree is not an answer to it.
55
+ * Never throws (PF-014).
56
+ */
57
+ export async function readTrackerMechanics(claudeDir) {
58
+ const root = path.join(claudeDir, 'skills', prefixSkillName(SKILL_REFS_SKILL_NAME), 'references');
59
+ let present = 0;
60
+ for (const rel of installedReferenceManifest()) {
61
+ try {
62
+ await fs.access(path.join(root, ...rel.split('/')));
63
+ present++;
64
+ }
65
+ catch (err) {
66
+ const code = err.code;
67
+ // ENOENT is the file simply not being there — that is a count of zero for
68
+ // this entry, not a failure to look. Anything else IS a failure to look.
69
+ if (code !== undefined && code !== 'ENOENT')
70
+ return { kind: 'unreadable', errno: code };
71
+ }
72
+ }
73
+ return present === 0 ? { kind: 'missing' } : { kind: 'installed', count: present };
74
+ }
75
+ /** Render the mechanics state for the `--status` note. Pure. */
76
+ export function formatTrackerMechanics(state) {
77
+ switch (state.kind) {
78
+ case 'installed':
79
+ return `installed (${state.count} file(s))`;
80
+ case 'missing':
81
+ return 'MISSING — run devflow init';
82
+ case 'unreadable':
83
+ return `unreadable (${state.errno})`;
84
+ default: {
85
+ const _exhaustive = state;
86
+ void _exhaustive;
87
+ return 'unknown';
88
+ }
89
+ }
90
+ }
91
+ /** Render a provenance value for the `--status` note. Pure; bounded; sanitised. */
92
+ export function formatTrackerProvenance(provenance) {
93
+ if (provenance.kind === 'absent') {
94
+ return 'not present (learned in the background at a session start)';
95
+ }
96
+ const parts = ['present'];
97
+ if (provenance.provider !== undefined) {
98
+ parts.push(`provider: ${describeTrackerValue(provenance.provider)}`);
99
+ }
100
+ if (provenance.inferredFrom !== undefined) {
101
+ parts.push(`inferred from: ${describeTrackerValue(provenance.inferredFrom)}`);
102
+ }
103
+ return parts.join(' — ');
104
+ }
105
+ /** Read the conventions `--status` reports for `provider`. Never throws: see readTrackerProvenance. */
106
+ export async function readTrackerStatusConventions(devflowDir, provider) {
107
+ if (provider === DEFAULT_TRACKER_PROVIDER)
108
+ return { kind: 'none' };
109
+ return {
110
+ kind: 'learned',
111
+ file: trackerConventionsPath(devflowDir, provider),
112
+ provenance: await readTrackerProvenance(devflowDir, provider),
113
+ };
114
+ }
115
+ /**
116
+ * The `--status` note's lines. Pure.
117
+ *
118
+ * The `Effective:` line appears ONLY when a repository layer selects the tracker
119
+ * (`selection` non-null) — `Effective: jira (project)` — so a machine whose own
120
+ * provider decides prints the same five labels it always has. The conventions
121
+ * lines describe the provider in effect HERE, which is the one whose file a
122
+ * session in this repository learns and a Git spawn in it reads.
123
+ */
124
+ export function formatTrackerStatus(input) {
125
+ const providerLabel = input.machine === DEFAULT_TRACKER_PROVIDER
126
+ ? `${color.green(input.machine)} ${color.dim('(default)')}`
127
+ : color.green(input.machine);
128
+ const lines = [`Provider: ${providerLabel}`];
129
+ if (input.selection !== null) {
130
+ lines.push(`Effective: ${color.green(input.selection.provider)} (${input.selection.source})`);
131
+ }
132
+ lines.push(...(input.conventions.kind === 'none'
133
+ ? ['Conventions: none (GitHub needs no learned conventions)', 'File: none']
134
+ : [`Conventions: ${formatTrackerProvenance(input.conventions.provenance)}`, `File: ${input.conventions.file}`]), `Mechanics: ${formatTrackerMechanics(input.mechanics)}`, `Inference: ${input.inference}`);
135
+ return lines.join('\n');
136
+ }
137
+ /** The real adapter — the ONE binding of each operation into the `--set` path. */
138
+ export function buildTrackerSetIO() {
139
+ return {
140
+ syncManifest: (devflowDir, state) => syncManifestFeature(devflowDir, 'tracker', state),
141
+ rearmInference: rearmTrackerInference,
142
+ applySentinel: applyTrackerSentinel,
143
+ };
144
+ }
145
+ /**
146
+ * Select the machine's default tracker provider.
147
+ *
148
+ * D-TRACKER-CONVERGE-SET: `--set` writes exactly three things, in this order —
149
+ *
150
+ * 1. the manifest (the machine default; what every other step names)
151
+ * 2. the attempt counters (re-armed, so the new provider gets its five tries)
152
+ * 3. the sentinel (the provider's name, or removed for github)
153
+ *
154
+ * and nothing else. Every provider's mechanics and the Tracker agent are already
155
+ * installed (D-INSTALL-ALL-PROVIDERS), so a selection change has no reference tree
156
+ * to swap and no agent to add or remove; and each provider keeps its own
157
+ * conventions file (D-TRACKER-PER-PROVIDER-CONVENTIONS), so there is nothing to
158
+ * move aside. The sentinel follows the manifest because it ADVERTISES the value
159
+ * the manifest records, and must never get ahead of it.
160
+ *
161
+ * Never throws, except where the manifest writer does. The re-arm and sentinel
162
+ * steps warn rather than abort: each degrades a working install, never breaks it.
163
+ */
164
+ export async function runTrackerSet(opts) {
165
+ const { devflowDir, current, requested, io } = opts;
166
+ const messages = [];
167
+ await io.syncManifest(devflowDir, { provider: requested });
168
+ // [DR-22] a selection change re-arms the attempt counters; [DR-10] the
169
+ // sentinel converges in both directions.
170
+ const rearm = await io.rearmInference(devflowDir);
171
+ if (!rearm.ok)
172
+ messages.push({ level: 'warn', text: rearm.error });
173
+ const sentinel = await io.applySentinel(devflowDir, requested);
174
+ if (!sentinel.ok)
175
+ messages.push({ level: 'warn', text: sentinel.error });
176
+ const unchanged = requested === current.provider;
177
+ messages.push({
178
+ level: unchanged ? 'info' : 'success',
179
+ text: unchanged ? `Tracker: ${requested} (unchanged)` : `Tracker: ${requested}`,
180
+ });
181
+ return { provider: requested, messages };
182
+ }
183
+ export const trackerCommand = new Command('tracker')
184
+ .description('Show or set the machine\'s issue tracker provider')
185
+ .option('--status', 'Show the provider in effect and its learned conventions file, and re-arm background inference')
186
+ .option('--set <id>', 'Set the machine\'s default issue tracker provider: github, jira, or linear')
187
+ .action(async (options) => {
188
+ const devflowDir = getDevFlowDirectory();
189
+ const hasFlag = options.status || options.set !== undefined;
190
+ if (!hasFlag) {
191
+ p.intro(color.bgCyan(color.white(' Tracker ')));
192
+ const validIds = TRACKER_PROVIDERS.map(t => `${t.id} — ${t.hint}`).join('\n ');
193
+ p.note(`${color.cyan('devflow tracker --status')} Show the provider and learned conventions\n` +
194
+ `${color.cyan('devflow tracker --set <id>')} Set the machine's default provider\n\n` +
195
+ `Valid provider IDs:\n ${validIds}`, 'Usage');
196
+ p.outro(color.dim('github is the default — devflow tracker --set github returns to it'));
197
+ return;
198
+ }
199
+ // Validate --set input before any I/O (parse-don't-validate at the boundary).
200
+ let setProvider;
201
+ if (options.set !== undefined) {
202
+ const parsed = parseTrackerId(options.set);
203
+ if (!parsed.ok) {
204
+ p.log.error(parsed.error);
205
+ process.exit(1);
206
+ }
207
+ setProvider = parsed.value;
208
+ }
209
+ const manifest = await readManifest(devflowDir);
210
+ if (!manifest) {
211
+ p.log.error('No manifest found. Run devflow init first.');
212
+ process.exit(1);
213
+ }
214
+ const current = manifest.features.tracker;
215
+ // ── Status ─────────────────────────────────────────────────────────────────
216
+ // --status wins when both flags are passed, mirroring `devflow compliance`.
217
+ if (options.status) {
218
+ const settingsModule = loadSettingsModule();
219
+ const selection = repoTrackerSelection(settingsModule, { dir: process.cwd() });
220
+ const effective = selection?.provider ?? current.provider;
221
+ const conventions = await readTrackerStatusConventions(devflowDir, effective);
222
+ const mechanics = await readTrackerMechanics(getClaudeDirectory());
223
+ // [D-F] Inspecting the status re-arms the attempt counters. --status is
224
+ // the command a capped user reaches for to find out why nothing is being
225
+ // learned, so it is the command that has to hand back another five
226
+ // tries; the alternative leaves the only escape a hand deletion of an
227
+ // undocumented dotfile. Every other --status in this CLI is a pure read,
228
+ // so this one reports the write it makes as a line of the note below — a
229
+ // machine-state change the output does not mention is a change the user
230
+ // cannot audit. Non-fatal exactly as on the --set path (avoids PF-009): a
231
+ // failed re-arm warns, it never aborts the report the user asked for.
232
+ const statusRearm = await rearmTrackerInference(devflowDir);
233
+ const inference = statusRearm.ok
234
+ ? `re-armed (${TRACKER_ATTEMPTS_MAX} attempts available)`
235
+ : 're-arm failed — see the warning below';
236
+ p.note(formatTrackerStatus({
237
+ machine: current.provider,
238
+ selection,
239
+ conventions,
240
+ mechanics,
241
+ inference,
242
+ }), 'Tracker Status');
243
+ if (!statusRearm.ok)
244
+ p.log.warn(statusRearm.error);
245
+ const trackedWarning = personalConfigTrackedWarning(settingsModule, { dir: process.cwd() });
246
+ if (trackedWarning !== null)
247
+ p.log.warn(trackedWarning);
248
+ return;
249
+ }
250
+ // ── Set ────────────────────────────────────────────────────────────────────
251
+ const outcome = await runTrackerSet({
252
+ devflowDir,
253
+ current,
254
+ requested: setProvider ?? current.provider,
255
+ io: buildTrackerSetIO(),
256
+ });
257
+ for (const msg of outcome.messages) {
258
+ switch (msg.level) {
259
+ case 'success':
260
+ p.log.success(msg.text);
261
+ break;
262
+ case 'warn':
263
+ p.log.warn(msg.text);
264
+ break;
265
+ case 'error':
266
+ p.log.error(msg.text);
267
+ break;
268
+ default:
269
+ p.log.info(msg.text);
270
+ break;
271
+ }
272
+ }
273
+ if (outcome.provider !== DEFAULT_TRACKER_PROVIDER) {
274
+ p.log.info(color.dim('Your issue conventions are learned in the background at the next session start'));
275
+ }
276
+ });
277
+ //# sourceMappingURL=tracker.js.map