sqlew 4.0.4 → 4.1.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 (203) hide show
  1. package/CHANGELOG.md +1805 -1762
  2. package/LICENSE +177 -39
  3. package/NOTICE +24 -0
  4. package/README.md +409 -390
  5. package/assets/claude-md-snippets/plan-mode-integration.md +17 -6
  6. package/assets/config.example.toml +282 -284
  7. package/assets/sample-agents/README.md +36 -40
  8. package/assets/sample-agents/sqlew-architect.md +321 -322
  9. package/assets/sample-agents/sqlew-researcher.md +292 -293
  10. package/assets/sample-agents/sqlew-scrum-master.md +286 -287
  11. package/assets/sample-commands/README.md +56 -57
  12. package/assets/sample-skills/sqlew-plan-guidance/SKILL.md +33 -26
  13. package/dist/cli/hooks/check-completion.d.ts +19 -0
  14. package/dist/cli/hooks/check-completion.d.ts.map +1 -0
  15. package/dist/cli/hooks/check-completion.js +104 -0
  16. package/dist/cli/hooks/check-completion.js.map +1 -0
  17. package/dist/cli/hooks/init-hooks.d.ts +35 -0
  18. package/dist/cli/hooks/init-hooks.d.ts.map +1 -0
  19. package/dist/cli/hooks/init-hooks.js +425 -0
  20. package/dist/cli/hooks/init-hooks.js.map +1 -0
  21. package/dist/cli/hooks/mark-done.d.ts +25 -0
  22. package/dist/cli/hooks/mark-done.d.ts.map +1 -0
  23. package/dist/cli/hooks/mark-done.js +128 -0
  24. package/dist/cli/hooks/mark-done.js.map +1 -0
  25. package/dist/cli/hooks/plan-id-utils.d.ts +83 -0
  26. package/dist/cli/hooks/plan-id-utils.d.ts.map +1 -0
  27. package/dist/cli/hooks/plan-id-utils.js +183 -0
  28. package/dist/cli/hooks/plan-id-utils.js.map +1 -0
  29. package/dist/cli/hooks/save.d.ts +23 -0
  30. package/dist/cli/hooks/save.d.ts.map +1 -0
  31. package/dist/cli/hooks/save.js +90 -0
  32. package/dist/cli/hooks/save.js.map +1 -0
  33. package/dist/cli/hooks/stdin-parser.d.ts +139 -0
  34. package/dist/cli/hooks/stdin-parser.d.ts.map +1 -0
  35. package/dist/cli/hooks/stdin-parser.js +127 -0
  36. package/dist/cli/hooks/stdin-parser.js.map +1 -0
  37. package/dist/cli/hooks/suggest.d.ts +19 -0
  38. package/dist/cli/hooks/suggest.d.ts.map +1 -0
  39. package/dist/cli/hooks/suggest.js +157 -0
  40. package/dist/cli/hooks/suggest.js.map +1 -0
  41. package/dist/cli/hooks/track-plan.d.ts +36 -0
  42. package/dist/cli/hooks/track-plan.d.ts.map +1 -0
  43. package/dist/cli/hooks/track-plan.js +152 -0
  44. package/dist/cli/hooks/track-plan.js.map +1 -0
  45. package/dist/cli.d.ts.map +1 -1
  46. package/dist/cli.js +56 -16
  47. package/dist/cli.js.map +1 -1
  48. package/dist/config/global-config.d.ts +187 -0
  49. package/dist/config/global-config.d.ts.map +1 -0
  50. package/dist/config/global-config.js +206 -0
  51. package/dist/config/global-config.js.map +1 -0
  52. package/dist/config/loader.d.ts +42 -0
  53. package/dist/config/loader.d.ts.map +1 -1
  54. package/dist/config/loader.js +96 -0
  55. package/dist/config/loader.js.map +1 -1
  56. package/dist/constants.d.ts +4 -0
  57. package/dist/constants.d.ts.map +1 -1
  58. package/dist/constants.js +10 -0
  59. package/dist/constants.js.map +1 -1
  60. package/dist/database/operations/queries.d.ts.map +1 -1
  61. package/dist/database/operations/queries.js +11 -2
  62. package/dist/database/operations/queries.js.map +1 -1
  63. package/dist/index.js +5 -2
  64. package/dist/index.js.map +1 -1
  65. package/dist/init-agents.js +0 -1
  66. package/dist/init-agents.js.map +1 -1
  67. package/dist/init-skills.d.ts +4 -3
  68. package/dist/init-skills.d.ts.map +1 -1
  69. package/dist/init-skills.js +10 -3
  70. package/dist/init-skills.js.map +1 -1
  71. package/dist/server/setup.d.ts +8 -0
  72. package/dist/server/setup.d.ts.map +1 -1
  73. package/dist/server/setup.js +141 -21
  74. package/dist/server/setup.js.map +1 -1
  75. package/dist/sync-agents.d.ts.map +1 -1
  76. package/dist/sync-agents.js +48 -3
  77. package/dist/sync-agents.js.map +1 -1
  78. package/dist/sync-commands.d.ts.map +1 -1
  79. package/dist/sync-commands.js +43 -3
  80. package/dist/sync-commands.js.map +1 -1
  81. package/dist/tools/constraints/actions/get.d.ts.map +1 -1
  82. package/dist/tools/constraints/actions/get.js +5 -8
  83. package/dist/tools/constraints/actions/get.js.map +1 -1
  84. package/dist/tools/constraints/help/help.d.ts.map +1 -1
  85. package/dist/tools/constraints/help/help.js +1 -6
  86. package/dist/tools/constraints/help/help.js.map +1 -1
  87. package/dist/tools/context/actions/get.d.ts.map +1 -1
  88. package/dist/tools/context/actions/get.js.map +1 -1
  89. package/dist/tools/context/actions/search-layer.d.ts.map +1 -1
  90. package/dist/tools/context/actions/search-layer.js +5 -3
  91. package/dist/tools/context/actions/search-layer.js.map +1 -1
  92. package/dist/tools/context/actions/set-from-policy.d.ts +2 -1
  93. package/dist/tools/context/actions/set-from-policy.d.ts.map +1 -1
  94. package/dist/tools/context/actions/set-from-policy.js.map +1 -1
  95. package/dist/tools/context/help/help.d.ts.map +1 -1
  96. package/dist/tools/context/help/help.js +1 -7
  97. package/dist/tools/context/help/help.js.map +1 -1
  98. package/dist/tools/context/internal/queries.d.ts.map +1 -1
  99. package/dist/tools/context/internal/queries.js +5 -2
  100. package/dist/tools/context/internal/queries.js.map +1 -1
  101. package/dist/tools/context/types.d.ts +1 -1
  102. package/dist/tools/context/types.d.ts.map +1 -1
  103. package/dist/tools/files/actions/get.d.ts.map +1 -1
  104. package/dist/tools/files/actions/get.js +4 -6
  105. package/dist/tools/files/actions/get.js.map +1 -1
  106. package/dist/tools/files/help/help.d.ts.map +1 -1
  107. package/dist/tools/files/help/help.js +1 -6
  108. package/dist/tools/files/help/help.js.map +1 -1
  109. package/dist/tools/suggest/help/constraint-help.d.ts.map +1 -1
  110. package/dist/tools/suggest/help/constraint-help.js +0 -2
  111. package/dist/tools/suggest/help/constraint-help.js.map +1 -1
  112. package/dist/tools/suggest/internal/constraint-queries.d.ts.map +1 -1
  113. package/dist/tools/suggest/internal/constraint-queries.js +12 -5
  114. package/dist/tools/suggest/internal/constraint-queries.js.map +1 -1
  115. package/dist/tools/suggest/internal/queries.js +2 -2
  116. package/dist/tools/suggest/internal/queries.js.map +1 -1
  117. package/dist/tools/tasks/help/help.d.ts.map +1 -1
  118. package/dist/tools/tasks/help/help.js +0 -6
  119. package/dist/tools/tasks/help/help.js.map +1 -1
  120. package/dist/tools/tasks/help/use-case.d.ts.map +1 -1
  121. package/dist/tools/tasks/help/use-case.js +0 -1
  122. package/dist/tools/tasks/help/use-case.js.map +1 -1
  123. package/dist/tools/tasks/watcher/status.d.ts.map +1 -1
  124. package/dist/tools/tasks/watcher/status.js +5 -1
  125. package/dist/tools/tasks/watcher/status.js.map +1 -1
  126. package/dist/types/decision/params.d.ts +7 -6
  127. package/dist/types/decision/params.d.ts.map +1 -1
  128. package/dist/types/decision/templates.d.ts +3 -2
  129. package/dist/types/decision/templates.d.ts.map +1 -1
  130. package/dist/types/view-entities.d.ts +2 -1
  131. package/dist/types/view-entities.d.ts.map +1 -1
  132. package/dist/types.d.ts +19 -11
  133. package/dist/types.d.ts.map +1 -1
  134. package/dist/types.js +4 -1
  135. package/dist/types.js.map +1 -1
  136. package/dist/utils/enum-converter.d.ts +72 -0
  137. package/dist/utils/enum-converter.d.ts.map +1 -0
  138. package/dist/utils/enum-converter.js +76 -0
  139. package/dist/utils/enum-converter.js.map +1 -0
  140. package/dist/utils/hook-queue.d.ts +81 -0
  141. package/dist/utils/hook-queue.d.ts.map +1 -0
  142. package/dist/utils/hook-queue.js +156 -0
  143. package/dist/utils/hook-queue.js.map +1 -0
  144. package/dist/utils/project-root.d.ts +9 -2
  145. package/dist/utils/project-root.d.ts.map +1 -1
  146. package/dist/utils/project-root.js +16 -2
  147. package/dist/utils/project-root.js.map +1 -1
  148. package/dist/utils/tag-parser.d.ts.map +1 -1
  149. package/dist/utils/tag-parser.js +6 -0
  150. package/dist/utils/tag-parser.js.map +1 -1
  151. package/dist/utils/validators.d.ts +1 -1
  152. package/dist/utils/validators.d.ts.map +1 -1
  153. package/dist/utils/validators.js +1 -1
  154. package/dist/utils/validators.js.map +1 -1
  155. package/dist/utils/vcs-adapter.d.ts +44 -0
  156. package/dist/utils/vcs-adapter.d.ts.map +1 -1
  157. package/dist/utils/vcs-adapter.js +88 -0
  158. package/dist/utils/vcs-adapter.js.map +1 -1
  159. package/dist/utils/view-queries.d.ts.map +1 -1
  160. package/dist/utils/view-queries.js +9 -19
  161. package/dist/utils/view-queries.js.map +1 -1
  162. package/dist/watcher/base-watcher.d.ts +69 -0
  163. package/dist/watcher/base-watcher.d.ts.map +1 -0
  164. package/dist/watcher/base-watcher.js +130 -0
  165. package/dist/watcher/base-watcher.js.map +1 -0
  166. package/dist/watcher/index.d.ts +3 -0
  167. package/dist/watcher/index.d.ts.map +1 -1
  168. package/dist/watcher/index.js +2 -0
  169. package/dist/watcher/index.js.map +1 -1
  170. package/dist/watcher/queue-watcher.d.ts +64 -0
  171. package/dist/watcher/queue-watcher.d.ts.map +1 -0
  172. package/dist/watcher/queue-watcher.js +187 -0
  173. package/dist/watcher/queue-watcher.js.map +1 -0
  174. package/docs/ADR_CONCEPTS.md +140 -0
  175. package/docs/CONFIGURATION.md +922 -925
  176. package/docs/CROSS_DATABASE.md +153 -0
  177. package/docs/DATABASE_AUTH.md +70 -356
  178. package/docs/HOOKS_GUIDE.md +159 -0
  179. package/docs/SLASH_COMMANDS.md +329 -337
  180. package/docs/TASK_SYSTEM_DEPRECATED.md +88 -0
  181. package/docs/changelogs/CHANGELOG_ARCHIVE_v3.4_and_older.md +293 -296
  182. package/docs/cli/DATA_EXPORT_IMPORT.md +699 -700
  183. package/docs/cli/README.md +276 -277
  184. package/package.json +123 -119
  185. package/docs/ACCEPTANCE_CRITERIA.md +0 -625
  186. package/docs/AI_AGENT_GUIDE.md +0 -198
  187. package/docs/ARCHITECTURE.md +0 -167
  188. package/docs/AUTO_FILE_TRACKING.md +0 -841
  189. package/docs/BATCH_VALIDATION.md +0 -617
  190. package/docs/BEST_PRACTICES.md +0 -168
  191. package/docs/CONSTRAINT_INTELLIGENCE.md +0 -339
  192. package/docs/DECISION_CONTEXT.md +0 -675
  193. package/docs/DECISION_INTELLIGENCE.md +0 -605
  194. package/docs/GIT_AWARE_AUTO_COMPLETE.md +0 -646
  195. package/docs/MIGRATION_GUIDE_V3.9.0.md +0 -371
  196. package/docs/SHARED_CONCEPTS.md +0 -225
  197. package/docs/SPECIALIZED_AGENTS.md +0 -126
  198. package/docs/TASK_ACTIONS.md +0 -1177
  199. package/docs/TASK_OVERVIEW.md +0 -452
  200. package/docs/TASK_PRUNING.md +0 -594
  201. package/docs/TOOL_REFERENCE.md +0 -1077
  202. package/docs/TOOL_SELECTION.md +0 -83
  203. package/docs/WORKFLOWS.md +0 -941
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Plan ID utilities for YAML frontmatter manipulation
3
+ *
4
+ * Handles reading and writing sqlew-plan-id in markdown files.
5
+ * Uses YAML frontmatter format (--- delimited section at top of file).
6
+ *
7
+ * @since v4.1.0
8
+ */
9
+ /**
10
+ * Parsed frontmatter data
11
+ */
12
+ export interface Frontmatter {
13
+ /** Raw frontmatter content (between --- delimiters) */
14
+ raw: string;
15
+ /** Parsed key-value pairs */
16
+ data: Record<string, string>;
17
+ /** Content after frontmatter */
18
+ content: string;
19
+ /** Whether the file had frontmatter */
20
+ hasFrontmatter: boolean;
21
+ }
22
+ /**
23
+ * Parse YAML frontmatter from markdown content
24
+ *
25
+ * @param content - Full file content
26
+ * @returns Parsed frontmatter and content
27
+ */
28
+ export declare function parseFrontmatter(content: string): Frontmatter;
29
+ /**
30
+ * Serialize frontmatter data back to string
31
+ *
32
+ * @param data - Key-value pairs to serialize
33
+ * @returns YAML frontmatter string (without delimiters)
34
+ */
35
+ export declare function serializeFrontmatter(data: Record<string, string>): string;
36
+ /**
37
+ * Build file content with frontmatter
38
+ *
39
+ * @param data - Frontmatter key-value pairs
40
+ * @param content - Main content after frontmatter
41
+ * @returns Complete file content
42
+ */
43
+ export declare function buildFileWithFrontmatter(data: Record<string, string>, content: string): string;
44
+ /**
45
+ * Get plan ID from a markdown file
46
+ *
47
+ * @param filePath - Path to markdown file
48
+ * @returns Plan ID or null if not found
49
+ */
50
+ export declare function getPlanId(filePath: string): string | null;
51
+ /**
52
+ * Set or add plan ID to a markdown file
53
+ *
54
+ * If the file has no frontmatter, adds one.
55
+ * If the file has frontmatter without plan ID, adds the ID.
56
+ * If the file already has a plan ID, does nothing.
57
+ *
58
+ * @param filePath - Path to markdown file
59
+ * @param planId - Plan ID to set (generates UUID if not provided)
60
+ * @returns The plan ID that was set or already existed
61
+ */
62
+ export declare function ensurePlanId(filePath: string, planId?: string): string;
63
+ /**
64
+ * Check if a file has a plan ID
65
+ *
66
+ * @param filePath - Path to markdown file
67
+ * @returns true if file has a plan ID
68
+ */
69
+ export declare function hasPlanId(filePath: string): boolean;
70
+ /**
71
+ * Generate a new plan ID (UUID v4)
72
+ *
73
+ * @returns New UUID
74
+ */
75
+ export declare function generatePlanId(): string;
76
+ /**
77
+ * Extract plan file name from a full path
78
+ *
79
+ * @param filePath - Full path to plan file
80
+ * @returns File name only (e.g., "rippling-spinning-eagle.md")
81
+ */
82
+ export declare function extractPlanFileName(filePath: string): string;
83
+ //# sourceMappingURL=plan-id-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-id-utils.d.ts","sourceRoot":"","sources":["../../../src/cli/hooks/plan-id-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAmBH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,cAAc,EAAE,OAAO,CAAC;CACzB;AAMD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAwD7D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAIzE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG9F;AAMD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CA6BtE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI5D"}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Plan ID utilities for YAML frontmatter manipulation
3
+ *
4
+ * Handles reading and writing sqlew-plan-id in markdown files.
5
+ * Uses YAML frontmatter format (--- delimited section at top of file).
6
+ *
7
+ * @since v4.1.0
8
+ */
9
+ import { readFileSync, writeFileSync, existsSync } from 'fs';
10
+ import { randomUUID } from 'crypto';
11
+ // ============================================================================
12
+ // Constants
13
+ // ============================================================================
14
+ /** YAML frontmatter delimiter */
15
+ const FRONTMATTER_DELIMITER = '---';
16
+ /** Key for plan ID in frontmatter */
17
+ const PLAN_ID_KEY = 'sqlew-plan-id';
18
+ // ============================================================================
19
+ // Parsing
20
+ // ============================================================================
21
+ /**
22
+ * Parse YAML frontmatter from markdown content
23
+ *
24
+ * @param content - Full file content
25
+ * @returns Parsed frontmatter and content
26
+ */
27
+ export function parseFrontmatter(content) {
28
+ const lines = content.split('\n');
29
+ // Check if file starts with ---
30
+ if (lines[0]?.trim() !== FRONTMATTER_DELIMITER) {
31
+ return {
32
+ raw: '',
33
+ data: {},
34
+ content,
35
+ hasFrontmatter: false,
36
+ };
37
+ }
38
+ // Find closing ---
39
+ let endIndex = -1;
40
+ for (let i = 1; i < lines.length; i++) {
41
+ if (lines[i]?.trim() === FRONTMATTER_DELIMITER) {
42
+ endIndex = i;
43
+ break;
44
+ }
45
+ }
46
+ if (endIndex === -1) {
47
+ // No closing delimiter - treat as no frontmatter
48
+ return {
49
+ raw: '',
50
+ data: {},
51
+ content,
52
+ hasFrontmatter: false,
53
+ };
54
+ }
55
+ // Extract frontmatter content
56
+ const frontmatterLines = lines.slice(1, endIndex);
57
+ const raw = frontmatterLines.join('\n');
58
+ const data = {};
59
+ // Parse simple key: value pairs
60
+ for (const line of frontmatterLines) {
61
+ const match = line.match(/^([^:]+):\s*(.*)$/);
62
+ if (match) {
63
+ const key = match[1].trim();
64
+ const value = match[2].trim();
65
+ data[key] = value;
66
+ }
67
+ }
68
+ // Extract content after frontmatter
69
+ const restContent = lines.slice(endIndex + 1).join('\n');
70
+ return {
71
+ raw,
72
+ data,
73
+ content: restContent,
74
+ hasFrontmatter: true,
75
+ };
76
+ }
77
+ /**
78
+ * Serialize frontmatter data back to string
79
+ *
80
+ * @param data - Key-value pairs to serialize
81
+ * @returns YAML frontmatter string (without delimiters)
82
+ */
83
+ export function serializeFrontmatter(data) {
84
+ return Object.entries(data)
85
+ .map(([key, value]) => `${key}: ${value}`)
86
+ .join('\n');
87
+ }
88
+ /**
89
+ * Build file content with frontmatter
90
+ *
91
+ * @param data - Frontmatter key-value pairs
92
+ * @param content - Main content after frontmatter
93
+ * @returns Complete file content
94
+ */
95
+ export function buildFileWithFrontmatter(data, content) {
96
+ const frontmatter = serializeFrontmatter(data);
97
+ return `${FRONTMATTER_DELIMITER}\n${frontmatter}\n${FRONTMATTER_DELIMITER}\n${content}`;
98
+ }
99
+ // ============================================================================
100
+ // Plan ID Operations
101
+ // ============================================================================
102
+ /**
103
+ * Get plan ID from a markdown file
104
+ *
105
+ * @param filePath - Path to markdown file
106
+ * @returns Plan ID or null if not found
107
+ */
108
+ export function getPlanId(filePath) {
109
+ if (!existsSync(filePath)) {
110
+ return null;
111
+ }
112
+ try {
113
+ const content = readFileSync(filePath, 'utf-8');
114
+ const frontmatter = parseFrontmatter(content);
115
+ return frontmatter.data[PLAN_ID_KEY] || null;
116
+ }
117
+ catch {
118
+ return null;
119
+ }
120
+ }
121
+ /**
122
+ * Set or add plan ID to a markdown file
123
+ *
124
+ * If the file has no frontmatter, adds one.
125
+ * If the file has frontmatter without plan ID, adds the ID.
126
+ * If the file already has a plan ID, does nothing.
127
+ *
128
+ * @param filePath - Path to markdown file
129
+ * @param planId - Plan ID to set (generates UUID if not provided)
130
+ * @returns The plan ID that was set or already existed
131
+ */
132
+ export function ensurePlanId(filePath, planId) {
133
+ if (!existsSync(filePath)) {
134
+ throw new Error(`File not found: ${filePath}`);
135
+ }
136
+ const content = readFileSync(filePath, 'utf-8');
137
+ const frontmatter = parseFrontmatter(content);
138
+ // If already has plan ID, return it
139
+ if (frontmatter.data[PLAN_ID_KEY]) {
140
+ return frontmatter.data[PLAN_ID_KEY];
141
+ }
142
+ // Generate new ID if not provided
143
+ const newPlanId = planId || randomUUID();
144
+ // Add plan ID to frontmatter data
145
+ const newData = {
146
+ [PLAN_ID_KEY]: newPlanId,
147
+ ...frontmatter.data,
148
+ };
149
+ // Build new file content
150
+ const newContent = buildFileWithFrontmatter(newData, frontmatter.content);
151
+ // Write back to file
152
+ writeFileSync(filePath, newContent, 'utf-8');
153
+ return newPlanId;
154
+ }
155
+ /**
156
+ * Check if a file has a plan ID
157
+ *
158
+ * @param filePath - Path to markdown file
159
+ * @returns true if file has a plan ID
160
+ */
161
+ export function hasPlanId(filePath) {
162
+ return getPlanId(filePath) !== null;
163
+ }
164
+ /**
165
+ * Generate a new plan ID (UUID v4)
166
+ *
167
+ * @returns New UUID
168
+ */
169
+ export function generatePlanId() {
170
+ return randomUUID();
171
+ }
172
+ /**
173
+ * Extract plan file name from a full path
174
+ *
175
+ * @param filePath - Full path to plan file
176
+ * @returns File name only (e.g., "rippling-spinning-eagle.md")
177
+ */
178
+ export function extractPlanFileName(filePath) {
179
+ const normalizedPath = filePath.replace(/\\/g, '/');
180
+ const parts = normalizedPath.split('/');
181
+ return parts[parts.length - 1] || '';
182
+ }
183
+ //# sourceMappingURL=plan-id-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-id-utils.js","sourceRoot":"","sources":["../../../src/cli/hooks/plan-id-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Save Hook Command
3
+ *
4
+ * PostToolUse hook for ExitPlanMode - enqueues decision status update.
5
+ * When plan mode exits, enqueues update from draft to in_progress.
6
+ * Actual DB operations happen when MCP server processes the queue.
7
+ *
8
+ * Usage:
9
+ * echo '{"tool_name": "ExitPlanMode"}' | sqlew save
10
+ *
11
+ * @since v4.1.0
12
+ * @updated v4.1.0 - Changed trigger from Edit|Write to ExitPlanMode only (zero delay on code edits)
13
+ * @updated v4.1.0 - File queue architecture (no DB operations in hooks)
14
+ */
15
+ /**
16
+ * Main save command entry point
17
+ *
18
+ * Called as PostToolUse hook when ExitPlanMode completes.
19
+ * Enqueues decision status update if a plan is being tracked.
20
+ * No DB operations - fast execution (<100ms).
21
+ */
22
+ export declare function saveCommand(): Promise<void>;
23
+ //# sourceMappingURL=save.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save.d.ts","sourceRoot":"","sources":["../../../src/cli/hooks/save.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAoBH;;;;;;GAMG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA+DjD"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Save Hook Command
3
+ *
4
+ * PostToolUse hook for ExitPlanMode - enqueues decision status update.
5
+ * When plan mode exits, enqueues update from draft to in_progress.
6
+ * Actual DB operations happen when MCP server processes the queue.
7
+ *
8
+ * Usage:
9
+ * echo '{"tool_name": "ExitPlanMode"}' | sqlew save
10
+ *
11
+ * @since v4.1.0
12
+ * @updated v4.1.0 - Changed trigger from Edit|Write to ExitPlanMode only (zero delay on code edits)
13
+ * @updated v4.1.0 - File queue architecture (no DB operations in hooks)
14
+ */
15
+ import { readStdinJson, sendContinue, getProjectPath } from './stdin-parser.js';
16
+ import { loadCurrentPlan, saveCurrentPlan } from '../../config/global-config.js';
17
+ import { enqueueDecisionUpdate } from '../../utils/hook-queue.js';
18
+ // ============================================================================
19
+ // Constants
20
+ // ============================================================================
21
+ /** Decision key prefix for plan-based decisions */
22
+ const PLAN_DECISION_PREFIX = 'plan/implementation';
23
+ /** Status for in-progress decisions */
24
+ const IN_PROGRESS_STATUS = 'in_progress';
25
+ // ============================================================================
26
+ // Main Entry Point
27
+ // ============================================================================
28
+ /**
29
+ * Main save command entry point
30
+ *
31
+ * Called as PostToolUse hook when ExitPlanMode completes.
32
+ * Enqueues decision status update if a plan is being tracked.
33
+ * No DB operations - fast execution (<100ms).
34
+ */
35
+ export async function saveCommand() {
36
+ try {
37
+ const input = await readStdinJson();
38
+ // Only process ExitPlanMode tool
39
+ const toolName = input.tool_name;
40
+ if (toolName !== 'ExitPlanMode') {
41
+ sendContinue();
42
+ return;
43
+ }
44
+ const projectPath = getProjectPath(input);
45
+ if (!projectPath) {
46
+ sendContinue();
47
+ return;
48
+ }
49
+ // Check if there's a current plan being tracked
50
+ const planInfo = loadCurrentPlan(projectPath);
51
+ if (!planInfo) {
52
+ // No plan being tracked - continue without action
53
+ sendContinue();
54
+ return;
55
+ }
56
+ // Check if already recorded for this plan
57
+ if (planInfo.recorded) {
58
+ // Already recorded - no need to record again
59
+ sendContinue();
60
+ return;
61
+ }
62
+ // Build decision key from plan file name
63
+ const planName = planInfo.plan_file.replace(/\.md$/, '');
64
+ const decisionKey = `${PLAN_DECISION_PREFIX}/${planName}`;
65
+ // Enqueue status update (no DB operations here)
66
+ enqueueDecisionUpdate(projectPath, {
67
+ key: decisionKey,
68
+ value: `Implementation in progress for plan: ${planInfo.plan_file}`,
69
+ status: IN_PROGRESS_STATUS,
70
+ layer: 'cross-cutting',
71
+ tags: ['plan', 'implementation', 'active', planInfo.plan_id.slice(0, 8)],
72
+ });
73
+ // Mark plan as recorded
74
+ const updatedInfo = {
75
+ ...planInfo,
76
+ recorded: true,
77
+ decision_pending: false,
78
+ plan_updated_at: new Date().toISOString(),
79
+ };
80
+ saveCurrentPlan(projectPath, updatedInfo);
81
+ sendContinue(`[sqlew] Queued decision update for plan: ${planInfo.plan_file} (will process on MCP startup)`);
82
+ }
83
+ catch (error) {
84
+ // On error, log to stderr but continue execution
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ console.error(`[sqlew save] Error: ${message}`);
87
+ sendContinue();
88
+ }
89
+ }
90
+ //# sourceMappingURL=save.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save.js","sourceRoot":"","sources":["../../../src/cli/hooks/save.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,eAAe,EAAwB,MAAM,+BAA+B,CAAC;AACvG,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,mDAAmD;AACnD,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAEnD,uCAAuC;AACvC,MAAM,kBAAkB,GAAG,aAAsB,CAAC;AAElD,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,aAAa,EAAE,CAAC;QAEpC,iCAAiC;QACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC;QACjC,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;YAChC,YAAY,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,YAAY,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QAED,gDAAgD;QAChD,MAAM,QAAQ,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,kDAAkD;YAClD,YAAY,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QAED,0CAA0C;QAC1C,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,6CAA6C;YAC7C,YAAY,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QAED,yCAAyC;QACzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACzD,MAAM,WAAW,GAAG,GAAG,oBAAoB,IAAI,QAAQ,EAAE,CAAC;QAE1D,gDAAgD;QAChD,qBAAqB,CAAC,WAAW,EAAE;YACjC,GAAG,EAAE,WAAW;YAChB,KAAK,EAAE,wCAAwC,QAAQ,CAAC,SAAS,EAAE;YACnE,MAAM,EAAE,kBAAkB;YAC1B,KAAK,EAAE,eAAe;YACtB,IAAI,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACzE,CAAC,CAAC;QAEH,wBAAwB;QACxB,MAAM,WAAW,GAAoB;YACnC,GAAG,QAAQ;YACX,QAAQ,EAAE,IAAI;YACd,gBAAgB,EAAE,KAAK;YACvB,eAAe,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAC1C,CAAC;QACF,eAAe,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAE1C,YAAY,CACV,4CAA4C,QAAQ,CAAC,SAAS,gCAAgC,CAC/F,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iDAAiD;QACjD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,uBAAuB,OAAO,EAAE,CAAC,CAAC;QAChD,YAAY,EAAE,CAAC;IACjB,CAAC;AACH,CAAC"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Claude Code Hooks stdin parser
3
+ *
4
+ * Parses JSON input from Claude Code Hooks.
5
+ * Hooks receive data via stdin in JSON format.
6
+ *
7
+ * @since v4.1.0
8
+ */
9
+ /**
10
+ * Tool input for various Claude Code tools
11
+ */
12
+ export interface ToolInput {
13
+ /** File path (Edit, Write tools) */
14
+ file_path?: string;
15
+ /** Command (Bash tool) */
16
+ command?: string;
17
+ /** Description (Task tool) */
18
+ description?: string;
19
+ /** Prompt (Task tool) */
20
+ prompt?: string;
21
+ /** Subagent type (Task tool) */
22
+ subagent_type?: string;
23
+ /** Todos (TodoWrite tool) */
24
+ todos?: TodoItem[];
25
+ /** Generic key-value pairs */
26
+ [key: string]: unknown;
27
+ }
28
+ /**
29
+ * Todo item from TodoWrite tool
30
+ */
31
+ export interface TodoItem {
32
+ /** Todo content */
33
+ content: string;
34
+ /** Todo status: pending, in_progress, completed */
35
+ status: 'pending' | 'in_progress' | 'completed';
36
+ /** Active form description */
37
+ activeForm: string;
38
+ }
39
+ /**
40
+ * Tool response from PostToolUse
41
+ */
42
+ export interface ToolResponse {
43
+ /** Whether the tool completed successfully */
44
+ completed?: boolean;
45
+ /** Summary of what was done */
46
+ summary?: string;
47
+ /** Output content */
48
+ output?: string;
49
+ /** Generic key-value pairs */
50
+ [key: string]: unknown;
51
+ }
52
+ /**
53
+ * Hook input from Claude Code
54
+ */
55
+ export interface HookInput {
56
+ /** Session ID (changes on resume) */
57
+ session_id?: string;
58
+ /** Current working directory */
59
+ cwd?: string;
60
+ /** Hook event name */
61
+ hook_event_name?: 'PreToolUse' | 'PostToolUse' | 'SessionStart' | 'SessionEnd' | 'Stop' | 'SubagentStop';
62
+ /** Tool name being called */
63
+ tool_name?: string;
64
+ /** Tool input parameters */
65
+ tool_input?: ToolInput;
66
+ /** Tool response (PostToolUse only) */
67
+ tool_response?: ToolResponse;
68
+ /** Transcript path */
69
+ transcript_path?: string;
70
+ /** Permission mode */
71
+ permission_mode?: string;
72
+ }
73
+ /**
74
+ * Hook output to Claude Code
75
+ */
76
+ export interface HookOutput {
77
+ /** Whether to continue execution */
78
+ continue?: boolean;
79
+ /** Reason for stopping (if continue=false) */
80
+ stopReason?: string;
81
+ /** Additional context to inject */
82
+ additionalContext?: string;
83
+ /** System message to add */
84
+ systemMessage?: string;
85
+ /** Whether to suppress output */
86
+ suppressOutput?: boolean;
87
+ }
88
+ /**
89
+ * Read and parse JSON from stdin
90
+ *
91
+ * Claude Code Hooks send data via stdin in JSON format.
92
+ * This function reads all stdin and parses it as JSON.
93
+ *
94
+ * @returns Parsed hook input
95
+ * @throws Error if stdin is empty or invalid JSON
96
+ */
97
+ export declare function readStdinJson(): Promise<HookInput>;
98
+ /**
99
+ * Write hook output to stdout
100
+ *
101
+ * @param output - Hook output to send
102
+ */
103
+ export declare function writeHookOutput(output: HookOutput): void;
104
+ /**
105
+ * Send a continue response
106
+ *
107
+ * @param additionalContext - Optional context to inject
108
+ * @param systemMessage - Optional system message
109
+ */
110
+ export declare function sendContinue(additionalContext?: string, systemMessage?: string): void;
111
+ /**
112
+ * Send a block response (exit code 2)
113
+ *
114
+ * @param reason - Reason for blocking
115
+ */
116
+ export declare function sendBlock(reason: string): void;
117
+ /**
118
+ * Check if the hook input is for a plan file
119
+ *
120
+ * @param input - Hook input
121
+ * @returns true if the tool is operating on a plan file
122
+ */
123
+ export declare function isPlanFile(input: HookInput): boolean;
124
+ /**
125
+ * Check if all todos are completed
126
+ *
127
+ * @param input - Hook input
128
+ * @returns true if all todos have status "completed"
129
+ */
130
+ export declare function areAllTodosCompleted(input: HookInput): boolean;
131
+ /**
132
+ * Get project path from hook input
133
+ * Uses cwd from input or falls back to CLAUDE_PROJECT_DIR
134
+ *
135
+ * @param input - Hook input
136
+ * @returns Project path or undefined
137
+ */
138
+ export declare function getProjectPath(input: HookInput): string | undefined;
139
+ //# sourceMappingURL=stdin-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdin-parser.d.ts","sourceRoot":"","sources":["../../../src/cli/hooks/stdin-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,8BAA8B;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,eAAe,CAAC,EAAE,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,YAAY,GAAG,MAAM,GAAG,cAAc,CAAC;IACzG,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,uCAAuC;IACvC,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,sBAAsB;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4BAA4B;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAMD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,SAAS,CAAC,CAoCxD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CASrF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAG9C;AAMD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CASpD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAO9D;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAEnE"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Claude Code Hooks stdin parser
3
+ *
4
+ * Parses JSON input from Claude Code Hooks.
5
+ * Hooks receive data via stdin in JSON format.
6
+ *
7
+ * @since v4.1.0
8
+ */
9
+ // ============================================================================
10
+ // Parsing
11
+ // ============================================================================
12
+ /**
13
+ * Read and parse JSON from stdin
14
+ *
15
+ * Claude Code Hooks send data via stdin in JSON format.
16
+ * This function reads all stdin and parses it as JSON.
17
+ *
18
+ * @returns Parsed hook input
19
+ * @throws Error if stdin is empty or invalid JSON
20
+ */
21
+ export async function readStdinJson() {
22
+ return new Promise((resolve, reject) => {
23
+ let data = '';
24
+ // Set encoding for text input
25
+ process.stdin.setEncoding('utf8');
26
+ // Read all data from stdin
27
+ process.stdin.on('data', (chunk) => {
28
+ data += chunk;
29
+ });
30
+ // Parse when stdin closes
31
+ process.stdin.on('end', () => {
32
+ if (!data.trim()) {
33
+ // Empty stdin - return empty object
34
+ resolve({});
35
+ return;
36
+ }
37
+ try {
38
+ const parsed = JSON.parse(data);
39
+ resolve(parsed);
40
+ }
41
+ catch (error) {
42
+ reject(new Error(`Invalid JSON input: ${error instanceof Error ? error.message : String(error)}`));
43
+ }
44
+ });
45
+ // Handle errors
46
+ process.stdin.on('error', (error) => {
47
+ reject(new Error(`Failed to read stdin: ${error.message}`));
48
+ });
49
+ // Resume stdin (it might be paused)
50
+ process.stdin.resume();
51
+ });
52
+ }
53
+ /**
54
+ * Write hook output to stdout
55
+ *
56
+ * @param output - Hook output to send
57
+ */
58
+ export function writeHookOutput(output) {
59
+ console.log(JSON.stringify(output));
60
+ }
61
+ /**
62
+ * Send a continue response
63
+ *
64
+ * @param additionalContext - Optional context to inject
65
+ * @param systemMessage - Optional system message
66
+ */
67
+ export function sendContinue(additionalContext, systemMessage) {
68
+ const output = { continue: true };
69
+ if (additionalContext) {
70
+ output.additionalContext = additionalContext;
71
+ }
72
+ if (systemMessage) {
73
+ output.systemMessage = systemMessage;
74
+ }
75
+ writeHookOutput(output);
76
+ }
77
+ /**
78
+ * Send a block response (exit code 2)
79
+ *
80
+ * @param reason - Reason for blocking
81
+ */
82
+ export function sendBlock(reason) {
83
+ console.error(reason);
84
+ process.exit(2);
85
+ }
86
+ // ============================================================================
87
+ // Helpers
88
+ // ============================================================================
89
+ /**
90
+ * Check if the hook input is for a plan file
91
+ *
92
+ * @param input - Hook input
93
+ * @returns true if the tool is operating on a plan file
94
+ */
95
+ export function isPlanFile(input) {
96
+ const filePath = input.tool_input?.file_path;
97
+ if (!filePath) {
98
+ return false;
99
+ }
100
+ // Check if the path matches .claude/plans/*.md pattern
101
+ const normalizedPath = filePath.replace(/\\/g, '/');
102
+ return /\.claude\/plans\/[^/]+\.md$/.test(normalizedPath);
103
+ }
104
+ /**
105
+ * Check if all todos are completed
106
+ *
107
+ * @param input - Hook input
108
+ * @returns true if all todos have status "completed"
109
+ */
110
+ export function areAllTodosCompleted(input) {
111
+ const todos = input.tool_input?.todos;
112
+ if (!todos || !Array.isArray(todos) || todos.length === 0) {
113
+ return false;
114
+ }
115
+ return todos.every((todo) => todo.status === 'completed');
116
+ }
117
+ /**
118
+ * Get project path from hook input
119
+ * Uses cwd from input or falls back to CLAUDE_PROJECT_DIR
120
+ *
121
+ * @param input - Hook input
122
+ * @returns Project path or undefined
123
+ */
124
+ export function getProjectPath(input) {
125
+ return input.cwd || process.env.CLAUDE_PROJECT_DIR;
126
+ }
127
+ //# sourceMappingURL=stdin-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdin-parser.js","sourceRoot":"","sources":["../../../src/cli/hooks/stdin-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA0FH,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,IAAI,GAAG,EAAE,CAAC;QAEd,8BAA8B;QAC9B,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAElC,2BAA2B;QAC3B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACzC,IAAI,IAAI,KAAK,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,0BAA0B;QAC1B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACjB,oCAAoC;gBACpC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACZ,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAc,CAAC;gBAC7C,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YACrG,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,gBAAgB;QAChB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAClC,MAAM,CAAC,IAAI,KAAK,CAAC,yBAAyB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,oCAAoC;QACpC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAkB;IAChD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,iBAA0B,EAAE,aAAsB;IAC7E,MAAM,MAAM,GAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC9C,IAAI,iBAAiB,EAAE,CAAC;QACtB,MAAM,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;IAC/C,CAAC;IACD,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,CAAC,aAAa,GAAG,aAAa,CAAC;IACvC,CAAC;IACD,eAAe,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAgB;IACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,EAAE,SAAS,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,uDAAuD;IACvD,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,6BAA6B,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAgB;IACnD,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC;IACtC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,KAAgB;IAC7C,OAAO,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AACrD,CAAC"}