@projitive/mcp 1.1.1 → 1.1.2

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projitive/mcp",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Projitive MCP Server for project and task discovery/update",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -4,7 +4,6 @@ export * from "./utils.js";
4
4
  export * from "./markdown.js";
5
5
  export * from "./files.js";
6
6
  export * from "./response.js";
7
- export * from "./confidence.js";
8
7
  export * from "./catch.js";
9
8
  export * from "./artifacts.js";
10
9
  export * from "./linter.js";
@@ -6,9 +6,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
7
  import packageJson from "../package.json" with { type: "json" };
8
8
  import { registerTools } from "./tools/index.js";
9
- import { registerResources } from "./resources/index.js";
10
9
  import { registerPrompts } from "./prompts/index.js";
11
- import { registerDesignContextResources, registerDesignContextPrompts } from "./design-context.js";
10
+ import { registerResources } from "./resources/index.js";
12
11
  const PROJITIVE_SPEC_VERSION = "1.1.0";
13
12
  const currentFilePath = fileURLToPath(import.meta.url);
14
13
  const sourceDir = path.dirname(currentFilePath);
@@ -21,12 +20,10 @@ const server = new McpServer({
21
20
  version: MCP_RUNTIME_VERSION,
22
21
  description: "Semantic Projitive MCP for project/task discovery and agent guidance with markdown-first outputs",
23
22
  });
24
- // Register all modules
23
+ // 注册所有模块
25
24
  registerTools(server);
26
- registerResources(server, repoRoot);
27
25
  registerPrompts(server);
28
- registerDesignContextResources(server);
29
- registerDesignContextPrompts(server);
26
+ registerResources(server, repoRoot);
30
27
  async function main() {
31
28
  console.error(`[projitive-mcp] starting server`);
32
29
  console.error(`[projitive-mcp] version=${MCP_RUNTIME_VERSION} spec=${PROJITIVE_SPEC_VERSION} transport=stdio pid=${process.pid}`);
@@ -26,10 +26,6 @@ vi.mock("./tools/task.js", () => ({
26
26
  vi.mock("./tools/roadmap.js", () => ({
27
27
  registerRoadmapTools: vi.fn(),
28
28
  }));
29
- vi.mock("./design-context.js", () => ({
30
- registerDesignContextResources: vi.fn(),
31
- registerDesignContextPrompts: vi.fn(),
32
- }));
33
29
  vi.mock("./resources/governance.js", () => ({
34
30
  registerGovernanceResources: vi.fn(),
35
31
  }));
@@ -87,8 +83,6 @@ describe("index module", () => {
87
83
  expect(content).toContain("registerTools(server)");
88
84
  expect(content).toContain("registerResources(server, repoRoot)");
89
85
  expect(content).toContain("registerPrompts(server)");
90
- expect(content).toContain("registerDesignContextResources(server)");
91
- expect(content).toContain("registerDesignContextPrompts(server)");
92
86
  });
93
87
  it("should have proper error handling in main", async () => {
94
88
  const indexPath = path.join(sourceDir, "index.ts");
@@ -7,7 +7,6 @@ import { catchIt, TASK_LINT_CODES, renderLintSuggestions } from "../common/index
7
7
  import { resolveGovernanceDir, resolveScanDepth, resolveScanRoot, discoverProjects, toProjectPath } from "./project.js";
8
8
  import { isValidRoadmapId } from "./roadmap.js";
9
9
  import { SUB_STATE_PHASES, BLOCKER_TYPES } from "../types.js";
10
- import { calculateConfidenceScore, calculateContextCompleteness, calculateSimilarTaskHistory, calculateSpecificationClarity, getOrCreateTaskAutoCreateValidationHook, runPreCreationValidation, generateConfidenceReport } from "../common/index.js";
11
10
  export const TASKS_START = "<!-- PROJITIVE:TASKS:START -->";
12
11
  export const TASKS_END = "<!-- PROJITIVE:TASKS:END -->";
13
12
  export const ALLOWED_STATUS = ["TODO", "IN_PROGRESS", "BLOCKED", "DONE"];
@@ -51,7 +50,7 @@ const NO_TASK_DISCOVERY_HOOK_FILE = "task_no_actionable.md";
51
50
  const DEFAULT_NO_TASK_DISCOVERY_GUIDANCE = [
52
51
  "- Check whether current code violates project guide/spec conventions; create TODO tasks for each actionable gap.",
53
52
  "- Check unit/integration test coverage and identify high-value missing tests; create TODO tasks for meaningful coverage improvements.",
54
- "- Check development/testing workflow for bottlenecks (slow feedback, fragile scripts, unclear runbooks); create TODO tasks to improve reliability.",
53
+ "- Check development/testing workflow for bottlenecks (slow feedback, fragile scripts, unclear runbooks); create tasks to improve reliability.",
55
54
  "- Scan for TODO/FIXME/HACK comments and convert feasible items into governed TODO tasks with evidence links.",
56
55
  "- Check dependency freshness and security advisories; create tasks for safe upgrades when needed.",
57
56
  "- Check repeated manual operations that can be automated (lint/test/release checks); create tasks to reduce operational toil.",
@@ -1205,111 +1204,4 @@ export function registerTaskTools(server) {
1205
1204
  });
1206
1205
  return asText(markdown);
1207
1206
  });
1208
- // ============================================================================
1209
- // Spec v1.1.0 - Confidence Scoring Tools
1210
- // ============================================================================
1211
- server.registerTool("taskCalculateConfidence", {
1212
- title: "Calculate Task Confidence",
1213
- description: "Calculate confidence score for auto-creating a new task (Spec v1.1.0)",
1214
- inputSchema: {
1215
- projectPath: z.string(),
1216
- candidateTaskSummary: z.string(),
1217
- contextCompleteness: z.number().min(0).max(1).optional(),
1218
- similarTaskHistory: z.number().min(0).max(1).optional(),
1219
- specificationClarity: z.number().min(0).max(1).optional(),
1220
- },
1221
- }, async ({ projectPath, candidateTaskSummary, contextCompleteness, similarTaskHistory, specificationClarity }) => {
1222
- const governanceDir = await resolveGovernanceDir(projectPath);
1223
- const { tasks } = await loadTasks(governanceDir);
1224
- // Calculate factors if not provided
1225
- const calculatedContextCompleteness = contextCompleteness ?? await calculateContextCompleteness(governanceDir);
1226
- const calculatedSimilarTaskHistory = similarTaskHistory ?? calculateSimilarTaskHistory(tasks, candidateTaskSummary);
1227
- const calculatedSpecificationClarity = specificationClarity ?? calculateSpecificationClarity({
1228
- hasRoadmap: true, // Assume roadmap exists for simplicity
1229
- hasDesignDocs: true,
1230
- hasClearAcceptanceCriteria: candidateTaskSummary.length > 50,
1231
- });
1232
- const factors = {
1233
- contextCompleteness: calculatedContextCompleteness,
1234
- similarTaskHistory: calculatedSimilarTaskHistory,
1235
- specificationClarity: calculatedSpecificationClarity,
1236
- };
1237
- const confidenceScore = calculateConfidenceScore(factors);
1238
- const validationResult = await runPreCreationValidation(governanceDir, confidenceScore);
1239
- const hookContent = await getOrCreateTaskAutoCreateValidationHook(governanceDir);
1240
- const markdown = renderToolResponseMarkdown({
1241
- toolName: "taskCalculateConfidence",
1242
- sections: [
1243
- summarySection([
1244
- `- governanceDir: ${governanceDir}`,
1245
- `- confidenceScore: ${(confidenceScore.score * 100).toFixed(0)}%`,
1246
- `- recommendation: ${confidenceScore.recommendation}`,
1247
- `- validationPassed: ${validationResult.passed}`,
1248
- ]),
1249
- evidenceSection([
1250
- "### Confidence Report",
1251
- ...generateConfidenceReport(confidenceScore).split("\n"),
1252
- "",
1253
- "### Validation Issues",
1254
- ...(validationResult.issues.length > 0
1255
- ? validationResult.issues.map(issue => `- ${issue}`)
1256
- : ["- (none)"]),
1257
- "",
1258
- "### Validation Hook",
1259
- "- hook created/verified at: hooks/task_auto_create_validation.md",
1260
- ]),
1261
- guidanceSection([
1262
- confidenceScore.recommendation === "auto_create"
1263
- ? "✅ Confidence is high - you can auto-create this task."
1264
- : confidenceScore.recommendation === "review_required"
1265
- ? "⚠️ Confidence is medium - review recommended before creating."
1266
- : "❌ Confidence is low - do not auto-create this task.",
1267
- "",
1268
- "### Next Steps",
1269
- "- If recommendation is auto_create: use taskUpdate or manually add the task",
1270
- "- If review_required: review the factors and improve context before creating",
1271
- "- If do_not_create: gather more requirements or context before attempting",
1272
- ]),
1273
- lintSection([]),
1274
- nextCallSection(confidenceScore.recommendation !== "do_not_create"
1275
- ? `projectContext(projectPath=\"${toProjectPath(governanceDir)}\")`
1276
- : undefined),
1277
- ],
1278
- });
1279
- return asText(markdown);
1280
- });
1281
- server.registerTool("taskCreateValidationHook", {
1282
- title: "Create Validation Hook",
1283
- description: "Create or update the task auto-create validation hook (Spec v1.1.0)",
1284
- inputSchema: {
1285
- projectPath: z.string(),
1286
- },
1287
- }, async ({ projectPath }) => {
1288
- const governanceDir = await resolveGovernanceDir(projectPath);
1289
- const hookContent = await getOrCreateTaskAutoCreateValidationHook(governanceDir);
1290
- const markdown = renderToolResponseMarkdown({
1291
- toolName: "taskCreateValidationHook",
1292
- sections: [
1293
- summarySection([
1294
- `- governanceDir: ${governanceDir}`,
1295
- `- hookPath: ${governanceDir}/hooks/task_auto_create_validation.md`,
1296
- `- status: created/verified`,
1297
- ]),
1298
- evidenceSection([
1299
- "### Hook Content",
1300
- "```markdown",
1301
- ...hookContent.split("\n"),
1302
- "```",
1303
- ]),
1304
- guidanceSection([
1305
- "Validation hook created successfully.",
1306
- "Edit the hook file to customize pre-creation and post-creation actions.",
1307
- "The hook will be used by taskCalculateConfidence for validation.",
1308
- ]),
1309
- lintSection([]),
1310
- nextCallSection(`taskCalculateConfidence(projectPath=\"${toProjectPath(governanceDir)}\", candidateTaskSummary=\"Your task summary here\")`),
1311
- ],
1312
- });
1313
- return asText(markdown);
1314
- });
1315
1207
  }
@@ -26,17 +26,6 @@ export const BLOCKER_TYPES = [
26
26
  "resource",
27
27
  "approval"
28
28
  ];
29
- // Weight factors for confidence calculation
30
- export const CONFIDENCE_WEIGHTS = {
31
- contextCompleteness: 0.4,
32
- similarTaskHistory: 0.3,
33
- specificationClarity: 0.3,
34
- };
35
- // Confidence thresholds
36
- export const CONFIDENCE_THRESHOLDS = {
37
- autoCreate: 0.85,
38
- reviewRequired: 0.6,
39
- };
40
29
  // ============================================================================
41
30
  // Parser Constants
42
31
  // ============================================================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projitive/mcp",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Projitive MCP Server for project and task discovery/update",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -1,231 +0,0 @@
1
- /**
2
- * Projitive MCP - Confidence Scoring for Spec v1.1.0
3
- *
4
- * This module implements the confidence scoring algorithm for auto-discovery
5
- * and task creation, along with validation hooks integration.
6
- */
7
- import fs from "node:fs/promises";
8
- import path from "node:path";
9
- import { CONFIDENCE_WEIGHTS, CONFIDENCE_THRESHOLDS } from "../types.js";
10
- // ============================================================================
11
- // Confidence Scoring Algorithm
12
- // ============================================================================
13
- /**
14
- * Calculate confidence score based on the three factors
15
- * Formula: context_completeness * 0.4 + similar_task_history * 0.3 + specification_clarity * 0.3
16
- */
17
- export function calculateConfidenceScore(factors) {
18
- // Validate input ranges
19
- const validateFactor = (value, name) => {
20
- if (value < 0 || value > 1) {
21
- console.warn(`[Confidence] ${name} value ${value} is outside [0, 1] range, clamping`);
22
- return Math.max(0, Math.min(1, value));
23
- }
24
- return value;
25
- };
26
- const contextCompleteness = validateFactor(factors.contextCompleteness, "contextCompleteness");
27
- const similarTaskHistory = validateFactor(factors.similarTaskHistory, "similarTaskHistory");
28
- const specificationClarity = validateFactor(factors.specificationClarity, "specificationClarity");
29
- // Calculate weighted score
30
- const score = contextCompleteness * CONFIDENCE_WEIGHTS.contextCompleteness +
31
- similarTaskHistory * CONFIDENCE_WEIGHTS.similarTaskHistory +
32
- specificationClarity * CONFIDENCE_WEIGHTS.specificationClarity;
33
- // Determine recommendation
34
- let recommendation;
35
- if (score >= CONFIDENCE_THRESHOLDS.autoCreate) {
36
- recommendation = "auto_create";
37
- }
38
- else if (score >= CONFIDENCE_THRESHOLDS.reviewRequired) {
39
- recommendation = "review_required";
40
- }
41
- else {
42
- recommendation = "do_not_create";
43
- }
44
- return {
45
- score,
46
- factors: {
47
- contextCompleteness,
48
- similarTaskHistory,
49
- specificationClarity,
50
- },
51
- recommendation,
52
- };
53
- }
54
- // ============================================================================
55
- // Factor Calculation Helpers
56
- // ============================================================================
57
- /**
58
- * Calculate context completeness factor by checking available governance artifacts
59
- */
60
- export async function calculateContextCompleteness(governanceDir) {
61
- const requiredFiles = [
62
- "tasks.md",
63
- "roadmap.md",
64
- "README.md"
65
- ];
66
- const optionalFiles = [
67
- "hooks/task_no_actionable.md",
68
- "hooks/task_auto_create_validation.md"
69
- ];
70
- let availableCount = 0;
71
- const totalFiles = requiredFiles.length + optionalFiles.length;
72
- // Check required files
73
- for (const file of requiredFiles) {
74
- const filePath = path.join(governanceDir, file);
75
- try {
76
- await fs.access(filePath);
77
- availableCount++;
78
- }
79
- catch {
80
- // File doesn't exist
81
- }
82
- }
83
- // Check optional files (weighted 0.5 each)
84
- for (const file of optionalFiles) {
85
- const filePath = path.join(governanceDir, file);
86
- try {
87
- await fs.access(filePath);
88
- availableCount += 0.5;
89
- }
90
- catch {
91
- // File doesn't exist
92
- }
93
- }
94
- return Math.min(1, availableCount / totalFiles);
95
- }
96
- /**
97
- * Calculate similar task history success rate
98
- */
99
- export function calculateSimilarTaskHistory(tasks, candidateTaskSummary) {
100
- // Filter similar tasks based on keyword matching
101
- const keywords = candidateTaskSummary.toLowerCase().split(/\s+/).filter(w => w.length > 3);
102
- const similarTasks = tasks.filter(task => {
103
- const taskText = `${task.title} ${task.summary}`.toLowerCase();
104
- return keywords.some(keyword => taskText.includes(keyword));
105
- });
106
- if (similarTasks.length === 0) {
107
- return 0.5; // Neutral score when no history
108
- }
109
- // Calculate success rate
110
- const completedTasks = similarTasks.filter(task => task.status === "DONE");
111
- return completedTasks.length / similarTasks.length;
112
- }
113
- /**
114
- * Calculate specification clarity factor
115
- */
116
- export function calculateSpecificationClarity(projectContext) {
117
- let clarity = 0.3; // Base clarity
118
- if (projectContext.hasRoadmap)
119
- clarity += 0.2;
120
- if (projectContext.hasDesignDocs)
121
- clarity += 0.2;
122
- if (projectContext.hasClearAcceptanceCriteria)
123
- clarity += 0.3;
124
- return Math.min(1, clarity);
125
- }
126
- // ============================================================================
127
- // Validation Hooks Integration
128
- // ============================================================================
129
- const TASK_AUTO_CREATE_VALIDATION_HOOK = "task_auto_create_validation.md";
130
- const DEFAULT_TASK_AUTO_CREATE_VALIDATION_HOOK = `# Task Auto-Create Validation Hook
131
-
132
- ## Pre-Creation Checklist
133
- - [ ] Context files exist and are readable
134
- - [ ] Similar tasks have been completed successfully
135
- - [ ] Acceptance criteria are clear and testable
136
- - [ ] Dependencies are identified and available
137
-
138
- ## Post-Creation Actions
139
- - [ ] Add evidence link to analysis document
140
- - [ ] Notify relevant stakeholders (if configured)
141
- - [ ] Schedule validation review (24h for high-confidence)
142
- `;
143
- /**
144
- * Check if task auto-create validation hook exists
145
- */
146
- export async function hasTaskAutoCreateValidationHook(governanceDir) {
147
- const hookPath = path.join(governanceDir, "hooks", TASK_AUTO_CREATE_VALIDATION_HOOK);
148
- try {
149
- await fs.access(hookPath);
150
- return true;
151
- }
152
- catch {
153
- return false;
154
- }
155
- }
156
- /**
157
- * Get or create task auto-create validation hook
158
- */
159
- export async function getOrCreateTaskAutoCreateValidationHook(governanceDir) {
160
- const hooksDir = path.join(governanceDir, "hooks");
161
- const hookPath = path.join(hooksDir, TASK_AUTO_CREATE_VALIDATION_HOOK);
162
- try {
163
- // Try to read existing hook
164
- const content = await fs.readFile(hookPath, "utf-8");
165
- return content;
166
- }
167
- catch {
168
- // Create hooks directory if it doesn't exist
169
- try {
170
- await fs.mkdir(hooksDir, { recursive: true });
171
- }
172
- catch {
173
- // Directory already exists or creation failed silently
174
- }
175
- // Create default hook
176
- await fs.writeFile(hookPath, DEFAULT_TASK_AUTO_CREATE_VALIDATION_HOOK, "utf-8");
177
- return DEFAULT_TASK_AUTO_CREATE_VALIDATION_HOOK;
178
- }
179
- }
180
- /**
181
- * Run pre-creation validation checklist
182
- */
183
- export async function runPreCreationValidation(governanceDir, confidenceScore) {
184
- const issues = [];
185
- // Check confidence score first
186
- if (confidenceScore.recommendation === "do_not_create") {
187
- issues.push(`Confidence score ${confidenceScore.score.toFixed(2)} is below threshold (${CONFIDENCE_THRESHOLDS.reviewRequired})`);
188
- }
189
- // Check context completeness
190
- if (confidenceScore.factors.contextCompleteness < 0.6) {
191
- issues.push(`Context completeness (${confidenceScore.factors.contextCompleteness.toFixed(2)}) is low - more governance artifacts recommended`);
192
- }
193
- // Check for validation hook
194
- const hasHook = await hasTaskAutoCreateValidationHook(governanceDir);
195
- if (!hasHook) {
196
- issues.push("Task auto-create validation hook not found - will create default hook");
197
- }
198
- return {
199
- passed: issues.length === 0 || confidenceScore.recommendation === "auto_create",
200
- issues,
201
- };
202
- }
203
- // ============================================================================
204
- // Confidence Report Generation
205
- // ============================================================================
206
- /**
207
- * Generate a human-readable confidence report
208
- */
209
- export function generateConfidenceReport(confidenceScore) {
210
- const lines = [
211
- "# Confidence Score Report",
212
- "",
213
- `## Final Score: ${(confidenceScore.score * 100).toFixed(0)}%`,
214
- `**Recommendation**: ${confidenceScore.recommendation.replace(/_/g, " ")}`,
215
- "",
216
- "## Factor Breakdown",
217
- "",
218
- `| Factor | Score | Weight | Contribution |`,
219
- `|--------|-------|--------|--------------|`,
220
- `| Context Completeness | ${(confidenceScore.factors.contextCompleteness * 100).toFixed(0)}% | ${(CONFIDENCE_WEIGHTS.contextCompleteness * 100).toFixed(0)}% | ${(confidenceScore.factors.contextCompleteness * CONFIDENCE_WEIGHTS.contextCompleteness * 100).toFixed(0)}% |`,
221
- `| Similar Task History | ${(confidenceScore.factors.similarTaskHistory * 100).toFixed(0)}% | ${(CONFIDENCE_WEIGHTS.similarTaskHistory * 100).toFixed(0)}% | ${(confidenceScore.factors.similarTaskHistory * CONFIDENCE_WEIGHTS.similarTaskHistory * 100).toFixed(0)}% |`,
222
- `| Specification Clarity | ${(confidenceScore.factors.specificationClarity * 100).toFixed(0)}% | ${(CONFIDENCE_WEIGHTS.specificationClarity * 100).toFixed(0)}% | ${(confidenceScore.factors.specificationClarity * CONFIDENCE_WEIGHTS.specificationClarity * 100).toFixed(0)}% |`,
223
- "",
224
- "## Thresholds",
225
- "",
226
- `- Auto-create: >= ${(CONFIDENCE_THRESHOLDS.autoCreate * 100).toFixed(0)}%`,
227
- `- Review required: ${(CONFIDENCE_THRESHOLDS.reviewRequired * 100).toFixed(0)}% - ${(CONFIDENCE_THRESHOLDS.autoCreate * 100).toFixed(0)}%`,
228
- `- Do not create: < ${(CONFIDENCE_THRESHOLDS.reviewRequired * 100).toFixed(0)}%`,
229
- ];
230
- return lines.join("\n");
231
- }
@@ -1,205 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import { afterEach, describe, expect, it } from "vitest";
5
- import { calculateConfidenceScore, calculateContextCompleteness, calculateSimilarTaskHistory, calculateSpecificationClarity, hasTaskAutoCreateValidationHook, getOrCreateTaskAutoCreateValidationHook, runPreCreationValidation, generateConfidenceReport, } from "./confidence.js";
6
- const tempPaths = [];
7
- async function createTempDir() {
8
- const dir = await fs.mkdtemp(path.join(os.tmpdir(), "projitive-confidence-test-"));
9
- tempPaths.push(dir);
10
- return dir;
11
- }
12
- afterEach(async () => {
13
- await Promise.all(tempPaths.splice(0).map(async (dir) => {
14
- await fs.rm(dir, { recursive: true, force: true });
15
- }));
16
- });
17
- describe("confidence module", () => {
18
- describe("calculateConfidenceScore", () => {
19
- it("calculates confidence score with valid inputs", () => {
20
- const result = calculateConfidenceScore({
21
- contextCompleteness: 0.8,
22
- similarTaskHistory: 0.7,
23
- specificationClarity: 0.9,
24
- });
25
- expect(result.score).toBeGreaterThan(0);
26
- expect(result.score).toBeLessThanOrEqual(1);
27
- expect(result.recommendation).toBeDefined();
28
- });
29
- it("recommends auto_create for high confidence scores", () => {
30
- const result = calculateConfidenceScore({
31
- contextCompleteness: 1.0,
32
- similarTaskHistory: 1.0,
33
- specificationClarity: 1.0,
34
- });
35
- expect(result.recommendation).toBe("auto_create");
36
- });
37
- it("recommends review_required for medium confidence scores", () => {
38
- const result = calculateConfidenceScore({
39
- contextCompleteness: 0.7,
40
- similarTaskHistory: 0.7,
41
- specificationClarity: 0.7,
42
- });
43
- expect(result.recommendation).toBe("review_required");
44
- });
45
- it("recommends do_not_create for low confidence scores", () => {
46
- const result = calculateConfidenceScore({
47
- contextCompleteness: 0.0,
48
- similarTaskHistory: 0.0,
49
- specificationClarity: 0.0,
50
- });
51
- expect(result.recommendation).toBe("do_not_create");
52
- });
53
- it("clamps values outside [0, 1] range", () => {
54
- const result = calculateConfidenceScore({
55
- contextCompleteness: 1.5,
56
- similarTaskHistory: -0.5,
57
- specificationClarity: 2.0,
58
- });
59
- expect(result.factors.contextCompleteness).toBe(1);
60
- expect(result.factors.similarTaskHistory).toBe(0);
61
- expect(result.factors.specificationClarity).toBe(1);
62
- });
63
- });
64
- describe("calculateContextCompleteness", () => {
65
- it("returns 0 for empty directory", async () => {
66
- const root = await createTempDir();
67
- const completeness = await calculateContextCompleteness(root);
68
- expect(completeness).toBe(0);
69
- });
70
- it("returns higher score for more complete context", async () => {
71
- const root = await createTempDir();
72
- await fs.writeFile(path.join(root, "tasks.md"), "", "utf-8");
73
- await fs.writeFile(path.join(root, "roadmap.md"), "", "utf-8");
74
- await fs.writeFile(path.join(root, "README.md"), "", "utf-8");
75
- const completeness = await calculateContextCompleteness(root);
76
- expect(completeness).toBeGreaterThan(0.5);
77
- });
78
- });
79
- describe("calculateSimilarTaskHistory", () => {
80
- const sampleTasks = [
81
- {
82
- id: "TASK-0001",
83
- title: "Implement feature X",
84
- status: "DONE",
85
- summary: "Build core functionality for feature X",
86
- owner: "ai-copilot",
87
- updatedAt: "2026-02-22T00:00:00.000Z",
88
- links: [],
89
- roadmapRefs: [],
90
- },
91
- {
92
- id: "TASK-0002",
93
- title: "Test feature Y",
94
- status: "TODO",
95
- summary: "Write tests for feature Y",
96
- owner: "ai-copilot",
97
- updatedAt: "2026-02-22T00:00:00.000Z",
98
- links: [],
99
- roadmapRefs: [],
100
- },
101
- {
102
- id: "TASK-0003",
103
- title: "Implement feature Z",
104
- status: "DONE",
105
- summary: "Build core functionality for feature Z",
106
- owner: "ai-copilot",
107
- updatedAt: "2026-02-22T00:00:00.000Z",
108
- links: [],
109
- roadmapRefs: [],
110
- },
111
- ];
112
- it("returns 0.5 when no similar tasks", () => {
113
- const result = calculateSimilarTaskHistory([], "Build something new");
114
- expect(result).toBe(0.5);
115
- });
116
- it("calculates success rate for similar tasks", () => {
117
- const result = calculateSimilarTaskHistory(sampleTasks, "Implement feature A with core functionality");
118
- expect(result).toBeGreaterThan(0);
119
- expect(result).toBeLessThanOrEqual(1);
120
- });
121
- it("handles tasks with no matching keywords", () => {
122
- const result = calculateSimilarTaskHistory(sampleTasks, "Something completely different unrelated");
123
- expect(result).toBe(0.5);
124
- });
125
- });
126
- describe("calculateSpecificationClarity", () => {
127
- it("returns base clarity with no context", () => {
128
- const result = calculateSpecificationClarity({});
129
- expect(result).toBe(0.3);
130
- });
131
- it("increases clarity with roadmap", () => {
132
- const result = calculateSpecificationClarity({ hasRoadmap: true });
133
- expect(result).toBeGreaterThan(0.3);
134
- });
135
- it("increases clarity with design docs", () => {
136
- const result = calculateSpecificationClarity({ hasDesignDocs: true });
137
- expect(result).toBeGreaterThan(0.3);
138
- });
139
- it("reaches maximum clarity with all factors", () => {
140
- const result = calculateSpecificationClarity({
141
- hasRoadmap: true,
142
- hasDesignDocs: true,
143
- hasClearAcceptanceCriteria: true,
144
- });
145
- expect(result).toBe(1);
146
- });
147
- });
148
- describe("validation hooks", () => {
149
- it("detects missing validation hook", async () => {
150
- const root = await createTempDir();
151
- const hasHook = await hasTaskAutoCreateValidationHook(root);
152
- expect(hasHook).toBe(false);
153
- });
154
- it("creates default validation hook", async () => {
155
- const root = await createTempDir();
156
- const hookContent = await getOrCreateTaskAutoCreateValidationHook(root);
157
- expect(hookContent).toContain("Task Auto-Create Validation Hook");
158
- });
159
- it("reads existing validation hook", async () => {
160
- const root = await createTempDir();
161
- const hooksDir = path.join(root, "hooks");
162
- await fs.mkdir(hooksDir, { recursive: true });
163
- const hookPath = path.join(hooksDir, "task_auto_create_validation.md");
164
- await fs.writeFile(hookPath, "custom hook content", "utf-8");
165
- const hookContent = await getOrCreateTaskAutoCreateValidationHook(root);
166
- expect(hookContent).toBe("custom hook content");
167
- });
168
- });
169
- describe("runPreCreationValidation", () => {
170
- it("validates confidence score", async () => {
171
- const root = await createTempDir();
172
- const confidenceScore = calculateConfidenceScore({
173
- contextCompleteness: 0.9,
174
- similarTaskHistory: 0.9,
175
- specificationClarity: 0.9,
176
- });
177
- const result = await runPreCreationValidation(root, confidenceScore);
178
- expect(result.passed).toBeDefined();
179
- expect(result.issues).toBeInstanceOf(Array);
180
- });
181
- });
182
- describe("generateConfidenceReport", () => {
183
- it("generates human-readable report", () => {
184
- const confidenceScore = calculateConfidenceScore({
185
- contextCompleteness: 0.8,
186
- similarTaskHistory: 0.7,
187
- specificationClarity: 0.9,
188
- });
189
- const report = generateConfidenceReport(confidenceScore);
190
- expect(report).toContain("Confidence Score Report");
191
- expect(report).toContain("Final Score");
192
- expect(report).toContain("Factor Breakdown");
193
- expect(report).toContain("Thresholds");
194
- });
195
- it("includes recommendation in report", () => {
196
- const confidenceScore = calculateConfidenceScore({
197
- contextCompleteness: 1.0,
198
- similarTaskHistory: 1.0,
199
- specificationClarity: 1.0,
200
- });
201
- const report = generateConfidenceReport(confidenceScore);
202
- expect(report).toContain("auto create");
203
- });
204
- });
205
- });
@@ -1,66 +0,0 @@
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 registerDesignContextResources(server) {
16
- // Register design context resources
17
- server.registerResource("designContext", "projitive://design-context/designs", {
18
- title: "Design Context",
19
- description: "Design context and resources for the project",
20
- mimeType: "text/markdown",
21
- }, async () => ({
22
- contents: [
23
- {
24
- uri: "projitive://design-context/designs",
25
- text: `# Design Context\n\nThis is the design context for the project.`,
26
- },
27
- ],
28
- }));
29
- }
30
- export function registerDesignContextPrompts(server) {
31
- // Register design context prompts
32
- server.registerPrompt("designContext", {
33
- title: "Design Context",
34
- description: "Get design context for the project",
35
- argsSchema: {
36
- projectPath: z.string().optional(),
37
- },
38
- }, async ({ projectPath }) => {
39
- const text = [
40
- "You are exploring the design context for the project.",
41
- "",
42
- projectPath
43
- ? [
44
- `1) Project path is known: "${projectPath}"`,
45
- "2) Review the design context resources.",
46
- "3) Identify design patterns and guidelines.",
47
- ].join("\n")
48
- : [
49
- "1) Project path is unknown: Run projectScan() to discover all governance roots.",
50
- "2) Select a project to work on.",
51
- "3) Run projectContext() to load project summary.",
52
- "4) Review the design context resources.",
53
- ].join("\n"),
54
- "",
55
- "Key resources to read:",
56
- "- projitive://design-context/designs - Design context and resources",
57
- "- projitive://governance/workspace - Project overview",
58
- "- projitive://governance/roadmap - Project roadmap",
59
- "",
60
- "Hard rules:",
61
- "- Follow the design patterns and guidelines.",
62
- "- Keep design documents in the .projitive/designs/ directory.",
63
- ].join("\n");
64
- return asUserPrompt(text);
65
- });
66
- }