@adhisang/minecraft-modding-mcp 4.0.0 → 4.1.1

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 (176) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +40 -23
  3. package/dist/build-suggested-call.d.ts +29 -0
  4. package/dist/build-suggested-call.js +58 -0
  5. package/dist/cache-registry.d.ts +3 -1
  6. package/dist/cache-registry.js +50 -6
  7. package/dist/entry-tools/analyze-symbol-service.d.ts +16 -16
  8. package/dist/entry-tools/batch-class-members-service.d.ts +34 -0
  9. package/dist/entry-tools/batch-class-members-service.js +97 -0
  10. package/dist/entry-tools/batch-class-source-service.d.ts +37 -0
  11. package/dist/entry-tools/batch-class-source-service.js +100 -0
  12. package/dist/entry-tools/batch-mappings-service.d.ts +36 -0
  13. package/dist/entry-tools/batch-mappings-service.js +66 -0
  14. package/dist/entry-tools/batch-runner.d.ts +72 -0
  15. package/dist/entry-tools/batch-runner.js +90 -0
  16. package/dist/entry-tools/batch-symbol-exists-service.d.ts +46 -0
  17. package/dist/entry-tools/batch-symbol-exists-service.js +113 -0
  18. package/dist/entry-tools/compare-minecraft-service.d.ts +6 -6
  19. package/dist/entry-tools/inspect-minecraft/handlers/artifact.d.ts +5 -0
  20. package/dist/entry-tools/inspect-minecraft/handlers/artifact.js +83 -0
  21. package/dist/entry-tools/inspect-minecraft/handlers/class-members.d.ts +6 -0
  22. package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +80 -0
  23. package/dist/entry-tools/inspect-minecraft/handlers/class-overview.d.ts +5 -0
  24. package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +248 -0
  25. package/dist/entry-tools/inspect-minecraft/handlers/class-source.d.ts +5 -0
  26. package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +60 -0
  27. package/dist/entry-tools/inspect-minecraft/handlers/file.d.ts +5 -0
  28. package/dist/entry-tools/inspect-minecraft/handlers/file.js +54 -0
  29. package/dist/entry-tools/inspect-minecraft/handlers/list-files.d.ts +5 -0
  30. package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +100 -0
  31. package/dist/entry-tools/inspect-minecraft/handlers/search.d.ts +5 -0
  32. package/dist/entry-tools/inspect-minecraft/handlers/search.js +155 -0
  33. package/dist/entry-tools/inspect-minecraft/handlers/versions.d.ts +6 -0
  34. package/dist/entry-tools/inspect-minecraft/handlers/versions.js +49 -0
  35. package/dist/entry-tools/inspect-minecraft/internal.d.ts +1042 -0
  36. package/dist/entry-tools/inspect-minecraft/internal.js +448 -0
  37. package/dist/entry-tools/inspect-minecraft-service.d.ts +193 -308
  38. package/dist/entry-tools/inspect-minecraft-service.js +20 -1244
  39. package/dist/entry-tools/manage-cache-service.d.ts +16 -16
  40. package/dist/entry-tools/validate-project/cases/access-transformer.d.ts +6 -0
  41. package/dist/entry-tools/validate-project/cases/access-transformer.js +106 -0
  42. package/dist/entry-tools/validate-project/cases/access-widener.d.ts +6 -0
  43. package/dist/entry-tools/validate-project/cases/access-widener.js +86 -0
  44. package/dist/entry-tools/validate-project/cases/mixin.d.ts +6 -0
  45. package/dist/entry-tools/validate-project/cases/mixin.js +90 -0
  46. package/dist/entry-tools/validate-project/cases/project-summary.d.ts +102 -0
  47. package/dist/entry-tools/validate-project/cases/project-summary.js +415 -0
  48. package/dist/entry-tools/validate-project/internal.d.ts +142 -0
  49. package/dist/entry-tools/validate-project/internal.js +303 -0
  50. package/dist/entry-tools/validate-project-service.d.ts +67 -47
  51. package/dist/entry-tools/validate-project-service.js +13 -563
  52. package/dist/entry-tools/verify-mixin-target-service.d.ts +133 -0
  53. package/dist/entry-tools/verify-mixin-target-service.js +323 -0
  54. package/dist/error-mapping.d.ts +40 -0
  55. package/dist/error-mapping.js +139 -0
  56. package/dist/errors.d.ts +6 -0
  57. package/dist/errors.js +6 -0
  58. package/dist/index.d.ts +2 -0
  59. package/dist/index.js +147 -1354
  60. package/dist/mapping/internal-types.d.ts +54 -0
  61. package/dist/mapping/internal-types.js +14 -0
  62. package/dist/mapping/loaders/mojang.d.ts +2 -0
  63. package/dist/mapping/loaders/mojang.js +64 -0
  64. package/dist/mapping/loaders/tiny-loom.d.ts +2 -0
  65. package/dist/mapping/loaders/tiny-loom.js +73 -0
  66. package/dist/mapping/loaders/tiny-maven.d.ts +2 -0
  67. package/dist/mapping/loaders/tiny-maven.js +104 -0
  68. package/dist/mapping/loaders/types.d.ts +14 -0
  69. package/dist/mapping/loaders/types.js +2 -0
  70. package/dist/mapping/lookup.d.ts +52 -0
  71. package/dist/mapping/lookup.js +496 -0
  72. package/dist/mapping/parsers/normalize.d.ts +10 -0
  73. package/dist/mapping/parsers/normalize.js +52 -0
  74. package/dist/mapping/parsers/proguard.d.ts +20 -0
  75. package/dist/mapping/parsers/proguard.js +138 -0
  76. package/dist/mapping/parsers/symbol-records.d.ts +27 -0
  77. package/dist/mapping/parsers/symbol-records.js +216 -0
  78. package/dist/mapping/parsers/tiny.d.ts +9 -0
  79. package/dist/mapping/parsers/tiny.js +96 -0
  80. package/dist/mapping/types.d.ts +147 -0
  81. package/dist/mapping/types.js +2 -0
  82. package/dist/mapping-pipeline-service.js +3 -2
  83. package/dist/mapping-service.d.ts +8 -145
  84. package/dist/mapping-service.js +30 -1207
  85. package/dist/mixin/access-validators.d.ts +9 -0
  86. package/dist/mixin/access-validators.js +257 -0
  87. package/dist/mixin/annotation-validators.d.ts +5 -0
  88. package/dist/mixin/annotation-validators.js +162 -0
  89. package/dist/mixin/helpers.d.ts +28 -0
  90. package/dist/mixin/helpers.js +315 -0
  91. package/dist/mixin/parsed-validator.d.ts +8 -0
  92. package/dist/mixin/parsed-validator.js +337 -0
  93. package/dist/mixin/types.d.ts +208 -0
  94. package/dist/mixin/types.js +28 -0
  95. package/dist/mixin-validator.d.ts +9 -201
  96. package/dist/mixin-validator.js +8 -1020
  97. package/dist/source/access-validate.d.ts +4 -0
  98. package/dist/source/access-validate.js +254 -0
  99. package/dist/source/artifact-resolver.d.ts +111 -0
  100. package/dist/source/artifact-resolver.js +1271 -0
  101. package/dist/source/cache-metrics.d.ts +26 -0
  102. package/dist/source/cache-metrics.js +172 -0
  103. package/dist/source/class-source/members-builder.d.ts +34 -0
  104. package/dist/source/class-source/members-builder.js +46 -0
  105. package/dist/source/class-source/snippet-builder.d.ts +19 -0
  106. package/dist/source/class-source/snippet-builder.js +46 -0
  107. package/dist/source/class-source-helpers.d.ts +34 -0
  108. package/dist/source/class-source-helpers.js +140 -0
  109. package/dist/source/class-source.d.ts +42 -0
  110. package/dist/source/class-source.js +883 -0
  111. package/dist/source/descriptor-utils.d.ts +6 -0
  112. package/dist/source/descriptor-utils.js +37 -0
  113. package/dist/source/file-access.d.ts +4 -0
  114. package/dist/source/file-access.js +102 -0
  115. package/dist/source/indexer.d.ts +82 -0
  116. package/dist/source/indexer.js +522 -0
  117. package/dist/source/lifecycle/diff-utils.d.ts +9 -0
  118. package/dist/source/lifecycle/diff-utils.js +107 -0
  119. package/dist/source/lifecycle/diff.d.ts +2 -0
  120. package/dist/source/lifecycle/diff.js +265 -0
  121. package/dist/source/lifecycle/mapping-helpers.d.ts +22 -0
  122. package/dist/source/lifecycle/mapping-helpers.js +327 -0
  123. package/dist/source/lifecycle/runtime-check.d.ts +2 -0
  124. package/dist/source/lifecycle/runtime-check.js +142 -0
  125. package/dist/source/lifecycle/trace.d.ts +2 -0
  126. package/dist/source/lifecycle/trace.js +231 -0
  127. package/dist/source/lifecycle.d.ts +4 -0
  128. package/dist/source/lifecycle.js +5 -0
  129. package/dist/source/search.d.ts +51 -0
  130. package/dist/source/search.js +676 -0
  131. package/dist/source/shared-utils.d.ts +6 -0
  132. package/dist/source/shared-utils.js +55 -0
  133. package/dist/source/state.d.ts +26 -0
  134. package/dist/source/state.js +24 -0
  135. package/dist/source/symbol-resolver.d.ts +3 -0
  136. package/dist/source/symbol-resolver.js +212 -0
  137. package/dist/source/validate-mixin/pipeline/mapping-health.d.ts +3 -0
  138. package/dist/source/validate-mixin/pipeline/mapping-health.js +41 -0
  139. package/dist/source/validate-mixin/pipeline/parse.d.ts +2 -0
  140. package/dist/source/validate-mixin/pipeline/parse.js +10 -0
  141. package/dist/source/validate-mixin/pipeline/resolve.d.ts +3 -0
  142. package/dist/source/validate-mixin/pipeline/resolve.js +78 -0
  143. package/dist/source/validate-mixin/pipeline/target-lookup.d.ts +6 -0
  144. package/dist/source/validate-mixin/pipeline/target-lookup.js +260 -0
  145. package/dist/source/validate-mixin/pipeline-context.d.ts +72 -0
  146. package/dist/source/validate-mixin/pipeline-context.js +93 -0
  147. package/dist/source/validate-mixin.d.ts +22 -0
  148. package/dist/source/validate-mixin.js +799 -0
  149. package/dist/source/workspace-target.d.ts +18 -0
  150. package/dist/source/workspace-target.js +305 -0
  151. package/dist/source-resolver.d.ts +1 -0
  152. package/dist/source-resolver.js +1 -1
  153. package/dist/source-service.d.ts +164 -170
  154. package/dist/source-service.js +70 -6116
  155. package/dist/stage-emitter.d.ts +13 -0
  156. package/dist/stage-emitter.js +30 -0
  157. package/dist/stdio-supervisor.d.ts +61 -0
  158. package/dist/stdio-supervisor.js +326 -9
  159. package/dist/tool-contract-manifest.d.ts +1 -1
  160. package/dist/tool-contract-manifest.js +23 -6
  161. package/dist/tool-guidance.d.ts +82 -0
  162. package/dist/tool-guidance.js +734 -0
  163. package/dist/tool-schema-registry.d.ts +16 -0
  164. package/dist/tool-schema-registry.js +37 -0
  165. package/dist/tool-schemas.d.ts +3518 -0
  166. package/dist/tool-schemas.js +813 -0
  167. package/dist/types.d.ts +36 -0
  168. package/dist/version-service.js +7 -6
  169. package/dist/workspace-context-cache.d.ts +32 -0
  170. package/dist/workspace-context-cache.js +66 -0
  171. package/dist/workspace-mapping-service.d.ts +16 -0
  172. package/dist/workspace-mapping-service.js +173 -1
  173. package/docs/README-ja.md +416 -0
  174. package/docs/examples.md +483 -0
  175. package/docs/tool-reference.md +462 -0
  176. package/package.json +17 -4
@@ -0,0 +1,415 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { buildEntryToolResult, createSummarySubject } from "../../response-contract.js";
3
+ import { ERROR_CODES, createError } from "../../../errors.js";
4
+ import { buildEarlyTasksForBlocked, buildFullTaskStatusReport } from "../internal.js";
5
+ // Telemetry failures must not change validation outcomes; swallow rejections
6
+ // so a broken emitter does not abort the summary or count as a validation error.
7
+ async function safeEmit(emitter, stage, payload) {
8
+ if (!emitter)
9
+ return;
10
+ try {
11
+ await emitter(stage, payload);
12
+ }
13
+ catch {
14
+ // swallow telemetry failure
15
+ }
16
+ }
17
+ export async function handleProjectSummary(deps, input, detail, include, options = {}) {
18
+ // Forwarded emitter for nested validators and probes; same swallow contract
19
+ // as safeEmit so a rejecting raw emitter cannot leak into their outcomes.
20
+ const wrappedEmitter = options.stageEmitter
21
+ ? (stage, meta) => safeEmit(options.stageEmitter, stage, meta)
22
+ : undefined;
23
+ if (input.subject.kind !== "workspace") {
24
+ throw createError({
25
+ code: ERROR_CODES.INVALID_INPUT,
26
+ message: "task=project-summary requires subject.kind=workspace."
27
+ });
28
+ }
29
+ if (!input.version && !input.preferProjectVersion) {
30
+ const baseResult = buildEntryToolResult({
31
+ task: "project-summary",
32
+ detail,
33
+ include,
34
+ summary: {
35
+ status: "blocked",
36
+ headline: "project-summary requires version or preferProjectVersion=true.",
37
+ subject: createSummarySubject({
38
+ task: "project-summary",
39
+ kind: input.subject.kind,
40
+ projectPath: input.subject.projectPath,
41
+ discover: input.subject.discover
42
+ }),
43
+ nextActions: [
44
+ {
45
+ tool: "validate-project",
46
+ params: {
47
+ task: "project-summary",
48
+ subject: input.subject
49
+ }
50
+ }
51
+ ],
52
+ notes: [
53
+ "Pass version explicitly, or retry with preferProjectVersion=true when gradle.properties declares the Minecraft version."
54
+ ]
55
+ },
56
+ blocks: {
57
+ workspace: {
58
+ projectPath: input.subject.projectPath
59
+ }
60
+ }
61
+ });
62
+ await safeEmit(options.stageEmitter, "validate-project:task-report", {
63
+ projectPath: input.subject.projectPath,
64
+ reason: "missing-version"
65
+ });
66
+ const tasks = await buildEarlyTasksForBlocked(input.subject.projectPath, detail, include);
67
+ return {
68
+ ...baseResult,
69
+ ...(tasks ? { tasks } : {}),
70
+ warnings: []
71
+ };
72
+ }
73
+ const projectPath = input.subject.projectPath;
74
+ const discover = input.subject.discover ?? ["mixins", "access-wideners"];
75
+ await safeEmit(options.stageEmitter, "validate-project:workspace-discovery", {
76
+ projectPath,
77
+ discover
78
+ });
79
+ const detectedProjectVersion = input.preferProjectVersion
80
+ ? await deps.detectProjectMinecraftVersion?.(projectPath)
81
+ : undefined;
82
+ const resolvedVersion = detectedProjectVersion ?? input.version;
83
+ const [mixinConfigs, accessWideners, accessTransformers] = await Promise.all([
84
+ discover.includes("mixins")
85
+ ? deps.discoverMixins(projectPath, input.configPaths)
86
+ : Promise.resolve([]),
87
+ discover.includes("access-wideners")
88
+ ? deps.discoverAccessWideners(projectPath)
89
+ : Promise.resolve([]),
90
+ discover.includes("access-transformers")
91
+ ? deps.discoverAccessTransformers?.(projectPath) ?? Promise.resolve([])
92
+ : Promise.resolve([])
93
+ ]);
94
+ if (!resolvedVersion && (mixinConfigs.length > 0 || accessWideners.length > 0 || accessTransformers.length > 0)) {
95
+ const baseResult = buildEntryToolResult({
96
+ task: "project-summary",
97
+ detail,
98
+ include,
99
+ summary: {
100
+ status: "blocked",
101
+ headline: "Could not resolve Minecraft version for discovered workspace validators.",
102
+ subject: createSummarySubject({
103
+ task: "project-summary",
104
+ kind: input.subject.kind,
105
+ projectPath,
106
+ discover: input.subject.discover,
107
+ mapping: input.mapping,
108
+ sourcePriority: input.sourcePriority,
109
+ scope: input.scope
110
+ }),
111
+ nextActions: [
112
+ {
113
+ tool: "validate-project",
114
+ params: {
115
+ task: "project-summary",
116
+ subject: input.subject
117
+ }
118
+ }
119
+ ],
120
+ notes: [
121
+ "Pass version explicitly, or make sure gradle.properties declares the Minecraft version before using preferProjectVersion=true."
122
+ ]
123
+ },
124
+ blocks: {
125
+ workspace: {
126
+ projectPath
127
+ }
128
+ }
129
+ });
130
+ await safeEmit(options.stageEmitter, "validate-project:task-report", {
131
+ projectPath,
132
+ reason: "version-unresolved",
133
+ mixinDiscoveryCount: mixinConfigs.length,
134
+ awDiscoveryCount: accessWideners.length,
135
+ atDiscoveryCount: accessTransformers.length
136
+ });
137
+ const tasks = await buildEarlyTasksForBlocked(projectPath, detail, include, {
138
+ mixinDiscoveryCount: mixinConfigs.length,
139
+ awDiscoveryCount: accessWideners.length,
140
+ atDiscoveryCount: accessTransformers.length
141
+ });
142
+ return {
143
+ ...baseResult,
144
+ ...(tasks ? { tasks } : {}),
145
+ warnings: [
146
+ "Could not resolve Minecraft version from gradle.properties for discovered workspace validators."
147
+ ]
148
+ };
149
+ }
150
+ if (!resolvedVersion) {
151
+ const baseResult = buildEntryToolResult({
152
+ task: "project-summary",
153
+ detail,
154
+ include,
155
+ summary: {
156
+ status: "ok",
157
+ headline: `Validated ${mixinConfigs.length} mixin config(s), ${accessWideners.length} access widener(s), and ${accessTransformers.length} access transformer(s).`,
158
+ subject: createSummarySubject({
159
+ task: "project-summary",
160
+ kind: input.subject.kind,
161
+ projectPath,
162
+ discover: input.subject.discover,
163
+ mapping: input.mapping,
164
+ sourcePriority: input.sourcePriority,
165
+ scope: input.scope
166
+ }),
167
+ counts: {
168
+ valid: 0,
169
+ partial: 0,
170
+ invalid: 0
171
+ }
172
+ },
173
+ blocks: {
174
+ workspace: {
175
+ projectPath
176
+ }
177
+ }
178
+ });
179
+ await safeEmit(options.stageEmitter, "validate-project:task-report", {
180
+ projectPath,
181
+ reason: "version-not-required"
182
+ });
183
+ const tasks = await buildEarlyTasksForBlocked(projectPath, detail, include);
184
+ return {
185
+ ...baseResult,
186
+ ...(tasks ? { tasks } : {}),
187
+ warnings: []
188
+ };
189
+ }
190
+ const validationVersion = resolvedVersion;
191
+ const warnings = [];
192
+ const mixinDurationStart = Date.now();
193
+ let validMixins = 0;
194
+ let partialMixins = 0;
195
+ let invalidMixins = 0;
196
+ let mixinCaughtErrors = 0;
197
+ await safeEmit(options.stageEmitter, "validate-project:mixin-validation", {
198
+ targetTotal: mixinConfigs.length
199
+ });
200
+ for (const [mixinIndex, configPath] of mixinConfigs.entries()) {
201
+ try {
202
+ await safeEmit(options.stageEmitter, "validate-project:mixin-validation", {
203
+ targetIndex: mixinIndex + 1,
204
+ targetTotal: mixinConfigs.length,
205
+ configPath
206
+ });
207
+ const mixinResult = await deps.validateMixin({
208
+ input: {
209
+ mode: "config",
210
+ configPaths: [configPath]
211
+ },
212
+ version: validationVersion,
213
+ mapping: input.mapping,
214
+ sourcePriority: input.sourcePriority,
215
+ scope: input.scope,
216
+ projectPath,
217
+ preferProjectVersion: false,
218
+ preferProjectMapping: input.preferProjectMapping,
219
+ sourceRoots: input.sourceRoots,
220
+ minSeverity: input.minSeverity,
221
+ hideUncertain: input.hideUncertain,
222
+ explain: input.explain,
223
+ warningMode: input.warningMode,
224
+ warningCategoryFilter: input.warningCategoryFilter,
225
+ treatInfoAsWarning: input.treatInfoAsWarning,
226
+ includeIssues: input.includeIssues
227
+ }, {
228
+ stageEmitter: wrappedEmitter
229
+ });
230
+ const summary = mixinResult.summary;
231
+ validMixins += summary?.valid ?? 0;
232
+ partialMixins += summary?.partial ?? 0;
233
+ invalidMixins += summary?.invalid ?? 0;
234
+ if (Array.isArray(mixinResult.warnings)) {
235
+ warnings.push(...mixinResult.warnings);
236
+ }
237
+ }
238
+ catch (error) {
239
+ invalidMixins += 1;
240
+ mixinCaughtErrors += 1;
241
+ if (error instanceof Error) {
242
+ warnings.push(`${configPath}: ${error.message}`);
243
+ }
244
+ }
245
+ }
246
+ const mixinDurationMs = Date.now() - mixinDurationStart;
247
+ const awDurationStart = Date.now();
248
+ let validAw = 0;
249
+ let invalidAw = 0;
250
+ let awCaughtErrors = 0;
251
+ await safeEmit(options.stageEmitter, "validate-project:access-widener-validation", {
252
+ targetTotal: accessWideners.length
253
+ });
254
+ for (const [awIndex, awPath] of accessWideners.entries()) {
255
+ try {
256
+ await safeEmit(options.stageEmitter, "validate-project:access-widener-validation", {
257
+ targetIndex: awIndex + 1,
258
+ targetTotal: accessWideners.length,
259
+ filePath: awPath
260
+ });
261
+ const output = await deps.validateAccessWidener({
262
+ content: await readFile(awPath, "utf8"),
263
+ version: validationVersion,
264
+ mapping: input.mapping,
265
+ sourcePriority: input.sourcePriority,
266
+ projectPath,
267
+ scope: input.scope,
268
+ preferProjectVersion: input.preferProjectVersion
269
+ });
270
+ if (output.valid) {
271
+ validAw += 1;
272
+ }
273
+ else {
274
+ invalidAw += 1;
275
+ }
276
+ if (Array.isArray(output.warnings)) {
277
+ warnings.push(...output.warnings);
278
+ }
279
+ }
280
+ catch (error) {
281
+ invalidAw += 1;
282
+ awCaughtErrors += 1;
283
+ if (error instanceof Error) {
284
+ warnings.push(error.message);
285
+ }
286
+ }
287
+ }
288
+ const awDurationMs = Date.now() - awDurationStart;
289
+ const atDurationStart = Date.now();
290
+ let validAt = 0;
291
+ let invalidAt = 0;
292
+ let atCaughtErrors = 0;
293
+ await safeEmit(options.stageEmitter, "validate-project:access-transformer-validation", {
294
+ targetTotal: accessTransformers.length
295
+ });
296
+ for (const [atIndex, atPath] of accessTransformers.entries()) {
297
+ try {
298
+ await safeEmit(options.stageEmitter, "validate-project:access-transformer-validation", {
299
+ targetIndex: atIndex + 1,
300
+ targetTotal: accessTransformers.length,
301
+ filePath: atPath
302
+ });
303
+ if (!deps.validateAccessTransformer) {
304
+ throw createError({
305
+ code: ERROR_CODES.CONTEXT_UNRESOLVED,
306
+ message: "Access Transformer validation is not configured."
307
+ });
308
+ }
309
+ const output = await deps.validateAccessTransformer({
310
+ content: await readFile(atPath, "utf8"),
311
+ version: validationVersion,
312
+ atNamespace: input.atNamespace,
313
+ sourcePriority: input.sourcePriority,
314
+ projectPath,
315
+ scope: input.scope,
316
+ preferProjectVersion: input.preferProjectVersion
317
+ });
318
+ if (output.valid) {
319
+ validAt += 1;
320
+ }
321
+ else {
322
+ invalidAt += 1;
323
+ }
324
+ if (Array.isArray(output.warnings)) {
325
+ warnings.push(...output.warnings);
326
+ }
327
+ }
328
+ catch (error) {
329
+ invalidAt += 1;
330
+ atCaughtErrors += 1;
331
+ if (error instanceof Error) {
332
+ warnings.push(error.message);
333
+ }
334
+ }
335
+ }
336
+ const atDurationMs = Date.now() - atDurationStart;
337
+ const invalidCount = invalidMixins + invalidAw + invalidAt;
338
+ const partialCount = partialMixins;
339
+ const status = invalidCount > 0 ? "invalid" : partialCount > 0 ? "partial" : "ok";
340
+ const baseResult = buildEntryToolResult({
341
+ task: "project-summary",
342
+ detail,
343
+ include,
344
+ summary: {
345
+ status,
346
+ headline: `Validated ${mixinConfigs.length} mixin config(s), ${accessWideners.length} access widener(s), and ${accessTransformers.length} access transformer(s).`,
347
+ subject: createSummarySubject({
348
+ task: "project-summary",
349
+ kind: input.subject.kind,
350
+ projectPath,
351
+ discover: input.subject.discover,
352
+ version: resolvedVersion,
353
+ mapping: input.mapping,
354
+ sourcePriority: input.sourcePriority,
355
+ scope: input.scope
356
+ }),
357
+ counts: {
358
+ valid: validMixins + validAw + validAt,
359
+ partial: partialCount,
360
+ invalid: invalidCount
361
+ }
362
+ },
363
+ blocks: {
364
+ project: {
365
+ summary: {
366
+ valid: validMixins + validAw + validAt,
367
+ partial: partialCount,
368
+ invalid: invalidCount
369
+ }
370
+ },
371
+ workspace: {
372
+ projectPath,
373
+ mixinConfigs,
374
+ accessWideners,
375
+ accessTransformers
376
+ }
377
+ },
378
+ alwaysBlocks: ["project"]
379
+ });
380
+ await safeEmit(options.stageEmitter, "validate-project:task-report", {
381
+ projectPath,
382
+ mixinDiscoveryCount: mixinConfigs.length,
383
+ awDiscoveryCount: accessWideners.length,
384
+ atDiscoveryCount: accessTransformers.length
385
+ });
386
+ const tasks = await buildFullTaskStatusReport(deps, {
387
+ projectPath,
388
+ detail,
389
+ include,
390
+ resolvedVersion: validationVersion,
391
+ mapping: input.mapping,
392
+ sourcePriority: input.sourcePriority,
393
+ scope: input.scope,
394
+ preferProjectVersion: input.preferProjectVersion,
395
+ mixinDiscoveryCount: mixinConfigs.length,
396
+ mixinCaughtErrors,
397
+ mixinCounts: { ok: validMixins, partial: partialMixins, invalid: invalidMixins },
398
+ mixinDurationMs,
399
+ awDiscoveryCount: accessWideners.length,
400
+ awCaughtErrors,
401
+ awCounts: { ok: validAw, invalid: invalidAw },
402
+ awDurationMs,
403
+ atDiscoveryCount: accessTransformers.length,
404
+ atCaughtErrors,
405
+ atCounts: { ok: validAt, invalid: invalidAt },
406
+ atDurationMs,
407
+ stageEmitter: wrappedEmitter
408
+ });
409
+ return {
410
+ ...baseResult,
411
+ ...(tasks ? { tasks } : {}),
412
+ warnings
413
+ };
414
+ }
415
+ //# sourceMappingURL=project-summary.js.map
@@ -0,0 +1,142 @@
1
+ import type { StageEmitter } from "../../stage-emitter.js";
2
+ import type { SourceMapping } from "../../types.js";
3
+ type TaskStatus = "ok" | "skipped" | "missing" | "error";
4
+ type TaskEntryBase = {
5
+ status: TaskStatus;
6
+ durationMs?: number;
7
+ error?: {
8
+ code: string;
9
+ detail: string;
10
+ };
11
+ warnings?: string[];
12
+ };
13
+ type TaskStatusReport = {
14
+ "workspace.detected": TaskEntryBase & {
15
+ evidence?: string[];
16
+ };
17
+ "gradle.readable": TaskEntryBase & {
18
+ propertiesPath?: string;
19
+ buildScripts?: string[];
20
+ };
21
+ "loom.cache.found": TaskEntryBase & {
22
+ cachePath?: string;
23
+ };
24
+ "minecraft.artifact.resolved": TaskEntryBase & {
25
+ artifactId?: string;
26
+ mapping?: SourceMapping;
27
+ };
28
+ "mixins.validated": TaskEntryBase & {
29
+ counts?: {
30
+ ok: number;
31
+ partial: number;
32
+ invalid: number;
33
+ };
34
+ };
35
+ "accessWideners.validated": TaskEntryBase & {
36
+ counts?: {
37
+ ok: number;
38
+ invalid: number;
39
+ };
40
+ };
41
+ "accessTransformers.validated": TaskEntryBase & {
42
+ counts?: {
43
+ ok: number;
44
+ invalid: number;
45
+ };
46
+ };
47
+ };
48
+ type MinecraftArtifactProbeInput = {
49
+ target: {
50
+ kind: "version";
51
+ value: string;
52
+ };
53
+ mapping?: "obfuscated" | "mojang" | "intermediary" | "yarn";
54
+ sourcePriority?: "loom-first" | "maven-first";
55
+ projectPath?: string;
56
+ scope?: "vanilla" | "merged" | "loader";
57
+ preferProjectVersion?: boolean;
58
+ };
59
+ type MinecraftArtifactProbeOutput = {
60
+ artifactId: string;
61
+ mappingApplied: SourceMapping;
62
+ warnings?: string[];
63
+ };
64
+ export type ValidateProjectDeps = {
65
+ validateMixin: (input: Record<string, unknown>, options?: {
66
+ stageEmitter?: StageEmitter;
67
+ }) => Promise<Record<string, unknown> & {
68
+ warnings?: string[];
69
+ }>;
70
+ validateAccessWidener: (input: {
71
+ content: string;
72
+ version: string;
73
+ mapping?: "obfuscated" | "mojang" | "intermediary" | "yarn";
74
+ sourcePriority?: "loom-first" | "maven-first";
75
+ projectPath?: string;
76
+ scope?: "vanilla" | "merged" | "loader";
77
+ preferProjectVersion?: boolean;
78
+ }) => Promise<Record<string, unknown> & {
79
+ warnings?: string[];
80
+ }>;
81
+ validateAccessTransformer?: (input: {
82
+ content: string;
83
+ version: string;
84
+ atNamespace?: "srg" | "mojang" | "obfuscated";
85
+ sourcePriority?: "loom-first" | "maven-first";
86
+ projectPath?: string;
87
+ scope?: "vanilla" | "merged" | "loader";
88
+ preferProjectVersion?: boolean;
89
+ }) => Promise<Record<string, unknown> & {
90
+ warnings?: string[];
91
+ }>;
92
+ discoverMixins: (projectPath: string, configPaths?: string[]) => Promise<string[]>;
93
+ discoverAccessWideners: (projectPath: string) => Promise<string[]>;
94
+ discoverAccessTransformers?: (projectPath: string) => Promise<string[]>;
95
+ detectProjectMinecraftVersion?: (projectPath: string) => Promise<string | undefined>;
96
+ probeMinecraftArtifact?: (input: MinecraftArtifactProbeInput) => Promise<MinecraftArtifactProbeOutput>;
97
+ resolveArtifact?: (input: MinecraftArtifactProbeInput) => Promise<MinecraftArtifactProbeOutput>;
98
+ };
99
+ export declare function runUpstreamProbes(projectPath: string): Promise<{
100
+ workspace: TaskStatusReport["workspace.detected"];
101
+ gradle: TaskStatusReport["gradle.readable"];
102
+ loom: TaskStatusReport["loom.cache.found"];
103
+ }>;
104
+ export declare function buildEarlyTasksForBlocked(projectPath: string, detail: "summary" | "standard" | "full", include: string[], discovery?: {
105
+ mixinDiscoveryCount: number;
106
+ awDiscoveryCount: number;
107
+ atDiscoveryCount: number;
108
+ }): Promise<TaskStatusReport | undefined>;
109
+ export declare function buildFullTaskStatusReport(deps: ValidateProjectDeps, args: {
110
+ projectPath: string;
111
+ detail: "summary" | "standard" | "full";
112
+ include: string[];
113
+ resolvedVersion: string;
114
+ mapping?: "obfuscated" | "mojang" | "intermediary" | "yarn";
115
+ sourcePriority?: "loom-first" | "maven-first";
116
+ scope?: "vanilla" | "merged" | "loader";
117
+ preferProjectVersion?: boolean;
118
+ mixinDiscoveryCount: number;
119
+ mixinCaughtErrors: number;
120
+ mixinCounts: {
121
+ ok: number;
122
+ partial: number;
123
+ invalid: number;
124
+ };
125
+ mixinDurationMs: number;
126
+ awDiscoveryCount: number;
127
+ awCaughtErrors: number;
128
+ awCounts: {
129
+ ok: number;
130
+ invalid: number;
131
+ };
132
+ awDurationMs: number;
133
+ atDiscoveryCount: number;
134
+ atCaughtErrors: number;
135
+ atCounts: {
136
+ ok: number;
137
+ invalid: number;
138
+ };
139
+ atDurationMs: number;
140
+ stageEmitter?: StageEmitter;
141
+ }): Promise<TaskStatusReport | undefined>;
142
+ export {};