prjct-cli 0.45.0 → 0.45.3

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 (207) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/bin/prjct.ts +117 -10
  3. package/core/__tests__/agentic/memory-system.test.ts +39 -26
  4. package/core/__tests__/agentic/plan-mode.test.ts +64 -46
  5. package/core/__tests__/agentic/prompt-builder.test.ts +14 -14
  6. package/core/__tests__/services/project-index.test.ts +353 -0
  7. package/core/__tests__/types/fs.test.ts +3 -3
  8. package/core/__tests__/utils/date-helper.test.ts +10 -10
  9. package/core/__tests__/utils/output.test.ts +9 -6
  10. package/core/__tests__/utils/project-commands.test.ts +5 -6
  11. package/core/agentic/agent-router.ts +9 -10
  12. package/core/agentic/chain-of-thought.ts +16 -4
  13. package/core/agentic/command-executor.ts +66 -40
  14. package/core/agentic/context-builder.ts +8 -5
  15. package/core/agentic/ground-truth.ts +15 -9
  16. package/core/agentic/index.ts +145 -152
  17. package/core/agentic/loop-detector.ts +40 -11
  18. package/core/agentic/memory-system.ts +98 -35
  19. package/core/agentic/orchestrator-executor.ts +135 -71
  20. package/core/agentic/plan-mode.ts +46 -16
  21. package/core/agentic/prompt-builder.ts +108 -42
  22. package/core/agentic/services.ts +10 -9
  23. package/core/agentic/skill-loader.ts +9 -15
  24. package/core/agentic/smart-context.ts +129 -79
  25. package/core/agentic/template-executor.ts +13 -12
  26. package/core/agentic/template-loader.ts +7 -4
  27. package/core/agentic/tool-registry.ts +16 -13
  28. package/core/agents/index.ts +1 -1
  29. package/core/agents/performance.ts +10 -27
  30. package/core/ai-tools/formatters.ts +8 -6
  31. package/core/ai-tools/generator.ts +4 -4
  32. package/core/ai-tools/index.ts +1 -1
  33. package/core/ai-tools/registry.ts +21 -11
  34. package/core/bus/bus.ts +23 -16
  35. package/core/bus/index.ts +2 -2
  36. package/core/cli/linear.ts +3 -5
  37. package/core/cli/start.ts +28 -25
  38. package/core/commands/analysis.ts +58 -39
  39. package/core/commands/analytics.ts +52 -44
  40. package/core/commands/base.ts +15 -13
  41. package/core/commands/cleanup.ts +6 -13
  42. package/core/commands/command-data.ts +28 -4
  43. package/core/commands/commands.ts +57 -24
  44. package/core/commands/context.ts +4 -4
  45. package/core/commands/design.ts +3 -10
  46. package/core/commands/index.ts +5 -8
  47. package/core/commands/maintenance.ts +7 -4
  48. package/core/commands/planning.ts +179 -56
  49. package/core/commands/register.ts +13 -9
  50. package/core/commands/registry.ts +15 -14
  51. package/core/commands/setup.ts +26 -14
  52. package/core/commands/shipping.ts +11 -16
  53. package/core/commands/snapshots.ts +16 -32
  54. package/core/commands/uninstall.ts +541 -0
  55. package/core/commands/workflow.ts +24 -28
  56. package/core/constants/index.ts +10 -22
  57. package/core/context/generator.ts +82 -33
  58. package/core/context-tools/files-tool.ts +18 -19
  59. package/core/context-tools/imports-tool.ts +13 -33
  60. package/core/context-tools/index.ts +29 -54
  61. package/core/context-tools/recent-tool.ts +16 -22
  62. package/core/context-tools/signatures-tool.ts +17 -26
  63. package/core/context-tools/summary-tool.ts +20 -22
  64. package/core/context-tools/token-counter.ts +25 -20
  65. package/core/context-tools/types.ts +5 -5
  66. package/core/domain/agent-generator.ts +7 -5
  67. package/core/domain/agent-loader.ts +2 -2
  68. package/core/domain/analyzer.ts +19 -16
  69. package/core/domain/architecture-generator.ts +6 -3
  70. package/core/domain/context-estimator.ts +3 -4
  71. package/core/domain/snapshot-manager.ts +25 -22
  72. package/core/domain/task-stack.ts +24 -14
  73. package/core/errors.ts +1 -1
  74. package/core/events/events.ts +2 -4
  75. package/core/events/index.ts +1 -2
  76. package/core/index.ts +28 -16
  77. package/core/infrastructure/agent-detector.ts +3 -3
  78. package/core/infrastructure/ai-provider.ts +23 -20
  79. package/core/infrastructure/author-detector.ts +16 -10
  80. package/core/infrastructure/capability-installer.ts +2 -2
  81. package/core/infrastructure/claude-agent.ts +6 -6
  82. package/core/infrastructure/command-installer.ts +22 -17
  83. package/core/infrastructure/config-manager.ts +18 -14
  84. package/core/infrastructure/editors-config.ts +8 -4
  85. package/core/infrastructure/path-manager.ts +8 -6
  86. package/core/infrastructure/permission-manager.ts +20 -17
  87. package/core/infrastructure/setup.ts +42 -38
  88. package/core/infrastructure/update-checker.ts +5 -5
  89. package/core/integrations/issue-tracker/enricher.ts +8 -19
  90. package/core/integrations/issue-tracker/index.ts +2 -2
  91. package/core/integrations/issue-tracker/manager.ts +15 -15
  92. package/core/integrations/issue-tracker/types.ts +5 -22
  93. package/core/integrations/jira/client.ts +67 -59
  94. package/core/integrations/jira/index.ts +11 -14
  95. package/core/integrations/jira/mcp-adapter.ts +5 -10
  96. package/core/integrations/jira/service.ts +10 -10
  97. package/core/integrations/linear/client.ts +27 -18
  98. package/core/integrations/linear/index.ts +9 -12
  99. package/core/integrations/linear/service.ts +11 -11
  100. package/core/integrations/linear/sync.ts +8 -8
  101. package/core/outcomes/analyzer.ts +5 -18
  102. package/core/outcomes/index.ts +2 -2
  103. package/core/outcomes/recorder.ts +3 -3
  104. package/core/plugin/builtin/webhook.ts +19 -15
  105. package/core/plugin/hooks.ts +29 -21
  106. package/core/plugin/index.ts +7 -7
  107. package/core/plugin/loader.ts +19 -19
  108. package/core/plugin/registry.ts +12 -23
  109. package/core/schemas/agents.ts +1 -1
  110. package/core/schemas/analysis.ts +1 -1
  111. package/core/schemas/enriched-task.ts +62 -49
  112. package/core/schemas/ideas.ts +13 -13
  113. package/core/schemas/index.ts +17 -27
  114. package/core/schemas/issues.ts +40 -25
  115. package/core/schemas/metrics.ts +25 -25
  116. package/core/schemas/outcomes.ts +70 -62
  117. package/core/schemas/permissions.ts +15 -12
  118. package/core/schemas/prd.ts +27 -14
  119. package/core/schemas/project.ts +3 -3
  120. package/core/schemas/roadmap.ts +47 -34
  121. package/core/schemas/schemas.ts +3 -4
  122. package/core/schemas/shipped.ts +3 -3
  123. package/core/schemas/state.ts +43 -29
  124. package/core/server/index.ts +5 -6
  125. package/core/server/routes-extended.ts +68 -72
  126. package/core/server/routes.ts +3 -3
  127. package/core/server/server.ts +31 -26
  128. package/core/services/agent-generator.ts +237 -0
  129. package/core/services/agent-service.ts +2 -2
  130. package/core/services/breakdown-service.ts +2 -4
  131. package/core/services/context-generator.ts +299 -0
  132. package/core/services/context-selector.ts +420 -0
  133. package/core/services/doctor-service.ts +426 -0
  134. package/core/services/file-categorizer.ts +448 -0
  135. package/core/services/file-scorer.ts +270 -0
  136. package/core/services/git-analyzer.ts +267 -0
  137. package/core/services/index.ts +27 -10
  138. package/core/services/memory-service.ts +3 -4
  139. package/core/services/project-index.ts +911 -0
  140. package/core/services/project-service.ts +4 -4
  141. package/core/services/skill-installer.ts +14 -17
  142. package/core/services/skill-lock.ts +3 -3
  143. package/core/services/skill-service.ts +12 -6
  144. package/core/services/stack-detector.ts +245 -0
  145. package/core/services/sync-service.ts +87 -345
  146. package/core/services/watch-service.ts +294 -0
  147. package/core/session/compaction.ts +23 -31
  148. package/core/session/index.ts +11 -5
  149. package/core/session/log-migration.ts +3 -3
  150. package/core/session/metrics.ts +19 -14
  151. package/core/session/session-log-manager.ts +12 -17
  152. package/core/session/task-session-manager.ts +25 -25
  153. package/core/session/utils.ts +1 -1
  154. package/core/storage/ideas-storage.ts +41 -57
  155. package/core/storage/index-storage.ts +514 -0
  156. package/core/storage/index.ts +41 -17
  157. package/core/storage/metrics-storage.ts +39 -34
  158. package/core/storage/queue-storage.ts +35 -45
  159. package/core/storage/shipped-storage.ts +17 -20
  160. package/core/storage/state-storage.ts +50 -30
  161. package/core/storage/storage-manager.ts +6 -6
  162. package/core/storage/storage.ts +18 -15
  163. package/core/sync/auth-config.ts +3 -3
  164. package/core/sync/index.ts +13 -19
  165. package/core/sync/oauth-handler.ts +3 -3
  166. package/core/sync/sync-client.ts +4 -9
  167. package/core/sync/sync-manager.ts +12 -14
  168. package/core/types/commands.ts +42 -7
  169. package/core/types/index.ts +284 -305
  170. package/core/types/integrations.ts +3 -3
  171. package/core/types/storage.ts +14 -14
  172. package/core/types/utils.ts +3 -3
  173. package/core/utils/agent-stream.ts +3 -1
  174. package/core/utils/animations.ts +14 -11
  175. package/core/utils/branding.ts +7 -7
  176. package/core/utils/cache.ts +1 -3
  177. package/core/utils/collection-filters.ts +3 -15
  178. package/core/utils/date-helper.ts +2 -7
  179. package/core/utils/file-helper.ts +13 -8
  180. package/core/utils/jsonl-helper.ts +13 -10
  181. package/core/utils/keychain.ts +4 -8
  182. package/core/utils/logger.ts +1 -1
  183. package/core/utils/next-steps.ts +3 -3
  184. package/core/utils/output.ts +58 -11
  185. package/core/utils/project-commands.ts +6 -6
  186. package/core/utils/project-credentials.ts +5 -12
  187. package/core/utils/runtime.ts +2 -2
  188. package/core/utils/session-helper.ts +3 -4
  189. package/core/utils/version.ts +3 -3
  190. package/core/wizard/index.ts +13 -0
  191. package/core/wizard/onboarding.ts +633 -0
  192. package/core/workflow/state-machine.ts +7 -7
  193. package/dist/bin/prjct.mjs +18755 -15574
  194. package/dist/core/infrastructure/command-installer.js +86 -79
  195. package/dist/core/infrastructure/editors-config.js +6 -6
  196. package/dist/core/infrastructure/setup.js +246 -225
  197. package/dist/core/utils/version.js +9 -9
  198. package/package.json +11 -12
  199. package/scripts/build.js +3 -3
  200. package/scripts/postinstall.js +2 -2
  201. package/templates/mcp-config.json +6 -1
  202. package/templates/permissions/permissive.jsonc +1 -1
  203. package/templates/permissions/strict.jsonc +5 -9
  204. package/templates/global/docs/agents.md +0 -88
  205. package/templates/global/docs/architecture.md +0 -103
  206. package/templates/global/docs/commands.md +0 -96
  207. package/templates/global/docs/validation.md +0 -95
@@ -0,0 +1,237 @@
1
+ /**
2
+ * AgentGenerator - Domain and workflow agent generation
3
+ *
4
+ * Extracted from sync-service.ts for single responsibility.
5
+ * Generates agent markdown files based on project stack.
6
+ *
7
+ * @version 1.0.0
8
+ */
9
+
10
+ import fs from 'node:fs/promises'
11
+ import path from 'node:path'
12
+ import type { StackDetection } from './stack-detector'
13
+
14
+ // ============================================================================
15
+ // TYPES
16
+ // ============================================================================
17
+
18
+ export interface AgentInfo {
19
+ name: string
20
+ type: 'workflow' | 'domain'
21
+ skill?: string
22
+ }
23
+
24
+ export interface ProjectStats {
25
+ fileCount: number
26
+ version: string
27
+ name: string
28
+ ecosystem: string
29
+ projectType: string
30
+ languages: string[]
31
+ frameworks: string[]
32
+ }
33
+
34
+ // ============================================================================
35
+ // AGENT GENERATOR CLASS
36
+ // ============================================================================
37
+
38
+ export class AgentGenerator {
39
+ private agentsPath: string
40
+ private templatesPath: string
41
+
42
+ constructor(agentsPath: string, templatesPath?: string) {
43
+ this.agentsPath = agentsPath
44
+ this.templatesPath = templatesPath || path.join(__dirname, '..', '..', 'templates', 'subagents')
45
+ }
46
+
47
+ /**
48
+ * Generate all agents based on stack detection
49
+ */
50
+ async generate(stack: StackDetection, stats: ProjectStats): Promise<AgentInfo[]> {
51
+ const agents: AgentInfo[] = []
52
+
53
+ // Purge old agents
54
+ await this.purgeOldAgents()
55
+
56
+ // Workflow agents (always generated) - IN PARALLEL
57
+ const workflowAgents = await this.generateWorkflowAgents()
58
+ agents.push(...workflowAgents)
59
+
60
+ // Domain agents (based on stack) - IN PARALLEL
61
+ const domainAgents = await this.generateDomainAgents(stack, stats)
62
+ agents.push(...domainAgents)
63
+
64
+ return agents
65
+ }
66
+
67
+ /**
68
+ * Remove existing agent files
69
+ */
70
+ private async purgeOldAgents(): Promise<void> {
71
+ try {
72
+ const files = await fs.readdir(this.agentsPath)
73
+ await Promise.all(
74
+ files
75
+ .filter((file) => file.endsWith('.md'))
76
+ .map((file) => fs.unlink(path.join(this.agentsPath, file)))
77
+ )
78
+ } catch {
79
+ // Directory might not exist yet
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Generate workflow agents (always included)
85
+ */
86
+ private async generateWorkflowAgents(): Promise<AgentInfo[]> {
87
+ const workflowAgentNames = ['prjct-workflow', 'prjct-planner', 'prjct-shipper']
88
+
89
+ await Promise.all(workflowAgentNames.map((name) => this.generateWorkflowAgent(name)))
90
+
91
+ return workflowAgentNames.map((name) => ({ name, type: 'workflow' as const }))
92
+ }
93
+
94
+ /**
95
+ * Generate domain agents based on stack
96
+ */
97
+ private async generateDomainAgents(
98
+ stack: StackDetection,
99
+ stats: ProjectStats
100
+ ): Promise<AgentInfo[]> {
101
+ const agentsToGenerate: { name: string; skill?: string }[] = []
102
+
103
+ if (stack.hasFrontend) {
104
+ agentsToGenerate.push({ name: 'frontend', skill: 'javascript-typescript' })
105
+ agentsToGenerate.push({ name: 'uxui', skill: 'frontend-design' })
106
+ }
107
+ if (stack.hasBackend) {
108
+ agentsToGenerate.push({ name: 'backend', skill: 'javascript-typescript' })
109
+ }
110
+ if (stack.hasDatabase) {
111
+ agentsToGenerate.push({ name: 'database' })
112
+ }
113
+ if (stack.hasTesting) {
114
+ agentsToGenerate.push({ name: 'testing', skill: 'developer-kit' })
115
+ }
116
+ if (stack.hasDocker) {
117
+ agentsToGenerate.push({ name: 'devops', skill: 'developer-kit' })
118
+ }
119
+
120
+ // Generate all domain agents IN PARALLEL
121
+ await Promise.all(
122
+ agentsToGenerate.map((agent) => this.generateDomainAgent(agent.name, stats, stack))
123
+ )
124
+
125
+ return agentsToGenerate.map((agent) => ({
126
+ name: agent.name,
127
+ type: 'domain' as const,
128
+ skill: agent.skill,
129
+ }))
130
+ }
131
+
132
+ /**
133
+ * Generate a single workflow agent
134
+ */
135
+ private async generateWorkflowAgent(name: string): Promise<void> {
136
+ let content = ''
137
+
138
+ try {
139
+ const templatePath = path.join(this.templatesPath, 'workflow', `${name}.md`)
140
+ content = await fs.readFile(templatePath, 'utf-8')
141
+ } catch {
142
+ // Generate minimal agent
143
+ content = this.generateMinimalWorkflowAgent(name)
144
+ }
145
+
146
+ await fs.writeFile(path.join(this.agentsPath, `${name}.md`), content, 'utf-8')
147
+ }
148
+
149
+ /**
150
+ * Generate a single domain agent
151
+ */
152
+ private async generateDomainAgent(
153
+ name: string,
154
+ stats: ProjectStats,
155
+ stack: StackDetection
156
+ ): Promise<void> {
157
+ let content = ''
158
+
159
+ try {
160
+ const templatePath = path.join(this.templatesPath, 'domain', `${name}.md`)
161
+ content = await fs.readFile(templatePath, 'utf-8')
162
+
163
+ // Inject project-specific context
164
+ content = content.replace('{projectName}', stats.name)
165
+ content = content.replace('{frameworks}', stack.frameworks.join(', ') || 'None detected')
166
+ content = content.replace('{ecosystem}', stats.ecosystem)
167
+ } catch {
168
+ // Generate minimal agent
169
+ content = this.generateMinimalDomainAgent(name, stats, stack)
170
+ }
171
+
172
+ await fs.writeFile(path.join(this.agentsPath, `${name}.md`), content, 'utf-8')
173
+ }
174
+
175
+ /**
176
+ * Generate minimal workflow agent content
177
+ */
178
+ private generateMinimalWorkflowAgent(name: string): string {
179
+ const descriptions: Record<string, string> = {
180
+ 'prjct-workflow': 'Task lifecycle: now, done, pause, resume',
181
+ 'prjct-planner': 'Planning: task, prd, spec, bug',
182
+ 'prjct-shipper': 'Shipping: ship, merge, review',
183
+ }
184
+
185
+ return `---
186
+ name: ${name}
187
+ description: ${descriptions[name] || 'Workflow agent'}
188
+ tools: Read, Write, Glob
189
+ ---
190
+
191
+ # ${name.toUpperCase()}
192
+
193
+ Workflow agent for prjct operations.
194
+
195
+ ## Project Context
196
+
197
+ When invoked:
198
+ 1. Read \`.prjct/prjct.config.json\` → extract \`projectId\`
199
+ 2. Read \`~/.prjct-cli/projects/{projectId}/storage/state.json\`
200
+ 3. Execute requested operation
201
+ `
202
+ }
203
+
204
+ /**
205
+ * Generate minimal domain agent content
206
+ */
207
+ private generateMinimalDomainAgent(
208
+ name: string,
209
+ stats: ProjectStats,
210
+ stack: StackDetection
211
+ ): string {
212
+ return `---
213
+ name: ${name}
214
+ description: ${name.charAt(0).toUpperCase() + name.slice(1)} specialist for ${stats.name}
215
+ tools: Read, Write, Glob, Grep
216
+ skills: []
217
+ ---
218
+
219
+ # ${name.toUpperCase()} AGENT
220
+
221
+ Domain specialist for ${name} tasks.
222
+
223
+ ## Project Context
224
+
225
+ - **Project**: ${stats.name}
226
+ - **Ecosystem**: ${stats.ecosystem}
227
+ - **Frameworks**: ${stack.frameworks.join(', ') || 'None detected'}
228
+
229
+ ## Your Role
230
+
231
+ You are the ${name} expert for this project. Apply best practices for the detected stack.
232
+ `
233
+ }
234
+ }
235
+
236
+ export const createAgentGenerator = (agentsPath: string) => new AgentGenerator(agentsPath)
237
+ export default AgentGenerator
@@ -4,10 +4,10 @@
4
4
  * Handles agent detection, initialization, and routing tasks to appropriate agents.
5
5
  */
6
6
 
7
- import agentDetector from '../infrastructure/agent-detector'
8
7
  import AgentRouter from '../agentic/agent-router'
9
- import type { AgentInfo, AgentAssignmentResult, ProjectContext } from '../types'
10
8
  import { AgentError } from '../errors'
9
+ import agentDetector from '../infrastructure/agent-detector'
10
+ import type { AgentAssignmentResult, AgentInfo, ProjectContext } from '../types'
11
11
 
12
12
  // Valid agent types - whitelist for security (prevents path traversal)
13
13
  const VALID_AGENT_TYPES = ['claude'] as const
@@ -4,7 +4,7 @@
4
4
  * Handles task breakdown, severity detection, and complexity estimation.
5
5
  */
6
6
 
7
- import type { Severity, ComplexityEstimate } from '../types'
7
+ import type { ComplexityEstimate, Severity } from '../types'
8
8
 
9
9
  export class BreakdownService {
10
10
  /**
@@ -77,9 +77,7 @@ export class BreakdownService {
77
77
  'authorization',
78
78
  ]
79
79
 
80
- const hasComplexKeyword = complexKeywords.some((kw) =>
81
- description.toLowerCase().includes(kw)
82
- )
80
+ const hasComplexKeyword = complexKeywords.some((kw) => description.toLowerCase().includes(kw))
83
81
 
84
82
  if (hasComplexKeyword || wordCount > 30) {
85
83
  return { level: 'high', hours: 8 }
@@ -0,0 +1,299 @@
1
+ /**
2
+ * ContextFileGenerator - Generates markdown context files
3
+ *
4
+ * Responsible for generating:
5
+ * - CLAUDE.md (main context for AI agents)
6
+ * - now.md (current task)
7
+ * - next.md (task queue)
8
+ * - ideas.md (captured ideas)
9
+ * - shipped.md (completed features)
10
+ */
11
+
12
+ import fs from 'node:fs/promises'
13
+ import path from 'node:path'
14
+ import dateHelper from '../utils/date-helper'
15
+
16
+ // ============================================================================
17
+ // TYPES
18
+ // ============================================================================
19
+
20
+ export interface GitData {
21
+ branch: string
22
+ commits: number
23
+ }
24
+
25
+ export interface ProjectStats {
26
+ name: string
27
+ version: string
28
+ ecosystem: string
29
+ projectType: string
30
+ fileCount: number
31
+ languages: string[]
32
+ frameworks: string[]
33
+ }
34
+
35
+ export interface Commands {
36
+ install: string
37
+ dev: string
38
+ test: string
39
+ build: string
40
+ lint: string
41
+ format: string
42
+ }
43
+
44
+ export interface AgentInfo {
45
+ name: string
46
+ type: 'workflow' | 'domain'
47
+ skill?: string
48
+ }
49
+
50
+ export interface ContextGeneratorConfig {
51
+ projectId: string
52
+ projectPath: string
53
+ globalPath: string
54
+ }
55
+
56
+ // ============================================================================
57
+ // CONTEXT FILE GENERATOR
58
+ // ============================================================================
59
+
60
+ export class ContextFileGenerator {
61
+ private config: ContextGeneratorConfig
62
+
63
+ constructor(config: ContextGeneratorConfig) {
64
+ this.config = config
65
+ }
66
+
67
+ /**
68
+ * Generate all context files in parallel
69
+ */
70
+ async generate(
71
+ git: GitData,
72
+ stats: ProjectStats,
73
+ commands: Commands,
74
+ agents: AgentInfo[]
75
+ ): Promise<string[]> {
76
+ const contextPath = path.join(this.config.globalPath, 'context')
77
+
78
+ // Generate all context files IN PARALLEL
79
+ await Promise.all([
80
+ this.generateClaudeMd(contextPath, git, stats, commands, agents),
81
+ this.generateNowMd(contextPath),
82
+ this.generateNextMd(contextPath),
83
+ this.generateIdeasMd(contextPath),
84
+ this.generateShippedMd(contextPath),
85
+ ])
86
+
87
+ return [
88
+ 'context/CLAUDE.md',
89
+ 'context/now.md',
90
+ 'context/next.md',
91
+ 'context/ideas.md',
92
+ 'context/shipped.md',
93
+ ]
94
+ }
95
+
96
+ // ==========================================================================
97
+ // INDIVIDUAL GENERATORS
98
+ // ==========================================================================
99
+
100
+ /**
101
+ * Generate CLAUDE.md - main context file for AI agents
102
+ */
103
+ private async generateClaudeMd(
104
+ contextPath: string,
105
+ git: GitData,
106
+ stats: ProjectStats,
107
+ commands: Commands,
108
+ agents: AgentInfo[]
109
+ ): Promise<void> {
110
+ const workflowAgents = agents.filter((a) => a.type === 'workflow').map((a) => a.name)
111
+ const domainAgents = agents.filter((a) => a.type === 'domain').map((a) => a.name)
112
+
113
+ const content = `# ${stats.name} - Project Rules
114
+ <!-- projectId: ${this.config.projectId} -->
115
+ <!-- Generated: ${dateHelper.getTimestamp()} -->
116
+ <!-- Ecosystem: ${stats.ecosystem} | Type: ${stats.projectType} -->
117
+
118
+ ## THIS PROJECT (${stats.ecosystem})
119
+
120
+ **Type:** ${stats.projectType}
121
+ **Path:** ${this.config.projectPath}
122
+
123
+ ### Commands (USE THESE, NOT OTHERS)
124
+
125
+ | Action | Command |
126
+ |--------|---------|
127
+ | Install dependencies | \`${commands.install}\` |
128
+ | Run dev server | \`${commands.dev}\` |
129
+ | Run tests | \`${commands.test}\` |
130
+ | Build | \`${commands.build}\` |
131
+ | Lint | \`${commands.lint}\` |
132
+ | Format | \`${commands.format}\` |
133
+
134
+ ### Code Conventions
135
+
136
+ - **Languages**: ${stats.languages.join(', ') || 'Not detected'}
137
+ - **Frameworks**: ${stats.frameworks.join(', ') || 'Not detected'}
138
+
139
+ ---
140
+
141
+ ## PRJCT RULES
142
+
143
+ ### Path Resolution
144
+ **ALL prjct writes go to**: \`~/.prjct-cli/projects/${this.config.projectId}/\`
145
+ - NEVER write to \`.prjct/\`
146
+ - NEVER write to \`./\` for prjct data
147
+
148
+ ### Workflow
149
+ \`\`\`
150
+ p. sync → p. task "desc" → [work] → p. done → p. ship
151
+ \`\`\`
152
+
153
+ | Command | Action |
154
+ |---------|--------|
155
+ | \`p. sync\` | Re-analyze project |
156
+ | \`p. task X\` | Start task |
157
+ | \`p. done\` | Complete subtask |
158
+ | \`p. ship X\` | Ship feature |
159
+
160
+ ---
161
+
162
+ ## PROJECT STATE
163
+
164
+ | Field | Value |
165
+ |-------|-------|
166
+ | Name | ${stats.name} |
167
+ | Version | ${stats.version} |
168
+ | Ecosystem | ${stats.ecosystem} |
169
+ | Branch | ${git.branch} |
170
+ | Files | ~${stats.fileCount} |
171
+ | Commits | ${git.commits} |
172
+
173
+ ---
174
+
175
+ ## AGENTS
176
+
177
+ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
178
+
179
+ **Workflow**: ${workflowAgents.join(', ')}
180
+ **Domain**: ${domainAgents.join(', ') || 'none'}
181
+ `
182
+
183
+ await fs.writeFile(path.join(contextPath, 'CLAUDE.md'), content, 'utf-8')
184
+ }
185
+
186
+ /**
187
+ * Generate now.md - current task status
188
+ */
189
+ private async generateNowMd(contextPath: string): Promise<void> {
190
+ let currentTask = null
191
+ try {
192
+ const statePath = path.join(this.config.globalPath, 'storage', 'state.json')
193
+ const state = JSON.parse(await fs.readFile(statePath, 'utf-8'))
194
+ currentTask = state.currentTask
195
+ } catch {
196
+ // No state file
197
+ }
198
+
199
+ const content = currentTask
200
+ ? `# NOW
201
+
202
+ **${currentTask.description}**
203
+
204
+ Started: ${currentTask.startedAt}
205
+ ${currentTask.branch ? `Branch: ${currentTask.branch.name}` : ''}
206
+ `
207
+ : `# NOW
208
+
209
+ _No active task_
210
+
211
+ Use \`p. task "description"\` to start working.
212
+ `
213
+
214
+ await fs.writeFile(path.join(contextPath, 'now.md'), content, 'utf-8')
215
+ }
216
+
217
+ /**
218
+ * Generate next.md - task queue
219
+ */
220
+ private async generateNextMd(contextPath: string): Promise<void> {
221
+ let queue: { tasks: { description: string; priority?: string }[] } = { tasks: [] }
222
+ try {
223
+ const queuePath = path.join(this.config.globalPath, 'storage', 'queue.json')
224
+ queue = JSON.parse(await fs.readFile(queuePath, 'utf-8'))
225
+ } catch {
226
+ // No queue file
227
+ }
228
+
229
+ const content = `# NEXT
230
+
231
+ ${
232
+ queue.tasks.length > 0
233
+ ? queue.tasks
234
+ .map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ''}`)
235
+ .join('\n')
236
+ : '_Empty queue_'
237
+ }
238
+ `
239
+
240
+ await fs.writeFile(path.join(contextPath, 'next.md'), content, 'utf-8')
241
+ }
242
+
243
+ /**
244
+ * Generate ideas.md - captured ideas
245
+ */
246
+ private async generateIdeasMd(contextPath: string): Promise<void> {
247
+ let ideas: { ideas: { text: string; priority?: string }[] } = { ideas: [] }
248
+ try {
249
+ const ideasPath = path.join(this.config.globalPath, 'storage', 'ideas.json')
250
+ ideas = JSON.parse(await fs.readFile(ideasPath, 'utf-8'))
251
+ } catch {
252
+ // No ideas file
253
+ }
254
+
255
+ const content = `# IDEAS
256
+
257
+ ${
258
+ ideas.ideas.length > 0
259
+ ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [${i.priority}]` : ''}`).join('\n')
260
+ : '_No ideas captured yet_'
261
+ }
262
+ `
263
+
264
+ await fs.writeFile(path.join(contextPath, 'ideas.md'), content, 'utf-8')
265
+ }
266
+
267
+ /**
268
+ * Generate shipped.md - completed features
269
+ */
270
+ private async generateShippedMd(contextPath: string): Promise<void> {
271
+ let shipped: { shipped: { name: string; version?: string; shippedAt: string }[] } = {
272
+ shipped: [],
273
+ }
274
+ try {
275
+ const shippedPath = path.join(this.config.globalPath, 'storage', 'shipped.json')
276
+ shipped = JSON.parse(await fs.readFile(shippedPath, 'utf-8'))
277
+ } catch {
278
+ // No shipped file
279
+ }
280
+
281
+ const content = `# SHIPPED 🚀
282
+
283
+ ${
284
+ shipped.shipped.length > 0
285
+ ? shipped.shipped
286
+ .slice(-10)
287
+ .map((s) => `- **${s.name}**${s.version ? ` v${s.version}` : ''} - ${s.shippedAt}`)
288
+ .join('\n')
289
+ : '_Nothing shipped yet_'
290
+ }
291
+
292
+ **Total shipped:** ${shipped.shipped.length}
293
+ `
294
+
295
+ await fs.writeFile(path.join(contextPath, 'shipped.md'), content, 'utf-8')
296
+ }
297
+ }
298
+
299
+ export default ContextFileGenerator