prjct-cli 0.31.0 → 0.34.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 (121) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/CLAUDE.md +41 -0
  3. package/core/__tests__/agentic/memory-system.test.ts +2 -2
  4. package/core/__tests__/types/fs.test.ts +125 -0
  5. package/core/agentic/agent-router.ts +16 -4
  6. package/core/agentic/chain-of-thought.ts +4 -12
  7. package/core/agentic/command-executor.ts +10 -11
  8. package/core/agentic/context-builder.ts +24 -10
  9. package/core/agentic/ground-truth.ts +139 -55
  10. package/core/agentic/prompt-builder.ts +20 -7
  11. package/core/agentic/smart-context.ts +1 -1
  12. package/core/agentic/template-loader.ts +1 -1
  13. package/core/agentic/tool-registry.ts +4 -2
  14. package/core/bus/bus.ts +1 -1
  15. package/core/commands/cleanup.ts +24 -8
  16. package/core/commands/planning.ts +4 -2
  17. package/core/commands/setup.ts +4 -4
  18. package/core/commands/shipping.ts +34 -8
  19. package/core/commands/snapshots.ts +27 -13
  20. package/core/context/generator.ts +9 -5
  21. package/core/domain/agent-generator.ts +1 -1
  22. package/core/domain/agent-loader.ts +1 -1
  23. package/core/domain/analyzer.ts +76 -31
  24. package/core/domain/context-estimator.ts +1 -1
  25. package/core/domain/snapshot-manager.ts +55 -21
  26. package/core/domain/task-stack.ts +16 -7
  27. package/core/infrastructure/author-detector.ts +1 -1
  28. package/core/infrastructure/claude-agent.ts +12 -8
  29. package/core/infrastructure/command-installer.ts +42 -21
  30. package/core/infrastructure/editors-config.ts +1 -1
  31. package/core/infrastructure/path-manager.ts +27 -2
  32. package/core/infrastructure/permission-manager.ts +1 -1
  33. package/core/infrastructure/setup.ts +31 -13
  34. package/core/infrastructure/update-checker.ts +5 -5
  35. package/core/integrations/jira/client.ts +91 -30
  36. package/core/integrations/jira/index.ts +29 -5
  37. package/core/integrations/jira/mcp-adapter.ts +451 -0
  38. package/core/integrations/linear/client.ts +23 -3
  39. package/core/plugin/loader.ts +16 -6
  40. package/core/plugin/registry.ts +16 -6
  41. package/core/server/routes-extended.ts +13 -6
  42. package/core/server/routes.ts +15 -5
  43. package/core/server/sse.ts +4 -3
  44. package/core/services/agent-service.ts +4 -2
  45. package/core/services/memory-service.ts +16 -5
  46. package/core/services/project-service.ts +11 -2
  47. package/core/services/skill-service.ts +4 -3
  48. package/core/session/compaction.ts +4 -5
  49. package/core/session/metrics.ts +11 -4
  50. package/core/session/task-session-manager.ts +27 -9
  51. package/core/storage/storage-manager.ts +12 -5
  52. package/core/storage/storage.ts +26 -10
  53. package/core/sync/auth-config.ts +2 -2
  54. package/core/sync/oauth-handler.ts +1 -1
  55. package/core/sync/sync-client.ts +4 -2
  56. package/core/sync/sync-manager.ts +1 -1
  57. package/core/types/agentic.ts +8 -18
  58. package/core/types/config.ts +1 -1
  59. package/core/types/index.ts +3 -2
  60. package/core/types/integrations.ts +4 -48
  61. package/core/types/storage.ts +0 -8
  62. package/core/types/task.ts +0 -4
  63. package/core/utils/file-helper.ts +10 -4
  64. package/core/utils/jsonl-helper.ts +4 -4
  65. package/core/utils/keychain.ts +130 -0
  66. package/core/utils/logger.ts +27 -25
  67. package/core/utils/runtime.ts +1 -1
  68. package/core/utils/session-helper.ts +4 -4
  69. package/core/utils/version.ts +1 -1
  70. package/package.json +1 -1
  71. package/packages/shared/src/utils.ts +1 -1
  72. package/scripts/postinstall.js +26 -2
  73. package/templates/agentic/orchestrator.md +303 -0
  74. package/templates/commands/bug.md +2 -0
  75. package/templates/commands/enrich.md +601 -195
  76. package/templates/commands/github.md +287 -0
  77. package/templates/commands/init.md +45 -26
  78. package/templates/commands/jira.md +198 -258
  79. package/templates/commands/linear.md +186 -172
  80. package/templates/commands/monday.md +232 -0
  81. package/templates/commands/p.md +57 -10
  82. package/templates/commands/setup.md +4 -1
  83. package/templates/commands/sync.md +133 -97
  84. package/templates/commands/task.md +12 -0
  85. package/templates/config/skill-mappings.json +95 -63
  86. package/templates/mcp-config.json +42 -39
  87. package/core/integrations/notion/client.ts +0 -413
  88. package/core/integrations/notion/index.ts +0 -46
  89. package/core/integrations/notion/setup.ts +0 -235
  90. package/core/integrations/notion/sync.ts +0 -818
  91. package/core/integrations/notion/templates.ts +0 -246
  92. package/core/plugin/builtin/notion.ts +0 -178
  93. package/dist/bin/prjct.mjs +0 -13581
  94. package/dist/core/infrastructure/command-installer.js +0 -473
  95. package/dist/core/infrastructure/editors-config.js +0 -157
  96. package/dist/core/infrastructure/setup.js +0 -893
  97. package/dist/core/utils/version.js +0 -142
  98. package/packages/shared/.turbo/turbo-build.log +0 -14
  99. package/packages/shared/dist/index.d.ts +0 -10
  100. package/packages/shared/dist/index.d.ts.map +0 -1
  101. package/packages/shared/dist/index.js +0 -4196
  102. package/packages/shared/dist/schemas.d.ts +0 -408
  103. package/packages/shared/dist/schemas.d.ts.map +0 -1
  104. package/packages/shared/dist/types.d.ts +0 -144
  105. package/packages/shared/dist/types.d.ts.map +0 -1
  106. package/packages/shared/dist/unified.d.ts +0 -139
  107. package/packages/shared/dist/unified.d.ts.map +0 -1
  108. package/packages/shared/dist/utils.d.ts +0 -60
  109. package/packages/shared/dist/utils.d.ts.map +0 -1
  110. package/templates/commands/ask.md +0 -128
  111. package/templates/commands/dashboard.md +0 -686
  112. package/templates/commands/feature.md +0 -46
  113. package/templates/commands/now.md +0 -53
  114. package/templates/commands/suggest.md +0 -116
  115. package/templates/global/docs/agents.md +0 -88
  116. package/templates/global/docs/architecture.md +0 -103
  117. package/templates/global/docs/commands.md +0 -96
  118. package/templates/global/docs/validation.md +0 -95
  119. package/templates/skills/notion-push.md +0 -116
  120. package/templates/skills/notion-setup.md +0 -199
  121. package/templates/skills/notion-sync.md +0 -290
package/CHANGELOG.md CHANGED
@@ -1,5 +1,188 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.34.0] - 2026-01-15
4
+
5
+ ### Feature: Agentic Orchestrator + MCP Auto-Install
6
+
7
+ Major release with intelligent task routing and simplified integration setup.
8
+
9
+ #### Orchestrator Agent (NEW)
10
+
11
+ Auto-routing system for tasks to the right agents and skills:
12
+
13
+ - **Domain Detection**: Analyzes task keywords to detect domains (frontend, backend, database, etc.)
14
+ - **Agent Loading**: Automatically loads relevant agents from `{globalPath}/agents/`
15
+ - **Skill Invocation**: Invokes skills from `~/.claude/skills/` based on task context
16
+ - **Multi-Domain Coordination**: Handles tasks spanning multiple domains with proper execution order
17
+
18
+ **Usage**: Orchestrator runs automatically for task-related commands (`p. task`, `p. done`, `p. ship`, etc.)
19
+
20
+ #### MCP Server Auto-Install
21
+
22
+ All integrations now auto-install their MCP servers:
23
+
24
+ - **Linear**: Auto-installs `mcp-remote` for Linear API
25
+ - **JIRA**: Auto-installs Atlassian MCP server
26
+ - **GitHub**: Auto-installs GitHub MCP server with token validation
27
+ - **Monday.com**: Auto-installs Monday MCP server
28
+
29
+ No more manual `~/.claude/settings.json` editing - just run `p. linear setup` and it handles everything.
30
+
31
+ #### Individual Command Skills
32
+
33
+ All 37 prjct commands now available as individual Claude Code skills:
34
+
35
+ - `/p.task` - Start a task
36
+ - `/p.sync` - Sync project
37
+ - `/p.linear` - Linear integration
38
+ - Plus 34 more commands
39
+
40
+ #### agentskills.io Integration
41
+
42
+ Skills are now discovered from the official agentskills.io ecosystem:
43
+
44
+ - Skills from `anthropics/skills` GitHub repo
45
+ - Proper SKILL.md format with YAML frontmatter
46
+ - Agent-to-skill mapping in `templates/config/skill-mappings.json`
47
+
48
+ **Files Changed:**
49
+ - `templates/agentic/orchestrator.md` (NEW)
50
+ - `templates/commands/p.md` - Orchestrator integration
51
+ - `templates/commands/task.md` - Orchestrator context usage
52
+ - `templates/commands/linear.md` - MCP auto-install
53
+ - `templates/commands/jira.md` - MCP auto-install
54
+ - `templates/commands/github.md` - MCP auto-install
55
+ - `templates/commands/monday.md` - MCP auto-install
56
+ - `templates/config/skill-mappings.json` - agentskills.io sources
57
+ - `scripts/postinstall.js` - Individual command installation
58
+
59
+ **Removed (deprecated):**
60
+ - `templates/commands/feature.md`
61
+ - `templates/commands/now.md`
62
+ - `templates/commands/dashboard.md`
63
+ - `templates/commands/suggest.md`
64
+ - `templates/commands/ask.md`
65
+
66
+ ---
67
+
68
+ ## [0.33.5] - 2026-01-13
69
+
70
+ ### Fix: Type Safety Improvements (PRJ-54)
71
+
72
+ Remove unsafe `as unknown` type casts with proper TypeScript interfaces.
73
+
74
+ **Changes:**
75
+ - `GroundTruthContext` now uses `ContextPaths` directly
76
+ - `chain-of-thought.ts` uses `Pick<ProjectContext, ...>` type alias
77
+ - `command-executor.ts` uses `PromptContext` instead of `Record<string, unknown>`
78
+
79
+ ---
80
+
81
+ ## [0.33.4] - 2026-01-13
82
+
83
+ ### Refactor: Error Type Differentiation Phase 3 (PRJ-61)
84
+
85
+ **Final phase** - Complete error differentiation across all 116 remaining catch blocks in 52 files.
86
+
87
+ **Pattern Applied:**
88
+ - `isNotFoundError()` for expected ENOENT errors
89
+ - `instanceof SyntaxError` for JSON parse errors
90
+ - `_error` capture for intentional catch-all blocks (network, git, etc.)
91
+ - Unexpected errors propagate with `throw error`
92
+
93
+ **Key Files Fixed:**
94
+ - `core/storage/storage.ts` - Storage read/exists operations
95
+ - `core/commands/shipping.ts` - Ship workflow error handling
96
+ - `core/session/task-session-manager.ts` - Session management
97
+ - `core/commands/cleanup.ts` - Cleanup operations
98
+ - `core/agentic/context-builder.ts` - Context building
99
+ - Plus 47 more files
100
+
101
+ **Stats:**
102
+ - Catches fixed this phase: 116
103
+ - Total fixed (Phase 1+2+3): 185
104
+ - Remaining: 0 empty catches
105
+
106
+ ---
107
+
108
+ ## [0.33.3] - 2026-01-13
109
+
110
+ ### Refactor: Error Type Differentiation Phase 2 (PRJ-60)
111
+
112
+ **Continuation of PRJ-51** - Differentiate error types in 3 more files (14 catch blocks):
113
+
114
+ **Files Modified:**
115
+ - `core/domain/snapshot-manager.ts` - 6 catches (fs.access, fs.readFile, fs.unlink, JSON.parse)
116
+ - `core/server/routes-extended.ts` - 2 catches (readJsonFile, writeJsonFile helpers)
117
+ - `core/infrastructure/setup.ts` - 6 catches (migration, settings parsing, status line)
118
+
119
+ **Pattern Applied:**
120
+ - ENOENT errors → handled gracefully (expected for missing files)
121
+ - SyntaxError → handled gracefully (expected for malformed JSON)
122
+ - Other errors → propagated or logged (unexpected)
123
+
124
+ **Stats:**
125
+ - Catches fixed: 14
126
+ - Total fixed (Phase 1+2): 69
127
+ - Remaining: ~211 catches in 63 files
128
+
129
+ ---
130
+
131
+ ## [0.33.2] - 2026-01-13
132
+
133
+ ### Refactor: Error Type Differentiation (PRJ-51)
134
+
135
+ **Problem:** 280 catch blocks across 69 files used empty `catch {}` which swallowed all errors without differentiating between expected (ENOENT) and unexpected errors.
136
+
137
+ **Solution:** Phase 1 implementation - differentiate error types in 3 priority files (55 catch blocks):
138
+
139
+ **Pattern Applied:**
140
+ ```typescript
141
+ // Before
142
+ } catch { return null }
143
+
144
+ // After
145
+ } catch (error) {
146
+ if (isNotFoundError(error)) return null // Expected: file doesn't exist
147
+ if (error instanceof SyntaxError) return null // Expected: invalid JSON
148
+ throw error // Unexpected: propagate
149
+ }
150
+ ```
151
+
152
+ **Files Modified:**
153
+ - `core/agentic/ground-truth.ts` - 21 catches (verification functions)
154
+ - `core/domain/analyzer.ts` - 18 catches (codebase analysis)
155
+ - `core/infrastructure/command-installer.ts` - 16 catches (command management)
156
+
157
+ **Tests Added:**
158
+ - `core/__tests__/types/fs.test.ts` - 15 new tests for error utilities
159
+
160
+ **Stats:**
161
+ - Tests: 137 → 152 (+15)
162
+ - Catches fixed: 55
163
+ - Files: 4 (3 refactored + 1 test)
164
+
165
+ ---
166
+
167
+ ## [0.33.1] - 2026-01-13
168
+
169
+ ### Refactor: Code Quality Improvements
170
+
171
+ **PRJ-58: Consolidate hardcoded paths to pathManager**
172
+ - Added `getClaudeDir()`, `getClaudeCommandsDir()`, `getClaudeSettingsPath()` to pathManager
173
+ - Refactored 6 files to use centralized path methods instead of `os.homedir()` concatenation
174
+ - Files: `compaction.ts`, `generator.ts`, `routes-extended.ts`, `routes.ts`, `auth-config.ts`, `setup.ts`
175
+
176
+ **PRJ-57: Simplify logger level detection**
177
+ - Use `Set` for truthy values instead of multiple OR conditions
178
+ - Remove redundant `'prjct'` equality check (covered by `includes`)
179
+ - Use nullish coalescing (`??`) instead of ternary
180
+ - Pre-compute level name to avoid runtime lookup
181
+ - Add `createLogMethod()` factory to reduce repetition
182
+ - File: `core/utils/logger.ts`
183
+
184
+ ---
185
+
3
186
  ## [0.30.3] - 2026-01-13
4
187
 
5
188
  ### Fix: Enrichment Not Enabled by Default
package/CLAUDE.md CHANGED
@@ -91,6 +91,7 @@ User Action → Storage (JSON) → Context (MD) → Sync Events
91
91
 
92
92
  ## COMMANDS
93
93
 
94
+ ### Core Workflow
94
95
  | Trigger | Purpose |
95
96
  |---------|---------|
96
97
  | `p. init` | Initialize project with deep analysis |
@@ -102,11 +103,51 @@ User Action → Storage (JSON) → Context (MD) → Sync Events
102
103
  | `p. resume` | Resume paused task |
103
104
  | `p. bug <desc>` | Report bug with auto-priority |
104
105
 
106
+ ### Issue Tracker Integrations
107
+ | Trigger | Purpose |
108
+ |---------|---------|
109
+ | `p. linear` | Linear issues (OAuth via MCP) |
110
+ | `p. jira` | JIRA issues (OAuth/SSO via MCP) |
111
+ | `p. github` | GitHub Issues (token via MCP) |
112
+ | `p. monday` | Monday.com boards (OAuth via MCP) |
113
+ | `p. enrich <ID>` | **AI-powered ticket enrichment** |
114
+
115
+ ### Ticket Enrichment (`p. enrich`)
116
+
117
+ Transform vague PM tickets into technical PRDs:
118
+
119
+ ```
120
+ PM creates: "Add user auth"
121
+
122
+ p. enrich PRJ-59
123
+
124
+ Architect analyzes codebase:
125
+ - Similar implementations found
126
+ - 5 files affected
127
+ - OAuth2 approach recommended
128
+ - 8 story points (not PM's guess of 2)
129
+
130
+ Publishes PRD to tracker:
131
+ - Technical approach
132
+ - Acceptance criteria
133
+ - LLM-ready prompt (for any AI tool)
134
+ ```
135
+
136
+ **Subcommands:**
137
+ - `p. enrich <ID>` - Enrich specific ticket
138
+ - `p. enrich setup` - Configure team preferences (estimation, output)
139
+ - `p. enrich batch` - Enrich all assigned tickets (backlog grooming)
140
+
105
141
  ### Workflow
106
142
  ```
107
143
  p. sync → p. task "description" → [work] → p. done → p. ship
108
144
  ```
109
145
 
146
+ ### With Issue Tracker
147
+ ```
148
+ p. linear → p. enrich PRJ-59 → p. linear start PRJ-59 → [work] → p. done → p. ship
149
+ ```
150
+
110
151
  ---
111
152
 
112
153
  ## INTELLIGENT BEHAVIOR
@@ -253,7 +253,7 @@ describe('MemorySystem P3.3', () => {
253
253
  try {
254
254
  const testPath = pathManager.getGlobalProjectPath(TEST_PROJECT_ID)
255
255
  await fs.rm(testPath, { recursive: true, force: true })
256
- } catch {
256
+ } catch (_error) {
257
257
  // Ignore cleanup errors
258
258
  }
259
259
  })
@@ -261,7 +261,7 @@ describe('MemorySystem P3.3', () => {
261
261
  afterAll(async () => {
262
262
  try {
263
263
  await fs.rm(TEST_GLOBAL_BASE_DIR, { recursive: true, force: true })
264
- } catch {
264
+ } catch (_error) {
265
265
  // Ignore cleanup errors
266
266
  }
267
267
  })
@@ -0,0 +1,125 @@
1
+ /**
2
+ * FS Types Tests
3
+ * Tests for file system error utilities
4
+ */
5
+
6
+ import { describe, it, expect } from 'bun:test'
7
+ import {
8
+ isNotFoundError,
9
+ isPermissionError,
10
+ isDirNotEmptyError,
11
+ isFileExistsError,
12
+ isNodeError,
13
+ } from '../../types/fs'
14
+
15
+ describe('FS Error Utilities', () => {
16
+ describe('isNotFoundError', () => {
17
+ it('should return true for ENOENT error', () => {
18
+ const error = new Error('File not found') as NodeJS.ErrnoException
19
+ error.code = 'ENOENT'
20
+ expect(isNotFoundError(error)).toBe(true)
21
+ })
22
+
23
+ it('should return false for other error codes', () => {
24
+ const error = new Error('Permission denied') as NodeJS.ErrnoException
25
+ error.code = 'EACCES'
26
+ expect(isNotFoundError(error)).toBe(false)
27
+ })
28
+
29
+ it('should return false for errors without code', () => {
30
+ const error = new Error('Generic error')
31
+ expect(isNotFoundError(error)).toBe(false)
32
+ })
33
+
34
+ it('should return false for non-error values', () => {
35
+ expect(isNotFoundError(null)).toBe(false)
36
+ expect(isNotFoundError(undefined)).toBe(false)
37
+ expect(isNotFoundError('string')).toBe(false)
38
+ })
39
+ })
40
+
41
+ describe('isPermissionError', () => {
42
+ it('should return true for EACCES error', () => {
43
+ const error = new Error('Permission denied') as NodeJS.ErrnoException
44
+ error.code = 'EACCES'
45
+ expect(isPermissionError(error)).toBe(true)
46
+ })
47
+
48
+ it('should return true for EPERM error', () => {
49
+ const error = new Error('Operation not permitted') as NodeJS.ErrnoException
50
+ error.code = 'EPERM'
51
+ expect(isPermissionError(error)).toBe(true)
52
+ })
53
+
54
+ it('should return false for other error codes', () => {
55
+ const error = new Error('File not found') as NodeJS.ErrnoException
56
+ error.code = 'ENOENT'
57
+ expect(isPermissionError(error)).toBe(false)
58
+ })
59
+ })
60
+
61
+ describe('isDirNotEmptyError', () => {
62
+ it('should return true for ENOTEMPTY error', () => {
63
+ const error = new Error('Directory not empty') as NodeJS.ErrnoException
64
+ error.code = 'ENOTEMPTY'
65
+ expect(isDirNotEmptyError(error)).toBe(true)
66
+ })
67
+
68
+ it('should return false for other error codes', () => {
69
+ const error = new Error('File not found') as NodeJS.ErrnoException
70
+ error.code = 'ENOENT'
71
+ expect(isDirNotEmptyError(error)).toBe(false)
72
+ })
73
+ })
74
+
75
+ describe('isFileExistsError', () => {
76
+ it('should return true for EEXIST error', () => {
77
+ const error = new Error('File exists') as NodeJS.ErrnoException
78
+ error.code = 'EEXIST'
79
+ expect(isFileExistsError(error)).toBe(true)
80
+ })
81
+
82
+ it('should return false for other error codes', () => {
83
+ const error = new Error('File not found') as NodeJS.ErrnoException
84
+ error.code = 'ENOENT'
85
+ expect(isFileExistsError(error)).toBe(false)
86
+ })
87
+ })
88
+
89
+ describe('isNodeError', () => {
90
+ it('should return true for Error with code property', () => {
91
+ const error = new Error('File not found') as NodeJS.ErrnoException
92
+ error.code = 'ENOENT'
93
+ expect(isNodeError(error)).toBe(true)
94
+ })
95
+
96
+ it('should return false for Error without code property', () => {
97
+ const error = new Error('Generic error')
98
+ expect(isNodeError(error)).toBe(false)
99
+ })
100
+
101
+ it('should return false for non-Error values', () => {
102
+ expect(isNodeError(null)).toBe(false)
103
+ expect(isNodeError({ code: 'ENOENT' })).toBe(false) // Not an Error instance
104
+ })
105
+ })
106
+
107
+ describe('SyntaxError handling pattern', () => {
108
+ it('should differentiate SyntaxError from fs errors', () => {
109
+ const syntaxError = new SyntaxError('Unexpected token')
110
+ const fsError = new Error('File not found') as NodeJS.ErrnoException
111
+ fsError.code = 'ENOENT'
112
+
113
+ // Pattern used in code
114
+ const handleError = (error: unknown): string => {
115
+ if (isNotFoundError(error)) return 'not-found'
116
+ if (error instanceof SyntaxError) return 'parse-error'
117
+ return 'other'
118
+ }
119
+
120
+ expect(handleError(fsError)).toBe('not-found')
121
+ expect(handleError(syntaxError)).toBe('parse-error')
122
+ expect(handleError(new Error('Other'))).toBe('other')
123
+ })
124
+ })
125
+ })
@@ -15,6 +15,7 @@ import fs from 'fs/promises'
15
15
  import path from 'path'
16
16
  import configManager from '../infrastructure/config-manager'
17
17
  import pathManager from '../infrastructure/path-manager'
18
+ import { isNotFoundError } from '../types/fs'
18
19
  import type { Agent, AssignmentContext } from '../types'
19
20
 
20
21
  // Re-export types for convenience
@@ -57,7 +58,11 @@ class AgentRouter {
57
58
  }
58
59
 
59
60
  return agents
60
- } catch {
61
+ } catch (error) {
62
+ // Agents directory doesn't exist yet - expected for new projects
63
+ if (!isNotFoundError(error)) {
64
+ console.error(`Agent loading error: ${(error as Error).message}`)
65
+ }
61
66
  return []
62
67
  }
63
68
  }
@@ -80,7 +85,11 @@ class AgentRouter {
80
85
  const filePath = path.join(this.agentsPath, `${name}.md`)
81
86
  const content = await fs.readFile(filePath, 'utf-8')
82
87
  return { name, content }
83
- } catch {
88
+ } catch (error) {
89
+ // Agent file doesn't exist - expected
90
+ if (!isNotFoundError(error)) {
91
+ console.error(`Agent load error: ${(error as Error).message}`)
92
+ }
84
93
  return null
85
94
  }
86
95
  }
@@ -130,8 +139,11 @@ class AgentRouter {
130
139
  }) + '\n'
131
140
 
132
141
  await fs.appendFile(logPath, entry)
133
- } catch {
134
- // Silent fail for logging
142
+ } catch (error) {
143
+ // Non-critical - log unexpected errors but don't fail
144
+ if (!isNotFoundError(error)) {
145
+ console.error(`Agent usage log error: ${(error as Error).message}`)
146
+ }
135
147
  }
136
148
  }
137
149
  }
@@ -6,19 +6,11 @@
6
6
  * @version 1.0.0
7
7
  */
8
8
 
9
- interface Context {
10
- projectId?: string | null
11
- projectPath: string
12
- params: Record<string, unknown>
13
- }
9
+ import type { ProjectContext, ContextState } from '../types'
14
10
 
15
- interface State {
16
- now?: string | null
17
- next?: string | null
18
- shipped?: string | null
19
- analysis?: string | null
20
- [key: string]: unknown
21
- }
11
+ // Type aliases for compatibility with ProjectContext from contextBuilder.build()
12
+ type Context = Pick<ProjectContext, 'projectId' | 'projectPath' | 'params'>
13
+ type State = ContextState
22
14
 
23
15
  interface ReasoningStep {
24
16
  step: string
@@ -24,6 +24,7 @@ import type {
24
24
  SimpleExecutionResult,
25
25
  ExecutionToolsFn,
26
26
  ApprovalContext,
27
+ PromptContext,
27
28
  } from '../types'
28
29
 
29
30
  // =============================================================================
@@ -42,7 +43,7 @@ export function signalStart(commandName: string): void {
42
43
  fs.mkdirSync(dir, { recursive: true })
43
44
  }
44
45
  fs.writeFileSync(RUNNING_FILE, `/p:${commandName}`)
45
- } catch {
46
+ } catch (_error) {
46
47
  // Silently ignore - status line is optional
47
48
  }
48
49
  }
@@ -55,7 +56,7 @@ export function signalEnd(): void {
55
56
  if (fs.existsSync(RUNNING_FILE)) {
56
57
  fs.unlinkSync(RUNNING_FILE)
57
58
  }
58
- } catch {
59
+ } catch (_error) {
59
60
  // Silently ignore - status line is optional
60
61
  }
61
62
  }
@@ -132,7 +133,7 @@ export class CommandExecutor {
132
133
  const preState = await contextBuilder.loadStateForCommand(metadataContext, commandName)
133
134
  groundTruthResult = await groundTruth.verify(
134
135
  commandName,
135
- metadataContext as unknown as Parameters<typeof groundTruth.verify>[1],
136
+ metadataContext,
136
137
  preState
137
138
  )
138
139
 
@@ -148,8 +149,8 @@ export class CommandExecutor {
148
149
  const reasoningState = await contextBuilder.loadStateForCommand(metadataContext, commandName)
149
150
  reasoning = await chainOfThought.reason(
150
151
  commandName,
151
- metadataContext as unknown as Parameters<typeof chainOfThought.reason>[1],
152
- reasoningState as Parameters<typeof chainOfThought.reason>[2]
152
+ metadataContext,
153
+ reasoningState
153
154
  )
154
155
 
155
156
  // If reasoning shows critical issues, warn but continue
@@ -160,11 +161,9 @@ export class CommandExecutor {
160
161
  }
161
162
 
162
163
  // 3. AGENTIC: Claude decides agent assignment via templates
163
- let context: Record<string, unknown> = metadataContext as unknown as Record<string, unknown>
164
-
165
- // Provide agent info to context so Claude can delegate
166
- context = {
167
- ...context,
164
+ // Build context with agent routing info for Claude delegation
165
+ const context: PromptContext = {
166
+ ...metadataContext,
168
167
  agentsPath: path.join(os.homedir(), '.prjct-cli', 'projects', metadataContext.projectId || '', 'agents'),
169
168
  agentRoutingPath: path.join(__dirname, '..', '..', 'templates', 'agentic', 'agent-routing.md'),
170
169
  agenticDelegation: true,
@@ -205,7 +204,7 @@ export class CommandExecutor {
205
204
  // Agent is null - Claude assigns via Task tool using agent-routing.md
206
205
  const prompt = promptBuilder.build(
207
206
  template,
208
- context as Parameters<typeof promptBuilder.build>[1],
207
+ context,
209
208
  state,
210
209
  null,
211
210
  learnedPatterns,
@@ -9,6 +9,7 @@
9
9
  import fs from 'fs/promises'
10
10
  import pathManager from '../infrastructure/path-manager'
11
11
  import configManager from '../infrastructure/config-manager'
12
+ import { isNotFoundError } from '../types/fs'
12
13
  import type { ContextPaths, ProjectContext, ContextState } from '../types'
13
14
 
14
15
  // Re-export types for convenience
@@ -113,10 +114,14 @@ class ContextBuilder {
113
114
  this._cache.delete(filePath)
114
115
  this._mtimes.delete(filePath)
115
116
  }
116
- } catch {
117
- // File doesn't exist - invalidate cache
118
- this._cache.delete(filePath)
119
- this._mtimes.delete(filePath)
117
+ } catch (error) {
118
+ // File doesn't exist or access error - invalidate cache
119
+ if (isNotFoundError(error)) {
120
+ this._cache.delete(filePath)
121
+ this._mtimes.delete(filePath)
122
+ } else {
123
+ throw error
124
+ }
120
125
  }
121
126
  }
122
127
  }
@@ -137,8 +142,11 @@ class ContextBuilder {
137
142
  try {
138
143
  const [content, stat] = await Promise.all([fs.readFile(filePath, 'utf-8'), fs.stat(filePath)])
139
144
  return { key, filePath, content, mtime: stat.mtimeMs }
140
- } catch {
141
- return { key, filePath, content: null, mtime: null }
145
+ } catch (error) {
146
+ if (isNotFoundError(error)) {
147
+ return { key, filePath, content: null, mtime: null }
148
+ }
149
+ throw error
142
150
  }
143
151
  })
144
152
 
@@ -227,8 +235,11 @@ class ContextBuilder {
227
235
  try {
228
236
  const content = await fs.readFile(filePath, 'utf-8')
229
237
  return { filePath, content }
230
- } catch {
231
- return { filePath, content: null }
238
+ } catch (error) {
239
+ if (isNotFoundError(error)) {
240
+ return { filePath, content: null }
241
+ }
242
+ throw error
232
243
  }
233
244
  })
234
245
 
@@ -264,8 +275,11 @@ class ContextBuilder {
264
275
  try {
265
276
  await fs.access(filePath)
266
277
  return true
267
- } catch {
268
- return false
278
+ } catch (error) {
279
+ if (isNotFoundError(error)) {
280
+ return false
281
+ }
282
+ throw error
269
283
  }
270
284
  }
271
285