@karthikrajkumar.kannan/get-things-done 1.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 (177) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +237 -0
  3. package/agents/backward/gtd-accuracy-verifier.md +198 -0
  4. package/agents/backward/gtd-api-doc-writer.md +130 -0
  5. package/agents/backward/gtd-api-extractor.md +128 -0
  6. package/agents/backward/gtd-architecture-analyzer.md +144 -0
  7. package/agents/backward/gtd-capacity-writer.md +123 -0
  8. package/agents/backward/gtd-codebase-mapper.md +274 -0
  9. package/agents/backward/gtd-completeness-auditor.md +129 -0
  10. package/agents/backward/gtd-data-flow-tracer.md +104 -0
  11. package/agents/backward/gtd-dependency-analyzer.md +98 -0
  12. package/agents/backward/gtd-diagram-generator.md +152 -0
  13. package/agents/backward/gtd-hld-writer.md +123 -0
  14. package/agents/backward/gtd-lld-writer.md +126 -0
  15. package/agents/backward/gtd-pattern-detector.md +111 -0
  16. package/agents/backward/gtd-performance-profiler.md +93 -0
  17. package/agents/backward/gtd-runbook-writer.md +126 -0
  18. package/agents/backward/gtd-security-scanner.md +106 -0
  19. package/agents/backward/gtd-sysdesign-writer.md +137 -0
  20. package/agents/backward/gtd-tdd-writer.md +125 -0
  21. package/agents/forward/gtd-code-reviewer.md +130 -0
  22. package/agents/forward/gtd-debugger.md +133 -0
  23. package/agents/forward/gtd-deployer.md +110 -0
  24. package/agents/forward/gtd-executor.md +110 -0
  25. package/agents/forward/gtd-phase-researcher.md +114 -0
  26. package/agents/forward/gtd-plan-checker.md +132 -0
  27. package/agents/forward/gtd-planner.md +136 -0
  28. package/agents/forward/gtd-project-researcher.md +106 -0
  29. package/agents/forward/gtd-research-synthesizer.md +99 -0
  30. package/agents/forward/gtd-roadmapper.md +126 -0
  31. package/agents/forward/gtd-test-runner.md +119 -0
  32. package/agents/forward/gtd-verifier.md +115 -0
  33. package/agents/sync/gtd-alignment-auditor.md +222 -0
  34. package/agents/sync/gtd-drift-detector.md +222 -0
  35. package/agents/sync/gtd-reconciliation-planner.md +194 -0
  36. package/bin/gtd-tools.cjs +89 -0
  37. package/bin/install.js +164 -0
  38. package/commands/gtd/backward/analyze.md +42 -0
  39. package/commands/gtd/backward/create-all.md +32 -0
  40. package/commands/gtd/backward/create-api-docs.md +33 -0
  41. package/commands/gtd/backward/create-capacity.md +33 -0
  42. package/commands/gtd/backward/create-hld.md +33 -0
  43. package/commands/gtd/backward/create-lld.md +33 -0
  44. package/commands/gtd/backward/create-runbook.md +33 -0
  45. package/commands/gtd/backward/create-sysdesign.md +33 -0
  46. package/commands/gtd/backward/create-tdd.md +33 -0
  47. package/commands/gtd/backward/diff.md +22 -0
  48. package/commands/gtd/backward/doc-status.md +24 -0
  49. package/commands/gtd/backward/review-docs.md +22 -0
  50. package/commands/gtd/backward/scan.md +32 -0
  51. package/commands/gtd/backward/update-docs.md +30 -0
  52. package/commands/gtd/backward/verify-docs.md +28 -0
  53. package/commands/gtd/forward/add-phase.md +28 -0
  54. package/commands/gtd/forward/autonomous.md +28 -0
  55. package/commands/gtd/forward/code-review.md +28 -0
  56. package/commands/gtd/forward/complete-milestone.md +28 -0
  57. package/commands/gtd/forward/debug.md +28 -0
  58. package/commands/gtd/forward/discuss-phase.md +29 -0
  59. package/commands/gtd/forward/execute-phase.md +28 -0
  60. package/commands/gtd/forward/fast.md +28 -0
  61. package/commands/gtd/forward/new-milestone.md +28 -0
  62. package/commands/gtd/forward/new-project.md +29 -0
  63. package/commands/gtd/forward/next.md +28 -0
  64. package/commands/gtd/forward/plan-phase.md +29 -0
  65. package/commands/gtd/forward/progress.md +28 -0
  66. package/commands/gtd/forward/quick.md +28 -0
  67. package/commands/gtd/forward/ship.md +28 -0
  68. package/commands/gtd/forward/verify-work.md +28 -0
  69. package/commands/gtd/sync/audit.md +27 -0
  70. package/commands/gtd/sync/drift.md +27 -0
  71. package/commands/gtd/sync/reconcile.md +27 -0
  72. package/commands/gtd/sync/sync.md +27 -0
  73. package/commands/gtd/utility/health.md +53 -0
  74. package/commands/gtd/utility/help.md +61 -0
  75. package/commands/gtd/utility/map-codebase.md +27 -0
  76. package/commands/gtd/utility/settings.md +65 -0
  77. package/commands/gtd/utility/status.md +57 -0
  78. package/contexts/analysis.md +26 -0
  79. package/contexts/execution.md +35 -0
  80. package/contexts/planning.md +33 -0
  81. package/contexts/research.md +26 -0
  82. package/contexts/review.md +27 -0
  83. package/contexts/writing.md +29 -0
  84. package/hooks/gtd-check-update.js +37 -0
  85. package/hooks/gtd-context-monitor.js +32 -0
  86. package/hooks/gtd-prompt-guard.js +35 -0
  87. package/hooks/gtd-statusline.js +32 -0
  88. package/lib/agent-skills.cjs +130 -0
  89. package/lib/analysis.cjs +242 -0
  90. package/lib/config.cjs +255 -0
  91. package/lib/deploy.cjs +222 -0
  92. package/lib/diff-engine.cjs +245 -0
  93. package/lib/docs.cjs +243 -0
  94. package/lib/drift-engine.cjs +202 -0
  95. package/lib/file-ops.cjs +106 -0
  96. package/lib/frontmatter.cjs +100 -0
  97. package/lib/git.cjs +137 -0
  98. package/lib/init.cjs +370 -0
  99. package/lib/installer-core.cjs +197 -0
  100. package/lib/installers/augment.cjs +62 -0
  101. package/lib/installers/claude.cjs +89 -0
  102. package/lib/installers/cline.cjs +96 -0
  103. package/lib/installers/codex.cjs +63 -0
  104. package/lib/installers/copilot.cjs +62 -0
  105. package/lib/installers/cursor.cjs +62 -0
  106. package/lib/installers/gemini.cjs +62 -0
  107. package/lib/installers/opencode.cjs +62 -0
  108. package/lib/installers/windsurf.cjs +62 -0
  109. package/lib/phase.cjs +206 -0
  110. package/lib/roadmap.cjs +156 -0
  111. package/lib/scale-adapter.cjs +192 -0
  112. package/lib/security.cjs +243 -0
  113. package/lib/state.cjs +320 -0
  114. package/lib/template.cjs +218 -0
  115. package/lib/test-runner.cjs +202 -0
  116. package/package.json +76 -0
  117. package/references/agent-contracts.md +157 -0
  118. package/references/analysis-patterns.md +138 -0
  119. package/references/context-budget.md +148 -0
  120. package/references/diagram-conventions.md +88 -0
  121. package/references/document-standards.md +60 -0
  122. package/references/framework-signatures.md +609 -0
  123. package/references/gate-prompts.md +239 -0
  124. package/references/language-analyzers.md +227 -0
  125. package/references/planning-config.md +125 -0
  126. package/references/questioning.md +142 -0
  127. package/references/verification-patterns.md +67 -0
  128. package/templates/backward/api-docs/standard.md +42 -0
  129. package/templates/backward/capacity/standard.md +50 -0
  130. package/templates/backward/formats/compliance-guide.md +45 -0
  131. package/templates/backward/hld/standard.md +62 -0
  132. package/templates/backward/lld/standard.md +63 -0
  133. package/templates/backward/runbook/standard.md +50 -0
  134. package/templates/backward/system-design/standard.md +64 -0
  135. package/templates/backward/tdd/compliance.md +146 -0
  136. package/templates/backward/tdd/enterprise.md +134 -0
  137. package/templates/backward/tdd/standard.md +88 -0
  138. package/templates/backward/tdd/startup.md +51 -0
  139. package/templates/forward/context.md +65 -0
  140. package/templates/forward/phase-prompt.md +109 -0
  141. package/templates/forward/project.md +71 -0
  142. package/templates/forward/requirements.md +74 -0
  143. package/templates/forward/research/ARCHITECTURE.md +118 -0
  144. package/templates/forward/research/FEATURES.md +95 -0
  145. package/templates/forward/research/PITFALLS.md +106 -0
  146. package/templates/forward/research/STACK.md +80 -0
  147. package/templates/forward/research/SUMMARY.md +86 -0
  148. package/templates/forward/roadmap.md +72 -0
  149. package/workflows/backward/analyze-codebase.md +123 -0
  150. package/workflows/backward/create-all.md +53 -0
  151. package/workflows/backward/generate-document.md +182 -0
  152. package/workflows/backward/incremental-update.md +71 -0
  153. package/workflows/backward/review-document.md +102 -0
  154. package/workflows/backward/scan-codebase.md +111 -0
  155. package/workflows/backward/verify-document.md +79 -0
  156. package/workflows/forward/add-phase.md +29 -0
  157. package/workflows/forward/autonomous.md +62 -0
  158. package/workflows/forward/code-review.md +78 -0
  159. package/workflows/forward/complete-milestone.md +45 -0
  160. package/workflows/forward/debug.md +78 -0
  161. package/workflows/forward/deploy-local.md +51 -0
  162. package/workflows/forward/discuss-phase.md +89 -0
  163. package/workflows/forward/execute-phase.md +138 -0
  164. package/workflows/forward/fast.md +64 -0
  165. package/workflows/forward/new-milestone.md +61 -0
  166. package/workflows/forward/new-project.md +126 -0
  167. package/workflows/forward/next.md +49 -0
  168. package/workflows/forward/plan-phase.md +100 -0
  169. package/workflows/forward/progress.md +37 -0
  170. package/workflows/forward/quick.md +65 -0
  171. package/workflows/forward/ship.md +40 -0
  172. package/workflows/forward/test-phase.md +47 -0
  173. package/workflows/forward/verify-work.md +52 -0
  174. package/workflows/sync/audit.md +110 -0
  175. package/workflows/sync/detect-drift.md +122 -0
  176. package/workflows/sync/reconcile.md +113 -0
  177. package/workflows/sync/sync.md +150 -0
@@ -0,0 +1,106 @@
1
+ /**
2
+ * GTD File Operations — Atomic writes, directory utilities, project root detection.
3
+ * @module lib/file-ops
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ /**
12
+ * Write content to a file atomically.
13
+ * Writes to a temp file first, then renames (atomic on same filesystem).
14
+ * Prevents corruption if the process crashes mid-write.
15
+ *
16
+ * @param {string} targetPath - Absolute path to write to
17
+ * @param {string} content - File content
18
+ */
19
+ function atomicWrite(targetPath, content) {
20
+ const tmpPath = targetPath + '.tmp.' + process.pid;
21
+ try {
22
+ const dir = path.dirname(targetPath);
23
+ if (!fs.existsSync(dir)) {
24
+ fs.mkdirSync(dir, { recursive: true });
25
+ }
26
+ fs.writeFileSync(tmpPath, content, 'utf8');
27
+ fs.renameSync(tmpPath, targetPath);
28
+ } catch (err) {
29
+ try {
30
+ fs.unlinkSync(tmpPath);
31
+ } catch (_) {
32
+ // Ignore cleanup errors
33
+ }
34
+ throw err;
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Ensure a directory exists (recursive mkdir).
40
+ * @param {string} dirPath - Directory path to create
41
+ */
42
+ function ensureDir(dirPath) {
43
+ if (!fs.existsSync(dirPath)) {
44
+ fs.mkdirSync(dirPath, { recursive: true });
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Find the project root by walking up the directory tree.
50
+ * Looks for: .planning/, .git/, package.json
51
+ *
52
+ * @param {string} [startDir=process.cwd()] - Starting directory
53
+ * @returns {string|null} Project root path or null
54
+ */
55
+ function findProjectRoot(startDir) {
56
+ let dir = startDir || process.cwd();
57
+ const root = path.parse(dir).root;
58
+
59
+ while (dir !== root) {
60
+ if (
61
+ fs.existsSync(path.join(dir, '.planning')) ||
62
+ fs.existsSync(path.join(dir, '.git')) ||
63
+ fs.existsSync(path.join(dir, 'package.json'))
64
+ ) {
65
+ return dir;
66
+ }
67
+ dir = path.dirname(dir);
68
+ }
69
+
70
+ return null;
71
+ }
72
+
73
+ /**
74
+ * Check if a file exists.
75
+ * @param {string} filePath - Path to check
76
+ * @returns {boolean}
77
+ */
78
+ function fileExists(filePath) {
79
+ try {
80
+ return fs.statSync(filePath).isFile();
81
+ } catch (_) {
82
+ return false;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Read a file, returning a default value if it doesn't exist.
88
+ * @param {string} filePath - Path to read
89
+ * @param {string} defaultValue - Default if file missing
90
+ * @returns {string}
91
+ */
92
+ function readFileOr(filePath, defaultValue) {
93
+ try {
94
+ return fs.readFileSync(filePath, 'utf8');
95
+ } catch (_) {
96
+ return defaultValue;
97
+ }
98
+ }
99
+
100
+ module.exports = {
101
+ atomicWrite,
102
+ ensureDir,
103
+ findProjectRoot,
104
+ fileExists,
105
+ readFileOr,
106
+ };
@@ -0,0 +1,100 @@
1
+ /**
2
+ * GTD Frontmatter Parser — YAML frontmatter between --- delimiters.
3
+ * @module lib/frontmatter
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ const FRONTMATTER_REGEX = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/;
9
+
10
+ /**
11
+ * Parse YAML frontmatter from a Markdown string.
12
+ * Supports simple key: value pairs and basic types (string, number, boolean, null).
13
+ *
14
+ * @param {string} content - Markdown content with optional frontmatter
15
+ * @returns {{ frontmatter: object, body: string }}
16
+ */
17
+ function parseFrontmatter(content) {
18
+ if (!content || typeof content !== 'string') {
19
+ return { frontmatter: {}, body: content || '' };
20
+ }
21
+
22
+ const match = content.match(FRONTMATTER_REGEX);
23
+ if (!match) {
24
+ return { frontmatter: {}, body: content };
25
+ }
26
+
27
+ const yamlBlock = match[1];
28
+ const body = match[2];
29
+ const frontmatter = parseSimpleYaml(yamlBlock);
30
+
31
+ return { frontmatter, body };
32
+ }
33
+
34
+ /**
35
+ * Serialize frontmatter and body back to a Markdown string.
36
+ *
37
+ * @param {object} frontmatter - Key-value pairs
38
+ * @param {string} body - Markdown body
39
+ * @returns {string}
40
+ */
41
+ function serializeFrontmatter(frontmatter, body) {
42
+ if (!frontmatter || Object.keys(frontmatter).length === 0) {
43
+ return body || '';
44
+ }
45
+
46
+ const yamlLines = Object.entries(frontmatter).map(([key, value]) => {
47
+ if (value === null || value === undefined) return `${key}: null`;
48
+ if (typeof value === 'boolean') return `${key}: ${value}`;
49
+ if (typeof value === 'number') return `${key}: ${value}`;
50
+ if (typeof value === 'string' && value.includes(':')) return `${key}: "${value}"`;
51
+ return `${key}: ${value}`;
52
+ });
53
+
54
+ return `---\n${yamlLines.join('\n')}\n---\n${body || ''}`;
55
+ }
56
+
57
+ /**
58
+ * Parse simple YAML (flat key-value pairs only).
59
+ * Handles: strings, numbers, booleans, null, quoted strings.
60
+ *
61
+ * @param {string} yaml - YAML block content
62
+ * @returns {object}
63
+ */
64
+ function parseSimpleYaml(yaml) {
65
+ const result = {};
66
+ const lines = yaml.split('\n');
67
+
68
+ for (const line of lines) {
69
+ const trimmed = line.trim();
70
+ if (!trimmed || trimmed.startsWith('#')) continue;
71
+
72
+ const colonIndex = trimmed.indexOf(':');
73
+ if (colonIndex === -1) continue;
74
+
75
+ const key = trimmed.slice(0, colonIndex).trim();
76
+ let value = trimmed.slice(colonIndex + 1).trim();
77
+
78
+ // Remove quotes
79
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
80
+ value = value.slice(1, -1);
81
+ } else if (value === 'true') {
82
+ value = true;
83
+ } else if (value === 'false') {
84
+ value = false;
85
+ } else if (value === 'null' || value === '~' || value === '') {
86
+ value = null;
87
+ } else if (!isNaN(Number(value)) && value !== '') {
88
+ value = Number(value);
89
+ }
90
+
91
+ result[key] = value;
92
+ }
93
+
94
+ return result;
95
+ }
96
+
97
+ module.exports = {
98
+ parseFrontmatter,
99
+ serializeFrontmatter,
100
+ };
package/lib/git.cjs ADDED
@@ -0,0 +1,137 @@
1
+ /**
2
+ * GTD Git Integration — Git operations for state tracking and change detection.
3
+ * @module lib/git
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ const { execSync } = require('child_process');
9
+ const path = require('path');
10
+
11
+ /**
12
+ * Execute a git command and return stdout trimmed.
13
+ * Returns null on any error (not a git repo, git not installed, etc.)
14
+ *
15
+ * @param {string} command - Git command (without 'git' prefix)
16
+ * @param {string} cwd - Working directory
17
+ * @returns {string|null}
18
+ */
19
+ function git(command, cwd) {
20
+ try {
21
+ return execSync(`git ${command}`, {
22
+ cwd,
23
+ encoding: 'utf8',
24
+ stdio: ['pipe', 'pipe', 'pipe'],
25
+ timeout: 10000,
26
+ }).trim();
27
+ } catch (_) {
28
+ return null;
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Get the current short commit hash.
34
+ * @param {string} projectRoot - Project root directory
35
+ * @returns {string|null} 7-character commit hash or null
36
+ */
37
+ function getGitCommit(projectRoot) {
38
+ return git('rev-parse --short HEAD', projectRoot);
39
+ }
40
+
41
+ /**
42
+ * Get the full commit hash.
43
+ * @param {string} projectRoot - Project root directory
44
+ * @returns {string|null} Full commit hash or null
45
+ */
46
+ function getGitCommitFull(projectRoot) {
47
+ return git('rev-parse HEAD', projectRoot);
48
+ }
49
+
50
+ /**
51
+ * Get the current branch name.
52
+ * @param {string} projectRoot - Project root directory
53
+ * @returns {string|null} Branch name or null
54
+ */
55
+ function getGitBranch(projectRoot) {
56
+ return git('rev-parse --abbrev-ref HEAD', projectRoot);
57
+ }
58
+
59
+ /**
60
+ * Check if there are uncommitted changes (staged or unstaged).
61
+ * @param {string} projectRoot - Project root directory
62
+ * @returns {boolean}
63
+ */
64
+ function hasUncommittedChanges(projectRoot) {
65
+ const status = git('status --porcelain', projectRoot);
66
+ return status !== null && status.length > 0;
67
+ }
68
+
69
+ /**
70
+ * Get the list of files changed between two commits.
71
+ * @param {string} projectRoot - Project root directory
72
+ * @param {string} fromCommit - Starting commit hash
73
+ * @param {string} [toCommit='HEAD'] - Ending commit hash
74
+ * @returns {string[]} Array of changed file paths (relative to project root)
75
+ */
76
+ function getChangedFiles(projectRoot, fromCommit, toCommit = 'HEAD') {
77
+ const output = git(`diff --name-only ${fromCommit}..${toCommit}`, projectRoot);
78
+ if (!output) return [];
79
+ return output.split('\n').filter((line) => line.length > 0);
80
+ }
81
+
82
+ /**
83
+ * Get recent commit messages for context.
84
+ * @param {string} projectRoot - Project root directory
85
+ * @param {number} [count=10] - Number of commits to retrieve
86
+ * @returns {Array<{hash: string, message: string}>}
87
+ */
88
+ function getRecentCommits(projectRoot, count = 10) {
89
+ const output = git(`log --oneline -${count}`, projectRoot);
90
+ if (!output) return [];
91
+ return output.split('\n').filter(Boolean).map((line) => {
92
+ const spaceIndex = line.indexOf(' ');
93
+ return {
94
+ hash: line.slice(0, spaceIndex),
95
+ message: line.slice(spaceIndex + 1),
96
+ };
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Check if a directory is inside a git repository.
102
+ * @param {string} dir - Directory to check
103
+ * @returns {boolean}
104
+ */
105
+ function isGitRepo(dir) {
106
+ return git('rev-parse --is-inside-work-tree', dir) === 'true';
107
+ }
108
+
109
+ /**
110
+ * Get the git root directory.
111
+ * @param {string} dir - Directory to start from
112
+ * @returns {string|null} Git root path or null
113
+ */
114
+ function getGitRoot(dir) {
115
+ return git('rev-parse --show-toplevel', dir);
116
+ }
117
+
118
+ /**
119
+ * Get the remote origin URL.
120
+ * @param {string} projectRoot - Project root directory
121
+ * @returns {string|null}
122
+ */
123
+ function getRemoteUrl(projectRoot) {
124
+ return git('remote get-url origin', projectRoot);
125
+ }
126
+
127
+ module.exports = {
128
+ getGitCommit,
129
+ getGitCommitFull,
130
+ getGitBranch,
131
+ hasUncommittedChanges,
132
+ getChangedFiles,
133
+ getRecentCommits,
134
+ isGitRepo,
135
+ getGitRoot,
136
+ getRemoteUrl,
137
+ };
package/lib/init.cjs ADDED
@@ -0,0 +1,370 @@
1
+ /**
2
+ * GTD Init Module — Assembles workflow context for agent orchestration.
3
+ *
4
+ * Each workflow type receives a tailored context payload containing only
5
+ * the data it needs. This keeps agent prompts focused and avoids
6
+ * loading unnecessary context into limited token windows.
7
+ *
8
+ * @module lib/init
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const os = require('os');
16
+ const { findProjectRoot, fileExists, readFileOr, ensureDir } = require('./file-ops.cjs');
17
+ const { loadConfig } = require('./config.cjs');
18
+ const { loadState } = require('./state.cjs');
19
+ const { getAnalysisStatus, getCodebaseMapStatus } = require('./analysis.cjs');
20
+ const {
21
+ getGitCommit,
22
+ getGitBranch,
23
+ hasUncommittedChanges,
24
+ isGitRepo,
25
+ getRemoteUrl,
26
+ } = require('./git.cjs');
27
+
28
+ /**
29
+ * Workflow → required context dimensions mapping.
30
+ * Each workflow only gets the context slices it needs.
31
+ */
32
+ const WORKFLOW_CONTEXT = {
33
+ // Backward workflows
34
+ 'scan-codebase': ['config', 'state', 'git'],
35
+ 'analyze-codebase': ['config', 'state', 'git', 'codebase_map', 'analysis_status'],
36
+ 'generate-document': ['config', 'state', 'git', 'codebase_map', 'analysis_status', 'doc_status'],
37
+ 'create-all': ['config', 'state', 'git', 'codebase_map', 'analysis_status', 'doc_status'],
38
+ 'verify-document': ['config', 'state', 'git', 'doc_status'],
39
+ 'review-document': ['config', 'state', 'doc_status'],
40
+ 'incremental-update': ['config', 'state', 'git', 'analysis_status', 'doc_status', 'git_diff'],
41
+
42
+ // Forward workflows
43
+ 'new-project': ['config', 'state', 'git', 'codebase_map'],
44
+ 'discuss-phase': ['config', 'state', 'git', 'roadmap', 'phase_context'],
45
+ 'plan-phase': ['config', 'state', 'git', 'roadmap', 'phase_context', 'research'],
46
+ 'execute-phase': ['config', 'state', 'git', 'roadmap', 'phase_context', 'plans'],
47
+ 'verify-work': ['config', 'state', 'git', 'roadmap', 'phase_context', 'plans', 'summaries'],
48
+ 'deploy-local': ['config', 'state', 'git', 'codebase_map'],
49
+ 'test-phase': ['config', 'state', 'git', 'phase_context'],
50
+ ship: ['config', 'state', 'git'],
51
+
52
+ // Sync workflows
53
+ 'detect-drift': ['config', 'state', 'git', 'analysis_status', 'doc_status', 'roadmap'],
54
+ reconcile: ['config', 'state', 'git', 'drift_report'],
55
+ sync: ['config', 'state', 'git', 'drift_report'],
56
+ audit: ['config', 'state', 'git', 'analysis_status', 'doc_status', 'roadmap'],
57
+
58
+ // Utility workflows
59
+ help: ['config', 'state'],
60
+ status: ['config', 'state', 'analysis_status', 'doc_status'],
61
+ settings: ['config'],
62
+ };
63
+
64
+ /**
65
+ * Main init function — assembles context for a workflow.
66
+ *
67
+ * @param {string[]} args - [workflowName, ...workflowArgs]
68
+ * @returns {void} Writes JSON to stdout
69
+ */
70
+ function init(args) {
71
+ const workflowName = args[0];
72
+ const workflowArgs = args.slice(1);
73
+
74
+ if (!workflowName) {
75
+ process.stderr.write('Usage: gtd-tools.cjs init <workflow> [args...]\n');
76
+ process.exit(1);
77
+ }
78
+
79
+ const projectRoot = findProjectRoot(process.cwd()) || process.cwd();
80
+ const docsRoot = path.join(projectRoot, '.planning');
81
+
82
+ // Base context — always present
83
+ const context = {
84
+ project_root: projectRoot,
85
+ docs_root: docsRoot,
86
+ workflow: workflowName,
87
+ args: parseWorkflowArgs(workflowName, workflowArgs),
88
+ timestamp: new Date().toISOString(),
89
+ gtd_version: getGtdVersion(),
90
+ };
91
+
92
+ // Determine which context slices this workflow needs
93
+ const needed = WORKFLOW_CONTEXT[workflowName] || ['config', 'state', 'git'];
94
+
95
+ // Load each needed context slice
96
+ if (needed.includes('config')) {
97
+ context.config = loadConfig(docsRoot);
98
+ }
99
+
100
+ if (needed.includes('state')) {
101
+ context.state = loadState(docsRoot);
102
+ }
103
+
104
+ if (needed.includes('git')) {
105
+ context.git = buildGitContext(projectRoot);
106
+ }
107
+
108
+ if (needed.includes('codebase_map')) {
109
+ context.codebase_map = getCodebaseMapStatus(docsRoot);
110
+ }
111
+
112
+ if (needed.includes('analysis_status')) {
113
+ context.analysis_status = getAnalysisStatus(docsRoot);
114
+ }
115
+
116
+ if (needed.includes('doc_status')) {
117
+ const state = context.state || loadState(docsRoot);
118
+ context.documents = state.backward.documents;
119
+ }
120
+
121
+ if (needed.includes('roadmap')) {
122
+ context.roadmap = loadArtifact(docsRoot, 'ROADMAP.md');
123
+ }
124
+
125
+ if (needed.includes('phase_context')) {
126
+ context.phase = loadPhaseContext(docsRoot, context.args);
127
+ }
128
+
129
+ if (needed.includes('plans')) {
130
+ context.plans = loadPhasePlans(docsRoot, context.args);
131
+ }
132
+
133
+ if (needed.includes('research')) {
134
+ context.research = loadResearchSummary(docsRoot);
135
+ }
136
+
137
+ if (needed.includes('drift_report')) {
138
+ context.drift_report = loadArtifact(docsRoot, 'DRIFT-REPORT.md');
139
+ }
140
+
141
+ // Resolve model tiers for this workflow
142
+ if (context.config) {
143
+ context.models = resolveModelsForWorkflow(workflowName, context.config);
144
+ }
145
+
146
+ // Output context
147
+ outputContext(context);
148
+ }
149
+
150
+ /**
151
+ * Build git context object.
152
+ */
153
+ function buildGitContext(projectRoot) {
154
+ if (!isGitRepo(projectRoot)) {
155
+ return { available: false };
156
+ }
157
+
158
+ return {
159
+ available: true,
160
+ commit: getGitCommit(projectRoot),
161
+ branch: getGitBranch(projectRoot),
162
+ has_changes: hasUncommittedChanges(projectRoot),
163
+ remote_url: getRemoteUrl(projectRoot),
164
+ };
165
+ }
166
+
167
+ /**
168
+ * Parse workflow-specific arguments.
169
+ */
170
+ function parseWorkflowArgs(workflowName, args) {
171
+ const parsed = { raw: args };
172
+
173
+ // Extract common flags
174
+ for (let i = 0; i < args.length; i++) {
175
+ const arg = args[i];
176
+
177
+ if (arg === '--auto' || arg === '-a') parsed.auto = true;
178
+ else if (arg === '--force' || arg === '-f') parsed.force = true;
179
+ else if (arg === '--parallel') parsed.parallel = true;
180
+ else if (arg === '--deep') parsed.deep = true;
181
+ else if (arg === '--format' && args[i + 1]) { parsed.format = args[++i]; }
182
+ else if (arg === '--since' && args[i + 1]) { parsed.since = args[++i]; }
183
+ else if (arg === '--focus' && args[i + 1]) { parsed.focus = args[++i]; }
184
+ else if (arg === '--module' && args[i + 1]) { parsed.module = args[++i]; }
185
+ else if (arg === '--wave' && args[i + 1]) { parsed.wave = parseInt(args[++i], 10); }
186
+ else if (arg === '--strategy' && args[i + 1]) { parsed.strategy = args[++i]; }
187
+ else if (arg === '--direction' && args[i + 1]) { parsed.direction = args[++i]; }
188
+ else if (arg === '--include-tests') parsed.include_tests = true;
189
+ else if (!arg.startsWith('-') && !parsed.positional) {
190
+ parsed.positional = arg;
191
+ }
192
+ }
193
+
194
+ // Workflow-specific positional arg interpretation
195
+ if (parsed.positional) {
196
+ if (['generate-document', 'verify-document', 'review-document'].includes(workflowName)) {
197
+ parsed.doc_type = parsed.positional;
198
+ } else if (
199
+ ['discuss-phase', 'plan-phase', 'execute-phase', 'verify-work', 'test-phase'].includes(
200
+ workflowName,
201
+ )
202
+ ) {
203
+ parsed.phase_number = parseInt(parsed.positional, 10);
204
+ }
205
+ }
206
+
207
+ return parsed;
208
+ }
209
+
210
+ /**
211
+ * Load a planning artifact as a string (or null if missing).
212
+ */
213
+ function loadArtifact(docsRoot, filename) {
214
+ const filepath = path.join(docsRoot, filename);
215
+ if (!fileExists(filepath)) return null;
216
+ try {
217
+ return fs.readFileSync(filepath, 'utf8');
218
+ } catch (_) {
219
+ return null;
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Load phase-specific context files.
225
+ */
226
+ function loadPhaseContext(docsRoot, args) {
227
+ const phaseNum = args.phase_number;
228
+ if (!phaseNum) return null;
229
+
230
+ const phasesDir = path.join(docsRoot, 'phases');
231
+ if (!fs.existsSync(phasesDir)) return { phase_number: phaseNum, exists: false };
232
+
233
+ // Find the phase directory (zero-padded: 01-, 02-, etc.)
234
+ const padded = String(phaseNum).padStart(2, '0');
235
+ const entries = fs.existsSync(phasesDir) ? fs.readdirSync(phasesDir) : [];
236
+ const phaseDir = entries.find((e) => e.startsWith(padded + '-'));
237
+
238
+ if (!phaseDir) return { phase_number: phaseNum, exists: false };
239
+
240
+ const fullPhaseDir = path.join(phasesDir, phaseDir);
241
+
242
+ return {
243
+ phase_number: phaseNum,
244
+ exists: true,
245
+ directory: fullPhaseDir,
246
+ context_file: loadArtifact(fullPhaseDir, `${padded}-CONTEXT.md`),
247
+ research_file: loadArtifact(fullPhaseDir, `${padded}-RESEARCH.md`),
248
+ };
249
+ }
250
+
251
+ /**
252
+ * Load plan files from a phase directory.
253
+ */
254
+ function loadPhasePlans(docsRoot, args) {
255
+ const phaseNum = args.phase_number;
256
+ if (!phaseNum) return null;
257
+
258
+ const padded = String(phaseNum).padStart(2, '0');
259
+ const phasesDir = path.join(docsRoot, 'phases');
260
+ if (!fs.existsSync(phasesDir)) return [];
261
+
262
+ const entries = fs.readdirSync(phasesDir);
263
+ const phaseDir = entries.find((e) => e.startsWith(padded + '-'));
264
+ if (!phaseDir) return [];
265
+
266
+ const fullPhaseDir = path.join(phasesDir, phaseDir);
267
+ const allFiles = fs.readdirSync(fullPhaseDir);
268
+ const planFiles = allFiles.filter((f) => f.includes('-PLAN') && f.endsWith('.md'));
269
+
270
+ return planFiles.map((f) => ({
271
+ filename: f,
272
+ path: path.join(fullPhaseDir, f),
273
+ }));
274
+ }
275
+
276
+ /**
277
+ * Load research summary if available.
278
+ */
279
+ function loadResearchSummary(docsRoot) {
280
+ const researchDir = path.join(docsRoot, 'research');
281
+ if (!fs.existsSync(researchDir)) return null;
282
+
283
+ return {
284
+ summary: loadArtifact(researchDir, 'SUMMARY.md'),
285
+ stack: loadArtifact(researchDir, 'STACK.md'),
286
+ features: loadArtifact(researchDir, 'FEATURES.md'),
287
+ architecture: loadArtifact(researchDir, 'ARCHITECTURE.md'),
288
+ pitfalls: loadArtifact(researchDir, 'PITFALLS.md'),
289
+ };
290
+ }
291
+
292
+ /**
293
+ * Resolve model tiers for agents used in this workflow.
294
+ */
295
+ function resolveModelsForWorkflow(workflowName, config) {
296
+ const models = config.models || {};
297
+ const backwardWorkflows = [
298
+ 'scan-codebase',
299
+ 'analyze-codebase',
300
+ 'generate-document',
301
+ 'create-all',
302
+ 'verify-document',
303
+ 'review-document',
304
+ 'incremental-update',
305
+ ];
306
+ const forwardWorkflows = [
307
+ 'new-project',
308
+ 'discuss-phase',
309
+ 'plan-phase',
310
+ 'execute-phase',
311
+ 'verify-work',
312
+ 'deploy-local',
313
+ 'test-phase',
314
+ 'ship',
315
+ ];
316
+
317
+ if (backwardWorkflows.includes(workflowName)) {
318
+ return {
319
+ analyzer: models.analyzer || 'sonnet',
320
+ writer: models.writer || 'sonnet',
321
+ verifier: models.verifier || 'haiku',
322
+ };
323
+ }
324
+
325
+ if (forwardWorkflows.includes(workflowName)) {
326
+ return {
327
+ researcher: models.researcher || 'sonnet',
328
+ planner: models.planner || 'sonnet',
329
+ executor: models.executor || 'sonnet',
330
+ verifier: models.verifier || 'haiku',
331
+ };
332
+ }
333
+
334
+ return models;
335
+ }
336
+
337
+ /**
338
+ * Output context as JSON, using @file: for large payloads.
339
+ */
340
+ function outputContext(context) {
341
+ const json = JSON.stringify(context, null, 2);
342
+
343
+ if (json.length > 50000) {
344
+ // Write to temp file to avoid overwhelming stdout
345
+ const tmpDir = path.join(os.tmpdir(), 'gtd');
346
+ ensureDir(tmpDir);
347
+ const tmpFile = path.join(tmpDir, `init-${Date.now()}.json`);
348
+ fs.writeFileSync(tmpFile, json, 'utf8');
349
+ process.stdout.write(`@file:${tmpFile}`);
350
+ } else {
351
+ process.stdout.write(json);
352
+ }
353
+ }
354
+
355
+ /**
356
+ * Get the GTD package version.
357
+ */
358
+ function getGtdVersion() {
359
+ try {
360
+ const pkg = require('../package.json');
361
+ return pkg.version;
362
+ } catch (_) {
363
+ return 'unknown';
364
+ }
365
+ }
366
+
367
+ module.exports = init;
368
+ module.exports.buildGitContext = buildGitContext;
369
+ module.exports.parseWorkflowArgs = parseWorkflowArgs;
370
+ module.exports.WORKFLOW_CONTEXT = WORKFLOW_CONTEXT;