@assistkick/create 1.0.1 → 1.3.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.
- package/dist/src/scaffolder.d.ts +6 -1
- package/dist/src/scaffolder.js +20 -9
- package/dist/src/scaffolder.js.map +1 -1
- package/package.json +3 -2
- package/templates/{product-system → assistkick-product-system}/CLAUDE.md +4 -4
- package/templates/{product-system → assistkick-product-system}/package.json +5 -5
- package/templates/{product-system → assistkick-product-system}/packages/backend/package.json +2 -2
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/routes/auth.ts +1 -1
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/routes/coherence.ts +1 -1
- package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +231 -0
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/routes/graph.ts +3 -3
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/routes/kanban.ts +6 -6
- package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +88 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +82 -0
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/server.ts +23 -10
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/coherence-review.ts +4 -4
- package/templates/assistkick-product-system/packages/backend/src/services/github_app_service.ts +146 -0
- package/templates/assistkick-product-system/packages/backend/src/services/init.ts +147 -0
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/invitation_service.ts +1 -1
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/password_reset_service.ts +1 -1
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/project_service.ts +72 -1
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +87 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +194 -0
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +159 -0
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/pty_session_manager.ts +114 -39
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/terminal_ws_handler.ts +28 -14
- package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/user_management_service.ts +1 -1
- package/templates/{product-system → assistkick-product-system}/packages/frontend/package.json +1 -1
- package/templates/{product-system → assistkick-product-system}/packages/frontend/src/App.tsx +1 -1
- package/templates/{product-system → assistkick-product-system}/packages/frontend/src/api/client.ts +151 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/GitRepoModal.tsx +352 -0
- package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/KanbanView.tsx +208 -95
- package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/ProjectSelector.tsx +17 -1
- package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +333 -0
- package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/Toolbar.tsx +15 -13
- package/templates/{product-system → assistkick-product-system}/packages/frontend/src/constants/graph.ts +1 -0
- package/templates/{product-system → assistkick-product-system}/packages/frontend/src/hooks/useProjects.ts +4 -0
- package/templates/{product-system → assistkick-product-system}/packages/frontend/src/routes/dashboard.tsx +22 -4
- package/templates/{product-system → assistkick-product-system}/packages/frontend/src/styles/index.css +486 -38
- package/templates/assistkick-product-system/packages/frontend/vite.config.ts +31 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0001_vengeful_wallop.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0002_greedy_excalibur.sql +4 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0001_snapshot.json +826 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0002_snapshot.json +854 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +27 -0
- package/templates/{product-system → assistkick-product-system}/packages/shared/db/schema.ts +5 -0
- package/templates/{product-system → assistkick-product-system}/packages/shared/lib/claude-service.ts +54 -1
- package/templates/{product-system → assistkick-product-system}/packages/shared/lib/db.ts +1 -1
- package/templates/{product-system → assistkick-product-system}/packages/shared/lib/git_workflow.ts +25 -0
- package/templates/{product-system → assistkick-product-system}/packages/shared/lib/pipeline-state-store.ts +4 -0
- package/templates/{product-system → assistkick-product-system}/packages/shared/lib/pipeline.ts +329 -89
- package/templates/assistkick-product-system/packages/shared/lib/pipeline_orchestrator.ts +186 -0
- package/templates/{product-system → assistkick-product-system}/packages/shared/lib/prompt_builder.ts +2 -2
- package/templates/{product-system → assistkick-product-system}/packages/shared/package.json +1 -1
- package/templates/assistkick-product-system/packages/shared/tools/db_explorer.ts +275 -0
- package/templates/{product-system → assistkick-product-system}/packages/shared/tools/get_kanban.ts +2 -1
- package/templates/{product-system → assistkick-product-system}/packages/shared/tools/move_card.ts +3 -2
- package/templates/{product-system → assistkick-product-system}/packages/shared/tools/update_node.ts +2 -2
- package/templates/{product-system → assistkick-product-system}/tests/db_sqlite_fallback.test.ts +1 -1
- package/templates/{product-system → assistkick-product-system}/tests/kanban.test.ts +1 -1
- package/templates/{product-system → assistkick-product-system}/tests/pipeline_stats_all_cards.test.ts +1 -1
- package/templates/{product-system → assistkick-product-system}/tests/web_terminal.test.ts +189 -150
- package/templates/skills/{product-bootstrap → assistkick-bootstrap}/SKILL.md +36 -28
- package/templates/skills/{product-code-reviewer → assistkick-code-reviewer}/SKILL.md +26 -18
- package/templates/skills/assistkick-db-explorer/SKILL.md +86 -0
- package/templates/skills/{product-debugger → assistkick-debugger}/SKILL.md +35 -27
- package/templates/skills/{product-developer → assistkick-developer}/SKILL.md +40 -32
- package/templates/skills/{product-interview → assistkick-interview}/SKILL.md +37 -29
- package/templates/product-system/packages/backend/src/routes/pipeline.ts +0 -41
- package/templates/product-system/packages/backend/src/services/init.ts +0 -80
- package/templates/product-system/packages/backend/src/services/pty_session_manager.test.ts +0 -88
- package/templates/product-system/packages/frontend/src/components/TerminalView.tsx +0 -200
- package/templates/product-system/packages/frontend/vite.config.ts +0 -20
- package/templates/product-system/packages/shared/db/migrations/meta/_journal.json +0 -13
- /package/templates/{product-system → assistkick-product-system}/.env.example +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/middleware/auth_middleware.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/middleware/auth_middleware.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/routes/projects.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/routes/users.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/auth_service.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/auth_service.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/email_service.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/invitation_service.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/password_reset_service.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/project_service.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/src/services/user_management_service.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/backend/tsconfig.json +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/index.html +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/package-lock.json +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/public/favicon.svg +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/api/client_projects.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/api/client_refresh.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/CoherenceView.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/GraphLegend.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/GraphSettings.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/GraphView.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/InviteUserDialog.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/LoginPage.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/QaIssueSheet.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/SidePanel.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/components/UsersView.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/hooks/useAuth.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/hooks/useGraph.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/hooks/useKanban.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/hooks/useTheme.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/hooks/useToast.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/hooks/use_projects_logic.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/main.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/pages/accept_invitation_page.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/pages/forgot_password_page.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/pages/register_page.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/pages/reset_password_page.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/routes/ProtectedRoute.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/routes/accept_invitation.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/routes/forgot_password.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/routes/login.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/routes/register.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/routes/reset_password.tsx +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/utils/auth_validation.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/utils/auth_validation.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/utils/login_validation.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/utils/login_validation.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/utils/logout.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/utils/node_sizing.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/utils/node_sizing.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/utils/task_status.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/src/utils/task_status.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/frontend/tsconfig.json +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/.env.example +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/README.md +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/db/migrate.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/db/migrations/0000_dashing_gorgon.sql +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/db/migrations/meta/0000_snapshot.json +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/drizzle.config.js +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/coherence.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/completeness.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/constants.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/graph.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/kanban.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/markdown.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/relevance_search.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/session.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/validator.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/lib/work_summary_parser.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/scripts/assign-project.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/add_edge.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/add_node.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/end_session.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/get_gaps.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/get_node.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/get_status.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/migrate_to_turso.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/rebuild_index.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/remove_edge.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/remove_node.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/resolve_question.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/search_nodes.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tools/start_session.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/packages/shared/tsconfig.json +0 -0
- /package/templates/{product-system → assistkick-product-system}/pnpm-workspace.yaml +0 -0
- /package/templates/{product-system → assistkick-product-system}/smoke_test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/coherence_review.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/edge_type_color_coding.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/emit-tool-use-events.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/feature_kind.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/gap_indicators.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/graceful_init.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/graph_legend.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/graph_settings_sheet.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/hide_defined_filter.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/neighborhood_focus.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/node_search.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/node_sizing.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/node_type_toggle_filters.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/node_type_visual_encoding.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/pipeline-state-store.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/pipeline-unit.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/pipeline.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/play_all.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/qa_issue_sheet.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/relevance_search.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/search_reorder.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/serve_ui.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/serve_ui_drizzle.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/session_context_recall.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/side_panel.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/spec_completeness_label.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/url_routing_test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/user_login.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/user_registration.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/work_summary.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tests/zoom_pan.test.ts +0 -0
- /package/templates/{product-system → assistkick-product-system}/tsconfig.json +0 -0
- /package/templates/skills/{product-debugger → assistkick-debugger}/references/agent-browser.md +0 -0
package/dist/src/scaffolder.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ type DbConfig = {
|
|
|
5
5
|
url: string;
|
|
6
6
|
authToken: string;
|
|
7
7
|
};
|
|
8
|
+
type PortConfig = {
|
|
9
|
+
backendPort: number;
|
|
10
|
+
frontendPort: number;
|
|
11
|
+
};
|
|
8
12
|
export type PromptFn = (question: string) => Promise<string>;
|
|
9
13
|
export declare class Scaffolder {
|
|
10
14
|
private readonly targetDir;
|
|
@@ -14,9 +18,10 @@ export declare class Scaffolder {
|
|
|
14
18
|
run: () => Promise<void>;
|
|
15
19
|
private checkPnpm;
|
|
16
20
|
private promptDbConfig;
|
|
21
|
+
private promptPortConfig;
|
|
17
22
|
private scaffoldProductSystem;
|
|
18
23
|
private scaffoldSkills;
|
|
19
24
|
skillHasModifications: (sourceDir: string, targetDir: string) => boolean;
|
|
20
|
-
generateEnv: (productSystemDir: string, dbConfig: DbConfig) => void;
|
|
25
|
+
generateEnv: (productSystemDir: string, dbConfig: DbConfig, portConfig: PortConfig) => void;
|
|
21
26
|
}
|
|
22
27
|
export {};
|
package/dist/src/scaffolder.js
CHANGED
|
@@ -17,27 +17,29 @@ export class Scaffolder {
|
|
|
17
17
|
}
|
|
18
18
|
run = async () => {
|
|
19
19
|
this.checkPnpm();
|
|
20
|
-
const productSystemTarget = join(this.targetDir, 'product-system');
|
|
20
|
+
const productSystemTarget = join(this.targetDir, 'assistkick-product-system');
|
|
21
21
|
const skillsTarget = join(this.targetDir, '.claude', 'skills');
|
|
22
22
|
const isRerun = existsSync(productSystemTarget);
|
|
23
23
|
let dbConfig = null;
|
|
24
|
+
let portConfig = null;
|
|
24
25
|
if (isRerun) {
|
|
25
|
-
console.log('product-system/ already exists. Updating code, preserving data/ and .env...');
|
|
26
|
+
console.log('assistkick-product-system/ already exists. Updating code, preserving data/ and .env...');
|
|
26
27
|
}
|
|
27
28
|
else {
|
|
28
29
|
dbConfig = await this.promptDbConfig();
|
|
30
|
+
portConfig = await this.promptPortConfig();
|
|
29
31
|
}
|
|
30
32
|
this.scaffoldProductSystem(productSystemTarget);
|
|
31
33
|
await this.scaffoldSkills(skillsTarget, isRerun);
|
|
32
|
-
if (!isRerun && dbConfig) {
|
|
33
|
-
this.generateEnv(productSystemTarget, dbConfig);
|
|
34
|
+
if (!isRerun && dbConfig && portConfig) {
|
|
35
|
+
this.generateEnv(productSystemTarget, dbConfig, portConfig);
|
|
34
36
|
}
|
|
35
37
|
console.log('\nRunning pnpm install...');
|
|
36
38
|
execSync('pnpm install', { cwd: productSystemTarget, stdio: 'inherit' });
|
|
37
39
|
console.log('\nRunning db:migrate...');
|
|
38
40
|
execSync('pnpm db:migrate', { cwd: productSystemTarget, stdio: 'inherit' });
|
|
39
|
-
console.log('\
|
|
40
|
-
console.log(' cd product-system && pnpm dev');
|
|
41
|
+
console.log('\nassistkick-product-system is ready!');
|
|
42
|
+
console.log(' cd assistkick-product-system && pnpm dev');
|
|
41
43
|
};
|
|
42
44
|
checkPnpm = () => {
|
|
43
45
|
try {
|
|
@@ -61,8 +63,16 @@ export class Scaffolder {
|
|
|
61
63
|
}
|
|
62
64
|
return { type: 'local' };
|
|
63
65
|
};
|
|
66
|
+
promptPortConfig = async () => {
|
|
67
|
+
console.log('\nPort configuration:');
|
|
68
|
+
const backendInput = await this.prompt('Backend port [default=3000]: ');
|
|
69
|
+
const frontendInput = await this.prompt('Frontend port [default=5173]: ');
|
|
70
|
+
const backendPort = backendInput.trim() ? parseInt(backendInput.trim(), 10) : 3000;
|
|
71
|
+
const frontendPort = frontendInput.trim() ? parseInt(frontendInput.trim(), 10) : 5173;
|
|
72
|
+
return { backendPort, frontendPort };
|
|
73
|
+
};
|
|
64
74
|
scaffoldProductSystem = (targetDir) => {
|
|
65
|
-
const sourceDir = join(this.templatesDir, 'product-system');
|
|
75
|
+
const sourceDir = join(this.templatesDir, 'assistkick-product-system');
|
|
66
76
|
mkdirSync(targetDir, { recursive: true });
|
|
67
77
|
cpSync(sourceDir, targetDir, {
|
|
68
78
|
recursive: true,
|
|
@@ -72,7 +82,7 @@ export class Scaffolder {
|
|
|
72
82
|
return base !== 'node_modules';
|
|
73
83
|
},
|
|
74
84
|
});
|
|
75
|
-
console.log('Scaffolded product-system/');
|
|
85
|
+
console.log('Scaffolded assistkick-product-system/');
|
|
76
86
|
};
|
|
77
87
|
scaffoldSkills = async (targetDir, isRerun) => {
|
|
78
88
|
const sourceSkillsDir = join(this.templatesDir, 'skills');
|
|
@@ -105,7 +115,7 @@ export class Scaffolder {
|
|
|
105
115
|
return false;
|
|
106
116
|
return readFileSync(sourceFile, 'utf-8') !== readFileSync(targetFile, 'utf-8');
|
|
107
117
|
};
|
|
108
|
-
generateEnv = (productSystemDir, dbConfig) => {
|
|
118
|
+
generateEnv = (productSystemDir, dbConfig, portConfig) => {
|
|
109
119
|
const lines = [];
|
|
110
120
|
if (dbConfig.type === 'local') {
|
|
111
121
|
lines.push('# Database — local SQLite', '# The database file is created automatically at data/local.db', '# To upgrade to Turso, uncomment and fill in the variables below:', '#TURSO_DATABASE_URL=libsql://your-db.turso.io', '#TURSO_AUTH_TOKEN=your-token', '');
|
|
@@ -113,6 +123,7 @@ export class Scaffolder {
|
|
|
113
123
|
else {
|
|
114
124
|
lines.push('# Database — Turso cloud', `TURSO_DATABASE_URL=${dbConfig.url}`, `TURSO_AUTH_TOKEN=${dbConfig.authToken}`, '');
|
|
115
125
|
}
|
|
126
|
+
lines.push('# Ports', `PORT=${portConfig.backendPort}`, `FRONTEND_PORT=${portConfig.frontendPort}`, '');
|
|
116
127
|
writeFileSync(join(productSystemDir, '.env'), lines.join('\n'));
|
|
117
128
|
console.log('Generated .env');
|
|
118
129
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffolder.js","sourceRoot":"","sources":["../../src/scaffolder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffolder.js","sourceRoot":"","sources":["../../src/scaffolder.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistkick/create",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "Scaffold
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Scaffold assistkick-product-system into any project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"@assistkick/create": "./dist/bin/create.js"
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"build": "tsc",
|
|
15
15
|
"prepare_templates": "bash scripts/prepare_templates.sh",
|
|
16
16
|
"prepublishOnly": "bash scripts/prepare_templates.sh && pnpm build",
|
|
17
|
+
"publish": "npm publish --access public",
|
|
17
18
|
"test": "tsx --test tests/**/*.test.ts"
|
|
18
19
|
},
|
|
19
20
|
"devDependencies": {
|
|
@@ -15,11 +15,11 @@ AI requirements interview system that builds a specification knowledge graph thr
|
|
|
15
15
|
## Project Structure
|
|
16
16
|
|
|
17
17
|
```
|
|
18
|
-
product-system/
|
|
18
|
+
assistkick-product-system/
|
|
19
19
|
packages/
|
|
20
|
-
backend/ — Express API server (@
|
|
21
|
-
frontend/ — React SPA (@
|
|
22
|
-
shared/ — DB schema, migrations, shared types (@
|
|
20
|
+
backend/ — Express API server (@assistkick/backend)
|
|
21
|
+
frontend/ — React SPA (@assistkick/frontend)
|
|
22
|
+
shared/ — DB schema, migrations, shared types (@assistkick/shared)
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Commands
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "assistkick",
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"description": "AI requirements interview system — builds a specification knowledge graph through structured interviews",
|
|
5
5
|
"private": true,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"dev": "concurrently -n backend,frontend -c blue,green \"pnpm --filter @
|
|
8
|
+
"dev": "concurrently -n backend,frontend -c blue,green \"pnpm --filter @assistkick/backend dev\" \"pnpm --filter @assistkick/frontend dev\"",
|
|
9
9
|
"build": "pnpm -r build",
|
|
10
10
|
"start": "tsx packages/backend/src/server.ts",
|
|
11
11
|
"test": "tsx --test tests/**/*.test.ts",
|
|
12
12
|
"clean": "pnpm -r clean",
|
|
13
|
-
"db:migrate": "pnpm --filter @
|
|
14
|
-
"db:rollback": "pnpm --filter @
|
|
15
|
-
"db:generate": "pnpm --filter @
|
|
13
|
+
"db:migrate": "pnpm --filter @assistkick/shared db:migrate",
|
|
14
|
+
"db:rollback": "pnpm --filter @assistkick/shared db:rollback",
|
|
15
|
+
"db:generate": "pnpm --filter @assistkick/shared db:generate"
|
|
16
16
|
},
|
|
17
17
|
"pnpm": {
|
|
18
18
|
"onlyBuiltDependencies": ["esbuild", "node-pty"]
|
package/templates/{product-system → assistkick-product-system}/packages/backend/package.json
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@
|
|
2
|
+
"name": "@assistkick/backend",
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"postinstall": "chmod +x node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper 2>/dev/null || true"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@
|
|
14
|
+
"@assistkick/shared": "workspace:*",
|
|
15
15
|
"bcryptjs": "^3.0.3",
|
|
16
16
|
"cookie-parser": "^1.4.7",
|
|
17
17
|
"cors": "^2.8.5",
|
package/templates/{product-system → assistkick-product-system}/packages/backend/src/routes/auth.ts
RENAMED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { Router } from 'express';
|
|
9
9
|
import { eq, count } from 'drizzle-orm';
|
|
10
10
|
import { randomUUID } from 'node:crypto';
|
|
11
|
-
import { users, refreshTokens } from '@
|
|
11
|
+
import { users, refreshTokens } from '@assistkick/shared/db/schema.js';
|
|
12
12
|
import type { AuthService } from '../services/auth_service.js';
|
|
13
13
|
import type { PasswordResetService } from '../services/password_reset_service.js';
|
|
14
14
|
import type { InvitationService } from '../services/invitation_service.js';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { Router } from 'express';
|
|
6
|
-
import { detectConflicts } from '@
|
|
6
|
+
import { detectConflicts } from '@assistkick/shared/lib/coherence.js';
|
|
7
7
|
import { log } from '../services/init.js';
|
|
8
8
|
import {
|
|
9
9
|
coherenceRunning,
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git repository routes — connect/manage git repos for projects.
|
|
3
|
+
* POST /api/projects/:id/git/connect — connect a git repo (clone URL + GitHub App)
|
|
4
|
+
* POST /api/projects/:id/git/init — initialize a new local git repo
|
|
5
|
+
* POST /api/projects/:id/git/disconnect — disconnect a git repo
|
|
6
|
+
* GET /api/projects/:id/git/status — get git repo status
|
|
7
|
+
* POST /api/projects/:id/git/test — test GitHub App connection
|
|
8
|
+
* GET /api/projects/:id/git/installations — list GitHub App installations
|
|
9
|
+
* GET /api/projects/:id/git/repos — list repos for an installation
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { Router } from 'express';
|
|
13
|
+
import type { ProjectService } from '../services/project_service.js';
|
|
14
|
+
import type { GitHubAppService } from '../services/github_app_service.js';
|
|
15
|
+
import type { ProjectWorkspaceService } from '../services/project_workspace_service.js';
|
|
16
|
+
|
|
17
|
+
interface GitRoutesDeps {
|
|
18
|
+
projectService: ProjectService;
|
|
19
|
+
githubAppService: GitHubAppService;
|
|
20
|
+
workspaceService: ProjectWorkspaceService;
|
|
21
|
+
log: (tag: string, ...args: any[]) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const createGitRoutes = ({ projectService, githubAppService, workspaceService, log }: GitRoutesDeps): Router => {
|
|
25
|
+
const router: Router = Router({ mergeParams: true });
|
|
26
|
+
|
|
27
|
+
// POST /api/projects/:id/git/connect — connect a git repo
|
|
28
|
+
router.post('/connect', async (req, res) => {
|
|
29
|
+
const { id } = req.params;
|
|
30
|
+
const { repoUrl, githubInstallationId, githubRepoFullName, baseBranch } = req.body;
|
|
31
|
+
log('GIT', `POST /api/projects/${id}/git/connect repoUrl="${repoUrl}"`);
|
|
32
|
+
|
|
33
|
+
if (!repoUrl && !githubRepoFullName) {
|
|
34
|
+
res.status(400).json({ error: 'Either repoUrl or githubRepoFullName is required' });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const project = await projectService.getById(id);
|
|
40
|
+
if (!project) {
|
|
41
|
+
res.status(404).json({ error: 'Project not found' });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Determine clone URL
|
|
46
|
+
let cloneUrl = repoUrl;
|
|
47
|
+
if (!cloneUrl && githubRepoFullName) {
|
|
48
|
+
if (githubInstallationId && githubAppService.isConfigured()) {
|
|
49
|
+
cloneUrl = await githubAppService.buildAuthenticatedCloneUrl(githubInstallationId, githubRepoFullName);
|
|
50
|
+
} else {
|
|
51
|
+
cloneUrl = `https://github.com/${githubRepoFullName}.git`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Clone the repo into the workspace
|
|
56
|
+
await workspaceService.cloneRepo(id, cloneUrl);
|
|
57
|
+
|
|
58
|
+
// Detect default branch
|
|
59
|
+
const detectedBranch = await workspaceService.getDefaultBranch(id);
|
|
60
|
+
const effectiveBranch = baseBranch || detectedBranch;
|
|
61
|
+
|
|
62
|
+
// Save repo metadata to project
|
|
63
|
+
const updated = await projectService.connectRepo(id, {
|
|
64
|
+
repoUrl: githubRepoFullName ? `https://github.com/${githubRepoFullName}.git` : repoUrl,
|
|
65
|
+
githubInstallationId,
|
|
66
|
+
githubRepoFullName,
|
|
67
|
+
baseBranch: effectiveBranch,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
res.json({ project: updated });
|
|
71
|
+
} catch (err: any) {
|
|
72
|
+
log('GIT', `Connect repo failed: ${err.message}`);
|
|
73
|
+
res.status(500).json({ error: `Failed to connect repo: ${err.message}` });
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// POST /api/projects/:id/git/init — initialize a new local git repo
|
|
78
|
+
router.post('/init', async (req, res) => {
|
|
79
|
+
const { id } = req.params;
|
|
80
|
+
log('GIT', `POST /api/projects/${id}/git/init`);
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const project = await projectService.getById(id);
|
|
84
|
+
if (!project) {
|
|
85
|
+
res.status(404).json({ error: 'Project not found' });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
await workspaceService.initWorkspace(id);
|
|
90
|
+
const branch = await workspaceService.getDefaultBranch(id);
|
|
91
|
+
|
|
92
|
+
// Update project with base branch (no remote URL since it's local only)
|
|
93
|
+
const updated = await projectService.connectRepo(id, {
|
|
94
|
+
repoUrl: '',
|
|
95
|
+
baseBranch: branch,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
res.json({ project: updated });
|
|
99
|
+
} catch (err: any) {
|
|
100
|
+
log('GIT', `Init repo failed: ${err.message}`);
|
|
101
|
+
res.status(500).json({ error: `Failed to initialize repo: ${err.message}` });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// POST /api/projects/:id/git/disconnect — disconnect a git repo
|
|
106
|
+
router.post('/disconnect', async (req, res) => {
|
|
107
|
+
const { id } = req.params;
|
|
108
|
+
log('GIT', `POST /api/projects/${id}/git/disconnect`);
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const updated = await projectService.disconnectRepo(id);
|
|
112
|
+
res.json({ project: updated });
|
|
113
|
+
} catch (err: any) {
|
|
114
|
+
log('GIT', `Disconnect repo failed: ${err.message}`);
|
|
115
|
+
if (err.message === 'Project not found') {
|
|
116
|
+
res.status(404).json({ error: err.message });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
res.status(500).json({ error: `Failed to disconnect repo: ${err.message}` });
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// GET /api/projects/:id/git/status — get git repo status
|
|
124
|
+
router.get('/status', async (req, res) => {
|
|
125
|
+
const { id } = req.params;
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const project = await projectService.getById(id);
|
|
129
|
+
if (!project) {
|
|
130
|
+
res.status(404).json({ error: 'Project not found' });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const gitStatus = await workspaceService.getStatus(id);
|
|
135
|
+
res.json({
|
|
136
|
+
...gitStatus,
|
|
137
|
+
repoUrl: project.repoUrl,
|
|
138
|
+
githubInstallationId: project.githubInstallationId,
|
|
139
|
+
githubRepoFullName: project.githubRepoFullName,
|
|
140
|
+
baseBranch: project.baseBranch,
|
|
141
|
+
githubAppConfigured: githubAppService.isConfigured(),
|
|
142
|
+
});
|
|
143
|
+
} catch (err: any) {
|
|
144
|
+
log('GIT', `Get git status failed: ${err.message}`);
|
|
145
|
+
res.status(500).json({ error: `Failed to get git status: ${err.message}` });
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// POST /api/projects/:id/git/test — test GitHub App connection
|
|
150
|
+
router.post('/test', async (req, res) => {
|
|
151
|
+
const { id } = req.params;
|
|
152
|
+
log('GIT', `POST /api/projects/${id}/git/test`);
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
if (!githubAppService.isConfigured()) {
|
|
156
|
+
res.json({
|
|
157
|
+
configured: false,
|
|
158
|
+
error: 'GitHub App credentials not configured (GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY)',
|
|
159
|
+
});
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const installations = await githubAppService.listInstallations();
|
|
164
|
+
res.json({
|
|
165
|
+
configured: true,
|
|
166
|
+
installations: installations.map(i => ({
|
|
167
|
+
id: i.id,
|
|
168
|
+
account: i.account.login,
|
|
169
|
+
accountType: i.account.type,
|
|
170
|
+
})),
|
|
171
|
+
});
|
|
172
|
+
} catch (err: any) {
|
|
173
|
+
log('GIT', `Test GitHub App connection failed: ${err.message}`);
|
|
174
|
+
res.json({
|
|
175
|
+
configured: true,
|
|
176
|
+
error: `Connection test failed: ${err.message}`,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// GET /api/projects/:id/git/installations — list GitHub App installations
|
|
182
|
+
router.get('/installations', async (_req, res) => {
|
|
183
|
+
try {
|
|
184
|
+
if (!githubAppService.isConfigured()) {
|
|
185
|
+
res.json({ installations: [], configured: false });
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const installations = await githubAppService.listInstallations();
|
|
190
|
+
res.json({
|
|
191
|
+
configured: true,
|
|
192
|
+
installations: installations.map(i => ({
|
|
193
|
+
id: i.id,
|
|
194
|
+
account: i.account.login,
|
|
195
|
+
accountType: i.account.type,
|
|
196
|
+
})),
|
|
197
|
+
});
|
|
198
|
+
} catch (err: any) {
|
|
199
|
+
log('GIT', `List installations failed: ${err.message}`);
|
|
200
|
+
res.status(500).json({ error: `Failed to list installations: ${err.message}` });
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// GET /api/projects/:id/git/repos?installation_id=xxx — list repos for an installation
|
|
205
|
+
router.get('/repos', async (req, res) => {
|
|
206
|
+
const installationId = req.query.installation_id as string;
|
|
207
|
+
|
|
208
|
+
if (!installationId) {
|
|
209
|
+
res.status(400).json({ error: 'installation_id query parameter is required' });
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
const repos = await githubAppService.listInstallationRepos(installationId);
|
|
215
|
+
res.json({
|
|
216
|
+
repos: repos.map(r => ({
|
|
217
|
+
id: r.id,
|
|
218
|
+
fullName: r.full_name,
|
|
219
|
+
private: r.private,
|
|
220
|
+
defaultBranch: r.default_branch,
|
|
221
|
+
cloneUrl: r.clone_url,
|
|
222
|
+
})),
|
|
223
|
+
});
|
|
224
|
+
} catch (err: any) {
|
|
225
|
+
log('GIT', `List repos failed: ${err.message}`);
|
|
226
|
+
res.status(500).json({ error: `Failed to list repos: ${err.message}` });
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
return router;
|
|
231
|
+
};
|
package/templates/{product-system → assistkick-product-system}/packages/backend/src/routes/graph.ts
RENAMED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import {Router} from 'express';
|
|
6
6
|
import {readFile} from 'node:fs/promises';
|
|
7
7
|
import {join} from 'node:path';
|
|
8
|
-
import {readGraph} from '@
|
|
9
|
-
import {getDb} from '@
|
|
10
|
-
import {nodes} from '@
|
|
8
|
+
import {readGraph} from '@assistkick/shared/lib/graph.js';
|
|
9
|
+
import {getDb} from '@assistkick/shared/lib/db.js';
|
|
10
|
+
import {nodes} from '@assistkick/shared/db/schema.js';
|
|
11
11
|
import {eq} from 'drizzle-orm';
|
|
12
12
|
import matter from 'gray-matter';
|
|
13
13
|
import {log, paths} from '../services/init.js';
|
package/templates/{product-system → assistkick-product-system}/packages/backend/src/routes/kanban.ts
RENAMED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
import { Router } from 'express';
|
|
6
6
|
import { randomUUID } from 'node:crypto';
|
|
7
|
-
import { readGraph } from '@
|
|
8
|
-
import { loadKanban, getKanbanEntry, saveKanbanEntry } from '@
|
|
7
|
+
import { readGraph } from '@assistkick/shared/lib/graph.js';
|
|
8
|
+
import { loadKanban, getKanbanEntry, saveKanbanEntry } from '@assistkick/shared/lib/kanban.js';
|
|
9
9
|
import { log, pipeline } from '../services/init.js';
|
|
10
10
|
|
|
11
11
|
const router: Router = Router();
|
|
12
12
|
|
|
13
|
-
const VALID_COLUMNS = ['todo', 'in_progress', 'in_review', 'qa', 'done'];
|
|
13
|
+
const VALID_COLUMNS = ['backlog', 'todo', 'in_progress', 'in_review', 'qa', 'done'];
|
|
14
14
|
|
|
15
15
|
// GET /api/kanban
|
|
16
16
|
router.get('/', async (req, res) => {
|
|
@@ -19,20 +19,20 @@ router.get('/', async (req, res) => {
|
|
|
19
19
|
try {
|
|
20
20
|
const kanban = await loadKanban(projectId);
|
|
21
21
|
|
|
22
|
-
// Auto-add missing feature nodes to the
|
|
22
|
+
// Auto-add missing feature nodes to the Backlog column
|
|
23
23
|
const graph = await readGraph(projectId);
|
|
24
24
|
const featureNodes = graph.nodes.filter((n: any) => n.type === 'feature');
|
|
25
25
|
for (const node of featureNodes) {
|
|
26
26
|
if (!kanban[node.id]) {
|
|
27
27
|
const newEntry = {
|
|
28
|
-
column: '
|
|
28
|
+
column: 'backlog',
|
|
29
29
|
rejection_count: 0,
|
|
30
30
|
notes: [],
|
|
31
31
|
moved_at: node.created_at || new Date().toISOString(),
|
|
32
32
|
};
|
|
33
33
|
await saveKanbanEntry(node.id, newEntry, projectId);
|
|
34
34
|
kanban[node.id] = newEntry;
|
|
35
|
-
log('KANBAN', `Auto-added ${node.id} to
|
|
35
|
+
log('KANBAN', `Auto-added ${node.id} to backlog`);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline API routes — start/status/unblock dev pipeline + orchestrator.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Router } from 'express';
|
|
6
|
+
import { log, pipeline, orchestrator } from '../services/init.js';
|
|
7
|
+
|
|
8
|
+
const router: Router = Router();
|
|
9
|
+
|
|
10
|
+
// POST /api/kanban/:id/develop
|
|
11
|
+
router.post('/:id/develop', async (req, res) => {
|
|
12
|
+
const featureId = req.params.id;
|
|
13
|
+
try {
|
|
14
|
+
const result = await pipeline.start(featureId);
|
|
15
|
+
res.status(result.status).json(result.error ? { error: result.error } : { started: result.started, feature_id: result.feature_id });
|
|
16
|
+
} catch (err: any) {
|
|
17
|
+
log('DEVELOP', `UNEXPECTED ERROR: ${err.message}`);
|
|
18
|
+
res.status(500).json({ error: err.message });
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// GET /api/kanban/:id/pipeline
|
|
23
|
+
router.get('/:id/pipeline', async (req, res) => {
|
|
24
|
+
const featureId = req.params.id;
|
|
25
|
+
const result = await pipeline.getStatus(featureId);
|
|
26
|
+
res.json(result);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// POST /api/kanban/:id/resume
|
|
30
|
+
router.post('/:id/resume', async (req, res) => {
|
|
31
|
+
const featureId = req.params.id;
|
|
32
|
+
try {
|
|
33
|
+
const result = await pipeline.resume(featureId);
|
|
34
|
+
res.status(result.status).json(result.error ? { error: result.error } : { resumed: result.resumed, feature_id: result.feature_id });
|
|
35
|
+
} catch (err: any) {
|
|
36
|
+
log('RESUME', `UNEXPECTED ERROR: ${err.message}`);
|
|
37
|
+
res.status(500).json({ error: err.message });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// POST /api/kanban/:id/unblock
|
|
42
|
+
router.post('/:id/unblock', async (req, res) => {
|
|
43
|
+
const featureId = req.params.id;
|
|
44
|
+
try {
|
|
45
|
+
const result = await pipeline.unblock(featureId);
|
|
46
|
+
res.status(result.status).json(result.error ? { error: result.error } : { unblocked: result.unblocked, feature_id: result.feature_id });
|
|
47
|
+
} catch (err: any) {
|
|
48
|
+
log('UNBLOCK', `ERROR: ${err.message}`);
|
|
49
|
+
res.status(500).json({ error: err.message });
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// --- Orchestrator (Play All) endpoints ---
|
|
54
|
+
|
|
55
|
+
// POST /api/pipeline/play-all
|
|
56
|
+
router.post('/play-all', async (req, res) => {
|
|
57
|
+
const projectId = req.query.project_id as string | undefined;
|
|
58
|
+
try {
|
|
59
|
+
const result = orchestrator.startPlayAll(projectId);
|
|
60
|
+
const resolved = await result;
|
|
61
|
+
res.status(resolved.status).json(
|
|
62
|
+
resolved.error ? { error: resolved.error } : { started: resolved.started }
|
|
63
|
+
);
|
|
64
|
+
} catch (err: any) {
|
|
65
|
+
log('ORCHESTRATOR', `UNEXPECTED ERROR: ${err.message}`);
|
|
66
|
+
res.status(500).json({ error: err.message });
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// POST /api/pipeline/stop-all
|
|
71
|
+
router.post('/stop-all', (_req, res) => {
|
|
72
|
+
try {
|
|
73
|
+
const result = orchestrator.stopPlayAll();
|
|
74
|
+
res.status(result.status).json(
|
|
75
|
+
result.error ? { error: result.error } : { stopped: result.stopped }
|
|
76
|
+
);
|
|
77
|
+
} catch (err: any) {
|
|
78
|
+
log('ORCHESTRATOR', `UNEXPECTED ERROR: ${err.message}`);
|
|
79
|
+
res.status(500).json({ error: err.message });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// GET /api/pipeline/orchestrator-status
|
|
84
|
+
router.get('/orchestrator-status', (_req, res) => {
|
|
85
|
+
res.json(orchestrator.getStatus());
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export default router;
|