@kaddo/mcp 3.67.0 → 3.69.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.
Files changed (2) hide show
  1. package/dist/index.js +287 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -500,6 +500,53 @@ function isCore(config) {
500
500
 
501
501
  // ../cli/src/services/artifact-reader.ts
502
502
  import matter3 from "gray-matter";
503
+ var VALID_SCOPE_CONFIDENCE_LEVELS = /* @__PURE__ */ new Set(["high", "medium", "low"]);
504
+ var VALID_COVERAGE_STATUSES = /* @__PURE__ */ new Set(["affected", "reviewed-not-affected", "unknown", "not-applicable"]);
505
+ function parseScopeConfidence(data) {
506
+ const sc = data.scope_confidence;
507
+ if (!sc || typeof sc !== "object" || Array.isArray(sc)) return null;
508
+ const obj = sc;
509
+ const level = String(obj.level ?? "");
510
+ if (!VALID_SCOPE_CONFIDENCE_LEVELS.has(level)) return null;
511
+ const reasons = Array.isArray(obj.reasons) ? obj.reasons.map(String).filter(Boolean) : [];
512
+ return { level, reasons };
513
+ }
514
+ function parseModuleCoverage(data) {
515
+ const mc = data.module_coverage;
516
+ if (!mc || typeof mc !== "object" || Array.isArray(mc)) return null;
517
+ const result = {};
518
+ for (const [id, val] of Object.entries(mc)) {
519
+ if (!val || typeof val !== "object" || Array.isArray(val)) continue;
520
+ const v = val;
521
+ const status = String(v.status ?? "");
522
+ if (!VALID_COVERAGE_STATUSES.has(status)) continue;
523
+ result[id] = {
524
+ status,
525
+ ...v.reason ? { reason: String(v.reason) } : {},
526
+ ...Array.isArray(v.evidence) ? { evidence: v.evidence.map(String).filter(Boolean) } : {}
527
+ };
528
+ }
529
+ return Object.keys(result).length > 0 ? result : null;
530
+ }
531
+ function parseImpactAnalysis(data) {
532
+ const ia = data.impact_analysis;
533
+ if (!ia || typeof ia !== "object" || Array.isArray(ia)) return null;
534
+ const surfaces = ia.surfaces;
535
+ if (!surfaces || typeof surfaces !== "object" || Array.isArray(surfaces)) return null;
536
+ const result = {};
537
+ for (const [id, val] of Object.entries(surfaces)) {
538
+ if (!val || typeof val !== "object" || Array.isArray(val)) continue;
539
+ const v = val;
540
+ const status = String(v.status ?? "");
541
+ if (!VALID_COVERAGE_STATUSES.has(status)) continue;
542
+ result[id] = {
543
+ status,
544
+ ...v.reason ? { reason: String(v.reason) } : {},
545
+ ...v.question ? { question: String(v.question) } : {}
546
+ };
547
+ }
548
+ return Object.keys(result).length > 0 ? result : null;
549
+ }
503
550
  function parseArtifact(filePath, raw) {
504
551
  try {
505
552
  const { data } = matter3(raw);
@@ -528,7 +575,10 @@ function parseArtifact(filePath, raw) {
528
575
  affectedModules: Array.isArray(data.affected_modules) ? data.affected_modules.map(String).filter(Boolean) : [],
529
576
  refinedBy: String(data.refined_by ?? ""),
530
577
  implementedBy: String(data.implemented_by ?? ""),
531
- closedBy: String(data.closed_by ?? "")
578
+ closedBy: String(data.closed_by ?? ""),
579
+ scopeConfidence: parseScopeConfidence(data),
580
+ moduleCoverage: parseModuleCoverage(data),
581
+ impactAnalysis: parseImpactAnalysis(data)
532
582
  };
533
583
  } catch {
534
584
  return null;
@@ -1105,12 +1155,44 @@ domains: []
1105
1155
  capabilities: []
1106
1156
  code: []
1107
1157
  created_at: YYYY-MM-DD
1158
+ # scope_confidence:
1159
+ # level: medium
1160
+ # reasons: []
1161
+ # module_coverage:
1162
+ # core:
1163
+ # status: affected
1164
+ # reason: ""
1165
+ # impact_analysis:
1166
+ # surfaces:
1167
+ # frontend:
1168
+ # status: affected
1169
+ # reason: ""
1108
1170
  ---
1109
1171
 
1110
1172
  # <Title>
1111
1173
 
1112
1174
  > Type: feature \xB7 Level: K2
1113
1175
 
1176
+ ## Actor and outcome
1177
+
1178
+ _Who experiences the change and what is the observable result?_
1179
+
1180
+ ## Current behavior
1181
+
1182
+ _What happens today?_
1183
+
1184
+ ## Target behavior
1185
+
1186
+ _What should happen after this change?_
1187
+
1188
+ ## Entry points
1189
+
1190
+ _Where does the flow start for the actor?_
1191
+
1192
+ ## End-to-end flow
1193
+
1194
+ _Describe the complete flow from entry point to final result._
1195
+
1114
1196
  ## Problem
1115
1197
 
1116
1198
  _What problem or opportunity does this address?_
@@ -1119,9 +1201,26 @@ _What problem or opportunity does this address?_
1119
1201
 
1120
1202
  _What should be true once this is done?_
1121
1203
 
1204
+ ## Impact analysis
1205
+
1206
+ _Which surfaces are affected, reviewed-not-affected, unknown, or not-applicable?_
1207
+
1208
+ ## Module coverage
1209
+
1210
+ _For multirepo: which modules were evaluated and their status._
1211
+
1212
+ ## Scope unknowns
1213
+
1214
+ _What remains unknown? Include focused questions._
1215
+
1216
+ ## Scope confidence
1217
+
1218
+ _high / medium / low \u2014 with reasons._
1219
+
1122
1220
  ## Acceptance criteria
1123
1221
 
1124
1222
  - [ ] ...
1223
+ - [ ] _Include at least one end-to-end criterion for user-facing changes._
1125
1224
 
1126
1225
  ## Design
1127
1226
 
@@ -1153,6 +1252,9 @@ ${QUALITY}
1153
1252
  - [ ] Title is specific and action-oriented.
1154
1253
  - [ ] \`code:\` globs declared so Guard can relate changes.
1155
1254
  - [ ] Knowledge level matches the real uncertainty.
1255
+ - [ ] Actor and outcome are identified.
1256
+ - [ ] Current and target behavior are documented.
1257
+ - [ ] Scope confidence is declared.
1156
1258
  `;
1157
1259
  var ROADMAP = `---
1158
1260
  type: roadmap
@@ -4559,8 +4661,23 @@ The context pack and the Work Item (draft or candidate).
4559
4661
 
4560
4662
  ## Output
4561
4663
 
4562
- An improved Work Item with: problem, expected result, scope, out of scope, acceptance criteria,
4563
- validation (how to test it), definition of done, open questions and dependencies.
4664
+ An improved Work Item with: actor and outcome, current behavior, target behavior, entry points,
4665
+ end-to-end flow, impact analysis, module coverage, scope unknowns, scope confidence, problem,
4666
+ expected result, scope, out of scope, acceptance criteria (including end-to-end criteria for
4667
+ user-facing changes), validation (how to test it), definition of done, open questions and
4668
+ dependencies.
4669
+
4670
+ ## Steps
4671
+
4672
+ 1. **Outcome framing** \u2014 identify actor, current behavior, target behavior, observable completion.
4673
+ 2. **Journey reconstruction** \u2014 map entry point, interaction, service/API, state change, response,
4674
+ final outcome.
4675
+ 3. **Surface review** \u2014 evaluate: product/UI, frontend, backend, database, configuration, feature
4676
+ flags, content/copy, authentication/authorization, notifications, analytics, documentation,
4677
+ operations/release \u2014 as affected, reviewed-not-affected, unknown, or not-applicable.
4678
+ 4. **Module review** \u2014 for multirepo, evaluate each mapped module with the same statuses.
4679
+ 5. **Completeness review** \u2014 confirm: outcome covered, journey covered, modules assessed, unknowns
4680
+ visible, acceptance criteria end-to-end, scope and out-of-scope coherent.
4564
4681
 
4565
4682
  ## Rules
4566
4683
 
@@ -4568,14 +4685,23 @@ validation (how to test it), definition of done, open questions and dependencies
4568
4685
  - Do not expand scope without explicit confirmation.
4569
4686
  - Do not create mega Work Items \u2014 split when it covers multiple outcomes.
4570
4687
  - Keep acceptance criteria testable.
4688
+ - Include at least one end-to-end acceptance criterion for user-facing changes.
4689
+ - Do not reduce a product intent to the first technical implementation found.
4690
+ - Evaluate surfaces and modules before proposing files.
4571
4691
  - This skill refines scope and acceptance criteria but does not approve implementation readiness.
4572
4692
  Readiness requires human confirmation through \`kaddo ready\` or the MCP \`mark_work_item_ready\` action.
4573
4693
 
4574
4694
  ## Quality checklist
4575
4695
 
4696
+ - Actor and outcome are identified.
4697
+ - Current and target behavior are documented.
4698
+ - Journey is reconstructed for user-facing changes.
4699
+ - Surfaces and modules are evaluated with explicit statuses.
4576
4700
  - Problem and expected result are unambiguous.
4577
4701
  - Scope and out-of-scope are explicit.
4578
- - Acceptance criteria and validation are present and testable.
4702
+ - Acceptance criteria include end-to-end validation when applicable.
4703
+ - Scope unknowns are visible, not hidden.
4704
+ - Scope confidence is declared with reasons.
4579
4705
  - Open questions and dependencies are surfaced, not hidden.
4580
4706
 
4581
4707
  ## Example output
@@ -4796,14 +4922,19 @@ steps, and stop criteria (when to pause and ask).
4796
4922
  ## Rules
4797
4923
 
4798
4924
  - Do not start coding without confirmation.
4799
- - Do not expand scope.
4925
+ - Do not expand scope without updating the Work Item.
4800
4926
  - Never make commits or push \u2014 suggest only.
4927
+ - Review scope coverage before planning: check that expected result, current/target behavior,
4928
+ module coverage, and acceptance criteria are consistent. Flag contradictions (e.g., user-facing
4929
+ change with unassessed frontend module).
4801
4930
 
4802
4931
  ## Quality checklist
4803
4932
 
4933
+ - Pre-implementation scope review is documented.
4804
4934
  - Scope and expected files are explicit.
4805
4935
  - Risks and validations are listed.
4806
4936
  - Stop criteria are defined.
4937
+ - Module coverage aligns with planned changes.
4807
4938
 
4808
4939
  ## Example output
4809
4940
 
@@ -5951,18 +6082,31 @@ A refined Work Item intended to be saved under the lifecycle workspace:
5951
6082
 
5952
6083
  ## Instructions
5953
6084
 
5954
- 1. Restate the problem in one clear sentence.
5955
- 2. Split the candidate if it is too large for a single Work Item.
5956
- 3. Preserve the candidate's type (\`feature\`, \`bugfix\`, \`hotfix\`, \`spike\`, \`chore\`).
5957
- Keep \`chore\` for maintenance/tooling/config/infra work \u2014 never upgrade a chore to a feature.
5958
- 4. Validate the Knowledge Level (K0\u2013K4) and propose a different one if needed.
5959
- 5. Propose acceptance criteria.
5960
- 6. Propose an Out of scope section.
5961
- 7. Propose **how to test it** \u2014 concrete validation steps (commands to run, manual steps, or
5962
- test cases) that prove the change works once implemented. This is mandatory.
5963
- 8. Propose a Definition of Done.
5964
- 9. Identify open questions and assumptions.
5965
- 10. Suggest ownership candidates (code globs) if evident.
6085
+ 1. **Interpret the outcome** \u2014 what must change for the actor or consumer of this change.
6086
+ 2. **Identify the actor** \u2014 who experiences or triggers the change.
6087
+ 3. **Describe current behavior** \u2014 what happens today.
6088
+ 4. **Describe target behavior** \u2014 what should happen after the change.
6089
+ 5. **Reconstruct the journey** \u2014 for user-facing changes, map the end-to-end flow from entry
6090
+ point to final observable result before proposing files.
6091
+ 6. **Evaluate surfaces** \u2014 assess each potentially affected surface (frontend, backend, database,
6092
+ configuration, content, feature flags, authentication, notifications, analytics, documentation,
6093
+ operations) as \`affected\`, \`reviewed-not-affected\`, \`unknown\`, or \`not-applicable\`.
6094
+ 7. **Evaluate modules** \u2014 for multirepo projects, assess each plausibly related mapped module with
6095
+ the same statuses. A module must be \`affected\`, \`reviewed-not-affected\`, \`unknown\`, or
6096
+ \`not-applicable\`. Do not leave related modules unmentioned.
6097
+ 8. Restate the problem in one clear sentence.
6098
+ 9. Split the candidate if it is too large for a single Work Item.
6099
+ 10. Preserve the candidate's type (\`feature\`, \`bugfix\`, \`hotfix\`, \`spike\`, \`chore\`).
6100
+ Keep \`chore\` for maintenance/tooling/config/infra work \u2014 never upgrade a chore to a feature.
6101
+ 11. Validate the Knowledge Level (K0\u2013K4) and propose a different one if needed.
6102
+ 12. Propose acceptance criteria \u2014 include at least one end-to-end criterion for user-facing changes.
6103
+ 13. Propose an Out of scope section.
6104
+ 14. Propose **how to test it** \u2014 concrete validation steps (commands to run, manual steps, or
6105
+ test cases) that prove the change works once implemented. This is mandatory.
6106
+ 15. Propose a Definition of Done.
6107
+ 16. Identify open questions, assumptions, and scope unknowns.
6108
+ 17. Determine scope confidence (high, medium, low) with reasons.
6109
+ 18. Suggest ownership candidates (code globs) if evident.
5966
6110
 
5967
6111
  ## Constraints
5968
6112
 
@@ -5970,19 +6114,49 @@ A refined Work Item intended to be saved under the lifecycle workspace:
5970
6114
  - Do not invent business facts.
5971
6115
  - Do not assign a Knowledge Level higher than the change requires.
5972
6116
  - Mark assumptions explicitly.
6117
+ - Do not reduce a product intent to the first technical implementation found.
6118
+ - Inspect the observable outcome before proposing files.
6119
+ - For user-facing changes, assess the entry point, interaction surface, backend behavior, and
6120
+ final user-visible result.
6121
+ - For multirepo projects, assess each plausibly related mapped module.
6122
+ - Do not mark the Work Item ready while material scope remains unknown.
6123
+ - Ask focused questions instead of silently narrowing the request.
6124
+ - Preserve unsupported assumptions as assumptions.
5973
6125
 
5974
6126
  ## Output Format
5975
6127
 
5976
6128
  \`\`\`markdown
5977
6129
  # <Work Item title>
5978
6130
 
6131
+ **Actor and outcome:**
6132
+
6133
+ **Current behavior:**
6134
+
6135
+ **Target behavior:**
6136
+
6137
+ **Entry points:**
6138
+
6139
+ **End-to-end flow:**
6140
+
5979
6141
  **Problem:**
5980
6142
 
5981
6143
  **Expected result:**
5982
6144
 
5983
6145
  **Suggested Knowledge Level:** K1 / K2 / K3 / K4
5984
6146
 
6147
+ **Impact analysis:**
6148
+ <!-- surfaces: affected / reviewed-not-affected / unknown / not-applicable -->
6149
+
6150
+ **Module coverage:**
6151
+ <!-- for multirepo: each module as affected / reviewed-not-affected / unknown / not-applicable -->
6152
+
6153
+ **Scope unknowns:**
6154
+
6155
+ **Scope confidence:** high / medium / low
6156
+ <!-- reasons: -->
6157
+
5985
6158
  **Acceptance criteria:**
6159
+ <!-- include at least one end-to-end criterion for user-facing changes -->
5986
6160
 
5987
6161
  **Out of scope:**
5988
6162
 
@@ -6719,6 +6893,20 @@ Working code, tests and migrations, plus updated knowledge (ADR / capabilities /
6719
6893
  when the change affects them. You also produce a suggested branch name and a suggested
6720
6894
  Conventional Commit message \u2014 as suggestions, never executed.
6721
6895
 
6896
+ ## Pre-implementation Scope Review (VS-095)
6897
+
6898
+ Before implementing, review the Work Item's scope coverage:
6899
+ - Check that expected result, current behavior, and target behavior are documented.
6900
+ - Verify the journey covers the full user-facing flow when applicable.
6901
+ - Confirm affected surfaces and modules are declared.
6902
+ - Check module_coverage: if a mapped module is plausibly related but not assessed, flag it.
6903
+ - Verify acceptance criteria include end-to-end validation for user-facing changes.
6904
+ - Check for unresolved scope unknowns that could change the implementation.
6905
+
6906
+ If you find a contradiction (e.g., target behavior describes a user-facing registration flow but
6907
+ the mapped frontend module was not assessed), explain the finding, propose updating the Work Item,
6908
+ and wait for confirmation before proceeding. Do not silently expand scope.
6909
+
6722
6910
  ## Instructions
6723
6911
 
6724
6912
  1. **Suggest a branch first** (do not run it). Follow the Git strategy
@@ -8398,6 +8586,16 @@ function buildProjectExplanation(dir) {
8398
8586
  releaseReady: completed.filter((a2) => a2.releaseStatus === "ready" || a2.releaseStatus === "released").length
8399
8587
  };
8400
8588
  })(),
8589
+ scopeCoverage: workItemArtifacts.filter((a2) => a2.scopeConfidence || a2.moduleCoverage || a2.impactAnalysis).map((a2) => {
8590
+ const unknownModules = a2.moduleCoverage ? Object.entries(a2.moduleCoverage).filter(([, v]) => v.status === "unknown").map(([k2]) => k2) : [];
8591
+ return {
8592
+ id: a2.id || a2.title,
8593
+ scopeConfidence: a2.scopeConfidence,
8594
+ moduleCoverage: a2.moduleCoverage,
8595
+ unknownModules,
8596
+ hasScopeCoverage: true
8597
+ };
8598
+ }),
8401
8599
  implementationEvidence: workItemArtifacts.filter((a2) => a2.affectedModules.length > 0).map((a2) => {
8402
8600
  const fm = a2.rawFrontmatter;
8403
8601
  const evidence = fm.implementation_evidence;
@@ -8578,6 +8776,23 @@ function renderExplanationHuman(exp) {
8578
8776
  }
8579
8777
  lines.push("");
8580
8778
  }
8779
+ if (exp.scopeCoverage.length > 0) {
8780
+ lines.push("## Work Item Scope Coverage");
8781
+ for (const sc of exp.scopeCoverage) {
8782
+ lines.push("");
8783
+ lines.push(`### ${sc.id}`);
8784
+ if (sc.scopeConfidence) lines.push(`- Scope confidence: ${sc.scopeConfidence.level}`);
8785
+ if (sc.moduleCoverage) {
8786
+ const affected = Object.entries(sc.moduleCoverage).filter(([, v]) => v.status === "affected").map(([k2]) => k2);
8787
+ const reviewed = Object.entries(sc.moduleCoverage).filter(([, v]) => v.status === "reviewed-not-affected").map(([k2]) => k2);
8788
+ const unknown = Object.entries(sc.moduleCoverage).filter(([, v]) => v.status === "unknown").map(([k2]) => k2);
8789
+ if (affected.length > 0) lines.push(`Affected: ${affected.join(", ")}`);
8790
+ if (reviewed.length > 0) lines.push(`Reviewed, not affected: ${reviewed.join(", ")}`);
8791
+ if (unknown.length > 0) lines.push(`Unknown: ${unknown.join(", ")}`);
8792
+ }
8793
+ }
8794
+ lines.push("");
8795
+ }
8581
8796
  if (exp.domains.length > 0) {
8582
8797
  lines.push("## Domains");
8583
8798
  lines.push(`- ${exp.domains.join(", ")}`);
@@ -9756,6 +9971,49 @@ function firstParagraph2(body) {
9756
9971
  }
9757
9972
  return "";
9758
9973
  }
9974
+ var VALID_COVERAGE_STATUSES2 = /* @__PURE__ */ new Set(["affected", "reviewed-not-affected", "unknown", "not-applicable"]);
9975
+ function parseScopeMeta(data) {
9976
+ const result = {};
9977
+ const sc = data.scope_confidence;
9978
+ if (sc && typeof sc === "object" && !Array.isArray(sc)) {
9979
+ const obj = sc;
9980
+ const level = String(obj.level ?? "");
9981
+ if (["high", "medium", "low"].includes(level)) {
9982
+ result.scope_confidence = { level, reasons: Array.isArray(obj.reasons) ? obj.reasons.map(String) : [] };
9983
+ }
9984
+ }
9985
+ const mc = data.module_coverage;
9986
+ if (mc && typeof mc === "object" && !Array.isArray(mc)) {
9987
+ const parsed = {};
9988
+ const unknowns = [];
9989
+ for (const [id, val] of Object.entries(mc)) {
9990
+ if (!val || typeof val !== "object" || Array.isArray(val)) continue;
9991
+ const v = val;
9992
+ const status = String(v.status ?? "");
9993
+ if (!VALID_COVERAGE_STATUSES2.has(status)) continue;
9994
+ parsed[id] = { status, ...v.reason ? { reason: String(v.reason) } : {} };
9995
+ if (status === "unknown") unknowns.push(id);
9996
+ }
9997
+ if (Object.keys(parsed).length > 0) result.module_coverage = parsed;
9998
+ if (unknowns.length > 0) result.scope_unknowns = unknowns;
9999
+ }
10000
+ const ia = data.impact_analysis;
10001
+ if (ia && typeof ia === "object" && !Array.isArray(ia)) {
10002
+ const surfaces = ia.surfaces;
10003
+ if (surfaces && typeof surfaces === "object" && !Array.isArray(surfaces)) {
10004
+ const parsed = {};
10005
+ for (const [id, val] of Object.entries(surfaces)) {
10006
+ if (!val || typeof val !== "object" || Array.isArray(val)) continue;
10007
+ const v = val;
10008
+ const status = String(v.status ?? "");
10009
+ if (!VALID_COVERAGE_STATUSES2.has(status)) continue;
10010
+ parsed[id] = { status, ...v.reason ? { reason: String(v.reason) } : {} };
10011
+ }
10012
+ if (Object.keys(parsed).length > 0) result.impact_analysis = parsed;
10013
+ }
10014
+ }
10015
+ return result;
10016
+ }
9759
10017
  function listWorkItems(root) {
9760
10018
  const files = listFiles(root, "knowledge/delivery/work-items", ".md");
9761
10019
  const items = [];
@@ -9798,7 +10056,8 @@ function listWorkItems(root) {
9798
10056
  ...data.implemented_by ? { implemented_by: String(data.implemented_by) } : {},
9799
10057
  ...data.closed_by ? { closed_by: String(data.closed_by) } : {},
9800
10058
  ...Array.isArray(data.release_gates) && data.release_gates.length > 0 ? { release_gates: data.release_gates } : {},
9801
- ...Array.isArray(data.completion_exceptions) && data.completion_exceptions.length > 0 ? { completion_exceptions: data.completion_exceptions } : {}
10059
+ ...Array.isArray(data.completion_exceptions) && data.completion_exceptions.length > 0 ? { completion_exceptions: data.completion_exceptions } : {},
10060
+ ...parseScopeMeta(data)
9802
10061
  });
9803
10062
  }
9804
10063
  return items.sort((a2, b2) => a2.id.localeCompare(b2.id));
@@ -10228,6 +10487,9 @@ function projectStatus(root) {
10228
10487
  if (explain.deliverySummary) {
10229
10488
  result.deliverySummary = explain.deliverySummary;
10230
10489
  }
10490
+ if (explain.scopeCoverage && Array.isArray(explain.scopeCoverage) && explain.scopeCoverage.length > 0) {
10491
+ result.scopeCoverage = explain.scopeCoverage;
10492
+ }
10231
10493
  return ok(result);
10232
10494
  }
10233
10495
  function listWorkItemsTool(root, filter = {}) {
@@ -10946,6 +11208,13 @@ function toContextWorkItem(a2) {
10946
11208
  wi.validationStatus = a2.validationStatus || (isHistorical ? "not-assessed" : void 0);
10947
11209
  wi.releaseStatus = a2.releaseStatus || (isHistorical ? "not-assessed" : void 0);
10948
11210
  if (a2.affectedModules.length > 0) wi.affectedModules = a2.affectedModules;
11211
+ if (a2.scopeConfidence) wi.scopeConfidence = a2.scopeConfidence;
11212
+ if (a2.moduleCoverage) wi.moduleCoverage = a2.moduleCoverage;
11213
+ if (a2.impactAnalysis) wi.impactAnalysis = a2.impactAnalysis;
11214
+ if (a2.moduleCoverage) {
11215
+ const unknowns = Object.entries(a2.moduleCoverage).filter(([, v]) => v.status === "unknown").map(([k2]) => k2);
11216
+ if (unknowns.length > 0) wi.scopeUnknowns = unknowns;
11217
+ }
10949
11218
  return wi;
10950
11219
  }
10951
11220
  function toContextArtifact(a2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/mcp",
3
- "version": "3.67.0",
3
+ "version": "3.69.0",
4
4
  "description": "MCP server for Kaddo project knowledge: read-only resources/tools/prompts plus safe derived generation under .kaddo/.",
5
5
  "license": "MIT",
6
6
  "repository": {