@mcoda/core 0.1.26 → 0.1.28

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.
@@ -64,6 +64,7 @@ export declare class TaskSufficiencyService {
64
64
  private loadProjectSnapshot;
65
65
  private evaluateCoverage;
66
66
  private buildGapItems;
67
+ private bundleGapItems;
67
68
  private ensureTargetStory;
68
69
  private insertGapTasks;
69
70
  private writeReportArtifacts;
@@ -1 +1 @@
1
- {"version":3,"file":"TaskSufficiencyService.d.ts","sourceRoot":"","sources":["../../../src/services/planning/TaskSufficiencyService.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAiC,MAAM,WAAW,CAAC;AAE/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAsCnD,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,mBAAmB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,aAAa,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,UAAU,EAAE,6BAA6B,EAAE,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,KAAK,mBAAmB,GAAG;IACzB,aAAa,EAAE,mBAAmB,CAAC;IACnC,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAqFF,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;IAC5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;gBAG9C,SAAS,EAAE,mBAAmB,EAC9B,IAAI,EAAE,mBAAmB,EACzB,SAAS,GAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAO;WAS9D,MAAM,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAU9E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YASd,gBAAgB;YA4BhB,iBAAiB;YAmCjB,cAAc;YAcd,mBAAmB;IAgEjC,OAAO,CAAC,gBAAgB;IA2BxB,OAAO,CAAC,aAAa;YAqBP,iBAAiB;YAyFjB,cAAc;YAkGd,oBAAoB;IAkB5B,QAAQ,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC;CA4R1F"}
1
+ {"version":3,"file":"TaskSufficiencyService.d.ts","sourceRoot":"","sources":["../../../src/services/planning/TaskSufficiencyService.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAiC,MAAM,WAAW,CAAC;AAE/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAmGnD,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,mBAAmB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,aAAa,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,UAAU,EAAE,6BAA6B,EAAE,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,KAAK,mBAAmB,GAAG;IACzB,aAAa,EAAE,mBAAmB,CAAC;IACnC,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAsNF,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;IAC5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;gBAG9C,SAAS,EAAE,mBAAmB,EAC9B,IAAI,EAAE,mBAAmB,EACzB,SAAS,GAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAO;WAS9D,MAAM,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAU9E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YASd,gBAAgB;YA4BhB,iBAAiB;YAmCjB,cAAc;YAcd,mBAAmB;IAwEjC,OAAO,CAAC,gBAAgB;IA2BxB,OAAO,CAAC,aAAa;IA+BrB,OAAO,CAAC,cAAc;YA2BR,iBAAiB;YAyGjB,cAAc;YAkId,oBAAoB;IAkB5B,QAAQ,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC;CA2U1F"}
@@ -6,14 +6,65 @@ import { JobService } from "../jobs/JobService.js";
6
6
  import { createEpicKeyGenerator, createStoryKeyGenerator, createTaskKeyGenerator } from "./KeyHelpers.js";
7
7
  const DEFAULT_MAX_ITERATIONS = 5;
8
8
  const DEFAULT_MAX_TASKS_PER_ITERATION = 24;
9
- const DEFAULT_MIN_COVERAGE_RATIO = 0.96;
9
+ const DEFAULT_MIN_COVERAGE_RATIO = 1;
10
10
  const SDS_SCAN_MAX_FILES = 120;
11
11
  const SDS_HEADING_LIMIT = 200;
12
12
  const SDS_FOLDER_LIMIT = 240;
13
+ const GAP_BUNDLE_MAX_ANCHORS = 3;
14
+ const COVERAGE_HEURISTICS_VERSION = 2;
13
15
  const REPORT_FILE_NAME = "task-sufficiency-report.json";
14
16
  const ignoredDirs = new Set([".git", "node_modules", "dist", "build", ".mcoda", ".docdex"]);
15
17
  const sdsFilenamePattern = /(sds|software[-_ ]design|system[-_ ]design|design[-_ ]spec)/i;
16
18
  const sdsContentPattern = /(software design specification|system design specification|^#\s*sds\b)/im;
19
+ const nonImplementationHeadingPattern = /\b(software design specification|system design specification|\bsds\b|revision history|table of contents|purpose|scope|definitions?|abbreviations?|glossary|references?|appendix|document control|authors?)\b/i;
20
+ const likelyImplementationHeadingPattern = /\b(architecture|entity|entities|service|services|module|modules|component|components|pipeline|workflow|api|endpoint|schema|model|feature|store|database|ingestion|training|inference|ui|frontend|backend|ops|observability|security|deployment|solver|integration|testing|validation|contract|index|mapping|registry|cache|queue|event|job|task|migration|controller|router|policy)\b/i;
21
+ const repoRootSegments = new Set([
22
+ "apps",
23
+ "api",
24
+ "backend",
25
+ "config",
26
+ "configs",
27
+ "db",
28
+ "deployment",
29
+ "deployments",
30
+ "docs",
31
+ "frontend",
32
+ "implementation",
33
+ "infra",
34
+ "internal",
35
+ "packages",
36
+ "scripts",
37
+ "service",
38
+ "services",
39
+ "shared",
40
+ "src",
41
+ "test",
42
+ "tests",
43
+ "ui",
44
+ "web",
45
+ ]);
46
+ const headingNoiseTokens = new Set(["and", "for", "from", "into", "the", "with"]);
47
+ const coverageStopTokens = new Set([
48
+ "about",
49
+ "across",
50
+ "after",
51
+ "before",
52
+ "between",
53
+ "from",
54
+ "into",
55
+ "over",
56
+ "under",
57
+ "using",
58
+ "with",
59
+ "without",
60
+ "into",
61
+ "onto",
62
+ "the",
63
+ "and",
64
+ "for",
65
+ "of",
66
+ "to",
67
+ ]);
17
68
  const normalizeText = (value) => value
18
69
  .toLowerCase()
19
70
  .replace(/[`*_]/g, " ")
@@ -22,16 +73,104 @@ const normalizeText = (value) => value
22
73
  .trim();
23
74
  const normalizeAnchor = (kind, value) => `${kind}:${normalizeText(value).replace(/\s+/g, " ").trim()}`;
24
75
  const unique = (items) => Array.from(new Set(items.filter(Boolean)));
76
+ const stripDecorators = (value) => value
77
+ .replace(/[`*_]/g, " ")
78
+ .replace(/^[\s>:\-[\]().]+/, "")
79
+ .replace(/\s+/g, " ")
80
+ .trim();
81
+ const normalizeHeadingCandidate = (value) => {
82
+ const cleaned = stripDecorators(value).replace(/^\d+(?:\.\d+)*\s+/, "").trim();
83
+ return cleaned.length > 0 ? cleaned : stripDecorators(value);
84
+ };
85
+ const headingLooksImplementationRelevant = (heading) => {
86
+ const normalized = normalizeHeadingCandidate(heading).toLowerCase();
87
+ if (!normalized || normalized.length < 3)
88
+ return false;
89
+ if (nonImplementationHeadingPattern.test(normalized))
90
+ return false;
91
+ if (likelyImplementationHeadingPattern.test(normalized))
92
+ return true;
93
+ const sectionMatch = heading.trim().match(/^(\d+)(?:\.\d+)*(?:\s+|$)/);
94
+ if (sectionMatch) {
95
+ const major = Number.parseInt(sectionMatch[1] ?? "", 10);
96
+ if (Number.isFinite(major) && major >= 3)
97
+ return true;
98
+ }
99
+ const tokens = normalized
100
+ .split(/\s+/)
101
+ .map((token) => token.replace(/[^a-z0-9.-]+/g, ""))
102
+ .filter((token) => token.length >= 4 && !headingNoiseTokens.has(token));
103
+ return tokens.length >= 2;
104
+ };
105
+ const normalizeFolderEntry = (entry) => {
106
+ const trimmed = stripDecorators(entry)
107
+ .replace(/^\.?\//, "")
108
+ .replace(/\/+$/, "")
109
+ .replace(/\s+/g, "");
110
+ if (!trimmed.includes("/"))
111
+ return undefined;
112
+ if (trimmed.includes("...") || trimmed.includes("*"))
113
+ return undefined;
114
+ return trimmed;
115
+ };
116
+ const folderEntryLooksRepoRelevant = (entry) => {
117
+ const normalized = normalizeFolderEntry(entry);
118
+ if (!normalized)
119
+ return false;
120
+ if (normalized.startsWith("/") || /^[A-Za-z]:\//.test(normalized))
121
+ return false;
122
+ const segments = normalized.split("/").filter(Boolean);
123
+ if (segments.length < 2)
124
+ return false;
125
+ const root = segments[0].toLowerCase();
126
+ return repoRootSegments.has(root);
127
+ };
128
+ const deriveSectionDomain = (heading) => {
129
+ const normalized = normalizeHeadingCandidate(heading).toLowerCase();
130
+ const tokens = normalized
131
+ .split(/\s+/)
132
+ .map((token) => token.replace(/[^a-z0-9.-]+/g, ""))
133
+ .filter((token) => token.length >= 3 && !headingNoiseTokens.has(token));
134
+ return tokens[0] ?? "coverage";
135
+ };
136
+ const deriveFolderDomain = (entry) => {
137
+ const normalized = normalizeFolderEntry(entry)?.toLowerCase();
138
+ if (!normalized)
139
+ return "structure";
140
+ const segments = normalized.split("/").filter(Boolean);
141
+ if (segments.length === 0)
142
+ return "structure";
143
+ return segments.length === 1 ? segments[0] : `${segments[0]}-${segments[1]}`;
144
+ };
25
145
  const extractMarkdownHeadings = (content, limit) => {
26
146
  if (!content)
27
147
  return [];
28
- const matches = [...content.matchAll(/^\s{0,3}#{1,6}\s+(.+?)\s*$/gm)];
148
+ const lines = content.split(/\r?\n/);
29
149
  const headings = [];
30
- for (const match of matches) {
31
- const heading = match[1]?.replace(/#+$/, "").trim();
32
- if (!heading)
150
+ for (let index = 0; index < lines.length; index += 1) {
151
+ const line = lines[index]?.trim() ?? "";
152
+ if (!line)
33
153
  continue;
34
- headings.push(heading);
154
+ const hashHeading = line.match(/^#{1,6}\s+(.+)$/);
155
+ if (hashHeading) {
156
+ const heading = hashHeading[1]?.replace(/#+$/, "").trim();
157
+ if (heading)
158
+ headings.push(heading);
159
+ }
160
+ else if (index + 1 < lines.length &&
161
+ /^[=-]{3,}\s*$/.test((lines[index + 1] ?? "").trim()) &&
162
+ !line.startsWith("-") &&
163
+ !line.startsWith("*")) {
164
+ headings.push(line);
165
+ }
166
+ else {
167
+ const numberedHeading = line.match(/^(\d+(?:\.\d+)+)\s+(.+)$/);
168
+ if (numberedHeading) {
169
+ const heading = `${numberedHeading[1]} ${numberedHeading[2]}`.trim();
170
+ if (/[a-z]/i.test(heading))
171
+ headings.push(heading);
172
+ }
173
+ }
35
174
  if (headings.length >= limit)
36
175
  break;
37
176
  }
@@ -60,39 +199,73 @@ const extractFolderEntries = (content, limit) => {
60
199
  }
61
200
  return unique(candidates).slice(0, limit);
62
201
  };
202
+ const tokenizeCoverageSignal = (value) => unique(value
203
+ .split(/\s+/)
204
+ .map((token) => token.replace(/[^a-z0-9._-]+/g, ""))
205
+ .filter((token) => token.length >= 3 && !coverageStopTokens.has(token)));
206
+ const buildBigrams = (tokens) => {
207
+ const bigrams = [];
208
+ for (let index = 0; index < tokens.length - 1; index += 1) {
209
+ const left = tokens[index];
210
+ const right = tokens[index + 1];
211
+ if (!left || !right)
212
+ continue;
213
+ bigrams.push(`${left} ${right}`);
214
+ }
215
+ return unique(bigrams);
216
+ };
63
217
  const headingCovered = (corpus, heading) => {
64
- const normalized = normalizeText(heading);
218
+ const normalized = normalizeText(normalizeHeadingCandidate(heading));
65
219
  if (!normalized)
66
220
  return true;
67
221
  if (corpus.includes(normalized))
68
222
  return true;
69
- const tokens = normalized
70
- .split(/\s+/)
71
- .filter((token) => token.length >= 4)
72
- .slice(0, 8);
223
+ const tokens = tokenizeCoverageSignal(normalized).slice(0, 10);
73
224
  if (tokens.length === 0)
74
225
  return true;
75
226
  const hitCount = tokens.filter((token) => corpus.includes(token)).length;
76
- const minHits = Math.min(2, tokens.length);
77
- return hitCount >= minHits;
227
+ const requiredHits = tokens.length <= 2
228
+ ? tokens.length
229
+ : tokens.length <= 4
230
+ ? 2
231
+ : Math.min(4, Math.ceil(tokens.length * 0.6));
232
+ if (hitCount < requiredHits)
233
+ return false;
234
+ if (tokens.length >= 3) {
235
+ const longestToken = tokens.reduce((longest, token) => (token.length > longest.length ? token : longest), "");
236
+ if (longestToken.length >= 6 && !corpus.includes(longestToken))
237
+ return false;
238
+ }
239
+ const bigrams = buildBigrams(tokens);
240
+ if (tokens.length >= 3 && bigrams.length > 0 && !bigrams.some((bigram) => corpus.includes(bigram))) {
241
+ return false;
242
+ }
243
+ return true;
78
244
  };
79
245
  const folderEntryCovered = (corpus, entry) => {
80
- const normalized = normalizeText(entry).replace(/\s+/g, "");
81
- if (!normalized)
246
+ const normalizedEntry = normalizeFolderEntry(entry)?.toLowerCase().replace(/\/+/g, "/");
247
+ if (!normalizedEntry)
82
248
  return true;
83
- if (corpus.includes(normalized))
249
+ const corpusTight = corpus.replace(/\s+/g, "");
250
+ if (corpusTight.includes(normalizedEntry.replace(/\s+/g, "")))
84
251
  return true;
85
- const segments = normalized.split("/").filter(Boolean);
252
+ const segments = normalizedEntry
253
+ .split("/")
254
+ .map((segment) => segment.trim().replace(/[^a-z0-9._-]+/g, ""))
255
+ .filter(Boolean);
86
256
  if (segments.length === 0)
87
257
  return true;
88
- const leaf = segments[segments.length - 1];
89
- const parent = segments.length > 1 ? segments[segments.length - 2] : undefined;
90
- if (leaf && corpus.includes(leaf)) {
91
- if (!parent)
92
- return true;
93
- return corpus.includes(parent);
258
+ const tailSegments = unique(segments.slice(Math.max(0, segments.length - 3)));
259
+ const hitCount = tailSegments.filter((segment) => corpus.includes(segment)).length;
260
+ const requiredHits = tailSegments.length <= 1 ? 1 : Math.min(2, tailSegments.length);
261
+ if (hitCount < requiredHits)
262
+ return false;
263
+ if (tailSegments.length >= 2) {
264
+ const hasStrongTokenMatch = tailSegments.some((segment) => segment.length >= 5 && corpus.includes(segment));
265
+ if (!hasStrongTokenMatch)
266
+ return false;
94
267
  }
95
- return false;
268
+ return true;
96
269
  };
97
270
  const readJsonSafe = (raw, fallback) => {
98
271
  if (typeof raw !== "string" || raw.trim().length === 0)
@@ -241,10 +414,19 @@ export class TaskSufficiencyService {
241
414
  for (const task of tasks) {
242
415
  corpusChunks.push(`${task.title ?? ""} ${task.description ?? ""}`);
243
416
  const metadata = readJsonSafe(task.metadata_json, null);
244
- const rawAnchor = metadata?.sufficiencyAudit?.anchor;
417
+ const sufficiencyAudit = metadata?.sufficiencyAudit;
418
+ const rawAnchor = sufficiencyAudit?.anchor;
245
419
  if (typeof rawAnchor === "string" && rawAnchor.trim().length > 0) {
246
420
  existingAnchors.add(rawAnchor.trim());
247
421
  }
422
+ const rawAnchors = sufficiencyAudit?.anchors;
423
+ if (Array.isArray(rawAnchors)) {
424
+ for (const anchor of rawAnchors) {
425
+ if (typeof anchor !== "string" || anchor.trim().length === 0)
426
+ continue;
427
+ existingAnchors.add(anchor.trim());
428
+ }
429
+ }
248
430
  }
249
431
  return {
250
432
  project,
@@ -285,7 +467,12 @@ export class TaskSufficiencyService {
285
467
  const normalizedAnchor = normalizeAnchor("section", heading);
286
468
  if (existingAnchors.has(normalizedAnchor))
287
469
  continue;
288
- items.push({ kind: "section", value: heading, normalizedAnchor });
470
+ items.push({
471
+ kind: "section",
472
+ value: heading,
473
+ normalizedAnchor,
474
+ domain: deriveSectionDomain(heading),
475
+ });
289
476
  if (items.length >= limit)
290
477
  return items;
291
478
  }
@@ -293,36 +480,82 @@ export class TaskSufficiencyService {
293
480
  const normalizedAnchor = normalizeAnchor("folder", entry);
294
481
  if (existingAnchors.has(normalizedAnchor))
295
482
  continue;
296
- items.push({ kind: "folder", value: entry, normalizedAnchor });
483
+ items.push({
484
+ kind: "folder",
485
+ value: entry,
486
+ normalizedAnchor,
487
+ domain: deriveFolderDomain(entry),
488
+ });
297
489
  if (items.length >= limit)
298
490
  return items;
299
491
  }
300
492
  return items;
301
493
  }
494
+ bundleGapItems(gapItems, limit) {
495
+ const bundles = [];
496
+ const activeByDomain = new Map();
497
+ for (const item of gapItems.slice(0, limit)) {
498
+ const domainKey = item.domain;
499
+ let bundle = activeByDomain.get(domainKey);
500
+ if (!bundle || bundle.values.length >= GAP_BUNDLE_MAX_ANCHORS) {
501
+ bundle = {
502
+ kind: item.kind,
503
+ domain: item.domain,
504
+ values: [],
505
+ normalizedAnchors: [],
506
+ };
507
+ bundles.push(bundle);
508
+ activeByDomain.set(domainKey, bundle);
509
+ }
510
+ else if (bundle.kind !== item.kind) {
511
+ bundle.kind = "mixed";
512
+ }
513
+ if (!bundle.values.includes(item.value))
514
+ bundle.values.push(item.value);
515
+ if (!bundle.normalizedAnchors.includes(item.normalizedAnchor)) {
516
+ bundle.normalizedAnchors.push(item.normalizedAnchor);
517
+ }
518
+ if (bundles.length >= limit)
519
+ break;
520
+ }
521
+ return bundles.slice(0, limit);
522
+ }
302
523
  async ensureTargetStory(project) {
303
524
  const db = this.workspaceRepo.getDb();
304
- const existingStory = await db.get(`SELECT us.id AS story_id, us.key AS story_key, us.epic_id AS epic_id, e.key AS epic_key
525
+ const existingStories = await db.all(`SELECT
526
+ us.id AS story_id,
527
+ us.key AS story_key,
528
+ us.metadata_json AS story_metadata_json,
529
+ us.epic_id AS epic_id,
530
+ e.key AS epic_key,
531
+ e.metadata_json AS epic_metadata_json
305
532
  FROM user_stories us
306
533
  JOIN epics e ON e.id = us.epic_id
307
534
  WHERE us.project_id = ?
308
- ORDER BY COALESCE(us.priority, 2147483647), datetime(us.created_at), us.key
309
- LIMIT 1`, project.id);
310
- if (existingStory) {
311
- return {
312
- epicId: existingStory.epic_id,
313
- epicKey: existingStory.epic_key,
314
- storyId: existingStory.story_id,
315
- storyKey: existingStory.story_key,
316
- };
535
+ ORDER BY COALESCE(us.priority, 2147483647), datetime(us.created_at), us.key`, project.id);
536
+ for (const row of existingStories) {
537
+ const storyMetadata = readJsonSafe(row.story_metadata_json, null) ?? {};
538
+ const epicMetadata = readJsonSafe(row.epic_metadata_json, null) ?? {};
539
+ const storySource = typeof storyMetadata.source === "string" ? storyMetadata.source : undefined;
540
+ const epicSource = typeof epicMetadata.source === "string" ? epicMetadata.source : undefined;
541
+ if (storySource === "task-sufficiency-audit" || epicSource === "task-sufficiency-audit") {
542
+ return {
543
+ epicId: row.epic_id,
544
+ epicKey: row.epic_key,
545
+ storyId: row.story_id,
546
+ storyKey: row.story_key,
547
+ };
548
+ }
317
549
  }
318
550
  let epicId = "";
319
551
  let epicKey = "";
320
- const existingEpic = await db.get(`SELECT id, key
552
+ const existingEpic = await db.get(`SELECT id, key, metadata_json
321
553
  FROM epics
322
554
  WHERE project_id = ?
323
- ORDER BY COALESCE(priority, 2147483647), datetime(created_at), key
324
- LIMIT 1`, project.id);
325
- if (existingEpic) {
555
+ ORDER BY COALESCE(priority, 2147483647), datetime(created_at), key`, project.id);
556
+ const existingEpicMetadata = readJsonSafe(existingEpic?.metadata_json, null) ?? {};
557
+ const existingEpicSource = typeof existingEpicMetadata.source === "string" ? existingEpicMetadata.source : undefined;
558
+ if (existingEpic && existingEpicSource === "task-sufficiency-audit") {
326
559
  epicId = existingEpic.id;
327
560
  epicKey = existingEpic.key;
328
561
  }
@@ -371,33 +604,60 @@ export class TaskSufficiencyService {
371
604
  const existingTaskKeys = await this.workspaceRepo.listTaskKeys(params.storyId);
372
605
  const taskKeyGen = createTaskKeyGenerator(params.storyKey, existingTaskKeys);
373
606
  const now = new Date().toISOString();
374
- const taskInserts = params.gapItems.map((gap, index) => {
375
- const titlePrefix = gap.kind === "section" ? "Cover SDS section" : "Materialize SDS folder entry";
376
- const title = `${titlePrefix}: ${gap.value}`.slice(0, 180);
377
- const objective = gap.kind === "section"
378
- ? `Implement or update product code to satisfy the SDS section \"${gap.value}\".`
379
- : `Create/update codebase artifacts required by SDS folder-tree entry \"${gap.value}\".`;
607
+ const taskInserts = params.gapBundles.map((bundle, index) => {
608
+ const target = bundle.values[0] ?? "SDS coverage gap";
609
+ const scopeCount = bundle.values.length;
610
+ const domainLabel = bundle.domain.replace(/[-_]+/g, " ").trim() || "coverage";
611
+ const titlePrefix = bundle.kind === "folder"
612
+ ? "Implement SDS path"
613
+ : bundle.kind === "mixed"
614
+ ? "Implement SDS bundle"
615
+ : "Implement SDS section";
616
+ const title = scopeCount <= 1
617
+ ? `${titlePrefix}: ${target}`.slice(0, 180)
618
+ : `Implement SDS ${domainLabel} coverage bundle (${scopeCount} anchors)`.slice(0, 180);
619
+ const objective = bundle.kind === "folder"
620
+ ? scopeCount <= 1
621
+ ? `Create or update production code under the SDS folder-tree path \`${target}\`.`
622
+ : `Create or update production code for ${scopeCount} related SDS folder-tree paths in the ${domainLabel} domain.`
623
+ : bundle.kind === "mixed"
624
+ ? `Implement a cohesive capability slice covering both SDS sections and folder targets in the ${domainLabel} domain.`
625
+ : scopeCount <= 1
626
+ ? `Implement the missing production functionality described by SDS section \`${target}\`.`
627
+ : `Implement ${scopeCount} related SDS section requirements in the ${domainLabel} domain.`;
628
+ const scopeLines = bundle.values.map((value) => `- ${value}`);
629
+ const anchorLines = bundle.normalizedAnchors.map((anchor) => `- ${anchor}`);
380
630
  const description = [
381
- `## Objective`,
631
+ "## Objective",
382
632
  objective,
383
- ``,
384
- `## Context`,
633
+ "",
634
+ "## Context",
385
635
  `- Generated by task-sufficiency-audit iteration ${params.iteration}.`,
386
- `- Anchor: ${gap.normalizedAnchor}`,
387
- ``,
388
- `## Implementation Plan`,
389
- `- Inspect SDS and current implementation for this anchor.`,
390
- `- Add or update production code and wiring to satisfy the requirement.`,
391
- `- Update impacted docs/contracts if the implementation surface changes.`,
392
- ``,
393
- `## Testing`,
394
- `- Add or update unit/component/integration tests for this anchor.`,
395
- `- Ensure existing regression suites remain green.`,
396
- ``,
397
- `## Definition of Done`,
398
- `- Anchor requirement is fully represented in code.`,
399
- `- Tests covering this scope pass.`,
636
+ `- Coverage domain: ${bundle.domain}`,
637
+ `- Scope kind: ${bundle.kind}`,
638
+ "",
639
+ "## Anchor Scope",
640
+ ...scopeLines,
641
+ "",
642
+ "## Anchor Keys",
643
+ ...anchorLines,
644
+ "",
645
+ "## Implementation Plan",
646
+ "- Phase 1: add or update contracts/interfaces used by this scope.",
647
+ "- Phase 2: implement production logic for each anchor item (no docs-only closure).",
648
+ "- Phase 3: wire dependencies and startup/runtime integration points affected by this scope.",
649
+ "- Keep implementation traceable to anchor keys in commit and test evidence.",
650
+ "",
651
+ "## Testing",
652
+ "- Add or update targeted unit/component/integration/API coverage for all listed anchors.",
653
+ "- Execute the smallest deterministic test scope that proves the behavior.",
654
+ "",
655
+ "## Definition of Done",
656
+ "- All anchor scope items in this bundle are represented in working code.",
657
+ "- Validation evidence exists and maps back to each anchor key.",
400
658
  ].join("\n");
659
+ const storyPointsBase = bundle.kind === "folder" ? 1 : 2;
660
+ const storyPoints = Math.min(8, Math.max(2, storyPointsBase + scopeCount + (bundle.kind === "mixed" ? 1 : 0)));
401
661
  return {
402
662
  projectId: params.project.id,
403
663
  epicId: params.epicId,
@@ -407,14 +667,17 @@ export class TaskSufficiencyService {
407
667
  description,
408
668
  type: "feature",
409
669
  status: "not_started",
410
- storyPoints: 1,
670
+ storyPoints,
411
671
  priority: params.maxPriority + index + 1,
412
672
  metadata: {
413
673
  sufficiencyAudit: {
414
674
  source: "task-sufficiency-audit",
415
- kind: gap.kind,
416
- value: gap.value,
417
- anchor: gap.normalizedAnchor,
675
+ kind: bundle.kind,
676
+ domain: bundle.domain,
677
+ scopeCount,
678
+ values: bundle.values,
679
+ anchor: bundle.normalizedAnchors[0],
680
+ anchors: bundle.normalizedAnchors,
418
681
  iteration: params.iteration,
419
682
  generatedAt: now,
420
683
  },
@@ -482,8 +745,25 @@ export class TaskSufficiencyService {
482
745
  if (sdsDocs.length === 0) {
483
746
  throw new Error("task-sufficiency-audit requires an SDS document but none was found. Add docs/sds.md (or a fuzzy-match SDS doc) and retry.");
484
747
  }
485
- const sectionHeadings = unique(sdsDocs.flatMap((doc) => extractMarkdownHeadings(doc.content, SDS_HEADING_LIMIT))).slice(0, SDS_HEADING_LIMIT);
486
- const folderEntries = unique(sdsDocs.flatMap((doc) => extractFolderEntries(doc.content, SDS_FOLDER_LIMIT))).slice(0, SDS_FOLDER_LIMIT);
748
+ const warnings = [];
749
+ const rawSectionHeadings = unique(sdsDocs.flatMap((doc) => extractMarkdownHeadings(doc.content, SDS_HEADING_LIMIT))).slice(0, SDS_HEADING_LIMIT);
750
+ const rawFolderEntries = unique(sdsDocs.flatMap((doc) => extractFolderEntries(doc.content, SDS_FOLDER_LIMIT))).slice(0, SDS_FOLDER_LIMIT);
751
+ const sectionHeadings = unique(rawSectionHeadings
752
+ .map((heading) => normalizeHeadingCandidate(heading))
753
+ .filter((heading) => headingLooksImplementationRelevant(heading))).slice(0, SDS_HEADING_LIMIT);
754
+ const folderEntries = unique(rawFolderEntries
755
+ .map((entry) => normalizeFolderEntry(entry))
756
+ .filter((entry) => Boolean(entry))
757
+ .filter((entry) => folderEntryLooksRepoRelevant(entry))).slice(0, SDS_FOLDER_LIMIT);
758
+ const skippedHeadingSignals = Math.max(0, rawSectionHeadings.length - sectionHeadings.length);
759
+ const skippedFolderSignals = Math.max(0, rawFolderEntries.length - folderEntries.length);
760
+ if (skippedHeadingSignals > 0 || skippedFolderSignals > 0) {
761
+ warnings.push(`Filtered non-actionable SDS signals (headings=${skippedHeadingSignals}, folders=${skippedFolderSignals}) before remediation.`);
762
+ }
763
+ const noActionableSignals = sectionHeadings.length === 0 && folderEntries.length === 0;
764
+ if (noActionableSignals) {
765
+ warnings.push("No actionable implementation signals detected from SDS headings/folder tree after filtering.");
766
+ }
487
767
  await this.jobService.writeCheckpoint(job.id, {
488
768
  stage: "sds_loaded",
489
769
  timestamp: new Date().toISOString(),
@@ -491,10 +771,16 @@ export class TaskSufficiencyService {
491
771
  docCount: sdsDocs.length,
492
772
  headingSignals: sectionHeadings.length,
493
773
  folderSignals: folderEntries.length,
774
+ rawHeadingSignals: rawSectionHeadings.length,
775
+ rawFolderSignals: rawFolderEntries.length,
776
+ filteredHeadingSignals: skippedHeadingSignals,
777
+ filteredFolderSignals: skippedFolderSignals,
494
778
  docs: sdsDocs.map((doc) => path.relative(request.workspace.workspaceRoot, doc.path)),
495
779
  },
496
780
  });
497
- const warnings = [];
781
+ if (noActionableSignals) {
782
+ throw new Error("task-sufficiency-audit could not derive actionable SDS implementation signals after filtering. Expand SDS implementation headings/folder tree and retry.");
783
+ }
498
784
  const iterations = [];
499
785
  let totalTasksAdded = 0;
500
786
  const totalTasksUpdated = 0;
@@ -529,7 +815,8 @@ export class TaskSufficiencyService {
529
815
  break;
530
816
  }
531
817
  const gapItems = this.buildGapItems(coverage, snapshot.existingAnchors, maxTasksPerIteration);
532
- if (gapItems.length === 0) {
818
+ const gapBundles = this.bundleGapItems(gapItems, maxTasksPerIteration);
819
+ if (gapBundles.length === 0) {
533
820
  warnings.push(`Iteration ${iteration}: unresolved SDS gaps remain but no insertable gap items were identified.`);
534
821
  iterations.push({
535
822
  iteration,
@@ -560,7 +847,11 @@ export class TaskSufficiencyService {
560
847
  missingSectionCount: coverage.missingSectionHeadings.length,
561
848
  missingFolderCount: coverage.missingFolderEntries.length,
562
849
  action: "dry_run",
563
- proposedGapItems: gapItems.map((item) => ({ kind: item.kind, value: item.value })),
850
+ proposedGapItems: gapBundles.map((bundle) => ({
851
+ kind: bundle.kind,
852
+ domain: bundle.domain,
853
+ values: bundle.values,
854
+ })),
564
855
  },
565
856
  });
566
857
  break;
@@ -572,7 +863,7 @@ export class TaskSufficiencyService {
572
863
  storyKey: target.storyKey,
573
864
  epicId: target.epicId,
574
865
  maxPriority: snapshot.maxPriority,
575
- gapItems,
866
+ gapBundles,
576
867
  iteration,
577
868
  jobId: job.id,
578
869
  commandRunId: commandRun.id,
@@ -600,7 +891,7 @@ export class TaskSufficiencyService {
600
891
  addedCount: createdTaskKeys.length,
601
892
  },
602
893
  });
603
- await this.jobService.appendLog(job.id, `Iteration ${iteration}: added ${createdTaskKeys.length} task(s): ${createdTaskKeys.join(", ")}\n`);
894
+ await this.jobService.appendLog(job.id, `Iteration ${iteration}: added ${createdTaskKeys.length} remediation task(s) from ${gapBundles.length} gap bundle(s): ${createdTaskKeys.join(", ")}\n`);
604
895
  }
605
896
  const finalSnapshot = await this.loadProjectSnapshot(request.projectKey);
606
897
  const finalCoverage = this.evaluateCoverage(finalSnapshot.corpus, sectionHeadings, folderEntries, finalSnapshot.existingAnchors);
@@ -615,6 +906,7 @@ export class TaskSufficiencyService {
615
906
  projectKey: request.projectKey,
616
907
  sourceCommand,
617
908
  generatedAt: new Date().toISOString(),
909
+ coverageHeuristicsVersion: COVERAGE_HEURISTICS_VERSION,
618
910
  dryRun,
619
911
  maxIterations,
620
912
  maxTasksPerIteration,
@@ -624,8 +916,15 @@ export class TaskSufficiencyService {
624
916
  totalTasksUpdated,
625
917
  docs: sdsDocs.map((doc) => ({
626
918
  path: path.relative(request.workspace.workspaceRoot, doc.path),
627
- headingSignals: extractMarkdownHeadings(doc.content, SDS_HEADING_LIMIT).length,
628
- folderSignals: extractFolderEntries(doc.content, SDS_FOLDER_LIMIT).length,
919
+ headingSignals: extractMarkdownHeadings(doc.content, SDS_HEADING_LIMIT)
920
+ .map((heading) => normalizeHeadingCandidate(heading))
921
+ .filter((heading) => headingLooksImplementationRelevant(heading)).length,
922
+ folderSignals: extractFolderEntries(doc.content, SDS_FOLDER_LIMIT)
923
+ .map((entry) => normalizeFolderEntry(entry))
924
+ .filter((entry) => Boolean(entry))
925
+ .filter((entry) => folderEntryLooksRepoRelevant(entry)).length,
926
+ rawHeadingSignals: extractMarkdownHeadings(doc.content, SDS_HEADING_LIMIT).length,
927
+ rawFolderSignals: extractFolderEntries(doc.content, SDS_FOLDER_LIMIT).length,
629
928
  })),
630
929
  finalCoverage: {
631
930
  coverageRatio: finalCoverage.coverageRatio,
@@ -1 +1 @@
1
- {"version":3,"file":"CodeReviewService.d.ts","sourceRoot":"","sources":["../../../src/services/review/CodeReviewService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CodeReviewService.d.ts","sourceRoot":"","sources":["../../../src/services/review/CodeReviewService.ts"],"names":[],"mappings":"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"}