@projitive/mcp 1.0.7 → 1.1.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.
Files changed (56) hide show
  1. package/README.md +3 -3
  2. package/output/package.json +4 -1
  3. package/output/source/{helpers/catch → common}/catch.js +6 -6
  4. package/output/source/{helpers/catch → common}/catch.test.js +6 -6
  5. package/output/source/common/confidence.js +231 -0
  6. package/output/source/common/confidence.test.js +205 -0
  7. package/output/source/common/errors.js +120 -0
  8. package/output/source/{helpers/files → common}/files.js +1 -1
  9. package/output/source/{helpers/files → common}/files.test.js +1 -1
  10. package/output/source/common/index.js +10 -0
  11. package/output/source/{helpers/linter/codes.js → common/linter.js} +13 -0
  12. package/output/source/{helpers/markdown → common}/markdown.test.js +1 -1
  13. package/output/source/{helpers/response → common}/response.test.js +1 -1
  14. package/output/source/common/types.js +7 -0
  15. package/output/source/common/utils.js +39 -0
  16. package/output/source/design-context.js +51 -500
  17. package/output/source/index.js +8 -193
  18. package/output/source/index.test.js +116 -0
  19. package/output/source/prompts/index.js +9 -0
  20. package/output/source/prompts/quickStart.js +94 -0
  21. package/output/source/prompts/taskDiscovery.js +190 -0
  22. package/output/source/prompts/taskExecution.js +161 -0
  23. package/output/source/resources/designs.js +108 -0
  24. package/output/source/resources/designs.test.js +154 -0
  25. package/output/source/resources/governance.js +40 -0
  26. package/output/source/resources/index.js +6 -0
  27. package/output/source/resources/readme.test.js +167 -0
  28. package/output/source/{reports.js → resources/reports.js} +5 -3
  29. package/output/source/resources/reports.test.js +149 -0
  30. package/output/source/tools/index.js +8 -0
  31. package/output/source/{projitive.js → tools/project.js} +6 -9
  32. package/output/source/tools/project.test.js +322 -0
  33. package/output/source/{roadmap.js → tools/roadmap.js} +4 -7
  34. package/output/source/tools/roadmap.test.js +103 -0
  35. package/output/source/{tasks.js → tools/task.js} +581 -27
  36. package/output/source/tools/task.test.js +473 -0
  37. package/output/source/types.js +67 -0
  38. package/package.json +4 -1
  39. package/output/source/designs.js +0 -38
  40. package/output/source/helpers/artifacts/index.js +0 -1
  41. package/output/source/helpers/catch/index.js +0 -1
  42. package/output/source/helpers/files/index.js +0 -1
  43. package/output/source/helpers/index.js +0 -6
  44. package/output/source/helpers/linter/index.js +0 -2
  45. package/output/source/helpers/linter/linter.js +0 -6
  46. package/output/source/helpers/markdown/index.js +0 -1
  47. package/output/source/helpers/response/index.js +0 -1
  48. package/output/source/projitive.test.js +0 -111
  49. package/output/source/roadmap.test.js +0 -11
  50. package/output/source/tasks.test.js +0 -152
  51. /package/output/source/{helpers/artifacts → common}/artifacts.js +0 -0
  52. /package/output/source/{helpers/artifacts → common}/artifacts.test.js +0 -0
  53. /package/output/source/{helpers/linter → common}/linter.test.js +0 -0
  54. /package/output/source/{helpers/markdown → common}/markdown.js +0 -0
  55. /package/output/source/{helpers/response → common}/response.js +0 -0
  56. /package/output/source/{readme.js → resources/readme.js} +0 -0
@@ -1,17 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import fs from "node:fs/promises";
3
2
  import path from "node:path";
4
3
  import process from "node:process";
5
4
  import { fileURLToPath } from "node:url";
6
5
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
- import { z } from "zod";
9
7
  import packageJson from "../package.json" with { type: "json" };
10
- import { registerProjectTools } from "./projitive.js";
11
- import { registerTaskTools } from "./tasks.js";
12
- import { registerRoadmapTools } from "./roadmap.js";
8
+ import { registerTools } from "./tools/index.js";
9
+ import { registerResources } from "./resources/index.js";
10
+ import { registerPrompts } from "./prompts/index.js";
13
11
  import { registerDesignContextResources, registerDesignContextPrompts } from "./design-context.js";
14
- const PROJITIVE_SPEC_VERSION = "1.0.0";
12
+ const PROJITIVE_SPEC_VERSION = "1.1.0";
15
13
  const currentFilePath = fileURLToPath(import.meta.url);
16
14
  const sourceDir = path.dirname(currentFilePath);
17
15
  const repoRoot = path.resolve(sourceDir, "..", "..", "..");
@@ -23,193 +21,10 @@ const server = new McpServer({
23
21
  version: MCP_RUNTIME_VERSION,
24
22
  description: "Semantic Projitive MCP for project/task discovery and agent guidance with markdown-first outputs",
25
23
  });
26
- function resolveRepoFile(relativePath) {
27
- return path.join(repoRoot, relativePath);
28
- }
29
- async function readMarkdownOrFallback(relativePath, fallbackTitle) {
30
- const absolutePath = resolveRepoFile(relativePath);
31
- const content = await fs.readFile(absolutePath, "utf-8").catch(() => undefined);
32
- if (typeof content === "string" && content.trim().length > 0) {
33
- return content;
34
- }
35
- return [
36
- `# ${fallbackTitle}`,
37
- "",
38
- `- file: ${relativePath}`,
39
- "- status: missing-or-empty",
40
- "- next: create this file or ensure it has readable markdown content",
41
- ].join("\n");
42
- }
43
- function renderMethodCatalogMarkdown() {
44
- return [
45
- "# MCP Method Catalog",
46
- "",
47
- "## Start Here",
48
- "- Unknown project path: `projectScan` -> `projectLocate` -> `projectContext` -> `taskNext`.",
49
- "- Known project path: `projectContext` -> `taskNext` (or `taskList`) -> `taskContext`.",
50
- "- Need to bootstrap governance: call `projectInit(projectPath=\"<project-dir>\")` only when `.projitive` is missing.",
51
- "",
52
- "## Methods",
53
- "| Order | Group | Method | Agent Use |",
54
- "|---|---|---|---|",
55
- "| 1 | Project | projectScan | discover governance roots when project is unknown |",
56
- "| 2 | Project | projectLocate | lock nearest governance root from any path |",
57
- "| 3 | Project | projectContext | load project summary before task decisions |",
58
- "| 4 | Task | taskNext | auto-pick highest-priority actionable task |",
59
- "| 5 | Task | taskList | list/filter tasks for manual selection |",
60
- "| 6 | Task | taskContext | inspect one task with evidence and read order |",
61
- "| 7 | Roadmap | roadmapList | inspect roadmap-task linkage |",
62
- "| 8 | Roadmap | roadmapContext | inspect one roadmap with references |",
63
- "| 9 | Project | projectNext | rank actionable projects across workspace |",
64
- "| 10 | Project | projectInit | bootstrap governance files if missing |"
65
- ].join("\n");
66
- }
67
- function registerGovernanceResources() {
68
- server.registerResource("governanceWorkspace", "projitive://governance/workspace", {
69
- title: "Governance Workspace",
70
- description: "Primary governance README under .projitive",
71
- mimeType: "text/markdown",
72
- }, async () => ({
73
- contents: [
74
- {
75
- uri: "projitive://governance/workspace",
76
- text: await readMarkdownOrFallback(".projitive/README.md", "Governance Workspace"),
77
- },
78
- ],
79
- }));
80
- server.registerResource("governanceTasks", "projitive://governance/tasks", {
81
- title: "Governance Tasks",
82
- description: "Current task pool and status under .projitive/tasks.md",
83
- mimeType: "text/markdown",
84
- }, async () => ({
85
- contents: [
86
- {
87
- uri: "projitive://governance/tasks",
88
- text: await readMarkdownOrFallback(".projitive/tasks.md", "Governance Tasks"),
89
- },
90
- ],
91
- }));
92
- server.registerResource("governanceRoadmap", "projitive://governance/roadmap", {
93
- title: "Governance Roadmap",
94
- description: "Current roadmap under .projitive/roadmap.md",
95
- mimeType: "text/markdown",
96
- }, async () => ({
97
- contents: [
98
- {
99
- uri: "projitive://governance/roadmap",
100
- text: await readMarkdownOrFallback(".projitive/roadmap.md", "Governance Roadmap"),
101
- },
102
- ],
103
- }));
104
- server.registerResource("mcpMethodCatalog", "projitive://mcp/method-catalog", {
105
- title: "MCP Method Catalog",
106
- description: "Method naming and purpose map for agent routing",
107
- mimeType: "text/markdown",
108
- }, async () => ({
109
- contents: [
110
- {
111
- uri: "projitive://mcp/method-catalog",
112
- text: renderMethodCatalogMarkdown(),
113
- },
114
- ],
115
- }));
116
- }
117
- function asUserPrompt(text) {
118
- return {
119
- messages: [
120
- {
121
- role: "user",
122
- content: {
123
- type: "text",
124
- text,
125
- },
126
- },
127
- ],
128
- };
129
- }
130
- function registerGovernancePrompts() {
131
- server.registerPrompt("executeTaskWorkflow", {
132
- title: "Execute Task Workflow",
133
- description: "Primary execution prompt: select one task, execute, and verify evidence consistency",
134
- argsSchema: {
135
- projectPath: z.string().optional(),
136
- taskId: z.string().optional(),
137
- },
138
- }, async ({ projectPath, taskId }) => {
139
- const taskEntry = taskId && projectPath
140
- ? `1) Run taskContext(projectPath=\"${projectPath}\", taskId=\"${taskId}\").`
141
- : "1) Run taskNext().";
142
- const text = [
143
- "You are executing Projitive governance workflow in agent-first mode.",
144
- "",
145
- "Fast path:",
146
- taskEntry,
147
- "2) Follow Suggested Read Order and identify execution blockers.",
148
- "3) Edit governance markdown only (tasks/designs/reports/roadmap).",
149
- "4) Re-run taskContext for the selected task and verify references.",
150
- "",
151
- "Fallbacks:",
152
- "- If `.projitive` is missing for a known project, run `projectInit(projectPath=\"<project-dir>\")` first.",
153
- "- If taskNext returns no actionable task, follow its no-task checklist and create 1-3 TODO tasks.",
154
- "- If project is unknown, run projectScan -> projectLocate -> projectContext before task tools.",
155
- "",
156
- "Hard rules:",
157
- "- Keep TASK/ROADMAP IDs immutable.",
158
- "- Every status transition must have report evidence.",
159
- "- Do not introduce non-governance file edits unless task scope requires.",
160
- ].join("\n");
161
- return asUserPrompt(text);
162
- });
163
- server.registerPrompt("updateTaskStatusWithEvidence", {
164
- title: "Update Task Status With Evidence",
165
- description: "Safe status transition playbook with mandatory evidence backfill",
166
- argsSchema: {
167
- projectPath: z.string(),
168
- taskId: z.string(),
169
- targetStatus: z.enum(["TODO", "IN_PROGRESS", "BLOCKED", "DONE"]),
170
- },
171
- }, async ({ projectPath, taskId, targetStatus }) => {
172
- const text = [
173
- "Perform a safe task status update with evidence alignment.",
174
- "",
175
- `1) Run taskContext(projectPath=\"${projectPath}\", taskId=\"${taskId}\").`,
176
- `2) Confirm transition to ${targetStatus} is valid.`,
177
- "3) Update tasks.md status and updatedAt.",
178
- "4) Add or update a report under reports/ with concrete evidence.",
179
- "5) Re-run taskContext and confirm status/evidence/reference consistency.",
180
- "6) If lint remains, fix and re-run taskContext once more.",
181
- "",
182
- "Checklist:",
183
- "- Transition is valid per status machine.",
184
- "- links/roadmapRefs remain parseable and consistent.",
185
- "- Only `hooks/task_no_actionable.md` is used as global background hook for no-task discovery.",
186
- ].join("\n");
187
- return asUserPrompt(text);
188
- });
189
- server.registerPrompt("triageProjectGovernance", {
190
- title: "Triage Project Governance",
191
- description: "Discovery-first triage prompt to pick project and next executable task",
192
- argsSchema: {},
193
- }, async () => {
194
- const text = [
195
- "Triage governance and pick one execution target quickly.",
196
- "",
197
- "0) If known project has no `.projitive`, run projectInit(projectPath=<project-dir>) first.",
198
- "1) If project path is unknown, run projectScan() and pick one discovered project.",
199
- "2) Run projectNext() to rank projects.",
200
- "3) Run projectContext(projectPath=<selectedProject>).",
201
- "4) Run taskNext() for best actionable task.",
202
- "5) If manual filtering is needed, run taskList(projectPath=<selectedProject>, status=IN_PROGRESS).",
203
- "6) Continue with taskContext(projectPath=<selectedProject>, taskId=<selectedTaskId>).",
204
- ].join("\n");
205
- return asUserPrompt(text);
206
- });
207
- }
208
- registerProjectTools(server);
209
- registerTaskTools(server);
210
- registerRoadmapTools(server);
211
- registerGovernanceResources();
212
- registerGovernancePrompts();
24
+ // Register all modules
25
+ registerTools(server);
26
+ registerResources(server, repoRoot);
27
+ registerPrompts(server);
213
28
  registerDesignContextResources(server);
214
29
  registerDesignContextPrompts(server);
215
30
  async function main() {
@@ -0,0 +1,116 @@
1
+ import { describe, it, expect, beforeAll, afterAll, vi, beforeEach } from "vitest";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import os from "node:os";
5
+ import { fileURLToPath } from "node:url";
6
+ const currentFilePath = fileURLToPath(import.meta.url);
7
+ const sourceDir = path.dirname(currentFilePath);
8
+ // Mock McpServer and StdioServerTransport
9
+ vi.mock("@modelcontextprotocol/sdk/server/mcp.js", () => ({
10
+ McpServer: vi.fn().mockImplementation(() => ({
11
+ registerResource: vi.fn(),
12
+ registerPrompt: vi.fn(),
13
+ connect: vi.fn().mockResolvedValue(undefined),
14
+ })),
15
+ }));
16
+ vi.mock("@modelcontextprotocol/sdk/server/stdio.js", () => ({
17
+ StdioServerTransport: vi.fn().mockImplementation(() => ({})),
18
+ }));
19
+ // Mock the registration functions
20
+ vi.mock("./tools/project.js", () => ({
21
+ registerProjectTools: vi.fn(),
22
+ }));
23
+ vi.mock("./tools/task.js", () => ({
24
+ registerTaskTools: vi.fn(),
25
+ }));
26
+ vi.mock("./tools/roadmap.js", () => ({
27
+ registerRoadmapTools: vi.fn(),
28
+ }));
29
+ vi.mock("./design-context.js", () => ({
30
+ registerDesignContextResources: vi.fn(),
31
+ registerDesignContextPrompts: vi.fn(),
32
+ }));
33
+ vi.mock("./resources/governance.js", () => ({
34
+ registerGovernanceResources: vi.fn(),
35
+ }));
36
+ vi.mock("./resources/designs.js", () => ({
37
+ registerDesignFilesResources: vi.fn(),
38
+ }));
39
+ vi.mock("./prompts/governance.js", () => ({
40
+ registerGovernancePrompts: vi.fn(),
41
+ }));
42
+ describe("index module", () => {
43
+ let tempDir;
44
+ let testProjectDir;
45
+ beforeAll(async () => {
46
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "projitive-index-test-"));
47
+ testProjectDir = path.join(tempDir, "test-project");
48
+ await fs.mkdir(testProjectDir);
49
+ });
50
+ afterAll(async () => {
51
+ await fs.rm(tempDir, { recursive: true, force: true });
52
+ });
53
+ beforeEach(() => {
54
+ vi.clearAllMocks();
55
+ });
56
+ it("should export the main server entry point", async () => {
57
+ const indexPath = path.join(sourceDir, "index.ts");
58
+ const exists = await fs.access(indexPath).then(() => true).catch(() => false);
59
+ expect(exists).toBe(true);
60
+ });
61
+ it("should have the correct shebang and imports", async () => {
62
+ const indexPath = path.join(sourceDir, "index.ts");
63
+ const content = await fs.readFile(indexPath, "utf-8");
64
+ expect(content.startsWith("#!/usr/bin/env node")).toBe(true);
65
+ expect(content).toContain("McpServer");
66
+ expect(content).toContain("StdioServerTransport");
67
+ expect(content).toContain("registerTools");
68
+ expect(content).toContain("registerResources");
69
+ expect(content).toContain("registerPrompts");
70
+ });
71
+ it("should define PROJITIVE_SPEC_VERSION as 1.1.0", async () => {
72
+ const indexPath = path.join(sourceDir, "index.ts");
73
+ const content = await fs.readFile(indexPath, "utf-8");
74
+ expect(content).toContain("PROJITIVE_SPEC_VERSION");
75
+ expect(content).toContain('"1.1.0"');
76
+ });
77
+ it("should have main function with server startup", async () => {
78
+ const indexPath = path.join(sourceDir, "index.ts");
79
+ const content = await fs.readFile(indexPath, "utf-8");
80
+ expect(content).toContain("async function main");
81
+ expect(content).toContain("server.connect");
82
+ expect(content).toContain("StdioServerTransport");
83
+ });
84
+ it("should register all tool categories", async () => {
85
+ const indexPath = path.join(sourceDir, "index.ts");
86
+ const content = await fs.readFile(indexPath, "utf-8");
87
+ expect(content).toContain("registerTools(server)");
88
+ expect(content).toContain("registerResources(server, repoRoot)");
89
+ expect(content).toContain("registerPrompts(server)");
90
+ expect(content).toContain("registerDesignContextResources(server)");
91
+ expect(content).toContain("registerDesignContextPrompts(server)");
92
+ });
93
+ it("should have proper error handling in main", async () => {
94
+ const indexPath = path.join(sourceDir, "index.ts");
95
+ const content = await fs.readFile(indexPath, "utf-8");
96
+ expect(content).toContain("void main().catch");
97
+ expect(content).toContain("console.error(\"Server error:\", error)");
98
+ expect(content).toContain("process.exit(1)");
99
+ });
100
+ it("should log server startup information", async () => {
101
+ const indexPath = path.join(sourceDir, "index.ts");
102
+ const content = await fs.readFile(indexPath, "utf-8");
103
+ expect(content).toContain("console.error(`[projitive-mcp] starting server`)");
104
+ expect(content).toContain("console.error(`[projitive-mcp] version=");
105
+ expect(content).toContain("spec=");
106
+ expect(content).toContain("transport=stdio");
107
+ expect(content).toContain("pid=");
108
+ });
109
+ it("should define MCP server with correct metadata", async () => {
110
+ const indexPath = path.join(sourceDir, "index.ts");
111
+ const content = await fs.readFile(indexPath, "utf-8");
112
+ expect(content).toContain("name: \"projitive\"");
113
+ expect(content).toContain("version: MCP_RUNTIME_VERSION");
114
+ expect(content).toContain("description:");
115
+ });
116
+ });
@@ -0,0 +1,9 @@
1
+ // Governance workflow prompts
2
+ import { registerQuickStartPrompt } from "./quickStart.js";
3
+ import { registerTaskDiscoveryPrompt } from "./taskDiscovery.js";
4
+ import { registerTaskExecutionPrompt } from "./taskExecution.js";
5
+ export function registerPrompts(server) {
6
+ registerQuickStartPrompt(server);
7
+ registerTaskDiscoveryPrompt(server);
8
+ registerTaskExecutionPrompt(server);
9
+ }
@@ -0,0 +1,94 @@
1
+ import { z } from "zod";
2
+ function asUserPrompt(text) {
3
+ return {
4
+ messages: [
5
+ {
6
+ role: "user",
7
+ content: {
8
+ type: "text",
9
+ text,
10
+ },
11
+ },
12
+ ],
13
+ };
14
+ }
15
+ export function registerQuickStartPrompt(server) {
16
+ server.registerPrompt("quickStart", {
17
+ title: "Quick Start",
18
+ description: "Complete workflow to discover project, load context, and start task execution",
19
+ argsSchema: {
20
+ projectPath: z.string().optional(),
21
+ },
22
+ }, async ({ projectPath }) => {
23
+ const text = [
24
+ "# How to Govern a Project",
25
+ "",
26
+ "You are a Projitive governance assistant. Here is the complete workflow:",
27
+ "",
28
+ "## Step 1: Discover the Project",
29
+ "",
30
+ projectPath
31
+ ? [
32
+ `- Known project path: "${projectPath}"`,
33
+ "- Call `projectContext(projectPath=\"" + projectPath + "\")` directly to load project overview",
34
+ ].join("\n")
35
+ : [
36
+ "- Unknown project path:",
37
+ " 1. Call `projectScan()` to discover all governance roots",
38
+ " 2. Select a target project",
39
+ " 3. Call `projectLocate(inputPath=\"<selected-path>\")` to lock governance root",
40
+ " 4. Call `projectContext(projectPath=\"<project-path>\")` to load project overview",
41
+ ].join("\n"),
42
+ "",
43
+ "## Step 2: Understand the Project",
44
+ "",
45
+ "After loading project context, read these resources:",
46
+ "- projitive://governance/workspace - Project overview",
47
+ "- projitive://governance/tasks - Current task pool",
48
+ "- projitive://governance/roadmap - Project roadmap",
49
+ "- projitive://designs/* - Design documents",
50
+ "",
51
+ "## Step 3: Discover Tasks",
52
+ "",
53
+ "Two ways to discover tasks:",
54
+ "",
55
+ "### Option A: Auto-select (Recommended)",
56
+ "Call `taskNext()` to get highest-priority actionable task.",
57
+ "",
58
+ "### Option B: Manual select",
59
+ "1. Call `taskList()` to list all tasks",
60
+ "2. Select a task based on status and priority",
61
+ "3. Call `taskContext(projectPath=\"...\", taskId=\"...\")` for details",
62
+ "",
63
+ "## Step 4: Execute the Task",
64
+ "",
65
+ "After getting task context:",
66
+ "1. Read evidence links in Suggested Read Order",
67
+ "2. Understand task requirements and acceptance criteria",
68
+ "3. Edit governance markdown only (tasks/designs/reports/roadmap)",
69
+ "4. Update task status:",
70
+ " - TODO → IN_PROGRESS (when starting execution)",
71
+ " - IN_PROGRESS → DONE (when completed)",
72
+ " - IN_PROGRESS → BLOCKED (when blocked)",
73
+ "5. Re-run taskContext() to verify changes",
74
+ "",
75
+ "## Special Cases",
76
+ "",
77
+ "### Case 1: No .projitive directory",
78
+ "Call `projectInit(projectPath=\"<project-dir>\")` to initialize governance structure.",
79
+ "",
80
+ "### Case 2: No actionable tasks",
81
+ "1. Check if tasks.md is missing",
82
+ "2. Read design documents in projitive://designs/",
83
+ "3. Create 1-3 new TODO tasks",
84
+ "",
85
+ "## Hard Rules",
86
+ "",
87
+ "- **NEVER modify TASK/ROADMAP IDs** - Keep them immutable once assigned",
88
+ "- **Every status transition must have report evidence** - Create execution reports in reports/ directory",
89
+ "- **Only edit files under .projitive/** - Unless task scope explicitly requires otherwise",
90
+ "- **Always verify after updates** - Re-run taskContext() to confirm reference consistency",
91
+ ].join("\n");
92
+ return asUserPrompt(text);
93
+ });
94
+ }
@@ -0,0 +1,190 @@
1
+ import { z } from "zod";
2
+ function asUserPrompt(text) {
3
+ return {
4
+ messages: [
5
+ {
6
+ role: "user",
7
+ content: {
8
+ type: "text",
9
+ text,
10
+ },
11
+ },
12
+ ],
13
+ };
14
+ }
15
+ export function registerTaskDiscoveryPrompt(server) {
16
+ server.registerPrompt("taskDiscovery", {
17
+ title: "Task Discovery",
18
+ description: "Minimal steps to find, context, and execute the first actionable task",
19
+ argsSchema: {
20
+ projectPath: z.string().optional(),
21
+ },
22
+ }, async ({ projectPath }) => {
23
+ const text = [
24
+ "# How to Discover Tasks",
25
+ "",
26
+ "You are a Projitive task discovery assistant. Here is the complete workflow to discover and execute your first task:",
27
+ "",
28
+ "## Step 1: Locate the Project",
29
+ "",
30
+ projectPath
31
+ ? [
32
+ `- Known project path: "${projectPath}"`,
33
+ "- Call `projectContext(projectPath=\"" + projectPath + "\")` directly to load project context",
34
+ ].join("\n")
35
+ : [
36
+ "- Unknown project path:",
37
+ " 1. Call `projectScan()` to discover all governance roots",
38
+ " 2. Select a project",
39
+ " 3. Call `projectLocate(inputPath=\"<selected-path>\")` to lock governance root",
40
+ " 4. Call `projectContext(projectPath=\"<project-path>\")` to load project context",
41
+ ].join("\n"),
42
+ "",
43
+ "## Step 2: Read Project Context",
44
+ "",
45
+ "After loading project context, focus on:",
46
+ "",
47
+ "### Task Summary",
48
+ "- total: Total tasks",
49
+ "- TODO: Pending tasks (highest priority)",
50
+ "- IN_PROGRESS: In-progress tasks (priority to continue)",
51
+ "- BLOCKED: Blocked tasks (need to resolve first)",
52
+ "- DONE: Completed tasks",
53
+ "",
54
+ "### Artifacts",
55
+ "Check if these files exist:",
56
+ "- \u2705 tasks.md - Task list (required)",
57
+ "- \u2705 roadmap.md - Roadmap",
58
+ "- \u2705 README.md - Project description",
59
+ "- \u2705 designs/ - Design documents directory",
60
+ "- \u2705 reports/ - Reports directory",
61
+ "",
62
+ "## Step 3: Select a Task",
63
+ "",
64
+ "### Priority Order",
65
+ "Select tasks in this priority order:",
66
+ "",
67
+ "1. **IN_PROGRESS** - Priority to continue in-progress tasks first",
68
+ " - These tasks have already started, should continue to finish",
69
+ " - Check updatedAt time, most recent first",
70
+ "",
71
+ "2. **TODO** - Next select pending tasks",
72
+ " - Tasks with roadmapRefs first",
73
+ " - Tasks with explicit owner first",
74
+ "",
75
+ "3. **BLOCKED** - Last consider blocked tasks",
76
+ " - Need to analyze blocker reason first",
77
+ " - May need to create sub-task to resolve blocker",
78
+ "",
79
+ "### Discovery Methods",
80
+ "",
81
+ "#### Method A: Auto-select with taskNext() (Recommended)",
82
+ "",
83
+ "Call `taskNext()`, the tool will automatically:",
84
+ "- Sort all tasks by priority",
85
+ "- Select highest-priority actionable task",
86
+ "- Return task ID and summary",
87
+ "",
88
+ "Then call `taskContext(projectPath=\"...\", taskId=\"<task-id>\")` for task details.",
89
+ "",
90
+ "#### Method B: Manual select with taskList()",
91
+ "",
92
+ "1. Call `taskList()` to get all tasks",
93
+ "2. Select based on these factors:",
94
+ " - status (IN_PROGRESS > TODO > BLOCKED)",
95
+ " - updatedAt time (most recent first)",
96
+ " - owner assigned (with owner first)",
97
+ " - roadmapRefs (with refs first)",
98
+ "3. Call `taskContext(projectPath=\"...\", taskId=\"<selected-id>\")` for details",
99
+ "",
100
+ "## Step 4: Understand Task Context",
101
+ "",
102
+ "After getting taskContext, read carefully:",
103
+ "",
104
+ "### Summary",
105
+ "- taskId: Task ID (NEVER modify this)",
106
+ "- status: Current status",
107
+ "- owner: Assignee",
108
+ "- roadmapRefs: Related roadmap",
109
+ "- updatedAt: Last updated time",
110
+ "",
111
+ "### Evidence",
112
+ "- Candidate Files - Related file list",
113
+ "- Reference Locations - Reference locations",
114
+ "",
115
+ "### Suggested Read Order",
116
+ "Read files in order, understand:",
117
+ "- Task background and motivation",
118
+ "- Task acceptance criteria",
119
+ "- Related design decisions",
120
+ "- Previous execution history",
121
+ "",
122
+ "### Lint Suggestions",
123
+ "Check if any warnings need to be resolved first.",
124
+ "",
125
+ "## Step 5: Execute the Task",
126
+ "",
127
+ "After understanding the task:",
128
+ "",
129
+ "1. **If status is TODO",
130
+ " - First call `taskUpdate()` to change status to IN_PROGRESS",
131
+ " - Set owner (if empty)",
132
+ " - Fill subState (optional, Spec v1.1.0)",
133
+ "",
134
+ "2. **If status is IN_PROGRESS",
135
+ " - Continue previous work",
136
+ " - Reference history reports in reports/",
137
+ "",
138
+ "3. **Execute task content**",
139
+ " - Edit governance files (tasks.md / designs/*.md / reports/*.md / roadmap.md)",
140
+ " - Create execution report (reports/ directory)",
141
+ " - Update task status to DONE",
142
+ "",
143
+ "4. **Verify changes**",
144
+ " - Re-run `taskContext()`",
145
+ " - Confirm all references still valid",
146
+ " - Confirm no new lint suggestions",
147
+ "",
148
+ "## Special Cases",
149
+ "",
150
+ "### Case 1: No tasks at all",
151
+ "",
152
+ "If taskNext() returns empty:",
153
+ "1. Check if tasks.md exists",
154
+ "2. Read design documents in designs/ directory",
155
+ "3. Read roadmap.md to understand project goals",
156
+ "4. Create 1-3 new TODO tasks",
157
+ "5. Each task must have:",
158
+ " - Unique TASK-xxxx ID",
159
+ " - Clear title",
160
+ " - Detailed summary",
161
+ " - Linked roadmapRefs (if applicable)",
162
+ "",
163
+ "### Case 2: All tasks are BLOCKED",
164
+ "",
165
+ "1. Select one blocked task and call `taskContext()`",
166
+ "2. Understand blocker reason (check blocker field, Spec v1.1.0)",
167
+ "3. Create a new TODO task to resolve blocker",
168
+ "4. Execute this new task first",
169
+ "",
170
+ "### Case 3: Missing required governance files",
171
+ "",
172
+ "If tasks.md does not exist:",
173
+ "1. Call `projectInit(projectPath=\"...\")` to initialize governance structure",
174
+ "2. Then restart discovery flow",
175
+ "",
176
+ "## Quick Reference",
177
+ "",
178
+ "| Tool | Purpose |",
179
+ "|------|---------|",
180
+ "| `projectScan()` | Discover all governance roots |",
181
+ "| `projectLocate()` | Lock governance root |",
182
+ "| `projectContext()` | Load project overview |",
183
+ "| `taskNext()` | Auto-select best task |",
184
+ "| `taskList()` | List all tasks |",
185
+ "| `taskContext()` | Get task details |",
186
+ "| `taskUpdate()` | Update task status |",
187
+ ].join("\n");
188
+ return asUserPrompt(text);
189
+ });
190
+ }