@projitive/mcp 2.0.2 → 2.0.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.
- package/README.md +14 -1
- package/output/package.json +8 -2
- package/output/source/common/artifacts.js +1 -1
- package/output/source/common/artifacts.test.js +11 -11
- package/output/source/common/errors.js +19 -19
- package/output/source/common/files.js +11 -11
- package/output/source/common/files.test.js +14 -14
- package/output/source/common/index.js +10 -10
- package/output/source/common/linter.js +27 -27
- package/output/source/common/linter.test.js +9 -9
- package/output/source/common/markdown.js +3 -3
- package/output/source/common/markdown.test.js +15 -15
- package/output/source/common/response.js +74 -74
- package/output/source/common/response.test.js +30 -30
- package/output/source/common/store.js +40 -40
- package/output/source/common/store.test.js +72 -72
- package/output/source/common/types.js +3 -3
- package/output/source/common/utils.js +8 -8
- package/output/source/index.js +16 -16
- package/output/source/index.test.js +64 -64
- package/output/source/prompts/index.js +3 -3
- package/output/source/prompts/quickStart.js +96 -96
- package/output/source/prompts/taskDiscovery.js +184 -180
- package/output/source/prompts/taskExecution.js +148 -147
- package/output/source/resources/designs.js +26 -26
- package/output/source/resources/designs.test.js +88 -88
- package/output/source/resources/governance.js +19 -19
- package/output/source/resources/index.js +2 -2
- package/output/source/resources/readme.js +7 -7
- package/output/source/resources/readme.test.js +113 -113
- package/output/source/resources/reports.js +10 -10
- package/output/source/resources/reports.test.js +83 -83
- package/output/source/tools/index.js +3 -3
- package/output/source/tools/project.js +196 -191
- package/output/source/tools/project.test.js +187 -164
- package/output/source/tools/roadmap.js +173 -76
- package/output/source/tools/roadmap.test.js +58 -42
- package/output/source/tools/task.js +380 -255
- package/output/source/tools/task.test.js +117 -110
- package/output/source/types.js +22 -22
- package/package.json +8 -2
|
@@ -1,169 +1,176 @@
|
|
|
1
|
-
import { describe, expect, it } from
|
|
2
|
-
import { collectTaskLintSuggestions, isValidTaskId, normalizeTask, rankActionableTaskCandidates, resolveNoTaskDiscoveryGuidance, renderTaskSeedTemplate, renderTasksMarkdown, loadTasksDocument, saveTasks, taskPriority, toTaskUpdatedAtMs, validateTransition, } from
|
|
3
|
-
import fs from
|
|
4
|
-
import os from
|
|
5
|
-
import path from
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { collectTaskLintSuggestions, isValidTaskId, normalizeTask, rankActionableTaskCandidates, resolveNoTaskDiscoveryGuidance, renderTaskSeedTemplate, renderTasksMarkdown, loadTasksDocument, saveTasks, taskPriority, toTaskUpdatedAtMs, validateTransition, } from './task.js';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
6
|
function buildCandidate(partial) {
|
|
7
7
|
const task = normalizeTask({
|
|
8
8
|
id: partial.id,
|
|
9
9
|
title: partial.title,
|
|
10
10
|
status: partial.status,
|
|
11
|
-
updatedAt: partial.task?.updatedAt ??
|
|
11
|
+
updatedAt: partial.task?.updatedAt ?? '2026-01-01T00:00:00.000Z',
|
|
12
12
|
});
|
|
13
13
|
return {
|
|
14
|
-
governanceDir: partial.governanceDir ??
|
|
14
|
+
governanceDir: partial.governanceDir ?? '/workspace/a',
|
|
15
15
|
task,
|
|
16
16
|
projectScore: partial.projectScore ?? 1,
|
|
17
|
-
projectLatestUpdatedAt: partial.projectLatestUpdatedAt ??
|
|
17
|
+
projectLatestUpdatedAt: partial.projectLatestUpdatedAt ?? '2026-01-01T00:00:00.000Z',
|
|
18
18
|
taskUpdatedAtMs: partial.taskUpdatedAtMs ?? toTaskUpdatedAtMs(task.updatedAt),
|
|
19
19
|
taskPriority: partial.taskPriority ?? taskPriority(task.status),
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
-
describe(
|
|
23
|
-
it(
|
|
24
|
-
expect(isValidTaskId(
|
|
25
|
-
expect(isValidTaskId(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
expect(validateTransition(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
expect(taskPriority(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
22
|
+
describe('tasks module', () => {
|
|
23
|
+
it('validates task IDs', () => {
|
|
24
|
+
expect(isValidTaskId('TASK-0001')).toBe(true);
|
|
25
|
+
expect(isValidTaskId('TASK-1')).toBe(true);
|
|
26
|
+
expect(isValidTaskId('TASK-12345')).toBe(true);
|
|
27
|
+
expect(isValidTaskId('TASK-ABCD')).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
it('allows and rejects expected transitions', () => {
|
|
30
|
+
expect(validateTransition('TODO', 'IN_PROGRESS')).toBe(true);
|
|
31
|
+
expect(validateTransition('IN_PROGRESS', 'DONE')).toBe(true);
|
|
32
|
+
expect(validateTransition('DONE', 'IN_PROGRESS')).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
it('assigns priority for actionable statuses', () => {
|
|
35
|
+
expect(taskPriority('IN_PROGRESS')).toBe(2);
|
|
36
|
+
expect(taskPriority('TODO')).toBe(1);
|
|
37
|
+
expect(taskPriority('BLOCKED')).toBe(0);
|
|
38
|
+
});
|
|
39
|
+
it('returns zero timestamp for invalid date', () => {
|
|
40
|
+
expect(toTaskUpdatedAtMs('invalid')).toBe(0);
|
|
41
|
+
});
|
|
42
|
+
it('ranks by project score, then task priority, then recency', () => {
|
|
41
43
|
const candidates = [
|
|
42
|
-
buildCandidate({ id:
|
|
43
|
-
buildCandidate({ id:
|
|
44
|
-
buildCandidate({ id:
|
|
44
|
+
buildCandidate({ id: 'TASK-0001', title: 'A', status: 'TODO', projectScore: 2 }),
|
|
45
|
+
buildCandidate({ id: 'TASK-0002', title: 'B', status: 'IN_PROGRESS', projectScore: 2 }),
|
|
46
|
+
buildCandidate({ id: 'TASK-0003', title: 'C', status: 'IN_PROGRESS', projectScore: 3 }),
|
|
45
47
|
];
|
|
46
48
|
const ranked = rankActionableTaskCandidates(candidates);
|
|
47
|
-
expect(ranked[0].task.id).toBe(
|
|
48
|
-
expect(ranked[1].task.id).toBe(
|
|
49
|
-
expect(ranked[2].task.id).toBe(
|
|
49
|
+
expect(ranked[0].task.id).toBe('TASK-0003');
|
|
50
|
+
expect(ranked[1].task.id).toBe('TASK-0002');
|
|
51
|
+
expect(ranked[2].task.id).toBe('TASK-0001');
|
|
50
52
|
});
|
|
51
|
-
it(
|
|
52
|
-
const task = normalizeTask({ id:
|
|
53
|
+
it('renders task markdown without legacy markers', () => {
|
|
54
|
+
const task = normalizeTask({ id: 'TASK-0002', title: 'render', status: 'IN_PROGRESS' });
|
|
53
55
|
const markdown = renderTasksMarkdown([task]);
|
|
54
|
-
expect(markdown.includes(
|
|
55
|
-
expect(markdown.includes(
|
|
56
|
-
expect(markdown.includes(
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
expect(markdown.includes('PROJITIVE:TASKS:START')).toBe(false);
|
|
57
|
+
expect(markdown.includes('PROJITIVE:TASKS:END')).toBe(false);
|
|
58
|
+
expect(markdown.includes('## TASK-0002 | IN_PROGRESS | render')).toBe(true);
|
|
59
|
+
expect(markdown).toContain('Author: yinxulai');
|
|
60
|
+
expect(markdown).toContain('Repository: https://github.com/yinxulai/projitive');
|
|
61
|
+
expect(markdown).toContain('Do not edit this file manually.');
|
|
62
|
+
});
|
|
63
|
+
it('renders tasks with subState and blocker metadata', () => {
|
|
59
64
|
const task1 = normalizeTask({
|
|
60
|
-
id:
|
|
61
|
-
title:
|
|
62
|
-
status:
|
|
65
|
+
id: 'TASK-0001',
|
|
66
|
+
title: 'In Progress Task',
|
|
67
|
+
status: 'IN_PROGRESS',
|
|
63
68
|
subState: {
|
|
64
|
-
phase:
|
|
69
|
+
phase: 'implementation',
|
|
65
70
|
confidence: 0.85,
|
|
66
71
|
},
|
|
67
72
|
});
|
|
68
73
|
const task2 = normalizeTask({
|
|
69
|
-
id:
|
|
70
|
-
title:
|
|
71
|
-
status:
|
|
74
|
+
id: 'TASK-0002',
|
|
75
|
+
title: 'Blocked Task',
|
|
76
|
+
status: 'BLOCKED',
|
|
72
77
|
blocker: {
|
|
73
|
-
type:
|
|
74
|
-
description:
|
|
78
|
+
type: 'external_dependency',
|
|
79
|
+
description: 'Waiting for API',
|
|
75
80
|
},
|
|
76
81
|
});
|
|
77
82
|
const markdown = renderTasksMarkdown([task1, task2]);
|
|
78
|
-
expect(markdown).toContain(
|
|
79
|
-
expect(markdown).toContain(
|
|
80
|
-
expect(markdown).toContain(
|
|
81
|
-
expect(markdown).toContain(
|
|
83
|
+
expect(markdown).toContain('phase: implementation');
|
|
84
|
+
expect(markdown).toContain('confidence: 0.85');
|
|
85
|
+
expect(markdown).toContain('type: external_dependency');
|
|
86
|
+
expect(markdown).toContain('description: Waiting for API');
|
|
82
87
|
});
|
|
83
|
-
it(
|
|
88
|
+
it('collects lint lines with stable code prefix', () => {
|
|
84
89
|
const task = normalizeTask({
|
|
85
|
-
id:
|
|
86
|
-
title:
|
|
87
|
-
status:
|
|
88
|
-
owner:
|
|
90
|
+
id: 'TASK-0001',
|
|
91
|
+
title: 'lint',
|
|
92
|
+
status: 'IN_PROGRESS',
|
|
93
|
+
owner: '',
|
|
89
94
|
roadmapRefs: [],
|
|
90
95
|
});
|
|
91
96
|
const lint = collectTaskLintSuggestions([task]);
|
|
92
|
-
expect(lint.some((line) => line.startsWith(
|
|
93
|
-
expect(lint.some((line) => line.startsWith(
|
|
97
|
+
expect(lint.some((line) => line.startsWith('- [TASK_IN_PROGRESS_OWNER_EMPTY]'))).toBe(true);
|
|
98
|
+
expect(lint.some((line) => line.startsWith('- [TASK_ROADMAP_REFS_EMPTY]'))).toBe(true);
|
|
94
99
|
});
|
|
95
|
-
it(
|
|
100
|
+
it('collects blocker/substate lint rules', () => {
|
|
96
101
|
const blocked = normalizeTask({
|
|
97
|
-
id:
|
|
98
|
-
title:
|
|
99
|
-
status:
|
|
100
|
-
summary:
|
|
101
|
-
roadmapRefs: [
|
|
102
|
+
id: 'TASK-0001',
|
|
103
|
+
title: 'Blocked',
|
|
104
|
+
status: 'BLOCKED',
|
|
105
|
+
summary: 'blocked reason',
|
|
106
|
+
roadmapRefs: ['ROADMAP-0001'],
|
|
102
107
|
});
|
|
103
108
|
const inProgress = normalizeTask({
|
|
104
|
-
id:
|
|
105
|
-
title:
|
|
106
|
-
status:
|
|
107
|
-
owner:
|
|
108
|
-
roadmapRefs: [
|
|
109
|
+
id: 'TASK-0002',
|
|
110
|
+
title: 'In Progress',
|
|
111
|
+
status: 'IN_PROGRESS',
|
|
112
|
+
owner: 'ai-copilot',
|
|
113
|
+
roadmapRefs: ['ROADMAP-0001'],
|
|
109
114
|
});
|
|
110
115
|
const lint = collectTaskLintSuggestions([blocked, inProgress]);
|
|
111
|
-
expect(lint.some((line) => line.includes(
|
|
112
|
-
expect(lint.some((line) => line.includes(
|
|
116
|
+
expect(lint.some((line) => line.includes('BLOCKED_WITHOUT_BLOCKER'))).toBe(true);
|
|
117
|
+
expect(lint.some((line) => line.includes('IN_PROGRESS_WITHOUT_SUBSTATE'))).toBe(true);
|
|
113
118
|
});
|
|
114
|
-
it(
|
|
119
|
+
it('normalizes links to project-root-relative format without leading slash', () => {
|
|
115
120
|
const task = normalizeTask({
|
|
116
|
-
id:
|
|
117
|
-
title:
|
|
118
|
-
status:
|
|
119
|
-
links: [
|
|
121
|
+
id: 'TASK-0003',
|
|
122
|
+
title: 'link normalize',
|
|
123
|
+
status: 'TODO',
|
|
124
|
+
links: ['/reports/a.md', './designs/b.md', 'reports/c.md', 'https://example.com/evidence'],
|
|
120
125
|
});
|
|
121
|
-
expect(task.links).toContain(
|
|
122
|
-
expect(task.links).toContain(
|
|
123
|
-
expect(task.links).toContain(
|
|
124
|
-
expect(task.links).toContain(
|
|
125
|
-
expect(task.links.some((item) => item.startsWith(
|
|
126
|
+
expect(task.links).toContain('reports/a.md');
|
|
127
|
+
expect(task.links).toContain('designs/b.md');
|
|
128
|
+
expect(task.links).toContain('reports/c.md');
|
|
129
|
+
expect(task.links).toContain('https://example.com/evidence');
|
|
130
|
+
expect(task.links.some((item) => item.startsWith('/'))).toBe(false);
|
|
126
131
|
});
|
|
127
|
-
it(
|
|
132
|
+
it('lints invalid links path format', () => {
|
|
128
133
|
const task = normalizeTask({
|
|
129
|
-
id:
|
|
130
|
-
title:
|
|
131
|
-
status:
|
|
132
|
-
links: [
|
|
133
|
-
roadmapRefs: [
|
|
134
|
+
id: 'TASK-0004',
|
|
135
|
+
title: 'invalid link',
|
|
136
|
+
status: 'TODO',
|
|
137
|
+
links: ['../outside.md'],
|
|
138
|
+
roadmapRefs: ['ROADMAP-0001'],
|
|
134
139
|
});
|
|
135
140
|
const lint = collectTaskLintSuggestions([task]);
|
|
136
|
-
expect(lint.some((line) => line.includes(
|
|
141
|
+
expect(lint.some((line) => line.includes('TASK_LINK_PATH_FORMAT_INVALID'))).toBe(true);
|
|
137
142
|
});
|
|
138
|
-
it(
|
|
139
|
-
const lines = renderTaskSeedTemplate(
|
|
140
|
-
const markdown = lines.join(
|
|
141
|
-
expect(markdown).toContain(
|
|
143
|
+
it('renders seed task template with provided roadmap ref', () => {
|
|
144
|
+
const lines = renderTaskSeedTemplate('ROADMAP-0099');
|
|
145
|
+
const markdown = lines.join('\n');
|
|
146
|
+
expect(markdown).toContain('- roadmapRefs: ROADMAP-0099');
|
|
142
147
|
});
|
|
143
|
-
it(
|
|
144
|
-
const guidance = await resolveNoTaskDiscoveryGuidance(
|
|
148
|
+
it('uses default no-task guidance when hook file is absent', async () => {
|
|
149
|
+
const guidance = await resolveNoTaskDiscoveryGuidance('/path/that/does/not/exist');
|
|
145
150
|
expect(guidance.length).toBeGreaterThan(3);
|
|
146
151
|
});
|
|
147
|
-
it(
|
|
148
|
-
const guidanceA = await resolveNoTaskDiscoveryGuidance(
|
|
149
|
-
const guidanceB = await resolveNoTaskDiscoveryGuidance(
|
|
152
|
+
it('returns same default no-task guidance regardless of path', async () => {
|
|
153
|
+
const guidanceA = await resolveNoTaskDiscoveryGuidance('/path/that/does/not/exist');
|
|
154
|
+
const guidanceB = await resolveNoTaskDiscoveryGuidance('/another/path');
|
|
150
155
|
expect(guidanceA).toEqual(guidanceB);
|
|
151
156
|
});
|
|
152
|
-
it(
|
|
153
|
-
const root = await fs.mkdtemp(path.join(os.tmpdir(),
|
|
154
|
-
const governanceDir = path.join(root,
|
|
157
|
+
it('loads and saves tasks from governance store and keeps newest-first order', async () => {
|
|
158
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'projitive-mcp-task-'));
|
|
159
|
+
const governanceDir = path.join(root, '.projitive');
|
|
155
160
|
await fs.mkdir(governanceDir, { recursive: true });
|
|
156
|
-
await fs.writeFile(path.join(governanceDir,
|
|
157
|
-
const tasksPath = path.join(governanceDir,
|
|
161
|
+
await fs.writeFile(path.join(governanceDir, '.projitive'), '', 'utf-8');
|
|
162
|
+
const tasksPath = path.join(governanceDir, '.projitive');
|
|
158
163
|
await saveTasks(tasksPath, [
|
|
159
|
-
normalizeTask({ id:
|
|
160
|
-
normalizeTask({ id:
|
|
164
|
+
normalizeTask({ id: 'TASK-0001', title: 'older', status: 'TODO', updatedAt: '2026-01-01T00:00:00.000Z' }),
|
|
165
|
+
normalizeTask({ id: 'TASK-0002', title: 'newer', status: 'TODO', updatedAt: '2026-02-01T00:00:00.000Z' }),
|
|
161
166
|
]);
|
|
162
167
|
const loaded = await loadTasksDocument(governanceDir);
|
|
163
|
-
expect(loaded.tasks[0].id).toBe(
|
|
164
|
-
expect(loaded.tasks[1].id).toBe(
|
|
165
|
-
const markdown = await fs.readFile(path.join(governanceDir,
|
|
166
|
-
expect(markdown).toContain(
|
|
168
|
+
expect(loaded.tasks[0].id).toBe('TASK-0002');
|
|
169
|
+
expect(loaded.tasks[1].id).toBe('TASK-0001');
|
|
170
|
+
const markdown = await fs.readFile(path.join(governanceDir, 'tasks.md'), 'utf-8');
|
|
171
|
+
expect(markdown).toContain('generated from .projitive governance store');
|
|
172
|
+
expect(markdown).toContain('Author: yinxulai');
|
|
173
|
+
expect(markdown).toContain('Repository: https://github.com/yinxulai/projitive');
|
|
167
174
|
await fs.rm(root, { recursive: true, force: true });
|
|
168
175
|
});
|
|
169
176
|
});
|
package/output/source/types.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// ============================================================================
|
|
6
6
|
// Task State Machine
|
|
7
7
|
// ============================================================================
|
|
8
|
-
export const ALLOWED_STATUS = [
|
|
8
|
+
export const ALLOWED_STATUS = ['TODO', 'IN_PROGRESS', 'BLOCKED', 'DONE'];
|
|
9
9
|
// ============================================================================
|
|
10
10
|
// Sub-state Metadata (Spec v1.1.0)
|
|
11
11
|
// ============================================================================
|
|
@@ -16,33 +16,33 @@ export const ALLOWED_STATUS = ["TODO", "IN_PROGRESS", "BLOCKED", "DONE"];
|
|
|
16
16
|
* - implementation: Writing and testing code
|
|
17
17
|
* - testing: Validation and verification
|
|
18
18
|
*/
|
|
19
|
-
export const SUB_STATE_PHASES = [
|
|
19
|
+
export const SUB_STATE_PHASES = ['discovery', 'design', 'implementation', 'testing'];
|
|
20
20
|
/**
|
|
21
21
|
* Blocker categorization for BLOCKED state (Spec v1.1.0)
|
|
22
22
|
*/
|
|
23
23
|
export const BLOCKER_TYPES = [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
'internal_dependency',
|
|
25
|
+
'external_dependency',
|
|
26
|
+
'resource',
|
|
27
|
+
'approval'
|
|
28
28
|
];
|
|
29
29
|
export const TASK_LINT_CODES = {
|
|
30
|
-
DUPLICATE_ID:
|
|
31
|
-
IN_PROGRESS_OWNER_EMPTY:
|
|
32
|
-
DONE_LINKS_MISSING:
|
|
33
|
-
BLOCKED_SUMMARY_EMPTY:
|
|
34
|
-
UPDATED_AT_INVALID:
|
|
35
|
-
ROADMAP_REFS_EMPTY:
|
|
36
|
-
OUTSIDE_MARKER:
|
|
37
|
-
FILTER_EMPTY:
|
|
38
|
-
LINK_TARGET_MISSING:
|
|
39
|
-
LINK_PATH_FORMAT_INVALID:
|
|
30
|
+
DUPLICATE_ID: 'TASK_DUPLICATE_ID',
|
|
31
|
+
IN_PROGRESS_OWNER_EMPTY: 'TASK_IN_PROGRESS_OWNER_EMPTY',
|
|
32
|
+
DONE_LINKS_MISSING: 'TASK_DONE_LINKS_MISSING',
|
|
33
|
+
BLOCKED_SUMMARY_EMPTY: 'TASK_BLOCKED_SUMMARY_EMPTY',
|
|
34
|
+
UPDATED_AT_INVALID: 'TASK_UPDATED_AT_INVALID',
|
|
35
|
+
ROADMAP_REFS_EMPTY: 'TASK_ROADMAP_REFS_EMPTY',
|
|
36
|
+
OUTSIDE_MARKER: 'TASK_OUTSIDE_MARKER',
|
|
37
|
+
FILTER_EMPTY: 'TASK_FILTER_EMPTY',
|
|
38
|
+
LINK_TARGET_MISSING: 'TASK_LINK_TARGET_MISSING',
|
|
39
|
+
LINK_PATH_FORMAT_INVALID: 'TASK_LINK_PATH_FORMAT_INVALID',
|
|
40
40
|
// Spec v1.1.0 - Blocker Categorization
|
|
41
|
-
BLOCKED_WITHOUT_BLOCKER:
|
|
42
|
-
BLOCKER_TYPE_INVALID:
|
|
43
|
-
BLOCKER_DESCRIPTION_EMPTY:
|
|
41
|
+
BLOCKED_WITHOUT_BLOCKER: 'TASK_BLOCKED_WITHOUT_BLOCKER',
|
|
42
|
+
BLOCKER_TYPE_INVALID: 'TASK_BLOCKER_TYPE_INVALID',
|
|
43
|
+
BLOCKER_DESCRIPTION_EMPTY: 'TASK_BLOCKER_DESCRIPTION_EMPTY',
|
|
44
44
|
// Spec v1.1.0 - Sub-state Metadata
|
|
45
|
-
IN_PROGRESS_WITHOUT_SUBSTATE:
|
|
46
|
-
SUBSTATE_PHASE_INVALID:
|
|
47
|
-
SUBSTATE_CONFIDENCE_INVALID:
|
|
45
|
+
IN_PROGRESS_WITHOUT_SUBSTATE: 'TASK_IN_PROGRESS_WITHOUT_SUBSTATE',
|
|
46
|
+
SUBSTATE_PHASE_INVALID: 'TASK_SUBSTATE_PHASE_INVALID',
|
|
47
|
+
SUBSTATE_CONFIDENCE_INVALID: 'TASK_SUBSTATE_CONFIDENCE_INVALID',
|
|
48
48
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@projitive/mcp",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "Projitive MCP Server for project and task discovery/update",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "",
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
"test": "vitest run",
|
|
17
17
|
"test:coverage": "vitest run --coverage",
|
|
18
18
|
"benchmark": "vitest bench --run",
|
|
19
|
-
"lint": "
|
|
19
|
+
"lint": "npm run lint:types && npm run lint:eslint",
|
|
20
|
+
"lint:types": "tsc -p tsconfig.json --noEmit",
|
|
21
|
+
"lint:eslint": "eslint .",
|
|
20
22
|
"build": "rm -rf output && tsc -p tsconfig.json",
|
|
21
23
|
"prepublishOnly": "npm run build",
|
|
22
24
|
"dev": "tsc -p tsconfig.json --watch"
|
|
@@ -31,8 +33,12 @@
|
|
|
31
33
|
"devDependencies": {
|
|
32
34
|
"@types/node": "^24.3.0",
|
|
33
35
|
"@vitest/coverage-v8": "^3.2.4",
|
|
36
|
+
"@eslint/js": "^9.37.0",
|
|
37
|
+
"eslint": "^9.37.0",
|
|
38
|
+
"globals": "^16.4.0",
|
|
34
39
|
"tsx": "^4.20.5",
|
|
35
40
|
"typescript": "^5.9.2",
|
|
41
|
+
"typescript-eslint": "^8.45.0",
|
|
36
42
|
"vitest": "^3.2.4"
|
|
37
43
|
}
|
|
38
44
|
}
|