@projitive/mcp 2.1.2 → 2.1.4

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.
@@ -12,7 +12,9 @@ export const TASK_RESEARCH_DIR = 'designs/research';
12
12
  export const TASK_RESEARCH_FILE_SUFFIX = '.implementation-research.md';
13
13
  export const CORE_DESIGN_DOCS_DIR = 'designs/core';
14
14
  export const CORE_ARCHITECTURE_DOC_FILE = `${CORE_DESIGN_DOCS_DIR}/architecture.md`;
15
- export const CORE_STYLE_DOC_FILE = `${CORE_DESIGN_DOCS_DIR}/style-guide.md`;
15
+ export const CORE_CODE_STYLE_DOC_FILE = `${CORE_DESIGN_DOCS_DIR}/code-style.md`;
16
+ export const CORE_UI_STYLE_DOC_FILE = `${CORE_DESIGN_DOCS_DIR}/ui-style.md`;
17
+ export const CORE_STYLE_DOC_FILE = CORE_UI_STYLE_DOC_FILE;
16
18
  function taskStatusGuidance(task) {
17
19
  if (task.status === 'TODO') {
18
20
  return [
@@ -209,6 +211,8 @@ function taskStatusGuidance(task) {
209
211
  }
210
212
  const DEFAULT_NO_TASK_DISCOVERY_GUIDANCE = [
211
213
  '- Recheck project state first: run projectContext and confirm there is truly no TODO/IN_PROGRESS task to execute.',
214
+ '- Before creating new tasks, inspect current branch context: check latest commits and workspace changes to infer what the user recently worked on.',
215
+ '- If recent code changes are not reflected in governance artifacts (tasks/roadmap/reports), sync governance first (taskUpdate/roadmapUpdate or create follow-up tasks) before expanding new scope.',
212
216
  '- Check BLOCKED tasks: if BLOCKED tasks exist, read their blocker metadata and take unblock action before creating new tasks.',
213
217
  ' - internal_dependency: create/track the blocking task, coordinate with owner',
214
218
  ' - external_dependency: reach out to blocking entity or escalate',
@@ -220,7 +224,8 @@ const DEFAULT_NO_TASK_DISCOVERY_GUIDANCE = [
220
224
  '- Prefer slices that unlock multiple downstream tasks before isolated refactors or low-impact cleanups.',
221
225
  '- Skip duplicate scope: do not create tasks that overlap existing TODO/IN_PROGRESS/BLOCKED task intent.',
222
226
  '- Use quality gates for discovery candidates: user value, delivery risk reduction, or measurable throughput improvement.',
223
- '- Review and update project architecture docs under designs/core/ (architecture.md, style-guide.md) if they are missing or outdated.',
227
+ '- Review and update core governance docs under designs/core/ (architecture.md, code-style.md, ui-style.md) if they are missing or outdated.',
228
+ '- If a task changes module boundaries, engineering conventions, or UI patterns, create follow-up TODO work or update the matching core doc before closing the loop.',
224
229
  '- Keep each discovery round small (1-3 tasks), then rerun taskNext immediately for re-ranking and execution.',
225
230
  ];
226
231
  const DEFAULT_TASK_CONTEXT_READING_GUIDANCE = [
@@ -232,14 +237,6 @@ const DEFAULT_TASK_CONTEXT_READING_GUIDANCE = [
232
237
  '- Read process guides under templates/docs/project guidelines to align with local governance rules.',
233
238
  '- If available, read docs/ architecture or migration guides before major structural changes.',
234
239
  ];
235
- export async function resolveNoTaskDiscoveryGuidance(governanceDir) {
236
- void governanceDir;
237
- return DEFAULT_NO_TASK_DISCOVERY_GUIDANCE;
238
- }
239
- export async function resolveTaskContextReadingGuidance(governanceDir) {
240
- void governanceDir;
241
- return DEFAULT_TASK_CONTEXT_READING_GUIDANCE;
242
- }
243
240
  async function readRoadmapIds(governanceDir) {
244
241
  const dbPath = path.join(governanceDir, '.projitive');
245
242
  try {
@@ -329,25 +326,30 @@ function collectTaskResearchBriefLintSuggestions(state) {
329
326
  }
330
327
  return [];
331
328
  }
332
- function inspectProjectContextDocsFromArtifacts(files) {
329
+ export function inspectProjectContextDocsFromArtifacts(files) {
333
330
  const markdownFiles = files
334
331
  .map((item) => item.replace(/\\/g, '/'))
335
332
  .filter((item) => item.toLowerCase().endsWith('.md'));
336
333
  const architectureDocSuffix = `/${CORE_ARCHITECTURE_DOC_FILE}`.toLowerCase();
337
- const styleDocSuffix = `/${CORE_STYLE_DOC_FILE}`.toLowerCase();
334
+ const codeStyleDocSuffix = `/${CORE_CODE_STYLE_DOC_FILE}`.toLowerCase();
335
+ const uiStyleDocSuffix = `/${CORE_UI_STYLE_DOC_FILE}`.toLowerCase();
338
336
  const architectureDocs = markdownFiles.filter((item) => item.toLowerCase().endsWith(architectureDocSuffix));
339
- const styleDocs = markdownFiles.filter((item) => item.toLowerCase().endsWith(styleDocSuffix));
337
+ const codeStyleDocs = markdownFiles.filter((item) => item.toLowerCase().endsWith(codeStyleDocSuffix));
338
+ const uiStyleDocs = markdownFiles.filter((item) => item.toLowerCase().endsWith(uiStyleDocSuffix));
340
339
  const missingArchitectureDocs = architectureDocs.length === 0;
341
- const missingStyleDocs = styleDocs.length === 0;
340
+ const missingCodeStyleDocs = codeStyleDocs.length === 0;
341
+ const missingUiStyleDocs = uiStyleDocs.length === 0;
342
342
  return {
343
343
  architectureDocs,
344
- styleDocs,
344
+ codeStyleDocs,
345
+ uiStyleDocs,
345
346
  missingArchitectureDocs,
346
- missingStyleDocs,
347
- ready: !missingArchitectureDocs && !missingStyleDocs,
347
+ missingCodeStyleDocs,
348
+ missingUiStyleDocs,
349
+ ready: !missingArchitectureDocs && !missingCodeStyleDocs && !missingUiStyleDocs,
348
350
  };
349
351
  }
350
- function collectProjectContextDocsLintSuggestions(state) {
352
+ export function collectProjectContextDocsLintSuggestions(state) {
351
353
  const suggestions = [];
352
354
  if (state.missingArchitectureDocs) {
353
355
  suggestions.push({
@@ -356,11 +358,18 @@ function collectProjectContextDocsLintSuggestions(state) {
356
358
  fixHint: `Add required file under governanceDir: ${CORE_ARCHITECTURE_DOC_FILE}.`,
357
359
  });
358
360
  }
359
- if (state.missingStyleDocs) {
361
+ if (state.missingCodeStyleDocs) {
362
+ suggestions.push({
363
+ code: PROJECT_LINT_CODES.CODE_STYLE_DOC_MISSING,
364
+ message: 'Project context is missing code style documentation.',
365
+ fixHint: `Add required file under governanceDir: ${CORE_CODE_STYLE_DOC_FILE}.`,
366
+ });
367
+ }
368
+ if (state.missingUiStyleDocs) {
360
369
  suggestions.push({
361
- code: PROJECT_LINT_CODES.STYLE_DOC_MISSING,
362
- message: 'Project context is missing design style documentation.',
363
- fixHint: `Add required file under governanceDir: ${CORE_STYLE_DOC_FILE}.`,
370
+ code: PROJECT_LINT_CODES.UI_STYLE_DOC_MISSING,
371
+ message: 'Project context is missing UI style documentation.',
372
+ fixHint: `Add required file under governanceDir: ${CORE_UI_STYLE_DOC_FILE}.`,
364
373
  });
365
374
  }
366
375
  return suggestions;
@@ -996,7 +1005,7 @@ export function registerTaskTools(server) {
996
1005
  }));
997
1006
  const preferredProject = projectSnapshots[0];
998
1007
  const preferredRoadmapRef = preferredProject?.roadmapIds[0] ?? 'ROADMAP-0001';
999
- const noTaskDiscoveryGuidance = await resolveNoTaskDiscoveryGuidance(preferredProject?.governanceDir);
1008
+ const noTaskDiscoveryGuidance = DEFAULT_NO_TASK_DISCOVERY_GUIDANCE;
1000
1009
  return { isEmpty: true, roots, depth, projects, projectSnapshots, preferredProject, preferredRoadmapRef, noTaskDiscoveryGuidance };
1001
1010
  }
1002
1011
  const selected = rankedCandidates[0];
@@ -1103,15 +1112,20 @@ export function registerTaskTools(server) {
1103
1112
  return [
1104
1113
  ...(!data.projectContextDocsState.ready
1105
1114
  ? [
1106
- '- Project context docs are incomplete. Complete missing project architecture/style docs before deep implementation.',
1115
+ '- Project context docs are incomplete. Complete missing project architecture, code style, and UI style docs before deep implementation.',
1116
+ `- Rerun projectInit to backfill missing governance artifacts first: projectInit(projectPath="${toProjectPath(data.selected.governanceDir)}")`,
1107
1117
  ...(data.projectContextDocsState.missingArchitectureDocs
1108
1118
  ? [`- Missing architecture design doc: create required file under governanceDir: ${CORE_ARCHITECTURE_DOC_FILE}.`]
1109
1119
  : []),
1110
- ...(data.projectContextDocsState.missingStyleDocs
1111
- ? [`- Missing design style doc: create required file under governanceDir: ${CORE_STYLE_DOC_FILE}.`]
1120
+ ...(data.projectContextDocsState.missingCodeStyleDocs
1121
+ ? [`- Missing code style doc: create required file under governanceDir: ${CORE_CODE_STYLE_DOC_FILE}.`]
1122
+ : []),
1123
+ ...(data.projectContextDocsState.missingUiStyleDocs
1124
+ ? [`- Missing UI style doc: create required file under governanceDir: ${CORE_UI_STYLE_DOC_FILE}.`]
1112
1125
  : []),
1113
1126
  ]
1114
1127
  : []),
1128
+ '- Governance state updates MUST go through tools; NEVER directly edit tasks.md/roadmap.md generated views.',
1115
1129
  '- Start immediately with Suggested Read Order and execute the selected task.',
1116
1130
  '- Update markdown artifacts directly while keeping TASK/ROADMAP IDs unchanged.',
1117
1131
  '- Re-run `taskContext` for the selectedTaskId after edits to verify evidence consistency.',
@@ -1159,7 +1173,7 @@ export function registerTaskTools(server) {
1159
1173
  throw new ToolExecutionError(`Task not found: ${taskId}`, ['run `taskList` to discover available IDs', 'retry with an existing task ID'], `taskList(projectPath="${toProjectPath(governanceDir)}")`);
1160
1174
  }
1161
1175
  const researchBriefState = await inspectTaskResearchBrief(governanceDir, task);
1162
- const contextReadingGuidance = await resolveTaskContextReadingGuidance(governanceDir);
1176
+ const contextReadingGuidance = DEFAULT_TASK_CONTEXT_READING_GUIDANCE;
1163
1177
  const taskLocation = (await findTextReferences(markdownPath, taskId))[0];
1164
1178
  const artifacts = await discoverGovernanceArtifacts(governanceDir);
1165
1179
  const fileCandidates = candidateFilesFromArtifacts(artifacts);
@@ -1188,8 +1202,9 @@ export function registerTaskTools(server) {
1188
1202
  `- roadmapRefs: ${task.roadmapRefs.join(', ') || '(none)'}`,
1189
1203
  `- researchBriefPath: ${researchBriefState.relativePath}`,
1190
1204
  `- researchBriefStatus: ${researchBriefState.ready ? 'READY' : 'MISSING'}`,
1191
- `- architectureDocsStatus: ${projectContextDocsState.missingArchitectureDocs ? 'MISSING' : 'READY'}`,
1192
- `- styleDocsStatus: ${projectContextDocsState.missingStyleDocs ? 'MISSING' : 'READY'}`,
1205
+ `- projectArchitectureDocsStatus: ${projectContextDocsState.missingArchitectureDocs ? 'MISSING' : 'READY'}`,
1206
+ `- codeStyleDocsStatus: ${projectContextDocsState.missingCodeStyleDocs ? 'MISSING' : 'READY'}`,
1207
+ `- uiStyleDocsStatus: ${projectContextDocsState.missingUiStyleDocs ? 'MISSING' : 'READY'}`,
1193
1208
  `- taskLocation: ${taskLocation ? `${taskLocation.filePath}#L${taskLocation.line}` : markdownPath}`,
1194
1209
  ];
1195
1210
  if (task.subState && task.status === 'IN_PROGRESS') {
@@ -1232,10 +1247,14 @@ export function registerTaskTools(server) {
1232
1247
  ...(projectContextDocsState.architectureDocs.length > 0
1233
1248
  ? projectContextDocsState.architectureDocs.map((item) => `- architecture: ${item}`)
1234
1249
  : [`- architecture: add required file under governanceDir: ${CORE_ARCHITECTURE_DOC_FILE}.`]),
1235
- `- design style docs: ${projectContextDocsState.styleDocs.length > 0 ? 'found' : 'missing'}`,
1236
- ...(projectContextDocsState.styleDocs.length > 0
1237
- ? projectContextDocsState.styleDocs.map((item) => `- style: ${item}`)
1238
- : [`- style: add required file under governanceDir: ${CORE_STYLE_DOC_FILE}.`]),
1250
+ `- code style docs: ${projectContextDocsState.codeStyleDocs.length > 0 ? 'found' : 'missing'}`,
1251
+ ...(projectContextDocsState.codeStyleDocs.length > 0
1252
+ ? projectContextDocsState.codeStyleDocs.map((item) => `- code-style: ${item}`)
1253
+ : [`- code-style: add required file under governanceDir: ${CORE_CODE_STYLE_DOC_FILE}.`]),
1254
+ `- UI style docs: ${projectContextDocsState.uiStyleDocs.length > 0 ? 'found' : 'missing'}`,
1255
+ ...(projectContextDocsState.uiStyleDocs.length > 0
1256
+ ? projectContextDocsState.uiStyleDocs.map((item) => `- ui-style: ${item}`)
1257
+ : [`- ui-style: add required file under governanceDir: ${CORE_UI_STYLE_DOC_FILE}.`]),
1239
1258
  '',
1240
1259
  '### Related Artifacts',
1241
1260
  ...(relatedArtifacts.length > 0 ? relatedArtifacts.map((file) => `- ${file}`) : ['- (none)']),
@@ -1248,7 +1267,7 @@ export function registerTaskTools(server) {
1248
1267
  '### Suggested Read Order',
1249
1268
  ...suggestedReadOrder.map((item, index) => `${index + 1}. ${item}`),
1250
1269
  ],
1251
- guidance: ({ researchBriefState, projectContextDocsState, contextReadingGuidance, task }) => [
1270
+ guidance: ({ normalizedProjectPath, researchBriefState, projectContextDocsState, contextReadingGuidance, task }) => [
1252
1271
  ...(!researchBriefState.ready
1253
1272
  ? [
1254
1273
  '- Pre-execution gate is NOT satisfied. Complete research brief first, then proceed with implementation.',
@@ -1262,17 +1281,21 @@ export function registerTaskTools(server) {
1262
1281
  ]),
1263
1282
  ...(!projectContextDocsState.ready
1264
1283
  ? [
1265
- '- Project context docs gate is NOT satisfied. Complete missing project architecture/style docs first.',
1284
+ '- Project context docs gate is NOT satisfied. Complete missing project architecture, code style, and UI style docs first.',
1285
+ `- Rerun projectInit to repair missing governance artifacts first: projectInit(projectPath="${normalizedProjectPath}")`,
1266
1286
  ...(projectContextDocsState.missingArchitectureDocs
1267
1287
  ? [`- Missing architecture design doc. Add required file under governanceDir: ${CORE_ARCHITECTURE_DOC_FILE} and include architecture boundaries and module responsibilities.`]
1268
1288
  : []),
1269
- ...(projectContextDocsState.missingStyleDocs
1270
- ? [`- Missing design style doc. Add required file under governanceDir: ${CORE_STYLE_DOC_FILE} and include style language, tokens/themes, and UI consistency rules.`]
1289
+ ...(projectContextDocsState.missingCodeStyleDocs
1290
+ ? [`- Missing code style doc. Add required file under governanceDir: ${CORE_CODE_STYLE_DOC_FILE} and include naming, module boundaries, testing expectations, and review rules.`]
1291
+ : []),
1292
+ ...(projectContextDocsState.missingUiStyleDocs
1293
+ ? [`- Missing UI style doc. Add required file under governanceDir: ${CORE_UI_STYLE_DOC_FILE} and include style language, tokens/themes, accessibility expectations, and UI consistency rules.`]
1271
1294
  : []),
1272
- '- Re-run taskContext and confirm both architectureDocsStatus/styleDocsStatus are READY.',
1295
+ '- Re-run taskContext and confirm projectArchitectureDocsStatus/codeStyleDocsStatus/uiStyleDocsStatus are READY.',
1273
1296
  ]
1274
1297
  : [
1275
- '- Project context docs gate satisfied. Architecture/style docs are available for execution alignment.',
1298
+ '- Project context docs gate satisfied. Architecture, code style, and UI style docs are available for execution alignment.',
1276
1299
  ]),
1277
1300
  '- Read the files in Suggested Read Order.',
1278
1301
  '',
@@ -1281,7 +1304,8 @@ export function registerTaskTools(server) {
1281
1304
  '',
1282
1305
  '- Verify whether current status and evidence are consistent.',
1283
1306
  ...taskStatusGuidance(task),
1284
- '- If updates are needed, use tool writes for governance store (`taskUpdate` / `roadmapUpdate`) and keep TASK IDs unchanged.',
1307
+ '- If updates are needed, use tool writes for governance store (`taskCreate` / `taskUpdate` / `roadmapCreate` / `roadmapUpdate`) and keep TASK IDs unchanged.',
1308
+ '- NEVER directly edit tasks.md/roadmap.md; they are generated views and will be overwritten.',
1285
1309
  '- After editing, re-run `taskContext` to verify references and context consistency.',
1286
1310
  ],
1287
1311
  suggestions: ({ task, researchBriefState, projectContextDocsState }) => [
@@ -1413,8 +1437,18 @@ export function registerTaskTools(server) {
1413
1437
  ? ['- Ensure pre-execution research brief exists under governanceDir before deep implementation.']
1414
1438
  : []),
1415
1439
  ...(updates.status === 'DONE'
1416
- ? ['- Verify evidence links are attached and reflect completed work.']
1440
+ ? [
1441
+ '- Verify evidence links are attached and reflect completed work.',
1442
+ '- Core docs review checklist (required):',
1443
+ '- [ ] architecture.md reviewed (designs/core/architecture.md)',
1444
+ '- [ ] code-style.md reviewed (designs/core/code-style.md)',
1445
+ '- [ ] ui-style.md reviewed (designs/core/ui-style.md)',
1446
+ '- Re-check whether this task changed module boundaries or system behavior, and update architecture.md if needed.',
1447
+ '- Re-check whether this task introduced or normalized engineering conventions, and update code-style.md if needed.',
1448
+ '- Re-check whether this task changed UI patterns, tokens, accessibility expectations, or interaction rules, and update ui-style.md if needed.',
1449
+ ]
1417
1450
  : []),
1451
+ '- Governance state changes must use task/roadmap tools only; never manually edit tasks.md/roadmap.md views.',
1418
1452
  '.projitive governance store is source of truth; tasks.md is a generated view and may be overwritten.',
1419
1453
  ],
1420
1454
  suggestions: async ({ previewTask, governanceDir }) => [
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
- import { collectTaskLintSuggestions, isValidTaskId, normalizeTask, rankActionableTaskCandidates, resolveNoTaskDiscoveryGuidance, renderTaskSeedTemplate, renderTasksMarkdown, loadTasksDocument, registerTaskTools, saveTasks, taskPriority, toTaskUpdatedAtMs, validateTransition, } from './task.js';
2
+ import { collectTaskLintSuggestions, isValidTaskId, normalizeTask, rankActionableTaskCandidates, renderTaskSeedTemplate, renderTasksMarkdown, loadTasksDocument, registerTaskTools, saveTasks, taskPriority, toTaskUpdatedAtMs, validateTransition, } from './task.js';
3
3
  import fs from 'node:fs/promises';
4
4
  import os from 'node:os';
5
5
  import path from 'node:path';
@@ -159,15 +159,6 @@ describe('tasks module', () => {
159
159
  const markdown = lines.join('\n');
160
160
  expect(markdown).toContain('- roadmapRefs: ROADMAP-0099');
161
161
  });
162
- it('uses default no-task guidance when hook file is absent', async () => {
163
- const guidance = await resolveNoTaskDiscoveryGuidance('/path/that/does/not/exist');
164
- expect(guidance.length).toBeGreaterThan(3);
165
- });
166
- it('returns same default no-task guidance regardless of path', async () => {
167
- const guidanceA = await resolveNoTaskDiscoveryGuidance('/path/that/does/not/exist');
168
- const guidanceB = await resolveNoTaskDiscoveryGuidance('/another/path');
169
- expect(guidanceA).toEqual(guidanceB);
170
- });
171
162
  it('loads and saves tasks from governance store and keeps newest-first order', async () => {
172
163
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'projitive-mcp-task-'));
173
164
  const governanceDir = path.join(root, '.projitive');
@@ -284,11 +275,14 @@ describe('tasks module', () => {
284
275
  expect(contextResult.content[0].text).toContain('### Pre-Execution Research Brief');
285
276
  expect(contextResult.content[0].text).toContain('researchBriefStatus: MISSING');
286
277
  expect(contextResult.content[0].text).toContain('designs/research/TASK-0001.implementation-research.md');
287
- expect(contextResult.content[0].text).toContain('architectureDocsStatus: MISSING');
288
- expect(contextResult.content[0].text).toContain('styleDocsStatus: MISSING');
278
+ expect(contextResult.content[0].text).toContain('projectArchitectureDocsStatus: MISSING');
279
+ expect(contextResult.content[0].text).toContain('codeStyleDocsStatus: MISSING');
280
+ expect(contextResult.content[0].text).toContain('uiStyleDocsStatus: MISSING');
289
281
  expect(contextResult.content[0].text).toContain('Project context docs gate is NOT satisfied');
290
282
  expect(contextResult.content[0].text).toContain('PROJECT_ARCHITECTURE_DOC_MISSING');
291
- expect(contextResult.content[0].text).toContain('PROJECT_STYLE_DOC_MISSING');
283
+ expect(contextResult.content[0].text).toContain('PROJECT_CODE_STYLE_DOC_MISSING');
284
+ expect(contextResult.content[0].text).toContain('PROJECT_UI_STYLE_DOC_MISSING');
285
+ expect(contextResult.content[0].text).toContain('projectInit(projectPath="');
292
286
  await fs.rm(projectRoot, { recursive: true, force: true });
293
287
  });
294
288
  it('taskUpdate allows TODO -> IN_PROGRESS when research brief is missing, with lint guidance', async () => {
@@ -353,19 +347,22 @@ describe('tasks module', () => {
353
347
  ]);
354
348
  await fs.mkdir(path.join(projectRoot, 'designs'), { recursive: true });
355
349
  await fs.writeFile(path.join(projectRoot, 'designs', 'architecture.md'), '# Architecture\n', 'utf-8');
356
- await fs.writeFile(path.join(projectRoot, 'designs', 'style-guide.md'), '# Style\n', 'utf-8');
350
+ await fs.writeFile(path.join(projectRoot, 'designs', 'code-style.md'), '# Code Style\n', 'utf-8');
351
+ await fs.writeFile(path.join(projectRoot, 'designs', 'ui-style.md'), '# UI Style\n', 'utf-8');
357
352
  const mockServer = { registerTool: vi.fn() };
358
353
  registerTaskTools(mockServer);
359
354
  const taskContext = getToolHandler(mockServer, 'taskContext');
360
355
  const contextResult = await taskContext({ projectPath: projectRoot, taskId: 'TASK-0001' });
361
- expect(contextResult.content[0].text).toContain('architectureDocsStatus: MISSING');
362
- expect(contextResult.content[0].text).toContain('styleDocsStatus: MISSING');
356
+ expect(contextResult.content[0].text).toContain('projectArchitectureDocsStatus: MISSING');
357
+ expect(contextResult.content[0].text).toContain('codeStyleDocsStatus: MISSING');
358
+ expect(contextResult.content[0].text).toContain('uiStyleDocsStatus: MISSING');
363
359
  expect(contextResult.content[0].text).toContain('designs/core/architecture.md');
364
360
  expect(contextResult.content[0].text).toContain('PROJECT_ARCHITECTURE_DOC_MISSING');
365
- expect(contextResult.content[0].text).toContain('PROJECT_STYLE_DOC_MISSING');
361
+ expect(contextResult.content[0].text).toContain('PROJECT_CODE_STYLE_DOC_MISSING');
362
+ expect(contextResult.content[0].text).toContain('PROJECT_UI_STYLE_DOC_MISSING');
366
363
  await fs.rm(projectRoot, { recursive: true, force: true });
367
364
  });
368
- it('taskContext marks project core docs ready when architecture/style docs exist under designs/core', async () => {
365
+ it('taskContext marks project core docs ready when architecture/code-style/ui-style docs exist under designs/core', async () => {
369
366
  const { projectRoot, governanceDir, dbPath } = await createGovernanceWorkspace();
370
367
  await replaceRoadmapsInStore(dbPath, [
371
368
  { id: 'ROADMAP-0001', title: 'Roadmap', status: 'active', updatedAt: '2026-03-14T00:00:00.000Z' },
@@ -376,13 +373,15 @@ describe('tasks module', () => {
376
373
  const coreDir = path.join(governanceDir, 'designs', 'core');
377
374
  await fs.mkdir(coreDir, { recursive: true });
378
375
  await fs.writeFile(path.join(coreDir, 'architecture.md'), '# Architecture\n', 'utf-8');
379
- await fs.writeFile(path.join(coreDir, 'style-guide.md'), '# Style\n', 'utf-8');
376
+ await fs.writeFile(path.join(coreDir, 'code-style.md'), '# Code Style\n', 'utf-8');
377
+ await fs.writeFile(path.join(coreDir, 'ui-style.md'), '# UI Style\n', 'utf-8');
380
378
  const mockServer = { registerTool: vi.fn() };
381
379
  registerTaskTools(mockServer);
382
380
  const taskContext = getToolHandler(mockServer, 'taskContext');
383
381
  const contextResult = await taskContext({ projectPath: projectRoot, taskId: 'TASK-0001' });
384
- expect(contextResult.content[0].text).toContain('architectureDocsStatus: READY');
385
- expect(contextResult.content[0].text).toContain('styleDocsStatus: READY');
382
+ expect(contextResult.content[0].text).toContain('projectArchitectureDocsStatus: READY');
383
+ expect(contextResult.content[0].text).toContain('codeStyleDocsStatus: READY');
384
+ expect(contextResult.content[0].text).toContain('uiStyleDocsStatus: READY');
386
385
  expect(contextResult.content[0].text).toContain('Project context docs gate satisfied');
387
386
  await fs.rm(projectRoot, { recursive: true, force: true });
388
387
  });
@@ -397,15 +396,19 @@ describe('tasks module', () => {
397
396
  const coreDir = path.join(governanceDir, 'designs', 'core');
398
397
  await fs.mkdir(coreDir, { recursive: true });
399
398
  await fs.writeFile(path.join(coreDir, 'system-architecture.md'), '# Architecture\n', 'utf-8');
400
- await fs.writeFile(path.join(coreDir, 'visual-style.md'), '# Style\n', 'utf-8');
399
+ await fs.writeFile(path.join(coreDir, 'engineering-style.md'), '# Code Style\n', 'utf-8');
400
+ await fs.writeFile(path.join(coreDir, 'visual-style.md'), '# UI Style\n', 'utf-8');
401
401
  const mockServer = { registerTool: vi.fn() };
402
402
  registerTaskTools(mockServer);
403
403
  const taskContext = getToolHandler(mockServer, 'taskContext');
404
404
  const contextResult = await taskContext({ projectPath: projectRoot, taskId: 'TASK-0001' });
405
- expect(contextResult.content[0].text).toContain('architectureDocsStatus: MISSING');
406
- expect(contextResult.content[0].text).toContain('styleDocsStatus: MISSING');
405
+ expect(contextResult.content[0].text).toContain('projectArchitectureDocsStatus: MISSING');
406
+ expect(contextResult.content[0].text).toContain('codeStyleDocsStatus: MISSING');
407
+ expect(contextResult.content[0].text).toContain('uiStyleDocsStatus: MISSING');
407
408
  expect(contextResult.content[0].text).toContain('add required file under governanceDir: designs/core/architecture.md');
408
- expect(contextResult.content[0].text).toContain('add required file under governanceDir: designs/core/style-guide.md');
409
+ expect(contextResult.content[0].text).toContain('add required file under governanceDir: designs/core/code-style.md');
410
+ expect(contextResult.content[0].text).toContain('add required file under governanceDir: designs/core/ui-style.md');
411
+ expect(contextResult.content[0].text).toContain('projectInit(projectPath="');
409
412
  await fs.rm(projectRoot, { recursive: true, force: true });
410
413
  });
411
414
  it('taskUpdate allows IN_PROGRESS -> DONE with lint guidance when conformance fails', async () => {
@@ -437,7 +440,8 @@ describe('tasks module', () => {
437
440
  const coreDir = path.join(governanceDir, 'designs', 'core');
438
441
  await fs.mkdir(coreDir, { recursive: true });
439
442
  await fs.writeFile(path.join(coreDir, 'architecture.md'), '# Architecture\n', 'utf-8');
440
- await fs.writeFile(path.join(coreDir, 'style-guide.md'), '# Style\n', 'utf-8');
443
+ await fs.writeFile(path.join(coreDir, 'code-style.md'), '# Code Style\n', 'utf-8');
444
+ await fs.writeFile(path.join(coreDir, 'ui-style.md'), '# UI Style\n', 'utf-8');
441
445
  const mockServer = { registerTool: vi.fn() };
442
446
  registerTaskTools(mockServer);
443
447
  const taskUpdate = getToolHandler(mockServer, 'taskUpdate');
@@ -449,6 +453,10 @@ describe('tasks module', () => {
449
453
  expect(result.isError).toBeUndefined();
450
454
  expect(result.content[0].text).toContain('newStatus: DONE');
451
455
  expect(result.content[0].text).toContain('TASK_DONE_LINKS_MISSING');
456
+ expect(result.content[0].text).toContain('Core docs review checklist (required):');
457
+ expect(result.content[0].text).toContain('- [ ] architecture.md reviewed (designs/core/architecture.md)');
458
+ expect(result.content[0].text).toContain('- [ ] code-style.md reviewed (designs/core/code-style.md)');
459
+ expect(result.content[0].text).toContain('- [ ] ui-style.md reviewed (designs/core/ui-style.md)');
452
460
  await fs.rm(projectRoot, { recursive: true, force: true });
453
461
  });
454
462
  it('taskUpdate allows IN_PROGRESS -> DONE when conformance re-check passes', async () => {
@@ -481,7 +489,8 @@ describe('tasks module', () => {
481
489
  const coreDir = path.join(governanceDir, 'designs', 'core');
482
490
  await fs.mkdir(coreDir, { recursive: true });
483
491
  await fs.writeFile(path.join(coreDir, 'architecture.md'), '# Architecture\n', 'utf-8');
484
- await fs.writeFile(path.join(coreDir, 'style-guide.md'), '# Style\n', 'utf-8');
492
+ await fs.writeFile(path.join(coreDir, 'code-style.md'), '# Code Style\n', 'utf-8');
493
+ await fs.writeFile(path.join(coreDir, 'ui-style.md'), '# UI Style\n', 'utf-8');
485
494
  const mockServer = { registerTool: vi.fn() };
486
495
  registerTaskTools(mockServer);
487
496
  const taskUpdate = getToolHandler(mockServer, 'taskUpdate');
@@ -492,6 +501,7 @@ describe('tasks module', () => {
492
501
  });
493
502
  expect(result.isError).toBeUndefined();
494
503
  expect(result.content[0].text).toContain('newStatus: DONE');
504
+ expect(result.content[0].text).toContain('Core docs review checklist (required):');
495
505
  await fs.rm(projectRoot, { recursive: true, force: true });
496
506
  });
497
507
  });
@@ -50,5 +50,6 @@ export const TASK_LINT_CODES = {
50
50
  };
51
51
  export const PROJECT_LINT_CODES = {
52
52
  ARCHITECTURE_DOC_MISSING: 'PROJECT_ARCHITECTURE_DOC_MISSING',
53
- STYLE_DOC_MISSING: 'PROJECT_STYLE_DOC_MISSING',
53
+ CODE_STYLE_DOC_MISSING: 'PROJECT_CODE_STYLE_DOC_MISSING',
54
+ UI_STYLE_DOC_MISSING: 'PROJECT_UI_STYLE_DOC_MISSING',
54
55
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projitive/mcp",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "description": "Projitive MCP Server for project and task discovery/update",
5
5
  "license": "ISC",
6
6
  "author": "",