prjct-cli 0.10.0 → 0.10.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 (43) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/core/__tests__/agentic/memory-system.test.js +263 -0
  3. package/core/__tests__/agentic/plan-mode.test.js +336 -0
  4. package/core/agentic/chain-of-thought.js +578 -0
  5. package/core/agentic/command-executor.js +238 -4
  6. package/core/agentic/context-builder.js +208 -8
  7. package/core/agentic/ground-truth.js +591 -0
  8. package/core/agentic/loop-detector.js +406 -0
  9. package/core/agentic/memory-system.js +850 -0
  10. package/core/agentic/parallel-tools.js +366 -0
  11. package/core/agentic/plan-mode.js +572 -0
  12. package/core/agentic/prompt-builder.js +76 -1
  13. package/core/agentic/response-templates.js +290 -0
  14. package/core/agentic/semantic-compression.js +517 -0
  15. package/core/agentic/think-blocks.js +657 -0
  16. package/core/agentic/tool-registry.js +32 -0
  17. package/core/agentic/validation-rules.js +380 -0
  18. package/core/command-registry.js +48 -0
  19. package/core/commands.js +65 -1
  20. package/core/context-sync.js +183 -0
  21. package/package.json +7 -15
  22. package/templates/commands/done.md +7 -0
  23. package/templates/commands/feature.md +8 -0
  24. package/templates/commands/ship.md +8 -0
  25. package/templates/commands/spec.md +128 -0
  26. package/templates/global/CLAUDE.md +17 -0
  27. package/core/__tests__/agentic/agent-router.test.js +0 -398
  28. package/core/__tests__/agentic/command-executor.test.js +0 -223
  29. package/core/__tests__/agentic/context-builder.test.js +0 -160
  30. package/core/__tests__/agentic/context-filter.test.js +0 -494
  31. package/core/__tests__/agentic/prompt-builder.test.js +0 -204
  32. package/core/__tests__/agentic/template-loader.test.js +0 -164
  33. package/core/__tests__/agentic/tool-registry.test.js +0 -243
  34. package/core/__tests__/domain/agent-generator.test.js +0 -289
  35. package/core/__tests__/domain/agent-loader.test.js +0 -179
  36. package/core/__tests__/domain/analyzer.test.js +0 -324
  37. package/core/__tests__/infrastructure/author-detector.test.js +0 -103
  38. package/core/__tests__/infrastructure/config-manager.test.js +0 -454
  39. package/core/__tests__/infrastructure/path-manager.test.js +0 -412
  40. package/core/__tests__/setup.test.js +0 -15
  41. package/core/__tests__/utils/date-helper.test.js +0 -169
  42. package/core/__tests__/utils/file-helper.test.js +0 -258
  43. package/core/__tests__/utils/jsonl-helper.test.js +0 -387
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Context Sync - Generates dynamic project context for Claude
3
+ *
4
+ * Creates ~/.prjct-cli/projects/{id}/CLAUDE.md with:
5
+ * - Stack info
6
+ * - Available agents (dynamic, varies per project)
7
+ * - Current task
8
+ * - Priority queue
9
+ *
10
+ * Called by: /p:sync, /p:analyze, /p:init
11
+ */
12
+
13
+ const fs = require('fs').promises
14
+ const path = require('path')
15
+ const os = require('os')
16
+
17
+ /**
18
+ * Generate project context file for Claude
19
+ * 100% DYNAMIC - reads whatever agents exist
20
+ *
21
+ * @param {string} projectPath - Local project path
22
+ * @param {string} projectId - Project ID from config
23
+ * @returns {Promise<{agents: string[], stack: string|null, currentTask: string|null}>}
24
+ */
25
+ async function generateLocalContext(projectPath, projectId) {
26
+ const globalPath = path.join(os.homedir(), '.prjct-cli/projects', projectId)
27
+
28
+ // 1. Read ALL agents that exist (dynamic - varies per project)
29
+ const agentsDir = path.join(globalPath, 'agents')
30
+ let agentFiles = []
31
+ try {
32
+ agentFiles = await fs.readdir(agentsDir)
33
+ agentFiles = agentFiles.filter(f => f.endsWith('.md'))
34
+ } catch {
35
+ // No agents directory yet
36
+ }
37
+
38
+ // 2. Read core files (may not exist)
39
+ const readSafe = async (p) => {
40
+ try {
41
+ return await fs.readFile(p, 'utf-8')
42
+ } catch {
43
+ return null
44
+ }
45
+ }
46
+
47
+ const [repoSummary, now, next, roadmap] = await Promise.all([
48
+ readSafe(path.join(globalPath, 'analysis/repo-summary.md')),
49
+ readSafe(path.join(globalPath, 'core/now.md')),
50
+ readSafe(path.join(globalPath, 'core/next.md')),
51
+ readSafe(path.join(globalPath, 'planning/roadmap.md'))
52
+ ])
53
+
54
+ // 3. Extract stack from repo-summary
55
+ const stack = extractStack(repoSummary)
56
+
57
+ // 4. Generate agent list with clean names
58
+ const agents = agentFiles.map(f => f.replace('.md', ''))
59
+
60
+ // 5. Extract current task
61
+ const currentTask = extractCurrentTask(now)
62
+
63
+ // 6. Extract top 3 from next.md
64
+ const nextTasks = extractTopTasks(next, 3)
65
+
66
+ // 7. Extract active features from roadmap
67
+ const activeFeatures = extractActiveFeatures(roadmap)
68
+
69
+ // 8. Generate CLAUDE.md content
70
+ const content = `# Project Context
71
+ <!-- Auto-generated by /p:sync - DO NOT EDIT -->
72
+ <!-- projectId: ${projectId} -->
73
+ <!-- Last sync: ${new Date().toISOString()} -->
74
+
75
+ ## Stack
76
+ ${stack || 'Run /p:analyze to detect stack'}
77
+
78
+ ## Available Agents
79
+ ${agents.length ? agents.map(a => `- ${a}`).join('\n') : 'None. Run /p:sync to generate.'}
80
+
81
+ ## Current Task
82
+ ${currentTask || 'None. Use /p:now to start.'}
83
+
84
+ ## Next Up
85
+ ${nextTasks.length ? nextTasks.map((t, i) => `${i + 1}. ${t}`).join('\n') : 'Empty queue.'}
86
+
87
+ ## Active Features
88
+ ${activeFeatures.length ? activeFeatures.map(f => `- ${f}`).join('\n') : 'None in progress.'}
89
+
90
+ ## Data Location
91
+ All project data: ~/.prjct-cli/projects/${projectId}/
92
+ - agents/ - Read for detailed patterns and code examples
93
+ - analysis/repo-summary.md - Full technical analysis
94
+ - planning/roadmap.md - Features and roadmap
95
+ `
96
+
97
+ // 9. Write to global storage (NOT in repo)
98
+ const contextPath = path.join(globalPath, 'CLAUDE.md')
99
+ await fs.writeFile(contextPath, content, 'utf-8')
100
+
101
+ return { agents, stack, currentTask }
102
+ }
103
+
104
+ /**
105
+ * Extract stack from repo-summary
106
+ */
107
+ function extractStack(summary) {
108
+ if (!summary) return null
109
+
110
+ // Try multiple patterns
111
+ const patterns = [
112
+ /\*\*(?:Stack|Framework|Language)\*\*[:\s|]+([^\n|]+)/i,
113
+ /\| \*\*Type\*\* \| ([^\|]+) \|/i,
114
+ /## Tech Stack[\s\S]*?### (?:Frontend|Backend)\n- \*\*([^*]+)\*\*/i
115
+ ]
116
+
117
+ for (const pattern of patterns) {
118
+ const match = summary.match(pattern)
119
+ if (match) return match[1].trim()
120
+ }
121
+
122
+ return null
123
+ }
124
+
125
+ /**
126
+ * Extract current task from now.md
127
+ */
128
+ function extractCurrentTask(now) {
129
+ if (!now) return null
130
+
131
+ // Skip headers and empty lines, get first content line
132
+ const lines = now.split('\n')
133
+ for (const line of lines) {
134
+ const trimmed = line.trim()
135
+ if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('<!--')) {
136
+ return trimmed
137
+ }
138
+ }
139
+ return null
140
+ }
141
+
142
+ /**
143
+ * Extract top N tasks from next.md
144
+ */
145
+ function extractTopTasks(next, count) {
146
+ if (!next) return []
147
+
148
+ return next
149
+ .split('\n')
150
+ .filter(l => l.match(/^[-*\d.]\s/))
151
+ .slice(0, count)
152
+ .map(l => l.replace(/^[-*\d.]\s+/, '').trim())
153
+ .filter(Boolean)
154
+ }
155
+
156
+ /**
157
+ * Extract active features from roadmap.md
158
+ */
159
+ function extractActiveFeatures(roadmap) {
160
+ if (!roadmap) return []
161
+
162
+ const features = []
163
+ const lines = roadmap.split('\n')
164
+ let inActive = false
165
+
166
+ for (const line of lines) {
167
+ if (line.includes('Active') || line.includes('In Progress')) {
168
+ inActive = true
169
+ continue
170
+ }
171
+ if (line.startsWith('## ') && inActive) {
172
+ break // End of active section
173
+ }
174
+ if (inActive && line.match(/^- \[ \]/)) {
175
+ const feature = line.replace(/^- \[ \]\s*\*\*/, '').replace(/\*\*.*$/, '').trim()
176
+ if (feature) features.push(feature)
177
+ }
178
+ }
179
+
180
+ return features.slice(0, 3) // Max 3
181
+ }
182
+
183
+ module.exports = { generateLocalContext }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "0.10.0",
3
+ "version": "0.10.3",
4
4
  "description": "Built for Claude - Ship fast, track progress, stay focused. Developer momentum tool for indie hackers.",
5
5
  "main": "core/index.js",
6
6
  "bin": {
@@ -15,18 +15,14 @@
15
15
  "update-commands": "node -e \"const installer = require('./core/infrastructure/command-installer'); installer.syncCommands().then(r => console.log('Commands updated:', r)).catch(e => console.error('Error:', e.message))\"",
16
16
  "install-global": "./scripts/install.sh",
17
17
  "update": "./scripts/update.sh",
18
- "test": "vitest run --workspace=vitest.workspace.js",
19
- "test:watch": "vitest --workspace=vitest.workspace.js",
20
- "test:coverage": "vitest run --coverage --workspace=vitest.workspace.js",
18
+ "test": "vitest run",
19
+ "test:watch": "vitest",
20
+ "test:coverage": "vitest run --coverage",
21
21
  "validate": "node scripts/validate-commands.js",
22
- "lint": "eslint \"**/*.js\" --ignore-pattern \"node_modules/**\" --ignore-pattern \"website/**\"",
23
- "lint:fix": "eslint \"**/*.js\" --fix --ignore-pattern \"node_modules/**\" --ignore-pattern \"website/**\"",
22
+ "lint": "eslint . --ignore-pattern node_modules",
23
+ "lint:fix": "eslint . --fix --ignore-pattern node_modules",
24
24
  "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,md}\" --config .config/.prettierrc --ignore-path .config/.prettierignore",
25
- "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,md}\" --config .config/.prettierrc --ignore-path .config/.prettierignore",
26
- "website:dev": "cd website && npm run dev",
27
- "website:build": "cd website && npm run build",
28
- "website:preview": "cd website && npm run preview",
29
- "website:install": "cd website && npm install"
25
+ "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,md}\" --config .config/.prettierrc --ignore-path .config/.prettierignore"
30
26
  },
31
27
  "keywords": [
32
28
  "claude-code",
@@ -48,7 +44,6 @@
48
44
  "prompts": "^2.4.2"
49
45
  },
50
46
  "devDependencies": {
51
- "@types/node": "^20.0.0",
52
47
  "@vitest/coverage-v8": "^3.2.4",
53
48
  "eslint": "^8.57.1",
54
49
  "eslint-config-prettier": "^10.1.8",
@@ -56,10 +51,7 @@
56
51
  "eslint-plugin-import": "^2.32.0",
57
52
  "eslint-plugin-n": "^16.6.2",
58
53
  "eslint-plugin-promise": "^6.6.0",
59
- "jsdom": "^27.0.0",
60
54
  "prettier": "^3.6.2",
61
- "prettier-plugin-tailwindcss": "^0.6.14",
62
- "typescript": "^5.0.0",
63
55
  "vitest": "^3.2.4"
64
56
  },
65
57
  "repository": {
@@ -1,10 +1,17 @@
1
1
  ---
2
2
  allowed-tools: [Read, Write]
3
3
  description: 'Complete task'
4
+ think-triggers: [report_complete]
4
5
  ---
5
6
 
6
7
  # /p:done
7
8
 
9
+ ## Think First
10
+ Before marking complete, verify:
11
+ 1. Is the task actually finished?
12
+ 2. Were all acceptance criteria met?
13
+ 3. Should this trigger a /p:ship?
14
+
8
15
  ## Check
9
16
  Requires: `core/now.md` has content
10
17
 
@@ -2,10 +2,18 @@
2
2
  allowed-tools: [Read, Write, Bash, GetTimestamp, GetDate]
3
3
  description: 'Value analysis + roadmap + task breakdown + auto-start'
4
4
  timestamp-rule: 'GetTimestamp() and GetDate() for ALL timestamps'
5
+ think-triggers: [explore_to_edit, complex_analysis]
5
6
  ---
6
7
 
7
8
  # /p:feature
8
9
 
10
+ ## Think First
11
+ Before creating feature, analyze:
12
+ 1. Is this a simple or complex feature?
13
+ 2. What files/components will be affected?
14
+ 3. Are there dependencies or blockers?
15
+ 4. Should I create a /p:spec first?
16
+
9
17
  ## Flow
10
18
 
11
19
  1. **Value**: Impact/effort/timing → do_now/defer/blocked
@@ -2,10 +2,18 @@
2
2
  allowed-tools: [Read, Write, Bash, GetTimestamp, GetDate]
3
3
  description: 'Ship feature workflow'
4
4
  timestamp-rule: 'GetTimestamp() and GetDate() for timestamps'
5
+ think-triggers: [git_decision, report_complete]
5
6
  ---
6
7
 
7
8
  # /p:ship
8
9
 
10
+ ## Think First
11
+ Before shipping, verify:
12
+ 1. Are there uncommitted changes to include?
13
+ 2. What version bump is needed (patch/minor/major)?
14
+ 3. Is the feature actually complete?
15
+ 4. Should tests run first?
16
+
9
17
  ## Workflow (non-blocking)
10
18
  1. Lint → Tests → Docs update
11
19
  2. Version bump → CHANGELOG
@@ -0,0 +1,128 @@
1
+ ---
2
+ allowed-tools: [Read, Write, Glob, GetTimestamp, GetDate]
3
+ description: 'Spec-driven development for complex features'
4
+ timestamp-rule: 'GetTimestamp() and GetDate() for ALL timestamps'
5
+ think-triggers: [explore_to_edit, complex_analysis]
6
+ ---
7
+
8
+ # /p:spec
9
+
10
+ Spec-Driven Development. Creates detailed specifications for complex features before implementation.
11
+
12
+ ## Think First
13
+ Before creating spec, analyze:
14
+ 1. Is this feature complex enough for a spec? (auth, payments, migrations = yes)
15
+ 2. What are the key architectural decisions to make?
16
+ 3. Are there multiple valid approaches? Document tradeoffs.
17
+ 4. What questions should I ask the user before proceeding?
18
+
19
+ ## Purpose
20
+
21
+ For features that require:
22
+ - Clear requirements before coding
23
+ - Design decisions documented
24
+ - Tasks broken into 20-30 min chunks
25
+ - User approval before starting
26
+
27
+ ## Flow
28
+
29
+ ### No params: Show template
30
+ ```
31
+ → Interactive spec template
32
+ → Ask for feature name
33
+ → Guide through requirements
34
+ ```
35
+
36
+ ### With feature name: Create spec
37
+ ```
38
+ /p:spec "Dark Mode"
39
+ 1. Analyze: Context, patterns, dependencies
40
+ 2. Propose: Requirements + Design + Tasks
41
+ 3. Write: `planning/specs/{slug}.md`
42
+ 4. Ask: User approval
43
+ 5. On approve: Add tasks to queue, start first
44
+ ```
45
+
46
+ ## Spec Structure
47
+
48
+ ```markdown
49
+ # Feature Spec: {name}
50
+
51
+ **Created**: {GetDate()}
52
+ **Status**: PENDING_APPROVAL | APPROVED | IN_PROGRESS | COMPLETED
53
+
54
+ ## Requirements (User approves)
55
+ - [ ] Requirement 1
56
+ - [ ] Requirement 2
57
+ - [ ] Requirement 3
58
+
59
+ ## Design (Claude proposes)
60
+ - **Approach**: {architecture decision}
61
+ - **Key decisions**: {list}
62
+ - **Dependencies**: {existing code/libs}
63
+
64
+ ## Tasks (20-30min each)
65
+ 1. [ ] Task 1 (20m) - {description}
66
+ 2. [ ] Task 2 (25m) - {description}
67
+ 3. [ ] Task 3 (30m) - {description}
68
+
69
+ **Total**: {n} tasks, ~{Xh}
70
+
71
+ ## Notes
72
+ - {implementation notes}
73
+ - {edge cases to consider}
74
+ ```
75
+
76
+ ## Validation
77
+
78
+ - Feature name required for creation
79
+ - Spec must have at least 1 requirement
80
+ - Each task should be 20-30 minutes
81
+ - Check for existing spec with same name
82
+
83
+ ## Data
84
+
85
+ Session: `{"ts":"{GetTimestamp()}","type":"spec_create","name":"{feature}","requirements":{n},"tasks":{n},"effort":"{Xh}"}`
86
+ Spec file: `planning/specs/{feature-slug}.md`
87
+
88
+ ## Response
89
+
90
+ ### On creation:
91
+ ```
92
+ 📋 Spec: {feature}
93
+
94
+ Requirements ({n}):
95
+ {numbered_list}
96
+
97
+ Design:
98
+ → {approach}
99
+ → {key_decision}
100
+
101
+ Tasks ({n}, ~{total_time}):
102
+ {numbered_list}
103
+
104
+ APPROVE? (y/n/edit)
105
+ ```
106
+
107
+ ### On approval:
108
+ ```
109
+ ✅ Spec approved: {feature}
110
+ → {n} tasks added to queue
111
+ → Starting: {task_1}
112
+
113
+ Use /p:done when complete
114
+ ```
115
+
116
+ ## Examples
117
+
118
+ ```
119
+ /p:spec "User Authentication"
120
+ → Creates spec with OAuth/JWT decisions
121
+ → Breaks into: setup, login, logout, session, tests
122
+ → Estimates ~4h total
123
+
124
+ /p:spec "Dark Mode"
125
+ → Creates spec with theme approach
126
+ → Breaks into: toggle, state, styles, persist, test
127
+ → Estimates ~3h total
128
+ ```
@@ -5,6 +5,23 @@ This section provides global context for all `/p:*` commands across any prjct pr
5
5
 
6
6
  **Auto-managed by prjct-cli** - This section is automatically updated when you install or update prjct.
7
7
 
8
+ ## 🤖 Project Context (OBLIGATORIO)
9
+
10
+ **ANTES de trabajar en un proyecto prjct, LEE el contexto del proyecto:**
11
+
12
+ 1. Lee `.prjct/prjct.config.json` → obtén `projectId`
13
+ 2. Lee `~/.prjct-cli/projects/{projectId}/CLAUDE.md` → contexto dinámico del proyecto
14
+ 3. Para detalles de implementación, lee los archivos en `agents/`
15
+
16
+ El archivo `CLAUDE.md` del proyecto contiene:
17
+ - Stack detectado del proyecto
18
+ - Agentes disponibles (varían por proyecto)
19
+ - Tarea actual
20
+ - Cola de prioridades
21
+ - Rutas a documentación detallada
22
+
23
+ **Si no existe CLAUDE.md**: Sugiere ejecutar `/p:sync` para generarlo.
24
+
8
25
  ## 🎯 Path Resolution for ALL /p:* Commands
9
26
 
10
27
  **CRITICAL**: Every `/p:*` command operates on **global storage**, NOT local files.