@polymorphism-tech/morph-spec 8.37.1 → 8.40.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 (317) hide show
  1. package/CLAUDE.md +37 -13
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +75 -49
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/CLAUDE.md +6 -5
  8. package/framework/MORPH.md +25 -22
  9. package/framework/agents.json +96 -36
  10. package/framework/docs/CLI.md +54 -17
  11. package/framework/evals/rubrics/code-quality.md +5 -0
  12. package/framework/evals/rubrics/condensed.md +6 -2
  13. package/framework/evals/rubrics/contracts.md +20 -0
  14. package/framework/evals/rubrics/test-coverage.md +17 -6
  15. package/framework/hooks/README.md +9 -3
  16. package/framework/hooks/claude-code/core/graph-refresh-kick.js +52 -0
  17. package/framework/hooks/claude-code/core/telemetry-log.js +172 -87
  18. package/framework/hooks/claude-code/core/validate-completion.js +16 -90
  19. package/framework/hooks/claude-code/core/worktree-context.js +10 -0
  20. package/framework/hooks/shared/command-tokens.js +96 -0
  21. package/framework/hooks/shared/git-exclude.js +44 -0
  22. package/framework/hooks/shared/git-paths.js +52 -0
  23. package/framework/hooks/shared/graph-freshness.js +380 -0
  24. package/framework/hooks/shared/graph-refresh.js +416 -0
  25. package/framework/hooks/shared/morph-cli.js +17 -5
  26. package/framework/hooks/shared/redact-secrets.js +55 -0
  27. package/framework/hooks/shared/telemetry-logger.js +25 -2
  28. package/framework/hooks/shared/transcript-usage.js +80 -0
  29. package/framework/mcp/registry.json +33 -2
  30. package/framework/rubrics/backend.json +2 -2
  31. package/framework/rubrics/default.json +2 -2
  32. package/framework/rubrics/frontend.json +2 -2
  33. package/framework/rules/csharp-standards.md +1 -0
  34. package/framework/rules/infrastructure-standards.md +0 -1
  35. package/framework/rules/morph-workflow.md +10 -4
  36. package/framework/rules/nextjs-standards.md +1 -0
  37. package/framework/schemas/config.schema.json +41 -1
  38. package/framework/schemas/feature.schema.json +5 -1
  39. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  40. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  41. package/framework/skills/core/morph-apply/SKILL.md +40 -11
  42. package/framework/skills/core/morph-brainstorming/SKILL.md +16 -7
  43. package/framework/skills/core/morph-eval/SKILL.md +1 -1
  44. package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
  45. package/framework/skills/core/morph-implement/SKILL.md +44 -10
  46. package/framework/skills/core/morph-media/SKILL.md +1 -1
  47. package/framework/skills/core/morph-plan/SKILL.md +73 -15
  48. package/framework/skills/core/morph-proposal/SKILL.md +1 -1
  49. package/framework/skills/core/morph-review/SKILL.md +51 -13
  50. package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
  51. package/framework/skills/core/morph-standards/SKILL.md +1 -1
  52. package/framework/skills/core/morph-uiux/SKILL.md +39 -13
  53. package/framework/standards/STANDARDS.json +189 -14
  54. package/framework/standards/ai-agents/context-providers.md +16 -26
  55. package/framework/standards/ai-agents/durable-workflows-hitl.md +15 -21
  56. package/framework/standards/ai-agents/modalities-image-gen.md +21 -25
  57. package/framework/standards/ai-agents/modalities-speech-to-text.md +4 -15
  58. package/framework/standards/ai-agents/modalities-text-to-speech.md +2 -11
  59. package/framework/standards/ai-agents/modalities-vision.md +1 -18
  60. package/framework/standards/ai-agents/prompt-sources.md +0 -4
  61. package/framework/standards/ai-agents/testing-ai.md +2 -1
  62. package/framework/standards/architecture/code-comments.md +100 -0
  63. package/framework/standards/backend/dotnet/testing.md +22 -0
  64. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +63 -50
  65. package/framework/standards/frontend/admin-app/data-table.md +562 -0
  66. package/framework/standards/frontend/admin-app/feedback.md +236 -0
  67. package/framework/standards/frontend/admin-app/forms.md +232 -0
  68. package/framework/standards/frontend/admin-app/page-structure.md +203 -0
  69. package/framework/standards/frontend/design-system/ai-image-generation.md +5 -5
  70. package/framework/standards/frontend/nextjs/components.md +37 -58
  71. package/framework/standards/frontend/nextjs/data-fetching.md +1 -0
  72. package/framework/standards/frontend/nextjs/forms.md +31 -30
  73. package/framework/standards/frontend/nextjs/state-management.md +2 -1
  74. package/framework/standards/frontend/nextjs/testing.md +18 -0
  75. package/framework/standards/integration/mcp/mcp-tools.md +48 -117
  76. package/framework/templates/code/dotnet/abstractions/result.cs +0 -2
  77. package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +26 -39
  78. package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +28 -68
  79. package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +99 -117
  80. package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +2 -44
  81. package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +40 -61
  82. package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +54 -107
  83. package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +53 -58
  84. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +192 -281
  85. package/framework/templates/code/dotnet/database/migration.cs +49 -83
  86. package/framework/templates/code/dotnet/database/vector-entity.cs +2 -46
  87. package/framework/templates/code/dotnet/extensions/result-extensions.cs +0 -2
  88. package/framework/templates/code/dotnet/feature/validator.cs.hbs +11 -15
  89. package/framework/templates/code/dotnet/jobs/agent.cs +3 -51
  90. package/framework/templates/code/dotnet/jobs/job.cs +2 -97
  91. package/framework/templates/code/dotnet/test.cs +2 -87
  92. package/framework/templates/code/typescript/contracts.ts +140 -167
  93. package/framework/templates/context/design-system.md +3 -3
  94. package/framework/templates/docs/proposal.md +11 -0
  95. package/framework/templates/docs/spec.md +15 -0
  96. package/framework/templates/docs/ui-mockups.md +115 -98
  97. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentApi.cs +1 -48
  98. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactory.cs +3 -79
  99. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactoryOptions.cs +1 -70
  100. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpec.cs +1 -47
  101. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpecOptions.cs +2 -99
  102. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/AiKitAssemblyMarker.cs +0 -6
  103. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/ConversationStore.cs +3 -88
  104. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/IConversationStore.cs +1 -41
  105. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/InMemoryConversationStore.cs +0 -21
  106. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/CountingChatClient.cs +1 -25
  107. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalAssertion.cs +2 -63
  108. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheMissException.cs +0 -30
  109. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheOptions.cs +1 -52
  110. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheStamp.cs +3 -78
  111. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalFixture.cs +4 -109
  112. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalMode.cs +0 -22
  113. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalQualityEvaluators.cs +1 -36
  114. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalScenario.cs +2 -57
  115. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalSummary.cs +0 -75
  116. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/OfflineChatClient.cs +2 -59
  117. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/ShortPathResponseCache.cs +4 -111
  118. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaGenerator.cs +0 -34
  119. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaProvider.cs +1 -57
  120. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaArtifact.cs +0 -19
  121. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaDisclosure.cs +2 -74
  122. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaGenerator.cs +2 -33
  123. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaIdempotencyKey.cs +1 -43
  124. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJob.cs +1 -96
  125. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobId.cs +0 -13
  126. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobState.cs +0 -27
  127. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaPricing.cs +0 -33
  128. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaProvenance.cs +0 -31
  129. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaRequest.cs +3 -75
  130. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaResult.cs +0 -42
  131. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaReview.cs +0 -39
  132. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaSeams.cs +1 -55
  133. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaStore.cs +3 -59
  134. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MorphMedia.cs +0 -46
  135. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/GoogleImageProvider.cs +3 -28
  136. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs +7 -61
  137. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/VeoVideoProvider.cs +2 -37
  138. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/IUsageCostSink.cs +1 -23
  139. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostMiddleware.cs +2 -82
  140. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostRecord.cs +1 -68
  141. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs +1 -62
  142. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphTelemetryOptions.cs +2 -62
  143. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/IProviderClientFactory.cs +1 -25
  144. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelAlias.cs +0 -124
  145. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelRegistry.cs +1 -73
  146. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaIngest.cs +1 -66
  147. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaPlan.cs +0 -41
  148. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentFactoryTests.cs +2 -112
  149. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentSpecTests.cs +2 -43
  150. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ConversationStoreTests.cs +5 -110
  151. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/DeltaIngestTests.cs +7 -103
  152. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalAssertionTests.cs +1 -42
  153. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheMissTests.cs +1 -30
  154. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheStampTests.cs +1 -19
  155. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFailuresTests.cs +0 -48
  156. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFixtureTests.cs +1 -29
  157. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalRefreshTests.cs +2 -38
  158. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalWorkspace.cs +1 -14
  159. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/KitEvals.cs +4 -69
  160. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/OfflineChatClientTests.cs +1 -10
  161. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClient.cs +1 -57
  162. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClientTests.cs +0 -26
  163. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeClock.cs +1 -19
  164. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeMediaProvider.cs +0 -32
  165. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeProviderClientFactory.cs +0 -14
  166. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeUsageCostSink.cs +0 -24
  167. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/InMemoryMediaStore.cs +0 -32
  168. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAccessibilityTests.cs +0 -37
  169. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAliasIsNotAnAgentTests.cs +0 -24
  170. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +0 -78
  171. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaGeneratorTests.cs +0 -53
  172. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaIdempotencyKeyTests.cs +0 -44
  173. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaJobStateTests.cs +0 -44
  174. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaReviewTests.cs +0 -19
  175. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaStoreTests.cs +0 -24
  176. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ModelRegistryTests.cs +6 -48
  177. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/SkeletonSmokeTests.cs +1 -13
  178. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/TelemetryTests.cs +2 -71
  179. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/UsageCostMiddlewareTests.cs +5 -100
  180. package/framework/templates/feature/decisions.md +124 -122
  181. package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +39 -43
  182. package/framework/templates/frontend/nextjs/env.mjs.hbs +29 -32
  183. package/framework/templates/frontend/nextjs/page.tsx.hbs +21 -22
  184. package/framework/templates/frontend/nextjs/use-feature.ts.hbs +42 -54
  185. package/framework/templates/integrations/asaas-client.cs +332 -387
  186. package/framework/templates/integrations/asaas-webhook.cs +290 -351
  187. package/framework/templates/integrations/neon-auth-config.cs +9 -105
  188. package/framework/templates/project/validate.js +97 -120
  189. package/package.json +2 -2
  190. package/src/commands/dashboard/dashboard.js +80 -53
  191. package/src/commands/graph/affected.js +4 -3
  192. package/src/commands/graph/build.js +109 -18
  193. package/src/commands/graph/explain.js +8 -5
  194. package/src/commands/graph/status.js +14 -8
  195. package/src/commands/mcp/mcp-setup.js +37 -9
  196. package/src/commands/observability/cost.js +148 -18
  197. package/src/commands/project/doctor.js +85 -15
  198. package/src/commands/project/init.js +6 -3
  199. package/src/commands/project/install-plugin-cmd.js +1 -1
  200. package/src/commands/project/update.js +30 -0
  201. package/src/commands/project/worktree.js +73 -90
  202. package/src/commands/state/advance.js +18 -0
  203. package/src/commands/state/approve.js +15 -0
  204. package/src/commands/state/archive.js +62 -9
  205. package/src/commands/state/finish.js +62 -14
  206. package/src/commands/state/gate-check.js +8 -1
  207. package/src/commands/state/gate-decision.js +8 -4
  208. package/src/commands/state/report-check.js +90 -9
  209. package/src/commands/state/usecase.js +66 -0
  210. package/src/commands/tasks/dag.js +17 -2
  211. package/src/commands/validation/validate-feature.js +6 -1
  212. package/src/commands/validation/verify.js +20 -1
  213. package/src/dashboard/app/App.jsx +80 -16
  214. package/src/dashboard/app/components/ActivityFeed.jsx +172 -0
  215. package/src/dashboard/app/components/CommandPalette.jsx +155 -0
  216. package/src/dashboard/app/components/DetailPanel.jsx +47 -11
  217. package/src/dashboard/app/components/EntityLink.jsx +55 -0
  218. package/src/dashboard/app/components/ErrorBoundary.jsx +54 -0
  219. package/src/dashboard/app/components/FlowGraph.jsx +19 -17
  220. package/src/dashboard/app/components/KnowledgeMarkdown.jsx +53 -0
  221. package/src/dashboard/app/components/Markdown.jsx +47 -0
  222. package/src/dashboard/app/components/PhaseRail.jsx +111 -0
  223. package/src/dashboard/app/components/SearchFilter.jsx +40 -22
  224. package/src/dashboard/app/components/Sidebar.jsx +146 -37
  225. package/src/dashboard/app/hooks/useMorphQuery.js +54 -0
  226. package/src/dashboard/app/hooks/usePref.js +38 -0
  227. package/src/dashboard/app/lib/format.js +69 -0
  228. package/src/dashboard/app/lib/phases.js +56 -0
  229. package/src/dashboard/app/lib/project.js +50 -0
  230. package/src/dashboard/app/pages/Activity.jsx +24 -0
  231. package/src/dashboard/app/pages/AgentMap.jsx +371 -370
  232. package/src/dashboard/app/pages/FeatureDetail.jsx +604 -0
  233. package/src/dashboard/app/pages/Features.jsx +400 -0
  234. package/src/dashboard/app/pages/Guide.jsx +146 -0
  235. package/src/dashboard/app/pages/HookInspector.jsx +357 -322
  236. package/src/dashboard/app/pages/PhasePipeline.jsx +277 -408
  237. package/src/dashboard/app/pages/Portfolio.jsx +156 -0
  238. package/src/dashboard/app/pages/Rubrics.jsx +101 -0
  239. package/src/dashboard/app/pages/RulesMap.jsx +300 -273
  240. package/src/dashboard/app/pages/SkillsLibrary.jsx +483 -366
  241. package/src/dashboard/app/pages/Standards.jsx +407 -332
  242. package/src/dashboard/app/styles/index.css +187 -47
  243. package/src/dashboard/index.html +14 -12
  244. package/src/dashboard/package.json +32 -24
  245. package/src/dashboard/scanner/activity-scanner.js +351 -0
  246. package/src/dashboard/scanner/agents-scanner.js +63 -1
  247. package/src/dashboard/scanner/docs-scanner.js +59 -0
  248. package/src/dashboard/scanner/feature-status.js +10 -0
  249. package/src/dashboard/scanner/features-scanner.js +360 -0
  250. package/src/dashboard/scanner/hooks-scanner.js +8 -1
  251. package/src/dashboard/scanner/index.js +14 -7
  252. package/src/dashboard/scanner/phases-scanner.js +14 -15
  253. package/src/dashboard/scanner/portfolio.js +153 -0
  254. package/src/dashboard/scanner/project-api.js +195 -0
  255. package/src/dashboard/scanner/rules-scanner.js +42 -37
  256. package/src/dashboard/scanner/skills-scanner.js +105 -43
  257. package/src/dashboard/scanner/standards-scanner.js +4 -1
  258. package/src/dashboard/vite-plugin-morph-data.js +134 -17
  259. package/src/lib/ai/comment-stripper.js +101 -4
  260. package/src/lib/detectors/claude-config-detector.js +2 -7
  261. package/src/lib/detectors/index.js +5 -1
  262. package/src/lib/evaluator-report.js +47 -0
  263. package/src/lib/generators/handoff-generator.js +4 -18
  264. package/src/lib/generators/settings-generator.js +208 -209
  265. package/src/lib/git/default-branch.js +52 -0
  266. package/src/lib/git/tree-fingerprint.js +58 -0
  267. package/src/lib/git/tree-state.js +167 -0
  268. package/src/lib/graph/god-nodes.js +12 -3
  269. package/src/lib/graph/graph-health.js +48 -2
  270. package/src/lib/graph/graph-loader.js +99 -25
  271. package/src/lib/graph/graphifyignore.js +145 -28
  272. package/src/lib/graph/sanitize.js +117 -11
  273. package/src/lib/installers/mcp-installer.js +724 -719
  274. package/src/lib/installers/memory-installer.js +1 -2
  275. package/src/lib/projects/registry.js +154 -0
  276. package/src/lib/risk-detector.js +90 -0
  277. package/src/lib/specs/acervo-format.js +70 -0
  278. package/src/lib/specs/acervo-lifecycle.js +264 -0
  279. package/src/lib/specs/adr-index.js +169 -0
  280. package/src/lib/specs/revocations.js +156 -0
  281. package/src/lib/specs/screen-checklist.js +357 -0
  282. package/src/lib/specs/usecase-check.js +20 -16
  283. package/src/lib/specs/usecase-promoter.js +103 -38
  284. package/src/lib/specs/usecase-registry.js +7 -7
  285. package/src/lib/tasks/tasks-json-parser.js +2 -3
  286. package/src/lib/telemetry/metrics.js +386 -0
  287. package/src/lib/telemetry/telemetry-reader.js +161 -51
  288. package/src/lib/telemetry/verify-event.js +79 -0
  289. package/src/lib/validators/code-budget/code-budget-validator.js +200 -0
  290. package/src/lib/validators/code-budget/comment-scanner.js +75 -0
  291. package/src/lib/validators/code-budget/index.js +9 -0
  292. package/src/lib/validators/reuse/reuse-validator.js +4 -2
  293. package/src/lib/validators/reuse/symbol-scanner.js +27 -22
  294. package/src/lib/validators/validation-runner.js +21 -5
  295. package/src/lib/validators/verify-runner.js +11 -0
  296. package/src/lib/worktree/finish-backup.js +739 -0
  297. package/src/lib/worktree/ignored-triage.js +15 -8
  298. package/src/lib/worktree/worktree-audit.js +5 -0
  299. package/src/scripts/install-plugin.js +1 -1
  300. package/src/scripts/setup-infra.js +31 -22
  301. package/src/utils/agents-installer.js +338 -24
  302. package/src/utils/banner.js +1 -1
  303. package/src/utils/hooks-installer.js +75 -15
  304. package/src/commands/index.js +0 -13
  305. package/src/commands/project/checkpoint.js +0 -209
  306. package/src/core/state/phase-state-machine.js +0 -197
  307. package/src/dashboard/app/hooks/useDetailPanel.js +0 -15
  308. package/src/dashboard/app/pages/LiveState.jsx +0 -206
  309. package/src/dashboard/scanner/squads-scanner.js +0 -13
  310. package/src/dashboard/scanner/state-scanner.js +0 -85
  311. package/src/lib/generators/index.js +0 -10
  312. package/src/lib/hooks/hook-executor.js +0 -167
  313. package/src/lib/validators/checkpoint-persistence.js +0 -39
  314. package/src/lib/validators/shared/emit-validator-dispatch.js +0 -14
  315. package/src/lib/validators/shared/index.js +0 -12
  316. package/src/lib/validators/shared/issue-counter.js +0 -14
  317. package/src/lib/validators/shared/result-formatter.js +0 -124
@@ -0,0 +1,156 @@
1
+ import { useState } from 'react';
2
+ import { Link } from 'react-router-dom';
3
+ import { FolderSimplePlus, X, ArrowRight } from '@phosphor-icons/react';
4
+ import { FeatureRow, isWorking } from './Features.jsx';
5
+ import { useProjects, projectHref, announceProjectsChanged } from '../lib/project.js';
6
+ import { useNow } from '../hooks/usePref.js';
7
+ import { timeAgo } from '../lib/format.js';
8
+
9
+ const ACTIVE_SHOWN = 4;
10
+
11
+ async function send(method, url, body) {
12
+ const res = await fetch(url, {
13
+ method,
14
+ headers: body ? { 'Content-Type': 'application/json' } : undefined,
15
+ body: body ? JSON.stringify(body) : undefined,
16
+ });
17
+ const out = await res.json().catch(() => ({}));
18
+ if (!res.ok) throw new Error(out.error || `HTTP ${res.status}`);
19
+ return out;
20
+ }
21
+
22
+ function ProjectBlock({ p, now, onRemove }) {
23
+ const s = p.summary;
24
+ const working = s ? s.activeFeatures.filter((f) => isWorking(f, now)).length : 0;
25
+ // What waits on you is already listed at the top of the page; here, the rest, latest first.
26
+ const rest = s ? s.activeFeatures.filter((f) => !f.awaiting) : [];
27
+ const shown = [...rest].sort((a, b) => (b.lastActivity?.ts || '').localeCompare(a.lastActivity?.ts || '')).slice(0, ACTIVE_SHOWN);
28
+ return (
29
+ <section className="bezel" aria-label={p.name}>
30
+ <div className="bezel-core overflow-hidden">
31
+ <header className="flex flex-col gap-3 px-5 py-4 md:flex-row md:items-center md:justify-between">
32
+ <div className="min-w-0">
33
+ <Link to={projectHref(p.id)} className="text-lg font-semibold tracking-tight hover:underline underline-offset-4">{p.name}</Link>
34
+ <p className="mt-0.5 truncate font-mono text-xs text-[var(--color-faint)]" title={p.dir}>{p.dir}</p>
35
+ </div>
36
+ <div className="flex flex-wrap items-center gap-x-5 gap-y-1 whitespace-nowrap text-sm md:shrink-0">
37
+ {!s && <span className="text-[var(--color-faint)]">lendo…</span>}
38
+ {s && (
39
+ <>
40
+ <span className="text-[var(--color-dim)]"><span className="font-mono text-[var(--color-fg)]">{s.active}</span> ativas</span>
41
+ {s.awaiting > 0 && <span className="text-[var(--color-warn)]"><span className="font-mono">{s.awaiting}</span> esperando você</span>}
42
+ {working > 0 && <span className="text-[var(--color-phase-implement)]">agente trabalhando</span>}
43
+ <span className="text-xs text-[var(--color-faint)]">{s.lastActivityTs ? `atividade ${timeAgo(s.lastActivityTs, now)}` : `${s.total} features`}</span>
44
+ </>
45
+ )}
46
+ <Link to={projectHref(p.id)} aria-label={`Abrir ${p.name}`}
47
+ className="fluid flex h-8 w-8 items-center justify-center rounded-full bg-white/[0.05] text-[var(--color-dim)] transition-transform hover:translate-x-0.5 hover:text-[var(--color-fg)]">
48
+ <ArrowRight weight="light" size={15} />
49
+ </Link>
50
+ {!p.launch && (
51
+ <button type="button" onClick={() => onRemove(p)} aria-label={`Remover ${p.name} do portfólio`} title="Remover do portfólio (não apaga nada)"
52
+ className="fluid flex h-8 w-8 items-center justify-center rounded-full text-[var(--color-faint)] transition-colors hover:bg-white/[0.05] hover:text-[var(--color-dim)]">
53
+ <X weight="light" size={14} />
54
+ </button>
55
+ )}
56
+ </div>
57
+ </header>
58
+ {s && shown.length > 0 && (
59
+ <ul className="divide-y divide-[var(--color-hair)] border-t border-[var(--color-hair)]">
60
+ {shown.map((f) => <FeatureRow key={f.name} f={f} now={now} project={p.id} />)}
61
+ </ul>
62
+ )}
63
+ {s && rest.length > ACTIVE_SHOWN && (
64
+ <Link to={projectHref(p.id)} className="block border-t border-[var(--color-hair)] px-5 py-2.5 text-sm text-[var(--color-dim)] hover:text-[var(--color-fg)]">
65
+ Ver as {s.active} features ativas
66
+ </Link>
67
+ )}
68
+ {s && s.active === 0 && (
69
+ <p className="border-t border-[var(--color-hair)] px-5 py-3 text-sm text-[var(--color-faint)]">
70
+ {s.legacyStateOnly ? 'Projeto no modelo de estado antigo: rode morph-spec update nele.' : 'Nada em andamento.'}
71
+ </p>
72
+ )}
73
+ </div>
74
+ </section>
75
+ );
76
+ }
77
+
78
+ export function PortfolioView({ data, now = Date.now(), onAdd = () => {}, onRemove = () => {}, busy = null, error = null }) {
79
+ const projects = data.projects || [];
80
+ const ready = projects.filter((p) => p.summary);
81
+ const totalActive = ready.reduce((n, p) => n + p.summary.active, 0);
82
+ const totalAwaiting = ready.reduce((n, p) => n + p.summary.awaiting, 0);
83
+ const awaiting = ready.flatMap((p) => p.summary.activeFeatures.filter((f) => f.awaiting).map((f) => ({ f, p })));
84
+ const ordered = [...projects].sort((a, b) => (b.summary?.lastActivityTs || '').localeCompare(a.summary?.lastActivityTs || ''));
85
+
86
+ return (
87
+ <div className="mx-auto max-w-6xl px-4 pb-24 pt-10 md:px-10 md:pt-14">
88
+ <header className="rise mb-10">
89
+ <h1 className="text-4xl font-semibold tracking-tight md:text-5xl">Portfólio</h1>
90
+ <p className="mt-3 text-sm text-[var(--color-dim)]">
91
+ {projects.length} {projects.length === 1 ? 'projeto' : 'projetos'}, {totalActive} features ativas
92
+ {totalAwaiting > 0 && <span className="text-[var(--color-warn)]">, {totalAwaiting} esperando você</span>}
93
+ </p>
94
+ </header>
95
+
96
+ {awaiting.length > 0 && (
97
+ <section className="rise-2 mb-10">
98
+ <h2 className="mb-3 px-1 text-sm font-medium">Esperando você</h2>
99
+ <div className="bezel">
100
+ <ul className="bezel-core divide-y divide-[var(--color-hair)] overflow-hidden">
101
+ {awaiting.map(({ f, p }) => <FeatureRow key={`${p.id}:${f.name}`} f={f} now={now} project={p.id} projectName={p.name} />)}
102
+ </ul>
103
+ </div>
104
+ </section>
105
+ )}
106
+
107
+ <div className="rise-3 space-y-6">
108
+ {ordered.map((p) => <ProjectBlock key={p.id} p={p} now={now} onRemove={onRemove} />)}
109
+ </div>
110
+
111
+ <section className="mt-14" aria-labelledby="found">
112
+ <h2 id="found" className="px-1 text-sm font-medium">Outros projetos com morph-spec</h2>
113
+ <p className="mb-4 mt-1 px-1 text-sm text-[var(--color-dim)]">
114
+ Encontrados nas pastas vizinhas dos projetos acima. Projetos também entram sozinhos quando você roda
115
+ <code className="mx-1 font-mono text-[var(--color-fg)]">morph-spec init</code>,
116
+ <code className="mx-1 font-mono text-[var(--color-fg)]">update</code> ou
117
+ <code className="mx-1 font-mono text-[var(--color-fg)]">dashboard</code> neles.
118
+ </p>
119
+ {error && <p className="mb-3 px-1 text-sm text-[var(--color-bad)]">{error}</p>}
120
+ {(data.suggestions || []).length === 0 && <p className="px-1 text-sm text-[var(--color-faint)]">Nenhum outro encontrado.</p>}
121
+ <ul className="grid grid-cols-1 gap-2 md:grid-cols-2">
122
+ {(data.suggestions || []).map((s) => (
123
+ <li key={s.dir} className="flex min-w-0 items-center justify-between gap-3 rounded-xl px-4 py-3 shadow-[inset_0_0_0_1px_var(--color-hair)]">
124
+ <div className="min-w-0">
125
+ <p className="truncate text-sm text-[var(--color-fg)]">{s.name}</p>
126
+ <p className="truncate font-mono text-xs text-[var(--color-faint)]" title={s.dir}>{s.dir}</p>
127
+ </div>
128
+ <button type="button" onClick={() => onAdd(s.dir)} disabled={busy === s.dir}
129
+ className="fluid inline-flex shrink-0 items-center gap-1.5 rounded-full bg-white/[0.06] px-3 py-1.5 text-sm text-[var(--color-fg)] transition-colors hover:bg-white/[0.1] active:scale-[0.98] disabled:opacity-50">
130
+ <FolderSimplePlus weight="light" size={15} /> {busy === s.dir ? 'Adicionando…' : 'Adicionar'}
131
+ </button>
132
+ </li>
133
+ ))}
134
+ </ul>
135
+ </section>
136
+ </div>
137
+ );
138
+ }
139
+
140
+ export default function Portfolio() {
141
+ const { data, error } = useProjects();
142
+ const now = useNow();
143
+ const [busy, setBusy] = useState(null);
144
+ const [actionError, setActionError] = useState(null);
145
+ const run = async (dir, fn) => {
146
+ setBusy(dir); setActionError(null);
147
+ // The server also pushes the change; reading again here does not depend on it.
148
+ try { await fn(); announceProjectsChanged(); } catch (err) { setActionError(err.message); } finally { setBusy(null); }
149
+ };
150
+ const onAdd = (dir) => run(dir, () => send('POST', '/api/morph/projects', { dir }));
151
+ const onRemove = (p) => run(p.dir, () => send('DELETE', `/api/morph/projects?dir=${encodeURIComponent(p.dir)}`));
152
+
153
+ if (error) return <p className="px-10 pt-16 text-sm text-[var(--color-bad)]">Não consegui ler o portfólio: {error}</p>;
154
+ if (!data) return <p className="px-10 pt-16 text-sm text-[var(--color-faint)]">Lendo os projetos…</p>;
155
+ return <PortfolioView data={data} now={now} onAdd={onAdd} onRemove={onRemove} busy={busy} error={actionError} />;
156
+ }
@@ -0,0 +1,101 @@
1
+ import morphData from 'virtual:morph-data';
2
+ import KnowledgeMarkdown from '../components/KnowledgeMarkdown.jsx';
3
+ import { useSelection } from '../components/EntityLink.jsx';
4
+
5
+ const DOCS = morphData.docs || { rubrics: [], proofRubrics: [] };
6
+ const README = DOCS.rubrics.find((r) => r.id === 'README');
7
+ const DIMENSIONS = DOCS.rubrics.filter((r) => r.id !== 'README' && r.id !== 'condensed');
8
+ const CONDENSED = DOCS.rubrics.find((r) => r.id === 'condensed');
9
+ const VALIDATORS = morphData.rubrics || [];
10
+
11
+ const GROUPS = [
12
+ { title: 'Dimensões do avaliador', hint: 'o score composto sai destas quatro', items: DIMENSIONS.map((r) => ({ key: `dim:${r.id}`, title: r.title, doc: r })) },
13
+ { title: 'Versão curta', hint: 'usada na avaliação por task', items: CONDENSED ? [{ key: 'dim:condensed', title: CONDENSED.title, doc: CONDENSED }] : [] },
14
+ { title: 'Provas', hint: 'o que o avaliador precisa ver acontecer', items: DOCS.proofRubrics.filter((r) => r.id !== 'README').map((r) => ({ key: `proof:${r.id}`, title: r.title, doc: r })) },
15
+ { title: 'Validadores determinísticos', hint: 'pesos por categoria no verify', items: VALIDATORS.map((v) => ({ key: `val:${v.id}`, title: `Rubrica ${v.id}`, validator: v })) },
16
+ ].filter((g) => g.items.length);
17
+
18
+ const ALL = GROUPS.flatMap((g) => g.items);
19
+
20
+ function ValidatorRubric({ v }) {
21
+ return (
22
+ <article className="prose-morph">
23
+ <h1>Rubrica {v.id}</h1>
24
+ {v.description && <p>{v.description}</p>}
25
+ <table>
26
+ <thead><tr><th>Categoria</th><th>Peso</th><th>Validadores</th><th>O que mede</th></tr></thead>
27
+ <tbody>
28
+ {Object.entries(v.categories).map(([name, c]) => (
29
+ <tr key={name}>
30
+ <td>{name}</td>
31
+ <td className="font-mono">{c.weight ?? '—'}</td>
32
+ <td className="font-mono text-xs">{(c.validators || []).join(', ') || '—'}</td>
33
+ <td>{c.description || ''}</td>
34
+ </tr>
35
+ ))}
36
+ </tbody>
37
+ </table>
38
+ <p>Aprova com <strong>{v.thresholds?.approve ?? '—'}</strong>; abaixo de <strong>{v.thresholds?.retry ?? '—'}</strong> a task volta para correção.</p>
39
+ </article>
40
+ );
41
+ }
42
+
43
+ export function RubricsView({ sel, onSel }) {
44
+ const current = ALL.find((i) => i.key === sel) || null;
45
+ return (
46
+ <div className="mx-auto max-w-7xl px-4 pb-24 pt-10 md:px-10 md:pt-14">
47
+ <header className="rise mb-8">
48
+ <h1 className="text-4xl font-semibold tracking-tight md:text-5xl">Rubricas</h1>
49
+ <p className="mt-3 max-w-2xl text-sm leading-relaxed text-[var(--color-dim)]">
50
+ Com o que o trabalho é julgado. O avaliador independente pontua cada dimensão de 0 a 10, e o Gate 3 exige score composto 9.
51
+ Os validadores rodam no <span className="font-mono text-[var(--color-fg)]">morph-spec verify</span>, sem modelo.
52
+ </p>
53
+ </header>
54
+ <div className="rise-2 grid gap-6 lg:grid-cols-[17rem_minmax(0,1fr)]">
55
+ <nav aria-label="Rubricas" className="lg:sticky lg:top-4 lg:self-start">
56
+ <button
57
+ type="button"
58
+ onClick={() => onSel(null)}
59
+ aria-current={!current ? 'page' : undefined}
60
+ className={['fluid mb-4 block w-full rounded-lg px-3 py-2 text-left text-sm transition-colors', !current ? 'bg-white/[0.08] text-[var(--color-fg)]' : 'text-[var(--color-dim)] hover:bg-white/[0.04]'].join(' ')}
61
+ >
62
+ Como a nota é calculada
63
+ </button>
64
+ {GROUPS.map((g) => (
65
+ <div key={g.title} className="mb-5">
66
+ <p className="px-3 text-xs text-[var(--color-faint)]">{g.title}</p>
67
+ <p className="mb-1.5 px-3 text-[11px] text-[var(--color-faint)]">{g.hint}</p>
68
+ <ul>
69
+ {g.items.map((i) => (
70
+ <li key={i.key}>
71
+ <button
72
+ type="button"
73
+ onClick={() => onSel(i.key)}
74
+ aria-current={current?.key === i.key ? 'page' : undefined}
75
+ className={['fluid block w-full truncate rounded-lg px-3 py-1.5 text-left text-sm transition-colors', current?.key === i.key ? 'bg-white/[0.08] text-[var(--color-fg)]' : 'text-[var(--color-dim)] hover:bg-white/[0.04] hover:text-[var(--color-fg)]'].join(' ')}
76
+ title={i.title}
77
+ >
78
+ {i.title}
79
+ </button>
80
+ </li>
81
+ ))}
82
+ </ul>
83
+ </div>
84
+ ))}
85
+ </nav>
86
+ <div className="bezel min-w-0">
87
+ <div className="bezel-core min-w-0 px-6 py-8 md:px-12 md:py-10">
88
+ {!current && (README ? <KnowledgeMarkdown text={README.content} /> : <p className="text-sm text-[var(--color-dim)]">Escolha uma rubrica.</p>)}
89
+ {current?.doc && <KnowledgeMarkdown text={current.doc.content} />}
90
+ {current?.validator && <ValidatorRubric v={current.validator} />}
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ );
96
+ }
97
+
98
+ export default function Rubrics() {
99
+ const [sel, setSel] = useSelection();
100
+ return <RubricsView sel={sel} onSel={setSel} />;
101
+ }