@uipath/skills 1.196.0 → 1.197.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 (592) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +5 -2
  3. package/CODEOWNERS +22 -7
  4. package/README.md +14 -1
  5. package/assets/skill-status.json +14 -1
  6. package/assets/uip-catalog-snapshot.json +13 -2
  7. package/hooks/hooks.json +12 -0
  8. package/hooks/send-telemetry.sh +445 -0
  9. package/hooks/suggest-permissions.sh +6 -0
  10. package/package.json +1 -1
  11. package/skills/uipath-admin/SKILL.md +24 -4
  12. package/skills/uipath-admin/references/audit-commands.md +25 -21
  13. package/skills/uipath-admin/references/audit-workflow-guide.md +26 -25
  14. package/skills/uipath-admin/references/diagnose/CAPABILITY.md +74 -0
  15. package/skills/uipath-admin/references/diagnose/references/failure-modes.md +228 -0
  16. package/skills/uipath-admin/references/diagnose/references/troubleshooting-guide.md +106 -0
  17. package/skills/uipath-admin/references/identity-troubleshoot-guide.md +251 -0
  18. package/skills/uipath-agents/SKILL.md +12 -8
  19. package/skills/uipath-agents/references/coded/capabilities/context-grounding.md +2 -0
  20. package/skills/uipath-agents/references/coded/capabilities/conversational-agents.md +2 -0
  21. package/skills/uipath-agents/references/coded/capabilities/guardrails/guardrails-recommend.md +12 -7
  22. package/skills/uipath-agents/references/coded/capabilities/guardrails/guardrails.md +141 -1
  23. package/skills/uipath-agents/references/coded/capabilities/human-in-the-loop.md +2 -0
  24. package/skills/uipath-agents/references/coded/capabilities/integration-service.md +19 -33
  25. package/skills/uipath-agents/references/coded/lifecycle/bindings-reference.md +54 -22
  26. package/skills/uipath-agents/references/coded/lifecycle/build.md +1 -0
  27. package/skills/uipath-agents/references/coded/lifecycle/evaluations/evaluation-sets.md +5 -1
  28. package/skills/uipath-agents/references/coded/lifecycle/setup.md +3 -1
  29. package/skills/uipath-agents/references/coded/quickstart.md +11 -10
  30. package/skills/uipath-agents/references/coded-vs-lowcode-guide.md +1 -0
  31. package/skills/uipath-agents/references/context-grounding-patterns.md +1 -1
  32. package/skills/uipath-agents/references/lowcode/agent-definition.md +97 -12
  33. package/skills/uipath-agents/references/lowcode/capabilities/built-in-tools/analyze-attachments.md +2 -2
  34. package/skills/uipath-agents/references/lowcode/capabilities/built-in-tools/batch-transform/impl-json.md +40 -14
  35. package/skills/uipath-agents/references/lowcode/capabilities/built-in-tools/built-in-tools.md +4 -3
  36. package/skills/uipath-agents/references/lowcode/capabilities/built-in-tools/deeprag/impl-json.md +38 -6
  37. package/skills/uipath-agents/references/lowcode/capabilities/context/attachments.md +1 -1
  38. package/skills/uipath-agents/references/lowcode/capabilities/context/context.md +1 -1
  39. package/skills/uipath-agents/references/lowcode/capabilities/context/datafabric.md +1 -1
  40. package/skills/uipath-agents/references/lowcode/capabilities/context/index.md +7 -3
  41. package/skills/uipath-agents/references/lowcode/capabilities/escalation/escalation.md +49 -38
  42. package/skills/uipath-agents/references/lowcode/capabilities/guardrails/guardrails-recommend.md +3 -1
  43. package/skills/uipath-agents/references/lowcode/capabilities/guardrails/guardrails.md +49 -49
  44. package/skills/uipath-agents/references/lowcode/capabilities/inline-in-flow/inline-in-flow.md +34 -14
  45. package/skills/uipath-agents/references/lowcode/capabilities/integration-service/integration-service.md +1 -1
  46. package/skills/uipath-agents/references/lowcode/capabilities/memory/memory.md +2 -0
  47. package/skills/uipath-agents/references/lowcode/capabilities/process/process.md +2 -2
  48. package/skills/uipath-agents/references/lowcode/capabilities/process/solution-files.md +1 -1
  49. package/skills/uipath-agents/references/lowcode/critical-rules/autonomous-critical-rules.md +15 -0
  50. package/skills/uipath-agents/references/lowcode/critical-rules/conversational-critical-rules.md +19 -0
  51. package/skills/uipath-agents/references/lowcode/{critical-rules.md → critical-rules/critical-rules.md} +25 -27
  52. package/skills/uipath-agents/references/lowcode/debug.md +6 -3
  53. package/skills/uipath-agents/references/lowcode/evaluations/evaluate.md +2 -0
  54. package/skills/uipath-agents/references/lowcode/lowcode.md +29 -6
  55. package/skills/uipath-agents/references/lowcode/model-selection-guide.md +4 -1
  56. package/skills/uipath-agents/references/lowcode/project-lifecycle.md +20 -8
  57. package/skills/uipath-agents/references/lowcode/prompting/agent-prompting-guide.md +17 -0
  58. package/skills/uipath-agents/references/lowcode/{agent-prompting-guide.md → prompting/autonomous-agent-prompting-guide.md} +9 -11
  59. package/skills/uipath-agents/references/lowcode/prompting/conversational-agent-prompting-guide.md +123 -0
  60. package/skills/uipath-agents/references/lowcode/solution-resources.md +1 -1
  61. package/skills/uipath-api-workflow/SKILL.md +32 -12
  62. package/skills/uipath-api-workflow/references/cli-reference.md +110 -22
  63. package/skills/uipath-api-workflow/references/connector-activity-discovery.md +43 -4
  64. package/skills/uipath-api-workflow/references/troubleshooting.md +23 -7
  65. package/skills/uipath-api-workflow/references/workflow-file-format.md +25 -7
  66. package/skills/uipath-coded-apps/SKILL.md +55 -12
  67. package/skills/uipath-coded-apps/assets/fixtures/governance-dashboard-starter-kit.tar.gz +0 -0
  68. package/skills/uipath-coded-apps/assets/scripts/dashboards/build-dashboard.mjs +1371 -0
  69. package/skills/uipath-coded-apps/assets/scripts/dashboards/capability-registry.json +845 -0
  70. package/skills/uipath-coded-apps/assets/scripts/dashboards/flows/build.mjs +338 -0
  71. package/skills/uipath-coded-apps/assets/scripts/dashboards/flows/edit.mjs +248 -0
  72. package/skills/uipath-coded-apps/assets/scripts/dashboards/flows/template.mjs +82 -0
  73. package/skills/uipath-coded-apps/assets/scripts/dashboards/flows/upgrade.mjs +73 -0
  74. package/skills/uipath-coded-apps/assets/scripts/dashboards/lifecycle.mjs +207 -0
  75. package/skills/uipath-coded-apps/assets/scripts/dashboards/setup-admin-folder.mjs +146 -0
  76. package/skills/uipath-coded-apps/assets/scripts/dashboards/tests/regime-eject.test.mjs +124 -0
  77. package/skills/uipath-coded-apps/assets/scripts/dashboards/tests/resolution.test.mjs +1635 -0
  78. package/skills/uipath-coded-apps/assets/templates/action-app/app-template.css +9 -0
  79. package/skills/uipath-coded-apps/assets/templates/action-app/document-tab-template.css +139 -0
  80. package/skills/uipath-coded-apps/assets/templates/action-app/form-template.css +442 -0
  81. package/skills/uipath-coded-apps/assets/templates/action-app/index-template.css +111 -0
  82. package/skills/uipath-coded-apps/assets/templates/action-app-template.md +357 -152
  83. package/skills/uipath-coded-apps/assets/templates/web-app-template.md +255 -78
  84. package/skills/uipath-coded-apps/references/create-action-app.md +284 -195
  85. package/skills/uipath-coded-apps/references/create-web-app.md +64 -26
  86. package/skills/uipath-coded-apps/references/dashboards/CAPABILITY.md +179 -0
  87. package/skills/uipath-coded-apps/references/dashboards/aesthetic/charting.md +138 -0
  88. package/skills/uipath-coded-apps/references/dashboards/aesthetic/layout-patterns.md +152 -0
  89. package/skills/uipath-coded-apps/references/dashboards/plugins/build/impl.md +423 -0
  90. package/skills/uipath-coded-apps/references/dashboards/plugins/deploy/impl.md +322 -0
  91. package/skills/uipath-coded-apps/references/dashboards/primitives/customization.md +66 -0
  92. package/skills/uipath-coded-apps/references/dashboards/primitives/detail-views.md +64 -0
  93. package/skills/uipath-coded-apps/references/dashboards/primitives/incremental-editor.md +92 -0
  94. package/skills/uipath-coded-apps/references/dashboards/primitives/state-file.md +64 -0
  95. package/skills/uipath-coded-apps/references/dashboards/primitives/tier-resolution.md +474 -0
  96. package/skills/uipath-coded-apps/references/debug.md +15 -21
  97. package/skills/uipath-coded-apps/references/oauth-client-setup.md +5 -5
  98. package/skills/uipath-coded-apps/references/oauth-scopes.md +64 -2
  99. package/skills/uipath-coded-apps/references/pack-publish-deploy.md +12 -5
  100. package/skills/uipath-coded-apps/references/patterns.md +10 -5
  101. package/skills/uipath-coded-apps/references/sdk/action-center.md +32 -6
  102. package/skills/uipath-coded-apps/references/sdk/agents.md +241 -0
  103. package/skills/uipath-coded-apps/references/sdk/governance-traces.md +186 -0
  104. package/skills/uipath-coded-apps/references/sdk/governance.md +72 -0
  105. package/skills/uipath-coded-apps/references/sdk/imports.md +4 -0
  106. package/skills/uipath-coded-apps/references/sdk/maestro.md +114 -0
  107. package/skills/uipath-coded-apps/references/sdk/orchestrator.md +80 -4
  108. package/skills/uipath-coded-apps/references/sdk/pagination.md +2 -0
  109. package/skills/uipath-coded-apps/references/sdk/traces.md +89 -0
  110. package/skills/uipath-coded-apps/references/widgets/validation-station.md +308 -0
  111. package/skills/uipath-coded-apps/scripts/validate-action-schema.js +241 -0
  112. package/skills/uipath-connector-builder/SKILL.md +192 -0
  113. package/skills/uipath-connector-builder/references/auth.md +171 -0
  114. package/skills/uipath-connector-builder/references/configuration.md +130 -0
  115. package/skills/uipath-connector-builder/references/debugging.md +80 -0
  116. package/skills/uipath-connector-builder/references/element-json.md +148 -0
  117. package/skills/uipath-connector-builder/references/events.md +132 -0
  118. package/skills/uipath-connector-builder/references/hooks.md +198 -0
  119. package/skills/uipath-connector-builder/references/overview.md +78 -0
  120. package/skills/uipath-connector-builder/references/standard-resources.md +111 -0
  121. package/skills/uipath-connector-builder/references/system-resources.md +85 -0
  122. package/skills/uipath-feedback/SKILL.md +43 -29
  123. package/skills/{uipath-agents/references/coded/frameworks/coded-functions.md → uipath-functions/SKILL.md} +36 -23
  124. package/skills/uipath-governance/SKILL.md +49 -8
  125. package/skills/uipath-governance/references/aops-policy/aops-policy-commands.md +10 -10
  126. package/skills/uipath-governance/references/aops-policy/aops-policy-deploy-guide.md +7 -7
  127. package/skills/uipath-governance/references/auth-context.md +101 -0
  128. package/skills/uipath-governance/references/cli-cheatsheet.md +207 -0
  129. package/skills/uipath-governance/references/compliance-pack/catalog/impl.md +79 -0
  130. package/skills/uipath-governance/references/compliance-pack/coverage/impl.md +141 -0
  131. package/skills/uipath-governance/references/compliance-pack/disable/impl.md +39 -0
  132. package/skills/uipath-governance/references/compliance-pack/full-apply/impl.md +164 -0
  133. package/skills/uipath-governance/references/compliance-pack/partial-apply/impl.md +266 -0
  134. package/skills/uipath-governance/references/compliance-pack/partial-apply/merge-overrides-guide.md +28 -0
  135. package/skills/uipath-governance/references/compliance-pack/partial-apply/planning.md +82 -0
  136. package/skills/uipath-governance/references/compliance-pack/partial-apply/synthesize-formdata-guide.md +22 -0
  137. package/skills/uipath-governance/references/compliance-pack/preview-gate.md +43 -0
  138. package/skills/uipath-governance/references/compliance-pack/query/impl.md +75 -0
  139. package/skills/uipath-governance/references/diagnose/CAPABILITY.md +71 -0
  140. package/skills/uipath-governance/references/diagnose/references/failure-modes.md +201 -0
  141. package/skills/uipath-governance/references/diagnose/references/troubleshooting-guide.md +137 -0
  142. package/skills/uipath-governance/references/disambiguation-guide.md +15 -0
  143. package/skills/uipath-governance/scripts/merge-overrides.mjs +81 -0
  144. package/skills/uipath-governance/scripts/synthesize-formdata.mjs +86 -0
  145. package/skills/uipath-human-in-the-loop/SKILL.md +30 -25
  146. package/skills/uipath-human-in-the-loop/references/hitl-node-apptask.md +38 -4
  147. package/skills/uipath-human-in-the-loop/references/hitl-node-coded-action-app.md +2 -3
  148. package/skills/uipath-human-in-the-loop/references/hitl-node-quickform.md +92 -34
  149. package/skills/uipath-ixp/SKILL.md +120 -0
  150. package/skills/uipath-ixp/references/cli-reference.md +121 -0
  151. package/skills/uipath-ixp/references/improve-prompts-guide.md +283 -0
  152. package/skills/uipath-ixp/references/label-documents-guide.md +207 -0
  153. package/skills/uipath-ixp/references/project-setup-guide.md +90 -0
  154. package/skills/uipath-maestro-bpmn/SKILL.md +167 -68
  155. package/skills/uipath-maestro-bpmn/references/cli-conventions.md +47 -0
  156. package/skills/uipath-maestro-bpmn/references/diagnose/CAPABILITY.md +6 -6
  157. package/skills/uipath-maestro-bpmn/references/operate/CAPABILITY.md +3 -3
  158. package/skills/uipath-maestro-bpmn/references/registry-workflow.md +199 -0
  159. package/skills/uipath-maestro-bpmn/references/structural-bpmn.md +500 -0
  160. package/skills/uipath-maestro-bpmn/validator/README.md +214 -0
  161. package/skills/uipath-maestro-bpmn/validator/bpmn-spec.json +2477 -0
  162. package/skills/uipath-maestro-bpmn/validator/model.mjs +419 -0
  163. package/skills/uipath-maestro-bpmn/validator/package.json +17 -0
  164. package/skills/uipath-maestro-bpmn/validator/rules.mjs +1403 -0
  165. package/skills/uipath-maestro-bpmn/validator/samples/invalid-conditional-and-variable.bpmn +25 -0
  166. package/skills/uipath-maestro-bpmn/validator/samples/valid-baseline.bpmn +52 -0
  167. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/A.2.0.bpmn +157 -0
  168. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/A.2.1.bpmn +333 -0
  169. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/B.1.0.bpmn +598 -0
  170. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/B.2.0.bpmn +1709 -0
  171. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/C.2.0.bpmn +564 -0
  172. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/C.3.0.bpmn +671 -0
  173. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/C.4.0.bpmn +1045 -0
  174. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/C.5.0.bpmn +1176 -0
  175. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/C.6.0.bpmn +670 -0
  176. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/C.7.0.bpmn +466 -0
  177. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/Can_Parse_Complex_Process_With_Task_Gateway_BoundaryEvent_etc.bpmn +74 -0
  178. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/ExclusiveGatewayDefaultFlow.bpmn +32 -0
  179. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/ExternalAgentWorkflow.bpmn +62 -0
  180. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/Golden_Scenario.initial.bpmn +361 -0
  181. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/InclusiveJoinRouteAwayBranch.bpmn +62 -0
  182. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/Parse_AsyncExecution_And_Create_CorrectModel.bpmn +74 -0
  183. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/Parse_IXP_ExtractionValidation_And_Create_CorrectModel.bpmn +35 -0
  184. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/Parse_IXP_Extraction_FileUpload_And_Create_CorrectModel.bpmn +33 -0
  185. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/Parse_IXP_Extraction_JobAttachment_And_Create_CorrectModel.bpmn +35 -0
  186. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/Parse_SubProcess_With_Multiple_Element_Types.bpmn +76 -0
  187. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/StartEventWithOutputs.bpmn +36 -0
  188. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/StartGatewayEnd.bpmn +44 -0
  189. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/all elements.bpmn +516 -0
  190. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/all_sequence_flow_types.bpmn +173 -0
  191. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/demo.bpmn +181 -0
  192. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/subprocess-example-001-collapsed.bpmn +126 -0
  193. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/subprocess-example-001-expanded.bpmn +122 -0
  194. package/skills/uipath-maestro-bpmn/validator/test/fixtures/expected-findings/subprocess-example-003-collapsed_deeply-nested.bpmn +438 -0
  195. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/A.1.0.bpmn +87 -0
  196. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/A.3.0.bpmn +165 -0
  197. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/ApiWorkflow.bpmn +39 -0
  198. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/BpmnNestedSubProcessTests.bpmn +102 -0
  199. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/BpmnTimerBoundaryEvents.bpmn +160 -0
  200. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/BpmnXmlWithCatchAllErrorEventSubProcess.bpmn +45 -0
  201. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/BpmnXmlWithSpecificErrorEventSubProcess.bpmn +46 -0
  202. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/CaseManagementWithConstantIdentifier.bpmn +218 -0
  203. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/ErrorBoundary.bpmn +78 -0
  204. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/ErrorPropagationInEventSubprocess.bpmn +340 -0
  205. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/EventBasedGatewayFirstCatcherWins.bpmn +56 -0
  206. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/Example-EventBasedGateway.bpmn +117 -0
  207. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/ExclusiveGatewayConditional.bpmn +45 -0
  208. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/ExclusiveGatewaySharedEndEvent.bpmn +45 -0
  209. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/ExclusiveWithParallelGateway.bpmn +68 -0
  210. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/FourScriptTasks.bpmn +84 -0
  211. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/HitlTaskOnly.bpmn +55 -0
  212. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/InclusiveGatewayForkJoin.bpmn +69 -0
  213. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/Parse_BPMN_Elements_And_Create_CorrectModel.bpmn +20 -0
  214. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/Parse_HttpRequest_ServiceTask_And_Create_Correct_Model.bpmn +34 -0
  215. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/Parse_MessageBoundaryEvent_And_Create_CorrectModel.bpmn +87 -0
  216. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/Parse_Script_Task_V2_And_Create_Correct_Model.bpmn +31 -0
  217. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/Parse_Sets_Containers_Properly.bpmn +129 -0
  218. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/ScriptWritesVariableThenGatewayBranches.bpmn +55 -0
  219. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/boundaryevent.bpmn +30 -0
  220. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/collapsed-subprocess.bpmn +83 -0
  221. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/connectable-types.bpmn +85 -0
  222. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/extensions-orchestrator-start-job.bpmn +80 -0
  223. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/multiparticipantpool.bpmn +77 -0
  224. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/nestedsubprocess.bpmn +36 -0
  225. package/skills/uipath-maestro-bpmn/validator/test/fixtures/known-good/simple.bpmn +59 -0
  226. package/skills/uipath-maestro-bpmn/validator/test/integration.test.mjs +146 -0
  227. package/skills/uipath-maestro-bpmn/validator/test/model-helpers.mjs +42 -0
  228. package/skills/uipath-maestro-bpmn/validator/test/ported-rule-tests.mjs +983 -0
  229. package/skills/uipath-maestro-bpmn/validator/test/run-tests.mjs +530 -0
  230. package/skills/uipath-maestro-bpmn/validator/uipath-moddle.v1.json +715 -0
  231. package/skills/uipath-maestro-bpmn/validator/validate-bpmn.mjs +164 -0
  232. package/skills/uipath-maestro-case/SKILL.md +5 -1
  233. package/skills/uipath-maestro-case/assets/templates/sdd-template-examples.md +10 -0
  234. package/skills/uipath-maestro-case/assets/templates/sdd-template.md +89 -17
  235. package/skills/uipath-maestro-case/references/bindings-and-expressions.md +26 -0
  236. package/skills/uipath-maestro-case/references/case-editing-operations.md +3 -0
  237. package/skills/uipath-maestro-case/references/implementation.md +11 -4
  238. package/skills/uipath-maestro-case/references/phase-0-interview.md +8 -7
  239. package/skills/uipath-maestro-case/references/phased-execution.md +2 -1
  240. package/skills/uipath-maestro-case/references/plugins/conditions/stage-exit-conditions/impl-json.md +21 -0
  241. package/skills/uipath-maestro-case/references/plugins/conditions/stage-exit-conditions/planning.md +2 -0
  242. package/skills/uipath-maestro-case/references/plugins/variables/global-vars/impl-json.md +15 -9
  243. package/skills/uipath-maestro-case/references/plugins/variables/io-binding/impl-json.md +131 -4
  244. package/skills/uipath-maestro-case/references/sdd-generation-rules.md +94 -17
  245. package/skills/uipath-maestro-flow/references/author/CAPABILITY.md +1 -1
  246. package/skills/uipath-maestro-flow/references/author/references/planning-arch.md +2 -2
  247. package/skills/uipath-maestro-flow/references/author/references/plugins/hitl/impl.md +11 -11
  248. package/skills/uipath-maestro-flow/references/author/references/plugins/hitl/planning.md +6 -6
  249. package/skills/uipath-maestro-flow/references/author/references/plugins/http/impl-connector.md +4 -1
  250. package/skills/uipath-maestro-flow/references/author/references/plugins/inline-agent/impl.md +157 -122
  251. package/skills/uipath-maestro-flow/references/author/references/plugins/inline-agent/planning.md +16 -4
  252. package/skills/uipath-maestro-flow/references/evaluate/references/commands-reference.md +8 -8
  253. package/skills/uipath-maestro-flow/references/evaluate/references/running-guide.md +3 -3
  254. package/skills/uipath-maestro-flow/references/shared/cli-commands.md +1 -1
  255. package/skills/uipath-planner/SKILL.md +19 -8
  256. package/skills/uipath-planner/assets/templates/agent-sdd-template.md +14 -0
  257. package/skills/uipath-planner/assets/templates/api-workflow-sdd-template.md +14 -0
  258. package/skills/uipath-planner/assets/templates/case-sdd-template.md +14 -0
  259. package/skills/uipath-planner/assets/templates/coded-app-sdd-template.md +14 -0
  260. package/skills/uipath-planner/assets/templates/flow-sdd-template.md +14 -0
  261. package/skills/uipath-planner/assets/templates/rpa-sdd-template.md +40 -5
  262. package/skills/uipath-planner/references/asdd-crosswalk-guide.md +55 -0
  263. package/skills/uipath-planner/references/attended-reauth-pattern-guide.md +43 -0
  264. package/skills/uipath-planner/references/multi-skill-patterns-guide.md +4 -0
  265. package/skills/uipath-planner/references/non-pdd-lane-guide.md +2 -0
  266. package/skills/uipath-planner/references/pdd-analysis-guide.md +24 -1
  267. package/skills/uipath-planner/references/pdd-driven-lane-guide.md +6 -2
  268. package/skills/uipath-planner/references/plan-and-tasks-format.md +2 -0
  269. package/skills/uipath-planner/references/platform-availability-guide.md +43 -0
  270. package/skills/uipath-planner/references/product-selection-guide.md +20 -0
  271. package/skills/uipath-planner/references/sdd-generation-guide.md +90 -21
  272. package/skills/uipath-planner/references/tenant-library-search-guide.md +5 -1
  273. package/skills/uipath-planner/scripts/docx-extract.sh +54 -0
  274. package/skills/uipath-planner/scripts/sdd-to-docx.sh +76 -0
  275. package/skills/uipath-platform/SKILL.md +54 -7
  276. package/skills/uipath-platform/references/context-grounding/index-management.md +123 -0
  277. package/skills/uipath-platform/references/data-fabric/bulk-import.md +86 -0
  278. package/skills/{uipath-data-fabric/references → uipath-platform/references/data-fabric}/choice-sets.md +33 -12
  279. package/skills/uipath-platform/references/data-fabric/data-fabric.md +352 -0
  280. package/skills/uipath-platform/references/data-fabric/entity-schema.md +444 -0
  281. package/skills/uipath-platform/references/data-fabric/file-attachments.md +122 -0
  282. package/skills/{uipath-data-fabric/references → uipath-platform/references/data-fabric}/filter-platform-contract.md +3 -3
  283. package/skills/{uipath-data-fabric/references → uipath-platform/references/data-fabric}/records-query.md +46 -10
  284. package/skills/uipath-platform/references/integration-service/http-request.md +15 -1
  285. package/skills/uipath-platform/references/integration-service/vendor-docs-registry.json +173 -0
  286. package/skills/uipath-platform/references/uip-commands.md +12 -4
  287. package/skills/uipath-review/SKILL.md +53 -12
  288. package/skills/uipath-review/references/agents/agent-common-issues.md +1 -1
  289. package/skills/uipath-review/references/agents/agent-grading-rubric.md +133 -0
  290. package/skills/uipath-review/references/agents/agent-review-checklist.md +23 -3
  291. package/skills/uipath-review/references/agents/agents-coded-rules.md +7 -0
  292. package/skills/uipath-review/references/agents/agents-lowcode-rules.md +13 -3
  293. package/skills/uipath-review/references/agents/guardrails/guardrails-review.md +198 -0
  294. package/skills/uipath-review/references/architecture-assessment-guide.md +2 -0
  295. package/skills/uipath-review/references/review-workflow-guide.md +9 -5
  296. package/skills/uipath-review/references/rule-catalog-workflow.md +3 -3
  297. package/skills/uipath-rpa/SKILL.md +18 -6
  298. package/skills/uipath-rpa/references/cli-reference.md +57 -3
  299. package/skills/uipath-rpa/references/common-activity-card.md +1 -1
  300. package/skills/uipath-rpa/references/connector-capabilities.md +2 -0
  301. package/skills/uipath-rpa/references/data-manipulation-guide.md +311 -0
  302. package/skills/uipath-rpa/references/environment-setup.md +0 -2
  303. package/skills/uipath-rpa/references/error-handling-guide.md +381 -0
  304. package/skills/uipath-rpa/references/is-connector-xaml-guide.md +127 -11
  305. package/skills/uipath-rpa/references/reframework-guide.md +2 -0
  306. package/skills/uipath-rpa/references/testing-guide.md +19 -0
  307. package/skills/uipath-rpa/references/ui-automation-guide.md +129 -18
  308. package/skills/uipath-rpa/references/uia-configure-target-workflows.md +22 -1
  309. package/skills/uipath-rpa/references/uia-elements-interaction-guide.md +93 -0
  310. package/skills/uipath-rpa/references/xaml/canvas-layout-guide.md +41 -4
  311. package/skills/uipath-rpa/references/xaml/common-pitfalls.md +12 -3
  312. package/skills/uipath-rpa/references/xaml/flowchart-guide.md +113 -0
  313. package/skills/uipath-rpa/references/xaml/xaml-basics-and-rules.md +5 -9
  314. package/skills/uipath-solution/SKILL.md +11 -8
  315. package/skills/uipath-solution/references/pack-and-deploy.md +18 -1
  316. package/skills/uipath-solution/references/solution-overview.md +3 -0
  317. package/skills/uipath-test/SKILL.md +2 -1
  318. package/skills/uipath-troubleshoot/SKILL.md +24 -26
  319. package/skills/uipath-troubleshoot/agents/depth-verifier.md +24 -25
  320. package/skills/uipath-troubleshoot/agents/hypothesis-generator.md +8 -4
  321. package/skills/uipath-troubleshoot/agents/hypothesis-tester.md +85 -38
  322. package/skills/uipath-troubleshoot/agents/presenter.md +7 -7
  323. package/skills/uipath-troubleshoot/agents/scope-checker.md +3 -6
  324. package/skills/uipath-troubleshoot/agents/shared.md +26 -21
  325. package/skills/uipath-troubleshoot/agents/triage.md +117 -49
  326. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/investigation_guide.md +43 -0
  327. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/overview.md +57 -0
  328. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/playbooks/cv-action-failed-after-find.md +100 -0
  329. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/playbooks/cv-cell-targeting-failures.md +111 -0
  330. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/playbooks/cv-element-not-found.md +125 -0
  331. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/playbooks/cv-get-text-empty-or-wrong-result.md +117 -0
  332. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/playbooks/cv-invalid-descriptor.md +102 -0
  333. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/playbooks/cv-scope-setup-failures.md +136 -0
  334. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/playbooks/cv-scroll-search-failures.md +114 -0
  335. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/playbooks/cv-server-auth-throttling-network.md +95 -0
  336. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/playbooks/cv-silent-failures-and-false-results.md +124 -0
  337. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/presentation.md +8 -0
  338. package/skills/uipath-troubleshoot/references/activity-packages/cv-activities/summary.md +15 -0
  339. package/skills/uipath-troubleshoot/references/activity-packages/database-activities/investigation_guide.md +42 -0
  340. package/skills/uipath-troubleshoot/references/activity-packages/database-activities/overview.md +41 -0
  341. package/skills/uipath-troubleshoot/references/activity-packages/database-activities/playbooks/connect-to-database-failures.md +104 -0
  342. package/skills/uipath-troubleshoot/references/activity-packages/database-activities/playbooks/execute-non-query-failures.md +97 -0
  343. package/skills/uipath-troubleshoot/references/activity-packages/database-activities/playbooks/execute-query-failures.md +134 -0
  344. package/skills/uipath-troubleshoot/references/activity-packages/database-activities/playbooks/start-transaction-failures.md +94 -0
  345. package/skills/uipath-troubleshoot/references/activity-packages/database-activities/presentation.md +10 -0
  346. package/skills/uipath-troubleshoot/references/activity-packages/database-activities/summary.md +10 -0
  347. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/investigation_guide.md +27 -9
  348. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/overview.md +51 -10
  349. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/playbooks/append-range-failures.md +146 -0
  350. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/playbooks/delete-range-failures.md +126 -0
  351. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/playbooks/excel-application-card-failures.md +139 -0
  352. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/playbooks/excel-application-scope-failures.md +118 -0
  353. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/playbooks/execute-macro-failures.md +149 -0
  354. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/playbooks/write-range-failures.md +145 -0
  355. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/presentation.md +12 -7
  356. package/skills/uipath-troubleshoot/references/activity-packages/excel-activities/summary.md +6 -0
  357. package/skills/uipath-troubleshoot/references/activity-packages/gsuite-activities/investigation_guide.md +1 -0
  358. package/skills/uipath-troubleshoot/references/activity-packages/gsuite-activities/overview.md +12 -4
  359. package/skills/uipath-troubleshoot/references/activity-packages/gsuite-activities/playbooks/connection-and-auth-failures.md +55 -0
  360. package/skills/uipath-troubleshoot/references/activity-packages/gsuite-activities/playbooks/drive-file-not-found.md +18 -10
  361. package/skills/uipath-troubleshoot/references/activity-packages/gsuite-activities/playbooks/get-newest-email-not-found.md +9 -8
  362. package/skills/uipath-troubleshoot/references/activity-packages/gsuite-activities/playbooks/invalid-or-null-input.md +68 -0
  363. package/skills/uipath-troubleshoot/references/activity-packages/gsuite-activities/playbooks/transient-and-timeout-errors.md +52 -0
  364. package/skills/uipath-troubleshoot/references/activity-packages/gsuite-activities/playbooks/upload-storage-quota-exceeded.md +1 -1
  365. package/skills/uipath-troubleshoot/references/activity-packages/gsuite-activities/summary.md +5 -2
  366. package/skills/uipath-troubleshoot/references/activity-packages/mail-activities/overview.md +28 -0
  367. package/skills/uipath-troubleshoot/references/activity-packages/mail-activities/playbooks/delete-outlook-mail-failures.md +105 -0
  368. package/skills/uipath-troubleshoot/references/activity-packages/mail-activities/playbooks/get-outlook-mail-failures.md +109 -0
  369. package/skills/uipath-troubleshoot/references/activity-packages/mail-activities/playbooks/move-outlook-mail-failures.md +97 -0
  370. package/skills/uipath-troubleshoot/references/activity-packages/mail-activities/playbooks/send-outlook-mail-failures.md +95 -0
  371. package/skills/uipath-troubleshoot/references/activity-packages/mail-activities/summary.md +8 -0
  372. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/investigation_guide.md +23 -0
  373. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/overview.md +9 -0
  374. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/application-scope-misconfigured.md +49 -0
  375. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/authentication-token-invalid.md +53 -0
  376. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/copy-item-argument-null.md +34 -0
  377. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/create-folder-invalid-path.md +36 -0
  378. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/download-file-conversion-or-destination.md +40 -0
  379. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/drive-item-not-found.md +1 -1
  380. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/email-trigger-connection-event-failure.md +45 -0
  381. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/insufficient-graph-scope.md +44 -0
  382. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/legacy-mail-null-reference.md +43 -0
  383. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/mail-folder-not-found.md +4 -3
  384. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/mail-invalid-odata-query.md +43 -0
  385. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/mail-message-not-found.md +45 -0
  386. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/request-throttled.md +45 -0
  387. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/send-mail-rejected.md +52 -0
  388. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/transient-service-error.md +48 -0
  389. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/playbooks/upload-file-quota-or-size.md +47 -0
  390. package/skills/uipath-troubleshoot/references/activity-packages/o365-activities/summary.md +15 -1
  391. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/investigation_guide.md +32 -0
  392. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/overview.md +38 -0
  393. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/playbooks/invoke-method-failures.md +57 -0
  394. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/playbooks/invoke-python-method-pipe-is-broken.md +44 -0
  395. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/playbooks/load-script-failures.md +62 -0
  396. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/playbooks/python-path-not-valid.md +39 -0
  397. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/playbooks/python-scope-architecture-version-mismatch.md +41 -0
  398. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/playbooks/working-folder-relative-path.md +34 -0
  399. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/presentation.md +9 -0
  400. package/skills/uipath-troubleshoot/references/activity-packages/python-activities/summary.md +12 -0
  401. package/skills/uipath-troubleshoot/references/activity-packages/system-activities/playbooks/get-asset-activity-bug-silent-failure.md +1 -1
  402. package/skills/uipath-troubleshoot/references/activity-packages/system-activities/playbooks/get-asset-robot-not-authenticated.md +29 -22
  403. package/skills/uipath-troubleshoot/references/activity-packages/system-activities/summary.md +1 -1
  404. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/investigation_guide.md +30 -0
  405. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/overview.md +36 -0
  406. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/playbooks/deserialize-malformed-input.md +36 -0
  407. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/playbooks/deserialize-null-input.md +35 -0
  408. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/playbooks/deserialize-type-mismatch.md +40 -0
  409. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/playbooks/http-client-null-reference.md +34 -0
  410. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/playbooks/http-request-connection-failure.md +48 -0
  411. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/playbooks/http-request-timeout.md +40 -0
  412. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/playbooks/net-http-request-aggregate-failure.md +38 -0
  413. package/skills/uipath-troubleshoot/references/activity-packages/web-activities/summary.md +13 -0
  414. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/investigation_guide.md +55 -0
  415. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/overview.md +82 -0
  416. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/add-picture-failures.md +51 -0
  417. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/append-text-missing-container.md +31 -0
  418. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/append-text-zero-byte-file.md +32 -0
  419. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/export-pdf-com-hang.md +46 -0
  420. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/export-pdf-missing-output-dir.md +32 -0
  421. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/export-pdf-output-path-format.md +35 -0
  422. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/read-text-doc-format.md +30 -0
  423. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/read-text-missing-container.md +29 -0
  424. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/read-text-protected-view.md +32 -0
  425. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/replace-text-com-busy.md +35 -0
  426. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/replace-text-file-locked.md +33 -0
  427. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/replace-text-headers-textboxes-skipped.md +30 -0
  428. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/replace-text-length-limit.md +30 -0
  429. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/replace-text-loop-template-overwrite.md +31 -0
  430. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/replace-text-multiline-formatting.md +31 -0
  431. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/replace-text-silent-no-substitution.md +32 -0
  432. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/replace-text-version-mismatch.md +30 -0
  433. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/word-com-interop-failures.md +52 -0
  434. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/word-com-start-background-session0.md +50 -0
  435. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/word-export-pdf-com-wrong-thread.md +46 -0
  436. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/word-open-sharepoint-url-com-command-failed.md +45 -0
  437. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/word-scope-cannot-create-unknown-type.md +30 -0
  438. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/word-scope-com-not-installed.md +35 -0
  439. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/word-scope-file-corrupted.md +34 -0
  440. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/word-scope-file-path-not-found.md +36 -0
  441. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/playbooks/word-scope-hangs-background-prompt.md +34 -0
  442. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/presentation.md +11 -0
  443. package/skills/uipath-troubleshoot/references/activity-packages/word-activities/summary.md +38 -0
  444. package/skills/uipath-troubleshoot/references/products/integration-service/investigation_guide.md +9 -0
  445. package/skills/uipath-troubleshoot/references/products/integration-service/overview.md +7 -0
  446. package/skills/uipath-troubleshoot/references/products/integration-service/playbooks/connection-invalid.md +9 -0
  447. package/skills/uipath-troubleshoot/references/products/integration-service/playbooks/connector-aggregate-exception.md +30 -0
  448. package/skills/uipath-troubleshoot/references/products/integration-service/playbooks/connector-general-exception.md +43 -0
  449. package/skills/uipath-troubleshoot/references/products/integration-service/playbooks/connector-null-reference.md +36 -0
  450. package/skills/uipath-troubleshoot/references/products/integration-service/playbooks/connector-remote-exception.md +31 -0
  451. package/skills/uipath-troubleshoot/references/products/integration-service/playbooks/connector-runtime-exception.md +40 -0
  452. package/skills/uipath-troubleshoot/references/products/integration-service/summary.md +5 -0
  453. package/skills/uipath-troubleshoot/references/products/maestro/investigation_guide.md +2 -1
  454. package/skills/uipath-troubleshoot/references/products/orchestrator/investigation_guide.md +105 -10
  455. package/skills/uipath-troubleshoot/references/products/orchestrator/playbooks/job-faulted-logon-failure.md +1 -1
  456. package/skills/uipath-troubleshoot/references/summary.md +59 -3
  457. package/skills/uipath-troubleshoot/schemas/evidence.schema.md +48 -0
  458. package/skills/uipath-troubleshoot/schemas/hypotheses.schema.md +22 -7
  459. package/skills/uipath-troubleshoot/schemas/scope-check.schema.md +1 -1
  460. package/skills/uipath-troubleshoot/schemas/state.schema.md +81 -6
  461. package/version-manifest.json +2 -2
  462. package/skills/uipath-data-fabric/SKILL.md +0 -239
  463. package/skills/uipath-data-fabric/references/bulk-import.md +0 -73
  464. package/skills/uipath-data-fabric/references/entity-schema.md +0 -391
  465. package/skills/uipath-data-fabric/references/file-attachments.md +0 -65
  466. package/skills/uipath-maestro-bpmn/.maintenance/README.md +0 -241
  467. package/skills/uipath-maestro-bpmn/.maintenance/check-all.sh +0 -41
  468. package/skills/uipath-maestro-bpmn/.maintenance/check-anchors.sh +0 -83
  469. package/skills/uipath-maestro-bpmn/.maintenance/check-depth.sh +0 -132
  470. package/skills/uipath-maestro-bpmn/.maintenance/check-link-text.sh +0 -123
  471. package/skills/uipath-maestro-bpmn/.maintenance/check-links.sh +0 -70
  472. package/skills/uipath-maestro-bpmn/.maintenance/check-orphans.sh +0 -93
  473. package/skills/uipath-maestro-bpmn/.maintenance/check-plugin-pairs.sh +0 -39
  474. package/skills/uipath-maestro-bpmn/.maintenance/check-real-pack.sh +0 -79
  475. package/skills/uipath-maestro-bpmn/.maintenance/check-template.sh +0 -42
  476. package/skills/uipath-maestro-bpmn/.maintenance/check-uip-commands.sh +0 -266
  477. package/skills/uipath-maestro-bpmn/.maintenance/check-validation-fixtures.py +0 -1255
  478. package/skills/uipath-maestro-bpmn/.maintenance/check-validation-fixtures.sh +0 -8
  479. package/skills/uipath-maestro-bpmn/fixtures/validation/README.md +0 -94
  480. package/skills/uipath-maestro-bpmn/fixtures/validation/agent-invocation/agent-invocation.bpmn +0 -62
  481. package/skills/uipath-maestro-bpmn/fixtures/validation/agent-invocation/bindings_v2.json +0 -37
  482. package/skills/uipath-maestro-bpmn/fixtures/validation/agent-invocation/entry-points.json +0 -21
  483. package/skills/uipath-maestro-bpmn/fixtures/validation/agent-invocation/operate.json +0 -9
  484. package/skills/uipath-maestro-bpmn/fixtures/validation/agent-invocation/package-descriptor.json +0 -10
  485. package/skills/uipath-maestro-bpmn/fixtures/validation/agent-invocation/project.uiproj +0 -7
  486. package/skills/uipath-maestro-bpmn/fixtures/validation/contract-variants/bindings_v2.json +0 -68
  487. package/skills/uipath-maestro-bpmn/fixtures/validation/contract-variants/contract-variants.bpmn +0 -270
  488. package/skills/uipath-maestro-bpmn/fixtures/validation/contract-variants/entry-points.json +0 -25
  489. package/skills/uipath-maestro-bpmn/fixtures/validation/contract-variants/operate.json +0 -9
  490. package/skills/uipath-maestro-bpmn/fixtures/validation/contract-variants/package-descriptor.json +0 -10
  491. package/skills/uipath-maestro-bpmn/fixtures/validation/contract-variants/project.uiproj +0 -7
  492. package/skills/uipath-maestro-bpmn/fixtures/validation/gateway-boundary-error/bindings_v2.json +0 -19
  493. package/skills/uipath-maestro-bpmn/fixtures/validation/gateway-boundary-error/entry-points.json +0 -25
  494. package/skills/uipath-maestro-bpmn/fixtures/validation/gateway-boundary-error/gateway-boundary-error.bpmn +0 -91
  495. package/skills/uipath-maestro-bpmn/fixtures/validation/gateway-boundary-error/operate.json +0 -9
  496. package/skills/uipath-maestro-bpmn/fixtures/validation/gateway-boundary-error/package-descriptor.json +0 -10
  497. package/skills/uipath-maestro-bpmn/fixtures/validation/gateway-boundary-error/project.uiproj +0 -7
  498. package/skills/uipath-maestro-bpmn/fixtures/validation/imported-brownfield-preservation/bindings_v2.json +0 -4
  499. package/skills/uipath-maestro-bpmn/fixtures/validation/imported-brownfield-preservation/entry-points.json +0 -25
  500. package/skills/uipath-maestro-bpmn/fixtures/validation/imported-brownfield-preservation/imported-brownfield-preservation.bpmn +0 -63
  501. package/skills/uipath-maestro-bpmn/fixtures/validation/imported-brownfield-preservation/operate.json +0 -9
  502. package/skills/uipath-maestro-bpmn/fixtures/validation/imported-brownfield-preservation/package-descriptor.json +0 -10
  503. package/skills/uipath-maestro-bpmn/fixtures/validation/imported-brownfield-preservation/project.uiproj +0 -7
  504. package/skills/uipath-maestro-bpmn/fixtures/validation/integration-service-enriched/bindings_v2.json +0 -52
  505. package/skills/uipath-maestro-bpmn/fixtures/validation/integration-service-enriched/entry-points.json +0 -21
  506. package/skills/uipath-maestro-bpmn/fixtures/validation/integration-service-enriched/integration-service-enriched.bpmn +0 -65
  507. package/skills/uipath-maestro-bpmn/fixtures/validation/integration-service-enriched/operate.json +0 -9
  508. package/skills/uipath-maestro-bpmn/fixtures/validation/integration-service-enriched/package-descriptor.json +0 -10
  509. package/skills/uipath-maestro-bpmn/fixtures/validation/integration-service-enriched/project.uiproj +0 -7
  510. package/skills/uipath-maestro-bpmn/fixtures/validation/linear-process/bindings_v2.json +0 -4
  511. package/skills/uipath-maestro-bpmn/fixtures/validation/linear-process/entry-points.json +0 -25
  512. package/skills/uipath-maestro-bpmn/fixtures/validation/linear-process/linear-process.bpmn +0 -55
  513. package/skills/uipath-maestro-bpmn/fixtures/validation/linear-process/operate.json +0 -9
  514. package/skills/uipath-maestro-bpmn/fixtures/validation/linear-process/package-descriptor.json +0 -10
  515. package/skills/uipath-maestro-bpmn/fixtures/validation/linear-process/project.uiproj +0 -7
  516. package/skills/uipath-maestro-bpmn/fixtures/validation/registry-coverage-matrix/bindings_v2.json +0 -20
  517. package/skills/uipath-maestro-bpmn/fixtures/validation/registry-coverage-matrix/entry-points.json +0 -17
  518. package/skills/uipath-maestro-bpmn/fixtures/validation/registry-coverage-matrix/operate.json +0 -9
  519. package/skills/uipath-maestro-bpmn/fixtures/validation/registry-coverage-matrix/package-descriptor.json +0 -10
  520. package/skills/uipath-maestro-bpmn/fixtures/validation/registry-coverage-matrix/project.uiproj +0 -7
  521. package/skills/uipath-maestro-bpmn/fixtures/validation/registry-coverage-matrix/registry-coverage-matrix.bpmn +0 -207
  522. package/skills/uipath-maestro-bpmn/fixtures/validation/subprocess-multi-instance/bindings_v2.json +0 -4
  523. package/skills/uipath-maestro-bpmn/fixtures/validation/subprocess-multi-instance/entry-points.json +0 -33
  524. package/skills/uipath-maestro-bpmn/fixtures/validation/subprocess-multi-instance/operate.json +0 -9
  525. package/skills/uipath-maestro-bpmn/fixtures/validation/subprocess-multi-instance/package-descriptor.json +0 -10
  526. package/skills/uipath-maestro-bpmn/fixtures/validation/subprocess-multi-instance/project.uiproj +0 -7
  527. package/skills/uipath-maestro-bpmn/fixtures/validation/subprocess-multi-instance/subprocess-multi-instance.bpmn +0 -94
  528. package/skills/uipath-maestro-bpmn/fixtures/validation/wrapper-family-contract/bindings_v2.json +0 -124
  529. package/skills/uipath-maestro-bpmn/fixtures/validation/wrapper-family-contract/entry-points.json +0 -25
  530. package/skills/uipath-maestro-bpmn/fixtures/validation/wrapper-family-contract/operate.json +0 -9
  531. package/skills/uipath-maestro-bpmn/fixtures/validation/wrapper-family-contract/package-descriptor.json +0 -10
  532. package/skills/uipath-maestro-bpmn/fixtures/validation/wrapper-family-contract/project.uiproj +0 -7
  533. package/skills/uipath-maestro-bpmn/fixtures/validation/wrapper-family-contract/wrapper-family-contract.bpmn +0 -151
  534. package/skills/uipath-maestro-bpmn/references/author/CAPABILITY.md +0 -141
  535. package/skills/uipath-maestro-bpmn/references/author/references/brownfield.md +0 -48
  536. package/skills/uipath-maestro-bpmn/references/author/references/editing-operations.md +0 -75
  537. package/skills/uipath-maestro-bpmn/references/author/references/greenfield.md +0 -41
  538. package/skills/uipath-maestro-bpmn/references/author/references/planning-arch.md +0 -82
  539. package/skills/uipath-maestro-bpmn/references/author/references/planning-impl.md +0 -104
  540. package/skills/uipath-maestro-bpmn/references/author/references/plugins/agents/impl.md +0 -34
  541. package/skills/uipath-maestro-bpmn/references/author/references/plugins/agents/planning.md +0 -38
  542. package/skills/uipath-maestro-bpmn/references/author/references/plugins/api-workflows/impl.md +0 -37
  543. package/skills/uipath-maestro-bpmn/references/author/references/plugins/api-workflows/planning.md +0 -28
  544. package/skills/uipath-maestro-bpmn/references/author/references/plugins/business-rules/impl.md +0 -36
  545. package/skills/uipath-maestro-bpmn/references/author/references/plugins/business-rules/planning.md +0 -29
  546. package/skills/uipath-maestro-bpmn/references/author/references/plugins/call-activity-subprocess/impl.md +0 -67
  547. package/skills/uipath-maestro-bpmn/references/author/references/plugins/call-activity-subprocess/planning.md +0 -29
  548. package/skills/uipath-maestro-bpmn/references/author/references/plugins/connectors/impl.md +0 -29
  549. package/skills/uipath-maestro-bpmn/references/author/references/plugins/connectors/planning.md +0 -33
  550. package/skills/uipath-maestro-bpmn/references/author/references/plugins/gateways/impl.md +0 -32
  551. package/skills/uipath-maestro-bpmn/references/author/references/plugins/gateways/planning.md +0 -34
  552. package/skills/uipath-maestro-bpmn/references/author/references/plugins/hitl/impl.md +0 -42
  553. package/skills/uipath-maestro-bpmn/references/author/references/plugins/hitl/planning.md +0 -30
  554. package/skills/uipath-maestro-bpmn/references/author/references/plugins/integration-service/impl.md +0 -134
  555. package/skills/uipath-maestro-bpmn/references/author/references/plugins/integration-service/planning.md +0 -67
  556. package/skills/uipath-maestro-bpmn/references/author/references/plugins/multi-instance/impl.md +0 -50
  557. package/skills/uipath-maestro-bpmn/references/author/references/plugins/multi-instance/planning.md +0 -29
  558. package/skills/uipath-maestro-bpmn/references/author/references/plugins/queues/impl.md +0 -29
  559. package/skills/uipath-maestro-bpmn/references/author/references/plugins/queues/planning.md +0 -29
  560. package/skills/uipath-maestro-bpmn/references/author/references/plugins/rpa-jobs/impl.md +0 -35
  561. package/skills/uipath-maestro-bpmn/references/author/references/plugins/rpa-jobs/planning.md +0 -29
  562. package/skills/uipath-maestro-bpmn/references/author/references/plugins/script/impl.md +0 -118
  563. package/skills/uipath-maestro-bpmn/references/author/references/plugins/script/planning.md +0 -30
  564. package/skills/uipath-maestro-bpmn/references/author/references/plugins/sequence-flows/impl.md +0 -30
  565. package/skills/uipath-maestro-bpmn/references/author/references/plugins/sequence-flows/planning.md +0 -30
  566. package/skills/uipath-maestro-bpmn/references/author/references/plugins/service-tasks/impl.md +0 -33
  567. package/skills/uipath-maestro-bpmn/references/author/references/plugins/service-tasks/planning.md +0 -31
  568. package/skills/uipath-maestro-bpmn/references/author/references/plugins/signals/impl.md +0 -33
  569. package/skills/uipath-maestro-bpmn/references/author/references/plugins/signals/planning.md +0 -46
  570. package/skills/uipath-maestro-bpmn/references/author/references/plugins/start-end-events/impl.md +0 -59
  571. package/skills/uipath-maestro-bpmn/references/author/references/plugins/start-end-events/planning.md +0 -37
  572. package/skills/uipath-maestro-bpmn/references/author/references/plugins/waits-triggers/impl.md +0 -40
  573. package/skills/uipath-maestro-bpmn/references/author/references/plugins/waits-triggers/planning.md +0 -34
  574. package/skills/uipath-maestro-bpmn/references/author/references/supported-elements.md +0 -123
  575. package/skills/uipath-maestro-bpmn/references/author/references/task-recipes/README.md +0 -29
  576. package/skills/uipath-maestro-bpmn/references/author/references/task-recipes/agent-job.md +0 -36
  577. package/skills/uipath-maestro-bpmn/references/author/references/task-recipes/api-workflow.md +0 -29
  578. package/skills/uipath-maestro-bpmn/references/author/references/task-recipes/business-rule.md +0 -18
  579. package/skills/uipath-maestro-bpmn/references/author/references/task-recipes/call-activity.md +0 -56
  580. package/skills/uipath-maestro-bpmn/references/author/references/task-recipes/hitl.md +0 -17
  581. package/skills/uipath-maestro-bpmn/references/author/references/task-recipes/http-request.md +0 -119
  582. package/skills/uipath-maestro-bpmn/references/author/references/task-recipes/queue.md +0 -21
  583. package/skills/uipath-maestro-bpmn/references/author/references/task-recipes/rpa-job.md +0 -23
  584. package/skills/uipath-maestro-bpmn/references/author/references/validation.md +0 -118
  585. package/skills/uipath-maestro-bpmn/references/shared/bpmn-xml-contract.md +0 -197
  586. package/skills/uipath-maestro-bpmn/references/shared/cli-conventions.md +0 -46
  587. package/skills/uipath-maestro-bpmn/references/shared/error-handling.md +0 -82
  588. package/skills/uipath-maestro-bpmn/references/shared/variables-bindings-expressions.md +0 -150
  589. package/skills/uipath-maestro-bpmn/references/shared/wrapper-shells.md +0 -554
  590. /package/skills/uipath-maestro-bpmn/references/{shared/expression-authoring.md → expression-authoring.md} +0 -0
  591. /package/skills/uipath-maestro-bpmn/references/{shared/public-safety.md → public-safety.md} +0 -0
  592. /package/{agents → skills/uipath-rpa/agents}/uipath-project-discovery-agent.md +0 -0
@@ -0,0 +1,1371 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * build-dashboard.mjs — Dashboard build pipeline
4
+ *
5
+ * Accepts an intent.json or edit-intent.json as a file path argument and
6
+ * generates a complete React dashboard project.
7
+ *
8
+ * Input routing:
9
+ * intent.json (has "metrics" field) → runDashboardBuild()
10
+ * edit-intent.json (has "op" field) → runIncrementalEdit()
11
+ *
12
+ * Usage:
13
+ * node build-dashboard.mjs <path-to-json>
14
+ *
15
+ * Exit codes:
16
+ * 0 — success
17
+ * 1 — fatal error (message on stderr)
18
+ * 2 — metric modules need retry (fix the named metrics/<name>.ts files and re-run)
19
+ */
20
+
21
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, renameSync, unlinkSync } from 'fs'
22
+ import { join, dirname, resolve } from 'path'
23
+ import { fileURLToPath, pathToFileURL } from 'url'
24
+ import { execSync } from 'child_process'
25
+ import { createHash } from 'crypto'
26
+ // Project-lifecycle utilities (versioning, prewarm, sdk-check, dev-server teardown)
27
+ // live in a sibling module. Imported for internal use here; the test-facing ones are
28
+ // re-exported so `import … from build-dashboard.mjs` keeps working. (Benign runtime
29
+ // import cycle — lifecycle.mjs imports primitives/consts back, used only at call time.)
30
+ import {
31
+ readScaffoldVersion, buildVersions, scaffoldDrift, runIntentMigrations, runPrewarm,
32
+ } from './lifecycle.mjs'
33
+ export { readScaffoldVersion, buildVersions, scaffoldDrift, runIntentMigrations }
34
+
35
+ // Use-case flow orchestrators (extracted to ./flows/*). Imported here for the
36
+ // entry-point dispatcher; packTemplate is also re-exported (tests import it from
37
+ // this module). Benign cycle: the flows import shared primitives back from here,
38
+ // referenced only inside their function bodies (call time), never at module eval.
39
+ import { runDashboardBuild } from './flows/build.mjs'
40
+ import { runIncrementalEdit } from './flows/edit.mjs'
41
+ import { packTemplate } from './flows/template.mjs'
42
+ export { packTemplate }
43
+
44
+ // ── Path constants ─────────────────────────────────────────────────────────────
45
+
46
+ const __dirname = dirname(fileURLToPath(import.meta.url))
47
+
48
+ // Widget generator templates ship INSIDE the starter-kit archive (under _gen/widgets),
49
+ // not in the skill — the skill carries no scaffold/template source and no zip code.
50
+ // The orchestration points this at <project>/_gen/widgets after the agent extracts
51
+ // the kit; tests set it via setWidgetsDir(). null until set.
52
+ let WIDGETS_DIR = null
53
+ export function setWidgetsDir(dir) { WIDGETS_DIR = dir }
54
+ function widgetsDir() {
55
+ if (!WIDGETS_DIR) fail('Widget templates dir not set — extract the starter kit (assertScaffoldExtracted) before generating widgets.')
56
+ return WIDGETS_DIR
57
+ }
58
+ function t3ShellTemplatePath() { return join(widgetsDir(), 't3-shell.tsx.template') }
59
+
60
+ /**
61
+ * Fixed dev server port. Kept BELOW the ephemeral ranges (Linux 32768+, Windows/macOS
62
+ * 49152+) so it can't land in an OS-reserved block — Windows (WinNAT/Hyper-V/WSL2)
63
+ * carves reserved chunks out of the ephemeral range, and a dev server can't bind one
64
+ * even when it's free (`An attempt was made to access a socket in a way forbidden by
65
+ * its access permissions`). 25173 is high enough to dodge common dev servers yet clear
66
+ * of every ephemeral range. Must match the scaffold's vite.config.ts `server.port`.
67
+ */
68
+ export const DASHBOARD_PORT = 25173
69
+
70
+ // ── Capability registry ────────────────────────────────────────────────────────
71
+
72
+ const REGISTRY = JSON.parse(readFileSync(resolve(__dirname, 'capability-registry.json'), 'utf8'))
73
+
74
+ // ── Type definitions (JSDoc only — this file is plain JavaScript) ────────────
75
+
76
+ /**
77
+ * @typedef {'T1'|'T2'|'T3'} MetricTier
78
+ */
79
+
80
+ /**
81
+ * A single metric entry inside intent.json.
82
+ * @typedef {Object} IntentMetric
83
+ * @property {string} name - Kebab-case metric identifier
84
+ * @property {MetricTier} tier - Resolution tier
85
+ * @property {string} [title] - Display title (required for all tiers)
86
+ * @property {string} [subtitle] - CardDescription line; auto-filled from time range when absent
87
+ * @property {string} [description] - Fallback for subtitle
88
+ * @property {string} [componentName] - Override PascalCase component name
89
+ * @property {string} [icon] - lucide-react icon name
90
+ * @property {string} [detailRoute] - HashRouter path for drilldown
91
+ * @property {Object} [params] - T2 filter params (validation only — the filter logic lives in the metric module)
92
+ * @property {string} [module] - Relative path to the metric's data-fetch module (defaults to metrics/<name>.ts)
93
+ * @property {string} [displayAs] - One of VALID_DISPLAY_TYPES
94
+ * @property {string} [valueField] - kpi-card: field shown as the headline number
95
+ * @property {string} [valueLabel] - kpi-card: label under the headline
96
+ * @property {string} [xKey] - Chart x-axis field
97
+ * @property {string} [yKey] - Chart value field
98
+ * @property {string} [headlineMode] - VALID_HEADLINE_MODES — how the chart headline aggregates
99
+ * @property {string} [deltaPolarity] - VALID_DELTA_POLARITIES — is an increase good?
100
+ * @property {string} [rateNum] - rate-chart: numerator field per bucket
101
+ * @property {string} [rateDen] - rate-chart: denominator field per bucket
102
+ * @property {string} [columns] - ColumnDef array literal string (tables)
103
+ * @property {Array<{key:string,label:string,align?:string,format?:string,color?:string}>} [columnDefs] - Structured columns; compiled to formatted/coloured cells
104
+ * @property {boolean} [detail] - kpi-card only: opt into a record-grain drill-down (module must export fetchDetail)
105
+ * @property {Array} [detailColumns] - Structured columns for the detail view (falls back to registry defaults.detailColumns)
106
+ * @property {string} [detailSortKey] - Raw field the detail table sorts on
107
+ * @property {string} [series] - multi-line-chart series literal
108
+ * @property {string} [pivotExpression] - multi-line-chart pivot expression
109
+ * @property {DetailViewSpec} [detailView]
110
+ * @property {{key:string}} [rowLink]
111
+ */
112
+
113
+ /**
114
+ * The full intent.json structure.
115
+ * @typedef {Object} DashboardIntent
116
+ * @property {string} dashboardName
117
+ * @property {string} [dashboardDescription] - One sentence for the dashboard header
118
+ * @property {'1d'|'7d'|'30d'|'90d'} timeRange
119
+ * @property {IntentMetric[]} metrics
120
+ * @property {string} projectDir - Project dir; "." by contract (build runs from inside the pre-warmed <routingName> folder; must already exist)
121
+ * @property {string} routingName - Permanent URL slug (e.g. "agent-health-x7k2")
122
+ * @property {string} orgName
123
+ * @property {string} tenantName
124
+ * @property {string} cloudUrl - e.g. https://alpha.uipath.com
125
+ * @property {string} apiUrl - e.g. https://alpha.api.uipath.com
126
+ * @property {string} [clientId] - External OAuth app client ID
127
+ */
128
+
129
+ /**
130
+ * Derived chart-widget spec — all fields resolved, ready for template substitution.
131
+ * @typedef {Object} WidgetSpec
132
+ * @property {string} componentName
133
+ * @property {string} template
134
+ * @property {string} title
135
+ * @property {string} subtitle
136
+ * @property {string} icon
137
+ * @property {string} detailRoute
138
+ * @property {string} dataHook
139
+ * @property {string} dataSelector
140
+ * @property {string} xKey
141
+ * @property {string} yKey
142
+ * @property {string} headlineMode
143
+ * @property {string} deltaPolarity
144
+ * @property {string} rateNum
145
+ * @property {string} rateDen
146
+ * @property {string} series
147
+ * @property {string} pivotExpression
148
+ */
149
+
150
+ /**
151
+ * Minimal widget descriptor used for layout classification.
152
+ * @typedef {Object} WidgetMeta
153
+ * @property {string} componentName
154
+ * @property {string} template
155
+ */
156
+
157
+ /**
158
+ * Per-widget entry persisted in state.json.
159
+ * @typedef {Object} WidgetHashEntry
160
+ * @property {string} hash - SHA-256 prefix of generated file content
161
+ * @property {MetricTier} tier
162
+ * @property {string} metric - Original metric name from intent
163
+ * @property {string} template - Template used for layout classification
164
+ * @property {IntentMetric} intentMetric - Full intent entry, persisted for CHANGE/REBUILD
165
+ */
166
+
167
+ // ── Constants ──────────────────────────────────────────────────────────────────
168
+
169
+ const TIME_RANGE_CONSTANTS = {
170
+ '1d': 'ONE_DAY_AGO',
171
+ '7d': 'SEVEN_DAYS_AGO',
172
+ '30d': 'THIRTY_DAYS_AGO',
173
+ '90d': 'NINETY_DAYS_AGO',
174
+ }
175
+
176
+ const KNOWN_EVENTS = new Set([
177
+ 'PREWARM_START', 'PREWARM_DONE', 'PREWARM_FAILED', 'SCAFFOLD_READY', 'ENV_WRITTEN',
178
+ 'WIDGET_READY', 'METRICS_PASS', 'METRICS_RETRY', 'CHART_DETAIL_MISSING', 'T3_FAILED', 'TSC_PASS', 'TSC_FAIL',
179
+ 'BUILD_RESULT', 'PARTIAL_BUILD_DETECTED', 'AUTH_MISSING',
180
+ 'HAND_EDIT_DETECTED', 'T2_SCHEMA_ERROR', 'INCREMENTAL_READY', 'UPGRADE_AVAILABLE', 'UPGRADE_DONE',
181
+ 'TEMPLATE_BUILD', 'EJECTED', 'EJECTED_PROJECT', 'TEMPLATE_PACKED',
182
+ ])
183
+
184
+ export const VALID_EDIT_OPS = ['ADD', 'REMOVE', 'CHANGE', 'REBUILD', 'UPGRADE', 'EJECT']
185
+
186
+ /**
187
+ * Display types supported for all widget tiers.
188
+ * Table/KPI types use t3-shell.tsx.template.
189
+ * Chart types use the standard chart templates with customDataFn injected.
190
+ */
191
+ export const VALID_DISPLAY_TYPES = [
192
+ 'kpi-card', 'ranked-table', 'data-table',
193
+ 'area-chart', 'line-chart', 'bar-chart', 'donut-chart', 'multi-line-chart', 'rate-chart',
194
+ ]
195
+
196
+ /** Detail-view sub-widget displayAs vocabularies (rich drill-down). */
197
+ const DETAIL_CHART_TYPES = new Set(['donut-chart', 'bar-chart', 'area-chart', 'line-chart', 'multi-line-chart'])
198
+ const DETAIL_TABLE_TYPES = new Set(['data-table', 'ranked-table'])
199
+
200
+ /**
201
+ * @typedef {Object} DetailViewWidget
202
+ * @property {'donut-chart'|'bar-chart'|'area-chart'|'line-chart'|'multi-line-chart'|'data-table'|'ranked-table'} displayAs
203
+ * @property {string} title
204
+ * @property {string} source Key into the detail fetch's named-source map.
205
+ * @property {string} [xKey]
206
+ * @property {string} [yKey]
207
+ * @property {Array<{key:string,color:string}>} [series] Required for multi-line-chart.
208
+ * @property {Array<object>} [columns] Table column defs.
209
+ */
210
+ /**
211
+ * @typedef {Object} DetailViewSpec
212
+ * @property {DetailViewWidget[]} widgets
213
+ */
214
+ /** Validate a metric's optional detailView spec. Throws with a precise message. */
215
+ export function validateDetailView(metric) {
216
+ const dv = metric.detailView
217
+ if (dv == null) return
218
+ if (!metric.rowLink?.key && metric.detail !== true) {
219
+ throw new Error(`metric "${metric.name}": detailView requires the metric to have rowLink.key (table) or detail:true (chart)`)
220
+ }
221
+ if (!Array.isArray(dv.widgets) || dv.widgets.length === 0) {
222
+ throw new Error(`metric "${metric.name}": detailView.widgets must be a non-empty array`)
223
+ }
224
+ for (const w of dv.widgets) {
225
+ if (!w.source || typeof w.source !== 'string') throw new Error(`metric "${metric.name}": each detailView widget needs a "source" string`)
226
+ if (!w.title) throw new Error(`metric "${metric.name}": detailView widget (source "${w.source}") needs a title`)
227
+ const isChart = DETAIL_CHART_TYPES.has(w.displayAs)
228
+ const isTable = DETAIL_TABLE_TYPES.has(w.displayAs)
229
+ if (!isChart && !isTable) throw new Error(`metric "${metric.name}": detailView widget displayAs "${w.displayAs}" invalid`)
230
+ if (w.displayAs === 'multi-line-chart') {
231
+ if (!w.xKey || !Array.isArray(w.series) || w.series.length === 0) throw new Error(`metric "${metric.name}": detailView multi-line-chart needs xKey + series[]`)
232
+ } else if (isChart) {
233
+ if (!w.xKey || !w.yKey) throw new Error(`metric "${metric.name}": detailView ${w.displayAs} needs xKey and yKey`)
234
+ }
235
+ }
236
+ }
237
+
238
+ /** Headline aggregate modes — how a chart's big number is computed from its series. */
239
+ export const VALID_HEADLINE_MODES = ['sum', 'avg', 'latest', 'count', 'max', 'min']
240
+
241
+ /** Delta polarity — whether an increase is good, bad, or neutral (drives badge colour). */
242
+ export const VALID_DELTA_POLARITIES = ['up-good', 'up-bad', 'neutral']
243
+
244
+ /** Column value formatters supported in table column defs. */
245
+ export const VALID_COLUMN_FORMATS = ['number', 'percent', 'duration', 'timeAgo', 'text']
246
+
247
+ /**
248
+ * Minimum SDK version the catalog metrics require — the agent-memory and
249
+ * governance subpaths ship in 1.4.1; the Agents insights aggregates
250
+ * (getSummary / getTopErrorCount / getTopConsumption / getIncidentDistribution
251
+ * / getUnitConsumptionSummary) ship in 1.5.0. A stale lockfile/registry
252
+ * otherwise surfaces as cryptic tsc "module not found" failures mid-build.
253
+ */
254
+ export const MIN_SDK_VERSION = '1.5.1'
255
+
256
+ export const SKILL_VERSION = '2.2.0' // 2.2 = runtime governance on AgentTraces getGovernanceDecisions/getGovernanceSummary (SDK 1.5.1)
257
+ const FIXTURE_ARCHIVE_PATH = resolve(__dirname, '../../fixtures/governance-dashboard-starter-kit.tar.gz')
258
+
259
+ export const INTENT_SCHEMA_VERSION = 2
260
+ export const STATE_SCHEMA_VERSION = 2
261
+
262
+ /**
263
+ * Generate (or remove) a table widget's keyed row-click detail view. Writes
264
+ * <Component>DetailView.tsx when the metric is a table with `rowLink`, and removes
265
+ * a stale one otherwise. Shared by fresh build, ADD, CHANGE, REBUILD, and upgrade so
266
+ * the row-click drill-down stays consistent on every path. Returns true if a keyed
267
+ * view now exists on disk.
268
+ * @returns {boolean}
269
+ */
270
+ export function writeKeyedViewIfRowLink(P, componentName, metric, entry, timeRange) {
271
+ const detailPath = join(P, 'src', 'dashboard', 'views', `${componentName}DetailView.tsx`)
272
+ const displayAs = metric.displayAs ?? entry?.template ?? ''
273
+ // rowLink and detailView fall back to the registry entry's defaults — same as
274
+ // title/columns — so a cataloged metric (e.g. agent-compliance-report) ships its
275
+ // drill-down without the intent having to restate it.
276
+ const rowLink = metric.rowLink ?? entry?.defaults?.rowLink
277
+ const detailView = metric.detailView ?? entry?.defaults?.detailView ?? null
278
+ if (rowLink?.key && widgetLayoutGroup(displayAs) === 'table') {
279
+ writeAtomic(detailPath, generateKeyedDetailViewFile({
280
+ componentName,
281
+ title: metric.title ?? entry?.defaults?.title ?? componentName,
282
+ subtitle: autoSubtitle(metric, entry?.defaults ?? {}, timeRange),
283
+ moduleSpecifier: metricModuleSpecifier(metric),
284
+ detailColumns: metric.detailColumns ? compileColumns(metric.detailColumns) : null,
285
+ detailView,
286
+ }))
287
+ return true
288
+ }
289
+ if (existsSync(detailPath)) unlinkSync(detailPath)
290
+ return false
291
+ }
292
+
293
+ /** Route descriptors for every widget that currently has a keyed DetailView file on disk. */
294
+ export function collectKeyedViews(P, state) {
295
+ return Object.keys(state.widgets ?? {})
296
+ .filter(name => existsSync(join(P, 'src', 'dashboard', 'views', `${name}DetailView.tsx`)))
297
+ .map(name => ({ componentName: name, routeBase: `/${name.toLowerCase()}` }))
298
+ }
299
+
300
+ /**
301
+ * Regenerate every widget + chart view from each widget's persisted intentMetric
302
+ * (metadata) against the on-disk metric modules. Used by the REBUILD op and by upgrade.
303
+ * @param {string} P resolved project dir
304
+ * @param {object} state parsed state.json (widget hashes refreshed in place)
305
+ * @param {string} timeRange
306
+ */
307
+ export function rebuildAllWidgets(P, state, timeRange) {
308
+ for (const [componentName, info] of Object.entries(state.widgets ?? {})) {
309
+ const m = info.intentMetric
310
+ if (!m) {
311
+ log(`⚠ Cannot rebuild "${componentName}" — built before intent persistence. Re-run a fresh build to refresh it.`)
312
+ continue
313
+ }
314
+ const { entry } = resolveMetric(m)
315
+ const content = buildWidgetFile(m, entry, timeRange)
316
+ writeAtomic(join(P, 'src', 'dashboard', 'widgets', `${componentName}.tsx`), content)
317
+ info.hash = hashContent(content)
318
+ const viewPath = join(P, 'src', 'dashboard', 'views', `${componentName}View.tsx`)
319
+ if (widgetGetsDetailView(info.template ?? '', m, entry)) {
320
+ writeAtomic(viewPath, generateViewFile(buildViewSpec(componentName, m, entry, timeRange)))
321
+ } else if (existsSync(viewPath)) {
322
+ unlinkSync(viewPath)
323
+ }
324
+ writeKeyedViewIfRowLink(P, componentName, m, entry, timeRange)
325
+ }
326
+ }
327
+
328
+
329
+ /** Map a time range to a human subtitle fragment. */
330
+ function timeRangeLabel(timeRange) {
331
+ return { '1d': 'last 24 hours', '7d': 'last 7 days', '30d': 'last 30 days', '90d': 'last 90 days' }[timeRange] ?? timeRange
332
+ }
333
+
334
+ /**
335
+ * OAuth scopes required for the dashboard.
336
+ * These MUST match what is registered on the external OAuth app.
337
+ * Use parent scopes only — .Read sub-scopes are not reliably registered.
338
+ */
339
+ export const DASHBOARD_SCOPES = 'OR.Assets OR.Jobs OR.Folders OR.Buckets OR.Execution OR.Tasks OR.Queues OR.Users Insights Insights.RealTimeData Traces.Api PIMS'
340
+
341
+ // ── Low-level utilities ────────────────────────────────────────────────────────
342
+
343
+ export function fail(msg) {
344
+ process.stderr.write(`ERROR: ${msg}\n`)
345
+ process.exit(1)
346
+ }
347
+
348
+ export function log(msg) {
349
+ process.stdout.write(msg + '\n')
350
+ }
351
+
352
+ /**
353
+ * The agent extracts the starter-kit .tar.gz into the project dir before building,
354
+ * using the OS `tar` (built into Windows 10+, macOS, Linux). This verifies the kit
355
+ * landed (scaffold app + the _gen/widgets generator templates) and fails loud with
356
+ * the extract command if not.
357
+ * @param {string} projectPath
358
+ */
359
+ export function assertScaffoldExtracted(projectPath) {
360
+ const hasScaffold = existsSync(join(projectPath, 'package.json'))
361
+ const hasTemplates = existsSync(join(projectPath, '_gen', 'widgets'))
362
+ if (hasScaffold && hasTemplates) return
363
+ fail([
364
+ `Starter kit not extracted into: ${projectPath}`,
365
+ `Extract it first with tar (built into Windows 10+, macOS, Linux).`,
366
+ `Feed the archive on stdin (-f -) so GNU tar doesn't misread the C:\\ drive colon as a remote host:`,
367
+ ` mkdir -p "${projectPath}" && tar -xz -C "${projectPath}" -f - < "${FIXTURE_ARCHIVE_PATH}"`,
368
+ `Then re-run the build.`,
369
+ ].join('\n'))
370
+ }
371
+
372
+ /**
373
+ * Atomic file write — write to .tmp then rename on success.
374
+ *
375
+ * On Windows the rename can fail with EPERM/EBUSY when a watcher (e.g. the Vite
376
+ * dev server during a REBUILD) holds the target file open. Retry the rename a
377
+ * few times with a short backoff, then fall back to a direct overwrite so the
378
+ * write still lands. A scoped CHANGE op touches one file and rarely races; a
379
+ * full REBUILD rewrites every widget — prefer stopping the dev server first.
380
+ */
381
+ export function writeAtomic(filePath, content) {
382
+ mkdirSync(dirname(filePath), { recursive: true })
383
+ const tmp = filePath + '.tmp'
384
+ writeFileSync(tmp, content, 'utf8')
385
+ const RETRYABLE = new Set(['EPERM', 'EBUSY', 'EACCES'])
386
+ for (let attempt = 0; ; attempt++) {
387
+ try {
388
+ renameSync(tmp, filePath)
389
+ return
390
+ } catch (err) {
391
+ if (!RETRYABLE.has(err?.code) || attempt >= 4) {
392
+ // Out of retries (or a non-lock error): overwrite in place so the new
393
+ // content still lands, then drop the tmp. Less atomic, but a held-open
394
+ // widget file would otherwise block the whole build.
395
+ try {
396
+ writeFileSync(filePath, content, 'utf8')
397
+ try { unlinkSync(tmp) } catch { /* ignore */ }
398
+ return
399
+ } catch {
400
+ throw err
401
+ }
402
+ }
403
+ // Busy-wait briefly (sync context): 50ms · 100ms · 150ms · 200ms.
404
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 50 * (attempt + 1))
405
+ }
406
+ }
407
+ }
408
+
409
+ export function hashContent(content) {
410
+ return createHash('sha256').update(content).digest('hex').slice(0, 16)
411
+ }
412
+
413
+ export function toPascalCase(str) {
414
+ return str.split('-').map(w => w[0].toUpperCase() + w.slice(1)).join('')
415
+ }
416
+
417
+ // ── Pre-warm ───────────────────────────────────────────────────────────────────
418
+
419
+ /**
420
+ * Stage A — isolated type-check of the agent-written metric modules, before any
421
+ * widget is generated. Fast (no React graph) and maps errors directly to the
422
+ * offending src/metrics/<name>.ts file.
423
+ * @param {string} projectPath
424
+ * @returns {{ ok: true } | { ok: false, errors: string[], files: string[] }}
425
+ */
426
+ export function runMetricsTypecheck(projectPath) {
427
+ try {
428
+ execSync('npx tsc -p tsconfig.metrics.json', { cwd: projectPath, stdio: 'pipe' })
429
+ return { ok: true }
430
+ } catch (e) {
431
+ const out = (e.stdout?.toString() ?? '') + (e.stderr?.toString() ?? '')
432
+ const errors = out.split('\n').filter(l => l.includes('error TS')).slice(0, 20)
433
+ const files = [...new Set((out.match(/src[/\\]metrics[/\\][\w-]+\.ts/g) ?? []).map(p => p.replace(/\\/g, '/')))]
434
+ return { ok: false, errors, files }
435
+ }
436
+ }
437
+
438
+ // ── Event streaming ────────────────────────────────────────────────────────────
439
+
440
+ /**
441
+ * Emit a structured event line to stdout (or a custom writer for testing).
442
+ * @param {string} type - Must be one of KNOWN_EVENTS
443
+ * @param {object|null} [payload=null]
444
+ * @param {{ write: (s: string) => void }} [writer=process.stdout]
445
+ */
446
+ export function emit(type, payload = null, writer = process.stdout) {
447
+ const line = payload != null ? `${type}:${JSON.stringify(payload)}` : type
448
+ writer.write(line + '\n')
449
+ }
450
+
451
+ /**
452
+ * Parse a stdout line back to a structured event, or null if not a known event.
453
+ * @param {string} line
454
+ * @returns {{ type: string, payload: object|null }|null}
455
+ */
456
+ export function parseEvent(line) {
457
+ const trimmed = line.trim()
458
+ const colonIdx = trimmed.indexOf(':')
459
+ if (colonIdx === -1) {
460
+ return KNOWN_EVENTS.has(trimmed) ? { type: trimmed, payload: null } : null
461
+ }
462
+ const type = trimmed.slice(0, colonIdx)
463
+ if (!KNOWN_EVENTS.has(type)) return null
464
+ try {
465
+ return { type, payload: JSON.parse(trimmed.slice(colonIdx + 1)) }
466
+ } catch {
467
+ return null
468
+ }
469
+ }
470
+
471
+ // ── Template helpers ───────────────────────────────────────────────────────────
472
+
473
+ /**
474
+ * Load a widget template and apply <PLACEHOLDER> substitutions.
475
+ * Injects time constants after the last import line.
476
+ * @param {string} templateName
477
+ * @param {Record<string, string>} subs
478
+ * @returns {string}
479
+ */
480
+ function applyTemplate(templateName, subs) {
481
+ const templatePath = join(widgetsDir(), `${templateName}.tsx`)
482
+ if (!existsSync(templatePath)) fail(`Template not found: ${templateName}.tsx in ${widgetsDir()}`)
483
+ let content = readFileSync(templatePath, 'utf8')
484
+
485
+ for (const [key, value] of Object.entries(subs)) {
486
+ content = content.split(`<${key}>`).join(value)
487
+ }
488
+
489
+ // Detect unresolved placeholders — a remaining <UPPER_CASE> token means a
490
+ // placeholder was in the template but not supplied in the substitution map.
491
+ // Fail loudly now rather than generating broken TypeScript that confuses tsc.
492
+ const unresolved = [...new Set((content.match(/<[A-Z][A-Z_]+>/g) ?? []))]
493
+ if (unresolved.length > 0) {
494
+ fail(
495
+ `Template "${templateName}.tsx" has unresolved placeholders: ${unresolved.join(', ')}. ` +
496
+ `These must be added to the substitution map passed to applyTemplate().`
497
+ )
498
+ }
499
+
500
+ return content
501
+ }
502
+
503
+ /**
504
+ * Generate a detail view file for a widget.
505
+ *
506
+ * Drills to RECORD GRAIN: the view runs the module's `fetchDetail` export — the
507
+ * individual records behind the chart (e.g. each job run), not the aggregate. When
508
+ * `detailColumns` (a compiled ColumnDef literal) is supplied, it drives the table
509
+ * (formatted/coloured cells); otherwise columns are auto-detected at runtime.
510
+ * `defaultSortKey` keys the initial sort on the raw field (e.g. an ISO timestamp)
511
+ * so chronological order is correct even when a column renders a friendly label.
512
+ *
513
+ * @param {{ componentName: string, title: string, subtitle?: string, moduleSpecifier: string, detailExport: string, detailColumns?: string|null, defaultSortKey?: string }} widget
514
+ * @returns {string} Full TypeScript file content
515
+ */
516
+ export function generateViewFile(widget) {
517
+ const { componentName, title, subtitle = '', moduleSpecifier, detailExport, detailColumns, defaultSortKey, detailView = null } = widget
518
+
519
+ const columnsExpr = detailColumns ? detailColumns : 'autoColumns(rows)'
520
+ const sortKeyExpr = defaultSortKey ? JSON.stringify(defaultSortKey) : '(columns[0]?.key as string)'
521
+
522
+ const compiled = detailView ? compileDetailWidgets(detailView, 'd') : null
523
+ const extraImports = compiled ? '\n' + [...compiled.imports].filter(i => !i.includes("'@/dashboard/chrome/RecordsTable'")).join('\n') : ''
524
+
525
+ const body = detailView
526
+ ? ` const d = (data && !Array.isArray(data)) ? (data as Record<string, unknown[]>) : { rows: toRows(data ?? []) }
527
+
528
+ if (loading) return (
529
+ <DetailViewShell title="${title ?? componentName}" description="${subtitle}">
530
+ <LoadingState height="h-96" />
531
+ </DetailViewShell>
532
+ )
533
+ if (error) return (
534
+ <DetailViewShell title="${title ?? componentName}" description="${subtitle}">
535
+ <EmptyState message={error.message} />
536
+ </DetailViewShell>
537
+ )
538
+ return (
539
+ <DetailViewShell title="${title ?? componentName}" description="${subtitle}">
540
+ <div className="space-y-6">
541
+ ${compiled.jsx}
542
+ </div>
543
+ </DetailViewShell>
544
+ )`
545
+ : ` const rows = toRows(data ?? [])
546
+ const columns = ${columnsExpr}
547
+
548
+ if (loading) return (
549
+ <DetailViewShell title="${title ?? componentName}" description="${subtitle}">
550
+ <LoadingState height="h-96" />
551
+ </DetailViewShell>
552
+ )
553
+ if (error) return (
554
+ <DetailViewShell title="${title ?? componentName}" description="${subtitle}">
555
+ <EmptyState message={error.message} />
556
+ </DetailViewShell>
557
+ )
558
+ return (
559
+ <DetailViewShell title="${title ?? componentName}" description="${subtitle}">
560
+ <RecordsTable rows={rows} columns={columns} defaultSortKey={${sortKeyExpr}} />
561
+ </DetailViewShell>
562
+ )`
563
+
564
+ return `import React from 'react'
565
+ import { DetailViewShell } from '@/dashboard/chrome/DetailViewShell'
566
+ import { RecordsTable, type ColumnDef } from '@/dashboard/chrome/RecordsTable'
567
+ import { useWidgetData } from '@/hooks/useWidgetData'
568
+ import { LoadingState, EmptyState } from '@/dashboard/chrome'
569
+ import { fmtNumber, fmtPercent, fmtDuration, fmtTimeAgo } from '@/lib/format'
570
+ import { toneClass } from '@/lib/widget'
571
+ import { ${detailExport} } from '${moduleSpecifier}'${extraImports}
572
+
573
+ type Row = Record<string, unknown>
574
+
575
+ /** Auto-detect columns from the first row when explicit detailColumns aren't given. */
576
+ function autoColumns(rows: Row[]): ColumnDef<Row>[] {
577
+ if (rows.length === 0) return [{ key: 'value', label: 'Value' }]
578
+ return Object.entries(rows[0])
579
+ .filter(([, v]) => v !== null && v !== undefined && typeof v !== 'object')
580
+ .map(([k, v]) => ({
581
+ key: k,
582
+ label: k.replace(/([A-Z])/g, ' $1').replace(/^(.)/, (s: string) => s.toUpperCase()).trim(),
583
+ ...(typeof v === 'number' && { align: 'right' as const }),
584
+ }))
585
+ }
586
+
587
+ export function ${componentName}View() {
588
+ const { data, loading, error } = useWidgetData(${detailExport}, [])
589
+
590
+ /** Safely extract a row array from any response shape */
591
+ function toRows(raw: unknown): Row[] {
592
+ if (!raw) return []
593
+ if (Array.isArray(raw)) return raw as Row[]
594
+ if (typeof raw === 'object') {
595
+ const obj = raw as Record<string, unknown>
596
+ if (Array.isArray(obj.items)) return obj.items as Row[]
597
+ if (Array.isArray(obj.data)) return obj.data as Row[]
598
+ if (obj.data && typeof obj.data === 'object') return toRows(obj.data)
599
+ }
600
+ return []
601
+ }
602
+
603
+ ${body}
604
+ }
605
+ `
606
+ }
607
+
608
+ /**
609
+ * Generate a KEYED detail view for a table widget with `rowLink` — reads the
610
+ * route param and calls the module's `fetchDetailByKey(sdk, key, getToken)`.
611
+ * @param {{componentName:string,title?:string,subtitle?:string,moduleSpecifier:string,detailColumns?:string|null}} widget
612
+ * @returns {string}
613
+ */
614
+ export function generateKeyedDetailViewFile(widget) {
615
+ const { componentName, title, subtitle = '', moduleSpecifier, detailColumns, detailView = null } = widget
616
+ const columnsExpr = detailColumns ? detailColumns : 'autoColumns(rows)'
617
+
618
+ const compiled = detailView ? compileDetailWidgets(detailView, 'd') : null
619
+ const extraImports = compiled ? '\n' + [...compiled.imports].filter(i => !i.includes("'@/dashboard/chrome/RecordsTable'")).join('\n') : ''
620
+
621
+ // Body branches: rich detailView renders compiled sub-widgets over a normalized
622
+ // source map; otherwise today's single RecordsTable (backward-compat, unchanged).
623
+ const stateInit = detailView ? `const [data, setData] = useState<unknown>(null)` : `const [data, setData] = useState<Row[]>([])`
624
+ const fetchThen = detailView
625
+ ? `.then((res: unknown) => { setData(res); setLoading(false) })`
626
+ : `.then((rows: Row[]) => { setData(rows); setLoading(false) })`
627
+
628
+ const body = detailView
629
+ ? ` const d = (data && !Array.isArray(data)) ? (data as Record<string, unknown[]>) : { rows: toRows(data as unknown) }
630
+ const heading = key ? \`${title ?? componentName}: \${decodeURIComponent(key)}\` : '${title ?? componentName}'
631
+
632
+ if (loading) return (
633
+ <DetailViewShell title={heading} description="${subtitle}">
634
+ <LoadingState height="h-96" />
635
+ </DetailViewShell>
636
+ )
637
+ if (error) return (
638
+ <DetailViewShell title={heading} description="${subtitle}">
639
+ <EmptyState message={error.message} />
640
+ </DetailViewShell>
641
+ )
642
+ return (
643
+ <DetailViewShell title={heading} description="${subtitle}">
644
+ <div className="space-y-6">
645
+ ${compiled.jsx}
646
+ </div>
647
+ </DetailViewShell>
648
+ )`
649
+ : ` const rows = data
650
+ const columns = ${columnsExpr}
651
+ const heading = key ? \`${title ?? componentName}: \${decodeURIComponent(key)}\` : '${title ?? componentName}'
652
+
653
+ if (loading) return (
654
+ <DetailViewShell title={heading} description="${subtitle}">
655
+ <LoadingState height="h-96" />
656
+ </DetailViewShell>
657
+ )
658
+ if (error) return (
659
+ <DetailViewShell title={heading} description="${subtitle}">
660
+ <EmptyState message={error.message} />
661
+ </DetailViewShell>
662
+ )
663
+ return (
664
+ <DetailViewShell title={heading} description="${subtitle}">
665
+ <RecordsTable rows={rows} columns={columns} />
666
+ </DetailViewShell>
667
+ )`
668
+
669
+ return `import React from 'react'
670
+ import { useParams } from 'react-router-dom'
671
+ import { useState, useEffect } from 'react'
672
+ import { DetailViewShell } from '@/dashboard/chrome/DetailViewShell'
673
+ import { RecordsTable, type ColumnDef } from '@/dashboard/chrome/RecordsTable'
674
+ import { useAuth } from '@/hooks/useAuth'
675
+ import { LoadingState, EmptyState } from '@/dashboard/chrome'
676
+ import { fmtNumber, fmtPercent, fmtDuration, fmtTimeAgo } from '@/lib/format'
677
+ import { toneClass } from '@/lib/widget'
678
+ import { fetchDetailByKey } from '${moduleSpecifier}'${extraImports}
679
+
680
+ type Row = Record<string, unknown>
681
+
682
+ /** Auto-detect columns from the first row when explicit detailColumns aren't given. */
683
+ function autoColumns(rows: Row[]): ColumnDef<Row>[] {
684
+ if (rows.length === 0) return [{ key: 'value', label: 'Value' }]
685
+ return Object.entries(rows[0])
686
+ .filter(([, v]) => v !== null && v !== undefined && typeof v !== 'object')
687
+ .map(([k, v]) => ({
688
+ key: k,
689
+ label: k.replace(/([A-Z])/g, ' $1').replace(/^(.)/, (s: string) => s.toUpperCase()).trim(),
690
+ ...(typeof v === 'number' && { align: 'right' as const }),
691
+ }))
692
+ }
693
+ ${detailView ? `
694
+ /** Safely extract a row array from any response shape (legacy fallback / bare arrays). */
695
+ function toRows(raw: unknown): Row[] {
696
+ if (!raw) return []
697
+ if (Array.isArray(raw)) return raw as Row[]
698
+ if (typeof raw === 'object') {
699
+ const obj = raw as Record<string, unknown>
700
+ if (Array.isArray(obj.items)) return obj.items as Row[]
701
+ if (Array.isArray(obj.data)) return obj.data as Row[]
702
+ if (obj.data && typeof obj.data === 'object') return toRows(obj.data)
703
+ }
704
+ return []
705
+ }
706
+ ` : ''}
707
+ export function ${componentName}DetailView() {
708
+ const { key } = useParams<{ key: string }>()
709
+ const { sdk, getToken } = useAuth()
710
+ ${stateInit}
711
+ const [loading, setLoading] = useState(true)
712
+ const [error, setError] = useState<Error | null>(null)
713
+
714
+ useEffect(() => {
715
+ if (!sdk || !key) return
716
+ setLoading(true)
717
+ fetchDetailByKey(sdk, key, getToken)
718
+ ${fetchThen}
719
+ .catch((err: unknown) => { setError(err instanceof Error ? err : new Error(String(err))); setLoading(false) })
720
+ }, [sdk, key])
721
+
722
+ ${body}
723
+ }
724
+ `
725
+ }
726
+
727
+ /**
728
+ * Generate Dashboard.tsx and widgets/index.ts from resolved widget metadata.
729
+ * @param {string} projectPath
730
+ * @param {WidgetMeta[]} widgetMeta
731
+ * @param {string} dashboardName
732
+ */
733
+ export function generateDashboardFiles(projectPath, widgetMeta, dashboardName, dashboardDescription = '') {
734
+ const widgetNames = widgetMeta.map(w => w.componentName)
735
+
736
+ const kpis = widgetMeta.filter(w => widgetLayoutGroup(w.template) === 'kpi')
737
+ const charts = widgetMeta.filter(w => widgetLayoutGroup(w.template) === 'chart')
738
+ const tables = widgetMeta.filter(w => widgetLayoutGroup(w.template) === 'table')
739
+
740
+ const kpiCols = Math.min(kpis.length, 4)
741
+ const kpiGrid = kpiCols === 1 ? 'grid-cols-1'
742
+ : kpiCols === 2 ? 'grid-cols-1 sm:grid-cols-2'
743
+ : kpiCols === 3 ? 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3'
744
+ : 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4'
745
+
746
+ const imports = widgetNames.map(n => `import { ${n} } from './widgets/${n}'`).join('\n')
747
+ const indexTs = widgetNames.map(n => `export { ${n} } from './${n}'`).join('\n') + '\n'
748
+
749
+ const kpiSection = kpis.length ? `
750
+ {/* KPI row */}
751
+ <div className="grid ${kpiGrid} gap-6">
752
+ ${kpis.map(w => `<${w.componentName} />`).join('\n ')}
753
+ </div>` : ''
754
+
755
+ const chartSection = charts.length ? `
756
+ {/* Charts */}
757
+ <div className="grid grid-cols-1 ${charts.length > 1 ? 'lg:grid-cols-2' : ''} gap-6 mt-10">
758
+ ${charts.map(w => `<${w.componentName} />`).join('\n ')}
759
+ </div>` : ''
760
+
761
+ const tableSection = tables.length ? `
762
+ {/* Tables */}
763
+ <div className="space-y-6 mt-10">
764
+ ${tables.map(w => `<${w.componentName} />`).join('\n ')}
765
+ </div>` : ''
766
+
767
+ const dashboardJsx = `import React from 'react'
768
+ import { Header } from '@/dashboard/chrome/Header'
769
+ ${imports}
770
+
771
+ export function Dashboard() {
772
+ return (
773
+ <div className="min-h-screen bg-background">
774
+ <div className="mx-auto max-w-screen-2xl px-4 py-8 md:px-8 md:py-10">
775
+ <Header title="${dashboardName}" description="${dashboardDescription || 'Operational metrics dashboard'}" />
776
+ ${kpiSection}${chartSection}${tableSection}
777
+ </div>
778
+ </div>
779
+ )
780
+ }
781
+ `
782
+ writeAtomic(join(projectPath, 'src', 'dashboard', 'Dashboard.tsx'), dashboardJsx)
783
+ writeAtomic(join(projectPath, 'src', 'dashboard', 'widgets', 'index.ts'), indexTs)
784
+ }
785
+
786
+ /**
787
+ * Classify a widget template into its layout group for Dashboard.tsx grid placement.
788
+ * @param {string} template
789
+ * @returns {'kpi'|'table'|'chart'}
790
+ */
791
+ export function widgetLayoutGroup(template) {
792
+ if (template === 'kpi-card') return 'kpi'
793
+ if (['data-table', 'ranked-table'].includes(template)) return 'table'
794
+ return 'chart'
795
+ }
796
+
797
+ /**
798
+ * Decide whether a widget gets a generated record-grain detail view (+ route).
799
+ * Single source of truth for fresh build, incremental ADD/CHANGE, rebuild, and
800
+ * upgrade — keeps the "is this card clickable / does a view file exist" decision
801
+ * consistent everywhere.
802
+ *
803
+ * - Chart widgets get a detail view UNLESS opted out with `noDetail: true` — set
804
+ * on the registry entry (T1/T2 catalog) OR on the metric in intent.json (T3,
805
+ * which has no registry entry). Used when the endpoint returns only
806
+ * pre-aggregated data, so a record drill-down would be fake. Opted-out charts
807
+ * render non-clickable.
808
+ * - KPI cards get a detail view when `detail` is true — either set on the metric
809
+ * (`detail: true` in intent.json) or defaulted on by the registry entry
810
+ * (`defaults.detail: true`, for cataloged KPIs that have a feasible record-grain
811
+ * query). A metric can force it off with `detail: false`. The module must export
812
+ * `fetchDetail`. A KPI with no `detail` signal links nowhere.
813
+ * - Tables never get a chart-style view here (they use `rowLink` keyed views).
814
+ *
815
+ * @param {string} template displayAs / registry template
816
+ * @param {object} [metric] intent metric (KPI `detail`, T3 `noDetail`)
817
+ * @param {object|null} [entry] registry entry (catalog `noDetail` / `defaults.detail`)
818
+ * @returns {boolean}
819
+ */
820
+ export function widgetGetsDetailView(template, metric = {}, entry = null) {
821
+ if (entry?.noDetail === true || metric?.noDetail === true) return false
822
+ if (widgetLayoutGroup(template) === 'chart') return true
823
+ if (template === 'kpi-card') {
824
+ // Metric override wins; otherwise the registry entry may default it on for a
825
+ // cataloged KPI whose drill-down records are queryable.
826
+ return (metric?.detail ?? entry?.defaults?.detail ?? false) === true
827
+ }
828
+ return false
829
+ }
830
+
831
+ /**
832
+ * Inject generated import and route blocks into App.tsx markers.
833
+ * @param {string} projectPath
834
+ * @param {string[]} viewWidgetNames - Widget names that have a generated view file
835
+ */
836
+ export function injectAppRoutes(projectPath, viewWidgetNames, keyedViews = []) {
837
+ const appPath = join(projectPath, 'src', 'App.tsx')
838
+ if (!existsSync(appPath)) {
839
+ emit('PARTIAL_BUILD_DETECTED', { message: 'App.tsx not found — scaffold may not be copied yet' })
840
+ return
841
+ }
842
+ let content = readFileSync(appPath, 'utf8')
843
+
844
+ const viewNames = viewWidgetNames
845
+
846
+ const imports = [
847
+ `import { Dashboard } from '@/dashboard/Dashboard'`,
848
+ ...viewNames.map(n => `import { ${n}View } from '@/dashboard/views/${n}View'`),
849
+ ...keyedViews.map(k => `import { ${k.componentName}DetailView } from '@/dashboard/views/${k.componentName}DetailView'`),
850
+ ].join('\n')
851
+
852
+ const routes = [
853
+ ` <Route path="/" element={<Dashboard />} />`,
854
+ ...viewNames.map(n => ` <Route path="/${n.toLowerCase()}" element={<${n}View />} />`),
855
+ ...keyedViews.map(k => ` <Route path="${k.routeBase}/:key" element={<${k.componentName}DetailView />} />`),
856
+ ].join('\n')
857
+
858
+ content = content.replace(
859
+ /\/\/ GENERATED_IMPORTS_START[\s\S]*?\/\/ GENERATED_IMPORTS_END/,
860
+ `// GENERATED_IMPORTS_START\n${imports}\n// GENERATED_IMPORTS_END`
861
+ )
862
+ content = content.replace(
863
+ /\{\/\* GENERATED_ROUTES_START \*\/\}[\s\S]*?\{\/\* GENERATED_ROUTES_END \*\/\}/,
864
+ `{/* GENERATED_ROUTES_START */}\n${routes}\n {/* GENERATED_ROUTES_END */}`
865
+ )
866
+
867
+ writeAtomic(appPath, content)
868
+ }
869
+
870
+ // ── Resolution Engine ──────────────────────────────────────────────────────────
871
+
872
+ /**
873
+ * Validate a DashboardIntent object and return an array of error messages.
874
+ * Returns an empty array when the intent is valid.
875
+ * @param {DashboardIntent} intent
876
+ * @returns {string[]}
877
+ */
878
+ export function validateIntent(intent) {
879
+ const errors = []
880
+ if (intent.schemaVersion !== 2) errors.push('intent.json must have "schemaVersion": 2')
881
+ if (!intent.dashboardName || typeof intent.dashboardName !== 'string') errors.push('dashboardName must be a non-empty string')
882
+ if (!['1d', '7d', '30d', '90d'].includes(intent.timeRange)) errors.push(`timeRange must be one of: 1d, 7d, 30d, 90d`)
883
+ if (!Array.isArray(intent.metrics) || intent.metrics.length === 0) errors.push('metrics must be a non-empty array')
884
+ for (const m of (intent.metrics ?? [])) {
885
+ if (!m.name) errors.push(`metric ${JSON.stringify(m.title ?? m)} missing name (needed to resolve its metrics/<name>.ts module)`)
886
+ if (!['T1', 'T2', 'T3'].includes(m.tier)) errors.push(`metric "${m.name}" has invalid tier: ${m.tier}`)
887
+ if (m.tier === 'T1' || m.tier === 'T2') {
888
+ if (!m.title) errors.push(`${m.tier} metric "${m.name}" missing title`)
889
+ }
890
+ if (m.tier === 'T2') {
891
+ if (!m.params) {
892
+ errors.push(`T2 metric "${m.name}" missing params`)
893
+ }
894
+ }
895
+ if (m.tier === 'T3') {
896
+ if (!m.title) errors.push(`T3 metric "${m.name}" missing title`)
897
+ if (!m.displayAs) errors.push(`T3 metric "${m.name}" needs displayAs — valid values: ${VALID_DISPLAY_TYPES.join(', ')}`)
898
+ else if (!VALID_DISPLAY_TYPES.includes(m.displayAs)) {
899
+ errors.push(`T3 metric "${m.name}" has unsupported displayAs "${m.displayAs}". Valid: ${VALID_DISPLAY_TYPES.join(', ')}`)
900
+ }
901
+ }
902
+ // Presentation hints (all tiers, all optional) — validate enums when present
903
+ if (m.headlineMode && !VALID_HEADLINE_MODES.includes(m.headlineMode)) {
904
+ errors.push(`metric "${m.name}" has invalid headlineMode "${m.headlineMode}". Valid: ${VALID_HEADLINE_MODES.join(', ')}`)
905
+ }
906
+ if (m.deltaPolarity && !VALID_DELTA_POLARITIES.includes(m.deltaPolarity)) {
907
+ errors.push(`metric "${m.name}" has invalid deltaPolarity "${m.deltaPolarity}". Valid: ${VALID_DELTA_POLARITIES.join(', ')}`)
908
+ }
909
+ if (m.displayAs === 'rate-chart' && (!m.rateNum || !m.rateDen)) {
910
+ errors.push(`rate-chart metric "${m.name}" needs rateNum and rateDen (the numerator/denominator field names its fnBody returns per bucket)`)
911
+ }
912
+ if (Array.isArray(m.detailColumns)) {
913
+ for (const c of m.detailColumns) {
914
+ if (!c.key || !c.label) errors.push(`metric "${m.name}" detailColumns entry missing key/label`)
915
+ if (c.format && !VALID_COLUMN_FORMATS.includes(c.format)) {
916
+ errors.push(`metric "${m.name}" detailColumns "${c.key}" has invalid format "${c.format}". Valid: ${VALID_COLUMN_FORMATS.join(', ')}`)
917
+ }
918
+ }
919
+ }
920
+ // Row-click drill-down config
921
+ if (m.rowLink !== undefined && (typeof m.rowLink !== 'object' || !m.rowLink.key || typeof m.rowLink.key !== 'string')) {
922
+ errors.push(`metric "${m.name}" rowLink must be an object with a string "key" (the row field used as the drill-down route param). The module must export fetchDetailByKey.`)
923
+ }
924
+ // Rich detail-view spec — throws with a precise message on any violation.
925
+ validateDetailView(m)
926
+ }
927
+ return errors
928
+ }
929
+
930
+ /**
931
+ * The module specifier a generated widget imports its data function from.
932
+ * Default convention: metrics/<metric-name>.ts → '@/metrics/<metric-name>'.
933
+ * An explicit `module` field (e.g. "metrics/custom.ts") overrides; the .ts is stripped.
934
+ * @param {{ name: string, module?: string }} metric
935
+ * @returns {string}
936
+ */
937
+ export function metricModuleSpecifier(metric) {
938
+ const rel = metric.module ?? `metrics/${metric.name}.ts`
939
+ return '@/' + rel.replace(/\.ts$/, '')
940
+ }
941
+
942
+ /**
943
+ * Look up a metric in the capability registry.
944
+ * T3 metrics always resolve (they carry their own generation logic).
945
+ * Returns null entry for unknown T1/T2 metrics (agent provides fnBody, registry lookup is for display hints only).
946
+ * @param {IntentMetric} metric
947
+ * @returns {{ tier: MetricTier, key: string, entry: object|null }}
948
+ */
949
+ export function resolveMetric(metric) {
950
+ if (metric.tier === 'T3') return { tier: 'T3', key: metric.name, entry: null }
951
+ const registrySection = metric.tier === 'T1' ? REGISTRY.t1 : REGISTRY.t2
952
+ const entry = registrySection[metric.name]
953
+ if (!entry) {
954
+ throw new Error(`Metric "${metric.name}" (${metric.tier}) not found in registry. Available: ${Object.keys(registrySection).join(', ')}`)
955
+ }
956
+ return { tier: metric.tier, key: metric.name, entry }
957
+ }
958
+
959
+ /**
960
+ * Resolve a widget subtitle (CardDescription). Falls back to a window label.
961
+ * @param {IntentMetric} metric
962
+ * @param {object} defaults - registry entry defaults
963
+ * @param {string} timeRange
964
+ * @returns {string}
965
+ */
966
+ export function autoSubtitle(metric, defaults, timeRange) {
967
+ const explicit = metric.subtitle ?? defaults.subtitle ?? metric.description ?? defaults.description
968
+ if (explicit) return explicit
969
+ const label = timeRangeLabel(timeRange)
970
+ return label.charAt(0).toUpperCase() + label.slice(1)
971
+ }
972
+
973
+ /**
974
+ * Compile a column spec into a TS array literal for RecordsTable.
975
+ * Accepts either a ready literal string (passed through) or an array of
976
+ * { key, label, align?, format?, color? } objects, for which it emits `render`
977
+ * functions that format (number/percent/duration/timeAgo) and optionally colour cells.
978
+ * @param {string|Array<object>} input
979
+ * @returns {string}
980
+ */
981
+ export function compileColumns(input) {
982
+ if (typeof input === 'string') return input
983
+ if (!Array.isArray(input) || input.length === 0) return '[{key:"name",label:"Name"}]'
984
+ const cols = input.map((c) => {
985
+ const parts = [`key:${JSON.stringify(c.key)}`, `label:${JSON.stringify(c.label)}`]
986
+ if (c.align) parts.push(`align:${JSON.stringify(c.align)} as const`)
987
+ const render = columnRender(c)
988
+ if (render) parts.push(`render:${render}`)
989
+ return `{${parts.join(',')}}`
990
+ })
991
+ return `[${cols.join(',')}]`
992
+ }
993
+
994
+ /**
995
+ * Compile a metric's `detailView` spec into the imports + JSX for a rich
996
+ * drill-down view. Chart sub-widgets render the matching primitive from
997
+ * `@/dashboard/charts`; table sub-widgets render a titled Card wrapping a
998
+ * RecordsTable. Each sub-widget reads its named source off `dataVar`
999
+ * (the normalized `{ rows, byHook, ... }` map).
1000
+ * @param {{ widgets: Array<object> }} detailView
1001
+ * @param {string} [dataVar='d']
1002
+ * @returns {{ imports: Set<string>, jsx: string }}
1003
+ */
1004
+ export function compileDetailWidgets(detailView, dataVar = 'd') {
1005
+ const imports = new Set()
1006
+ const blocks = []
1007
+ const CHART_IMPORT = {
1008
+ 'donut-chart': 'Donut',
1009
+ 'bar-chart': 'Bars',
1010
+ 'area-chart': 'TrendArea',
1011
+ 'line-chart': 'TrendArea',
1012
+ 'multi-line-chart': 'MultiLine',
1013
+ }
1014
+ for (const w of (detailView.widgets ?? [])) {
1015
+ const srcExpr = `(${dataVar}[${JSON.stringify(w.source)}] ?? []) as Record<string, unknown>[]`
1016
+ if (DETAIL_CHART_TYPES.has(w.displayAs)) {
1017
+ const comp = CHART_IMPORT[w.displayAs]
1018
+ imports.add(`import { ${comp} } from '@/dashboard/charts'`)
1019
+ imports.add(`import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'`)
1020
+ const emptyProp = typeof w.emptyMessage === 'string' ? ` emptyMessage={${JSON.stringify(w.emptyMessage)}}` : ''
1021
+ let chartEl
1022
+ if (w.displayAs === 'multi-line-chart') {
1023
+ chartEl = `<MultiLine data={${srcExpr}} xKey={${JSON.stringify(w.xKey)}} series={${compileSeries(w.series)}}${emptyProp} />`
1024
+ } else if (w.displayAs === 'donut-chart') {
1025
+ chartEl = `<Donut data={${srcExpr}} nameKey={${JSON.stringify(w.xKey)}} valueKey={${JSON.stringify(w.yKey)}}${emptyProp} />`
1026
+ } else if (w.displayAs === 'bar-chart') {
1027
+ chartEl = `<Bars data={${srcExpr}} nameKey={${JSON.stringify(w.xKey)}} valueKey={${JSON.stringify(w.yKey)}}${emptyProp} />`
1028
+ } else if (w.displayAs === 'area-chart') {
1029
+ chartEl = `<TrendArea data={${srcExpr}} xKey={${JSON.stringify(w.xKey)}} yKey={${JSON.stringify(w.yKey)}}${emptyProp} />`
1030
+ } else { // line-chart
1031
+ chartEl = `<TrendArea data={${srcExpr}} xKey={${JSON.stringify(w.xKey)}} yKey={${JSON.stringify(w.yKey)}} area={false}${emptyProp} />`
1032
+ }
1033
+ blocks.push(` <Card>
1034
+ <CardHeader><CardTitle>{${JSON.stringify(w.title)}}</CardTitle></CardHeader>
1035
+ <CardContent>
1036
+ ${chartEl}
1037
+ </CardContent>
1038
+ </Card>`)
1039
+ } else {
1040
+ // table sub-widget
1041
+ imports.add(`import { RecordsTable, type ColumnDef } from '@/dashboard/chrome/RecordsTable'`)
1042
+ imports.add(`import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'`)
1043
+ const colsExpr = w.columns ? compileColumns(w.columns) : `autoColumns(${srcExpr})`
1044
+ blocks.push(` <Card>
1045
+ <CardHeader><CardTitle>{${JSON.stringify(w.title)}}</CardTitle></CardHeader>
1046
+ <CardContent>
1047
+ <RecordsTable rows={${srcExpr}} columns={${colsExpr}} />
1048
+ </CardContent>
1049
+ </Card>`)
1050
+ }
1051
+ }
1052
+ return { imports, jsx: blocks.join('\n') }
1053
+ }
1054
+
1055
+ /**
1056
+ * Compile a multi-line-chart `series` spec into a TS array literal.
1057
+ * Accepts either a ready literal string (passed through) or an array of
1058
+ * `{ key, color, label? }` objects — the natural form an author writes in
1059
+ * intent.json. Without this, naive string coercion of the array writes the JS
1060
+ * default `[object Object],[object Object]` into the SERIES constant and tsc fails.
1061
+ * @param {string|Array<{key:string,color:string,label?:string}>} input
1062
+ * @returns {string}
1063
+ */
1064
+ export function compileSeries(input) {
1065
+ if (typeof input === 'string') return input
1066
+ if (!Array.isArray(input) || input.length === 0) return '[{key:"value",color:"hsl(var(--chart-1))"}]'
1067
+ const items = input.map((s) => {
1068
+ const parts = [`key:${JSON.stringify(s.key)}`, `color:${JSON.stringify(s.color)}`]
1069
+ if (s.label) parts.push(`label:${JSON.stringify(s.label)}`)
1070
+ return `{${parts.join(',')}}`
1071
+ })
1072
+ return `[${items.join(',')}]`
1073
+ }
1074
+
1075
+ /** Build a `render` function body for a column with `format` and/or `color`. Returns null if neither. */
1076
+ function columnRender(c) {
1077
+ if (!c.format && !c.color) return null
1078
+ let valExpr
1079
+ switch (c.format) {
1080
+ case 'number': valExpr = 'fmtNumber(Number(v))'; break
1081
+ case 'percent': valExpr = 'fmtPercent(Number(v))'; break
1082
+ case 'duration': valExpr = 'fmtDuration(Number(v))'; break
1083
+ case 'timeAgo': valExpr = 'fmtTimeAgo(String(v))'; break
1084
+ default: valExpr = 'String(v ?? "—")'
1085
+ }
1086
+ if (c.color) {
1087
+ // color: 'goodHigh' (higher is better) | 'goodLow' (lower is better)
1088
+ return `(v:unknown)=>React.createElement('span',{className:toneClass(Number(v),${JSON.stringify(c.color)})},${valExpr})`
1089
+ }
1090
+ return `(v:unknown)=>${valExpr}`
1091
+ }
1092
+
1093
+ /**
1094
+ * Build the spec passed to generateViewFile for a widget's detail view.
1095
+ * Shared by the fresh build and incremental ADD/CHANGE so detail views stay
1096
+ * consistent. The view always runs the module's record-grain `fetchDetail` export.
1097
+ * @param {string} componentName
1098
+ * @param {IntentMetric} metric
1099
+ * @param {object|null} entry - registry entry (for defaults)
1100
+ * @param {string} timeRange
1101
+ */
1102
+ export function buildViewSpec(componentName, metric, entry, timeRange) {
1103
+ // Detail views show RECORD GRAIN: a chart/KPI exports `fetchData` (the
1104
+ // aggregate the widget renders) AND `fetchDetail` (the individual records
1105
+ // behind it). The view always runs `fetchDetail` — every chart metric is
1106
+ // required to export it (enforced by the CHART_DETAIL_MISSING gate), and a
1107
+ // KPI reaches this path only with `detail: true`. detailColumns fall back to
1108
+ // the registry defaults so a cataloged metric's drill-down is styled with no
1109
+ // intent.json config.
1110
+ const detailColumns = metric.detailColumns ?? entry?.defaults?.detailColumns
1111
+ return {
1112
+ componentName,
1113
+ title: metric.title ?? entry?.defaults?.title ?? componentName,
1114
+ subtitle: autoSubtitle(metric, entry?.defaults ?? {}, timeRange),
1115
+ moduleSpecifier: metricModuleSpecifier(metric),
1116
+ detailExport: 'fetchDetail',
1117
+ detailColumns: detailColumns ? compileColumns(detailColumns) : null,
1118
+ defaultSortKey: metric.detailSortKey ?? entry?.defaults?.detailSortKey,
1119
+ detailView: metric.detailView ?? entry?.defaults?.detailView ?? null,
1120
+ }
1121
+ }
1122
+
1123
+ /**
1124
+ * Generate the TypeScript source for any widget file.
1125
+ * All tiers (T1, T2, T3) use fnBody — the agent writes the SDK call.
1126
+ * Registry provides display hints; agent provides the data fetching logic.
1127
+ * @param {IntentMetric} metric - Must have fnBody, displayAs (or registry template), title
1128
+ * @param {object|null} registryEntry - Registry entry for display hints (null for T3)
1129
+ * @param {'1d'|'7d'|'30d'|'90d'} [timeRange='30d']
1130
+ * @returns {string} Full TypeScript file content
1131
+ */
1132
+ export function buildWidgetFile(metric, registryEntry = null, timeRange = '30d') {
1133
+ if (!metric.title) throw new Error(`metric "${metric.name}" missing title`)
1134
+
1135
+ const defaults = registryEntry?.defaults ?? {}
1136
+ const componentName = metric.componentName ?? toPascalCase(metric.name)
1137
+ const displayAs = metric.displayAs ?? registryEntry?.template
1138
+ const iconName = metric.icon ?? defaults.icon ?? 'Activity'
1139
+
1140
+ if (!displayAs) throw new Error(`metric "${metric.name}" needs displayAs`)
1141
+
1142
+ const CHART_TYPES = new Set(['area-chart', 'line-chart', 'bar-chart', 'donut-chart', 'multi-line-chart', 'rate-chart'])
1143
+
1144
+ // ── Chart path ─────────────────────────────────────────────────────────────
1145
+ if (CHART_TYPES.has(displayAs)) {
1146
+ const moduleSpecifier = metricModuleSpecifier(metric)
1147
+ // noDetail charts (Insights endpoints with only pre-aggregated data) get NO
1148
+ // drill-down: an empty DETAIL_ROUTE makes the template render a non-clickable
1149
+ // card (no cursor-pointer, no ViewAllLink). Step 5a then skips the view file.
1150
+ const hasDetail = widgetGetsDetailView(displayAs, metric, registryEntry)
1151
+ const spec = {
1152
+ componentName,
1153
+ template: displayAs,
1154
+ detailRoute: hasDetail ? (metric.detailRoute ?? `/${componentName.toLowerCase()}`) : '',
1155
+ icon: iconName,
1156
+ title: metric.title,
1157
+ subtitle: autoSubtitle(metric, defaults, timeRange),
1158
+ dataHook: 'useWidgetData(fetchData, [])',
1159
+ hookImport: [
1160
+ "import { useWidgetData } from '@/hooks/useWidgetData'",
1161
+ `import { fetchData } from '${moduleSpecifier}'`,
1162
+ ].join('\n'),
1163
+ sdkImportLine: '',
1164
+ responseTypeImport: '',
1165
+ dataSelector: 'data ?? []',
1166
+ xKey: metric.xKey ?? defaults.xKey ?? 'date',
1167
+ yKey: metric.yKey ?? defaults.yKey ?? 'value',
1168
+ headlineMode: metric.headlineMode ?? defaults.headlineMode ?? 'sum',
1169
+ deltaPolarity: metric.deltaPolarity ?? defaults.deltaPolarity ?? 'neutral',
1170
+ rateNum: metric.rateNum ?? defaults.rateNum ?? 'num',
1171
+ rateDen: metric.rateDen ?? defaults.rateDen ?? 'den',
1172
+ series: compileSeries(metric.series ?? defaults.series ?? '[{key:"value",color:"hsl(var(--chart-1))"}]'),
1173
+ pivotExpression: metric.pivotExpression ?? defaults.pivotExpression ?? 'rawData',
1174
+ emptyMessage: metric.emptyMessage ?? defaults.emptyMessage ?? 'No data',
1175
+ }
1176
+ return applyTemplate(spec.template, specToSubs(spec))
1177
+ }
1178
+
1179
+ // ── KPI / table path (shell template) ──────────────────────────────────────
1180
+ const t3ShellPath = t3ShellTemplatePath()
1181
+ if (!existsSync(t3ShellPath)) {
1182
+ throw new Error(`T3 shell template not found at ${t3ShellPath}`)
1183
+ }
1184
+ // No explicit columns → emit an empty literal; the widget auto-detects columns
1185
+ // from the actual row data at runtime (real keys + labels), instead of a static
1186
+ // name/value placeholder that renders every cell as "—".
1187
+ const columns = compileColumns(metric.columnDefs ?? metric.columns ?? defaults.columnDefs ?? defaults.columns ?? '[]')
1188
+ // kpi-card defaults to the conventional { value, previous } shape. Without a
1189
+ // valueField the shell renders data.length (the "headline 1" bug) — invisible
1190
+ // until you look at live data. Default it; if a metric explicitly clears it,
1191
+ // fail loud rather than silently show the row count.
1192
+ const isKpiCard = displayAs === 'kpi-card'
1193
+ const valueField = metric.valueField ?? defaults.valueField ?? (isKpiCard ? 'value' : '')
1194
+ const valueLabel = metric.valueLabel ?? defaults.valueLabel ?? ''
1195
+ // previousField defaults only for the conventional { value, previous } shape;
1196
+ // a custom valueField (e.g. "count") gets no unsolicited badge field. The
1197
+ // badge still renders only when the module actually returns a previous value.
1198
+ const previousField = metric.previousField ?? defaults.previousField
1199
+ ?? (isKpiCard && valueField === 'value' ? 'previous' : '')
1200
+ if (isKpiCard && !valueField) {
1201
+ throw new Error(
1202
+ `kpi-card metric "${metric.name}" has no valueField — it would silently render the ` +
1203
+ `row count instead of the metric. Set valueField (e.g. "value") in the metric or ` +
1204
+ `registry defaults, and have the module return [{ value, previous? }].`,
1205
+ )
1206
+ }
1207
+ const deltaPolarity = metric.deltaPolarity ?? defaults.deltaPolarity ?? 'neutral'
1208
+ const rowLinkKey = metric.rowLink?.key ?? defaults.rowLink?.key ?? ''
1209
+ const rowLinkRoute = rowLinkKey ? `/${componentName.toLowerCase()}` : ''
1210
+ // KPI drill-down: a kpi-card with `detail: true` (module exports fetchDetail)
1211
+ // becomes a clickable card that navigates to its record-grain view. Empty for
1212
+ // a plain KPI or any table (tables drill via ROW_LINK, not the card). Step 5a
1213
+ // generates the matching view + route when this is set.
1214
+ const kpiDetailRoute = widgetGetsDetailView(displayAs, metric, registryEntry)
1215
+ ? (metric.detailRoute ?? `/${componentName.toLowerCase()}`) : ''
1216
+ const defaultSortAsc = metric.defaultSortAsc === true ? 'true' : 'false'
1217
+ const emptyMessage = metric.emptyMessage ?? defaults.emptyMessage ?? 'No data'
1218
+ const subtitle = autoSubtitle(metric, defaults, timeRange)
1219
+
1220
+ let content = readFileSync(t3ShellPath, 'utf8')
1221
+ content = content
1222
+ .split('<<METRIC_IMPORT>>').join(`import { fetchData } from '${metricModuleSpecifier(metric)}'`)
1223
+ .split('<<COMPONENT_NAME>>').join(componentName)
1224
+ .split('<<TITLE>>').join(metric.title ?? componentName)
1225
+ .split('<<DESCRIPTION>>').join(subtitle)
1226
+ .split('<<ICON_NAME>>').join(iconName)
1227
+ .split('<<DISPLAY_AS>>').join(displayAs ?? 'ranked-table')
1228
+ .split('<<COLUMNS>>').join(columns)
1229
+ .split('<<VALUE_FIELD>>').join(valueField)
1230
+ .split('<<VALUE_LABEL>>').join(valueLabel)
1231
+ .split('<<PREVIOUS_FIELD>>').join(previousField)
1232
+ .split('<<DELTA_POLARITY>>').join(deltaPolarity)
1233
+ .split('<<ROW_LINK_KEY>>').join(rowLinkKey)
1234
+ .split('<<ROW_LINK_ROUTE>>').join(rowLinkRoute)
1235
+ .split('<<KPI_DETAIL_ROUTE>>').join(kpiDetailRoute)
1236
+ .split('<<DEFAULT_SORT_ASC>>').join(defaultSortAsc)
1237
+ .split('<<EMPTY_MESSAGE>>').join(emptyMessage)
1238
+ return content
1239
+ }
1240
+
1241
+ /**
1242
+ * Convert a WidgetSpec to the substitution map used by applyTemplate.
1243
+ * @param {WidgetSpec} spec
1244
+ * @returns {Record<string, string>}
1245
+ */
1246
+ function specToSubs(spec) {
1247
+ return {
1248
+ COMPONENT_NAME: spec.componentName,
1249
+ TITLE: spec.title,
1250
+ SUBTITLE: spec.subtitle,
1251
+ DETAIL_ROUTE: spec.detailRoute,
1252
+ ICON: spec.icon,
1253
+ DATA_HOOK: spec.dataHook,
1254
+ DATA_SELECTOR: spec.dataSelector,
1255
+ X_KEY: spec.xKey,
1256
+ Y_KEY: spec.yKey,
1257
+ DATA_KEY: spec.yKey,
1258
+ NAME_KEY: spec.xKey,
1259
+ HEADLINE_MODE: spec.headlineMode,
1260
+ DELTA_POLARITY: spec.deltaPolarity,
1261
+ RATE_NUM: spec.rateNum,
1262
+ RATE_DEN: spec.rateDen,
1263
+ SERIES: spec.series,
1264
+ PIVOT_EXPRESSION: spec.pivotExpression,
1265
+ EMPTY_MESSAGE: spec.emptyMessage ?? 'No data',
1266
+ SDK_IMPORT_LINE: spec.sdkImportLine ?? '',
1267
+ RESPONSE_TYPE_IMPORT: spec.responseTypeImport ?? '',
1268
+ HOOK_IMPORT: spec.hookImport ?? "import { useWidgetData } from '@/hooks/useWidgetData'",
1269
+ }
1270
+ }
1271
+
1272
+ // ── Build pipelines ────────────────────────────────────────────────────────────
1273
+
1274
+ /**
1275
+ * Parse tsc error output to find which widget file caused the error.
1276
+ * Falls back to defaultName if the path can't be extracted.
1277
+ * @param {string} tscOutput
1278
+ * @param {string} defaultName
1279
+ * @returns {string}
1280
+ */
1281
+ function widgetNameFromTscErrors(tscOutput, defaultName) {
1282
+ const match = tscOutput.match(/widgets[/\\](\w+)\.tsx\(\d+/)
1283
+ return match?.[1] ?? defaultName
1284
+ }
1285
+
1286
+
1287
+ /**
1288
+ * Validate an edit-intent.json and normalize it to a batch.
1289
+ * Accepts either a single operation ({ op, ... } — legacy shape) or a batch
1290
+ * ({ ops: [{ op, ... }, ...] }). Throws for unknown operation types.
1291
+ * @param {{ projectDir: string, op?: string, ops?: Array<object>, target?: string, metric?: IntentMetric, delta?: object }} editIntent
1292
+ * @returns {{ projectDir: string, ops: Array<{ op: string, target?: string, metric?: IntentMetric, delta?: object }> }}
1293
+ */
1294
+ export function classifyEditIntent(editIntent) {
1295
+ const ops = Array.isArray(editIntent.ops)
1296
+ ? editIntent.ops
1297
+ : [{ op: editIntent.op, target: editIntent.target, metric: editIntent.metric, delta: editIntent.delta }]
1298
+ if (ops.length === 0) throw new Error('classifyEditIntent: ops array is empty')
1299
+ ops.forEach((o, i) => {
1300
+ if (!VALID_EDIT_OPS.includes(o.op)) {
1301
+ throw new Error(`classifyEditIntent: invalid op "${o.op}" (ops[${i}]). Must be one of: ${VALID_EDIT_OPS.join(', ')}`)
1302
+ }
1303
+ })
1304
+ return { projectDir: editIntent.projectDir, ops }
1305
+ }
1306
+
1307
+ /**
1308
+ * Build the metric used to regenerate a widget for a CHANGE op.
1309
+ * Starts from the persisted intentMetric (full metadata: title/displayAs/hints) and merges
1310
+ * the delta on top. Falls back to a minimal ref for legacy state files that
1311
+ * predate intentMetric persistence — then the delta itself must carry title + displayAs.
1312
+ * The data-fetch code lives in the metric module on disk (resolved by name); it is not part of this ref.
1313
+ * @param {object|undefined} stored - state.widgets[target]
1314
+ * @param {string} target - widget component name
1315
+ * @param {object|undefined} delta - fields to change
1316
+ * @returns {IntentMetric}
1317
+ */
1318
+ export function resolveChangeMetric(stored, target, delta) {
1319
+ const base = stored?.intentMetric ?? { name: stored?.metric ?? target.toLowerCase(), tier: stored?.tier ?? 'T1' }
1320
+ return { ...base, ...(delta ?? {}) }
1321
+ }
1322
+
1323
+
1324
+
1325
+
1326
+ // ── Entry point ────────────────────────────────────────────────────────────────
1327
+
1328
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
1329
+
1330
+ // --prewarm <routingName|projectDir> mode: run npm ci in an already-extracted
1331
+ // project, then exit. The agent extracts the starter-kit archive into
1332
+ // <cwd>/<routingName> first. resolve() (not join()) so an ABSOLUTE path is
1333
+ // honored as-is — join(cwd, '/abs/path') concatenates into a broken path on
1334
+ // Windows (C:\cwd\C:\abs\path) and npm ci runs in the wrong place.
1335
+ if (process.argv[2] === '--prewarm' && process.argv[3]) {
1336
+ const routingName = process.argv[3]
1337
+ const prewarmDir = resolve(process.cwd(), routingName)
1338
+ assertScaffoldExtracted(prewarmDir)
1339
+ await runPrewarm(prewarmDir)
1340
+ process.exit(0)
1341
+ }
1342
+
1343
+ // --pack-template <projectDir> mode: stage modify-face source + template.json
1344
+ // into dist/_source for a one-artifact template package (run after `npm run build`).
1345
+ if (process.argv[2] === '--pack-template' && process.argv[3]) {
1346
+ packTemplate(process.argv[3])
1347
+ process.exit(0)
1348
+ }
1349
+
1350
+ const planArg = process.argv[2]
1351
+ if (!planArg) fail('Usage: node build-dashboard.mjs <intent.json|edit-intent.json>')
1352
+
1353
+ let plan
1354
+ try {
1355
+ plan = JSON.parse(readFileSync(planArg, 'utf8'))
1356
+ } catch (e) {
1357
+ fail(`Could not read plan JSON from ${planArg}: ${e.message}`)
1358
+ }
1359
+
1360
+ if (plan.metrics) {
1361
+ const intentErrors = validateIntent(plan)
1362
+ if (intentErrors.length > 0) fail(`Invalid intent.json:\n${intentErrors.map(e => ' • ' + e).join('\n')}`)
1363
+ await runDashboardBuild(plan, planArg)
1364
+ } else if (plan.op || plan.ops) {
1365
+ classifyEditIntent(plan)
1366
+ await runIncrementalEdit(plan, planArg)
1367
+ } else {
1368
+ fail('Unrecognised input format. Expected intent.json (has "metrics") or edit-intent.json (has "op").')
1369
+ }
1370
+
1371
+ } // end entry-point guard