@projitive/mcp 1.0.5 → 1.0.7
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/README.md +4 -4
- package/output/package.json +1 -1
- package/output/source/design-context.js +4 -1
- package/output/source/index.js +10 -11
- package/output/source/projitive.js +55 -11
- package/output/source/projitive.test.js +36 -0
- package/output/source/roadmap.js +3 -3
- package/output/source/tasks.js +8 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Language: English | [简体中文](README_CN.md)
|
|
4
4
|
|
|
5
|
-
**Current Spec Version: projitive-spec v1.0.0 | MCP Version: 1.0.
|
|
5
|
+
**Current Spec Version: projitive-spec v1.0.0 | MCP Version: 1.0.7**
|
|
6
6
|
|
|
7
7
|
Projitive MCP server (semantic interface edition) helps agents discover projects, select tasks, locate evidence, and execute under governance workflows.
|
|
8
8
|
|
|
@@ -149,7 +149,7 @@ npm run test
|
|
|
149
149
|
#### `projectInit`
|
|
150
150
|
|
|
151
151
|
- **Purpose**: manually initialize governance directory structure for a project (default `.projitive`).
|
|
152
|
-
- **Input**: `projectPath
|
|
152
|
+
- **Input**: `projectPath`, `governanceDir?`, `force?`
|
|
153
153
|
- **Output Example (Markdown)**:
|
|
154
154
|
|
|
155
155
|
```markdown
|
|
@@ -177,7 +177,7 @@ npm run test
|
|
|
177
177
|
#### `projectNext`
|
|
178
178
|
|
|
179
179
|
- **Purpose**: directly list recently actionable projects (ranked by actionable task count and recency).
|
|
180
|
-
- **Input**: `
|
|
180
|
+
- **Input**: `maxDepth?`, `limit?`
|
|
181
181
|
- **Output Example (Markdown)**:
|
|
182
182
|
|
|
183
183
|
```markdown
|
|
@@ -294,7 +294,7 @@ npm run test
|
|
|
294
294
|
#### `taskNext`
|
|
295
295
|
|
|
296
296
|
- **Purpose**: one-step workflow for project discovery + best task selection + evidence/read-order output.
|
|
297
|
-
- **Input**: `
|
|
297
|
+
- **Input**: `maxDepth?`, `topCandidates?`
|
|
298
298
|
- **Output Example (Markdown)**:
|
|
299
299
|
|
|
300
300
|
```markdown
|
package/output/package.json
CHANGED
|
@@ -84,8 +84,11 @@ export function registerDesignContextPrompts(server) {
|
|
|
84
84
|
text: [
|
|
85
85
|
"Execute Projitive task with minimal calls:",
|
|
86
86
|
"",
|
|
87
|
+
"Prerequisite:",
|
|
88
|
+
"- If target project has no `.projitive`, run: projectInit(projectPath=<project-dir>)",
|
|
89
|
+
"",
|
|
87
90
|
"STEP 1: Get task (1 call)",
|
|
88
|
-
"- Run: taskNext(
|
|
91
|
+
"- Run: taskNext()",
|
|
89
92
|
"- Result: selectedTaskId, suggestedReadOrder",
|
|
90
93
|
"",
|
|
91
94
|
"STEP 2: Load context (1-2 calls)",
|
package/output/source/index.js
CHANGED
|
@@ -47,7 +47,7 @@ function renderMethodCatalogMarkdown() {
|
|
|
47
47
|
"## Start Here",
|
|
48
48
|
"- Unknown project path: `projectScan` -> `projectLocate` -> `projectContext` -> `taskNext`.",
|
|
49
49
|
"- Known project path: `projectContext` -> `taskNext` (or `taskList`) -> `taskContext`.",
|
|
50
|
-
"- Need to bootstrap governance: call `projectInit` only when `.projitive` is missing.",
|
|
50
|
+
"- Need to bootstrap governance: call `projectInit(projectPath=\"<project-dir>\")` only when `.projitive` is missing.",
|
|
51
51
|
"",
|
|
52
52
|
"## Methods",
|
|
53
53
|
"| Order | Group | Method | Agent Use |",
|
|
@@ -61,7 +61,7 @@ function renderMethodCatalogMarkdown() {
|
|
|
61
61
|
"| 7 | Roadmap | roadmapList | inspect roadmap-task linkage |",
|
|
62
62
|
"| 8 | Roadmap | roadmapContext | inspect one roadmap with references |",
|
|
63
63
|
"| 9 | Project | projectNext | rank actionable projects across workspace |",
|
|
64
|
-
"| 10 | Project | projectInit | bootstrap governance files if missing |"
|
|
64
|
+
"| 10 | Project | projectInit | bootstrap governance files if missing |"
|
|
65
65
|
].join("\n");
|
|
66
66
|
}
|
|
67
67
|
function registerGovernanceResources() {
|
|
@@ -132,14 +132,13 @@ function registerGovernancePrompts() {
|
|
|
132
132
|
title: "Execute Task Workflow",
|
|
133
133
|
description: "Primary execution prompt: select one task, execute, and verify evidence consistency",
|
|
134
134
|
argsSchema: {
|
|
135
|
-
rootPath: z.string().optional(),
|
|
136
135
|
projectPath: z.string().optional(),
|
|
137
136
|
taskId: z.string().optional(),
|
|
138
137
|
},
|
|
139
|
-
}, async ({
|
|
138
|
+
}, async ({ projectPath, taskId }) => {
|
|
140
139
|
const taskEntry = taskId && projectPath
|
|
141
140
|
? `1) Run taskContext(projectPath=\"${projectPath}\", taskId=\"${taskId}\").`
|
|
142
|
-
:
|
|
141
|
+
: "1) Run taskNext().";
|
|
143
142
|
const text = [
|
|
144
143
|
"You are executing Projitive governance workflow in agent-first mode.",
|
|
145
144
|
"",
|
|
@@ -150,6 +149,7 @@ function registerGovernancePrompts() {
|
|
|
150
149
|
"4) Re-run taskContext for the selected task and verify references.",
|
|
151
150
|
"",
|
|
152
151
|
"Fallbacks:",
|
|
152
|
+
"- If `.projitive` is missing for a known project, run `projectInit(projectPath=\"<project-dir>\")` first.",
|
|
153
153
|
"- If taskNext returns no actionable task, follow its no-task checklist and create 1-3 TODO tasks.",
|
|
154
154
|
"- If project is unknown, run projectScan -> projectLocate -> projectContext before task tools.",
|
|
155
155
|
"",
|
|
@@ -189,17 +189,16 @@ function registerGovernancePrompts() {
|
|
|
189
189
|
server.registerPrompt("triageProjectGovernance", {
|
|
190
190
|
title: "Triage Project Governance",
|
|
191
191
|
description: "Discovery-first triage prompt to pick project and next executable task",
|
|
192
|
-
argsSchema: {
|
|
193
|
-
|
|
194
|
-
},
|
|
195
|
-
}, async ({ rootPath }) => {
|
|
192
|
+
argsSchema: {},
|
|
193
|
+
}, async () => {
|
|
196
194
|
const text = [
|
|
197
195
|
"Triage governance and pick one execution target quickly.",
|
|
198
196
|
"",
|
|
197
|
+
"0) If known project has no `.projitive`, run projectInit(projectPath=<project-dir>) first.",
|
|
199
198
|
"1) If project path is unknown, run projectScan() and pick one discovered project.",
|
|
200
|
-
|
|
199
|
+
"2) Run projectNext() to rank projects.",
|
|
201
200
|
"3) Run projectContext(projectPath=<selectedProject>).",
|
|
202
|
-
"4) Run taskNext(
|
|
201
|
+
"4) Run taskNext() for best actionable task.",
|
|
203
202
|
"5) If manual filtering is needed, run taskList(projectPath=<selectedProject>, status=IN_PROGRESS).",
|
|
204
203
|
"6) Continue with taskContext(projectPath=<selectedProject>, taskId=<selectedTaskId>).",
|
|
205
204
|
].join("\n");
|
|
@@ -133,6 +133,41 @@ function parentDir(dirPath) {
|
|
|
133
133
|
const parent = path.dirname(dirPath);
|
|
134
134
|
return parent === dirPath ? null : parent;
|
|
135
135
|
}
|
|
136
|
+
export function toProjectPath(governanceDir) {
|
|
137
|
+
return path.dirname(governanceDir);
|
|
138
|
+
}
|
|
139
|
+
async function listChildGovernanceDirs(parentPath) {
|
|
140
|
+
const entriesResult = await catchIt(fs.readdir(parentPath, { withFileTypes: true }));
|
|
141
|
+
if (entriesResult.isError()) {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
const folders = entriesResult.value
|
|
145
|
+
.filter((entry) => entry.isDirectory())
|
|
146
|
+
.map((entry) => path.join(parentPath, entry.name));
|
|
147
|
+
const markerChecks = await Promise.all(folders.map(async (folderPath) => ({
|
|
148
|
+
folderPath,
|
|
149
|
+
hasMarker: await hasProjectMarker(folderPath),
|
|
150
|
+
})));
|
|
151
|
+
const candidates = markerChecks
|
|
152
|
+
.filter((item) => item.hasMarker)
|
|
153
|
+
.map((item) => item.folderPath)
|
|
154
|
+
.sort((a, b) => a.localeCompare(b));
|
|
155
|
+
return candidates;
|
|
156
|
+
}
|
|
157
|
+
async function resolveChildGovernanceDir(parentPath) {
|
|
158
|
+
const candidates = await listChildGovernanceDirs(parentPath);
|
|
159
|
+
if (candidates.length === 0) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
const defaultCandidate = path.join(parentPath, DEFAULT_GOVERNANCE_DIR);
|
|
163
|
+
if (candidates.includes(defaultCandidate)) {
|
|
164
|
+
return defaultCandidate;
|
|
165
|
+
}
|
|
166
|
+
if (candidates.length === 1) {
|
|
167
|
+
return candidates[0];
|
|
168
|
+
}
|
|
169
|
+
throw new Error(`Multiple governance roots found under path: ${parentPath}. Use projectPath/governanceDir explicitly.`);
|
|
170
|
+
}
|
|
136
171
|
export async function resolveGovernanceDir(inputPath) {
|
|
137
172
|
const absolutePath = path.resolve(inputPath);
|
|
138
173
|
const statResult = await catchIt(fs.stat(absolutePath));
|
|
@@ -145,6 +180,10 @@ export async function resolveGovernanceDir(inputPath) {
|
|
|
145
180
|
if (await hasProjectMarker(cursor)) {
|
|
146
181
|
return cursor;
|
|
147
182
|
}
|
|
183
|
+
const childGovernanceDir = await resolveChildGovernanceDir(cursor);
|
|
184
|
+
if (childGovernanceDir) {
|
|
185
|
+
return childGovernanceDir;
|
|
186
|
+
}
|
|
148
187
|
cursor = parentDir(cursor);
|
|
149
188
|
}
|
|
150
189
|
throw new Error(`No ${PROJECT_MARKER} marker found from path: ${absolutePath}`);
|
|
@@ -158,6 +197,8 @@ export async function discoverProjects(rootPath, maxDepth) {
|
|
|
158
197
|
if (await hasProjectMarker(currentPath)) {
|
|
159
198
|
results.push(currentPath);
|
|
160
199
|
}
|
|
200
|
+
const childGovernanceDirs = await listChildGovernanceDirs(currentPath);
|
|
201
|
+
results.push(...childGovernanceDirs);
|
|
161
202
|
const entriesResult = await catchIt(fs.readdir(currentPath, { withFileTypes: true }));
|
|
162
203
|
if (entriesResult.isError()) {
|
|
163
204
|
return;
|
|
@@ -274,9 +315,9 @@ export async function initializeProjectStructure(inputPath, governanceDir, force
|
|
|
274
315
|
export function registerProjectTools(server) {
|
|
275
316
|
server.registerTool("projectInit", {
|
|
276
317
|
title: "Project Init",
|
|
277
|
-
description: "Bootstrap governance files when a project has no .projitive yet",
|
|
318
|
+
description: "Bootstrap governance files when a project has no .projitive yet (requires projectPath)",
|
|
278
319
|
inputSchema: {
|
|
279
|
-
projectPath: z.string()
|
|
320
|
+
projectPath: z.string(),
|
|
280
321
|
governanceDir: z.string().optional(),
|
|
281
322
|
force: z.boolean().optional(),
|
|
282
323
|
},
|
|
@@ -313,7 +354,7 @@ export function registerProjectTools(server) {
|
|
|
313
354
|
"- After init, fill owner/roadmapRefs/links in tasks.md before marking DONE.",
|
|
314
355
|
"- Keep task source-of-truth inside marker block only.",
|
|
315
356
|
]),
|
|
316
|
-
nextCallSection(`projectContext(projectPath=\"${initialized.
|
|
357
|
+
nextCallSection(`projectContext(projectPath=\"${initialized.projectPath}\")`),
|
|
317
358
|
],
|
|
318
359
|
});
|
|
319
360
|
return asText(markdown);
|
|
@@ -356,12 +397,11 @@ export function registerProjectTools(server) {
|
|
|
356
397
|
title: "Project Next",
|
|
357
398
|
description: "Rank actionable projects and return the best execution target",
|
|
358
399
|
inputSchema: {
|
|
359
|
-
rootPath: z.string().optional(),
|
|
360
400
|
maxDepth: z.number().int().min(0).max(8).optional(),
|
|
361
401
|
limit: z.number().int().min(1).max(50).optional(),
|
|
362
402
|
},
|
|
363
|
-
}, async ({
|
|
364
|
-
const root = resolveScanRoot(
|
|
403
|
+
}, async ({ maxDepth, limit }) => {
|
|
404
|
+
const root = resolveScanRoot();
|
|
365
405
|
const depth = resolveScanDepth(maxDepth);
|
|
366
406
|
const projects = await discoverProjects(root, depth);
|
|
367
407
|
const snapshots = await Promise.all(projects.map(async (governanceDir) => {
|
|
@@ -409,13 +449,13 @@ export function registerProjectTools(server) {
|
|
|
409
449
|
...ranked.map((item, index) => `${index + 1}. ${item.governanceDir} | actionable=${item.actionable} | in_progress=${item.inProgress} | todo=${item.todo} | blocked=${item.blocked} | done=${item.done} | latest=${item.latestUpdatedAt} | tasksPath=${item.tasksPath}${item.tasksExists ? "" : " (missing)"}`),
|
|
410
450
|
]),
|
|
411
451
|
guidanceSection([
|
|
412
|
-
"- Pick top 1 project and call `projectContext` with its
|
|
452
|
+
"- Pick top 1 project and call `projectContext` with its projectPath.",
|
|
413
453
|
"- Then call `taskList` and `taskContext` to continue execution.",
|
|
414
454
|
"- If `tasksPath` is missing, create tasks.md using project convention before task-level operations.",
|
|
415
455
|
]),
|
|
416
456
|
lintSection(ranked[0]?.lintSuggestions ?? []),
|
|
417
457
|
nextCallSection(ranked[0]
|
|
418
|
-
? `projectContext(projectPath=\"${ranked[0].governanceDir}\")`
|
|
458
|
+
? `projectContext(projectPath=\"${toProjectPath(ranked[0].governanceDir)}\")`
|
|
419
459
|
: undefined),
|
|
420
460
|
],
|
|
421
461
|
});
|
|
@@ -430,18 +470,20 @@ export function registerProjectTools(server) {
|
|
|
430
470
|
}, async ({ inputPath }) => {
|
|
431
471
|
const resolvedFrom = normalizePath(inputPath);
|
|
432
472
|
const governanceDir = await resolveGovernanceDir(resolvedFrom);
|
|
473
|
+
const projectPath = toProjectPath(governanceDir);
|
|
433
474
|
const markerPath = path.join(governanceDir, ".projitive");
|
|
434
475
|
const markdown = renderToolResponseMarkdown({
|
|
435
476
|
toolName: "projectLocate",
|
|
436
477
|
sections: [
|
|
437
478
|
summarySection([
|
|
438
479
|
`- resolvedFrom: ${resolvedFrom}`,
|
|
480
|
+
`- projectPath: ${projectPath}`,
|
|
439
481
|
`- governanceDir: ${governanceDir}`,
|
|
440
482
|
`- markerPath: ${markerPath}`,
|
|
441
483
|
]),
|
|
442
|
-
guidanceSection(["- Call `projectContext` with this
|
|
484
|
+
guidanceSection(["- Call `projectContext` with this projectPath to get task and roadmap summaries."]),
|
|
443
485
|
lintSection(["- Run `projectContext` to get governance/module lint suggestions for this project."]),
|
|
444
|
-
nextCallSection(`projectContext(projectPath=\"${
|
|
486
|
+
nextCallSection(`projectContext(projectPath=\"${projectPath}\")`),
|
|
445
487
|
],
|
|
446
488
|
});
|
|
447
489
|
return asText(markdown);
|
|
@@ -454,6 +496,7 @@ export function registerProjectTools(server) {
|
|
|
454
496
|
},
|
|
455
497
|
}, async ({ projectPath }) => {
|
|
456
498
|
const governanceDir = await resolveGovernanceDir(projectPath);
|
|
499
|
+
const normalizedProjectPath = toProjectPath(governanceDir);
|
|
457
500
|
const artifacts = await discoverGovernanceArtifacts(governanceDir);
|
|
458
501
|
const { tasksPath, tasks, markdown: tasksMarkdown } = await loadTasksDocument(governanceDir);
|
|
459
502
|
const roadmapIds = await readRoadmapIds(governanceDir);
|
|
@@ -469,6 +512,7 @@ export function registerProjectTools(server) {
|
|
|
469
512
|
toolName: "projectContext",
|
|
470
513
|
sections: [
|
|
471
514
|
summarySection([
|
|
515
|
+
`- projectPath: ${normalizedProjectPath}`,
|
|
472
516
|
`- governanceDir: ${governanceDir}`,
|
|
473
517
|
`- tasksFile: ${tasksPath}`,
|
|
474
518
|
`- roadmapIds: ${roadmapIds.length}`,
|
|
@@ -489,7 +533,7 @@ export function registerProjectTools(server) {
|
|
|
489
533
|
"- Then call `taskContext` with a task ID to retrieve evidence locations and reading order.",
|
|
490
534
|
]),
|
|
491
535
|
lintSection(lintSuggestions),
|
|
492
|
-
nextCallSection(`taskList(projectPath=\"${
|
|
536
|
+
nextCallSection(`taskList(projectPath=\"${normalizedProjectPath}\")`),
|
|
493
537
|
],
|
|
494
538
|
});
|
|
495
539
|
return asText(markdown);
|
|
@@ -31,6 +31,24 @@ describe("projitive module", () => {
|
|
|
31
31
|
const resolved = await resolveGovernanceDir(deepDir);
|
|
32
32
|
expect(resolved).toBe(governanceDir);
|
|
33
33
|
});
|
|
34
|
+
it("resolves nested default governance dir when input path is project root", async () => {
|
|
35
|
+
const root = await createTempDir();
|
|
36
|
+
const projectRoot = path.join(root, "repo");
|
|
37
|
+
const governanceDir = path.join(projectRoot, ".projitive");
|
|
38
|
+
await fs.mkdir(governanceDir, { recursive: true });
|
|
39
|
+
await fs.writeFile(path.join(governanceDir, ".projitive"), "", "utf-8");
|
|
40
|
+
const resolved = await resolveGovernanceDir(projectRoot);
|
|
41
|
+
expect(resolved).toBe(governanceDir);
|
|
42
|
+
});
|
|
43
|
+
it("resolves nested custom governance dir when input path is project root", async () => {
|
|
44
|
+
const root = await createTempDir();
|
|
45
|
+
const projectRoot = path.join(root, "repo");
|
|
46
|
+
const governanceDir = path.join(projectRoot, "governance");
|
|
47
|
+
await fs.mkdir(governanceDir, { recursive: true });
|
|
48
|
+
await fs.writeFile(path.join(governanceDir, ".projitive"), "", "utf-8");
|
|
49
|
+
const resolved = await resolveGovernanceDir(projectRoot);
|
|
50
|
+
expect(resolved).toBe(governanceDir);
|
|
51
|
+
});
|
|
34
52
|
it("discovers projects by marker file", async () => {
|
|
35
53
|
const root = await createTempDir();
|
|
36
54
|
const p1 = path.join(root, "a");
|
|
@@ -43,6 +61,24 @@ describe("projitive module", () => {
|
|
|
43
61
|
expect(projects).toContain(p1);
|
|
44
62
|
expect(projects).toContain(p2);
|
|
45
63
|
});
|
|
64
|
+
it("discovers nested default governance directory under project root", async () => {
|
|
65
|
+
const root = await createTempDir();
|
|
66
|
+
const projectRoot = path.join(root, "app");
|
|
67
|
+
const governanceDir = path.join(projectRoot, ".projitive");
|
|
68
|
+
await fs.mkdir(governanceDir, { recursive: true });
|
|
69
|
+
await fs.writeFile(path.join(governanceDir, ".projitive"), "", "utf-8");
|
|
70
|
+
const projects = await discoverProjects(root, 3);
|
|
71
|
+
expect(projects).toContain(governanceDir);
|
|
72
|
+
});
|
|
73
|
+
it("discovers nested custom governance directory under project root", async () => {
|
|
74
|
+
const root = await createTempDir();
|
|
75
|
+
const projectRoot = path.join(root, "app");
|
|
76
|
+
const governanceDir = path.join(projectRoot, "governance");
|
|
77
|
+
await fs.mkdir(governanceDir, { recursive: true });
|
|
78
|
+
await fs.writeFile(path.join(governanceDir, ".projitive"), "", "utf-8");
|
|
79
|
+
const projects = await discoverProjects(root, 3);
|
|
80
|
+
expect(projects).toContain(governanceDir);
|
|
81
|
+
});
|
|
46
82
|
it("initializes governance structure under default .projitive directory", async () => {
|
|
47
83
|
const root = await createTempDir();
|
|
48
84
|
const initialized = await initializeProjectStructure(root);
|
package/output/source/roadmap.js
CHANGED
|
@@ -6,7 +6,7 @@ import { discoverGovernanceArtifacts } from "./helpers/files/index.js";
|
|
|
6
6
|
import { ROADMAP_LINT_CODES, renderLintSuggestions } from "./helpers/linter/index.js";
|
|
7
7
|
import { findTextReferences } from "./helpers/markdown/index.js";
|
|
8
8
|
import { asText, evidenceSection, guidanceSection, lintSection, nextCallSection, renderErrorMarkdown, renderToolResponseMarkdown, summarySection, } from "./helpers/response/index.js";
|
|
9
|
-
import { resolveGovernanceDir } from "./projitive.js";
|
|
9
|
+
import { resolveGovernanceDir, toProjectPath } from "./projitive.js";
|
|
10
10
|
import { loadTasks } from "./tasks.js";
|
|
11
11
|
export const ROADMAP_ID_REGEX = /^ROADMAP-\d{4}$/;
|
|
12
12
|
function collectRoadmapLintSuggestionItems(roadmapIds, tasks) {
|
|
@@ -99,7 +99,7 @@ export function registerRoadmapTools(server) {
|
|
|
99
99
|
guidanceSection(["- Pick one roadmap ID and call `roadmapContext`."]),
|
|
100
100
|
lintSection(lintSuggestions),
|
|
101
101
|
nextCallSection(roadmapIds[0]
|
|
102
|
-
? `roadmapContext(projectPath=\"${governanceDir}\", roadmapId=\"${roadmapIds[0]}\")`
|
|
102
|
+
? `roadmapContext(projectPath=\"${toProjectPath(governanceDir)}\", roadmapId=\"${roadmapIds[0]}\")`
|
|
103
103
|
: undefined),
|
|
104
104
|
],
|
|
105
105
|
});
|
|
@@ -157,7 +157,7 @@ export function registerRoadmapTools(server) {
|
|
|
157
157
|
"- Re-run `roadmapContext` after edits to confirm references remain consistent.",
|
|
158
158
|
]),
|
|
159
159
|
lintSection(lintSuggestions),
|
|
160
|
-
nextCallSection(`roadmapContext(projectPath=\"${governanceDir}\", roadmapId=\"${roadmapId}\")`),
|
|
160
|
+
nextCallSection(`roadmapContext(projectPath=\"${toProjectPath(governanceDir)}\", roadmapId=\"${roadmapId}\")`),
|
|
161
161
|
],
|
|
162
162
|
});
|
|
163
163
|
return asText(markdown);
|
package/output/source/tasks.js
CHANGED
|
@@ -7,7 +7,7 @@ import { findTextReferences } from "./helpers/markdown/index.js";
|
|
|
7
7
|
import { asText, evidenceSection, guidanceSection, lintSection, nextCallSection, renderErrorMarkdown, renderToolResponseMarkdown, summarySection, } from "./helpers/response/index.js";
|
|
8
8
|
import { catchIt } from "./helpers/catch/index.js";
|
|
9
9
|
import { TASK_LINT_CODES, renderLintSuggestions } from "./helpers/linter/index.js";
|
|
10
|
-
import { resolveGovernanceDir, resolveScanDepth, resolveScanRoot, discoverProjects } from "./projitive.js";
|
|
10
|
+
import { resolveGovernanceDir, resolveScanDepth, resolveScanRoot, discoverProjects, toProjectPath } from "./projitive.js";
|
|
11
11
|
import { isValidRoadmapId } from "./roadmap.js";
|
|
12
12
|
export const TASKS_START = "<!-- PROJITIVE:TASKS:START -->";
|
|
13
13
|
export const TASKS_END = "<!-- PROJITIVE:TASKS:END -->";
|
|
@@ -535,7 +535,7 @@ export function registerTaskTools(server) {
|
|
|
535
535
|
guidanceSection(["- Pick one task ID and call `taskContext`."]),
|
|
536
536
|
lintSection(lintSuggestions),
|
|
537
537
|
nextCallSection(nextTaskId
|
|
538
|
-
? `taskContext(projectPath=\"${governanceDir}\", taskId=\"${nextTaskId}\")`
|
|
538
|
+
? `taskContext(projectPath=\"${toProjectPath(governanceDir)}\", taskId=\"${nextTaskId}\")`
|
|
539
539
|
: undefined),
|
|
540
540
|
],
|
|
541
541
|
});
|
|
@@ -545,12 +545,11 @@ export function registerTaskTools(server) {
|
|
|
545
545
|
title: "Task Next",
|
|
546
546
|
description: "Start here to auto-select the highest-priority actionable task",
|
|
547
547
|
inputSchema: {
|
|
548
|
-
rootPath: z.string().optional(),
|
|
549
548
|
maxDepth: z.number().int().min(0).max(8).optional(),
|
|
550
549
|
topCandidates: z.number().int().min(1).max(20).optional(),
|
|
551
550
|
},
|
|
552
|
-
}, async ({
|
|
553
|
-
const root = resolveScanRoot(
|
|
551
|
+
}, async ({ maxDepth, topCandidates }) => {
|
|
552
|
+
const root = resolveScanRoot();
|
|
554
553
|
const depth = resolveScanDepth(maxDepth);
|
|
555
554
|
const projects = await discoverProjects(root, depth);
|
|
556
555
|
const rankedCandidates = rankActionableTaskCandidates(await readActionableTaskCandidates(projects));
|
|
@@ -610,7 +609,7 @@ export function registerTaskTools(server) {
|
|
|
610
609
|
"- Ensure each new task has stable TASK-xxxx ID and at least one roadmapRefs item.",
|
|
611
610
|
]),
|
|
612
611
|
nextCallSection(preferredProject
|
|
613
|
-
? `projectContext(projectPath=\"${preferredProject.governanceDir}\")`
|
|
612
|
+
? `projectContext(projectPath=\"${toProjectPath(preferredProject.governanceDir)}\")`
|
|
614
613
|
: "projectScan()"),
|
|
615
614
|
],
|
|
616
615
|
});
|
|
@@ -673,7 +672,7 @@ export function registerTaskTools(server) {
|
|
|
673
672
|
"- Re-run `taskContext` for the selectedTaskId after edits to verify evidence consistency.",
|
|
674
673
|
]),
|
|
675
674
|
lintSection(lintSuggestions),
|
|
676
|
-
nextCallSection(`taskContext(projectPath=\"${selected.governanceDir}\", taskId=\"${selected.task.id}\")`),
|
|
675
|
+
nextCallSection(`taskContext(projectPath=\"${toProjectPath(selected.governanceDir)}\", taskId=\"${selected.task.id}\")`),
|
|
677
676
|
],
|
|
678
677
|
});
|
|
679
678
|
return asText(markdown);
|
|
@@ -697,7 +696,7 @@ export function registerTaskTools(server) {
|
|
|
697
696
|
const task = tasks.find((item) => item.id === taskId);
|
|
698
697
|
if (!task) {
|
|
699
698
|
return {
|
|
700
|
-
...asText(renderErrorMarkdown("taskContext", `Task not found: ${taskId}`, ["run `taskList` to discover available IDs", "retry with an existing task ID"], `taskList(projectPath=\"${governanceDir}\")`)),
|
|
699
|
+
...asText(renderErrorMarkdown("taskContext", `Task not found: ${taskId}`, ["run `taskList` to discover available IDs", "retry with an existing task ID"], `taskList(projectPath=\"${toProjectPath(governanceDir)}\")`)),
|
|
701
700
|
isError: true,
|
|
702
701
|
};
|
|
703
702
|
}
|
|
@@ -754,7 +753,7 @@ export function registerTaskTools(server) {
|
|
|
754
753
|
"- After editing, re-run `taskContext` to verify references and context consistency.",
|
|
755
754
|
]),
|
|
756
755
|
lintSection(lintSuggestions),
|
|
757
|
-
nextCallSection(`taskContext(projectPath=\"${governanceDir}\", taskId=\"${task.id}\")`),
|
|
756
|
+
nextCallSection(`taskContext(projectPath=\"${toProjectPath(governanceDir)}\", taskId=\"${task.id}\")`),
|
|
758
757
|
],
|
|
759
758
|
});
|
|
760
759
|
return asText(coreMarkdown);
|