mcp-adr-analysis-server 2.5.4 → 2.6.0
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/dist/.tsbuildinfo +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +74 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/resources/todo-list-resource.d.ts +6 -0
- package/dist/src/resources/todo-list-resource.d.ts.map +1 -1
- package/dist/src/resources/todo-list-resource.js +55 -0
- package/dist/src/resources/todo-list-resource.js.map +1 -1
- package/dist/src/tools/generate-adr-todo-tool.d.ts +34 -0
- package/dist/src/tools/generate-adr-todo-tool.d.ts.map +1 -0
- package/dist/src/tools/generate-adr-todo-tool.js +292 -0
- package/dist/src/tools/generate-adr-todo-tool.js.map +1 -0
- package/dist/src/tools/release-tracking-tool.d.ts.map +1 -1
- package/dist/src/tools/release-tracking-tool.js +119 -21
- package/dist/src/tools/release-tracking-tool.js.map +1 -1
- package/dist/src/tools/tool-catalog.d.ts.map +1 -1
- package/dist/src/tools/tool-catalog.js +29 -0
- package/dist/src/tools/tool-catalog.js.map +1 -1
- package/dist/src/utils/adr-todo-generator.d.ts +77 -0
- package/dist/src/utils/adr-todo-generator.d.ts.map +1 -0
- package/dist/src/utils/adr-todo-generator.js +320 -0
- package/dist/src/utils/adr-todo-generator.js.map +1 -0
- package/dist/src/utils/local-milestone-store.d.ts +40 -0
- package/dist/src/utils/local-milestone-store.d.ts.map +1 -0
- package/dist/src/utils/local-milestone-store.js +185 -0
- package/dist/src/utils/local-milestone-store.js.map +1 -0
- package/dist/src/utils/release-readiness-detector.d.ts +8 -0
- package/dist/src/utils/release-readiness-detector.d.ts.map +1 -1
- package/dist/src/utils/release-readiness-detector.js.map +1 -1
- package/package.json +2 -2
|
@@ -12,6 +12,12 @@ export interface TodoTask {
|
|
|
12
12
|
dependencies?: string[];
|
|
13
13
|
createdAt?: string;
|
|
14
14
|
updatedAt?: string;
|
|
15
|
+
adrId?: string;
|
|
16
|
+
linkedAdrs?: string[];
|
|
17
|
+
milestoneId?: string;
|
|
18
|
+
tddPhase?: 'test' | 'production';
|
|
19
|
+
effort?: string;
|
|
20
|
+
category?: string;
|
|
15
21
|
}
|
|
16
22
|
/**
|
|
17
23
|
* Generate comprehensive todo list resource with task management and progress tracking.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"todo-list-resource.d.ts","sourceRoot":"","sources":["../../../src/resources/todo-list-resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"todo-list-resource.d.ts","sourceRoot":"","sources":["../../../src/resources/todo-list-resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAkID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CA2DlF"}
|
|
@@ -14,6 +14,46 @@ function parseTodoMarkdown(content) {
|
|
|
14
14
|
const lines = content.split('\n');
|
|
15
15
|
let currentTask = null;
|
|
16
16
|
let taskCounter = 0;
|
|
17
|
+
const pinPatterns = [
|
|
18
|
+
[
|
|
19
|
+
/<!--\s*adr:\s*([^\s>]+)\s*-->/i,
|
|
20
|
+
(m, t) => {
|
|
21
|
+
if (m[1])
|
|
22
|
+
t.adrId = m[1];
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
[
|
|
26
|
+
/<!--\s*linked-adrs:\s*([^>]+?)\s*-->/i,
|
|
27
|
+
(m, t) => {
|
|
28
|
+
if (m[1])
|
|
29
|
+
t.linkedAdrs = m[1]
|
|
30
|
+
.split(',')
|
|
31
|
+
.map(s => s.trim())
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
/<!--\s*milestone:\s*([^\s>]+)\s*-->/i,
|
|
37
|
+
(m, t) => {
|
|
38
|
+
if (m[1])
|
|
39
|
+
t.milestoneId = m[1];
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
/<!--\s*tdd:\s*(test|production)\s*-->/i,
|
|
44
|
+
(m, t) => {
|
|
45
|
+
if (m[1])
|
|
46
|
+
t.tddPhase = m[1].toLowerCase();
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
/<!--\s*task-id:\s*([^\s>]+)\s*-->/i,
|
|
51
|
+
(m, t) => {
|
|
52
|
+
if (m[1])
|
|
53
|
+
t.id = m[1];
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
];
|
|
17
57
|
for (const line of lines) {
|
|
18
58
|
const trimmed = line.trim();
|
|
19
59
|
// Parse task line: ## Task Title
|
|
@@ -30,6 +70,20 @@ function parseTodoMarkdown(content) {
|
|
|
30
70
|
};
|
|
31
71
|
continue;
|
|
32
72
|
}
|
|
73
|
+
// Parse inline pin comments
|
|
74
|
+
if (currentTask) {
|
|
75
|
+
let pinMatched = false;
|
|
76
|
+
for (const [pattern, apply] of pinPatterns) {
|
|
77
|
+
const m = trimmed.match(pattern);
|
|
78
|
+
if (m) {
|
|
79
|
+
apply(m, currentTask);
|
|
80
|
+
pinMatched = true;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (pinMatched)
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
33
87
|
// Parse status
|
|
34
88
|
if (trimmed.startsWith('**Status:**') && currentTask) {
|
|
35
89
|
const status = trimmed.substring(11).trim().toLowerCase();
|
|
@@ -65,6 +119,7 @@ function parseTodoMarkdown(content) {
|
|
|
65
119
|
if (currentTask &&
|
|
66
120
|
!trimmed.startsWith('**') &&
|
|
67
121
|
!trimmed.startsWith('#') &&
|
|
122
|
+
!trimmed.startsWith('<!--') &&
|
|
68
123
|
trimmed.length > 0) {
|
|
69
124
|
currentTask.description = (currentTask.description || '') + '\n' + trimmed;
|
|
70
125
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"todo-list-resource.js","sourceRoot":"","sources":["../../../src/resources/todo-list-resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"todo-list-resource.js","sourceRoot":"","sources":["../../../src/resources/todo-list-resource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generate_adr_todo MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Decomposes ADRs into TODO entries with stable IDs, idempotent merging, and
|
|
5
|
+
* optional milestone linking. Mirrors the bounded-section persistence pattern
|
|
6
|
+
* proven in `release-tracker.ts:580-596` so manual edits to TODO.md outside the
|
|
7
|
+
* managed block are preserved verbatim.
|
|
8
|
+
*
|
|
9
|
+
* Re-runs are safe: tasks key off `adrId + slug(title) + tddPhase`, user-set
|
|
10
|
+
* status survives, and tasks whose source ADR is deleted/superseded are moved
|
|
11
|
+
* to a "Stale Tasks" subsection rather than silently dropped.
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
declare const GenerateAdrTodoSchema: z.ZodObject<{
|
|
15
|
+
adrDirectory: z.ZodDefault<z.ZodString>;
|
|
16
|
+
scope: z.ZodDefault<z.ZodEnum<{
|
|
17
|
+
pending: "pending";
|
|
18
|
+
accepted: "accepted";
|
|
19
|
+
all: "all";
|
|
20
|
+
}>>;
|
|
21
|
+
projectPath: z.ZodOptional<z.ZodString>;
|
|
22
|
+
todoPath: z.ZodDefault<z.ZodString>;
|
|
23
|
+
phase: z.ZodDefault<z.ZodEnum<{
|
|
24
|
+
test: "test";
|
|
25
|
+
production: "production";
|
|
26
|
+
both: "both";
|
|
27
|
+
}>>;
|
|
28
|
+
linkToMilestones: z.ZodDefault<z.ZodBoolean>;
|
|
29
|
+
dryRun: z.ZodDefault<z.ZodBoolean>;
|
|
30
|
+
}, z.core.$strip>;
|
|
31
|
+
export type GenerateAdrTodoArgs = z.infer<typeof GenerateAdrTodoSchema>;
|
|
32
|
+
export declare function generateAdrTodo(args: Record<string, unknown>): Promise<any>;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=generate-adr-todo-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-adr-todo-tool.d.ts","sourceRoot":"","sources":["../../../src/tools/generate-adr-todo-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiBxB,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;iBAmBzB,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAoIxE,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAyIjF"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generate_adr_todo MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Decomposes ADRs into TODO entries with stable IDs, idempotent merging, and
|
|
5
|
+
* optional milestone linking. Mirrors the bounded-section persistence pattern
|
|
6
|
+
* proven in `release-tracker.ts:580-596` so manual edits to TODO.md outside the
|
|
7
|
+
* managed block are preserved verbatim.
|
|
8
|
+
*
|
|
9
|
+
* Re-runs are safe: tasks key off `adrId + slug(title) + tddPhase`, user-set
|
|
10
|
+
* status survives, and tasks whose source ADR is deleted/superseded are moved
|
|
11
|
+
* to a "Stale Tasks" subsection rather than silently dropped.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
14
|
+
import { resolve } from 'path';
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
import { McpAdrError } from '../types/index.js';
|
|
17
|
+
import { jsonSafeError } from '../utils/json-safe.js';
|
|
18
|
+
import { validateMcpResponse } from '../utils/mcp-response-validator.js';
|
|
19
|
+
import { discoverAdrsInDirectory } from '../utils/adr-discovery.js';
|
|
20
|
+
import { decomposeAdrToTasks, linkTasksToMilestones, mergeTodoTasks, renderTodoSection, spliceTodoSection, } from '../utils/adr-todo-generator.js';
|
|
21
|
+
import { listLocal } from '../utils/local-milestone-store.js';
|
|
22
|
+
import { buildMilestoneMap } from '../utils/release-tracker.js';
|
|
23
|
+
const GenerateAdrTodoSchema = z.object({
|
|
24
|
+
adrDirectory: z.string().default('docs/adrs').describe('Directory containing ADR files'),
|
|
25
|
+
scope: z
|
|
26
|
+
.enum(['all', 'pending', 'accepted'])
|
|
27
|
+
.default('pending')
|
|
28
|
+
.describe('Which ADRs to decompose: all, pending (proposed/draft), or accepted only'),
|
|
29
|
+
projectPath: z.string().optional().describe('Project root path (defaults to process.cwd())'),
|
|
30
|
+
todoPath: z.string().default('TODO.md').describe('Output TODO file (relative to projectPath)'),
|
|
31
|
+
phase: z
|
|
32
|
+
.enum(['both', 'test', 'production'])
|
|
33
|
+
.default('both')
|
|
34
|
+
.describe('TDD pairing: "both" emits paired test+production tasks (default), "production" or "test" narrows output'),
|
|
35
|
+
linkToMilestones: z
|
|
36
|
+
.boolean()
|
|
37
|
+
.default(true)
|
|
38
|
+
.describe('Link generated tasks to release milestones (local + GitHub merged)'),
|
|
39
|
+
dryRun: z.boolean().default(false).describe('Compute changes but do not write TODO.md'),
|
|
40
|
+
});
|
|
41
|
+
function inScope(status, scope) {
|
|
42
|
+
if (scope === 'all')
|
|
43
|
+
return true;
|
|
44
|
+
const s = (status || '').toLowerCase();
|
|
45
|
+
if (scope === 'accepted')
|
|
46
|
+
return s === 'accepted';
|
|
47
|
+
// 'pending' covers anything that isn't accepted/superseded/deprecated/rejected
|
|
48
|
+
return !['accepted', 'superseded', 'deprecated', 'rejected'].includes(s);
|
|
49
|
+
}
|
|
50
|
+
function isSuperseded(status) {
|
|
51
|
+
const s = (status || '').toLowerCase();
|
|
52
|
+
return s === 'superseded' || s === 'deprecated' || s === 'rejected';
|
|
53
|
+
}
|
|
54
|
+
function parseExistingTasks(content) {
|
|
55
|
+
// Lightweight parser scoped to the bounded section. We can't import the
|
|
56
|
+
// private `parseTodoMarkdown` from `todo-list-resource.ts`, so we replicate
|
|
57
|
+
// its behavior over the entire content (cheap; TODO.md is tiny in practice).
|
|
58
|
+
const tasks = [];
|
|
59
|
+
const lines = content.split('\n');
|
|
60
|
+
let current = null;
|
|
61
|
+
let counter = 0;
|
|
62
|
+
const pinPatterns = [
|
|
63
|
+
[
|
|
64
|
+
/<!--\s*adr:\s*([^\s>]+)\s*-->/i,
|
|
65
|
+
(m, t) => {
|
|
66
|
+
if (m[1])
|
|
67
|
+
t.adrId = m[1];
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
[
|
|
71
|
+
/<!--\s*linked-adrs:\s*([^>]+?)\s*-->/i,
|
|
72
|
+
(m, t) => {
|
|
73
|
+
if (m[1])
|
|
74
|
+
t.linkedAdrs = m[1]
|
|
75
|
+
.split(',')
|
|
76
|
+
.map(s => s.trim())
|
|
77
|
+
.filter(Boolean);
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
[
|
|
81
|
+
/<!--\s*milestone:\s*([^\s>]+)\s*-->/i,
|
|
82
|
+
(m, t) => {
|
|
83
|
+
if (m[1])
|
|
84
|
+
t.milestoneId = m[1];
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
/<!--\s*tdd:\s*(test|production)\s*-->/i,
|
|
89
|
+
(m, t) => {
|
|
90
|
+
if (m[1])
|
|
91
|
+
t.tddPhase = m[1].toLowerCase();
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
/<!--\s*task-id:\s*([^\s>]+)\s*-->/i,
|
|
96
|
+
(m, t) => {
|
|
97
|
+
if (m[1])
|
|
98
|
+
t.id = m[1];
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
];
|
|
102
|
+
for (const line of lines) {
|
|
103
|
+
const trimmed = line.trim();
|
|
104
|
+
if (trimmed.startsWith('## ')) {
|
|
105
|
+
if (current)
|
|
106
|
+
tasks.push(current);
|
|
107
|
+
counter++;
|
|
108
|
+
current = {
|
|
109
|
+
id: `task-${counter}`,
|
|
110
|
+
title: trimmed.substring(3).trim(),
|
|
111
|
+
status: 'pending',
|
|
112
|
+
};
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (current) {
|
|
116
|
+
let pinned = false;
|
|
117
|
+
for (const [pat, apply] of pinPatterns) {
|
|
118
|
+
const m = trimmed.match(pat);
|
|
119
|
+
if (m) {
|
|
120
|
+
apply(m, current);
|
|
121
|
+
pinned = true;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (pinned)
|
|
126
|
+
continue;
|
|
127
|
+
if (trimmed.startsWith('**Status:**')) {
|
|
128
|
+
const status = trimmed.substring(11).trim().toLowerCase();
|
|
129
|
+
current.status = status.includes('progress')
|
|
130
|
+
? 'in_progress'
|
|
131
|
+
: status.includes('completed')
|
|
132
|
+
? 'completed'
|
|
133
|
+
: 'pending';
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (trimmed.startsWith('**Priority:**')) {
|
|
137
|
+
const p = trimmed.substring(13).trim().toLowerCase();
|
|
138
|
+
current.priority = p.includes('critical')
|
|
139
|
+
? 'critical'
|
|
140
|
+
: p.includes('high')
|
|
141
|
+
? 'high'
|
|
142
|
+
: p.includes('low')
|
|
143
|
+
? 'low'
|
|
144
|
+
: 'medium';
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (trimmed.startsWith('**Effort:**')) {
|
|
148
|
+
current.effort = trimmed.substring(11).trim();
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (trimmed.startsWith('**Category:**')) {
|
|
152
|
+
current.category = trimmed.substring(13).trim();
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (!trimmed.startsWith('**') &&
|
|
156
|
+
!trimmed.startsWith('#') &&
|
|
157
|
+
!trimmed.startsWith('<!--') &&
|
|
158
|
+
trimmed.length > 0) {
|
|
159
|
+
current.description =
|
|
160
|
+
(current.description || '') + (current.description ? '\n' : '') + trimmed;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (current)
|
|
165
|
+
tasks.push(current);
|
|
166
|
+
return tasks;
|
|
167
|
+
}
|
|
168
|
+
export async function generateAdrTodo(args) {
|
|
169
|
+
try {
|
|
170
|
+
const validated = GenerateAdrTodoSchema.parse(args);
|
|
171
|
+
const projectPath = validated.projectPath ?? process.cwd();
|
|
172
|
+
const discovery = await discoverAdrsInDirectory(validated.adrDirectory, projectPath, {
|
|
173
|
+
includeContent: true,
|
|
174
|
+
includeTimeline: false,
|
|
175
|
+
});
|
|
176
|
+
const allAdrs = discovery.adrs;
|
|
177
|
+
const filteredAdrs = allAdrs.filter(a => inScope(a.status, validated.scope));
|
|
178
|
+
const activeAdrIds = new Set(allAdrs.filter(a => !isSuperseded(a.status)).map(a => a.filename));
|
|
179
|
+
const supersededAdrIds = new Set(allAdrs.filter(a => isSuperseded(a.status)).map(a => a.filename));
|
|
180
|
+
const generatedAt = new Date().toISOString();
|
|
181
|
+
const generated = [];
|
|
182
|
+
for (const adr of filteredAdrs) {
|
|
183
|
+
generated.push(...decomposeAdrToTasks(adr, { phase: validated.phase, generatedAt }));
|
|
184
|
+
}
|
|
185
|
+
const milestones = validated.linkToMilestones
|
|
186
|
+
? await buildMilestoneMap(allAdrs, projectPath).catch(() => [])
|
|
187
|
+
: [];
|
|
188
|
+
if (validated.linkToMilestones) {
|
|
189
|
+
try {
|
|
190
|
+
const local = listLocal(projectPath);
|
|
191
|
+
const seen = new Set(milestones.map(m => (m.id || m.name).toLowerCase()));
|
|
192
|
+
for (const lm of local) {
|
|
193
|
+
const key = (lm.id || lm.name).toLowerCase();
|
|
194
|
+
if (!seen.has(key)) {
|
|
195
|
+
milestones.push(lm);
|
|
196
|
+
seen.add(key);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// local store missing or unreadable — non-fatal
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
let linkedTasks = generated;
|
|
205
|
+
let linkedMilestones = milestones;
|
|
206
|
+
if (validated.linkToMilestones && milestones.length > 0) {
|
|
207
|
+
const linked = linkTasksToMilestones(generated, milestones, allAdrs);
|
|
208
|
+
linkedTasks = linked.tasks;
|
|
209
|
+
linkedMilestones = linked.milestones;
|
|
210
|
+
}
|
|
211
|
+
const todoFullPath = resolve(projectPath, validated.todoPath);
|
|
212
|
+
const existingContent = existsSync(todoFullPath) ? readFileSync(todoFullPath, 'utf8') : '';
|
|
213
|
+
const existingTasks = existingContent ? parseExistingTasks(existingContent) : [];
|
|
214
|
+
const mergeResult = mergeTodoTasks(existingTasks, linkedTasks, {
|
|
215
|
+
activeAdrIds,
|
|
216
|
+
supersededAdrIds,
|
|
217
|
+
});
|
|
218
|
+
// Only ADR-derived tasks belong inside the managed section. Manual tasks
|
|
219
|
+
// (no adrId) get rendered as part of the user's hand-edited content
|
|
220
|
+
// outside the bounded block, so we don't include them in the section.
|
|
221
|
+
const managedTasks = mergeResult.merged.filter(t => !!t.adrId);
|
|
222
|
+
const section = renderTodoSection(managedTasks, mergeResult.stale, {
|
|
223
|
+
milestones: linkedMilestones,
|
|
224
|
+
generatedAt,
|
|
225
|
+
});
|
|
226
|
+
const newContent = spliceTodoSection(existingContent, section);
|
|
227
|
+
let wrote = false;
|
|
228
|
+
if (!validated.dryRun && newContent !== existingContent) {
|
|
229
|
+
writeFileSync(todoFullPath, newContent, 'utf8');
|
|
230
|
+
wrote = true;
|
|
231
|
+
}
|
|
232
|
+
const summaryLines = [
|
|
233
|
+
`# Generate ADR TODO`,
|
|
234
|
+
``,
|
|
235
|
+
`**ADR directory:** \`${validated.adrDirectory}\``,
|
|
236
|
+
`**Scope:** ${validated.scope}`,
|
|
237
|
+
`**Phase:** ${validated.phase}`,
|
|
238
|
+
`**TODO file:** \`${validated.todoPath}\` ${wrote ? '(updated)' : validated.dryRun ? '(dry run — not written)' : '(unchanged)'}`,
|
|
239
|
+
``,
|
|
240
|
+
`## Summary`,
|
|
241
|
+
``,
|
|
242
|
+
`- ADRs discovered: ${allAdrs.length}`,
|
|
243
|
+
`- ADRs in scope: ${filteredAdrs.length}`,
|
|
244
|
+
`- Tasks generated: ${linkedTasks.length}`,
|
|
245
|
+
`- Tasks added: ${mergeResult.added}`,
|
|
246
|
+
`- Tasks preserved: ${mergeResult.preserved}`,
|
|
247
|
+
`- Stale tasks (moved to "Stale Tasks"): ${mergeResult.stale.length}`,
|
|
248
|
+
`- Milestones linked: ${linkedMilestones.length}`,
|
|
249
|
+
``,
|
|
250
|
+
];
|
|
251
|
+
if (mergeResult.stale.length > 0) {
|
|
252
|
+
summaryLines.push(`## Stale Tasks`, ``);
|
|
253
|
+
for (const t of mergeResult.stale.slice(0, 20)) {
|
|
254
|
+
summaryLines.push(`- \`${t.id}\` — ${t.title}${t.adrId ? ` _(orphaned: ${t.adrId})_` : ''}`);
|
|
255
|
+
}
|
|
256
|
+
if (mergeResult.stale.length > 20) {
|
|
257
|
+
summaryLines.push(`- … and ${mergeResult.stale.length - 20} more`);
|
|
258
|
+
}
|
|
259
|
+
summaryLines.push(``);
|
|
260
|
+
}
|
|
261
|
+
if (validated.dryRun) {
|
|
262
|
+
summaryLines.push(`## Dry-Run Diff Preview`, ``, '```diff', ...buildSimpleDiff(existingContent, newContent).slice(0, 200), '```', ``);
|
|
263
|
+
}
|
|
264
|
+
if (filteredAdrs.length === 0) {
|
|
265
|
+
summaryLines.push(`## No ADRs in scope`, ``, `Add ADR markdown files under \`${validated.adrDirectory}\` (or widen \`scope\`) and re-run.`);
|
|
266
|
+
}
|
|
267
|
+
return validateMcpResponse({
|
|
268
|
+
content: [{ type: 'text', text: summaryLines.join('\n') }],
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
throw new McpAdrError(`generate_adr_todo failed: ${jsonSafeError(error)}`, 'GENERATE_ADR_TODO_ERROR');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function buildSimpleDiff(before, after) {
|
|
276
|
+
const beforeLines = before.split('\n');
|
|
277
|
+
const afterLines = after.split('\n');
|
|
278
|
+
const out = [];
|
|
279
|
+
const max = Math.max(beforeLines.length, afterLines.length);
|
|
280
|
+
for (let i = 0; i < max; i++) {
|
|
281
|
+
const a = beforeLines[i];
|
|
282
|
+
const b = afterLines[i];
|
|
283
|
+
if (a === b)
|
|
284
|
+
continue;
|
|
285
|
+
if (a !== undefined)
|
|
286
|
+
out.push(`- ${a}`);
|
|
287
|
+
if (b !== undefined)
|
|
288
|
+
out.push(`+ ${b}`);
|
|
289
|
+
}
|
|
290
|
+
return out;
|
|
291
|
+
}
|
|
292
|
+
//# sourceMappingURL=generate-adr-todo-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-adr-todo-tool.js","sourceRoot":"","sources":["../../../src/tools/generate-adr-todo-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release-tracking-tool.d.ts","sourceRoot":"","sources":["../../../src/tools/release-tracking-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"release-tracking-tool.d.ts","sourceRoot":"","sources":["../../../src/tools/release-tracking-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAwGH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAmDjF"}
|
|
@@ -20,6 +20,7 @@ import { McpAdrError } from '../types/index.js';
|
|
|
20
20
|
import { validateMcpResponse } from '../utils/mcp-response-validator.js';
|
|
21
21
|
import { jsonSafeError } from '../utils/json-safe.js';
|
|
22
22
|
import { detectReleases, detectProjectType, mapAdrsToReleases, generateChangelog, writeChangelog, compareReleases, buildMilestoneMap, createGitHubRelease, syncGitHubMilestone, updateTodoMilestones, previewNextRelease, saveTrackingState, } from '../utils/release-tracker.js';
|
|
23
|
+
import { listLocal, markPushed, slugify, upsertLocal, writeReleasePlanFile, } from '../utils/local-milestone-store.js';
|
|
23
24
|
// ─── Schema ────────────────────────────────────────────────────────
|
|
24
25
|
const ReleaseTrackingSchema = z.object({
|
|
25
26
|
operation: z
|
|
@@ -32,6 +33,7 @@ const ReleaseTrackingSchema = z.object({
|
|
|
32
33
|
'next_release_preview',
|
|
33
34
|
'create_milestone',
|
|
34
35
|
'sync_milestones',
|
|
36
|
+
'push_local_milestones',
|
|
35
37
|
])
|
|
36
38
|
.describe('Operation to perform'),
|
|
37
39
|
projectPath: z.string().optional().describe('Project root path'),
|
|
@@ -66,6 +68,18 @@ const ReleaseTrackingSchema = z.object({
|
|
|
66
68
|
.default(false)
|
|
67
69
|
.describe('Sync milestones to GitHub (requires gh CLI)'),
|
|
68
70
|
updateTodo: z.boolean().default(false).describe('Update TODO.md with milestone status'),
|
|
71
|
+
localOnly: z
|
|
72
|
+
.boolean()
|
|
73
|
+
.default(false)
|
|
74
|
+
.describe('For create_milestone: persist locally instead of calling gh CLI'),
|
|
75
|
+
writeReleasePlan: z
|
|
76
|
+
.boolean()
|
|
77
|
+
.default(false)
|
|
78
|
+
.describe('For create_milestone/push_local_milestones: also render local milestones into RELEASE_PLAN.md (bounded section)'),
|
|
79
|
+
releasePlanPath: z
|
|
80
|
+
.string()
|
|
81
|
+
.default('RELEASE_PLAN.md')
|
|
82
|
+
.describe('Path to RELEASE_PLAN.md (relative to projectPath)'),
|
|
69
83
|
});
|
|
70
84
|
// ─── Main Export ───────────────────────────────────────────────────
|
|
71
85
|
export async function releaseTracking(args) {
|
|
@@ -97,6 +111,8 @@ export async function releaseTracking(args) {
|
|
|
97
111
|
return await handleCreateMilestone(projectPath, validatedArgs);
|
|
98
112
|
case 'sync_milestones':
|
|
99
113
|
return await handleSyncMilestones(projectPath, adrs, validatedArgs);
|
|
114
|
+
case 'push_local_milestones':
|
|
115
|
+
return await handlePushLocalMilestones(projectPath, validatedArgs);
|
|
100
116
|
default:
|
|
101
117
|
throw new McpAdrError('INVALID_ARGS', `Unknown operation: ${validatedArgs.operation}`);
|
|
102
118
|
}
|
|
@@ -407,32 +423,114 @@ ${preview.readiness.recommendations.join('\n')}`,
|
|
|
407
423
|
],
|
|
408
424
|
});
|
|
409
425
|
}
|
|
426
|
+
function persistLocalMilestone(projectPath, args, pushed, githubNumber) {
|
|
427
|
+
const id = slugify(args.milestoneTitle);
|
|
428
|
+
const milestone = {
|
|
429
|
+
id,
|
|
430
|
+
name: args.milestoneTitle,
|
|
431
|
+
completed: 0,
|
|
432
|
+
total: 0,
|
|
433
|
+
completionRate: 0,
|
|
434
|
+
criticalTodos: 0,
|
|
435
|
+
blockers: [],
|
|
436
|
+
linkedAdrIds: [],
|
|
437
|
+
linkedTodoIds: [],
|
|
438
|
+
source: pushed ? 'github' : 'local',
|
|
439
|
+
pushed,
|
|
440
|
+
...(args.milestoneDescription !== undefined ? { description: args.milestoneDescription } : {}),
|
|
441
|
+
...(args.milestoneDueDate !== undefined ? { dueDate: args.milestoneDueDate } : {}),
|
|
442
|
+
...(githubNumber !== undefined ? { githubNumber } : {}),
|
|
443
|
+
};
|
|
444
|
+
return upsertLocal(projectPath, milestone);
|
|
445
|
+
}
|
|
410
446
|
async function handleCreateMilestone(projectPath, args) {
|
|
411
447
|
if (!args.milestoneTitle) {
|
|
412
448
|
throw new McpAdrError('INVALID_ARGS', 'milestoneTitle is required for create_milestone operation');
|
|
413
449
|
}
|
|
414
|
-
|
|
450
|
+
let mode = args.localOnly ? 'local-only' : 'github';
|
|
451
|
+
let ghNumber;
|
|
452
|
+
let ghError;
|
|
453
|
+
if (!args.localOnly) {
|
|
454
|
+
const result = syncGitHubMilestone(projectPath, args.milestoneTitle, args.milestoneDescription || '', args.milestoneDueDate);
|
|
455
|
+
if (result.success) {
|
|
456
|
+
ghNumber = result.number;
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
mode = 'local-fallback';
|
|
460
|
+
ghError = result.error;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
const stored = persistLocalMilestone(projectPath, args, mode === 'github', ghNumber);
|
|
464
|
+
let releasePlanPath;
|
|
465
|
+
if (args.writeReleasePlan) {
|
|
466
|
+
const milestones = listLocal(projectPath);
|
|
467
|
+
releasePlanPath = writeReleasePlanFile(projectPath, milestones, args.releasePlanPath);
|
|
468
|
+
}
|
|
469
|
+
const summary = [];
|
|
470
|
+
if (mode === 'github') {
|
|
471
|
+
summary.push(`# Milestone Created/Updated`, ``, `**Title**: ${args.milestoneTitle}`, `**Number**: #${ghNumber}`, `**Local id**: \`${stored.id}\` (cached for offline use)`);
|
|
472
|
+
}
|
|
473
|
+
else if (mode === 'local-only') {
|
|
474
|
+
summary.push(`# Milestone Persisted Locally`, ``, `**Title**: ${args.milestoneTitle}`, `**Local id**: \`${stored.id}\``, `**Storage**: \`.mcp-adr-cache/milestones.local.json\``, ``, `Run \`release_tracking\` with \`operation: "push_local_milestones"\` once \`gh\` auth is configured to publish.`);
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
summary.push(`# Milestone Persisted Locally (gh fallback)`, ``, `**Title**: ${args.milestoneTitle}`, `**Local id**: \`${stored.id}\``, `**Storage**: \`.mcp-adr-cache/milestones.local.json\``, ``, `⚠️ \`gh api\` failed: ${ghError ?? 'unknown error'}.`, ``, `The milestone has been saved locally so the workflow can continue. Resolve gh auth (\`gh auth status\`) then run \`release_tracking\` with \`operation: "push_local_milestones"\` to sync upstream. Pass \`localOnly: true\` to suppress this fallback warning.`);
|
|
478
|
+
}
|
|
479
|
+
if (args.milestoneDescription)
|
|
480
|
+
summary.push(`**Description**: ${args.milestoneDescription}`);
|
|
481
|
+
if (args.milestoneDueDate)
|
|
482
|
+
summary.push(`**Due Date**: ${args.milestoneDueDate}`);
|
|
483
|
+
if (releasePlanPath) {
|
|
484
|
+
summary.push(``, `📝 RELEASE_PLAN.md updated at \`${releasePlanPath}\``);
|
|
485
|
+
}
|
|
415
486
|
return validateMcpResponse({
|
|
416
|
-
content: [
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
: `#
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
487
|
+
content: [{ type: 'text', text: summary.join('\n') }],
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
async function handlePushLocalMilestones(projectPath, args) {
|
|
491
|
+
const local = listLocal(projectPath);
|
|
492
|
+
if (local.length === 0) {
|
|
493
|
+
return validateMcpResponse({
|
|
494
|
+
content: [
|
|
495
|
+
{
|
|
496
|
+
type: 'text',
|
|
497
|
+
text: `# Push Local Milestones\n\nNo local milestones found at \`.mcp-adr-cache/milestones.local.json\`. Create one first via \`release_tracking\` with \`operation: "create_milestone"\` and \`localOnly: true\`.`,
|
|
498
|
+
},
|
|
499
|
+
],
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
const lines = [`# Push Local Milestones`, ``, `**Total**: ${local.length}`, ``];
|
|
503
|
+
let synced = 0;
|
|
504
|
+
let skipped = 0;
|
|
505
|
+
let failed = 0;
|
|
506
|
+
for (const milestone of local) {
|
|
507
|
+
if (milestone.pushed) {
|
|
508
|
+
lines.push(`- ⏭️ \`${milestone.id ?? slugify(milestone.name)}\` — already pushed (#${milestone.githubNumber ?? '?'})`);
|
|
509
|
+
skipped += 1;
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
const result = syncGitHubMilestone(projectPath, milestone.name, milestone.description ?? '', milestone.dueDate);
|
|
513
|
+
if (result.success && result.number !== undefined) {
|
|
514
|
+
markPushed(projectPath, milestone.id ?? slugify(milestone.name), result.number);
|
|
515
|
+
lines.push(`- ✅ \`${milestone.id ?? slugify(milestone.name)}\` — pushed (#${result.number})`);
|
|
516
|
+
synced += 1;
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
lines.push(`- ❌ \`${milestone.id ?? slugify(milestone.name)}\` — failed (${result.error ?? 'unknown error'})`);
|
|
520
|
+
failed += 1;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
lines.push(``, `**Synced**: ${synced} · **Skipped**: ${skipped} · **Failed**: ${failed}`);
|
|
524
|
+
if (args.writeReleasePlan) {
|
|
525
|
+
const refreshed = listLocal(projectPath);
|
|
526
|
+
const path = writeReleasePlanFile(projectPath, refreshed, args.releasePlanPath);
|
|
527
|
+
lines.push(``, `📝 RELEASE_PLAN.md updated at \`${path}\``);
|
|
528
|
+
}
|
|
529
|
+
if (failed > 0) {
|
|
530
|
+
lines.push(``, `⚠️ Some pushes failed. Run \`gh auth status\` to verify auth and re-invoke \`push_local_milestones\` to retry.`);
|
|
531
|
+
}
|
|
532
|
+
return validateMcpResponse({
|
|
533
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
436
534
|
});
|
|
437
535
|
}
|
|
438
536
|
async function handleSyncMilestones(projectPath, adrs, args) {
|