@assistkick/create 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/dist/bin/create.d.ts +2 -0
  2. package/dist/bin/create.js +25 -0
  3. package/dist/bin/create.js.map +1 -0
  4. package/dist/src/scaffolder.d.ts +22 -0
  5. package/dist/src/scaffolder.js +120 -0
  6. package/dist/src/scaffolder.js.map +1 -0
  7. package/package.json +24 -0
  8. package/templates/product-system/.env.example +8 -0
  9. package/templates/product-system/CLAUDE.md +45 -0
  10. package/templates/product-system/package.json +32 -0
  11. package/templates/product-system/packages/backend/package.json +37 -0
  12. package/templates/product-system/packages/backend/src/middleware/auth_middleware.test.ts +86 -0
  13. package/templates/product-system/packages/backend/src/middleware/auth_middleware.ts +35 -0
  14. package/templates/product-system/packages/backend/src/routes/auth.ts +463 -0
  15. package/templates/product-system/packages/backend/src/routes/coherence.ts +187 -0
  16. package/templates/product-system/packages/backend/src/routes/graph.ts +67 -0
  17. package/templates/product-system/packages/backend/src/routes/kanban.ts +201 -0
  18. package/templates/product-system/packages/backend/src/routes/pipeline.ts +41 -0
  19. package/templates/product-system/packages/backend/src/routes/projects.ts +122 -0
  20. package/templates/product-system/packages/backend/src/routes/users.ts +97 -0
  21. package/templates/product-system/packages/backend/src/server.ts +159 -0
  22. package/templates/product-system/packages/backend/src/services/auth_service.test.ts +115 -0
  23. package/templates/product-system/packages/backend/src/services/auth_service.ts +82 -0
  24. package/templates/product-system/packages/backend/src/services/coherence-review.ts +339 -0
  25. package/templates/product-system/packages/backend/src/services/email_service.ts +75 -0
  26. package/templates/product-system/packages/backend/src/services/init.ts +80 -0
  27. package/templates/product-system/packages/backend/src/services/invitation_service.test.ts +235 -0
  28. package/templates/product-system/packages/backend/src/services/invitation_service.ts +193 -0
  29. package/templates/product-system/packages/backend/src/services/password_reset_service.test.ts +151 -0
  30. package/templates/product-system/packages/backend/src/services/password_reset_service.ts +135 -0
  31. package/templates/product-system/packages/backend/src/services/project_service.test.ts +215 -0
  32. package/templates/product-system/packages/backend/src/services/project_service.ts +171 -0
  33. package/templates/product-system/packages/backend/src/services/pty_session_manager.test.ts +88 -0
  34. package/templates/product-system/packages/backend/src/services/pty_session_manager.ts +279 -0
  35. package/templates/product-system/packages/backend/src/services/terminal_ws_handler.ts +133 -0
  36. package/templates/product-system/packages/backend/src/services/user_management_service.test.ts +158 -0
  37. package/templates/product-system/packages/backend/src/services/user_management_service.ts +128 -0
  38. package/templates/product-system/packages/backend/tsconfig.json +22 -0
  39. package/templates/product-system/packages/frontend/index.html +13 -0
  40. package/templates/product-system/packages/frontend/package-lock.json +2666 -0
  41. package/templates/product-system/packages/frontend/package.json +30 -0
  42. package/templates/product-system/packages/frontend/public/favicon.svg +16 -0
  43. package/templates/product-system/packages/frontend/src/App.tsx +29 -0
  44. package/templates/product-system/packages/frontend/src/api/client.ts +386 -0
  45. package/templates/product-system/packages/frontend/src/api/client_projects.test.ts +104 -0
  46. package/templates/product-system/packages/frontend/src/api/client_refresh.test.ts +145 -0
  47. package/templates/product-system/packages/frontend/src/components/CoherenceView.tsx +414 -0
  48. package/templates/product-system/packages/frontend/src/components/GraphLegend.tsx +124 -0
  49. package/templates/product-system/packages/frontend/src/components/GraphSettings.tsx +112 -0
  50. package/templates/product-system/packages/frontend/src/components/GraphView.tsx +370 -0
  51. package/templates/product-system/packages/frontend/src/components/InviteUserDialog.tsx +85 -0
  52. package/templates/product-system/packages/frontend/src/components/KanbanView.tsx +470 -0
  53. package/templates/product-system/packages/frontend/src/components/LoginPage.tsx +116 -0
  54. package/templates/product-system/packages/frontend/src/components/ProjectSelector.tsx +187 -0
  55. package/templates/product-system/packages/frontend/src/components/QaIssueSheet.tsx +192 -0
  56. package/templates/product-system/packages/frontend/src/components/SidePanel.tsx +231 -0
  57. package/templates/product-system/packages/frontend/src/components/TerminalView.tsx +200 -0
  58. package/templates/product-system/packages/frontend/src/components/Toolbar.tsx +84 -0
  59. package/templates/product-system/packages/frontend/src/components/UsersView.tsx +249 -0
  60. package/templates/product-system/packages/frontend/src/constants/graph.ts +191 -0
  61. package/templates/product-system/packages/frontend/src/hooks/useAuth.tsx +54 -0
  62. package/templates/product-system/packages/frontend/src/hooks/useGraph.ts +27 -0
  63. package/templates/product-system/packages/frontend/src/hooks/useKanban.ts +21 -0
  64. package/templates/product-system/packages/frontend/src/hooks/useProjects.ts +86 -0
  65. package/templates/product-system/packages/frontend/src/hooks/useTheme.ts +26 -0
  66. package/templates/product-system/packages/frontend/src/hooks/useToast.tsx +62 -0
  67. package/templates/product-system/packages/frontend/src/hooks/use_projects_logic.test.ts +61 -0
  68. package/templates/product-system/packages/frontend/src/main.tsx +12 -0
  69. package/templates/product-system/packages/frontend/src/pages/accept_invitation_page.tsx +167 -0
  70. package/templates/product-system/packages/frontend/src/pages/forgot_password_page.tsx +100 -0
  71. package/templates/product-system/packages/frontend/src/pages/register_page.tsx +137 -0
  72. package/templates/product-system/packages/frontend/src/pages/reset_password_page.tsx +146 -0
  73. package/templates/product-system/packages/frontend/src/routes/ProtectedRoute.tsx +12 -0
  74. package/templates/product-system/packages/frontend/src/routes/accept_invitation.tsx +14 -0
  75. package/templates/product-system/packages/frontend/src/routes/dashboard.tsx +221 -0
  76. package/templates/product-system/packages/frontend/src/routes/forgot_password.tsx +13 -0
  77. package/templates/product-system/packages/frontend/src/routes/login.tsx +14 -0
  78. package/templates/product-system/packages/frontend/src/routes/register.tsx +14 -0
  79. package/templates/product-system/packages/frontend/src/routes/reset_password.tsx +13 -0
  80. package/templates/product-system/packages/frontend/src/styles/index.css +3358 -0
  81. package/templates/product-system/packages/frontend/src/utils/auth_validation.test.ts +51 -0
  82. package/templates/product-system/packages/frontend/src/utils/auth_validation.ts +19 -0
  83. package/templates/product-system/packages/frontend/src/utils/login_validation.test.ts +61 -0
  84. package/templates/product-system/packages/frontend/src/utils/login_validation.ts +24 -0
  85. package/templates/product-system/packages/frontend/src/utils/logout.test.ts +63 -0
  86. package/templates/product-system/packages/frontend/src/utils/node_sizing.test.ts +62 -0
  87. package/templates/product-system/packages/frontend/src/utils/node_sizing.ts +24 -0
  88. package/templates/product-system/packages/frontend/src/utils/task_status.test.ts +53 -0
  89. package/templates/product-system/packages/frontend/src/utils/task_status.ts +14 -0
  90. package/templates/product-system/packages/frontend/tsconfig.json +21 -0
  91. package/templates/product-system/packages/frontend/vite.config.ts +20 -0
  92. package/templates/product-system/packages/shared/.env.example +3 -0
  93. package/templates/product-system/packages/shared/README.md +1 -0
  94. package/templates/product-system/packages/shared/db/migrate.ts +32 -0
  95. package/templates/product-system/packages/shared/db/migrations/0000_dashing_gorgon.sql +128 -0
  96. package/templates/product-system/packages/shared/db/migrations/meta/0000_snapshot.json +819 -0
  97. package/templates/product-system/packages/shared/db/migrations/meta/_journal.json +13 -0
  98. package/templates/product-system/packages/shared/db/schema.ts +137 -0
  99. package/templates/product-system/packages/shared/drizzle.config.js +14 -0
  100. package/templates/product-system/packages/shared/lib/claude-service.ts +215 -0
  101. package/templates/product-system/packages/shared/lib/coherence.ts +278 -0
  102. package/templates/product-system/packages/shared/lib/completeness.ts +30 -0
  103. package/templates/product-system/packages/shared/lib/constants.ts +327 -0
  104. package/templates/product-system/packages/shared/lib/db.ts +81 -0
  105. package/templates/product-system/packages/shared/lib/git_workflow.ts +110 -0
  106. package/templates/product-system/packages/shared/lib/graph.ts +186 -0
  107. package/templates/product-system/packages/shared/lib/kanban.ts +161 -0
  108. package/templates/product-system/packages/shared/lib/markdown.ts +205 -0
  109. package/templates/product-system/packages/shared/lib/pipeline-state-store.ts +124 -0
  110. package/templates/product-system/packages/shared/lib/pipeline.ts +489 -0
  111. package/templates/product-system/packages/shared/lib/prompt_builder.ts +170 -0
  112. package/templates/product-system/packages/shared/lib/relevance_search.ts +159 -0
  113. package/templates/product-system/packages/shared/lib/session.ts +152 -0
  114. package/templates/product-system/packages/shared/lib/validator.ts +117 -0
  115. package/templates/product-system/packages/shared/lib/work_summary_parser.ts +130 -0
  116. package/templates/product-system/packages/shared/package.json +30 -0
  117. package/templates/product-system/packages/shared/scripts/assign-project.ts +52 -0
  118. package/templates/product-system/packages/shared/tools/add_edge.ts +61 -0
  119. package/templates/product-system/packages/shared/tools/add_node.ts +101 -0
  120. package/templates/product-system/packages/shared/tools/end_session.ts +87 -0
  121. package/templates/product-system/packages/shared/tools/get_gaps.ts +87 -0
  122. package/templates/product-system/packages/shared/tools/get_kanban.ts +125 -0
  123. package/templates/product-system/packages/shared/tools/get_node.ts +78 -0
  124. package/templates/product-system/packages/shared/tools/get_status.ts +98 -0
  125. package/templates/product-system/packages/shared/tools/migrate_to_turso.ts +385 -0
  126. package/templates/product-system/packages/shared/tools/move_card.ts +143 -0
  127. package/templates/product-system/packages/shared/tools/rebuild_index.ts +77 -0
  128. package/templates/product-system/packages/shared/tools/remove_edge.ts +59 -0
  129. package/templates/product-system/packages/shared/tools/remove_node.ts +96 -0
  130. package/templates/product-system/packages/shared/tools/resolve_question.ts +75 -0
  131. package/templates/product-system/packages/shared/tools/search_nodes.ts +106 -0
  132. package/templates/product-system/packages/shared/tools/start_session.ts +144 -0
  133. package/templates/product-system/packages/shared/tools/update_node.ts +133 -0
  134. package/templates/product-system/packages/shared/tsconfig.json +24 -0
  135. package/templates/product-system/pnpm-workspace.yaml +2 -0
  136. package/templates/product-system/smoke_test.ts +219 -0
  137. package/templates/product-system/tests/coherence_review.test.ts +562 -0
  138. package/templates/product-system/tests/db_sqlite_fallback.test.ts +75 -0
  139. package/templates/product-system/tests/edge_type_color_coding.test.ts +147 -0
  140. package/templates/product-system/tests/emit-tool-use-events.test.ts +85 -0
  141. package/templates/product-system/tests/feature_kind.test.ts +139 -0
  142. package/templates/product-system/tests/gap_indicators.test.ts +199 -0
  143. package/templates/product-system/tests/graceful_init.test.ts +142 -0
  144. package/templates/product-system/tests/graph_legend.test.ts +314 -0
  145. package/templates/product-system/tests/graph_settings_sheet.test.ts +804 -0
  146. package/templates/product-system/tests/hide_defined_filter.test.ts +205 -0
  147. package/templates/product-system/tests/kanban.test.ts +529 -0
  148. package/templates/product-system/tests/neighborhood_focus.test.ts +132 -0
  149. package/templates/product-system/tests/node_search.test.ts +340 -0
  150. package/templates/product-system/tests/node_sizing.test.ts +170 -0
  151. package/templates/product-system/tests/node_type_toggle_filters.test.ts +285 -0
  152. package/templates/product-system/tests/node_type_visual_encoding.test.ts +103 -0
  153. package/templates/product-system/tests/pipeline-state-store.test.ts +268 -0
  154. package/templates/product-system/tests/pipeline-unit.test.ts +593 -0
  155. package/templates/product-system/tests/pipeline.test.ts +195 -0
  156. package/templates/product-system/tests/pipeline_stats_all_cards.test.ts +193 -0
  157. package/templates/product-system/tests/play_all.test.ts +296 -0
  158. package/templates/product-system/tests/qa_issue_sheet.test.ts +464 -0
  159. package/templates/product-system/tests/relevance_search.test.ts +186 -0
  160. package/templates/product-system/tests/search_reorder.test.ts +88 -0
  161. package/templates/product-system/tests/serve_ui.test.ts +281 -0
  162. package/templates/product-system/tests/serve_ui_drizzle.test.ts +114 -0
  163. package/templates/product-system/tests/session_context_recall.test.ts +135 -0
  164. package/templates/product-system/tests/side_panel.test.ts +345 -0
  165. package/templates/product-system/tests/spec_completeness_label.test.ts +69 -0
  166. package/templates/product-system/tests/url_routing_test.ts +122 -0
  167. package/templates/product-system/tests/user_login.test.ts +150 -0
  168. package/templates/product-system/tests/user_registration.test.ts +205 -0
  169. package/templates/product-system/tests/web_terminal.test.ts +572 -0
  170. package/templates/product-system/tests/work_summary.test.ts +211 -0
  171. package/templates/product-system/tests/zoom_pan.test.ts +43 -0
  172. package/templates/product-system/tsconfig.json +24 -0
  173. package/templates/skills/product-bootstrap/SKILL.md +312 -0
  174. package/templates/skills/product-code-reviewer/SKILL.md +147 -0
  175. package/templates/skills/product-debugger/SKILL.md +206 -0
  176. package/templates/skills/product-debugger/references/agent-browser.md +1156 -0
  177. package/templates/skills/product-developer/SKILL.md +182 -0
  178. package/templates/skills/product-interview/SKILL.md +220 -0
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Tests for WorkSummaryParser — parsing structured work summaries from
3
+ * developer Claude output and git diff --name-status.
4
+ * Uses node:test built-in runner per nfr_001.
5
+ */
6
+ import { describe, it } from 'node:test';
7
+ import assert from 'node:assert/strict';
8
+ import { WorkSummaryParser } from '../packages/shared/lib/work_summary_parser.js';
9
+
10
+ describe('WorkSummaryParser', () => {
11
+ describe('parseFromOutput', () => {
12
+ it('extracts approach and decisions from well-formed output', () => {
13
+ const parser = new WorkSummaryParser();
14
+ const output = `
15
+ Some implementation text here...
16
+
17
+ ## Work Summary
18
+ ### Approach
19
+ I added a new column to the database and updated the pipeline to capture developer output after each cycle. The work summary is parsed from a structured block in the Claude output.
20
+ ### Decisions
21
+ - Used a JSON column instead of a separate table for simplicity
22
+ - Chose to capture git diff --name-status rather than full diff to keep data small
23
+ - Made the work summary section collapsible in the UI
24
+ `;
25
+
26
+ const result = parser.parseFromOutput(output);
27
+
28
+ assert.ok(result.approach.includes('added a new column'));
29
+ assert.equal(result.decisions.length, 3);
30
+ assert.ok(result.decisions[0].includes('JSON column'));
31
+ assert.ok(result.decisions[1].includes('git diff'));
32
+ assert.ok(result.decisions[2].includes('collapsible'));
33
+ });
34
+
35
+ it('returns empty values when no work summary block exists', () => {
36
+ const parser = new WorkSummaryParser();
37
+ const output = 'Just some regular output without a work summary.';
38
+
39
+ const result = parser.parseFromOutput(output);
40
+
41
+ assert.equal(result.approach, '');
42
+ assert.deepEqual(result.decisions, []);
43
+ });
44
+
45
+ it('handles approach without decisions', () => {
46
+ const parser = new WorkSummaryParser();
47
+ const output = `
48
+ ## Work Summary
49
+ ### Approach
50
+ Simple implementation with minimal changes.
51
+ `;
52
+
53
+ const result = parser.parseFromOutput(output);
54
+
55
+ assert.ok(result.approach.includes('Simple implementation'));
56
+ assert.deepEqual(result.decisions, []);
57
+ });
58
+
59
+ it('handles decisions with asterisk bullets', () => {
60
+ const parser = new WorkSummaryParser();
61
+ const output = `
62
+ ## Work Summary
63
+ ### Approach
64
+ Did the thing.
65
+ ### Decisions
66
+ * Decision one
67
+ * Decision two
68
+ `;
69
+
70
+ const result = parser.parseFromOutput(output);
71
+
72
+ assert.equal(result.decisions.length, 2);
73
+ assert.equal(result.decisions[0], 'Decision one');
74
+ assert.equal(result.decisions[1], 'Decision two');
75
+ });
76
+
77
+ it('stops parsing decisions at next heading', () => {
78
+ const parser = new WorkSummaryParser();
79
+ const output = `
80
+ ## Work Summary
81
+ ### Approach
82
+ Did it.
83
+ ### Decisions
84
+ - Decision A
85
+
86
+ ## Some Other Section
87
+ This should not be parsed as decisions.
88
+ `;
89
+
90
+ const result = parser.parseFromOutput(output);
91
+
92
+ assert.equal(result.decisions.length, 1);
93
+ assert.equal(result.decisions[0], 'Decision A');
94
+ });
95
+ });
96
+
97
+ describe('parseDiffNameStatus', () => {
98
+ it('categorizes files by A/M/D status markers', () => {
99
+ const parser = new WorkSummaryParser();
100
+ const diffOutput = `A\tpackages/shared/lib/new_file.ts
101
+ M\tpackages/shared/lib/pipeline.ts
102
+ M\tpackages/shared/db/schema.ts
103
+ D\tpackages/frontend/src/old_component.tsx
104
+ A\tpackages/frontend/src/KanbanView.tsx`;
105
+
106
+ const result = parser.parseDiffNameStatus(diffOutput);
107
+
108
+ assert.deepEqual(result.filesCreated, [
109
+ 'packages/shared/lib/new_file.ts',
110
+ 'packages/frontend/src/KanbanView.tsx',
111
+ ]);
112
+ assert.deepEqual(result.filesUpdated, [
113
+ 'packages/shared/lib/pipeline.ts',
114
+ 'packages/shared/db/schema.ts',
115
+ ]);
116
+ assert.deepEqual(result.filesDeleted, [
117
+ 'packages/frontend/src/old_component.tsx',
118
+ ]);
119
+ });
120
+
121
+ it('returns empty arrays for empty diff', () => {
122
+ const parser = new WorkSummaryParser();
123
+ const result = parser.parseDiffNameStatus('');
124
+
125
+ assert.deepEqual(result.filesCreated, []);
126
+ assert.deepEqual(result.filesUpdated, []);
127
+ assert.deepEqual(result.filesDeleted, []);
128
+ });
129
+
130
+ it('handles single added file', () => {
131
+ const parser = new WorkSummaryParser();
132
+ const diffOutput = `A\tsrc/index.ts`;
133
+
134
+ const result = parser.parseDiffNameStatus(diffOutput);
135
+
136
+ assert.deepEqual(result.filesCreated, ['src/index.ts']);
137
+ assert.deepEqual(result.filesUpdated, []);
138
+ assert.deepEqual(result.filesDeleted, []);
139
+ });
140
+
141
+ it('handles single modified file', () => {
142
+ const parser = new WorkSummaryParser();
143
+ const diffOutput = `M\tsrc/index.ts`;
144
+
145
+ const result = parser.parseDiffNameStatus(diffOutput);
146
+
147
+ assert.deepEqual(result.filesCreated, []);
148
+ assert.deepEqual(result.filesUpdated, ['src/index.ts']);
149
+ assert.deepEqual(result.filesDeleted, []);
150
+ });
151
+
152
+ it('handles single deleted file', () => {
153
+ const parser = new WorkSummaryParser();
154
+ const diffOutput = `D\tsrc/removed.ts`;
155
+
156
+ const result = parser.parseDiffNameStatus(diffOutput);
157
+
158
+ assert.deepEqual(result.filesCreated, []);
159
+ assert.deepEqual(result.filesUpdated, []);
160
+ assert.deepEqual(result.filesDeleted, ['src/removed.ts']);
161
+ });
162
+
163
+ it('treats unknown status markers as updated', () => {
164
+ const parser = new WorkSummaryParser();
165
+ const diffOutput = `R\tsrc/renamed.ts`;
166
+
167
+ const result = parser.parseDiffNameStatus(diffOutput);
168
+
169
+ assert.deepEqual(result.filesCreated, []);
170
+ assert.deepEqual(result.filesUpdated, ['src/renamed.ts']);
171
+ assert.deepEqual(result.filesDeleted, []);
172
+ });
173
+ });
174
+
175
+ describe('buildSummary', () => {
176
+ it('combines cycle, diff name-status, and Claude output into a WorkSummary', () => {
177
+ const parser = new WorkSummaryParser();
178
+ const diffOutput = `A\tsrc/new.ts
179
+ M\tsrc/foo.ts`;
180
+ const claudeOutput = `
181
+ ## Work Summary
182
+ ### Approach
183
+ Implemented the feature by adding a new module.
184
+ ### Decisions
185
+ - Chose class-based approach per nfr_001
186
+ `;
187
+
188
+ const summary = parser.buildSummary(1, diffOutput, claudeOutput);
189
+
190
+ assert.equal(summary.cycle, 1);
191
+ assert.deepEqual(summary.filesCreated, ['src/new.ts']);
192
+ assert.deepEqual(summary.filesUpdated, ['src/foo.ts']);
193
+ assert.deepEqual(summary.filesDeleted, []);
194
+ assert.ok(summary.approach.includes('new module'));
195
+ assert.equal(summary.decisions.length, 1);
196
+ assert.ok(summary.timestamp);
197
+ });
198
+
199
+ it('provides default approach when none in output', () => {
200
+ const parser = new WorkSummaryParser();
201
+ const summary = parser.buildSummary(2, '', 'No summary block here');
202
+
203
+ assert.equal(summary.cycle, 2);
204
+ assert.deepEqual(summary.filesCreated, []);
205
+ assert.deepEqual(summary.filesUpdated, []);
206
+ assert.deepEqual(summary.filesDeleted, []);
207
+ assert.equal(summary.approach, 'No approach narrative provided.');
208
+ assert.deepEqual(summary.decisions, []);
209
+ });
210
+ });
211
+ });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Tests for Zoom and Pan logic (feat_019).
3
+ * Tests pure computation functions extracted from GraphView.
4
+ */
5
+ import { describe, it } from 'node:test';
6
+ import assert from 'node:assert/strict';
7
+
8
+ // Pure function extracted from GraphView
9
+ const nodeRadius = (d: { edgeCount: number }) => {
10
+ const base = 8;
11
+ const scale = Math.min(d.edgeCount * 1.5, 20);
12
+ return base + scale;
13
+ };
14
+
15
+ describe('Zoom and Pan', () => {
16
+
17
+ describe('nodeRadius (affects zoom bounds)', () => {
18
+ it('returns base radius of 8 for zero-edge node', () => {
19
+ assert.equal(nodeRadius({ edgeCount: 0 }), 8);
20
+ });
21
+
22
+ it('increases radius with edge count', () => {
23
+ const r0 = nodeRadius({ edgeCount: 0 });
24
+ const r5 = nodeRadius({ edgeCount: 5 });
25
+ assert.ok(r5 > r0, 'more edges should yield larger radius');
26
+ });
27
+
28
+ it('caps radius at 28 (8 base + 20 max scale)', () => {
29
+ assert.equal(nodeRadius({ edgeCount: 100 }), 28);
30
+ assert.equal(nodeRadius({ edgeCount: 200 }), 28);
31
+ });
32
+ });
33
+
34
+ describe('nodeRadius consistency', () => {
35
+ it('nodeRadius returns consistent values for force simulation', () => {
36
+ const node = { edgeCount: 5 };
37
+ const r1 = nodeRadius(node);
38
+ const r2 = nodeRadius(node);
39
+ assert.equal(r1, r2);
40
+ assert.equal(r1, 8 + Math.min(5 * 1.5, 20)); // 15.5
41
+ });
42
+ });
43
+ });
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": false,
4
+ "allowJs": true,
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "target": "ESNext",
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "outDir": "build",
12
+ "rootDir": ".",
13
+ "sourceMap": true,
14
+ "declaration": true
15
+ },
16
+ "include": [
17
+ "tests/**/*.ts",
18
+ "smoke_test.ts"
19
+ ],
20
+ "exclude": [
21
+ "node_modules",
22
+ "packages"
23
+ ]
24
+ }
@@ -0,0 +1,312 @@
1
+ ---
2
+ name: product-bootstrap
3
+ description: Bootstrap the product knowledge graph for an existing project by scanning the codebase and interviewing the user. Use when the user wants to onboard a project, bootstrap the graph, initialize the product system, or bring the knowledge graph up to speed for an existing codebase.
4
+ ---
5
+
6
+ # Product Bootstrap Skill
7
+
8
+ ## Your Role
9
+ You are bootstrapping the product knowledge graph for an existing project.
10
+ Your goal is to rapidly build a well-connected specification graph by
11
+ **scanning the codebase first** and **asking the user only about intent,
12
+ priorities, and preferences**. You interact with the graph exclusively
13
+ through the tools below.
14
+
15
+ All tools live in `product-system/packages/shared/tools/` and
16
+ are run with `npx tsx`.
17
+
18
+ ## Bootstrap Philosophy
19
+ Unlike a greenfield interview, the project already exists. The codebase is
20
+ the primary source of truth for **what exists**. The user is the source of
21
+ truth for **what matters, what's next, and why**.
22
+
23
+ - **Read code first, ask questions second**
24
+ - **Populate aggressively** — create nodes for everything you discover
25
+ - **Ask the user to confirm and prioritize**, not to describe what you can see
26
+ - **Wire edges densely** — a bootstrap graph with sparse edges is useless
27
+
28
+ ## Session Start Protocol
29
+ 1. Call `start_session`
30
+ 2. Call `get_status` — check if this is a cold start or a continuation
31
+ 3. If cold start (empty graph): begin with **Phase 1**
32
+ 4. If continuing: call `get_gaps --blocking-only` and resume at the
33
+ appropriate phase
34
+
35
+ ## Phase 1 — Project Survey (Codebase Scan)
36
+
37
+ **Goal:** Understand the project structure, tech stack, and domain without
38
+ asking the user a single question yet.
39
+
40
+ 1. **Explore the project root** — read `package.json`, `Cargo.toml`,
41
+ `pyproject.toml`, `go.mod`, `Gemfile`, or equivalent to identify:
42
+ - Language and framework
43
+ - Key dependencies
44
+ - Build system and scripts
45
+ 2. **Scan directory structure** — use Glob to map top-level directories and
46
+ understand the layout (e.g. `src/`, `lib/`, `api/`, `components/`,
47
+ `models/`, `migrations/`)
48
+ 3. **Read configuration files** — `.env.example`, CI configs, Docker files,
49
+ `tsconfig.json`, etc. to identify infrastructure and deployment patterns
50
+ 4. **Identify data models** — look for ORM models, database schemas,
51
+ migration files, type definitions, or GraphQL schemas
52
+ 5. **Identify API surface** — look for route definitions, controllers,
53
+ resolvers, or API handlers
54
+ 6. **Identify UI structure** (if applicable) — look for pages, components,
55
+ layouts
56
+
57
+ **Output of Phase 1:** A mental map of the project. Do NOT create nodes yet.
58
+ Present a summary to the user:
59
+ - "Here's what I found in your codebase: [tech stack], [main modules],
60
+ [data entities], [API shape]. Does this look right? Anything I missed?"
61
+
62
+ ## Phase 2 — Foundation Nodes
63
+
64
+ **Goal:** Create the structural backbone of the graph. Create nodes in this
65
+ order, using what you learned in Phase 1.
66
+
67
+ ### 2a. Tech Choices
68
+ For each technology identified (language, framework, database, hosting,
69
+ key libraries), create a `tech_choice` node:
70
+ ```
71
+ add_node --type tech_choice --name "TypeScript" --description "Primary language..."
72
+ ```
73
+
74
+ ### 2b. User Roles
75
+ Scan for auth logic, role enums, middleware, or permission checks. Create a
76
+ `user_role` node for each role discovered. Ask the user: "I found these
77
+ roles: [list]. Are there others? Which is the primary user?"
78
+
79
+ ### 2c. Design Patterns
80
+ Identify architectural patterns in use (e.g. MVC, event-driven, repository
81
+ pattern, component composition, state management approach). Create a
82
+ `design_pattern` node for each.
83
+
84
+ ### 2d. Decisions
85
+ For patterns that reflect deliberate architectural choices (e.g. "monorepo",
86
+ "REST over GraphQL", "server-side rendering"), create `decision` nodes.
87
+ Ask the user: "I see these architectural decisions. Any context on why, or
88
+ any you'd revisit?"
89
+
90
+ ### 2e. Data Entities
91
+ For each model/schema/table discovered, create a `data_entity` node with
92
+ fields listed in the description. Wire `reads_writes` edges as you discover
93
+ which modules touch which entities.
94
+
95
+ ### Edge Pass after Phase 2:
96
+ - `tech_choice` → `governed_by` → relevant `decision` nodes
97
+ - `design_pattern` → `governed_by` → relevant `decision` nodes
98
+ - `data_entity` → `reads_writes` edges to each other where foreign keys exist
99
+
100
+ Present all created nodes and edges to the user for confirmation.
101
+
102
+ ## Phase 3 — Feature Discovery
103
+
104
+ **Goal:** Map the project's capabilities as features in the graph.
105
+
106
+ 1. **Scan for feature boundaries** — look at:
107
+ - Route/page definitions (each route often = a feature)
108
+ - Major UI components or pages
109
+ - API endpoint groups
110
+ - Background jobs, workers, or cron tasks
111
+ - CLI commands (if applicable)
112
+ 2. **Create top-level features** — one `feature` node per major capability.
113
+ Set status to `defined` for features that are clearly implemented.
114
+ 3. **Decompose large features** — if a feature has sub-routes, tabs, or
115
+ distinct modes, create sub-features and wire `contains` edges.
116
+ 4. **Wire edges:**
117
+ - `feature` → `implemented_with` → `tech_choice` or `component`
118
+ - `feature` → `depends_on` → other features it requires
119
+ - `feature` → `reads_writes` → `data_entity`
120
+ - `feature` → `performed_by` → `user_role`
121
+ - `feature` → `governed_by` → `decision` or `design_pattern`
122
+
123
+ Ask the user: "Here are the features I identified: [list]. Any missing?
124
+ Which are most important to you right now?"
125
+
126
+ ## Phase 4 — Component Mapping
127
+
128
+ **Goal:** Map internal components and modules that implement features.
129
+
130
+ 1. **Identify reusable components** — shared UI components, service classes,
131
+ utility modules, middleware, hooks
132
+ 2. **Create `component` nodes** for significant reusable pieces
133
+ 3. **Wire edges:**
134
+ - `component` → `implemented_with` → `tech_choice`
135
+ - `feature` → `implemented_with` → `component`
136
+ - `component` → `reads_writes` → `data_entity`
137
+ - `component` → `depends_on` → other components
138
+
139
+ ## Phase 5 — Non-Functional Requirements & Constraints
140
+
141
+ **Goal:** Capture the quality attributes and constraints.
142
+
143
+ Ask the user about (only what's relevant):
144
+ - Performance targets (response times, throughput)
145
+ - Security requirements (auth method, data sensitivity, compliance)
146
+ - Scalability expectations
147
+ - Accessibility requirements
148
+ - Browser/device support
149
+ - Uptime/availability targets
150
+
151
+ Create `non_functional_requirement` nodes and wire `constrained_by` edges
152
+ from the features they apply to.
153
+
154
+ ## Phase 6 — Flows & Integration Points
155
+
156
+ **Goal:** Capture key user journeys and external integrations.
157
+
158
+ 1. **Identify critical flows** — onboarding, checkout, CRUD cycles, admin
159
+ workflows. Create `flow` nodes with step-by-step descriptions.
160
+ 2. **Identify external integrations** — third-party APIs, webhooks, OAuth
161
+ providers, payment processors. Create nodes and wire appropriately.
162
+ 3. **Wire edges:**
163
+ - `flow` → `contains` → features involved in the flow
164
+ - `flow` → `performed_by` → `user_role`
165
+
166
+ ## Phase 7 — Gap Analysis & Prioritization
167
+
168
+ **Goal:** Identify what's missing and let the user prioritize.
169
+
170
+ 1. Call `get_gaps` — present the full gap report
171
+ 2. Call `get_status` — show completeness metrics
172
+ 3. Ask the user:
173
+ - "Which areas should I dig deeper into?"
174
+ - "Are there planned features not yet in the codebase?"
175
+ - "Any known technical debt or areas you want to redesign?"
176
+ 4. Create nodes for planned/future work with status `draft`
177
+
178
+ ## Session End Protocol
179
+ 1. Call `get_gaps` — report remaining gaps
180
+ 2. Call `get_status` — show overall progress
181
+ 3. Call `end_session` with a summary
182
+ 4. Tell the user which phase to resume at next session
183
+
184
+ ## Tool Reference
185
+
186
+ ### start_session
187
+ ```
188
+ npx tsx packages/shared/tools/start_session.ts
189
+ ```
190
+
191
+ ### end_session
192
+ ```
193
+ npx tsx packages/shared/tools/end_session.ts --summary "..." --nodes-touched "feat_001,dec_001" --questions-resolved 3
194
+ ```
195
+
196
+ ### search_nodes
197
+ ```
198
+ npx tsx packages/shared/tools/search_nodes.ts --query "keyword"
199
+ npx tsx packages/shared/tools/search_nodes.ts --type feature
200
+ npx tsx packages/shared/tools/search_nodes.ts --has-open-questions
201
+ npx tsx packages/shared/tools/search_nodes.ts --completeness-below 0.5
202
+ ```
203
+
204
+ ### get_node
205
+ ```
206
+ npx tsx packages/shared/tools/get_node.ts <node_id>
207
+ npx tsx packages/shared/tools/get_node.ts --name "Node Name"
208
+ ```
209
+ Returns full .md content plus a Relations section listing all connected nodes
210
+ with direction, relation type, name, type, and status.
211
+
212
+ ### add_node
213
+ ```
214
+ npx tsx packages/shared/tools/add_node.ts --type <type> --name "Name" --description "..."
215
+ ```
216
+ Valid types: feature, component, data_entity, decision, tech_choice,
217
+ non_functional_requirement, design_token, design_pattern, user_role,
218
+ flow, assumption, open_question
219
+
220
+ ### update_node
221
+ ```
222
+ npx tsx packages/shared/tools/update_node.ts <id> --add-acceptance-criteria "..."
223
+ npx tsx packages/shared/tools/update_node.ts <id> --add-open-question "..."
224
+ npx tsx packages/shared/tools/update_node.ts <id> --add-note "Session N: ..."
225
+ npx tsx packages/shared/tools/update_node.ts <id> --set-status <draft|partially_defined|defined>
226
+ npx tsx packages/shared/tools/update_node.ts <id> --set-priority <low|medium|high|blocking>
227
+ npx tsx packages/shared/tools/update_node.ts <id> --set-description "..."
228
+ npx tsx packages/shared/tools/update_node.ts <id> --set-section "SectionName=content"
229
+ ```
230
+
231
+ ### resolve_question
232
+ ```
233
+ npx tsx packages/shared/tools/resolve_question.ts <id> --question "..." --answer "..."
234
+ ```
235
+
236
+ ### add_edge
237
+ ```
238
+ npx tsx packages/shared/tools/add_edge.ts <from_id> <relation> <to_id>
239
+ ```
240
+ Valid relations: contains, depends_on, governed_by, constrained_by,
241
+ implemented_with, reads_writes, exposes, consumes, performed_by,
242
+ escalates_to, relates_to
243
+
244
+ ### remove_edge
245
+ ```
246
+ npx tsx packages/shared/tools/remove_edge.ts <from_id> <relation> <to_id>
247
+ ```
248
+
249
+ ### get_gaps
250
+ ```
251
+ npx tsx packages/shared/tools/get_gaps.ts
252
+ npx tsx packages/shared/tools/get_gaps.ts --blocking-only
253
+ npx tsx packages/shared/tools/get_gaps.ts --type feature
254
+ ```
255
+
256
+ ### get_status
257
+ ```
258
+ npx tsx packages/shared/tools/get_status.ts
259
+ ```
260
+
261
+ ### rebuild_index
262
+ ```
263
+ npx tsx packages/shared/tools/rebuild_index.ts
264
+ npx tsx packages/shared/tools/rebuild_index.ts --dry-run
265
+ ```
266
+
267
+ ## Search Strategy
268
+ The `search_nodes --query` tool returns graph-aware relevance-ranked results.
269
+
270
+ 1. **Start with specific keywords** — direct matches appear first with
271
+ `relevance: "direct"`.
272
+ 2. **Read expansion results** — each direct match surfaces its 1-hop graph
273
+ neighbors. Use them to discover related nodes without manual edge walking.
274
+ 3. **Fall back to structural overview** — on zero matches, the tool returns
275
+ the top-5 most-connected nodes per type (the project backbone).
276
+ 4. **Use `--type` filters to drill in** — narrow with `--type feature`,
277
+ `--type decision`, etc.
278
+ 5. **Trust strong-edge neighbors** — `depends_on`, `implemented_with`,
279
+ `governed_by`, `contains` are architecturally significant. `relates_to`
280
+ is a weak signal.
281
+
282
+ ## Edge Type Semantics
283
+
284
+ - **depends_on** — prerequisite chain
285
+ - **implemented_with** — technical realization
286
+ - **governed_by** — architectural constraints
287
+ - **constrained_by** — non-functional limits
288
+ - **contains** — parent-child composition
289
+ - **reads_writes** — data access
290
+ - **exposes** — API surface
291
+ - **consumes** — data intake
292
+ - **performed_by** — actor
293
+ - **escalates_to** — delegation
294
+ - **relates_to** — loose association (weakest)
295
+
296
+ ## Rules
297
+ 1. Never read or write graph.tson or .md files directly — always use the tools
298
+ 2. Always call get_node before update_node — never update blind
299
+ 3. Always record answers via resolve_question — don't just add a note
300
+ 4. Nodes should reflect reality (codebase + user statements), not inferences —
301
+ use `assumption` node type for inferences
302
+ 5. If the user contradicts something in the graph, update it and add a note
303
+ 6. All tool commands must be run from the `product-system/`
304
+ directory
305
+ 7. Set status to `defined` for features clearly implemented in the codebase;
306
+ use `draft` for planned/future work
307
+ 8. **Scan code before asking** — only ask the user about intent, priorities,
308
+ and preferences. Never ask "how does X work?" when you can read the code.
309
+ 9. **Batch node creation** — create multiple related nodes before running
310
+ edge discovery, to maximize edge connections found in a single pass
311
+ 10. **Present and confirm** — after each phase, show the user what you created
312
+ and get confirmation before moving on