@sureshdsk/devflow-mcp 3.0.0 → 3.0.1
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +4 -4
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_global-error/page.js +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +2 -2
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +14 -13
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -13
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +5 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/projects/[id]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/projects/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/route.js +2 -2
- package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/specs/[name]/artifacts/[artifactType]/approve/route.js +2 -2
- package/.next/standalone/.next/server/app/api/specs/[name]/artifacts/[artifactType]/approve/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/specs/[name]/artifacts/[artifactType]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/specs/[name]/artifacts/[artifactType]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/specs/[name]/promote/route.js +2 -2
- package/.next/standalone/.next/server/app/api/specs/[name]/promote/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/specs/[name]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/specs/[name]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/specs/route.js +2 -2
- package/.next/standalone/.next/server/app/api/specs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[id]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/tasks/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tasks/route.js +2 -2
- package/.next/standalone/.next/server/app/api/tasks/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -14
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +5 -4
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page.js +2 -2
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/specs/[name]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/specs/[name]/page.js +2 -2
- package/.next/standalone/.next/server/app/specs/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/specs/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0be0eb8b._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__a9d478ee._.js → [root-of-the-server]__160c54ca._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17ac51e3._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bb083e9._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1dc1e944._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__22ecfa2c._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__13a93eb6._.js → [root-of-the-server]__64710c0d._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__a2b7e5f2._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__cf302bda._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__d85482cd._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__dfa21757._.js +3 -0
- package/.next/standalone/.next/server/chunks/_3f452afe._.js +2 -2
- package/.next/standalone/.next/server/chunks/src_db_index_ts_a71f50f0._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__023e2c69._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0a1a1435._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0c49a387._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1be1fc5f._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3a2f2efb._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4693399c._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__937c9212._.js → [root-of-the-server]__72a14301._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8064ca06._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8b786d48._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8c052461._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8d306066._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__9532fd59._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__a119dd75._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__7fb6ef14._.js → [root-of-the-server]__a57b312b._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__a80bd0ea._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__abe095b3._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__ad3bd783._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1e05fe0e._.js → [root-of-the-server]__ae9f05d6._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__c8781469._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__c8a25070._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__e8c1e595._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0ff3de19._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_01a5cd4b._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_05c6819f._.js +31 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_06c2c30a._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_09efe605._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_mermaid_dist_chunks_mermaid_core_ef601841._.js → node_modules_0a439e3b._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_3507b41a._.js → node_modules_0e73ad6c._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_0e7ff06d._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_0f73e25c._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_14cf9cea._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_19801f01._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_2235b8cf._.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_23096c6d._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_23db4cf7._.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_24381e95._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_24ca0eb6._.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_27525793._.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_mermaid_dist_chunks_mermaid_core_4cfa6360._.js → node_modules_27c20382._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_2c901b92._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_33b818b7._.js +45 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_345d7791._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_36185c24._.js +45 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_3ac7ce09._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_41b77cc7._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_ed317ff6._.js → node_modules_42acd8db._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_434aa5ec._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_54a9e72d._.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_54f1273a._.js +26 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_58d64491._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_5e012e3d._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_5ea9e4cf._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_5ecf8270._.js +26 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_611c99b5._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_d3-scale_src_e02ef77f._.js → node_modules_6629853d._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_6fe2661c._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_7fe65a84._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_860f971a._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_882f3743._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_8e047938._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_9268cdc4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_942541c9._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_9d52c0d6._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_@tanstack_query-core_build_modern_21ece5ea._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_ae6841d2._.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_ba280bb0._.js +31 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_bffdb8ec._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_c00f1821._.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_c142ba86._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_d1a47cde._.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_d9b454fe._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_dbe36b1d._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_ddbe26b7._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_e76b8bf2._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_e945b74d._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_fbd8a2ee._.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_katex_dist_katex_mjs_31d456ba._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_katex_dist_katex_mjs_e1edc676._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_lodash-es_33e24dce._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-QXUST7PY_mjs_159fba97._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-S3R3BYOJ_mjs_dbeeb277._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_mermaid_core_mjs_a11916de._.js +9 -0
- package/.next/standalone/.next/server/chunks/ssr/src_66a70595._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_components_kanban-board_tsx_7b875e8e._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +2 -2
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/AGENTS.md +13 -7
- package/.next/standalone/CONTRIBUTING.md +42 -26
- package/.next/standalone/README.md +166 -25
- package/.next/standalone/bin/devflow.js +12 -5
- package/.next/standalone/bun.lock +78 -24
- package/.next/standalone/devflow/project-config.json +4 -0
- package/.next/standalone/devflow/schemas/api-first/schema.yaml +39 -0
- package/.next/standalone/devflow/schemas/api-first/templates/api-design.md +41 -0
- package/.next/standalone/devflow/schemas/api-first/templates/db-design.md +28 -0
- package/.next/standalone/devflow/schemas/api-first/templates/final-architecture.md +31 -0
- package/.next/standalone/devflow/schemas/api-first/templates/proposal.md +22 -0
- package/.next/standalone/devflow/schemas/api-first/templates/tasks.md +16 -0
- package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/.approvals.json +1 -1
- package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/.meta.json +1 -1
- package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/design.md +11 -0
- package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/proposal.md +3 -0
- package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/tasks.md +34 -2
- package/.next/standalone/devflow/specs/precommit/.approvals.json +26 -0
- package/.next/standalone/devflow/specs/precommit/.meta.json +7 -0
- package/.next/standalone/devflow/specs/precommit/design.md +105 -0
- package/.next/standalone/devflow/specs/precommit/proposal.md +43 -0
- package/.next/standalone/devflow/specs/precommit/specs.md +89 -0
- package/.next/standalone/devflow/specs/precommit/tasks.md +283 -0
- package/.next/standalone/docs/custom-schemas.md +117 -0
- package/.next/standalone/docs/local-dev-guide.md +73 -0
- package/.next/standalone/drizzle.config.ts +7 -7
- package/.next/standalone/eslint.config.mjs +2 -2
- package/.next/standalone/instrumentation.ts +3 -5
- package/.next/standalone/next.config.ts +11 -2
- package/.next/standalone/node_modules/{sharp → libsql}/node_modules/detect-libc/package.json +4 -8
- package/.next/standalone/package-lock.json +5257 -2085
- package/.next/standalone/package.json +16 -7
- package/.next/standalone/postcss.config.mjs +1 -1
- package/.next/standalone/scripts/init-db.js +3 -5
- package/.next/standalone/scripts/init-db.test.js +6 -6
- package/.next/standalone/scripts/init-schema.js +22 -22
- package/.next/standalone/scripts/init-schema.test.js +45 -45
- package/.next/standalone/scripts/install-environments.js +27 -8
- package/.next/standalone/scripts/install-environments.test.js +19 -10
- package/.next/standalone/scripts/install-skills.js +104 -31
- package/.next/standalone/scripts/install-skills.test.js +6 -6
- package/.next/standalone/server.js +1 -1
- package/.next/standalone/src/app/api/agents/route.ts +2 -2
- package/.next/standalone/src/app/api/projects/[id]/route.ts +10 -19
- package/.next/standalone/src/app/api/projects/route.ts +4 -10
- package/.next/standalone/src/app/api/specs/[name]/artifacts/[artifactType]/approve/route.ts +8 -8
- package/.next/standalone/src/app/api/specs/[name]/artifacts/[artifactType]/route.ts +14 -14
- package/.next/standalone/src/app/api/specs/[name]/promote/route.ts +17 -23
- package/.next/standalone/src/app/api/specs/[name]/route.ts +34 -36
- package/.next/standalone/src/app/api/specs/route.ts +10 -10
- package/.next/standalone/src/app/api/tasks/[id]/route.ts +11 -33
- package/.next/standalone/src/app/api/tasks/route.ts +3 -6
- package/.next/standalone/src/app/globals.css +3 -3
- package/.next/standalone/src/app/layout.tsx +9 -5
- package/.next/standalone/src/app/page.tsx +1 -1
- package/.next/standalone/src/app/specs/[name]/page.tsx +26 -68
- package/.next/standalone/src/components/kanban-board.tsx +78 -157
- package/.next/standalone/src/components/kanban-column.tsx +10 -12
- package/.next/standalone/src/components/markdown-preview.tsx +36 -19
- package/.next/standalone/src/components/providers.tsx +20 -0
- package/.next/standalone/src/components/specs/artifact-dag-status.tsx +12 -14
- package/.next/standalone/src/components/specs/artifact-editor.tsx +55 -26
- package/.next/standalone/src/components/specs/spec-detail.tsx +48 -40
- package/.next/standalone/src/components/specs/spec-kanban-column.tsx +49 -68
- package/.next/standalone/src/components/specs/spec-modal.tsx +119 -83
- package/.next/standalone/src/components/task-card.tsx +34 -38
- package/.next/standalone/src/components/task-dialog.tsx +16 -31
- package/.next/standalone/src/components/ui/badge.tsx +12 -18
- package/.next/standalone/src/components/ui/button.tsx +23 -28
- package/.next/standalone/src/components/ui/card.tsx +42 -62
- package/.next/standalone/src/components/ui/dialog.tsx +17 -35
- package/.next/standalone/src/db/index.ts +10 -10
- package/.next/standalone/src/db/schema.ts +37 -37
- package/.next/standalone/src/hooks/use-queries.ts +81 -0
- package/.next/standalone/src/hooks/use-websocket.ts +74 -0
- package/.next/standalone/src/lib/schema.test.ts +37 -37
- package/.next/standalone/src/lib/schema.ts +77 -31
- package/.next/standalone/src/lib/specs-dir.ts +8 -8
- package/.next/standalone/src/lib/specs.ts +98 -92
- package/.next/standalone/src/lib/utils.ts +2 -2
- package/.next/standalone/src/mcp/server.ts +556 -349
- package/.next/standalone/src/mcp/websocket.ts +26 -23
- package/.next/standalone/src/schemas/backend-api/templates/proposal.md +6 -4
- package/.next/standalone/src/schemas/backend-api/templates/tasks.md +6 -0
- package/.next/standalone/src/schemas/data-engineering/templates/proposal.md +6 -4
- package/.next/standalone/src/schemas/data-engineering/templates/tasks.md +6 -0
- package/.next/standalone/src/schemas/devops-platform/templates/proposal.md +6 -4
- package/.next/standalone/src/schemas/devops-platform/templates/tasks.md +6 -0
- package/.next/standalone/src/schemas/frontend-product/templates/proposal.md +6 -4
- package/.next/standalone/src/schemas/frontend-product/templates/tasks.md +6 -0
- package/.next/standalone/src/schemas/spec-driven/templates/proposal.md +6 -4
- package/.next/standalone/src/schemas/spec-driven/templates/tasks.md +26 -0
- package/.next/standalone/src/websocket/server.ts +20 -18
- package/.next/standalone/tsconfig.json +3 -12
- package/.next/standalone/tsconfig.tsbuildinfo +1 -1
- package/.next/static/chunks/4f23f64d46848f57.js +1 -0
- package/.next/static/chunks/53081dcdcad4f31e.js +1 -0
- package/.next/static/chunks/{6a3d582315f1c214.js → 701cfcbb41e0ab47.js} +1 -1
- package/.next/static/chunks/ac4b6b4d5b7e486e.css +1 -0
- package/.next/static/chunks/d0309ea872db5d9f.js +1 -0
- package/.next/static/chunks/d4cf8893a018e965.js +1 -0
- package/.next/static/chunks/e6c0233269a4bd69.js +13 -0
- package/.next/static/chunks/{7e65cfa9841f66a5.js → e7d83ce855afe416.js} +2 -2
- package/.next/static/chunks/ee7035560fc9e5e9.js +1 -0
- package/.next/static/chunks/{turbopack-f4d3806ab575051d.js → turbopack-8b3b66a22a5e0fb4.js} +2 -2
- package/README.md +166 -25
- package/bin/devflow.js +12 -5
- package/drizzle.config.ts +7 -7
- package/next.config.ts +11 -2
- package/package.json +16 -7
- package/scripts/init-db.js +3 -5
- package/scripts/init-db.test.js +6 -6
- package/scripts/init-schema.js +22 -22
- package/scripts/init-schema.test.js +45 -45
- package/scripts/install-environments.js +27 -8
- package/scripts/install-environments.test.js +19 -10
- package/scripts/install-skills.js +104 -31
- package/scripts/install-skills.test.js +6 -6
- package/src/app/api/agents/route.ts +2 -2
- package/src/app/api/projects/[id]/route.ts +10 -19
- package/src/app/api/projects/route.ts +4 -10
- package/src/app/api/specs/[name]/artifacts/[artifactType]/approve/route.ts +8 -8
- package/src/app/api/specs/[name]/artifacts/[artifactType]/route.ts +14 -14
- package/src/app/api/specs/[name]/promote/route.ts +17 -23
- package/src/app/api/specs/[name]/route.ts +34 -36
- package/src/app/api/specs/route.ts +10 -10
- package/src/app/api/tasks/[id]/route.ts +11 -33
- package/src/app/api/tasks/route.ts +3 -6
- package/src/app/globals.css +3 -3
- package/src/app/layout.tsx +9 -5
- package/src/app/page.tsx +1 -1
- package/src/app/specs/[name]/page.tsx +26 -68
- package/src/components/kanban-board.tsx +78 -157
- package/src/components/kanban-column.tsx +10 -12
- package/src/components/markdown-preview.tsx +36 -19
- package/src/components/providers.tsx +20 -0
- package/src/components/specs/artifact-dag-status.tsx +12 -14
- package/src/components/specs/artifact-editor.tsx +55 -26
- package/src/components/specs/spec-detail.tsx +48 -40
- package/src/components/specs/spec-kanban-column.tsx +49 -68
- package/src/components/specs/spec-modal.tsx +119 -83
- package/src/components/task-card.tsx +34 -38
- package/src/components/task-dialog.tsx +16 -31
- package/src/components/ui/badge.tsx +12 -18
- package/src/components/ui/button.tsx +23 -28
- package/src/components/ui/card.tsx +42 -62
- package/src/components/ui/dialog.tsx +17 -35
- package/src/db/index.ts +10 -10
- package/src/db/schema.ts +37 -37
- package/src/hooks/use-queries.ts +81 -0
- package/src/hooks/use-websocket.ts +74 -0
- package/src/lib/schema.test.ts +37 -37
- package/src/lib/schema.ts +77 -31
- package/src/lib/specs-dir.ts +8 -8
- package/src/lib/specs.ts +98 -92
- package/src/lib/utils.ts +2 -2
- package/src/mcp/server.ts +556 -349
- package/src/mcp/websocket.ts +26 -23
- package/src/schemas/backend-api/templates/proposal.md +6 -4
- package/src/schemas/backend-api/templates/tasks.md +6 -0
- package/src/schemas/data-engineering/templates/proposal.md +6 -4
- package/src/schemas/data-engineering/templates/tasks.md +6 -0
- package/src/schemas/devops-platform/templates/proposal.md +6 -4
- package/src/schemas/devops-platform/templates/tasks.md +6 -0
- package/src/schemas/frontend-product/templates/proposal.md +6 -4
- package/src/schemas/frontend-product/templates/tasks.md +6 -0
- package/src/schemas/spec-driven/templates/proposal.md +6 -4
- package/src/schemas/spec-driven/templates/tasks.md +26 -0
- package/src/types/bun-sqlite.d.ts +1 -1
- package/src/websocket/server.ts +20 -18
- package/tsconfig.json +3 -12
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1be4e4b6._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__492a4a24._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__67c59ae1._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__6cc7aecd._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__83a77b07._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__88d91cb5._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9e095e8._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__b367d327._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__eb413bbc._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0b8c072a._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12b2191f._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15316462._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19c9c409._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19e5e22f._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__25b5ccb3._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__2f78c3da._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3160b3f4._.js +0 -9
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__319559be._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__34f7cbcb._.js +0 -31
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3abab94b._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3b3d8930._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4250799b._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4c29cbc3._.js +0 -26
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4e0bb6eb._.js +0 -9
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__5678d2e3._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__673445e0._.js +0 -31
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__934de06b._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__9b6c6f09._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__a1b83a98._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__b00a15c5._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__b8567be3._.js +0 -26
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__ce64536e._.js +0 -45
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__e96d33d2._.js +0 -45
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__fd7ec054._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_16a3f9e7._.js +0 -17
- package/.next/standalone/.next/server/chunks/ssr/node_modules_45bce0e1._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_5e5a372d._.js +0 -17
- package/.next/standalone/.next/server/chunks/ssr/node_modules_6ece6f1e._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_d173e749._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_d3-shape_src_arc_fb1ac087.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_1f73a830._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_663ac803._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-FMBD7UC4_mjs_4f485529._.js +0 -17
- package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-TZMSLE5B_mjs_8436a62a._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_f78d2dc4._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/src_app_layout_tsx_cc8184fa._.js +0 -3
- package/.next/standalone/devflow/specs/add-default-schema-template-selection/.approvals.json +0 -26
- package/.next/standalone/devflow/specs/add-default-schema-template-selection/.meta.json +0 -8
- package/.next/standalone/devflow/specs/add-default-schema-template-selection/design.md +0 -126
- package/.next/standalone/devflow/specs/add-default-schema-template-selection/proposal.md +0 -65
- package/.next/standalone/devflow/specs/add-default-schema-template-selection/specs.md +0 -107
- package/.next/standalone/devflow/specs/add-default-schema-template-selection/tasks.md +0 -235
- package/.next/standalone/devflow/specs/test-no-project/.approvals.json +0 -17
- package/.next/standalone/devflow/specs/test-no-project/.meta.json +0 -6
- package/.next/standalone/devflow/specs/ui-cleanup/.approvals.json +0 -29
- package/.next/standalone/devflow/specs/ui-cleanup/.meta.json +0 -6
- package/.next/standalone/devflow/specs/ui-cleanup/design.md +0 -49
- package/.next/standalone/devflow/specs/ui-cleanup/proposal.md +0 -34
- package/.next/standalone/devflow/specs/ui-cleanup/specs.md +0 -55
- package/.next/standalone/devflow/specs/ui-cleanup/tasks.md +0 -28
- package/.next/standalone/node_modules/@img/colour/color.cjs +0 -1594
- package/.next/standalone/node_modules/@img/colour/index.cjs +0 -1
- package/.next/standalone/node_modules/@img/colour/package.json +0 -45
- package/.next/standalone/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node +0 -0
- package/.next/standalone/node_modules/@img/sharp-darwin-arm64/package.json +0 -40
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/README.md +0 -46
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/lib/glib-2.0/include/glibconfig.h +0 -220
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/lib/index.js +0 -1
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.8.17.3.dylib +0 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/package.json +0 -36
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/versions.json +0 -30
- package/.next/standalone/node_modules/buffer-from/index.js +0 -72
- package/.next/standalone/node_modules/buffer-from/package.json +0 -19
- package/.next/standalone/node_modules/sharp/lib/channel.js +0 -177
- package/.next/standalone/node_modules/sharp/lib/colour.js +0 -195
- package/.next/standalone/node_modules/sharp/lib/composite.js +0 -212
- package/.next/standalone/node_modules/sharp/lib/constructor.js +0 -499
- package/.next/standalone/node_modules/sharp/lib/index.js +0 -16
- package/.next/standalone/node_modules/sharp/lib/input.js +0 -809
- package/.next/standalone/node_modules/sharp/lib/is.js +0 -143
- package/.next/standalone/node_modules/sharp/lib/libvips.js +0 -207
- package/.next/standalone/node_modules/sharp/lib/operation.js +0 -1016
- package/.next/standalone/node_modules/sharp/lib/output.js +0 -1666
- package/.next/standalone/node_modules/sharp/lib/resize.js +0 -595
- package/.next/standalone/node_modules/sharp/lib/sharp.js +0 -121
- package/.next/standalone/node_modules/sharp/lib/utility.js +0 -291
- package/.next/standalone/node_modules/sharp/node_modules/detect-libc/lib/detect-libc.js +0 -313
- package/.next/standalone/node_modules/sharp/node_modules/detect-libc/lib/elf.js +0 -39
- package/.next/standalone/node_modules/sharp/node_modules/detect-libc/lib/filesystem.js +0 -51
- package/.next/standalone/node_modules/sharp/node_modules/detect-libc/lib/process.js +0 -24
- package/.next/standalone/node_modules/sharp/node_modules/semver/classes/comparator.js +0 -143
- package/.next/standalone/node_modules/sharp/node_modules/semver/classes/range.js +0 -557
- package/.next/standalone/node_modules/sharp/node_modules/semver/classes/semver.js +0 -333
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/cmp.js +0 -54
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/coerce.js +0 -62
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/compare.js +0 -7
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/eq.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/gt.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/gte.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/lt.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/lte.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/neq.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/parse.js +0 -18
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/satisfies.js +0 -12
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/constants.js +0 -37
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/debug.js +0 -11
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/identifiers.js +0 -29
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/lrucache.js +0 -42
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/parse-options.js +0 -17
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/re.js +0 -223
- package/.next/standalone/node_modules/sharp/node_modules/semver/package.json +0 -78
- package/.next/standalone/node_modules/sharp/package.json +0 -202
- package/.next/standalone/node_modules/source-map/lib/array-set.js +0 -121
- package/.next/standalone/node_modules/source-map/lib/base64-vlq.js +0 -140
- package/.next/standalone/node_modules/source-map/lib/base64.js +0 -67
- package/.next/standalone/node_modules/source-map/lib/binary-search.js +0 -111
- package/.next/standalone/node_modules/source-map/lib/mapping-list.js +0 -79
- package/.next/standalone/node_modules/source-map/lib/quick-sort.js +0 -114
- package/.next/standalone/node_modules/source-map/lib/source-map-consumer.js +0 -1145
- package/.next/standalone/node_modules/source-map/lib/source-map-generator.js +0 -425
- package/.next/standalone/node_modules/source-map/lib/source-node.js +0 -413
- package/.next/standalone/node_modules/source-map/lib/util.js +0 -488
- package/.next/standalone/node_modules/source-map/package.json +0 -73
- package/.next/standalone/node_modules/source-map/source-map.js +0 -8
- package/.next/standalone/node_modules/source-map-support/LICENSE.md +0 -21
- package/.next/standalone/node_modules/source-map-support/README.md +0 -284
- package/.next/standalone/node_modules/source-map-support/browser-source-map-support.js +0 -114
- package/.next/standalone/node_modules/source-map-support/package.json +0 -31
- package/.next/standalone/node_modules/source-map-support/register-hook-require.js +0 -1
- package/.next/standalone/node_modules/source-map-support/register.js +0 -1
- package/.next/standalone/node_modules/source-map-support/source-map-support.js +0 -625
- package/.next/standalone/node_modules/typescript/lib/_tsc.js +0 -133818
- package/.next/standalone/node_modules/typescript/lib/_tsserver.js +0 -659
- package/.next/standalone/node_modules/typescript/lib/_typingsInstaller.js +0 -222
- package/.next/standalone/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/de/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/es/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/it/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/tsc.js +0 -8
- package/.next/standalone/node_modules/typescript/lib/tsserver.js +0 -8
- package/.next/standalone/node_modules/typescript/lib/tsserverlibrary.js +0 -21
- package/.next/standalone/node_modules/typescript/lib/typesMap.json +0 -497
- package/.next/standalone/node_modules/typescript/lib/typescript.js +0 -200276
- package/.next/standalone/node_modules/typescript/lib/typingsInstaller.js +0 -8
- package/.next/standalone/node_modules/typescript/lib/watchGuard.js +0 -53
- package/.next/standalone/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +0 -2122
- package/.next/standalone/node_modules/typescript/package.json +0 -120
- package/.next/standalone/src/components/ui/collapsible.tsx +0 -12
- package/.next/standalone/src/components/ui/sheet.tsx +0 -130
- package/.next/standalone/src/components/ui/tabs.tsx +0 -58
- package/.next/static/chunks/0177331b8adf7346.js +0 -7
- package/.next/static/chunks/06af74e2f3e207c5.js +0 -7
- package/.next/static/chunks/1748d5cd2443723b.css +0 -1
- package/.next/static/chunks/7ae917cb100be2b9.js +0 -7
- package/.next/static/chunks/7c4b901b394c3a8c.js +0 -7
- package/src/components/ui/collapsible.tsx +0 -12
- package/src/components/ui/sheet.tsx +0 -130
- package/src/components/ui/tabs.tsx +0 -58
- /package/.next/standalone/node_modules/{detect-libc → libsql/node_modules/detect-libc}/lib/detect-libc.js +0 -0
- /package/.next/standalone/node_modules/{detect-libc → libsql/node_modules/detect-libc}/lib/filesystem.js +0 -0
- /package/.next/standalone/node_modules/{detect-libc → libsql/node_modules/detect-libc}/lib/process.js +0 -0
- /package/.next/static/{5YFrdIQd1UU2IxLxekrU9 → Ql6qo0GYLL23WRu6ec4N5}/_buildManifest.js +0 -0
- /package/.next/static/{5YFrdIQd1UU2IxLxekrU9 → Ql6qo0GYLL23WRu6ec4N5}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{5YFrdIQd1UU2IxLxekrU9 → Ql6qo0GYLL23WRu6ec4N5}/_ssgManifest.js +0 -0
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Server } from
|
|
3
|
-
import { StdioServerTransport } from
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import { randomUUID } from "crypto";
|
|
11
|
-
import { broadcastUpdate } from "./websocket.js";
|
|
12
|
-
import path from "path";
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { getDb, schema } from '../db/index.js';
|
|
6
|
+
import { eq, desc, and } from 'drizzle-orm';
|
|
7
|
+
import { randomUUID } from 'crypto';
|
|
8
|
+
import { broadcastUpdate } from './websocket.js';
|
|
9
|
+
import path from 'path';
|
|
13
10
|
|
|
14
11
|
function slugify(str: string): string {
|
|
15
12
|
return str
|
|
16
13
|
.toLowerCase()
|
|
17
|
-
.replace(/[^a-z0-9]+/g,
|
|
18
|
-
.replace(/^-+|-+$/g,
|
|
14
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
15
|
+
.replace(/^-+|-+$/g, '');
|
|
19
16
|
}
|
|
20
17
|
|
|
21
18
|
function defaultProjectName(): string {
|
|
22
19
|
return slugify(path.basename(process.cwd()));
|
|
23
20
|
}
|
|
21
|
+
import { listSchemas, createSchema } from '../lib/schema.js';
|
|
22
|
+
import { getSpecsDir } from '../lib/specs-dir.js';
|
|
24
23
|
import {
|
|
25
24
|
listSpecs,
|
|
26
25
|
getSpec,
|
|
@@ -36,18 +35,18 @@ import {
|
|
|
36
35
|
getArtifactTemplate,
|
|
37
36
|
fillTaskSummary,
|
|
38
37
|
updateTaskBodyInSpec,
|
|
39
|
-
} from
|
|
38
|
+
} from '../lib/specs.js';
|
|
40
39
|
|
|
41
40
|
const server = new Server(
|
|
42
41
|
{
|
|
43
|
-
name:
|
|
44
|
-
version:
|
|
42
|
+
name: 'devflow-mcp',
|
|
43
|
+
version: '2.0.0',
|
|
45
44
|
},
|
|
46
45
|
{
|
|
47
46
|
capabilities: {
|
|
48
47
|
tools: {},
|
|
49
48
|
},
|
|
50
|
-
}
|
|
49
|
+
},
|
|
51
50
|
);
|
|
52
51
|
|
|
53
52
|
// Tool definitions
|
|
@@ -56,411 +55,511 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
56
55
|
tools: [
|
|
57
56
|
// Project Management
|
|
58
57
|
{
|
|
59
|
-
name:
|
|
60
|
-
description:
|
|
58
|
+
name: 'list_projects',
|
|
59
|
+
description: 'List all projects',
|
|
61
60
|
inputSchema: {
|
|
62
|
-
type:
|
|
61
|
+
type: 'object',
|
|
63
62
|
properties: {
|
|
64
63
|
status: {
|
|
65
|
-
type:
|
|
66
|
-
enum: [
|
|
67
|
-
description:
|
|
64
|
+
type: 'string',
|
|
65
|
+
enum: ['active', 'archived', 'completed'],
|
|
66
|
+
description: 'Filter by project status (optional)',
|
|
68
67
|
},
|
|
69
68
|
},
|
|
70
69
|
},
|
|
71
70
|
},
|
|
72
71
|
{
|
|
73
|
-
name:
|
|
74
|
-
description:
|
|
72
|
+
name: 'create_project',
|
|
73
|
+
description:
|
|
74
|
+
'Create a new project. If name is omitted, defaults to the current directory name (slugified).',
|
|
75
75
|
inputSchema: {
|
|
76
|
-
type:
|
|
76
|
+
type: 'object',
|
|
77
77
|
properties: {
|
|
78
|
-
name: {
|
|
79
|
-
|
|
78
|
+
name: {
|
|
79
|
+
type: 'string',
|
|
80
|
+
description: 'Project name (optional — defaults to current directory name)',
|
|
81
|
+
},
|
|
82
|
+
description: { type: 'string', description: 'Project description' },
|
|
80
83
|
},
|
|
81
84
|
},
|
|
82
85
|
},
|
|
83
86
|
{
|
|
84
|
-
name:
|
|
85
|
-
description:
|
|
87
|
+
name: 'get_project',
|
|
88
|
+
description: 'Get project details with all tasks',
|
|
86
89
|
inputSchema: {
|
|
87
|
-
type:
|
|
90
|
+
type: 'object',
|
|
88
91
|
properties: {
|
|
89
|
-
projectId: { type:
|
|
92
|
+
projectId: { type: 'string', description: 'Project ID' },
|
|
90
93
|
},
|
|
91
|
-
required: [
|
|
94
|
+
required: ['projectId'],
|
|
92
95
|
},
|
|
93
96
|
},
|
|
94
97
|
{
|
|
95
|
-
name:
|
|
96
|
-
description:
|
|
98
|
+
name: 'update_project',
|
|
99
|
+
description: 'Update project details',
|
|
97
100
|
inputSchema: {
|
|
98
|
-
type:
|
|
101
|
+
type: 'object',
|
|
99
102
|
properties: {
|
|
100
|
-
projectId: { type:
|
|
101
|
-
name: { type:
|
|
102
|
-
description: { type:
|
|
103
|
+
projectId: { type: 'string', description: 'Project ID' },
|
|
104
|
+
name: { type: 'string', description: 'New project name' },
|
|
105
|
+
description: { type: 'string', description: 'New description' },
|
|
103
106
|
status: {
|
|
104
|
-
type:
|
|
105
|
-
enum: [
|
|
106
|
-
description:
|
|
107
|
+
type: 'string',
|
|
108
|
+
enum: ['active', 'archived', 'completed'],
|
|
109
|
+
description: 'New status',
|
|
107
110
|
},
|
|
108
111
|
},
|
|
109
|
-
required: [
|
|
112
|
+
required: ['projectId'],
|
|
110
113
|
},
|
|
111
114
|
},
|
|
112
115
|
{
|
|
113
|
-
name:
|
|
114
|
-
description:
|
|
116
|
+
name: 'get_or_create_project',
|
|
117
|
+
description:
|
|
118
|
+
"Get an existing project by name or create it if it doesn't exist. If name is omitted, defaults to the current directory name (slugified). Use the project directory name as a default if no project name is specified.",
|
|
115
119
|
inputSchema: {
|
|
116
|
-
type:
|
|
120
|
+
type: 'object',
|
|
117
121
|
properties: {
|
|
118
|
-
name: {
|
|
119
|
-
|
|
122
|
+
name: {
|
|
123
|
+
type: 'string',
|
|
124
|
+
description: 'Project name (optional — defaults to current directory name)',
|
|
125
|
+
},
|
|
126
|
+
description: { type: 'string', description: 'Description (used only if creating)' },
|
|
120
127
|
},
|
|
121
128
|
},
|
|
122
129
|
},
|
|
123
130
|
// Task Management
|
|
124
131
|
{
|
|
125
|
-
name:
|
|
126
|
-
description:
|
|
132
|
+
name: 'list_tasks',
|
|
133
|
+
description: 'List tasks with optional filters',
|
|
127
134
|
inputSchema: {
|
|
128
|
-
type:
|
|
135
|
+
type: 'object',
|
|
129
136
|
properties: {
|
|
130
|
-
projectId: { type:
|
|
131
|
-
specName: { type:
|
|
137
|
+
projectId: { type: 'string', description: 'Filter by project ID' },
|
|
138
|
+
specName: { type: 'string', description: 'Filter by spec name' },
|
|
132
139
|
status: {
|
|
133
|
-
type:
|
|
134
|
-
enum: [
|
|
135
|
-
description:
|
|
140
|
+
type: 'string',
|
|
141
|
+
enum: ['backlog', 'todo', 'in_progress', 'interrupted', 'done'],
|
|
142
|
+
description: 'Filter by status',
|
|
136
143
|
},
|
|
137
|
-
assignedAgent: { type:
|
|
144
|
+
assignedAgent: { type: 'string', description: 'Filter by assigned agent' },
|
|
138
145
|
},
|
|
139
146
|
},
|
|
140
147
|
},
|
|
141
148
|
{
|
|
142
|
-
name:
|
|
143
|
-
description:
|
|
149
|
+
name: 'get_task',
|
|
150
|
+
description: 'Get details of a specific task',
|
|
144
151
|
inputSchema: {
|
|
145
|
-
type:
|
|
152
|
+
type: 'object',
|
|
146
153
|
properties: {
|
|
147
|
-
taskId: { type:
|
|
154
|
+
taskId: { type: 'string', description: 'Task ID' },
|
|
148
155
|
},
|
|
149
|
-
required: [
|
|
156
|
+
required: ['taskId'],
|
|
150
157
|
},
|
|
151
158
|
},
|
|
152
159
|
{
|
|
153
|
-
name:
|
|
154
|
-
description:
|
|
160
|
+
name: 'create_task',
|
|
161
|
+
description:
|
|
162
|
+
'Create a new task. Can auto-create project if projectName is provided instead of projectId.',
|
|
155
163
|
inputSchema: {
|
|
156
|
-
type:
|
|
164
|
+
type: 'object',
|
|
157
165
|
properties: {
|
|
158
|
-
title: { type:
|
|
159
|
-
body: { type:
|
|
160
|
-
description: {
|
|
161
|
-
|
|
166
|
+
title: { type: 'string', description: 'Task title' },
|
|
167
|
+
body: { type: 'string', description: 'Task body (markdown)' },
|
|
168
|
+
description: {
|
|
169
|
+
type: 'string',
|
|
170
|
+
description:
|
|
171
|
+
'Task description (legacy — auto-composed into body if body not provided)',
|
|
172
|
+
},
|
|
173
|
+
context: {
|
|
174
|
+
type: 'string',
|
|
175
|
+
description:
|
|
176
|
+
'Additional context (legacy — auto-composed into body if body not provided)',
|
|
177
|
+
},
|
|
162
178
|
priority: {
|
|
163
|
-
type:
|
|
164
|
-
enum: [
|
|
165
|
-
description:
|
|
179
|
+
type: 'string',
|
|
180
|
+
enum: ['low', 'medium', 'high', 'urgent'],
|
|
181
|
+
description: 'Task priority',
|
|
166
182
|
},
|
|
167
183
|
status: {
|
|
168
|
-
type:
|
|
169
|
-
enum: [
|
|
170
|
-
description:
|
|
184
|
+
type: 'string',
|
|
185
|
+
enum: ['backlog', 'todo', 'in_progress', 'done'],
|
|
186
|
+
description: 'Initial status (defaults to backlog)',
|
|
171
187
|
},
|
|
172
|
-
projectId: { type:
|
|
188
|
+
projectId: { type: 'string', description: 'Project ID' },
|
|
173
189
|
projectName: {
|
|
174
|
-
type:
|
|
190
|
+
type: 'string',
|
|
175
191
|
description: "Project name — auto-creates the project if it doesn't exist",
|
|
176
192
|
},
|
|
177
|
-
specName: { type:
|
|
193
|
+
specName: { type: 'string', description: 'Spec name to link this task to' },
|
|
178
194
|
},
|
|
179
|
-
required: [
|
|
195
|
+
required: ['title'],
|
|
180
196
|
},
|
|
181
197
|
},
|
|
182
198
|
{
|
|
183
|
-
name:
|
|
184
|
-
description:
|
|
199
|
+
name: 'create_tasks_bulk',
|
|
200
|
+
description: 'Create multiple tasks at once',
|
|
185
201
|
inputSchema: {
|
|
186
|
-
type:
|
|
202
|
+
type: 'object',
|
|
187
203
|
properties: {
|
|
188
|
-
projectId: { type:
|
|
189
|
-
projectName: { type:
|
|
190
|
-
specName: { type:
|
|
204
|
+
projectId: { type: 'string', description: 'Project ID for all tasks' },
|
|
205
|
+
projectName: { type: 'string', description: 'Project name (auto-creates if needed)' },
|
|
206
|
+
specName: { type: 'string', description: 'Spec name to link tasks to' },
|
|
191
207
|
tasks: {
|
|
192
|
-
type:
|
|
193
|
-
description:
|
|
208
|
+
type: 'array',
|
|
209
|
+
description: 'Array of task objects',
|
|
194
210
|
items: {
|
|
195
|
-
type:
|
|
211
|
+
type: 'object',
|
|
196
212
|
properties: {
|
|
197
|
-
title: { type:
|
|
198
|
-
body: { type:
|
|
199
|
-
description: {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
213
|
+
title: { type: 'string' },
|
|
214
|
+
body: { type: 'string', description: 'Task body (markdown)' },
|
|
215
|
+
description: {
|
|
216
|
+
type: 'string',
|
|
217
|
+
description: 'Legacy — auto-composed into body if body not provided',
|
|
218
|
+
},
|
|
219
|
+
context: {
|
|
220
|
+
type: 'string',
|
|
221
|
+
description: 'Legacy — auto-composed into body if body not provided',
|
|
222
|
+
},
|
|
223
|
+
priority: { type: 'string', enum: ['low', 'medium', 'high', 'urgent'] },
|
|
224
|
+
status: { type: 'string', enum: ['backlog', 'todo', 'in_progress', 'done'] },
|
|
203
225
|
},
|
|
204
|
-
required: [
|
|
226
|
+
required: ['title'],
|
|
205
227
|
},
|
|
206
228
|
},
|
|
207
229
|
},
|
|
208
|
-
required: [
|
|
230
|
+
required: ['tasks'],
|
|
209
231
|
},
|
|
210
232
|
},
|
|
211
233
|
{
|
|
212
|
-
name:
|
|
234
|
+
name: 'update_task',
|
|
213
235
|
description: "Update a task's details or status",
|
|
214
236
|
inputSchema: {
|
|
215
|
-
type:
|
|
237
|
+
type: 'object',
|
|
216
238
|
properties: {
|
|
217
|
-
taskId: { type:
|
|
218
|
-
title: { type:
|
|
219
|
-
body: { type:
|
|
239
|
+
taskId: { type: 'string', description: 'Task ID' },
|
|
240
|
+
title: { type: 'string', description: 'New title' },
|
|
241
|
+
body: { type: 'string', description: 'New task body (markdown)' },
|
|
220
242
|
status: {
|
|
221
|
-
type:
|
|
222
|
-
enum: [
|
|
223
|
-
description:
|
|
243
|
+
type: 'string',
|
|
244
|
+
enum: ['backlog', 'todo', 'in_progress', 'interrupted', 'done'],
|
|
245
|
+
description: 'New status',
|
|
224
246
|
},
|
|
225
247
|
priority: {
|
|
226
|
-
type:
|
|
227
|
-
enum: [
|
|
228
|
-
description:
|
|
248
|
+
type: 'string',
|
|
249
|
+
enum: ['low', 'medium', 'high', 'urgent'],
|
|
250
|
+
description: 'New priority',
|
|
229
251
|
},
|
|
230
|
-
specName: { type:
|
|
252
|
+
specName: { type: 'string', description: 'Link or re-link to a spec' },
|
|
231
253
|
},
|
|
232
|
-
required: [
|
|
254
|
+
required: ['taskId'],
|
|
233
255
|
},
|
|
234
256
|
},
|
|
235
257
|
// Agent Workflow
|
|
236
258
|
{
|
|
237
|
-
name:
|
|
238
|
-
description:
|
|
259
|
+
name: 'check_in',
|
|
260
|
+
description: 'Agent checks in to a task (sets status to in_progress, assigns agent)',
|
|
239
261
|
inputSchema: {
|
|
240
|
-
type:
|
|
262
|
+
type: 'object',
|
|
241
263
|
properties: {
|
|
242
|
-
taskId: { type:
|
|
243
|
-
agentName: { type:
|
|
244
|
-
executionPlan: { type:
|
|
264
|
+
taskId: { type: 'string', description: 'Task ID to check in to' },
|
|
265
|
+
agentName: { type: 'string', description: 'Name/identifier of the agent' },
|
|
266
|
+
executionPlan: { type: 'string', description: "Agent's plan for completing the task" },
|
|
245
267
|
},
|
|
246
|
-
required: [
|
|
268
|
+
required: ['taskId', 'agentName'],
|
|
247
269
|
},
|
|
248
270
|
},
|
|
249
271
|
{
|
|
250
|
-
name:
|
|
251
|
-
description:
|
|
272
|
+
name: 'check_out',
|
|
273
|
+
description: 'Agent checks out of a task (sets status to done)',
|
|
252
274
|
inputSchema: {
|
|
253
|
-
type:
|
|
275
|
+
type: 'object',
|
|
254
276
|
properties: {
|
|
255
|
-
taskId: { type:
|
|
256
|
-
agentName: { type:
|
|
277
|
+
taskId: { type: 'string', description: 'Task ID to check out of' },
|
|
278
|
+
agentName: { type: 'string', description: 'Name/identifier of the agent' },
|
|
257
279
|
taskSummary: {
|
|
258
|
-
type:
|
|
259
|
-
description:
|
|
280
|
+
type: 'object',
|
|
281
|
+
description: 'Structured summary of what was accomplished',
|
|
260
282
|
properties: {
|
|
261
|
-
whatWasDone: { type:
|
|
262
|
-
filesChanged: { type:
|
|
263
|
-
issuesEncountered: { type:
|
|
264
|
-
followUps: { type:
|
|
283
|
+
whatWasDone: { type: 'string', description: 'What was accomplished' },
|
|
284
|
+
filesChanged: { type: 'string', description: 'Files changed (optional)' },
|
|
285
|
+
issuesEncountered: { type: 'string', description: 'Issues encountered (optional)' },
|
|
286
|
+
followUps: { type: 'string', description: 'Follow-up items (optional)' },
|
|
265
287
|
},
|
|
266
|
-
required: [
|
|
288
|
+
required: ['whatWasDone'],
|
|
267
289
|
},
|
|
268
290
|
},
|
|
269
|
-
required: [
|
|
291
|
+
required: ['taskId', 'agentName'],
|
|
270
292
|
},
|
|
271
293
|
},
|
|
272
294
|
{
|
|
273
|
-
name:
|
|
274
|
-
description:
|
|
295
|
+
name: 'log_activity',
|
|
296
|
+
description: 'Log an activity or comment on a task',
|
|
275
297
|
inputSchema: {
|
|
276
|
-
type:
|
|
298
|
+
type: 'object',
|
|
277
299
|
properties: {
|
|
278
|
-
taskId: { type:
|
|
279
|
-
agentName: { type:
|
|
300
|
+
taskId: { type: 'string', description: 'Task ID' },
|
|
301
|
+
agentName: { type: 'string', description: 'Name/identifier of the agent' },
|
|
280
302
|
action: {
|
|
281
|
-
type:
|
|
282
|
-
enum: [
|
|
283
|
-
description:
|
|
303
|
+
type: 'string',
|
|
304
|
+
enum: ['check_in', 'check_out', 'update', 'comment'],
|
|
305
|
+
description: 'Type of action',
|
|
284
306
|
},
|
|
285
|
-
details: { type:
|
|
307
|
+
details: { type: 'string', description: 'Activity details or comment' },
|
|
286
308
|
},
|
|
287
|
-
required: [
|
|
309
|
+
required: ['taskId', 'agentName', 'action'],
|
|
288
310
|
},
|
|
289
311
|
},
|
|
290
312
|
{
|
|
291
|
-
name:
|
|
292
|
-
description:
|
|
313
|
+
name: 'get_activity_log',
|
|
314
|
+
description: 'Get activity log for a task',
|
|
293
315
|
inputSchema: {
|
|
294
|
-
type:
|
|
316
|
+
type: 'object',
|
|
295
317
|
properties: {
|
|
296
|
-
taskId: { type:
|
|
297
|
-
limit: { type:
|
|
318
|
+
taskId: { type: 'string', description: 'Task ID' },
|
|
319
|
+
limit: { type: 'number', description: 'Max number of entries (default 50)' },
|
|
298
320
|
},
|
|
299
|
-
required: [
|
|
321
|
+
required: ['taskId'],
|
|
300
322
|
},
|
|
301
323
|
},
|
|
302
324
|
// Spec Management
|
|
303
325
|
{
|
|
304
|
-
name:
|
|
305
|
-
description:
|
|
326
|
+
name: 'list_specs',
|
|
327
|
+
description: 'List all specs in the devflow/specs directory',
|
|
306
328
|
inputSchema: {
|
|
307
|
-
type:
|
|
329
|
+
type: 'object',
|
|
308
330
|
properties: {
|
|
309
|
-
projectId: { type:
|
|
331
|
+
projectId: { type: 'string', description: 'Filter by project ID (optional)' },
|
|
310
332
|
},
|
|
311
333
|
},
|
|
312
334
|
},
|
|
313
335
|
{
|
|
314
|
-
name:
|
|
315
|
-
description:
|
|
336
|
+
name: 'create_spec',
|
|
337
|
+
description:
|
|
338
|
+
'Create a new spec folder with meta and approvals files. Run list_projects or get_or_create_project first to get a projectId.',
|
|
316
339
|
inputSchema: {
|
|
317
|
-
type:
|
|
340
|
+
type: 'object',
|
|
318
341
|
properties: {
|
|
319
342
|
name: {
|
|
320
|
-
type:
|
|
321
|
-
description:
|
|
343
|
+
type: 'string',
|
|
344
|
+
description: 'Spec folder name (slug, e.g. add-oauth)',
|
|
322
345
|
},
|
|
323
|
-
title: { type:
|
|
324
|
-
projectId: {
|
|
325
|
-
|
|
346
|
+
title: { type: 'string', description: 'Human-readable title' },
|
|
347
|
+
projectId: {
|
|
348
|
+
type: 'string',
|
|
349
|
+
description:
|
|
350
|
+
'Project ID to link to — run list_projects or get_or_create_project first',
|
|
351
|
+
},
|
|
352
|
+
description: { type: 'string', description: 'Optional description' },
|
|
326
353
|
schema: {
|
|
327
|
-
type:
|
|
328
|
-
description:
|
|
354
|
+
type: 'string',
|
|
355
|
+
description: 'Schema name (defaults to spec-driven)',
|
|
329
356
|
},
|
|
330
357
|
},
|
|
331
|
-
required: [
|
|
358
|
+
required: ['name', 'title', 'projectId'],
|
|
332
359
|
},
|
|
333
360
|
},
|
|
334
361
|
{
|
|
335
|
-
name:
|
|
336
|
-
description:
|
|
362
|
+
name: 'get_spec',
|
|
363
|
+
description: 'Get full spec details including artifact contents and statuses',
|
|
337
364
|
inputSchema: {
|
|
338
|
-
type:
|
|
365
|
+
type: 'object',
|
|
339
366
|
properties: {
|
|
340
|
-
specName: { type:
|
|
367
|
+
specName: { type: 'string', description: 'Spec folder name' },
|
|
341
368
|
},
|
|
342
|
-
required: [
|
|
369
|
+
required: ['specName'],
|
|
343
370
|
},
|
|
344
371
|
},
|
|
345
372
|
{
|
|
346
|
-
name:
|
|
347
|
-
description:
|
|
373
|
+
name: 'get_spec_status',
|
|
374
|
+
description: 'Get the DAG status of all artifacts in a spec',
|
|
348
375
|
inputSchema: {
|
|
349
|
-
type:
|
|
376
|
+
type: 'object',
|
|
350
377
|
properties: {
|
|
351
|
-
specName: { type:
|
|
378
|
+
specName: { type: 'string', description: 'Spec folder name' },
|
|
352
379
|
},
|
|
353
|
-
required: [
|
|
380
|
+
required: ['specName'],
|
|
354
381
|
},
|
|
355
382
|
},
|
|
356
383
|
{
|
|
357
|
-
name:
|
|
358
|
-
description:
|
|
384
|
+
name: 'get_artifact',
|
|
385
|
+
description: 'Get the content of a spec artifact',
|
|
359
386
|
inputSchema: {
|
|
360
|
-
type:
|
|
387
|
+
type: 'object',
|
|
361
388
|
properties: {
|
|
362
|
-
specName: { type:
|
|
389
|
+
specName: { type: 'string', description: 'Spec folder name' },
|
|
363
390
|
artifactType: {
|
|
364
|
-
type:
|
|
365
|
-
description:
|
|
391
|
+
type: 'string',
|
|
392
|
+
description: 'Artifact type (e.g. proposal, specs, design, tasks)',
|
|
366
393
|
},
|
|
367
394
|
},
|
|
368
|
-
required: [
|
|
395
|
+
required: ['specName', 'artifactType'],
|
|
369
396
|
},
|
|
370
397
|
},
|
|
371
398
|
{
|
|
372
|
-
name:
|
|
373
|
-
description:
|
|
399
|
+
name: 'get_artifact_template',
|
|
400
|
+
description: 'Get the template for a spec artifact to use as a starting point',
|
|
374
401
|
inputSchema: {
|
|
375
|
-
type:
|
|
402
|
+
type: 'object',
|
|
376
403
|
properties: {
|
|
377
|
-
specName: { type:
|
|
404
|
+
specName: { type: 'string', description: 'Spec folder name' },
|
|
378
405
|
artifactType: {
|
|
379
|
-
type:
|
|
380
|
-
description:
|
|
406
|
+
type: 'string',
|
|
407
|
+
description: 'Artifact type (e.g. proposal, specs, design, tasks)',
|
|
381
408
|
},
|
|
382
409
|
},
|
|
383
|
-
required: [
|
|
410
|
+
required: ['specName', 'artifactType'],
|
|
384
411
|
},
|
|
385
412
|
},
|
|
386
413
|
{
|
|
387
|
-
name:
|
|
388
|
-
description:
|
|
414
|
+
name: 'write_artifact',
|
|
415
|
+
description:
|
|
416
|
+
'Write content to a spec artifact file. Blocked if required predecessors not approved.',
|
|
389
417
|
inputSchema: {
|
|
390
|
-
type:
|
|
418
|
+
type: 'object',
|
|
391
419
|
properties: {
|
|
392
|
-
specName: { type:
|
|
420
|
+
specName: { type: 'string', description: 'Spec folder name' },
|
|
393
421
|
artifactType: {
|
|
394
|
-
type:
|
|
395
|
-
description:
|
|
422
|
+
type: 'string',
|
|
423
|
+
description: 'Artifact type (e.g. proposal, specs, design, tasks)',
|
|
396
424
|
},
|
|
397
|
-
content: { type:
|
|
425
|
+
content: { type: 'string', description: 'Markdown content to write' },
|
|
398
426
|
},
|
|
399
|
-
required: [
|
|
427
|
+
required: ['specName', 'artifactType', 'content'],
|
|
400
428
|
},
|
|
401
429
|
},
|
|
402
430
|
{
|
|
403
|
-
name:
|
|
404
|
-
description:
|
|
431
|
+
name: 'approve_artifact',
|
|
432
|
+
description: 'Approve a spec artifact, allowing downstream artifacts to be written',
|
|
405
433
|
inputSchema: {
|
|
406
|
-
type:
|
|
434
|
+
type: 'object',
|
|
407
435
|
properties: {
|
|
408
|
-
specName: { type:
|
|
436
|
+
specName: { type: 'string', description: 'Spec folder name' },
|
|
409
437
|
artifactType: {
|
|
410
|
-
type:
|
|
411
|
-
description:
|
|
438
|
+
type: 'string',
|
|
439
|
+
description: 'Artifact type to approve',
|
|
412
440
|
},
|
|
413
441
|
approvedBy: {
|
|
414
|
-
type:
|
|
442
|
+
type: 'string',
|
|
415
443
|
description: "Who is approving (agent name or 'human')",
|
|
416
444
|
},
|
|
417
445
|
},
|
|
418
|
-
required: [
|
|
446
|
+
required: ['specName', 'artifactType'],
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
name: 'draft_artifact',
|
|
451
|
+
description: 'Reset an artifact approval back to draft state',
|
|
452
|
+
inputSchema: {
|
|
453
|
+
type: 'object',
|
|
454
|
+
properties: {
|
|
455
|
+
specName: { type: 'string', description: 'Spec folder name' },
|
|
456
|
+
artifactType: { type: 'string', description: 'Artifact type to reset' },
|
|
457
|
+
},
|
|
458
|
+
required: ['specName', 'artifactType'],
|
|
419
459
|
},
|
|
420
460
|
},
|
|
421
461
|
{
|
|
422
|
-
name:
|
|
423
|
-
description:
|
|
462
|
+
name: 'validate_spec',
|
|
463
|
+
description: 'Validate a spec for completeness and quality',
|
|
424
464
|
inputSchema: {
|
|
425
|
-
type:
|
|
465
|
+
type: 'object',
|
|
426
466
|
properties: {
|
|
427
|
-
specName: { type:
|
|
428
|
-
artifactType: { type: "string", description: "Artifact type to reset" },
|
|
467
|
+
specName: { type: 'string', description: 'Spec folder name' },
|
|
429
468
|
},
|
|
430
|
-
required: [
|
|
469
|
+
required: ['specName'],
|
|
431
470
|
},
|
|
432
471
|
},
|
|
433
472
|
{
|
|
434
|
-
name:
|
|
435
|
-
description:
|
|
473
|
+
name: 'promote_spec',
|
|
474
|
+
description:
|
|
475
|
+
"Promote approved tasks.md to Kanban tasks. The project is read from the spec's metadata — no need to supply projectId.",
|
|
436
476
|
inputSchema: {
|
|
437
|
-
type:
|
|
477
|
+
type: 'object',
|
|
438
478
|
properties: {
|
|
439
|
-
specName: { type:
|
|
479
|
+
specName: { type: 'string', description: 'Spec folder name' },
|
|
440
480
|
},
|
|
441
|
-
required: [
|
|
481
|
+
required: ['specName'],
|
|
482
|
+
},
|
|
483
|
+
},
|
|
484
|
+
// Schema Management
|
|
485
|
+
{
|
|
486
|
+
name: 'list_schemas',
|
|
487
|
+
description:
|
|
488
|
+
'List all available schemas (bundled and project-local) with their artifact DAGs',
|
|
489
|
+
inputSchema: {
|
|
490
|
+
type: 'object',
|
|
491
|
+
properties: {},
|
|
442
492
|
},
|
|
443
493
|
},
|
|
444
494
|
{
|
|
445
|
-
name:
|
|
446
|
-
description:
|
|
495
|
+
name: 'create_schema',
|
|
496
|
+
description:
|
|
497
|
+
'Create a new project-local schema with schema.yaml and template files under devflow/schemas/<name>/',
|
|
447
498
|
inputSchema: {
|
|
448
|
-
type:
|
|
499
|
+
type: 'object',
|
|
449
500
|
properties: {
|
|
450
|
-
|
|
501
|
+
name: {
|
|
502
|
+
type: 'string',
|
|
503
|
+
description: 'Schema name (kebab-case slug, e.g. "ml-pipeline")',
|
|
504
|
+
},
|
|
505
|
+
artifacts: {
|
|
506
|
+
type: 'array',
|
|
507
|
+
description: 'Array of artifact definitions',
|
|
508
|
+
items: {
|
|
509
|
+
type: 'object',
|
|
510
|
+
properties: {
|
|
511
|
+
id: { type: 'string', description: 'Artifact ID (e.g. "proposal")' },
|
|
512
|
+
generates: {
|
|
513
|
+
type: 'string',
|
|
514
|
+
description: 'Output filename (e.g. "proposal.md")',
|
|
515
|
+
},
|
|
516
|
+
description: { type: 'string', description: 'What this artifact covers' },
|
|
517
|
+
template: {
|
|
518
|
+
type: 'string',
|
|
519
|
+
description: 'Template filename (e.g. "proposal.md")',
|
|
520
|
+
},
|
|
521
|
+
requires: {
|
|
522
|
+
type: 'array',
|
|
523
|
+
items: { type: 'string' },
|
|
524
|
+
description: 'IDs of artifacts that must be approved first',
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
required: ['id', 'generates', 'description', 'template', 'requires'],
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
qualityRules: {
|
|
531
|
+
type: 'object',
|
|
532
|
+
description: 'Optional quality rules',
|
|
533
|
+
properties: {
|
|
534
|
+
requireRfc2119: { type: 'boolean' },
|
|
535
|
+
minScenariosPerRequirement: { type: 'number' },
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
apply: {
|
|
539
|
+
type: 'object',
|
|
540
|
+
description: 'Which artifacts must be approved before promoting to tasks',
|
|
541
|
+
properties: {
|
|
542
|
+
requires: { type: 'array', items: { type: 'string' } },
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
templates: {
|
|
546
|
+
type: 'object',
|
|
547
|
+
description:
|
|
548
|
+
'Map of artifactId → markdown template content. Keys should match artifact IDs.',
|
|
549
|
+
},
|
|
451
550
|
},
|
|
452
|
-
required: [
|
|
551
|
+
required: ['name', 'artifacts', 'templates'],
|
|
453
552
|
},
|
|
454
553
|
},
|
|
455
554
|
{
|
|
456
|
-
name:
|
|
457
|
-
description:
|
|
555
|
+
name: 'archive_spec',
|
|
556
|
+
description: 'Move a spec to the archive folder',
|
|
458
557
|
inputSchema: {
|
|
459
|
-
type:
|
|
558
|
+
type: 'object',
|
|
460
559
|
properties: {
|
|
461
|
-
specName: { type:
|
|
560
|
+
specName: { type: 'string', description: 'Spec folder name to archive' },
|
|
462
561
|
},
|
|
463
|
-
required: [
|
|
562
|
+
required: ['specName'],
|
|
464
563
|
},
|
|
465
564
|
},
|
|
466
565
|
],
|
|
@@ -474,7 +573,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
474
573
|
try {
|
|
475
574
|
switch (name) {
|
|
476
575
|
// ── Project tools ──────────────────────────────────────────────────────
|
|
477
|
-
case
|
|
576
|
+
case 'list_projects': {
|
|
478
577
|
const db = await getDb();
|
|
479
578
|
let query = db.select().from(schema.projects);
|
|
480
579
|
const projects = await query.orderBy(desc(schema.projects.createdAt));
|
|
@@ -484,11 +583,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
484
583
|
: projects;
|
|
485
584
|
|
|
486
585
|
return {
|
|
487
|
-
content: [{ type:
|
|
586
|
+
content: [{ type: 'text', text: JSON.stringify(filtered, null, 2) }],
|
|
488
587
|
};
|
|
489
588
|
}
|
|
490
589
|
|
|
491
|
-
case
|
|
590
|
+
case 'create_project': {
|
|
492
591
|
const { name: rawName, description } = args as {
|
|
493
592
|
name?: string;
|
|
494
593
|
description?: string;
|
|
@@ -499,16 +598,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
499
598
|
id: randomUUID(),
|
|
500
599
|
name: projectName,
|
|
501
600
|
description: description || null,
|
|
502
|
-
status:
|
|
601
|
+
status: 'active' as const,
|
|
503
602
|
};
|
|
504
603
|
await db.insert(schema.projects).values(newProject);
|
|
505
|
-
broadcastUpdate({ type:
|
|
604
|
+
broadcastUpdate({ type: 'project_created', project: newProject });
|
|
506
605
|
return {
|
|
507
|
-
content: [{ type:
|
|
606
|
+
content: [{ type: 'text', text: JSON.stringify(newProject, null, 2) }],
|
|
508
607
|
};
|
|
509
608
|
}
|
|
510
609
|
|
|
511
|
-
case
|
|
610
|
+
case 'get_project': {
|
|
512
611
|
const { projectId } = args as { projectId: string };
|
|
513
612
|
const db = await getDb();
|
|
514
613
|
const project = await db
|
|
@@ -518,7 +617,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
518
617
|
.limit(1);
|
|
519
618
|
|
|
520
619
|
if (project.length === 0) {
|
|
521
|
-
return { content: [{ type:
|
|
620
|
+
return { content: [{ type: 'text', text: 'Project not found' }], isError: true };
|
|
522
621
|
}
|
|
523
622
|
|
|
524
623
|
const tasks = await db
|
|
@@ -530,14 +629,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
530
629
|
return {
|
|
531
630
|
content: [
|
|
532
631
|
{
|
|
533
|
-
type:
|
|
632
|
+
type: 'text',
|
|
534
633
|
text: JSON.stringify({ ...project[0], tasks }, null, 2),
|
|
535
634
|
},
|
|
536
635
|
],
|
|
537
636
|
};
|
|
538
637
|
}
|
|
539
638
|
|
|
540
|
-
case
|
|
639
|
+
case 'update_project': {
|
|
541
640
|
const { projectId, ...updates } = args as {
|
|
542
641
|
projectId: string;
|
|
543
642
|
name?: string;
|
|
@@ -556,13 +655,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
556
655
|
.where(eq(schema.projects.id, projectId))
|
|
557
656
|
.limit(1);
|
|
558
657
|
|
|
559
|
-
broadcastUpdate({ type:
|
|
658
|
+
broadcastUpdate({ type: 'project_updated', project: updated[0] });
|
|
560
659
|
return {
|
|
561
|
-
content: [{ type:
|
|
660
|
+
content: [{ type: 'text', text: JSON.stringify(updated[0], null, 2) }],
|
|
562
661
|
};
|
|
563
662
|
}
|
|
564
663
|
|
|
565
|
-
case
|
|
664
|
+
case 'get_or_create_project': {
|
|
566
665
|
const { name: rawName, description } = args as {
|
|
567
666
|
name?: string;
|
|
568
667
|
description?: string;
|
|
@@ -577,7 +676,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
577
676
|
|
|
578
677
|
if (existing.length > 0) {
|
|
579
678
|
return {
|
|
580
|
-
content: [
|
|
679
|
+
content: [
|
|
680
|
+
{ type: 'text', text: JSON.stringify({ ...existing[0], created: false }, null, 2) },
|
|
681
|
+
],
|
|
581
682
|
};
|
|
582
683
|
}
|
|
583
684
|
|
|
@@ -585,17 +686,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
585
686
|
id: randomUUID(),
|
|
586
687
|
name: projectName,
|
|
587
688
|
description: description || null,
|
|
588
|
-
status:
|
|
689
|
+
status: 'active' as const,
|
|
589
690
|
};
|
|
590
691
|
await db.insert(schema.projects).values(newProject);
|
|
591
|
-
broadcastUpdate({ type:
|
|
692
|
+
broadcastUpdate({ type: 'project_created', project: newProject });
|
|
592
693
|
return {
|
|
593
|
-
content: [
|
|
694
|
+
content: [
|
|
695
|
+
{ type: 'text', text: JSON.stringify({ ...newProject, created: true }, null, 2) },
|
|
696
|
+
],
|
|
594
697
|
};
|
|
595
698
|
}
|
|
596
699
|
|
|
597
700
|
// ── Task tools ─────────────────────────────────────────────────────────
|
|
598
|
-
case
|
|
701
|
+
case 'list_tasks': {
|
|
599
702
|
const { projectId, specName, status, assignedAgent } = args as {
|
|
600
703
|
projectId?: string;
|
|
601
704
|
specName?: string;
|
|
@@ -603,10 +706,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
603
706
|
assignedAgent?: string;
|
|
604
707
|
};
|
|
605
708
|
const db = await getDb();
|
|
606
|
-
let tasks = await db
|
|
607
|
-
.select()
|
|
608
|
-
.from(schema.tasks)
|
|
609
|
-
.orderBy(schema.tasks.order);
|
|
709
|
+
let tasks = await db.select().from(schema.tasks).orderBy(schema.tasks.order);
|
|
610
710
|
|
|
611
711
|
if (projectId) tasks = tasks.filter((t) => t.projectId === projectId);
|
|
612
712
|
if (specName) tasks = tasks.filter((t) => t.specName === specName);
|
|
@@ -614,11 +714,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
614
714
|
if (assignedAgent) tasks = tasks.filter((t) => t.assignedAgent === assignedAgent);
|
|
615
715
|
|
|
616
716
|
return {
|
|
617
|
-
content: [{ type:
|
|
717
|
+
content: [{ type: 'text', text: JSON.stringify(tasks, null, 2) }],
|
|
618
718
|
};
|
|
619
719
|
}
|
|
620
720
|
|
|
621
|
-
case
|
|
721
|
+
case 'get_task': {
|
|
622
722
|
const { taskId } = args as { taskId: string };
|
|
623
723
|
const db = await getDb();
|
|
624
724
|
const task = await db
|
|
@@ -628,7 +728,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
628
728
|
.limit(1);
|
|
629
729
|
|
|
630
730
|
if (task.length === 0) {
|
|
631
|
-
return { content: [{ type:
|
|
731
|
+
return { content: [{ type: 'text', text: 'Task not found' }], isError: true };
|
|
632
732
|
}
|
|
633
733
|
|
|
634
734
|
const activity = await db
|
|
@@ -639,12 +739,27 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
639
739
|
.limit(10);
|
|
640
740
|
|
|
641
741
|
return {
|
|
642
|
-
content: [
|
|
742
|
+
content: [
|
|
743
|
+
{
|
|
744
|
+
type: 'text',
|
|
745
|
+
text: JSON.stringify({ ...task[0], recentActivity: activity }, null, 2),
|
|
746
|
+
},
|
|
747
|
+
],
|
|
643
748
|
};
|
|
644
749
|
}
|
|
645
750
|
|
|
646
|
-
case
|
|
647
|
-
const {
|
|
751
|
+
case 'create_task': {
|
|
752
|
+
const {
|
|
753
|
+
title,
|
|
754
|
+
body: bodyParam,
|
|
755
|
+
description,
|
|
756
|
+
priority,
|
|
757
|
+
status,
|
|
758
|
+
context,
|
|
759
|
+
projectId,
|
|
760
|
+
projectName,
|
|
761
|
+
specName,
|
|
762
|
+
} = args as {
|
|
648
763
|
title: string;
|
|
649
764
|
body?: string;
|
|
650
765
|
description?: string;
|
|
@@ -674,11 +789,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
674
789
|
id: randomUUID(),
|
|
675
790
|
name: sluggedName,
|
|
676
791
|
description: null,
|
|
677
|
-
status:
|
|
792
|
+
status: 'active' as const,
|
|
678
793
|
};
|
|
679
794
|
await db.insert(schema.projects).values(newProject);
|
|
680
795
|
targetProjectId = newProject.id;
|
|
681
|
-
broadcastUpdate({ type:
|
|
796
|
+
broadcastUpdate({ type: 'project_created', project: newProject });
|
|
682
797
|
}
|
|
683
798
|
}
|
|
684
799
|
|
|
@@ -697,21 +812,26 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
697
812
|
specName: specName || null,
|
|
698
813
|
title,
|
|
699
814
|
body: resolvedBody,
|
|
700
|
-
status: (status ||
|
|
701
|
-
priority: (priority ||
|
|
815
|
+
status: (status || 'backlog') as 'backlog' | 'todo' | 'in_progress' | 'done',
|
|
816
|
+
priority: (priority || 'medium') as 'low' | 'medium' | 'high' | 'urgent',
|
|
702
817
|
assignedAgent: null,
|
|
703
818
|
order: 0,
|
|
704
819
|
};
|
|
705
820
|
|
|
706
821
|
await db.insert(schema.tasks).values(newTask);
|
|
707
|
-
broadcastUpdate({ type:
|
|
822
|
+
broadcastUpdate({ type: 'task_created', task: newTask });
|
|
708
823
|
return {
|
|
709
|
-
content: [{ type:
|
|
824
|
+
content: [{ type: 'text', text: JSON.stringify(newTask, null, 2) }],
|
|
710
825
|
};
|
|
711
826
|
}
|
|
712
827
|
|
|
713
|
-
case
|
|
714
|
-
const {
|
|
828
|
+
case 'create_tasks_bulk': {
|
|
829
|
+
const {
|
|
830
|
+
projectId,
|
|
831
|
+
projectName,
|
|
832
|
+
specName,
|
|
833
|
+
tasks: taskList,
|
|
834
|
+
} = args as {
|
|
715
835
|
projectId?: string;
|
|
716
836
|
projectName?: string;
|
|
717
837
|
specName?: string;
|
|
@@ -743,11 +863,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
743
863
|
id: randomUUID(),
|
|
744
864
|
name: sluggedName,
|
|
745
865
|
description: null,
|
|
746
|
-
status:
|
|
866
|
+
status: 'active' as const,
|
|
747
867
|
};
|
|
748
868
|
await db.insert(schema.projects).values(newProject);
|
|
749
869
|
targetProjectId = newProject.id;
|
|
750
|
-
broadcastUpdate({ type:
|
|
870
|
+
broadcastUpdate({ type: 'project_created', project: newProject });
|
|
751
871
|
}
|
|
752
872
|
}
|
|
753
873
|
|
|
@@ -766,22 +886,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
766
886
|
specName: specName || null,
|
|
767
887
|
title: task.title,
|
|
768
888
|
body: resolvedBody,
|
|
769
|
-
status: (task.status ||
|
|
770
|
-
priority: (task.priority ||
|
|
889
|
+
status: (task.status || 'backlog') as 'backlog' | 'todo' | 'in_progress' | 'done',
|
|
890
|
+
priority: (task.priority || 'medium') as 'low' | 'medium' | 'high' | 'urgent',
|
|
771
891
|
assignedAgent: null,
|
|
772
892
|
order: index,
|
|
773
893
|
};
|
|
774
894
|
});
|
|
775
895
|
|
|
776
896
|
await db.insert(schema.tasks).values(newTasks);
|
|
777
|
-
broadcastUpdate({ type:
|
|
897
|
+
broadcastUpdate({ type: 'tasks_created', count: newTasks.length });
|
|
778
898
|
return {
|
|
779
|
-
content: [
|
|
899
|
+
content: [
|
|
900
|
+
{
|
|
901
|
+
type: 'text',
|
|
902
|
+
text: JSON.stringify({ created: newTasks.length, tasks: newTasks }, null, 2),
|
|
903
|
+
},
|
|
904
|
+
],
|
|
780
905
|
};
|
|
781
906
|
}
|
|
782
907
|
|
|
783
|
-
case
|
|
784
|
-
const {
|
|
908
|
+
case 'update_task': {
|
|
909
|
+
const {
|
|
910
|
+
taskId,
|
|
911
|
+
title,
|
|
912
|
+
body: bodyParam,
|
|
913
|
+
status,
|
|
914
|
+
priority,
|
|
915
|
+
specName,
|
|
916
|
+
} = args as {
|
|
785
917
|
taskId: string;
|
|
786
918
|
title?: string;
|
|
787
919
|
body?: string;
|
|
@@ -807,14 +939,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
807
939
|
.where(eq(schema.tasks.id, taskId))
|
|
808
940
|
.limit(1);
|
|
809
941
|
|
|
810
|
-
broadcastUpdate({ type:
|
|
942
|
+
broadcastUpdate({ type: 'task_updated', task: updated[0] });
|
|
811
943
|
return {
|
|
812
|
-
content: [{ type:
|
|
944
|
+
content: [{ type: 'text', text: JSON.stringify(updated[0], null, 2) }],
|
|
813
945
|
};
|
|
814
946
|
}
|
|
815
947
|
|
|
816
948
|
// ── Agent workflow tools ───────────────────────────────────────────────
|
|
817
|
-
case
|
|
949
|
+
case 'check_in': {
|
|
818
950
|
const { taskId, agentName, executionPlan } = args as {
|
|
819
951
|
taskId: string;
|
|
820
952
|
agentName: string;
|
|
@@ -824,7 +956,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
824
956
|
|
|
825
957
|
// If executionPlan provided, prepend it to the existing body
|
|
826
958
|
const taskSet: Record<string, unknown> = {
|
|
827
|
-
status:
|
|
959
|
+
status: 'in_progress',
|
|
828
960
|
assignedAgent: agentName,
|
|
829
961
|
updatedAt: new Date(),
|
|
830
962
|
};
|
|
@@ -835,22 +967,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
835
967
|
.from(schema.tasks)
|
|
836
968
|
.where(eq(schema.tasks.id, taskId))
|
|
837
969
|
.limit(1);
|
|
838
|
-
const existingBody = existingTask[0]?.body ||
|
|
970
|
+
const existingBody = existingTask[0]?.body || '';
|
|
839
971
|
const planSection = `**Execution Plan**\n\n${executionPlan}`;
|
|
840
972
|
taskSet.body = existingBody ? `${planSection}\n\n${existingBody}` : planSection;
|
|
841
973
|
}
|
|
842
974
|
|
|
843
|
-
await db
|
|
844
|
-
.update(schema.tasks)
|
|
845
|
-
.set(taskSet)
|
|
846
|
-
.where(eq(schema.tasks.id, taskId));
|
|
975
|
+
await db.update(schema.tasks).set(taskSet).where(eq(schema.tasks.id, taskId));
|
|
847
976
|
|
|
848
977
|
await db.insert(schema.agentActivity).values({
|
|
849
978
|
id: randomUUID(),
|
|
850
979
|
taskId,
|
|
851
980
|
agentName,
|
|
852
|
-
action:
|
|
853
|
-
details: executionPlan ? `Plan: ${executionPlan}` :
|
|
981
|
+
action: 'check_in',
|
|
982
|
+
details: executionPlan ? `Plan: ${executionPlan}` : 'Checked in',
|
|
854
983
|
timestamp: new Date(),
|
|
855
984
|
});
|
|
856
985
|
|
|
@@ -860,13 +989,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
860
989
|
.where(eq(schema.tasks.id, taskId))
|
|
861
990
|
.limit(1);
|
|
862
991
|
|
|
863
|
-
broadcastUpdate({ type:
|
|
992
|
+
broadcastUpdate({ type: 'task_updated', task: task[0] });
|
|
864
993
|
return {
|
|
865
|
-
content: [{ type:
|
|
994
|
+
content: [{ type: 'text', text: JSON.stringify(task[0], null, 2) }],
|
|
866
995
|
};
|
|
867
996
|
}
|
|
868
997
|
|
|
869
|
-
case
|
|
998
|
+
case 'check_out': {
|
|
870
999
|
const { taskId, agentName, taskSummary } = args as {
|
|
871
1000
|
taskId: string;
|
|
872
1001
|
agentName: string;
|
|
@@ -880,7 +1009,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
880
1009
|
const db = await getDb();
|
|
881
1010
|
|
|
882
1011
|
const taskSet: Record<string, unknown> = {
|
|
883
|
-
status:
|
|
1012
|
+
status: 'done',
|
|
884
1013
|
updatedAt: new Date(),
|
|
885
1014
|
};
|
|
886
1015
|
|
|
@@ -891,7 +1020,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
891
1020
|
.from(schema.tasks)
|
|
892
1021
|
.where(eq(schema.tasks.id, taskId))
|
|
893
1022
|
.limit(1);
|
|
894
|
-
const existingBody = existingTask[0]?.body ||
|
|
1023
|
+
const existingBody = existingTask[0]?.body || '';
|
|
895
1024
|
const updatedBody = fillTaskSummary(existingBody, taskSummary);
|
|
896
1025
|
taskSet.body = updatedBody;
|
|
897
1026
|
|
|
@@ -903,17 +1032,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
903
1032
|
}
|
|
904
1033
|
}
|
|
905
1034
|
|
|
906
|
-
await db
|
|
907
|
-
.update(schema.tasks)
|
|
908
|
-
.set(taskSet)
|
|
909
|
-
.where(eq(schema.tasks.id, taskId));
|
|
1035
|
+
await db.update(schema.tasks).set(taskSet).where(eq(schema.tasks.id, taskId));
|
|
910
1036
|
|
|
911
1037
|
await db.insert(schema.agentActivity).values({
|
|
912
1038
|
id: randomUUID(),
|
|
913
1039
|
taskId,
|
|
914
1040
|
agentName,
|
|
915
|
-
action:
|
|
916
|
-
details: taskSummary ? taskSummary.whatWasDone :
|
|
1041
|
+
action: 'check_out',
|
|
1042
|
+
details: taskSummary ? taskSummary.whatWasDone : 'Checked out',
|
|
917
1043
|
timestamp: new Date(),
|
|
918
1044
|
});
|
|
919
1045
|
|
|
@@ -923,13 +1049,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
923
1049
|
.where(eq(schema.tasks.id, taskId))
|
|
924
1050
|
.limit(1);
|
|
925
1051
|
|
|
926
|
-
broadcastUpdate({ type:
|
|
1052
|
+
broadcastUpdate({ type: 'task_updated', task: task[0] });
|
|
927
1053
|
return {
|
|
928
|
-
content: [{ type:
|
|
1054
|
+
content: [{ type: 'text', text: JSON.stringify(task[0], null, 2) }],
|
|
929
1055
|
};
|
|
930
1056
|
}
|
|
931
1057
|
|
|
932
|
-
case
|
|
1058
|
+
case 'log_activity': {
|
|
933
1059
|
const { taskId, agentName, action, details } = args as {
|
|
934
1060
|
taskId: string;
|
|
935
1061
|
agentName: string;
|
|
@@ -948,13 +1074,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
948
1074
|
};
|
|
949
1075
|
|
|
950
1076
|
await db.insert(schema.agentActivity).values(entry);
|
|
951
|
-
broadcastUpdate({ type:
|
|
1077
|
+
broadcastUpdate({ type: 'activity_logged', taskId });
|
|
952
1078
|
return {
|
|
953
|
-
content: [{ type:
|
|
1079
|
+
content: [{ type: 'text', text: JSON.stringify(entry, null, 2) }],
|
|
954
1080
|
};
|
|
955
1081
|
}
|
|
956
1082
|
|
|
957
|
-
case
|
|
1083
|
+
case 'get_activity_log': {
|
|
958
1084
|
const { taskId, limit } = args as { taskId: string; limit?: number };
|
|
959
1085
|
const db = await getDb();
|
|
960
1086
|
|
|
@@ -966,12 +1092,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
966
1092
|
.limit(limit || 50);
|
|
967
1093
|
|
|
968
1094
|
return {
|
|
969
|
-
content: [{ type:
|
|
1095
|
+
content: [{ type: 'text', text: JSON.stringify(activity, null, 2) }],
|
|
970
1096
|
};
|
|
971
1097
|
}
|
|
972
1098
|
|
|
973
1099
|
// ── Spec tools ─────────────────────────────────────────────────────────
|
|
974
|
-
case
|
|
1100
|
+
case 'list_specs': {
|
|
975
1101
|
const { projectId: filterProjectId } = args as { projectId?: string };
|
|
976
1102
|
let specs;
|
|
977
1103
|
if (filterProjectId) {
|
|
@@ -985,12 +1111,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
985
1111
|
specs = await listSpecs();
|
|
986
1112
|
}
|
|
987
1113
|
return {
|
|
988
|
-
content: [{ type:
|
|
1114
|
+
content: [{ type: 'text', text: JSON.stringify(specs, null, 2) }],
|
|
989
1115
|
};
|
|
990
1116
|
}
|
|
991
1117
|
|
|
992
|
-
case
|
|
993
|
-
const {
|
|
1118
|
+
case 'create_spec': {
|
|
1119
|
+
const {
|
|
1120
|
+
name: specName,
|
|
1121
|
+
title,
|
|
1122
|
+
projectId,
|
|
1123
|
+
description,
|
|
1124
|
+
schema: schemaName,
|
|
1125
|
+
} = args as {
|
|
994
1126
|
name: string;
|
|
995
1127
|
title: string;
|
|
996
1128
|
projectId: string;
|
|
@@ -998,48 +1130,58 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
998
1130
|
schema?: string;
|
|
999
1131
|
};
|
|
1000
1132
|
await createSpec(specName, title, projectId, description, schemaName);
|
|
1001
|
-
broadcastUpdate({ type:
|
|
1133
|
+
broadcastUpdate({ type: 'spec_created', specName });
|
|
1002
1134
|
return {
|
|
1003
|
-
content: [
|
|
1135
|
+
content: [
|
|
1136
|
+
{
|
|
1137
|
+
type: 'text',
|
|
1138
|
+
text: JSON.stringify({ name: specName, title, projectId, created: true }, null, 2),
|
|
1139
|
+
},
|
|
1140
|
+
],
|
|
1004
1141
|
};
|
|
1005
1142
|
}
|
|
1006
1143
|
|
|
1007
|
-
case
|
|
1144
|
+
case 'get_spec': {
|
|
1008
1145
|
const { specName } = args as { specName: string };
|
|
1009
1146
|
const spec = await getSpec(specName);
|
|
1010
1147
|
return {
|
|
1011
|
-
content: [{ type:
|
|
1148
|
+
content: [{ type: 'text', text: JSON.stringify(spec, null, 2) }],
|
|
1012
1149
|
};
|
|
1013
1150
|
}
|
|
1014
1151
|
|
|
1015
|
-
case
|
|
1152
|
+
case 'get_spec_status': {
|
|
1016
1153
|
const { specName } = args as { specName: string };
|
|
1017
1154
|
const statuses = await getSpecStatus(specName);
|
|
1018
1155
|
return {
|
|
1019
|
-
content: [{ type:
|
|
1156
|
+
content: [{ type: 'text', text: JSON.stringify(statuses, null, 2) }],
|
|
1020
1157
|
};
|
|
1021
1158
|
}
|
|
1022
1159
|
|
|
1023
|
-
case
|
|
1160
|
+
case 'get_artifact': {
|
|
1024
1161
|
const { specName, artifactType } = args as { specName: string; artifactType: string };
|
|
1025
1162
|
const content = await getArtifact(specName, artifactType);
|
|
1026
1163
|
if (content === null) {
|
|
1027
|
-
return {
|
|
1164
|
+
return {
|
|
1165
|
+
content: [
|
|
1166
|
+
{ type: 'text', text: `Artifact "${artifactType}" not found in spec "${specName}"` },
|
|
1167
|
+
],
|
|
1168
|
+
isError: true,
|
|
1169
|
+
};
|
|
1028
1170
|
}
|
|
1029
1171
|
return {
|
|
1030
|
-
content: [{ type:
|
|
1172
|
+
content: [{ type: 'text', text: content }],
|
|
1031
1173
|
};
|
|
1032
1174
|
}
|
|
1033
1175
|
|
|
1034
|
-
case
|
|
1176
|
+
case 'get_artifact_template': {
|
|
1035
1177
|
const { specName, artifactType } = args as { specName: string; artifactType: string };
|
|
1036
1178
|
const template = await getArtifactTemplate(specName, artifactType);
|
|
1037
1179
|
return {
|
|
1038
|
-
content: [{ type:
|
|
1180
|
+
content: [{ type: 'text', text: template }],
|
|
1039
1181
|
};
|
|
1040
1182
|
}
|
|
1041
1183
|
|
|
1042
|
-
case
|
|
1184
|
+
case 'write_artifact': {
|
|
1043
1185
|
const { specName, artifactType, content } = args as {
|
|
1044
1186
|
specName: string;
|
|
1045
1187
|
artifactType: string;
|
|
@@ -1049,65 +1191,76 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1049
1191
|
// Check blocker gate
|
|
1050
1192
|
const statuses = await getSpecStatus(specName);
|
|
1051
1193
|
const status = statuses.find((s) => s.id === artifactType);
|
|
1052
|
-
if (status?.state ===
|
|
1194
|
+
if (status?.state === 'blocked') {
|
|
1053
1195
|
return {
|
|
1054
|
-
content: [
|
|
1196
|
+
content: [
|
|
1197
|
+
{
|
|
1198
|
+
type: 'text',
|
|
1199
|
+
text: `Cannot write "${artifactType}": required artifacts (${status.requires.join(', ')}) must be approved first`,
|
|
1200
|
+
},
|
|
1201
|
+
],
|
|
1055
1202
|
isError: true,
|
|
1056
1203
|
};
|
|
1057
1204
|
}
|
|
1058
1205
|
|
|
1059
1206
|
await writeArtifact(specName, artifactType, content);
|
|
1060
|
-
broadcastUpdate({ type:
|
|
1207
|
+
broadcastUpdate({ type: 'artifact_updated', specName, artifactType });
|
|
1061
1208
|
return {
|
|
1062
|
-
content: [
|
|
1209
|
+
content: [
|
|
1210
|
+
{ type: 'text', text: `Successfully wrote ${artifactType} for spec "${specName}"` },
|
|
1211
|
+
],
|
|
1063
1212
|
};
|
|
1064
1213
|
}
|
|
1065
1214
|
|
|
1066
|
-
case
|
|
1215
|
+
case 'approve_artifact': {
|
|
1067
1216
|
const { specName, artifactType, approvedBy } = args as {
|
|
1068
1217
|
specName: string;
|
|
1069
1218
|
artifactType: string;
|
|
1070
1219
|
approvedBy?: string;
|
|
1071
1220
|
};
|
|
1072
|
-
await approveArtifact(specName, artifactType, approvedBy ||
|
|
1073
|
-
broadcastUpdate({ type:
|
|
1221
|
+
await approveArtifact(specName, artifactType, approvedBy || 'agent');
|
|
1222
|
+
broadcastUpdate({ type: 'artifact_approved', specName, artifactType });
|
|
1074
1223
|
return {
|
|
1075
|
-
content: [{ type:
|
|
1224
|
+
content: [{ type: 'text', text: `Approved "${artifactType}" for spec "${specName}"` }],
|
|
1076
1225
|
};
|
|
1077
1226
|
}
|
|
1078
1227
|
|
|
1079
|
-
case
|
|
1228
|
+
case 'draft_artifact': {
|
|
1080
1229
|
const { specName, artifactType } = args as { specName: string; artifactType: string };
|
|
1081
1230
|
await draftArtifact(specName, artifactType);
|
|
1082
|
-
broadcastUpdate({ type:
|
|
1231
|
+
broadcastUpdate({ type: 'artifact_drafted', specName, artifactType });
|
|
1083
1232
|
return {
|
|
1084
|
-
content: [
|
|
1233
|
+
content: [
|
|
1234
|
+
{ type: 'text', text: `Reset "${artifactType}" to draft for spec "${specName}"` },
|
|
1235
|
+
],
|
|
1085
1236
|
};
|
|
1086
1237
|
}
|
|
1087
1238
|
|
|
1088
|
-
case
|
|
1239
|
+
case 'validate_spec': {
|
|
1089
1240
|
const { specName } = args as { specName: string };
|
|
1090
1241
|
const report = await validateSpec(specName);
|
|
1091
1242
|
return {
|
|
1092
|
-
content: [{ type:
|
|
1243
|
+
content: [{ type: 'text', text: JSON.stringify(report, null, 2) }],
|
|
1093
1244
|
};
|
|
1094
1245
|
}
|
|
1095
1246
|
|
|
1096
|
-
case
|
|
1247
|
+
case 'promote_spec': {
|
|
1097
1248
|
const { specName } = args as { specName: string };
|
|
1098
1249
|
|
|
1099
1250
|
const specDetail = await getSpec(specName);
|
|
1100
1251
|
const projectId = specDetail.projectId;
|
|
1101
1252
|
if (!projectId) {
|
|
1102
1253
|
return {
|
|
1103
|
-
content: [
|
|
1254
|
+
content: [
|
|
1255
|
+
{ type: 'text', text: 'Spec has no project — re-create it with a projectId' },
|
|
1256
|
+
],
|
|
1104
1257
|
isError: true,
|
|
1105
1258
|
};
|
|
1106
1259
|
}
|
|
1107
1260
|
|
|
1108
|
-
if (specDetail.approvals.artifacts[
|
|
1261
|
+
if (specDetail.approvals.artifacts['tasks']?.state !== 'approved') {
|
|
1109
1262
|
return {
|
|
1110
|
-
content: [{ type:
|
|
1263
|
+
content: [{ type: 'text', text: 'tasks artifact must be approved before promoting' }],
|
|
1111
1264
|
isError: true,
|
|
1112
1265
|
};
|
|
1113
1266
|
}
|
|
@@ -1115,7 +1268,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1115
1268
|
const parsedTasks = await parseTasksArtifact(specName);
|
|
1116
1269
|
if (parsedTasks.length === 0) {
|
|
1117
1270
|
return {
|
|
1118
|
-
content: [{ type:
|
|
1271
|
+
content: [{ type: 'text', text: 'No tasks found in tasks.md' }],
|
|
1119
1272
|
isError: true,
|
|
1120
1273
|
};
|
|
1121
1274
|
}
|
|
@@ -1127,31 +1280,85 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1127
1280
|
specName,
|
|
1128
1281
|
title: task.title,
|
|
1129
1282
|
body: task.body || null,
|
|
1130
|
-
status:
|
|
1131
|
-
priority: (task.priority ||
|
|
1283
|
+
status: 'backlog' as const,
|
|
1284
|
+
priority: (task.priority || 'medium') as 'low' | 'medium' | 'high' | 'urgent',
|
|
1132
1285
|
assignedAgent: null,
|
|
1133
1286
|
order: index,
|
|
1134
1287
|
}));
|
|
1135
1288
|
|
|
1136
1289
|
await db.insert(schema.tasks).values(newTasks);
|
|
1137
|
-
broadcastUpdate({ type:
|
|
1290
|
+
broadcastUpdate({ type: 'spec_promoted', specName, taskCount: newTasks.length });
|
|
1291
|
+
return {
|
|
1292
|
+
content: [
|
|
1293
|
+
{
|
|
1294
|
+
type: 'text',
|
|
1295
|
+
text: JSON.stringify({ promoted: newTasks.length, tasks: newTasks }, null, 2),
|
|
1296
|
+
},
|
|
1297
|
+
],
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// ── Schema tools ───────────────────────────────────────────────────────
|
|
1302
|
+
case 'list_schemas': {
|
|
1303
|
+
const entries = await listSchemas(getSpecsDir());
|
|
1304
|
+
const result = entries.map((e) => ({
|
|
1305
|
+
id: e.id,
|
|
1306
|
+
source: e.source,
|
|
1307
|
+
artifacts: e.schema.artifacts.map((a) => ({
|
|
1308
|
+
id: a.id,
|
|
1309
|
+
generates: a.generates,
|
|
1310
|
+
description: a.description,
|
|
1311
|
+
requires: a.requires,
|
|
1312
|
+
})),
|
|
1313
|
+
qualityRules: e.schema.qualityRules,
|
|
1314
|
+
apply: e.schema.apply,
|
|
1315
|
+
}));
|
|
1138
1316
|
return {
|
|
1139
|
-
content: [{ type:
|
|
1317
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
case 'create_schema': {
|
|
1322
|
+
const { name, artifacts, qualityRules, apply, templates } = args as {
|
|
1323
|
+
name: string;
|
|
1324
|
+
artifacts: Array<{
|
|
1325
|
+
id: string;
|
|
1326
|
+
generates: string;
|
|
1327
|
+
description: string;
|
|
1328
|
+
template: string;
|
|
1329
|
+
requires: string[];
|
|
1330
|
+
}>;
|
|
1331
|
+
qualityRules?: { requireRfc2119?: boolean; minScenariosPerRequirement?: number };
|
|
1332
|
+
apply?: { requires: string[] };
|
|
1333
|
+
templates: Record<string, string>;
|
|
1334
|
+
};
|
|
1335
|
+
const schemaDir = await createSchema(
|
|
1336
|
+
{ name, artifacts, qualityRules, apply, templates },
|
|
1337
|
+
getSpecsDir(),
|
|
1338
|
+
);
|
|
1339
|
+
broadcastUpdate({ type: 'schema_created', name });
|
|
1340
|
+
return {
|
|
1341
|
+
content: [
|
|
1342
|
+
{
|
|
1343
|
+
type: 'text',
|
|
1344
|
+
text: `Created schema "${name}" at ${schemaDir}\n\nArtifacts: ${artifacts.map((a) => a.id).join(' → ')}`,
|
|
1345
|
+
},
|
|
1346
|
+
],
|
|
1140
1347
|
};
|
|
1141
1348
|
}
|
|
1142
1349
|
|
|
1143
|
-
case
|
|
1350
|
+
case 'archive_spec': {
|
|
1144
1351
|
const { specName } = args as { specName: string };
|
|
1145
1352
|
await archiveSpec(specName);
|
|
1146
|
-
broadcastUpdate({ type:
|
|
1353
|
+
broadcastUpdate({ type: 'spec_archived', specName });
|
|
1147
1354
|
return {
|
|
1148
|
-
content: [{ type:
|
|
1355
|
+
content: [{ type: 'text', text: `Archived spec "${specName}"` }],
|
|
1149
1356
|
};
|
|
1150
1357
|
}
|
|
1151
1358
|
|
|
1152
1359
|
default:
|
|
1153
1360
|
return {
|
|
1154
|
-
content: [{ type:
|
|
1361
|
+
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
1155
1362
|
isError: true,
|
|
1156
1363
|
};
|
|
1157
1364
|
}
|
|
@@ -1159,7 +1366,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1159
1366
|
return {
|
|
1160
1367
|
content: [
|
|
1161
1368
|
{
|
|
1162
|
-
type:
|
|
1369
|
+
type: 'text',
|
|
1163
1370
|
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
1164
1371
|
},
|
|
1165
1372
|
],
|
|
@@ -1170,34 +1377,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1170
1377
|
|
|
1171
1378
|
function resolveAgentName(): string {
|
|
1172
1379
|
// 1. Env-based detection (set by agent host process)
|
|
1173
|
-
if (process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT) return
|
|
1174
|
-
if (process.env.CODEX) return
|
|
1175
|
-
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) return
|
|
1176
|
-
if (process.env.WINDSURF_PLUGIN_VERSION) return
|
|
1380
|
+
if (process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT) return 'Claude Code';
|
|
1381
|
+
if (process.env.CODEX) return 'Codex';
|
|
1382
|
+
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) return 'Cursor';
|
|
1383
|
+
if (process.env.WINDSURF_PLUGIN_VERSION) return 'Windsurf';
|
|
1177
1384
|
// 2. MCP clientInfo (available after initialize handshake)
|
|
1178
1385
|
const clientInfo = server.getClientVersion();
|
|
1179
1386
|
if (clientInfo?.name) {
|
|
1180
1387
|
const n = clientInfo.name.toLowerCase();
|
|
1181
|
-
if (n.includes(
|
|
1182
|
-
if (n.includes(
|
|
1183
|
-
if (n.includes(
|
|
1184
|
-
if (n.includes(
|
|
1185
|
-
if (n.includes(
|
|
1388
|
+
if (n.includes('claude')) return 'Claude Code';
|
|
1389
|
+
if (n.includes('codex')) return 'Codex';
|
|
1390
|
+
if (n.includes('cursor')) return 'Cursor';
|
|
1391
|
+
if (n.includes('windsurf')) return 'Windsurf';
|
|
1392
|
+
if (n.includes('copilot')) return 'Copilot';
|
|
1186
1393
|
return clientInfo.name; // use as-is if unrecognized
|
|
1187
1394
|
}
|
|
1188
|
-
return
|
|
1395
|
+
return 'Unknown Agent';
|
|
1189
1396
|
}
|
|
1190
1397
|
|
|
1191
1398
|
async function main() {
|
|
1192
1399
|
const transport = new StdioServerTransport();
|
|
1193
1400
|
await server.connect(transport);
|
|
1194
|
-
console.error(
|
|
1401
|
+
console.error('DevFlow MCP server running on stdio');
|
|
1195
1402
|
|
|
1196
1403
|
// Re-broadcast identify after initialize so clientInfo is available
|
|
1197
1404
|
// The initial identify (sent on WS open) uses env-based detection;
|
|
1198
1405
|
// this one fires ~1s later with the MCP clientInfo name as fallback.
|
|
1199
1406
|
setTimeout(() => {
|
|
1200
|
-
broadcastUpdate({ type:
|
|
1407
|
+
broadcastUpdate({ type: 'identify', role: 'mcp', agent: resolveAgentName() });
|
|
1201
1408
|
}, 1000);
|
|
1202
1409
|
}
|
|
1203
1410
|
|