@yinuo-ngm/mcp-server 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +191 -208
  2. package/lib/audit/audit-event.d.ts +14 -0
  3. package/lib/audit/audit-event.js +2 -0
  4. package/lib/audit/audit-log.service.d.ts +7 -0
  5. package/lib/audit/audit-log.service.js +187 -0
  6. package/lib/audit/redact.d.ts +3 -0
  7. package/lib/audit/redact.js +28 -0
  8. package/lib/catalog/capabilities/blocked-local-actions.d.ts +1 -0
  9. package/lib/catalog/capabilities/blocked-local-actions.js +18 -0
  10. package/lib/catalog/capabilities/frontend-standard.d.ts +2 -0
  11. package/lib/catalog/capabilities/frontend-standard.js +36 -0
  12. package/lib/catalog/capabilities/hub-v2.d.ts +2 -0
  13. package/lib/catalog/capabilities/hub-v2.js +34 -0
  14. package/lib/catalog/capabilities/nginx.d.ts +2 -0
  15. package/lib/catalog/capabilities/nginx.js +23 -0
  16. package/lib/catalog/capabilities/project.d.ts +2 -0
  17. package/lib/catalog/capabilities/project.js +23 -0
  18. package/lib/catalog/capabilities/router.d.ts +2 -0
  19. package/lib/catalog/capabilities/router.js +11 -0
  20. package/lib/catalog/capabilities/runtime.d.ts +2 -0
  21. package/lib/catalog/capabilities/runtime.js +17 -0
  22. package/lib/catalog/capabilities/workspace.d.ts +2 -0
  23. package/lib/catalog/capabilities/workspace.js +23 -0
  24. package/lib/catalog/helpers.d.ts +3 -0
  25. package/lib/catalog/helpers.js +42 -0
  26. package/lib/catalog/index.d.ts +4 -0
  27. package/lib/catalog/index.js +23 -0
  28. package/lib/catalog/tools/frontend-standard.d.ts +2 -0
  29. package/lib/catalog/tools/frontend-standard.js +166 -0
  30. package/lib/catalog/tools/hub-v2-api.d.ts +2 -0
  31. package/lib/catalog/tools/hub-v2-api.js +124 -0
  32. package/lib/catalog/tools/hub-v2-docs.d.ts +2 -0
  33. package/lib/catalog/tools/hub-v2-docs.js +40 -0
  34. package/lib/catalog/tools/nginx.d.ts +2 -0
  35. package/lib/catalog/tools/nginx.js +82 -0
  36. package/lib/catalog/tools/project.d.ts +2 -0
  37. package/lib/catalog/tools/project.js +124 -0
  38. package/lib/catalog/tools/router.d.ts +2 -0
  39. package/lib/catalog/tools/router.js +26 -0
  40. package/lib/catalog/tools/runtime.d.ts +2 -0
  41. package/lib/catalog/tools/runtime.js +40 -0
  42. package/lib/catalog/tools/workspace.d.ts +2 -0
  43. package/lib/catalog/tools/workspace.js +75 -0
  44. package/lib/catalog/types.d.ts +15 -0
  45. package/lib/catalog/types.js +2 -0
  46. package/lib/context/create-tool-context.js +11 -10
  47. package/lib/context/local-server-client.d.ts +2 -0
  48. package/lib/context/local-server-client.js +174 -0
  49. package/lib/context/tool-context.d.ts +36 -0
  50. package/lib/doctor.d.ts +8 -0
  51. package/lib/doctor.js +194 -0
  52. package/lib/errors/error-codes.d.ts +12 -0
  53. package/lib/errors/error-codes.js +14 -0
  54. package/lib/errors/mcp-tool-error.d.ts +8 -0
  55. package/lib/errors/mcp-tool-error.js +14 -0
  56. package/lib/filesystem/project-files.d.ts +18 -0
  57. package/lib/filesystem/project-files.js +112 -0
  58. package/lib/git/local-git-read-service.d.ts +2 -0
  59. package/lib/git/local-git-read-service.js +96 -0
  60. package/lib/index.d.ts +1 -0
  61. package/lib/index.js +4 -0
  62. package/lib/policy/assert-tool-policy.js +10 -1
  63. package/lib/register-tools.js +67 -10
  64. package/lib/registry/tool-names.d.ts +95 -0
  65. package/lib/registry/tool-names.js +97 -0
  66. package/lib/services/path-guard.service.d.ts +4 -0
  67. package/lib/services/path-guard.service.js +75 -0
  68. package/lib/services/permission.service.d.ts +5 -0
  69. package/lib/services/permission.service.js +38 -0
  70. package/lib/services/project-resolver.service.d.ts +32 -0
  71. package/lib/services/project-resolver.service.js +95 -0
  72. package/lib/standard/frontend-standard.default.d.ts +2 -0
  73. package/lib/standard/frontend-standard.default.js +51 -0
  74. package/lib/standard/frontend-standard.schema.d.ts +196 -0
  75. package/lib/standard/frontend-standard.schema.js +61 -0
  76. package/lib/standard/frontend-standard.service.d.ts +79 -0
  77. package/lib/standard/frontend-standard.service.js +115 -0
  78. package/lib/standard/project-scan.d.ts +9 -0
  79. package/lib/standard/project-scan.js +91 -0
  80. package/lib/standard/validators/angular-structure.validator.d.ts +4 -0
  81. package/lib/standard/validators/angular-structure.validator.js +75 -0
  82. package/lib/standard/validators/component.validator.d.ts +4 -0
  83. package/lib/standard/validators/component.validator.js +94 -0
  84. package/lib/standard/validators/git.validator.d.ts +8 -0
  85. package/lib/standard/validators/git.validator.js +32 -0
  86. package/lib/standard/validators/review.validator.d.ts +15 -0
  87. package/lib/standard/validators/review.validator.js +67 -0
  88. package/lib/standard/validators/test.validator.d.ts +19 -0
  89. package/lib/standard/validators/test.validator.js +89 -0
  90. package/lib/tool-catalog.d.ts +2 -0
  91. package/lib/tool-catalog.js +6 -0
  92. package/lib/tools/angular/angular-standard.tools.d.ts +2 -0
  93. package/lib/tools/angular/angular-standard.tools.js +53 -0
  94. package/lib/tools/angular/index.d.ts +1 -0
  95. package/lib/tools/angular/index.js +5 -0
  96. package/lib/tools/capability.tools.d.ts +2 -0
  97. package/lib/tools/capability.tools.js +205 -0
  98. package/lib/tools/controlled/index.d.ts +2 -0
  99. package/lib/tools/controlled/index.js +13 -0
  100. package/lib/tools/controlled/local-server.d.ts +6 -0
  101. package/lib/tools/controlled/local-server.js +17 -0
  102. package/lib/tools/controlled/operation-policy.d.ts +22 -0
  103. package/lib/tools/controlled/operation-policy.js +50 -0
  104. package/lib/tools/controlled/operation-result.d.ts +30 -0
  105. package/lib/tools/controlled/operation-result.js +33 -0
  106. package/lib/tools/controlled/schemas.d.ts +159 -0
  107. package/lib/tools/controlled/schemas.js +49 -0
  108. package/lib/tools/controlled.tools.d.ts +1 -0
  109. package/lib/tools/controlled.tools.js +5 -0
  110. package/lib/tools/file-write.tools.d.ts +2 -0
  111. package/lib/tools/file-write.tools.js +70 -0
  112. package/lib/tools/git.tools.js +109 -8
  113. package/lib/tools/hub-v2/client.d.ts +6 -1
  114. package/lib/tools/hub-v2/client.js +15 -0
  115. package/lib/tools/hub-v2/config/config-paths.d.ts +2 -0
  116. package/lib/tools/hub-v2/config/config-paths.js +17 -0
  117. package/lib/tools/hub-v2/config/env.d.ts +1 -0
  118. package/lib/tools/hub-v2/config/env.js +12 -0
  119. package/lib/tools/hub-v2/config/index.d.ts +8 -0
  120. package/lib/tools/hub-v2/config/index.js +18 -0
  121. package/lib/tools/hub-v2/config/jsonc.d.ts +5 -0
  122. package/lib/tools/hub-v2/config/jsonc.js +86 -0
  123. package/lib/tools/hub-v2/config/load-config.d.ts +18 -0
  124. package/lib/tools/hub-v2/config/load-config.js +93 -0
  125. package/lib/tools/hub-v2/config/project-selector.d.ts +5 -0
  126. package/lib/tools/hub-v2/config/project-selector.js +92 -0
  127. package/lib/tools/hub-v2/config/resolve-context.d.ts +13 -0
  128. package/lib/tools/hub-v2/config/resolve-context.js +33 -0
  129. package/lib/tools/hub-v2/docs.tools.js +138 -4
  130. package/lib/tools/hub-v2/index.js +2 -0
  131. package/lib/tools/hub-v2/issues-workflow.tools.d.ts +2 -0
  132. package/lib/tools/hub-v2/issues-workflow.tools.js +199 -0
  133. package/lib/tools/hub-v2/issues.tools.js +96 -6
  134. package/lib/tools/hub-v2/projects.tools.js +16 -3
  135. package/lib/tools/hub-v2/raw.d.ts +8 -0
  136. package/lib/tools/hub-v2/raw.js +33 -0
  137. package/lib/tools/hub-v2/rd.tools.js +167 -8
  138. package/lib/tools/hub-v2/schemas.d.ts +668 -71
  139. package/lib/tools/hub-v2/schemas.js +152 -1
  140. package/lib/tools/hub-v2/upload.tools.js +53 -5
  141. package/lib/tools/index.d.ts +1 -0
  142. package/lib/tools/index.js +22 -0
  143. package/lib/tools/log.tools.js +33 -6
  144. package/lib/tools/nginx/index.d.ts +1 -0
  145. package/lib/tools/nginx/index.js +5 -0
  146. package/lib/tools/nginx/nginx-control.tools.d.ts +2 -0
  147. package/lib/tools/nginx/nginx-control.tools.js +133 -0
  148. package/lib/tools/nginx/nginx-proxy.d.ts +24 -0
  149. package/lib/tools/nginx/nginx-proxy.js +154 -0
  150. package/lib/tools/nginx.tools.d.ts +2 -0
  151. package/lib/tools/nginx.tools.js +111 -0
  152. package/lib/tools/project/index.d.ts +2 -0
  153. package/lib/tools/project/index.js +7 -0
  154. package/lib/tools/project/launch-status.d.ts +10 -0
  155. package/lib/tools/project/launch-status.js +78 -0
  156. package/lib/tools/project/local-diagnostics.d.ts +19 -0
  157. package/lib/tools/project/local-diagnostics.js +97 -0
  158. package/lib/tools/project/observe-redaction.d.ts +3 -0
  159. package/lib/tools/project/observe-redaction.js +25 -0
  160. package/lib/tools/project/observe-runtime.d.ts +72 -0
  161. package/lib/tools/project/observe-runtime.js +147 -0
  162. package/lib/tools/project/project-control.tools.d.ts +2 -0
  163. package/lib/tools/project/project-control.tools.js +216 -0
  164. package/lib/tools/project/project-observe.tools.d.ts +2 -0
  165. package/lib/tools/project/project-observe.tools.js +191 -0
  166. package/lib/tools/project/runtime-config.d.ts +7 -0
  167. package/lib/tools/project/runtime-config.js +50 -0
  168. package/lib/tools/project-observe.tools.d.ts +1 -0
  169. package/lib/tools/project-observe.tools.js +5 -0
  170. package/lib/tools/project.tools.d.ts +8 -0
  171. package/lib/tools/project.tools.js +97 -6
  172. package/lib/tools/proxy.tools.js +4 -4
  173. package/lib/tools/review/index.d.ts +1 -0
  174. package/lib/tools/review/index.js +5 -0
  175. package/lib/tools/review/review.tools.d.ts +2 -0
  176. package/lib/tools/review/review.tools.js +152 -0
  177. package/lib/tools/runtime/index.d.ts +1 -0
  178. package/lib/tools/runtime/index.js +5 -0
  179. package/lib/tools/runtime/runtime-control.tools.d.ts +2 -0
  180. package/lib/tools/runtime/runtime-control.tools.js +89 -0
  181. package/lib/tools/runtime.tools.js +41 -4
  182. package/lib/tools/standard/index.d.ts +1 -0
  183. package/lib/tools/standard/index.js +5 -0
  184. package/lib/tools/standard/standard.tools.d.ts +2 -0
  185. package/lib/tools/standard/standard.tools.js +91 -0
  186. package/lib/tools/task.tools.js +44 -9
  187. package/lib/tools/test/index.d.ts +1 -0
  188. package/lib/tools/test/index.js +5 -0
  189. package/lib/tools/test/test-standard.tools.d.ts +2 -0
  190. package/lib/tools/test/test-standard.tools.js +51 -0
  191. package/lib/tools/tool-catalog.d.ts +2 -0
  192. package/lib/tools/tool-catalog.js +7 -0
  193. package/lib/tools/workflow/frontend-workflow.tools.d.ts +2 -0
  194. package/lib/tools/workflow/frontend-workflow.tools.js +364 -0
  195. package/lib/tools/workflow/index.d.ts +1 -0
  196. package/lib/tools/workflow/index.js +5 -0
  197. package/lib/tools/workspace-package.d.ts +22 -0
  198. package/lib/tools/workspace-package.js +130 -0
  199. package/lib/tools/workspace.tools.d.ts +7 -0
  200. package/lib/tools/workspace.tools.js +336 -0
  201. package/lib/utils/errors.js +6 -1
  202. package/lib/utils/result.d.ts +9 -0
  203. package/lib/utils/result.js +9 -0
  204. package/lib/workflow/frontend-task.schema.d.ts +83 -0
  205. package/lib/workflow/frontend-task.schema.js +25 -0
  206. package/lib/workflow/frontend-task.service.d.ts +57 -0
  207. package/lib/workflow/frontend-task.service.js +195 -0
  208. package/lib/workflow/workflow-status.d.ts +2 -0
  209. package/lib/workflow/workflow-status.js +14 -0
  210. package/lib/workflow/workflow-transition.d.ts +9 -0
  211. package/lib/workflow/workflow-transition.js +38 -0
  212. package/package.json +5 -3
  213. package/lib/tools/hub-v2/config.d.ts +0 -34
  214. package/lib/tools/hub-v2/config.js +0 -297
@@ -12,27 +12,62 @@ const taskStatusSchema = zod_1.z.object({
12
12
  function taskTools() {
13
13
  return [
14
14
  {
15
- name: "ngm.task.list",
15
+ name: "ngm_task_list",
16
16
  description: "List registered task views for a project, or active tasks when projectId is omitted.",
17
17
  riskLevel: "read",
18
18
  inputSchema: taskListSchema,
19
19
  async handler(args, context) {
20
- if (args.projectId) {
21
- const rows = await context.services.core.task.listViewsByProject(args.projectId);
22
- return (0, result_1.ok)("ngm.task.list", rows);
20
+ const localServer = context.services.localServer;
21
+ const availability = localServer ? await localServer.availability() : { available: false, reason: "local server client is not configured" };
22
+ if (availability.available && localServer) {
23
+ if (args.projectId) {
24
+ const rows = await localServer.listTaskViews(args.projectId);
25
+ return (0, result_1.ok)("ngm_task_list", {
26
+ controlPlane: "local-server",
27
+ localServer: availability,
28
+ rows,
29
+ });
30
+ }
31
+ const activeTasks = await localServer.listActiveTasks();
32
+ return (0, result_1.ok)("ngm_task_list", {
33
+ controlPlane: "local-server",
34
+ localServer: availability,
35
+ activeTasks,
36
+ });
23
37
  }
24
- const activeTasks = await context.services.core.task.listActive();
25
- return (0, result_1.ok)("ngm.task.list", activeTasks);
38
+ return (0, result_1.ok)("ngm_task_list", {
39
+ controlPlane: "unavailable",
40
+ localServer: availability,
41
+ status: "unavailable",
42
+ reason: "ng-manager local server is not running; start it with ngm server or ngm ui to inspect shared task state",
43
+ rows: args.projectId ? [] : undefined,
44
+ activeTasks: args.projectId ? undefined : [],
45
+ });
26
46
  },
27
47
  },
28
48
  {
29
- name: "ngm.task.getStatus",
49
+ name: "ngm_task_get_status",
30
50
  description: "Get the runtime status for a registered task.",
31
51
  riskLevel: "read",
32
52
  inputSchema: taskStatusSchema,
33
53
  async handler(args, context) {
34
- const runtime = await context.services.core.task.status(args.taskId);
35
- return (0, result_1.ok)("ngm.task.getStatus", runtime);
54
+ const localServer = context.services.localServer;
55
+ const availability = localServer ? await localServer.availability() : { available: false, reason: "local server client is not configured" };
56
+ if (availability.available && localServer) {
57
+ const runtime = await localServer.getTaskStatus(args.taskId);
58
+ return (0, result_1.ok)("ngm_task_get_status", {
59
+ controlPlane: "local-server",
60
+ localServer: availability,
61
+ runtime,
62
+ });
63
+ }
64
+ return (0, result_1.ok)("ngm_task_get_status", {
65
+ controlPlane: "unavailable",
66
+ localServer: availability,
67
+ status: "unavailable",
68
+ reason: "ng-manager local server is not running; start it with ngm server or ngm ui to inspect shared task state",
69
+ taskId: args.taskId,
70
+ });
36
71
  },
37
72
  },
38
73
  ];
@@ -0,0 +1 @@
1
+ export { testStandardTools } from "./test-standard.tools";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.testStandardTools = void 0;
4
+ var test_standard_tools_1 = require("./test-standard.tools");
5
+ Object.defineProperty(exports, "testStandardTools", { enumerable: true, get: function () { return test_standard_tools_1.testStandardTools; } });
@@ -0,0 +1,2 @@
1
+ import type { McpToolDefinition } from "../index";
2
+ export declare function testStandardTools(): McpToolDefinition[];
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.testStandardTools = testStandardTools;
4
+ const zod_1 = require("zod");
5
+ const result_1 = require("../../utils/result");
6
+ const project_files_1 = require("../../filesystem/project-files");
7
+ const frontend_standard_service_1 = require("../../standard/frontend-standard.service");
8
+ const test_validator_1 = require("../../standard/validators/test.validator");
9
+ const projectSchema = zod_1.z.object({
10
+ projectId: zod_1.z.string().trim().min(1).optional(),
11
+ projectPath: zod_1.z.string().trim().min(1).optional(),
12
+ }).strict();
13
+ function testStandardTools() {
14
+ return [
15
+ {
16
+ name: "ngm_test_detect_missing_specs",
17
+ description: "Detect service/util/complex component files that should have frontend spec coverage. MVP emits warnings only.",
18
+ riskLevel: "read",
19
+ inputSchema: projectSchema,
20
+ async handler(args, context) {
21
+ const project = await (0, project_files_1.resolveProjectRoot)(context, args);
22
+ const loaded = await (0, frontend_standard_service_1.loadFrontendStandard)(project);
23
+ const files = await (0, frontend_standard_service_1.scanFrontendProject)(project.projectRoot);
24
+ return (0, result_1.ok)("ngm_test_detect_missing_specs", (0, test_validator_1.detectMissingSpecs)(files, loaded.standard));
25
+ },
26
+ },
27
+ {
28
+ name: "ngm_test_generate_spec_plan",
29
+ description: "Generate a lightweight spec plan for missing service/util/component specs.",
30
+ riskLevel: "read",
31
+ inputSchema: projectSchema,
32
+ async handler(args, context) {
33
+ const project = await (0, project_files_1.resolveProjectRoot)(context, args);
34
+ const loaded = await (0, frontend_standard_service_1.loadFrontendStandard)(project);
35
+ const files = await (0, frontend_standard_service_1.scanFrontendProject)(project.projectRoot);
36
+ return (0, result_1.ok)("ngm_test_generate_spec_plan", (0, test_validator_1.generateSpecPlan)(files, loaded.standard));
37
+ },
38
+ },
39
+ {
40
+ name: "ngm_test_validate_naming",
41
+ description: "Validate frontend test file naming, preferring Angular .spec.ts files.",
42
+ riskLevel: "read",
43
+ inputSchema: projectSchema,
44
+ async handler(args, context) {
45
+ const project = await (0, project_files_1.resolveProjectRoot)(context, args);
46
+ const files = await (0, frontend_standard_service_1.scanFrontendProject)(project.projectRoot);
47
+ return (0, result_1.ok)("ngm_test_validate_naming", (0, test_validator_1.validateSpecNaming)(files));
48
+ },
49
+ },
50
+ ];
51
+ }
@@ -0,0 +1,2 @@
1
+ export { blockedLocalActions, capabilityCatalog, toolCatalog } from "../catalog";
2
+ export type { CapabilityCatalogEntry, ToolCatalogEntry } from "../catalog/types";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toolCatalog = exports.capabilityCatalog = exports.blockedLocalActions = void 0;
4
+ var catalog_1 = require("../catalog");
5
+ Object.defineProperty(exports, "blockedLocalActions", { enumerable: true, get: function () { return catalog_1.blockedLocalActions; } });
6
+ Object.defineProperty(exports, "capabilityCatalog", { enumerable: true, get: function () { return catalog_1.capabilityCatalog; } });
7
+ Object.defineProperty(exports, "toolCatalog", { enumerable: true, get: function () { return catalog_1.toolCatalog; } });
@@ -0,0 +1,2 @@
1
+ import type { McpToolDefinition } from "../index";
2
+ export declare function frontendWorkflowTools(): McpToolDefinition[];
@@ -0,0 +1,364 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.frontendWorkflowTools = frontendWorkflowTools;
4
+ const zod_1 = require("zod");
5
+ const result_1 = require("../../utils/result");
6
+ const project_files_1 = require("../../filesystem/project-files");
7
+ const operation_result_1 = require("../controlled/operation-result");
8
+ const operation_policy_1 = require("../controlled/operation-policy");
9
+ const frontend_standard_service_1 = require("../../standard/frontend-standard.service");
10
+ const test_validator_1 = require("../../standard/validators/test.validator");
11
+ const review_validator_1 = require("../../standard/validators/review.validator");
12
+ const frontend_task_service_1 = require("../../workflow/frontend-task.service");
13
+ const workflow_transition_1 = require("../../workflow/workflow-transition");
14
+ const projectSchema = zod_1.z.object({
15
+ projectId: zod_1.z.string().trim().min(1).optional(),
16
+ projectPath: zod_1.z.string().trim().min(1).optional(),
17
+ }).strict();
18
+ const createTaskSchema = projectSchema.extend({
19
+ taskId: zod_1.z.string().trim().min(1).optional(),
20
+ title: zod_1.z.string().trim().min(1),
21
+ description: zod_1.z.string().trim().optional(),
22
+ confirm: zod_1.z.boolean().optional(),
23
+ dryRun: zod_1.z.boolean().optional(),
24
+ }).strict();
25
+ const devPlanSchema = projectSchema.extend({
26
+ taskId: zod_1.z.string().trim().min(1),
27
+ title: zod_1.z.string().trim().min(1).optional(),
28
+ context: zod_1.z.string().optional(),
29
+ acceptance: zod_1.z.array(zod_1.z.string().trim().min(1)).optional(),
30
+ confirm: zod_1.z.boolean().optional(),
31
+ dryRun: zod_1.z.boolean().optional(),
32
+ }).strict();
33
+ const validateSchema = projectSchema.extend({
34
+ taskId: zod_1.z.string().trim().min(1).optional(),
35
+ confirm: zod_1.z.boolean().optional(),
36
+ dryRun: zod_1.z.boolean().optional(),
37
+ }).strict();
38
+ const deliverySchema = projectSchema.extend({
39
+ taskId: zod_1.z.string().trim().min(1),
40
+ summary: zod_1.z.string().trim().min(1),
41
+ verification: zod_1.z.array(zod_1.z.string().trim().min(1)).optional(),
42
+ risks: zod_1.z.array(zod_1.z.string().trim().min(1)).optional(),
43
+ confirm: zod_1.z.boolean().optional(),
44
+ dryRun: zod_1.z.boolean().optional(),
45
+ }).strict();
46
+ const advanceStatusSchema = projectSchema.extend({
47
+ taskId: zod_1.z.string().trim().min(1),
48
+ nextStatus: zod_1.z.enum(["context-ready", "patch-ready", "applied", "verified", "review-ready", "failed"]),
49
+ note: zod_1.z.string().trim().optional(),
50
+ confirm: zod_1.z.boolean().optional(),
51
+ dryRun: zod_1.z.boolean().optional(),
52
+ }).strict();
53
+ function writePreview(tool, safetyMessage, data) {
54
+ return (0, result_1.ok)(tool, {
55
+ operation: (0, operation_result_1.operation)("preview", "write", "low", safetyMessage),
56
+ ...data,
57
+ });
58
+ }
59
+ function toWorkflowCheckStatus(status) {
60
+ return status === "passed" || status === "warning" || status === "failed" || status === "blocked" ? status : "pending";
61
+ }
62
+ function aggregateValidationStatus(results) {
63
+ if (results.some((item) => item.status === "failed"))
64
+ return "failed";
65
+ if (results.some((item) => item.status === "blocked"))
66
+ return "blocked";
67
+ if (results.some((item) => item.status === "warning"))
68
+ return "warning";
69
+ return "passed";
70
+ }
71
+ function transitionBlocked(toolName, safetyMessage, error) {
72
+ if (error instanceof workflow_transition_1.WorkflowTransitionError) {
73
+ return (0, result_1.ok)(toolName, (0, operation_result_1.blocked)("write", "low", safetyMessage, (0, workflow_transition_1.workflowTransitionReason)(error.from, error.to)));
74
+ }
75
+ throw error;
76
+ }
77
+ async function readChangedFiles(context, args, projectRoot) {
78
+ if (!context.services.git.changedFiles)
79
+ return [];
80
+ try {
81
+ return await context.services.git.changedFiles({ ...args, projectPath: projectRoot });
82
+ }
83
+ catch {
84
+ return [];
85
+ }
86
+ }
87
+ function frontendWorkflowTools() {
88
+ return [
89
+ {
90
+ name: "ngm_workflow_create_frontend_task",
91
+ description: "Preview or create .ng-manager/frontend-tasks/{taskId}/task.json for a frontend workflow task.",
92
+ riskLevel: "write",
93
+ allowPreviewWhenBlocked: true,
94
+ deferPolicyToHandler: true,
95
+ isConfirmed: operation_result_1.isConfirmed,
96
+ inputSchema: createTaskSchema,
97
+ async handler(args, context) {
98
+ const project = await (0, project_files_1.resolveProjectRoot)(context, args);
99
+ const taskId = args.taskId || (0, frontend_task_service_1.createTaskId)(args.title);
100
+ const safetyMessage = "Create frontend workflow task metadata under project .ng-manager/frontend-tasks.";
101
+ if (!(0, operation_result_1.isConfirmed)(args)) {
102
+ return writePreview("ngm_workflow_create_frontend_task", safetyMessage, {
103
+ project,
104
+ task: { taskId, title: args.title, description: args.description, status: "draft" },
105
+ });
106
+ }
107
+ const policyBlock = (0, operation_policy_1.requireWritePolicy)("low", safetyMessage);
108
+ if (policyBlock)
109
+ return (0, result_1.ok)("ngm_workflow_create_frontend_task", policyBlock);
110
+ const result = await (0, frontend_task_service_1.createFrontendTask)(project, {
111
+ taskId: args.taskId,
112
+ title: args.title,
113
+ description: args.description,
114
+ });
115
+ if (result.status === "blocked") {
116
+ return (0, result_1.ok)("ngm_workflow_create_frontend_task", (0, operation_result_1.blocked)("write", "low", safetyMessage, result.reason, {
117
+ taskId: result.taskId,
118
+ }));
119
+ }
120
+ return (0, result_1.ok)("ngm_workflow_create_frontend_task", {
121
+ operation: (0, operation_result_1.operation)("executed", "write", "low", safetyMessage),
122
+ project,
123
+ task: result.task,
124
+ changedFiles: result.changedFiles,
125
+ });
126
+ },
127
+ },
128
+ {
129
+ name: "ngm_workflow_generate_dev_plan",
130
+ description: "Preview or write .ng-manager/frontend-tasks/{taskId}/dev-plan.md and advance task status to plan-ready.",
131
+ riskLevel: "write",
132
+ allowPreviewWhenBlocked: true,
133
+ deferPolicyToHandler: true,
134
+ isConfirmed: operation_result_1.isConfirmed,
135
+ inputSchema: devPlanSchema,
136
+ async handler(args, context) {
137
+ const project = await (0, project_files_1.resolveProjectRoot)(context, args);
138
+ const task = await (0, frontend_task_service_1.readFrontendTask)(project, args.taskId).catch(() => undefined);
139
+ const title = args.title || task?.title || args.taskId;
140
+ const markdown = (0, frontend_task_service_1.devPlanMarkdown)({ taskId: args.taskId, title, context: args.context, acceptance: args.acceptance });
141
+ const safetyMessage = "Write frontend development plan under project .ng-manager/frontend-tasks.";
142
+ if (!(0, operation_result_1.isConfirmed)(args)) {
143
+ return writePreview("ngm_workflow_generate_dev_plan", safetyMessage, { project, taskId: args.taskId, markdown });
144
+ }
145
+ const policyBlock = (0, operation_policy_1.requireWritePolicy)("low", safetyMessage);
146
+ if (policyBlock)
147
+ return (0, result_1.ok)("ngm_workflow_generate_dev_plan", policyBlock);
148
+ if (!task)
149
+ return (0, result_1.ok)("ngm_workflow_generate_dev_plan", (0, operation_result_1.blocked)("write", "low", safetyMessage, "task.json was not found; create the frontend task first"));
150
+ let result;
151
+ try {
152
+ result = await (0, frontend_task_service_1.writeTaskMarkdown)(project, args.taskId, "dev-plan.md", markdown, "plan-ready");
153
+ }
154
+ catch (error) {
155
+ return transitionBlocked("ngm_workflow_generate_dev_plan", safetyMessage, error);
156
+ }
157
+ return (0, result_1.ok)("ngm_workflow_generate_dev_plan", {
158
+ operation: (0, operation_result_1.operation)("executed", "write", "low", safetyMessage),
159
+ project,
160
+ task: result.task,
161
+ changedFiles: result.changedFiles,
162
+ });
163
+ },
164
+ },
165
+ {
166
+ name: "ngm_workflow_advance_status",
167
+ description: "Preview or advance a frontend workflow task status through the controlled workflow transition graph.",
168
+ riskLevel: "write",
169
+ allowPreviewWhenBlocked: true,
170
+ deferPolicyToHandler: true,
171
+ isConfirmed: operation_result_1.isConfirmed,
172
+ inputSchema: advanceStatusSchema,
173
+ async handler(args, context) {
174
+ const project = await (0, project_files_1.resolveProjectRoot)(context, args);
175
+ const task = await (0, frontend_task_service_1.readFrontendTask)(project, args.taskId).catch(() => undefined);
176
+ const safetyMessage = "Advance frontend workflow task status in task.json.";
177
+ if (!(0, operation_result_1.isConfirmed)(args)) {
178
+ return writePreview("ngm_workflow_advance_status", safetyMessage, {
179
+ project,
180
+ taskId: args.taskId,
181
+ fromStatus: task?.status,
182
+ nextStatus: args.nextStatus,
183
+ note: args.note,
184
+ });
185
+ }
186
+ const policyBlock = (0, operation_policy_1.requireWritePolicy)("low", safetyMessage);
187
+ if (policyBlock)
188
+ return (0, result_1.ok)("ngm_workflow_advance_status", policyBlock);
189
+ if (!task)
190
+ return (0, result_1.ok)("ngm_workflow_advance_status", (0, operation_result_1.blocked)("write", "low", safetyMessage, "task.json was not found; create the frontend task first"));
191
+ let updated;
192
+ try {
193
+ updated = await (0, frontend_task_service_1.updateTaskStatus)(project, args.taskId, args.nextStatus);
194
+ }
195
+ catch (error) {
196
+ return transitionBlocked("ngm_workflow_advance_status", safetyMessage, error);
197
+ }
198
+ return (0, result_1.ok)("ngm_workflow_advance_status", {
199
+ operation: (0, operation_result_1.operation)("executed", "write", "low", safetyMessage),
200
+ project,
201
+ task: updated,
202
+ note: args.note,
203
+ changedFiles: [`.ng-manager/frontend-tasks/${args.taskId}/task.json`],
204
+ });
205
+ },
206
+ },
207
+ {
208
+ name: "ngm_workflow_validate_before_write",
209
+ description: "Preview or persist lightweight frontend project validation before AI writes source changes.",
210
+ riskLevel: "write",
211
+ allowPreviewWhenBlocked: true,
212
+ deferPolicyToHandler: true,
213
+ isConfirmed: operation_result_1.isConfirmed,
214
+ inputSchema: validateSchema,
215
+ async handler(args, context) {
216
+ const project = await (0, project_files_1.resolveProjectRoot)(context, args);
217
+ const loaded = await (0, frontend_standard_service_1.loadFrontendStandard)(project);
218
+ const validation = await (0, frontend_standard_service_1.validateFrontendProject)(project, loaded.standard);
219
+ const test = validation.checks.missingSpecs;
220
+ const checks = {
221
+ standard: toWorkflowCheckStatus(validation.status),
222
+ test: toWorkflowCheckStatus(test.status),
223
+ review: "pending",
224
+ build: "pending",
225
+ };
226
+ const safetyMessage = "Update frontend workflow pre-write checks in task.json.";
227
+ const preview = {
228
+ operation: (0, operation_result_1.operation)("preview", "write", "low", safetyMessage),
229
+ project,
230
+ taskId: args.taskId,
231
+ checks,
232
+ validation,
233
+ };
234
+ if (!args.taskId || !(0, operation_result_1.isConfirmed)(args))
235
+ return (0, result_1.ok)("ngm_workflow_validate_before_write", preview);
236
+ const policyBlock = (0, operation_policy_1.requireWritePolicy)("low", safetyMessage);
237
+ if (policyBlock)
238
+ return (0, result_1.ok)("ngm_workflow_validate_before_write", policyBlock);
239
+ let task;
240
+ try {
241
+ task = await (0, frontend_task_service_1.updateFrontendTask)(project, args.taskId, { checks });
242
+ }
243
+ catch (error) {
244
+ return transitionBlocked("ngm_workflow_validate_before_write", safetyMessage, error);
245
+ }
246
+ return (0, result_1.ok)("ngm_workflow_validate_before_write", {
247
+ ...preview,
248
+ operation: (0, operation_result_1.operation)("executed", "write", "low", safetyMessage),
249
+ task,
250
+ changedFiles: [`.ng-manager/frontend-tasks/${args.taskId}/task.json`],
251
+ });
252
+ },
253
+ },
254
+ {
255
+ name: "ngm_workflow_validate_before_commit",
256
+ description: "Preview or persist frontend standard/test/review/Git checks before commit.",
257
+ riskLevel: "write",
258
+ allowPreviewWhenBlocked: true,
259
+ deferPolicyToHandler: true,
260
+ isConfirmed: operation_result_1.isConfirmed,
261
+ inputSchema: validateSchema,
262
+ async handler(args, context) {
263
+ const project = await (0, project_files_1.resolveProjectRoot)(context, args);
264
+ const loaded = await (0, frontend_standard_service_1.loadFrontendStandard)(project);
265
+ const validation = await (0, frontend_standard_service_1.validateFrontendProject)(project, loaded.standard);
266
+ const files = await (0, frontend_standard_service_1.scanFrontendProject)(project.projectRoot);
267
+ const changedFiles = await readChangedFiles(context, args, project.projectRoot);
268
+ const test = (0, test_validator_1.detectMissingSpecs)(files, loaded.standard);
269
+ const review = (0, review_validator_1.detectReviewRisks)(files, changedFiles, loaded.standard);
270
+ const aggregateStatus = aggregateValidationStatus([validation, test, review]);
271
+ const checks = {
272
+ standard: toWorkflowCheckStatus(validation.status),
273
+ test: toWorkflowCheckStatus(test.status),
274
+ review: toWorkflowCheckStatus(review.status),
275
+ build: "pending",
276
+ };
277
+ const safetyMessage = "Update frontend workflow pre-commit checks in task.json.";
278
+ const preview = {
279
+ operation: (0, operation_result_1.operation)("preview", "write", "low", safetyMessage),
280
+ project,
281
+ taskId: args.taskId,
282
+ status: aggregateStatus,
283
+ changedFiles,
284
+ checks,
285
+ standard: validation,
286
+ test,
287
+ review,
288
+ git: {
289
+ changedFiles,
290
+ },
291
+ };
292
+ if (!args.taskId || !(0, operation_result_1.isConfirmed)(args))
293
+ return (0, result_1.ok)("ngm_workflow_validate_before_commit", preview);
294
+ const policyBlock = (0, operation_policy_1.requireWritePolicy)("low", safetyMessage);
295
+ if (policyBlock)
296
+ return (0, result_1.ok)("ngm_workflow_validate_before_commit", policyBlock);
297
+ let task;
298
+ try {
299
+ const current = await (0, frontend_task_service_1.readFrontendTask)(project, args.taskId);
300
+ const statusPatch = aggregateStatus === "failed" || aggregateStatus === "blocked"
301
+ ? { status: "failed" }
302
+ : current.status === "applied"
303
+ ? { status: "verified" }
304
+ : {};
305
+ task = await (0, frontend_task_service_1.updateFrontendTask)(project, args.taskId, {
306
+ checks,
307
+ changedFiles,
308
+ ...statusPatch,
309
+ });
310
+ }
311
+ catch (error) {
312
+ return transitionBlocked("ngm_workflow_validate_before_commit", safetyMessage, error);
313
+ }
314
+ return (0, result_1.ok)("ngm_workflow_validate_before_commit", {
315
+ ...preview,
316
+ operation: (0, operation_result_1.operation)("executed", "write", "low", safetyMessage),
317
+ task,
318
+ changedFiles: [`.ng-manager/frontend-tasks/${args.taskId}/task.json`],
319
+ });
320
+ },
321
+ },
322
+ {
323
+ name: "ngm_workflow_generate_delivery_report",
324
+ description: "Preview or write .ng-manager/frontend-tasks/{taskId}/delivery-report.md and advance task status to delivered.",
325
+ riskLevel: "write",
326
+ allowPreviewWhenBlocked: true,
327
+ deferPolicyToHandler: true,
328
+ isConfirmed: operation_result_1.isConfirmed,
329
+ inputSchema: deliverySchema,
330
+ async handler(args, context) {
331
+ const project = await (0, project_files_1.resolveProjectRoot)(context, args);
332
+ const markdown = (0, frontend_task_service_1.deliveryReportMarkdown)({
333
+ taskId: args.taskId,
334
+ summary: args.summary,
335
+ verification: args.verification,
336
+ risks: args.risks,
337
+ });
338
+ const safetyMessage = "Write frontend delivery report under project .ng-manager/frontend-tasks.";
339
+ if (!(0, operation_result_1.isConfirmed)(args)) {
340
+ return writePreview("ngm_workflow_generate_delivery_report", safetyMessage, { project, taskId: args.taskId, markdown });
341
+ }
342
+ const policyBlock = (0, operation_policy_1.requireWritePolicy)("low", safetyMessage);
343
+ if (policyBlock)
344
+ return (0, result_1.ok)("ngm_workflow_generate_delivery_report", policyBlock);
345
+ const task = await (0, frontend_task_service_1.readFrontendTask)(project, args.taskId).catch(() => undefined);
346
+ if (!task)
347
+ return (0, result_1.ok)("ngm_workflow_generate_delivery_report", (0, operation_result_1.blocked)("write", "low", safetyMessage, "task.json was not found; create the frontend task first"));
348
+ let result;
349
+ try {
350
+ result = await (0, frontend_task_service_1.writeTaskMarkdown)(project, args.taskId, "delivery-report.md", markdown, "delivered");
351
+ }
352
+ catch (error) {
353
+ return transitionBlocked("ngm_workflow_generate_delivery_report", safetyMessage, error);
354
+ }
355
+ return (0, result_1.ok)("ngm_workflow_generate_delivery_report", {
356
+ operation: (0, operation_result_1.operation)("executed", "write", "low", safetyMessage),
357
+ project,
358
+ task: result.task,
359
+ changedFiles: result.changedFiles,
360
+ });
361
+ },
362
+ },
363
+ ];
364
+ }
@@ -0,0 +1 @@
1
+ export { frontendWorkflowTools } from "./frontend-workflow.tools";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.frontendWorkflowTools = void 0;
4
+ var frontend_workflow_tools_1 = require("./frontend-workflow.tools");
5
+ Object.defineProperty(exports, "frontendWorkflowTools", { enumerable: true, get: function () { return frontend_workflow_tools_1.frontendWorkflowTools; } });
@@ -0,0 +1,22 @@
1
+ export type PackageJsonSummary = {
2
+ name?: string;
3
+ version?: string;
4
+ private?: boolean;
5
+ description?: string;
6
+ path: string;
7
+ packageJsonPath: string;
8
+ scripts: Record<string, string>;
9
+ engines: Record<string, unknown>;
10
+ dependencies: Record<string, string>;
11
+ devDependencies: Record<string, string>;
12
+ peerDependencies: Record<string, string>;
13
+ workspaces?: unknown;
14
+ bin?: unknown;
15
+ main?: string;
16
+ types?: string;
17
+ exports?: unknown;
18
+ };
19
+ export declare function toRelativeWorkspacePath(workspaceRoot: string, filePath: string): string;
20
+ export declare function readPackageJsonSummary(workspaceRoot: string, packageDir: string): Promise<PackageJsonSummary>;
21
+ export declare function readOptionalPackageJsonSummary(workspaceRoot: string, packageDir: string): Promise<PackageJsonSummary | null>;
22
+ export declare function listKnownWorkspacePackages(workspaceRoot: string): Promise<PackageJsonSummary[]>;