@polymorphism-tech/morph-spec 4.3.7 → 4.6.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 (394) hide show
  1. package/.morph/.morphversion +3 -3
  2. package/.morph/analytics/threads-log.jsonl +6 -9
  3. package/.morph/config/config.json +2 -3
  4. package/.morph/framework/standards/STANDARDS.json +812 -0
  5. package/.morph/{standards → framework/standards}/ai-agents/team-orchestration.md +3 -3
  6. package/.morph/{standards → framework/standards}/frontend/nextjs/nextjs-patterns.md +17 -0
  7. package/.morph/framework/standards/integration/mcp/mcp-tools.md +384 -0
  8. package/.morph/{templates → framework/templates}/README.md +17 -17
  9. package/.morph/{templates → framework/templates}/REGISTRY.json +48 -233
  10. package/.morph/framework/templates/code/dotnet/contracts/contracts.cs.hbs +172 -0
  11. package/.morph/{templates → framework/templates}/context/CONTEXT-FEATURE.md +1 -1
  12. package/.morph/{templates → framework/templates}/context/CONTEXT.md +3 -3
  13. package/.morph/framework/templates/docs/clarifications.md +253 -0
  14. package/.morph/framework/templates/docs/onboarding.md +123 -0
  15. package/.morph/framework/templates/docs/schema-analysis.md +119 -0
  16. package/.morph/{templates → framework/templates}/docs/spec.md +149 -149
  17. package/.morph/framework/templates/docs/ui-components.md +124 -0
  18. package/.morph/framework/templates/docs/ui-design-system.md +76 -0
  19. package/.morph/framework/templates/docs/ui-flows.md +167 -0
  20. package/.morph/framework/templates/docs/ui-mockups.md +98 -0
  21. package/.morph/framework/templates/docs/user-stories.md +34 -0
  22. package/.morph/{templates → framework/templates}/examples/spec-examples.md +1 -1
  23. package/.morph/{templates → framework/templates}/infrastructure/github/README.md +11 -11
  24. package/.morph/{templates → framework/templates}/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +2 -2
  25. package/.morph/{templates → framework/templates}/meta-prompts/parallel-workers/parallel-worker.md +2 -2
  26. package/.morph/{templates → framework/templates}/meta-prompts/validators/pre-commit-validator.md +1 -1
  27. package/.morph/logs/tool-failures.log +7 -0
  28. package/.morph/memory/pre-compact-2026-02-23T15-43-03-521Z.json +16 -0
  29. package/.morph/state.json +1 -1
  30. package/CLAUDE.md +77 -155
  31. package/README.md +20 -18
  32. package/bin/detect-agents.js +1 -1
  33. package/bin/morph-spec.js +116 -266
  34. package/bin/task-manager.cjs +2 -2
  35. package/bin/validate.js +1 -1
  36. package/claude-plugin.json +14 -0
  37. package/docs/claude-alignment-report.md +137 -0
  38. package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +512 -0
  39. package/docs/plans/2026-02-22-claude-settings.md +515 -0
  40. package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +728 -0
  41. package/docs/plans/2026-02-22-morph-spec-next.md +478 -0
  42. package/docs/plans/2026-02-22-native-alignment-design.md +199 -0
  43. package/docs/plans/2026-02-22-native-alignment-impl.md +925 -0
  44. package/docs/plans/2026-02-22-native-enrichment-design.md +244 -0
  45. package/docs/plans/2026-02-22-native-enrichment.md +735 -0
  46. package/framework/CLAUDE.md +77 -0
  47. package/framework/{skills/level-2-domains → agents}/ai-agents/ai-system-architect.md +7 -3
  48. package/framework/{skills/level-2-domains → agents}/architecture/po-pm-advisor.md +7 -1
  49. package/framework/{skills/level-2-domains → agents}/architecture/prompt-engineer.md +7 -1
  50. package/framework/{skills/level-2-domains → agents}/architecture/seo-growth-hacker.md +7 -1
  51. package/framework/{skills/level-2-domains → agents}/architecture/standards-architect.md +10 -6
  52. package/framework/agents/backend/api-designer.md +103 -0
  53. package/framework/{skills/level-2-domains → agents}/backend/dotnet-senior.md +7 -1
  54. package/framework/agents/backend/ef-modeler.md +119 -0
  55. package/framework/{skills/level-2-domains → agents}/backend/hangfire-orchestrator.md +8 -4
  56. package/framework/{skills/level-2-domains → agents}/backend/ms-agent-expert.md +7 -3
  57. package/framework/{skills/level-2-domains → agents}/frontend/blazor-builder.md +7 -3
  58. package/framework/{skills/level-2-domains → agents}/frontend/nextjs-expert.md +7 -3
  59. package/framework/{skills/level-2-domains → agents}/frontend/ui-ux-designer.md +8 -2
  60. package/framework/{skills/level-2-domains → agents}/infrastructure/azure-architect.md +7 -1
  61. package/framework/{skills/level-2-domains → agents}/infrastructure/azure-deploy-specialist.md +7 -1
  62. package/framework/{skills/level-2-domains → agents}/infrastructure/bicep-architect.md +7 -3
  63. package/framework/{skills/level-2-domains → agents}/infrastructure/container-specialist.md +7 -3
  64. package/framework/{skills/level-2-domains → agents}/infrastructure/devops-engineer.md +7 -3
  65. package/framework/{skills/level-2-domains → agents}/integrations/asaas-financial.md +7 -3
  66. package/framework/{skills/level-2-domains → agents}/integrations/azure-identity.md +7 -3
  67. package/framework/{skills/level-2-domains → agents}/integrations/clerk-auth.md +7 -3
  68. package/framework/{skills/level-2-domains/integrations/hangfire-orchestrator.md → agents/integrations/hangfire-integration.md} +7 -1
  69. package/framework/{skills/level-2-domains → agents}/integrations/resend-email.md +7 -3
  70. package/framework/{skills/level-2-domains → agents}/quality/code-analyzer.md +9 -5
  71. package/framework/{skills/level-2-domains → agents}/quality/testing-specialist.md +7 -3
  72. package/framework/commands/morph-apply.md +9 -9
  73. package/framework/commands/morph-archive.md +8 -8
  74. package/framework/commands/morph-infra.md +1 -1
  75. package/framework/commands/morph-proposal.md +9 -9
  76. package/framework/commands/morph-status.md +3 -3
  77. package/framework/commands/morph-troubleshoot.md +1 -1
  78. package/framework/hooks/README.md +201 -282
  79. package/framework/hooks/claude-code/notification/approval-reminder.js +52 -0
  80. package/framework/hooks/claude-code/post-tool-use/dispatch.js +83 -0
  81. package/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +42 -0
  82. package/framework/hooks/claude-code/pre-compact/save-morph-context.js +61 -0
  83. package/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +71 -0
  84. package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +58 -0
  85. package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +64 -0
  86. package/framework/hooks/claude-code/session-start/inject-morph-context.js +94 -0
  87. package/framework/hooks/claude-code/statusline.py +538 -0
  88. package/framework/hooks/claude-code/statusline.sh +7 -0
  89. package/framework/hooks/claude-code/stop/validate-completion.js +88 -0
  90. package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +91 -0
  91. package/framework/hooks/shared/hook-response.js +45 -0
  92. package/framework/hooks/shared/phase-utils.js +129 -0
  93. package/framework/hooks/shared/state-reader.js +138 -0
  94. package/framework/hooks/shared/stdin-reader.js +26 -0
  95. package/framework/phases.json +145 -0
  96. package/framework/rules/csharp-standards.md +10 -0
  97. package/framework/rules/frontend-standards.md +14 -0
  98. package/framework/rules/infrastructure-standards.md +13 -0
  99. package/framework/rules/morph-workflow.md +86 -0
  100. package/framework/rules/testing-standards.md +11 -0
  101. package/framework/skills/README.md +66 -0
  102. package/framework/skills/level-0-meta/brainstorming/SKILL.md +135 -0
  103. package/framework/skills/level-0-meta/brainstorming/references/proposal-example.md +138 -0
  104. package/framework/skills/level-0-meta/{code-review.md → code-review/SKILL.md} +13 -4
  105. package/framework/skills/level-0-meta/code-review/references/review-example.md +164 -0
  106. package/framework/skills/level-0-meta/code-review/scripts/scan-csharp.mjs +121 -0
  107. package/framework/skills/level-0-meta/mcp-registry.json +207 -0
  108. package/framework/skills/level-0-meta/{morph-checklist.md → morph-checklist/SKILL.md} +8 -3
  109. package/framework/skills/{level-1-workflows/morph-replicate.md → level-0-meta/morph-replicate/SKILL.md} +13 -6
  110. package/framework/skills/level-0-meta/{simulation-checklist.md → simulation-checklist/SKILL.md} +9 -4
  111. package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +334 -0
  112. package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +147 -0
  113. package/framework/skills/level-0-meta/verification-before-completion/scripts/check-phase-outputs.mjs +110 -0
  114. package/framework/skills/level-1-workflows/{phase-clarify.md → phase-clarify/SKILL.md} +65 -4
  115. package/framework/skills/level-1-workflows/phase-clarify/references/clarifications-example.md +117 -0
  116. package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +181 -0
  117. package/framework/skills/level-1-workflows/phase-design/SKILL.md +303 -0
  118. package/framework/skills/level-1-workflows/phase-design/references/spec-example.md +253 -0
  119. package/framework/skills/level-1-workflows/phase-implement/SKILL.md +254 -0
  120. package/framework/skills/level-1-workflows/phase-implement/references/recap-example.md +132 -0
  121. package/framework/skills/level-1-workflows/phase-setup/SKILL.md +171 -0
  122. package/framework/skills/level-1-workflows/{phase-tasks.md → phase-tasks/SKILL.md} +89 -7
  123. package/framework/skills/level-1-workflows/phase-tasks/references/tasks-example.md +231 -0
  124. package/framework/skills/level-1-workflows/phase-tasks/scripts/validate-tasks.mjs +112 -0
  125. package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +246 -0
  126. package/framework/standards/STANDARDS.json +812 -0
  127. package/framework/standards/ai-agents/team-orchestration.md +3 -3
  128. package/framework/standards/frontend/nextjs/nextjs-patterns.md +17 -0
  129. package/framework/standards/integration/mcp/mcp-tools.md +384 -0
  130. package/framework/templates/README.md +17 -17
  131. package/framework/templates/REGISTRY.json +48 -233
  132. package/framework/templates/code/dotnet/contracts/contracts.cs.hbs +172 -0
  133. package/framework/templates/context/CONTEXT-FEATURE.md +1 -1
  134. package/framework/templates/context/CONTEXT.md +3 -3
  135. package/framework/templates/docs/clarifications.md +253 -0
  136. package/framework/templates/docs/onboarding.md +123 -0
  137. package/framework/templates/docs/schema-analysis.md +119 -0
  138. package/framework/templates/docs/spec.md +149 -149
  139. package/framework/templates/docs/ui-components.md +124 -0
  140. package/framework/templates/docs/ui-design-system.md +76 -0
  141. package/framework/templates/docs/ui-flows.md +167 -0
  142. package/framework/templates/docs/ui-mockups.md +98 -0
  143. package/framework/templates/docs/user-stories.md +34 -0
  144. package/framework/templates/examples/spec-examples.md +1 -1
  145. package/framework/templates/infrastructure/github/README.md +11 -11
  146. package/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +2 -2
  147. package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +2 -2
  148. package/framework/templates/meta-prompts/validators/pre-commit-validator.md +1 -1
  149. package/framework/workflows/configs/express.json +45 -0
  150. package/framework/workflows/configs/spec-only.json +43 -0
  151. package/framework/workflows/docs/enforcement-pipeline.md +8 -8
  152. package/framework/workflows/docs/full-morph.md +3 -3
  153. package/package.json +3 -1
  154. package/scripts/generate-refs.js +336 -0
  155. package/scripts/generate-standards-registry.js +44 -0
  156. package/scripts/validate-real.mjs +255 -0
  157. package/src/commands/feature/create-story.js +362 -361
  158. package/src/commands/feature/shard-spec.js +225 -224
  159. package/src/commands/feature/sprint-status.js +1 -1
  160. package/src/commands/generation/generate-onboarding.js +169 -0
  161. package/src/commands/generation/generate.js +2 -2
  162. package/src/commands/mcp/mcp-setup.js +315 -0
  163. package/src/commands/project/changes.js +66 -0
  164. package/src/commands/project/checkpoint.js +209 -0
  165. package/src/commands/project/cost.js +179 -0
  166. package/src/commands/project/diff.js +278 -0
  167. package/src/commands/project/doctor.js +55 -7
  168. package/src/commands/project/init.js +318 -136
  169. package/src/commands/project/revert.js +173 -0
  170. package/src/commands/project/standards.js +80 -0
  171. package/src/commands/project/status.js +376 -0
  172. package/src/commands/project/update-agents.js +23 -0
  173. package/src/commands/project/update.js +60 -88
  174. package/src/commands/state/advance-phase.js +4 -3
  175. package/src/commands/state/state.js +10 -3
  176. package/src/commands/state/validate-phase.js +19 -2
  177. package/src/commands/templates/template-customize.js +4 -4
  178. package/src/commands/templates/template-render.js +1 -1
  179. package/src/commands/templates/template-show.js +1 -1
  180. package/src/commands/validation/validate-feature.js +359 -0
  181. package/src/core/orchestrator.js +3 -38
  182. package/src/core/paths/output-schema.js +135 -0
  183. package/src/core/state/state-manager.js +831 -592
  184. package/src/core/templates/template-registry.js +2 -2
  185. package/src/core/workflows/workflow-detector.js +17 -1
  186. package/src/lib/agents/micro-agent-factory.js +1 -1
  187. package/src/lib/context/context-bundler.js +2 -1
  188. package/src/lib/detectors/claude-config-detector.js +390 -0
  189. package/src/lib/detectors/conversation-analyzer.js +4 -4
  190. package/src/lib/detectors/design-system-detector.js +6 -5
  191. package/src/lib/detectors/standards-generator.js +2 -2
  192. package/src/lib/generators/context-generator.js +539 -538
  193. package/src/lib/generators/recap-generator.js +1 -1
  194. package/src/lib/generators/settings-generator.js +210 -0
  195. package/src/lib/hooks/hook-executor.js +1 -1
  196. package/src/lib/installers/mcp-installer.js +299 -0
  197. package/src/lib/learning/learning-system.js +3 -3
  198. package/src/lib/orchestration/team-orchestrator.js +1 -1
  199. package/src/lib/standards/standards-context-injector.js +7 -7
  200. package/src/lib/threads/thread-coordinator.js +1 -1
  201. package/src/lib/troubleshooting/troubleshoot-grep.js +1 -1
  202. package/src/lib/validators/contracts/contract-compliance-validator.js +274 -273
  203. package/src/lib/validators/design-system/design-system-validator.js +1 -1
  204. package/src/lib/validators/spec-validator.js +258 -258
  205. package/src/lib/validators/validation-runner.js +270 -269
  206. package/src/utils/agents-installer.js +206 -0
  207. package/src/utils/claude-settings-manager.js +258 -0
  208. package/src/utils/file-copier.js +1 -1
  209. package/src/utils/hooks-installer.js +354 -28
  210. package/src/utils/skills-installer.js +118 -0
  211. package/.morph/project/context/README.md +0 -17
  212. package/.morph/project/context/detection-log.md +0 -16
  213. package/.morph/project/standards/inferred.md +0 -59
  214. package/framework/hooks/agent-stop/validate-and-continue.js +0 -96
  215. package/framework/hooks/agent-stop/validate-checkpoints.js +0 -101
  216. package/framework/hooks/agent-stop/validate-tests.js +0 -109
  217. package/framework/hooks/agent-teams/dispatch.js +0 -67
  218. package/framework/hooks/agent-teams/phase-advanced.js +0 -80
  219. package/framework/hooks/agent-teams/task-completed.js +0 -76
  220. package/framework/hooks/agent-teams/teammate-idle.js +0 -70
  221. package/framework/skills/level-1-workflows/phase-design.md +0 -213
  222. package/framework/skills/level-1-workflows/phase-setup.md +0 -106
  223. package/framework/skills/level-1-workflows/phase-uiux.md +0 -169
  224. package/framework/skills/level-2-domains/backend/api-designer.md +0 -59
  225. package/framework/skills/level-2-domains/backend/ef-modeler.md +0 -58
  226. package/framework/skills/level-3-technologies/README.md +0 -7
  227. package/framework/skills/level-4-patterns/README.md +0 -7
  228. package/src/commands/agents/agents-fuse.js +0 -97
  229. package/src/commands/agents/micro-agent.js +0 -112
  230. package/src/commands/agents/spawn-team.js +0 -237
  231. package/src/commands/agents/squad-template.js +0 -146
  232. package/src/commands/analytics/analytics.js +0 -176
  233. package/src/commands/context/context-prime.js +0 -63
  234. package/src/commands/context/core-four.js +0 -54
  235. package/src/commands/generation/generate-context.js +0 -40
  236. package/src/commands/project/detect-agents.js +0 -207
  237. package/src/commands/project/detect-workflow.js +0 -174
  238. package/src/commands/threads/thread-template.js +0 -103
  239. package/src/commands/threads/threads.js +0 -261
  240. package/src/commands/utils/session-summary.js +0 -291
  241. package/src/llm/analyzer.js +0 -215
  242. package/src/llm/few-shot-examples.js +0 -216
  243. package/src/llm/project-config-schema.json +0 -188
  244. package/src/llm/prompt-builder.js +0 -96
  245. /package/.morph/{config → framework}/agents.json +0 -0
  246. /package/.morph/{standards → framework/standards}/ai-agents/blazor-ui.md +0 -0
  247. /package/.morph/{standards → framework/standards}/ai-agents/production.md +0 -0
  248. /package/.morph/{standards → framework/standards}/ai-agents/setup.md +0 -0
  249. /package/.morph/{standards → framework/standards}/ai-agents/workflows.md +0 -0
  250. /package/.morph/{standards → framework/standards}/architecture/ddd/aggregates.md +0 -0
  251. /package/.morph/{standards → framework/standards}/architecture/ddd/entities.md +0 -0
  252. /package/.morph/{standards → framework/standards}/architecture/ddd/value-objects.md +0 -0
  253. /package/.morph/{standards → framework/standards}/backend/api/minimal-api.md +0 -0
  254. /package/.morph/{standards → framework/standards}/backend/api/rest.md +0 -0
  255. /package/.morph/{standards → framework/standards}/backend/api/validation.md +0 -0
  256. /package/.morph/{standards → framework/standards}/backend/authentication/passkeys.md +0 -0
  257. /package/.morph/{standards → framework/standards}/backend/database/ef-core.md +0 -0
  258. /package/.morph/{standards → framework/standards}/backend/database/migrations.md +0 -0
  259. /package/.morph/{standards → framework/standards}/backend/database/postgresql/database.md +0 -0
  260. /package/.morph/{standards → framework/standards}/backend/database/repository-patterns.md +0 -0
  261. /package/.morph/{standards → framework/standards}/backend/database/vector-search-rag.md +0 -0
  262. /package/.morph/{standards → framework/standards}/backend/dotnet/async.md +0 -0
  263. /package/.morph/{standards → framework/standards}/backend/dotnet/core.md +0 -0
  264. /package/.morph/{standards → framework/standards}/backend/dotnet/di.md +0 -0
  265. /package/.morph/{standards → framework/standards}/backend/dotnet/program-cs-checklist.md +0 -0
  266. /package/.morph/{standards → framework/standards}/backend/integrations/asaas/asaas-api.md +0 -0
  267. /package/.morph/{standards → framework/standards}/backend/integrations/clerk/clerk-auth.md +0 -0
  268. /package/.morph/{standards → framework/standards}/backend/integrations/hangfire/hangfire-jobs.md +0 -0
  269. /package/.morph/{standards → framework/standards}/backend/integrations/resend/resend-email.md +0 -0
  270. /package/.morph/{standards → framework/standards}/context/analytics.md +0 -0
  271. /package/.morph/{standards → framework/standards}/context/bundles.md +0 -0
  272. /package/.morph/{standards → framework/standards}/context/priming.md +0 -0
  273. /package/.morph/{standards → framework/standards}/core/architecture.md +0 -0
  274. /package/.morph/{standards → framework/standards}/core/coding.md +0 -0
  275. /package/.morph/{standards → framework/standards}/core/git-branching-strategy.md +0 -0
  276. /package/.morph/{standards → framework/standards}/core/git.md +0 -0
  277. /package/.morph/{standards → framework/standards}/core/testing.md +0 -0
  278. /package/.morph/{standards → framework/standards}/data/nosql/blob-storage.md +0 -0
  279. /package/.morph/{standards → framework/standards}/data/nosql/cache/redis.md +0 -0
  280. /package/.morph/{standards → framework/standards}/data/nosql/cosmos-db.md +0 -0
  281. /package/.morph/{standards → framework/standards}/data/vector-search/azure-ai-search.md +0 -0
  282. /package/.morph/{standards → framework/standards}/data/vector-search/rag-chunking.md +0 -0
  283. /package/.morph/{standards → framework/standards}/frontend/blazor/design-checklist.md +0 -0
  284. /package/.morph/{standards → framework/standards}/frontend/blazor/fluent-ui-setup.md +0 -0
  285. /package/.morph/{standards → framework/standards}/frontend/blazor/fluent-ui.md +0 -0
  286. /package/.morph/{standards → framework/standards}/frontend/blazor/html-conversion.md +0 -0
  287. /package/.morph/{standards → framework/standards}/frontend/blazor/lifecycle.md +0 -0
  288. /package/.morph/{standards → framework/standards}/frontend/blazor/pitfalls.md +0 -0
  289. /package/.morph/{standards → framework/standards}/frontend/blazor/state.md +0 -0
  290. /package/.morph/{standards → framework/standards}/frontend/design-system/animations.md +0 -0
  291. /package/.morph/{standards → framework/standards}/frontend/design-system/naming.md +0 -0
  292. /package/.morph/{standards → framework/standards}/infrastructure/azure/azure.md +0 -0
  293. /package/.morph/{standards → framework/standards}/infrastructure/azure/bicep/bicep-patterns.md +0 -0
  294. /package/.morph/{standards → framework/standards}/infrastructure/azure/devops/azure-devops-setup.md +0 -0
  295. /package/.morph/{standards → framework/standards}/infrastructure/azure/devops/local-development.md +0 -0
  296. /package/.morph/{standards → framework/standards}/infrastructure/azure/services/functions.md +0 -0
  297. /package/.morph/{standards → framework/standards}/infrastructure/azure/services/service-bus.md +0 -0
  298. /package/.morph/{standards → framework/standards}/infrastructure/azure/services/storage.md +0 -0
  299. /package/.morph/{standards → framework/standards}/infrastructure/docker/easypanel-deploy.md +0 -0
  300. /package/.morph/{standards → framework/standards}/infrastructure/supabase/mcp-setup.md +0 -0
  301. /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-auth.md +0 -0
  302. /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-pgvector.md +0 -0
  303. /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-rls.md +0 -0
  304. /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-storage.md +0 -0
  305. /package/.morph/{standards → framework/standards}/integration/api/graphql.md +0 -0
  306. /package/.morph/{standards → framework/standards}/integration/api/grpc.md +0 -0
  307. /package/.morph/{standards → framework/standards}/integration/api/rest-design.md +0 -0
  308. /package/.morph/{standards → framework/standards}/integration/event-driven/cqrs.md +0 -0
  309. /package/.morph/{standards → framework/standards}/integration/event-driven/event-sourcing.md +0 -0
  310. /package/.morph/{standards → framework/standards}/integration/event-driven/service-bus.md +0 -0
  311. /package/.morph/{standards → framework/standards}/observability/logging.md +0 -0
  312. /package/.morph/{standards → framework/standards}/observability/metrics.md +0 -0
  313. /package/.morph/{standards → framework/standards}/observability/monitoring.md +0 -0
  314. /package/.morph/{standards → framework/standards}/observability/tracing.md +0 -0
  315. /package/.morph/{standards → framework/standards}/workflows/parallel-execution.md +0 -0
  316. /package/.morph/{standards → framework/standards}/workflows/thread-management.md +0 -0
  317. /package/.morph/{templates → framework/templates}/.idea/morph-templates.xml +0 -0
  318. /package/.morph/{templates → framework/templates}/.vscode/morph-templates.code-snippets +0 -0
  319. /package/.morph/{templates → framework/templates}/IDE-SNIPPETS.md +0 -0
  320. /package/.morph/{templates → framework/templates}/code/dotnet/backend/repository.cs +0 -0
  321. /package/.morph/{templates → framework/templates}/code/dotnet/backend/service.cs +0 -0
  322. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/Commands.cs +0 -0
  323. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/Entities.cs +0 -0
  324. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/Queries.cs +0 -0
  325. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/README.md +0 -0
  326. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/api-contracts.cs +0 -0
  327. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/contracts.cs +0 -0
  328. /package/.morph/{templates → framework/templates}/code/dotnet/database/migration.cs +0 -0
  329. /package/.morph/{templates → framework/templates}/code/dotnet/frontend/component.razor +0 -0
  330. /package/.morph/{templates → framework/templates}/code/dotnet/jobs/agent.cs +0 -0
  331. /package/.morph/{templates → framework/templates}/code/dotnet/jobs/job.cs +0 -0
  332. /package/.morph/{templates → framework/templates}/code/dotnet/test.cs +0 -0
  333. /package/.morph/{templates → framework/templates}/code/sql/rls-policy.sql +0 -0
  334. /package/.morph/{templates → framework/templates}/code/sql/supabase-migration.sql +0 -0
  335. /package/.morph/{templates → framework/templates}/code/sql/supabase-migration.template.sql +0 -0
  336. /package/.morph/{templates → framework/templates}/code/typescript/contracts.ts +0 -0
  337. /package/.morph/{templates → framework/templates}/docs/proposal.md +0 -0
  338. /package/.morph/{templates → framework/templates}/examples/design-system-examples.md +0 -0
  339. /package/.morph/{templates → framework/templates}/feature/decisions.md +0 -0
  340. /package/.morph/{templates → framework/templates}/feature/recap.md +0 -0
  341. /package/.morph/{templates → framework/templates}/feature/tasks.md +0 -0
  342. /package/.morph/{templates → framework/templates}/infrastructure/azure/Dockerfile.example +0 -0
  343. /package/.morph/{templates → framework/templates}/infrastructure/azure/README.md +0 -0
  344. /package/.morph/{templates → framework/templates}/infrastructure/azure/app-insights.bicep +0 -0
  345. /package/.morph/{templates → framework/templates}/infrastructure/azure/app-service.bicep +0 -0
  346. /package/.morph/{templates → framework/templates}/infrastructure/azure/container-app-env.bicep +0 -0
  347. /package/.morph/{templates → framework/templates}/infrastructure/azure/container-app.bicep +0 -0
  348. /package/.morph/{templates → framework/templates}/infrastructure/azure/deploy-checklist.md +0 -0
  349. /package/.morph/{templates → framework/templates}/infrastructure/azure/deploy.ps1 +0 -0
  350. /package/.morph/{templates → framework/templates}/infrastructure/azure/deploy.sh +0 -0
  351. /package/.morph/{templates → framework/templates}/infrastructure/azure/key-vault.bicep +0 -0
  352. /package/.morph/{templates → framework/templates}/infrastructure/azure/main.bicep +0 -0
  353. /package/.morph/{templates → framework/templates}/infrastructure/azure/parameters.dev.json +0 -0
  354. /package/.morph/{templates → framework/templates}/infrastructure/azure/parameters.prod.json +0 -0
  355. /package/.morph/{templates → framework/templates}/infrastructure/azure/parameters.staging.json +0 -0
  356. /package/.morph/{templates → framework/templates}/infrastructure/azure/sql-database.bicep +0 -0
  357. /package/.morph/{templates → framework/templates}/infrastructure/azure/storage.bicep +0 -0
  358. /package/.morph/{templates → framework/templates}/infrastructure/docker/Dockerfile.template +0 -0
  359. /package/.morph/{templates → framework/templates}/infrastructure/docker/docker-compose.template.yml +0 -0
  360. /package/.morph/{templates → framework/templates}/infrastructure/docker/dockerfile-api.dockerfile +0 -0
  361. /package/.morph/{templates → framework/templates}/infrastructure/docker/dockerfile-web.dockerfile +0 -0
  362. /package/.morph/{templates → framework/templates}/infrastructure/docker/easypanel.template.json +0 -0
  363. /package/.morph/{templates → framework/templates}/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -0
  364. /package/.morph/{templates → framework/templates}/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -0
  365. /package/.morph/{templates → framework/templates}/infrastructure/github/actions/health-check/action.yml.hbs +0 -0
  366. /package/.morph/{templates → framework/templates}/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -0
  367. /package/.morph/{templates → framework/templates}/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -0
  368. /package/.morph/{templates → framework/templates}/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -0
  369. /package/.morph/{templates → framework/templates}/integrations/asaas-client.cs +0 -0
  370. /package/.morph/{templates → framework/templates}/integrations/asaas-webhook.cs +0 -0
  371. /package/.morph/{templates → framework/templates}/integrations/azure-identity-config.cs +0 -0
  372. /package/.morph/{templates → framework/templates}/integrations/clerk-config.cs +0 -0
  373. /package/.morph/{templates → framework/templates}/meta-prompts/fusion/fusion-agent.md +0 -0
  374. /package/.morph/{templates → framework/templates}/meta-prompts/fusion/fusion-aggregator.md +0 -0
  375. /package/.morph/{templates → framework/templates}/meta-prompts/hops/hop-retry.md +0 -0
  376. /package/.morph/{templates → framework/templates}/meta-prompts/hops/hop-validation.md +0 -0
  377. /package/.morph/{templates → framework/templates}/meta-prompts/hops/hop-wrapper.md +0 -0
  378. /package/.morph/{templates → framework/templates}/meta-prompts/parallel-workers/parallel-coordinator.md +0 -0
  379. /package/.morph/{templates → framework/templates}/meta-prompts/squad-leaders/backend-squad.md +0 -0
  380. /package/.morph/{templates → framework/templates}/meta-prompts/squad-leaders/frontend-squad.md +0 -0
  381. /package/.morph/{templates → framework/templates}/meta-prompts/squad-leaders/squad-leader.md +0 -0
  382. /package/.morph/{templates → framework/templates}/meta-prompts/validators/checkpoint-validator.md +0 -0
  383. /package/.morph/{templates → framework/templates}/saas/subscription.cs +0 -0
  384. /package/.morph/{templates → framework/templates}/saas/tenant.cs +0 -0
  385. /package/.morph/{templates → framework/templates}/state.template.json +0 -0
  386. /package/.morph/{templates → framework/templates}/ui/FluentDesignTheme.cs +0 -0
  387. /package/.morph/{templates → framework/templates}/ui/MudTheme.cs +0 -0
  388. /package/.morph/{templates → framework/templates}/ui/design-system.css +0 -0
  389. /package/framework/{skills/level-2-domains → agents}/README.md +0 -0
  390. /package/framework/hooks/{commit-msg → git/commit-msg}/conventional-commits.sh +0 -0
  391. /package/framework/hooks/{pre-commit → git/pre-commit}/agents.sh +0 -0
  392. /package/framework/hooks/{pre-commit → git/pre-commit}/orchestrator.sh +0 -0
  393. /package/framework/hooks/{pre-commit → git/pre-commit}/specs.sh +0 -0
  394. /package/framework/hooks/{pre-push → git/pre-push}/run-tests.sh +0 -0
@@ -0,0 +1,538 @@
1
+ #!/usr/bin/env python3
2
+ # framework/hooks/claude-code/statusline.py
3
+ # Claude Code statusline for morph-spec
4
+ # Receives JSON via stdin from Claude Code after each response
5
+
6
+ import sys
7
+ import json
8
+ import os
9
+ import subprocess
10
+ import time
11
+ import re
12
+ import hashlib
13
+ from pathlib import Path
14
+ from datetime import datetime, timezone
15
+
16
+ # Ensure UTF-8 output on Windows (stdout defaults to CP1252 otherwise)
17
+ if hasattr(sys.stdout, 'reconfigure'):
18
+ sys.stdout.reconfigure(encoding='utf-8')
19
+
20
+ # ANSI colors
21
+ R = '\033[0m' # Reset
22
+ BOLD = '\033[1m'
23
+ CYAN = '\033[36m'
24
+ MAGENTA = '\033[35m'
25
+ GREEN = '\033[32m'
26
+ YELLOW = '\033[33m'
27
+ RED = '\033[31m'
28
+ BLUE = '\033[34m'
29
+ GRAY = '\033[90m'
30
+ WHITE = '\033[97m'
31
+
32
+
33
+ # ── MORPH framework constants (derived from phases.json / trust-manager.js) ──
34
+
35
+ # Ordered core phases for pipeline mini-map (5 positions, optional phases mapped)
36
+ # uiux maps to position 2 (same slot as design — they're mutually exclusive in practice)
37
+ PHASE_POSITIONS = {
38
+ 'proposal': 1, 'setup': 1,
39
+ 'uiux': 2, 'design': 2,
40
+ 'clarify': 3,
41
+ 'tasks': 4,
42
+ 'implement': 5, 'sync': 5,
43
+ }
44
+ PHASE_ABBREV = {
45
+ 'proposal': 'prop', 'setup': 'setup',
46
+ 'uiux': 'ui', 'design': 'design',
47
+ 'clarify': 'clarify', 'tasks': 'tasks',
48
+ 'implement': 'impl', 'sync': 'sync',
49
+ }
50
+ PIPELINE_TOTAL = 5
51
+
52
+ # Approval gates per phase (from phases.json pausePoints)
53
+ PHASE_GATES = {
54
+ 'proposal': 'proposal',
55
+ 'uiux': 'uiux',
56
+ 'design': 'design',
57
+ 'tasks': 'tasks',
58
+ }
59
+
60
+ # Trust level thresholds and badges (from trust-manager.js)
61
+ # passRate >= threshold → level
62
+ TRUST_LEVELS = [
63
+ (0.95, 'maximum', GREEN + BOLD, '◆◆◆◆'),
64
+ (0.90, 'high', GREEN, '◆◆◆○'),
65
+ (0.80, 'medium', YELLOW, '◆◆○○'),
66
+ (0.00, 'low', RED, '◆○○○'),
67
+ ]
68
+
69
+ CHECKPOINT_FREQUENCY = 3 # matches llm-interaction.json default
70
+
71
+
72
+ # ── General helpers ──────────────────────────────────────────────────────────
73
+
74
+ def ctx_color(pct):
75
+ """Color based on context usage. 80% = Claude's auto-compact threshold."""
76
+ if pct < 60:
77
+ return GREEN
78
+ if pct < 80:
79
+ return YELLOW
80
+ return RED
81
+
82
+
83
+ def progress_bar(pct, width=8):
84
+ filled = int(pct / 100 * width)
85
+ empty = width - filled
86
+ return f"{'█' * filled}{'░' * empty}"
87
+
88
+
89
+ def format_tokens(n):
90
+ if n >= 1_000_000:
91
+ return f"{n / 1_000_000:.1f}m"
92
+ if n >= 1000:
93
+ return f"{n // 1000}k"
94
+ return str(n)
95
+
96
+
97
+ # ── MORPH feature helpers ────────────────────────────────────────────────────
98
+
99
+ def calculate_trust(checkpoints):
100
+ """Return (level_str, color, badge, pass_rate) from checkpoint array."""
101
+ if not checkpoints:
102
+ return 'low', RED, '○○○○', 0.0
103
+ total = len(checkpoints)
104
+ passed = sum(1 for c in checkpoints if c.get('passed'))
105
+ rate = passed / total
106
+ for threshold, level, color, badge in TRUST_LEVELS:
107
+ if rate >= threshold:
108
+ return level, color, badge, rate
109
+ return 'low', RED, '○○○○', rate
110
+
111
+
112
+ def get_phase_minimap(phase):
113
+ """Return colored dot strip + phase abbrev, e.g. '●►○○○ design'."""
114
+ pos = PHASE_POSITIONS.get(phase)
115
+ if pos is None:
116
+ return None
117
+ dots = ''
118
+ for i in range(1, PIPELINE_TOTAL + 1):
119
+ if i < pos:
120
+ dots += f"{GREEN}●{R}"
121
+ elif i == pos:
122
+ dots += f"{CYAN}►{R}"
123
+ else:
124
+ dots += f"{GRAY}○{R}"
125
+ abbrev = PHASE_ABBREV.get(phase, phase)
126
+ return f"{dots} {CYAN}{abbrev}{R}"
127
+
128
+
129
+ def get_checkpoint_countdown(tasks_done):
130
+ """Tasks remaining until next checkpoint fires (frequency=3)."""
131
+ if tasks_done <= 0:
132
+ return None
133
+ remaining = CHECKPOINT_FREQUENCY - (tasks_done % CHECKPOINT_FREQUENCY)
134
+ return 0 if remaining == CHECKPOINT_FREQUENCY else remaining
135
+
136
+
137
+ def get_next_gate(phase, approval_gates):
138
+ """Return the upcoming gate for this phase if not yet triggered in state."""
139
+ gate_id = PHASE_GATES.get(phase)
140
+ if not gate_id:
141
+ return None
142
+ # If the gate already appears in approvalGates (approved or pending),
143
+ # it's either done or already shown as pending — don't duplicate.
144
+ if gate_id in (approval_gates or {}):
145
+ return None
146
+ return gate_id
147
+
148
+
149
+ def get_all_active_features(cwd):
150
+ """Return list of all in_progress features with enriched MORPH metadata."""
151
+ state_path = Path(cwd) / '.morph' / 'state.json'
152
+ if not state_path.exists():
153
+ return []
154
+ try:
155
+ state = json.loads(state_path.read_text())
156
+ features = state.get('features', {})
157
+ result = []
158
+ for name, feat in features.items():
159
+ if feat.get('status') != 'in_progress':
160
+ continue
161
+ phase = feat.get('phase', '?')
162
+ tasks = feat.get('tasks', {})
163
+ done = tasks.get('completed', 0)
164
+ total = tasks.get('total', 0)
165
+ gates = feat.get('approvalGates', {})
166
+ checkpts = feat.get('checkpoints', [])
167
+
168
+ pending = [g for g, v in gates.items() if not v.get('approved')]
169
+ trust_lvl, trust_color, trust_badge, trust_rate = calculate_trust(checkpts)
170
+ countdown = get_checkpoint_countdown(done)
171
+ next_gate = get_next_gate(phase, gates)
172
+ minimap = get_phase_minimap(phase)
173
+
174
+ result.append({
175
+ 'name': name,
176
+ 'phase': phase,
177
+ 'tasks_done': done,
178
+ 'tasks_total': total,
179
+ 'pending': pending[0] if pending else None,
180
+ 'trust_level': trust_lvl,
181
+ 'trust_color': trust_color,
182
+ 'trust_badge': trust_badge,
183
+ 'trust_rate': trust_rate,
184
+ 'countdown': countdown,
185
+ 'next_gate': next_gate,
186
+ 'minimap': minimap,
187
+ })
188
+ return result
189
+ except Exception:
190
+ return []
191
+
192
+
193
+ # ── Git helpers ───────────────────────────────────────────────────────────────
194
+
195
+ def get_git_info(cwd):
196
+ """Get git branch and diff stats. Uses a 5s file cache to avoid lag."""
197
+ try:
198
+ cache_file = Path(cwd) / '.morph' / '.git-cache'
199
+ try:
200
+ if cache_file.exists():
201
+ age = time.time() - cache_file.stat().st_mtime
202
+ if age < 5:
203
+ return cache_file.read_text().strip()
204
+ except Exception:
205
+ pass
206
+
207
+ branch = subprocess.check_output(
208
+ ['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
209
+ cwd=cwd, stderr=subprocess.DEVNULL, timeout=2
210
+ ).decode().strip()
211
+
212
+ # Diff stats: insertions/deletions from staged + unstaged changes
213
+ ins, dels = 0, 0
214
+ for cmd in [['diff', '--shortstat'], ['diff', '--cached', '--shortstat']]:
215
+ try:
216
+ out = subprocess.check_output(
217
+ ['git'] + cmd, cwd=cwd, stderr=subprocess.DEVNULL, timeout=2
218
+ ).decode()
219
+ m = re.search(r'(\d+) insertion', out)
220
+ if m:
221
+ ins += int(m.group(1))
222
+ m = re.search(r'(\d+) deletion', out)
223
+ if m:
224
+ dels += int(m.group(1))
225
+ except Exception:
226
+ pass
227
+
228
+ parts = [f"{BLUE} {branch}{R}"]
229
+ if ins or dels:
230
+ parts.append(f"{GREEN}+{ins}{R}{GRAY},{R}{RED}-{dels}{R}")
231
+
232
+ result = ' '.join(parts)
233
+ try:
234
+ cache_file.parent.mkdir(parents=True, exist_ok=True)
235
+ cache_file.write_text(result)
236
+ except Exception:
237
+ pass
238
+ return result
239
+ except Exception:
240
+ return ""
241
+
242
+
243
+ def get_worktree_info(cwd):
244
+ """Detect if running in a git worktree (not the main worktree)."""
245
+ try:
246
+ out = subprocess.check_output(
247
+ ['git', 'worktree', 'list', '--porcelain'],
248
+ cwd=cwd, stderr=subprocess.DEVNULL, timeout=2
249
+ ).decode()
250
+ entries, current = [], {}
251
+ for line in out.splitlines():
252
+ if line.startswith('worktree '):
253
+ if current:
254
+ entries.append(current)
255
+ current = {'path': line.split(' ', 1)[1]}
256
+ elif line.startswith('branch '):
257
+ current['branch'] = line.split(' ', 1)[1]
258
+ if current:
259
+ entries.append(current)
260
+ if len(entries) > 1:
261
+ cwd_r = str(Path(cwd).resolve())
262
+ for entry in entries[1:]:
263
+ if str(Path(entry.get('path', '')).resolve()) == cwd_r:
264
+ branch = entry.get('branch', '').replace('refs/heads/', '')
265
+ return f"{MAGENTA}worktree:{branch}{R}"
266
+ except Exception:
267
+ pass
268
+ return ""
269
+
270
+
271
+ # ── Transcript / JSONL helpers ────────────────────────────────────────────────
272
+
273
+ def read_transcript_jsonl(path):
274
+ """Read and parse JSONL transcript file. Returns list of parsed entries."""
275
+ entries = []
276
+ try:
277
+ with open(path, 'r', encoding='utf-8') as f:
278
+ for line in f:
279
+ line = line.strip()
280
+ if not line:
281
+ continue
282
+ try:
283
+ entries.append(json.loads(line))
284
+ except Exception:
285
+ pass
286
+ except Exception:
287
+ pass
288
+ return entries
289
+
290
+
291
+ def get_token_metrics(entries):
292
+ """Sum token usage from all non-sidechain JSONL entries."""
293
+ total_input, total_output, total_cached = 0, 0, 0
294
+ for entry in entries:
295
+ if entry.get('isSidechain') or entry.get('isApiErrorMessage'):
296
+ continue
297
+ usage = (entry.get('message') or {}).get('usage') or {}
298
+ if not usage:
299
+ continue
300
+ total_input += usage.get('input_tokens', 0)
301
+ total_output += usage.get('output_tokens', 0)
302
+ total_cached += (
303
+ usage.get('cache_creation_input_tokens', 0) +
304
+ usage.get('cache_read_input_tokens', 0)
305
+ )
306
+ return {'input': total_input, 'output': total_output, 'cached': total_cached}
307
+
308
+
309
+ def parse_timestamp(ts):
310
+ """Parse ISO 8601 timestamp to Unix float. Returns None on error."""
311
+ try:
312
+ return datetime.fromisoformat(ts.replace('Z', '+00:00')).timestamp()
313
+ except Exception:
314
+ return None
315
+
316
+
317
+ def get_session_duration(entries):
318
+ """Elapsed time since first message. Returns 'Xhr Ym' or None."""
319
+ now = time.time()
320
+ for entry in entries:
321
+ ts = entry.get('timestamp')
322
+ if not ts:
323
+ continue
324
+ t = parse_timestamp(ts)
325
+ if t is None:
326
+ continue
327
+ elapsed_s = now - t
328
+ hours = int(elapsed_s // 3600)
329
+ minutes = int((elapsed_s % 3600) // 60)
330
+ if hours == 0:
331
+ return f"{minutes}m"
332
+ elif minutes == 0:
333
+ return f"{hours}hr"
334
+ else:
335
+ return f"{hours}hr {minutes}m"
336
+ return None
337
+
338
+
339
+ def get_session_name(entries):
340
+ """Find the most recent /rename title. Returns string or None."""
341
+ for entry in reversed(entries):
342
+ if entry.get('type') == 'custom-title' and entry.get('customTitle'):
343
+ return entry['customTitle']
344
+ return None
345
+
346
+
347
+ def get_block_start(transcript_path, entries):
348
+ """Find start of current 5-hour billing block. Cached per transcript."""
349
+ h = hashlib.sha256(transcript_path.encode()).hexdigest()[:16]
350
+ cache_dir = Path.home() / '.cache' / 'morph-spec'
351
+ cache_file = cache_dir / f'block-{h}.json'
352
+ now = time.time()
353
+ block_s = 5 * 3600
354
+
355
+ try:
356
+ if cache_file.exists():
357
+ cached = json.loads(cache_file.read_text())
358
+ start = cached.get('block_start')
359
+ if start and (now - start) < block_s:
360
+ return start
361
+ except Exception:
362
+ pass
363
+
364
+ start = None
365
+ for entry in entries:
366
+ ts = entry.get('timestamp')
367
+ if not ts:
368
+ continue
369
+ t = parse_timestamp(ts)
370
+ if t is None:
371
+ continue
372
+ if (now - t) <= block_s:
373
+ start = t
374
+ break
375
+
376
+ if start is None:
377
+ return None
378
+
379
+ try:
380
+ cache_dir.mkdir(parents=True, exist_ok=True)
381
+ cache_file.write_text(json.dumps({'block_start': start}))
382
+ except Exception:
383
+ pass
384
+ return start
385
+
386
+
387
+ def format_block_timer(block_start):
388
+ """Format block timer as 'bar Xhr Ym' relative to 5-hour window."""
389
+ now = time.time()
390
+ elapsed_s = max(0.0, now - block_start)
391
+ pct = min(elapsed_s / (5 * 3600) * 100, 100)
392
+ hours = int(elapsed_s // 3600)
393
+ minutes = int((elapsed_s % 3600) // 60)
394
+ if hours == 0:
395
+ time_str = f"{minutes}m"
396
+ elif minutes == 0:
397
+ time_str = f"{hours}hr"
398
+ else:
399
+ time_str = f"{hours}hr {minutes}m"
400
+ return f"{progress_bar(pct, 6)} {time_str}"
401
+
402
+
403
+ # ── Main ──────────────────────────────────────────────────────────────────────
404
+
405
+ def main():
406
+ try:
407
+ raw = sys.stdin.read()
408
+ if not raw.strip():
409
+ sys.exit(0)
410
+ data = json.loads(raw)
411
+ except Exception:
412
+ sys.exit(0)
413
+
414
+ cwd = data.get('cwd', os.getcwd())
415
+ transcript_path = data.get('transcript_path')
416
+
417
+ # Read JSONL transcript once — shared by session clock, block timer,
418
+ # token metrics, and session name.
419
+ entries = read_transcript_jsonl(transcript_path) if transcript_path else []
420
+
421
+ # ── MORPH feature lines (one line per active feature) ────────────────────
422
+ features = get_all_active_features(cwd)
423
+ for feat in features:
424
+ parts = [f"{CYAN}{BOLD}{feat['name']}{R}"]
425
+
426
+ # Phase pipeline mini-map: ●●►○○ design
427
+ if feat['minimap']:
428
+ parts.append(feat['minimap'])
429
+
430
+ # Task progress bar
431
+ if feat['tasks_total'] > 0:
432
+ pct = feat['tasks_done'] / feat['tasks_total'] * 100
433
+ bar = progress_bar(pct, 6)
434
+ parts.append(f"{GREEN}{bar} {feat['tasks_done']}/{feat['tasks_total']}{R}")
435
+
436
+ # Checkpoint countdown: how many tasks until next validation fires
437
+ if feat['countdown'] is not None:
438
+ if feat['countdown'] == 0:
439
+ parts.append(f"{GREEN}ckpt!{R}") # just hit checkpoint
440
+ elif feat['countdown'] == 1:
441
+ parts.append(f"{YELLOW}ckpt:1{R}") # 1 task away — heads up
442
+ else:
443
+ parts.append(f"{GRAY}ckpt:{feat['countdown']}{R}")
444
+
445
+ # Trust level badge: ◆◆◆○ high
446
+ tc = feat['trust_color']
447
+ parts.append(f"{tc}{feat['trust_badge']}{R}")
448
+
449
+ # Pending approval gate (blocking — already triggered, not yet approved)
450
+ if feat['pending']:
451
+ parts.append(f"{YELLOW}⏳ {feat['pending']} pending{R}")
452
+
453
+ # Upcoming gate (not yet triggered — reminds what comes at end of phase)
454
+ if feat['next_gate']:
455
+ parts.append(f"{GRAY}→gate:{feat['next_gate']}{R}")
456
+
457
+ print(' | '.join(parts))
458
+
459
+ # ── Session info line (always shown) ─────────────────────────────────────
460
+ parts2 = []
461
+
462
+ # Session name (set via /rename)
463
+ if entries:
464
+ session_name = get_session_name(entries)
465
+ if session_name:
466
+ parts2.append(f"{CYAN}{BOLD}📌 {session_name}{R}")
467
+
468
+ # Model
469
+ model = data.get('model', {})
470
+ model_name = model.get('display_name', model.get('id', ''))
471
+ if model_name:
472
+ short = model_name.replace('Claude ', '').replace(' (claude.ai)', '')
473
+ parts2.append(f"{WHITE}{BOLD}🤖 {short}{R}")
474
+
475
+ # Session clock (elapsed time since first message)
476
+ if entries:
477
+ duration = get_session_duration(entries)
478
+ if duration:
479
+ parts2.append(f"{YELLOW}⏱ {duration}{R}")
480
+
481
+ # Block timer (progress through current 5-hour billing window)
482
+ if entries and transcript_path:
483
+ block_start = get_block_start(transcript_path, entries)
484
+ if block_start is not None:
485
+ parts2.append(f"{YELLOW}blk:{format_block_timer(block_start)}{R}")
486
+
487
+ # Context window (60% = yellow, 80% = red/auto-compact threshold)
488
+ ctx = data.get('context_window', {})
489
+ if ctx:
490
+ used_pct = ctx.get('used_percentage', 0)
491
+ cur = ctx.get('current_usage', 0)
492
+ total_ctx = ctx.get('context_window_size', 0)
493
+ color = ctx_color(used_pct)
494
+ bar = progress_bar(used_pct, 8)
495
+ toks = f"{format_tokens(cur)}/{format_tokens(total_ctx)}"
496
+ suffix = f" {RED}~cmpct{R}" if used_pct >= 80 else ""
497
+ parts2.append(f"{color}{bar} {used_pct:.0f}%{R} ({toks}){suffix}")
498
+
499
+ # Token breakdown from JSONL (session totals: input / output / cached)
500
+ if entries:
501
+ tok = get_token_metrics(entries)
502
+ tok_parts = []
503
+ if tok['input']:
504
+ tok_parts.append(f"in:{format_tokens(tok['input'])}")
505
+ if tok['output']:
506
+ tok_parts.append(f"out:{format_tokens(tok['output'])}")
507
+ if tok['cached']:
508
+ tok_parts.append(f"↩{format_tokens(tok['cached'])}")
509
+ if tok_parts:
510
+ parts2.append(f"{GRAY}{' '.join(tok_parts)}{R}")
511
+
512
+ # Cost
513
+ cost = data.get('cost', {})
514
+ if cost.get('total_cost_usd'):
515
+ usd = cost['total_cost_usd']
516
+ parts2.append(f"{GRAY}${usd:.3f}{R}")
517
+
518
+ # Agent name (if running in agent mode)
519
+ agent = data.get('agent', {})
520
+ if agent.get('name'):
521
+ parts2.append(f"{BLUE}agent:{agent['name']}{R}")
522
+
523
+ # Git info (branch + diff stats, 5s cached)
524
+ git = get_git_info(cwd)
525
+ if git:
526
+ parts2.append(git)
527
+
528
+ # Worktree info
529
+ wt = get_worktree_info(cwd)
530
+ if wt:
531
+ parts2.append(wt)
532
+
533
+ if parts2:
534
+ print(' | '.join(parts2))
535
+
536
+
537
+ if __name__ == '__main__':
538
+ main()
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ # morph-spec statusline — installed globally to ~/.claude/statusline.sh
3
+ # Claude Code invokes this with JSON via stdin after each response.
4
+ # Requires: Python 3 available as `python3` on PATH.
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ python3 "${SCRIPT_DIR}/statusline.py" 2>/dev/null || true
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Stop Hook: Validate Completion (Advisory)
5
+ *
6
+ * Event: Stop
7
+ *
8
+ * When Claude stops, checks for incomplete work:
9
+ * - In implement phase: checks uncompleted tasks
10
+ * - In spec phases: checks required outputs still created: false
11
+ * - Returns additionalContext with what remains (advisory, not blocking)
12
+ *
13
+ * Uses stop_hook_active env check to prevent infinite loops.
14
+ *
15
+ * Fail-open: exits 0 on any error.
16
+ */
17
+
18
+ import { stateExists, getActiveFeature, getMissingOutputs } from '../../shared/state-reader.js';
19
+ import { injectContext, pass } from '../../shared/hook-response.js';
20
+
21
+ try {
22
+ // Prevent infinite loop
23
+ if (process.env.MORPH_STOP_HOOK_ACTIVE === '1') pass();
24
+
25
+ if (!stateExists()) pass();
26
+
27
+ const active = getActiveFeature();
28
+ if (!active) pass();
29
+
30
+ const { name, feature } = active;
31
+ const warnings = [];
32
+
33
+ // Check for incomplete tasks during implement phase
34
+ if (feature.phase === 'implement' && feature.tasks) {
35
+ const remaining = (feature.tasks.total || 0) - (feature.tasks.completed || 0);
36
+ if (remaining > 0) {
37
+ warnings.push(`${remaining} task(s) remaining for feature '${name}'`);
38
+ if (feature.tasks.inProgress > 0) {
39
+ warnings.push(` ${feature.tasks.inProgress} task(s) still in progress`);
40
+ }
41
+ }
42
+ }
43
+
44
+ // Check for missing outputs in spec phases
45
+ if (['proposal', 'design', 'clarify', 'tasks', 'uiux'].includes(feature.phase)) {
46
+ const missing = getMissingOutputs(name);
47
+ if (missing.length > 0) {
48
+ warnings.push(`Missing outputs for '${name}' (${feature.phase} phase):`);
49
+ for (const output of missing.slice(0, 5)) {
50
+ warnings.push(` - ${output.type}: ${output.path}`);
51
+ }
52
+ if (missing.length > 5) {
53
+ warnings.push(` ... and ${missing.length - 5} more`);
54
+ }
55
+ }
56
+ }
57
+
58
+ // Check pending approval gates
59
+ if (feature.approvalGates) {
60
+ const pendingGates = Object.entries(feature.approvalGates)
61
+ .filter(([, gate]) => !gate.approved && gate.timestamp === null)
62
+ .map(([name]) => name);
63
+
64
+ // Only warn about gates relevant to current/past phases
65
+ const relevantGates = pendingGates.filter(gate => {
66
+ const gatePhaseMap = { proposal: 'proposal', uiux: 'uiux', design: 'design', tasks: 'tasks' };
67
+ return gatePhaseMap[gate] !== undefined;
68
+ });
69
+
70
+ if (relevantGates.length > 0) {
71
+ warnings.push(`Pending approvals: ${relevantGates.join(', ')}`);
72
+ }
73
+ }
74
+
75
+ if (warnings.length === 0) pass();
76
+
77
+ const message = [
78
+ 'MORPH-SPEC: Incomplete work detected:',
79
+ ...warnings.map(w => ` ${w}`),
80
+ '',
81
+ 'Resume with: morph-spec status ' + name
82
+ ].join('\n');
83
+
84
+ injectContext(message);
85
+ } catch {
86
+ // Fail-open
87
+ process.exit(0);
88
+ }