@polymorphism-tech/morph-spec 4.18.0 → 4.20.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 (86) hide show
  1. package/README.md +2 -2
  2. package/bin/morph-spec.js +11 -0
  3. package/bin/task-manager.js +47 -10
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/agents/architecture/architecture-expert.md +98 -0
  8. package/framework/agents/architecture/morph-spec-architect.md +66 -0
  9. package/framework/agents/architecture/packages-validator.md +89 -0
  10. package/framework/agents/architecture/security-expert.md +79 -0
  11. package/framework/agents/backend/ms-agent-expert.md +1 -1
  12. package/framework/agents/frontend/design-system-validator.md +100 -0
  13. package/framework/agents/frontend/nextjs-component-validator.md +97 -0
  14. package/framework/agents/frontend/{ui-ux-designer.md → ui-designer.md} +31 -0
  15. package/framework/agents.json +1 -1
  16. package/framework/hooks/claude-code/post-tool-use/dispatch.js +56 -0
  17. package/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +78 -44
  18. package/framework/hooks/claude-code/post-tool-use/loop-detect.js +103 -0
  19. package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +60 -11
  20. package/framework/hooks/claude-code/session-start/inject-morph-context.js +21 -2
  21. package/framework/hooks/claude-code/stop/validate-completion.js +48 -1
  22. package/framework/hooks/shared/activity-logger.js +56 -1
  23. package/framework/hooks/shared/build-check.js +79 -0
  24. package/framework/hooks/shared/payload-utils.js +39 -0
  25. package/framework/hooks/shared/session-snapshot.js +105 -0
  26. package/framework/phases.json +1 -1
  27. package/framework/rubrics/backend.json +36 -0
  28. package/framework/rubrics/default.json +36 -0
  29. package/framework/rubrics/frontend.json +36 -0
  30. package/framework/skills/level-0-meta/mcp-registry.json +34 -1
  31. package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +1 -1
  32. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +1 -1
  33. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +11 -1
  34. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +12 -1
  35. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
  36. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
  37. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +119 -11
  38. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  39. package/framework/standards/ai-agents/production.md +5 -2
  40. package/framework/standards/ai-agents/setup.md +13 -14
  41. package/framework/standards/ai-agents/workflows.md +8 -6
  42. package/framework/standards/backend/database/vector-search-rag.md +1 -1
  43. package/framework/templates/code/dotnet/jobs/agent.cs +0 -1
  44. package/package.json +1 -1
  45. package/src/commands/dashboard/dashboard.js +53 -0
  46. package/src/commands/mcp/mcp-setup.js +21 -0
  47. package/src/commands/project/init.js +11 -0
  48. package/src/dashboard/app/App.jsx +31 -0
  49. package/src/dashboard/app/components/DetailPanel.jsx +11 -0
  50. package/src/dashboard/app/components/FlowGraph.jsx +17 -0
  51. package/src/dashboard/app/components/SearchFilter.jsx +22 -0
  52. package/src/dashboard/app/components/Sidebar.jsx +45 -0
  53. package/src/dashboard/app/hooks/useDetailPanel.js +15 -0
  54. package/src/dashboard/app/main.jsx +13 -0
  55. package/src/dashboard/app/pages/AgentMap.jsx +371 -0
  56. package/src/dashboard/app/pages/HookInspector.jsx +418 -0
  57. package/src/dashboard/app/pages/LiveState.jsx +239 -0
  58. package/src/dashboard/app/pages/PhasePipeline.jsx +410 -0
  59. package/src/dashboard/app/pages/RulesMap.jsx +273 -0
  60. package/src/dashboard/app/pages/SkillsLibrary.jsx +367 -0
  61. package/src/dashboard/app/pages/Standards.jsx +332 -0
  62. package/src/dashboard/app/pages/Workflows.jsx +346 -0
  63. package/src/dashboard/app/styles/index.css +47 -0
  64. package/src/dashboard/index.html +12 -0
  65. package/src/dashboard/package.json +24 -0
  66. package/src/dashboard/scanner/agents-scanner.js +35 -0
  67. package/src/dashboard/scanner/hooks-scanner.js +41 -0
  68. package/src/dashboard/scanner/index.js +21 -0
  69. package/src/dashboard/scanner/phases-scanner.js +15 -0
  70. package/src/dashboard/scanner/rubrics-scanner.js +12 -0
  71. package/src/dashboard/scanner/rules-scanner.js +37 -0
  72. package/src/dashboard/scanner/skills-scanner.js +43 -0
  73. package/src/dashboard/scanner/squads-scanner.js +13 -0
  74. package/src/dashboard/scanner/standards-scanner.js +26 -0
  75. package/src/dashboard/scanner/state-scanner.js +8 -0
  76. package/src/dashboard/scanner/workflows-scanner.js +18 -0
  77. package/src/dashboard/vite-plugin-morph-data.js +17 -0
  78. package/src/dashboard/vite.config.js +24 -0
  79. package/src/lib/checkpoints/checkpoint-hooks.js +2 -1
  80. package/src/lib/contracts/sprint-contract-generator.js +137 -0
  81. package/src/lib/generators/recap-generator.js +15 -0
  82. package/src/lib/installers/mcp-installer.js +25 -0
  83. package/src/lib/validators/score-aggregator.js +244 -0
  84. package/src/lib/validators/validation-runner.js +44 -0
  85. package/src/scripts/setup-infra.js +8 -0
  86. package/src/utils/hooks-installer.js +12 -1
@@ -4,7 +4,7 @@ description: MORPH-SPEC Phase 2 (UI/UX). Creates design-system.md, mockups.md, c
4
4
  argument-hint: "[feature-name]"
5
5
  user-invocable: false
6
6
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
7
- cliVersion: "4.18.0"
7
+ cliVersion: "4.20.0"
8
8
  ---
9
9
 
10
10
  # MORPH UI/UX Design - Phase 2
@@ -43,8 +43,10 @@ Conditional phase for features with front-end. Collects UI/UX requirements, gene
43
43
  | Capture existing app | **Playwright MCP** `browser_navigate()` + `browser_take_screenshot()` | — |
44
44
  | Read Tailwind config | **Read** `tailwind.config.{js,ts}` | **Grep** `colors:` |
45
45
  | Trend research | **Context7 MCP** / **WebSearch** | — |
46
+ | Generate AI screen designs | **Stitch MCP** `generate_screen_from_text()` + `fetch_screen_image()` | HTML mockup + Playwright (Step 3.5) |
47
+ | Export design tokens from Stitch | **Stitch MCP** `fetch_screen_code()` | Manual design-system.md creation |
46
48
 
47
- **MCPs for this phase:** Playwright (preview, inspection, responsiveness), Context7 (component docs).
49
+ **MCPs for this phase:** Playwright (preview, inspection, responsiveness), Context7 (component docs), Stitch (optional: AI screen generation, design.md export).
48
50
 
49
51
  **Anti-patterns:**
50
52
  - Task agent to read a screenshot (use Read directly on image)
@@ -244,6 +246,37 @@ Track: `dsExists` (bool).
244
246
  | **B** | `dsExists` AND NOT `cssTokensFound` | Print: `✓ Design system found (no CSS tokens to cross-check)`. Proceed to Step 1. |
245
247
  | **C** | NOT `dsExists` AND tokens found | Auto-generate `.morph/context/design-system.md` from ALL scanned token sources (CSS vars, Tailwind config, etc.). Merge tokens from multiple sources, preferring Tailwind/Theme config over raw CSS. If Step 0.2 produced `existing-ui-analysis.md`, cross-reference visual analysis with extracted tokens. Proceed to Step 1. |
246
248
  | **D** | NOT `dsExists` AND NOT `cssTokensFound` | Greenfield project. Ask user for aesthetic direction + brand color using `AskUserQuestion` (same options as morph-init). Scaffold from template. Proceed to Step 1. |
249
+ | **E** | Stitch MCP available AND `design.md` found in project root | Parse Stitch design.md, extract color/typography/spacing/radius/shadow tokens, map into `.morph/context/design-system.md` template. If `dsExists`, merge (Stitch fills gaps, manually-set tokens preserved). Add changelog entry. Proceed to Step 1. |
250
+
251
+ **Case E — Stitch design.md integration:**
252
+
253
+ > **Prerequisite:** Stitch MCP detected (tools matching pattern `stitch` found) OR a `design.md` file exists in the project root.
254
+
255
+ 1. If Stitch MCP is available, check for existing projects:
256
+ ```
257
+ stitch__list_projects({})
258
+ ```
259
+ If projects exist, list screens and fetch the design export:
260
+ ```
261
+ stitch__list_screens({ projectId: selectedProjectId })
262
+ stitch__fetch_screen_code({ screenId: screenId })
263
+ ```
264
+
265
+ 2. If `design.md` exists in project root (manual export from Stitch), read it directly.
266
+
267
+ 3. Parse the design.md content and map tokens into `design-system.md` template sections:
268
+ - Color values → `## Color Tokens` (map to `--color-primary`, `--color-accent`, etc.)
269
+ - Font families/sizes → `## Typography` (map to `--font-display`, `--font-body`)
270
+ - Spacing values → `## Spacing Tokens`
271
+ - Border radius → `## Border Radius Tokens`
272
+ - Shadow definitions → `## Shadow Tokens`
273
+
274
+ 4. Write or merge into `.morph/context/design-system.md` using the existing template structure.
275
+
276
+ 5. Add changelog entry:
277
+ `- [today's date] [morph-phase-uiux] Tokens imported from Stitch design.md ({N} tokens)`
278
+
279
+ Print: `✓ Design system populated from Stitch design — .morph/context/design-system.md`
247
280
 
248
281
  **Case C — auto-generate from scanned tokens:**
249
282
 
@@ -416,11 +449,79 @@ Detect the stack from `.morph/config/config.json` and recommend the appropriate
416
449
 
417
450
  > **MCP:** After selecting the UI library, use **Context7 MCP** (`resolve-library-id` → `query-docs`) to fetch the library's latest component API (e.g., shadcn/ui primitives, Radix props, MUI component APIs). This ensures component specs in `components.md` reference real, current props — not outdated or hallucinated ones. If Context7 is not available, use **WebSearch** + **WebFetch** to check the official component documentation.
418
451
 
419
- ### Step 3.5: Visual Mockup (Playwright MCP)
452
+ ### Step 3.5: Visual Mockup (Playwright MCP or Stitch MCP)
420
453
 
421
- > **Purpose:** Generate a real HTML preview using project design tokens before writing formal specs.
454
+ > **Purpose:** Generate a real visual preview using project design tokens before writing formal specs.
422
455
  > Seeing the actual visual before committing to components prevents misaligned specs.
423
456
 
457
+ #### 3.5.0 — Stitch MCP Path (Alternative to HTML Mockup)
458
+
459
+ > **Skip if:** Stitch MCP is NOT available. Fall through to 3.5.1 (HTML mockup).
460
+ > **Use when:** Stitch MCP is detected and user wants AI-generated screen designs.
461
+
462
+ If Stitch MCP is available, present the user with a choice:
463
+
464
+ ```json
465
+ {
466
+ "questions": [{
467
+ "header": "Design Tool",
468
+ "question": "Stitch MCP is available for AI-generated screen designs. How would you like to create visual mockups?",
469
+ "multiSelect": false,
470
+ "options": [
471
+ { "label": "Use Stitch", "description": "Generate screens via Google Stitch AI — higher fidelity, exportable design.md" },
472
+ { "label": "Use HTML mockup", "description": "Generate HTML file + Playwright screenshots — current default workflow" }
473
+ ]
474
+ }]
475
+ }
476
+ ```
477
+
478
+ **If "Use Stitch" selected:**
479
+
480
+ 1. **Create or select project:**
481
+ ```
482
+ stitch__create_project({ name: "{feature-name}-design" })
483
+ ```
484
+ Or if project already exists (from Case E in Step 0.5.3), reuse it.
485
+
486
+ 2. **Generate screens from design brief:**
487
+ Build a prompt from the aesthetic direction (Step 1.5), selected trends (Step 1.3), and user input (Step 2):
488
+ ```
489
+ stitch__generate_screen_from_text({
490
+ projectId: projectId,
491
+ prompt: "Create a {detectedDomain} screen with {aestheticDirection} direction. Colors: {primaryColor}, {accentColor}. Font: {fontPair}. Layout: {layoutDescription}. Features: {componentList}"
492
+ })
493
+ ```
494
+
495
+ 3. **Fetch screen images for review:**
496
+ ```
497
+ stitch__list_screens({ projectId: projectId })
498
+ stitch__fetch_screen_image({ screenId: screenId })
499
+ ```
500
+ Save images to `.morph/features/$ARGUMENTS/1-ui/stitch-screen-*.png`
501
+
502
+ 4. **Present to user for feedback** (same approval loop as 3.5.3):
503
+ - Show Stitch-generated screen images
504
+ - Ask: "Does this visual direction match your intent?"
505
+ - Iterate: regenerate via `generate_screen_from_text` with refined prompts
506
+
507
+ 5. **Export design tokens:**
508
+ ```
509
+ stitch__fetch_screen_code({ screenId: approvedScreenId })
510
+ ```
511
+ Parse the design.md export and update `.morph/context/design-system.md` with any new or refined tokens.
512
+
513
+ 6. **Skip to Step 4** — Stitch screens replace the HTML mockup. `mockups.md` still documents states and interactions textually.
514
+
515
+ > **Key advantage:** Unlike screenshots, the Stitch MCP transmits real HTML/CSS code via `fetch_screen_code()`.
516
+ > This produces dramatically higher fidelity results than screenshot-based workflows because Claude Code
517
+ > receives the actual component structure, CSS properties, and design tokens — not pixel approximations.
518
+ > Use `react-components` or `shadcn-ui` companion skills to convert Stitch HTML into production React components.
519
+
520
+ **If "Use HTML mockup" selected:**
521
+ → Proceed to 3.5.1 (existing workflow, unchanged)
522
+
523
+ ---
524
+
424
525
  #### 3.5.1 — Generate HTML Mockup
425
526
 
426
527
  Create an HTML file that represents the main screen/layout using **real tokens from `.morph/context/design-system.md`**:
@@ -533,6 +634,13 @@ Create the following files in `.morph/features/$ARGUMENTS/`:
533
634
  - Spacing and layout (grid, margins, paddings)
534
635
  - Base components (buttons, inputs, cards)
535
636
 
637
+ **If Stitch was used (Step 3.5.0):**
638
+ - Derive `design-system.md` primarily from Stitch's exported design.md
639
+ - Map Stitch tokens into existing template sections (Color Tokens, Typography, Spacing, etc.)
640
+ - Cross-reference with tokens from Step 0.5 — preserve manually-set tokens, let Stitch values fill gaps
641
+ - Add to `## Aesthetic Direction`: "Visual direction generated via Google Stitch (project: {projectName})"
642
+ - Ensure all CSS custom properties use the standard `--color-*`, `--font-*`, `--space-*` naming convention
643
+
536
644
  #### 4.2. `mockups.md`
537
645
 
538
646
  ASCII wireframes + descriptions:
@@ -666,13 +774,13 @@ Use `AskUserQuestion` to capture explicit approval before advancing:
666
774
 
667
775
  ## Phase Outputs
668
776
 
669
- <!-- morph-outputs:uiux -->
670
- | Output | Caminho |
671
- |--------|---------|
672
- | `uiDesignSystem` | `.morph/features/{feature}/1-ui/design-system.md` |
673
- | `uiMockups` | `.morph/features/{feature}/1-ui/mockups.md` |
674
- | `uiComponents` | `.morph/features/{feature}/1-ui/components.md` |
675
- | `uiFlows` | `.morph/features/{feature}/1-ui/flows.md` |
777
+ <!-- morph-outputs:uiux -->
778
+ | Output | Caminho |
779
+ |--------|---------|
780
+ | `uiDesignSystem` | `.morph/features/{feature}/1-ui/design-system.md` |
781
+ | `uiMockups` | `.morph/features/{feature}/1-ui/mockups.md` |
782
+ | `uiComponents` | `.morph/features/{feature}/1-ui/components.md` |
783
+ | `uiFlows` | `.morph/features/{feature}/1-ui/flows.md` |
676
784
  <!-- /morph-outputs -->
677
785
 
678
786
  ---
@@ -4,7 +4,7 @@ description: Guided workflow for mid-implementation scope escalation — analyze
4
4
  user-invocable: true
5
5
  argument-hint: "[feature-name]"
6
6
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
7
- cliVersion: "4.18.0"
7
+ cliVersion: "4.20.0"
8
8
  ---
9
9
 
10
10
  # Scope Escalation Workflow
@@ -118,10 +118,13 @@ Expose agents as interoperable web services using the standardized A2A protocol.
118
118
  ### Packages
119
119
 
120
120
  ```xml
121
- <!-- ⚠️ MAF packages are in PREVIEW — API surface may change before GA -->
122
- <PackageReference Include="Microsoft.Agents.AI.Hosting.A2A.AspNetCore" Version="1.0.0-preview.*" />
121
+ <!-- A2A hosting — not yet published on NuGet, uncomment when GA -->
122
+ <!-- <PackageReference Include="Microsoft.Agents.AI.Hosting.A2A.AspNetCore" Version="1.0.0-preview.*" /> -->
123
123
  ```
124
124
 
125
+ > **Note:** The A2A hosting package is part of the MAF preview and is **not yet available on NuGet**.
126
+ > The patterns below reflect the expected API surface. Until GA, implement A2A manually via HTTP endpoints.
127
+
125
128
  ### Expose Agent via A2A
126
129
 
127
130
  ```csharp
@@ -14,23 +14,23 @@ Semantic Kernel is superseded. Do NOT use `Kernel`, `KernelFunction`, or `Invoke
14
14
 
15
15
  ```xml
16
16
  <!-- .csproj -->
17
- <!-- ⚠️ MAF packages are in PREVIEW — API surface may change before GA -->
18
- <PackageReference Include="Microsoft.Agents.AI" Version="1.0.0-preview.*" />
19
- <PackageReference Include="Microsoft.Agents.AI.Abstractions" Version="1.0.0-preview.*" />
20
- <PackageReference Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0-preview.*" />
21
-
22
- <!-- For Web API hosting + A2A -->
23
- <PackageReference Include="Microsoft.Agents.AI.Hosting" Version="1.0.0-preview.*" />
17
+ <!-- Microsoft.Extensions.AI — STABLE abstractions for IChatClient, AIFunctionFactory, tools -->
18
+ <PackageReference Include="Microsoft.Extensions.AI" Version="9.5.0" />
19
+ <PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.3.0-preview.*" />
24
20
 
25
21
  <!-- For Azure OpenAI -->
26
22
  <PackageReference Include="Azure.AI.OpenAI" Version="2.*" />
27
23
  <PackageReference Include="Azure.Identity" Version="1.*" />
28
24
 
29
- <!-- For Microsoft.Extensions.AI abstractions (STABLE — use as fallback when MAF preview breaks) -->
30
- <PackageReference Include="Microsoft.Extensions.AI" Version="9.5.0" />
31
- <PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.3.0-preview.*" />
25
+ <!-- For A2A protocol hosting (when GA) -->
26
+ <!-- <PackageReference Include="Microsoft.Agents.AI.Hosting.A2A.AspNetCore" Version="1.0.0-preview.*" /> -->
32
27
  ```
33
28
 
29
+ > **Note:** The Microsoft Agent Framework (MAF) packages (`Microsoft.Agents.AI.*`) are **not yet published on NuGet**.
30
+ > Use `Microsoft.Extensions.AI` as the primary package — it provides `IChatClient`, `AIFunctionFactory`,
31
+ > and all abstractions shown in this guide. The MAF `ChatClientAgent`, `AsAIAgent()`, and `AgentWorkflowBuilder`
32
+ > APIs documented here reflect the expected GA surface. Until MAF ships, implement agents using `IChatClient` directly.
33
+
34
34
  ---
35
35
 
36
36
  ## Quick Start (Minimal Agent)
@@ -38,7 +38,7 @@ Semantic Kernel is superseded. Do NOT use `Kernel`, `KernelFunction`, or `Invoke
38
38
  ```csharp
39
39
  using Azure.AI.OpenAI;
40
40
  using Azure.Identity;
41
- using Microsoft.Agents.AI;
41
+ using Microsoft.Extensions.AI;
42
42
 
43
43
  AIAgent agent = new AzureOpenAIClient(
44
44
  new Uri("https://your-resource.openai.azure.com/"),
@@ -104,7 +104,6 @@ builder.Services.AddSingleton<IChatClient>(sp =>
104
104
  ### Using ChatClientAgent
105
105
 
106
106
  ```csharp
107
- using Microsoft.Agents.AI;
108
107
  using Microsoft.Extensions.AI;
109
108
 
110
109
  public class OrderAnalysisAgent
@@ -374,7 +373,7 @@ builder.Services.AddOpenTelemetry()
374
373
 
375
374
  ## Checklist
376
375
 
377
- - [ ] `Microsoft.Agents.AI` + `Microsoft.Agents.AI.OpenAI` installed
376
+ - [ ] `Microsoft.Extensions.AI` + `Microsoft.Extensions.AI.OpenAI` installed
378
377
  - [ ] `IChatClient` registered as singleton via DI
379
378
  - [ ] Agents created with `ChatClientAgent` or `AsAIAgent()`
380
379
  - [ ] Agents registered with `builder.AddAIAgent()` (keyed services)
@@ -391,7 +390,7 @@ builder.Services.AddOpenTelemetry()
391
390
 
392
391
  | Wrong | Correct |
393
392
  |-------|---------|
394
- | `using Microsoft.SemanticKernel` | `using Microsoft.Agents.AI` |
393
+ | `using Microsoft.SemanticKernel` | `using Microsoft.Extensions.AI` |
395
394
  | `Kernel.InvokePromptAsync()` | `agent.RunAsync()` |
396
395
  | `[KernelFunction]` | `AIFunctionFactory.Create()` |
397
396
  | `[AgentTool]` attribute | `[Description]` + `AIFunctionFactory` |
@@ -23,11 +23,14 @@ Workflows compose multiple agents and executors into coordinated pipelines using
23
23
  ### Packages
24
24
 
25
25
  ```xml
26
- <!-- ⚠️ MAF packages are in PREVIEW — API surface may change before GA -->
27
- <PackageReference Include="Microsoft.Agents.AI" Version="1.0.0-preview.*" />
28
- <PackageReference Include="Microsoft.Agents.AI.Workflows" Version="1.0.0-preview.*" />
26
+ <!-- Microsoft.Extensions.AI — core abstractions -->
27
+ <PackageReference Include="Microsoft.Extensions.AI" Version="9.5.0" />
29
28
  ```
30
29
 
30
+ > **Note:** Workflow orchestration APIs (`AgentWorkflowBuilder`, `BuildSequential`, `CreateGroupChatBuilderWith`)
31
+ > are part of the MAF preview that is **not yet published on NuGet**. The patterns documented here reflect
32
+ > the expected GA surface. Until MAF ships, implement sequential/parallel workflows manually using `IChatClient`.
33
+
31
34
  ---
32
35
 
33
36
  ## 5 Orchestration Patterns
@@ -51,8 +54,7 @@ Agents execute in order — each agent receives the output of the previous one.
51
54
  ```
52
55
 
53
56
  ```csharp
54
- using Microsoft.Agents.AI;
55
- using Microsoft.Agents.AI.Workflows;
57
+ using Microsoft.Extensions.AI;
56
58
 
57
59
  AIAgent writer = new ChatClientAgent(chatClient, new ChatClientAgentOptions
58
60
  {
@@ -330,7 +332,7 @@ var agent = chatClient.AsAIAgent(instructions: prompt, name: "Analyst");
330
332
 
331
333
  ## Checklist
332
334
 
333
- - [ ] `Microsoft.Agents.AI.Workflows` package installed
335
+ - [ ] `Microsoft.Extensions.AI` package installed
334
336
  - [ ] Orchestration pattern selected and justified
335
337
  - [ ] Agents have clear, single responsibilities
336
338
  - [ ] Workflow built with `AgentWorkflowBuilder`
@@ -239,7 +239,7 @@ EF.Functions.VectorDistance(vector1, vector2, DistanceFunction.Cosine)
239
239
  ### Implementação RAG com Agent Framework
240
240
 
241
241
  ```csharp
242
- using Microsoft.Agents.AI;
242
+ using Microsoft.Extensions.AI;
243
243
 
244
244
  public interface IDocumentAssistantAgent
245
245
  {
@@ -5,7 +5,6 @@
5
5
 
6
6
  using System.ComponentModel;
7
7
  using System.Text.Json;
8
- using Microsoft.Agents.AI;
9
8
  using Microsoft.Extensions.AI;
10
9
  using Microsoft.Extensions.Logging;
11
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polymorphism-tech/morph-spec",
3
- "version": "4.18.0",
3
+ "version": "4.20.0",
4
4
  "description": "MORPH-SPEC: AI-First development framework with validation pipeline and multi-stack support",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -0,0 +1,53 @@
1
+ import { spawn } from 'child_process';
2
+ import { existsSync } from 'fs';
3
+ import { resolve, dirname } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import chalk from 'chalk';
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+
9
+ export async function dashboardCommand(options = {}) {
10
+ const port = options.port || '3200';
11
+ const dashboardDir = resolve(__dirname, '..', '..', 'dashboard');
12
+ const nodeModules = resolve(dashboardDir, 'node_modules');
13
+
14
+ // Check if dashboard dependencies are installed
15
+ if (!existsSync(nodeModules)) {
16
+ console.log(chalk.yellow('Installing dashboard dependencies...'));
17
+ const install = spawn('npm', ['install'], {
18
+ cwd: dashboardDir,
19
+ stdio: 'inherit',
20
+ shell: true,
21
+ });
22
+ await new Promise((res, rej) => {
23
+ install.on('close', (code) => (code === 0 ? res() : rej(new Error(`npm install failed with code ${code}`))));
24
+ });
25
+ }
26
+
27
+ console.log(chalk.cyan(`\n Starting morph-spec dashboard at http://localhost:${port}\n`));
28
+
29
+ const env = {
30
+ ...process.env,
31
+ MORPH_PROJECT_DIR: process.cwd(),
32
+ };
33
+
34
+ const viteArgs = ['vite', '--port', port];
35
+ if (options.open !== false) viteArgs.push('--open');
36
+
37
+ const vite = spawn('npx', viteArgs, {
38
+ cwd: dashboardDir,
39
+ stdio: 'inherit',
40
+ shell: true,
41
+ env,
42
+ });
43
+
44
+ vite.on('error', (err) => {
45
+ console.error(chalk.red(`Failed to start dashboard: ${err.message}`));
46
+ process.exit(1);
47
+ });
48
+
49
+ process.on('SIGINT', () => {
50
+ vite.kill();
51
+ process.exit(0);
52
+ });
53
+ }
@@ -16,6 +16,7 @@ import ora from 'ora';
16
16
  import {
17
17
  orchestrateMcpSetup,
18
18
  installAutoMcps,
19
+ installCompanionSkills,
19
20
  installMcpWithCredentials,
20
21
  generateSetupInstructions,
21
22
  formatMcpStatusTable,
@@ -120,6 +121,16 @@ async function autoInstall(targetPath, stack, existingMcps) {
120
121
  console.log(chalk.gray(` Skipped (already configured): ${result.skipped.join(', ')}`));
121
122
  }
122
123
 
124
+ // Install companion skills for MCPs that define them
125
+ const skillResults = installCompanionSkills(orchestration.autoInstallable);
126
+ for (const r of skillResults) {
127
+ if (r.success) {
128
+ console.log(chalk.green(` ✓ Companion skills installed: ${r.repo}`));
129
+ } else {
130
+ console.log(chalk.yellow(` ⚠ Failed to install companion skills: ${r.repo}`));
131
+ }
132
+ }
133
+
123
134
  console.log('');
124
135
  }
125
136
 
@@ -305,6 +316,16 @@ async function interactiveWizard(targetPath, stack, existingMcps) {
305
316
  const spinner = ora('Installing...').start();
306
317
  const result = await installAutoMcps(targetPath, orchestration.autoInstallable);
307
318
  spinner.succeed(`Installed: ${result.added.join(', ')}`);
319
+
320
+ // Install companion skills for MCPs that define them
321
+ const skillResults = installCompanionSkills(orchestration.autoInstallable);
322
+ for (const r of skillResults) {
323
+ if (r.success) {
324
+ console.log(chalk.green(` ✓ Companion skills: ${r.repo}`));
325
+ } else {
326
+ console.log(chalk.yellow(` ⚠ Companion skills failed: ${r.repo}`));
327
+ }
328
+ }
308
329
  }
309
330
  }
310
331
 
@@ -20,6 +20,7 @@ import { generateSettings, saveIntegrations } from '../../lib/generators/setting
20
20
  import {
21
21
  orchestrateMcpSetup,
22
22
  installAutoMcps,
23
+ installCompanionSkills,
23
24
  installMcpWithCredentials,
24
25
  generateSetupInstructions,
25
26
  formatMcpStatusTable,
@@ -256,6 +257,16 @@ export async function initCommand(options) {
256
257
  for (const name of result.added) {
257
258
  autoInstalled[name] = orchestration.autoInstallable[name];
258
259
  }
260
+
261
+ // Install companion skills for MCPs that define them (e.g., Stitch agent skills)
262
+ const skillResults = installCompanionSkills(orchestration.autoInstallable);
263
+ for (const r of skillResults) {
264
+ if (r.success) {
265
+ logger.info(`✓ Companion skills installed: ${r.repo}`);
266
+ } else {
267
+ logger.warn(`Failed to install companion skills: ${r.repo}`);
268
+ }
269
+ }
259
270
  }
260
271
  }
261
272
 
@@ -0,0 +1,31 @@
1
+ import { Routes, Route, Navigate } from 'react-router-dom';
2
+ import Sidebar from './components/Sidebar.jsx';
3
+ import AgentMap from './pages/AgentMap.jsx';
4
+ import PhasePipeline from './pages/PhasePipeline.jsx';
5
+ import HookInspector from './pages/HookInspector.jsx';
6
+ import SkillsLibrary from './pages/SkillsLibrary.jsx';
7
+ import RulesMap from './pages/RulesMap.jsx';
8
+ import Standards from './pages/Standards.jsx';
9
+ import Workflows from './pages/Workflows.jsx';
10
+ import LiveState from './pages/LiveState.jsx';
11
+
12
+ export default function App() {
13
+ return (
14
+ <div className="flex h-screen bg-gray-950 text-gray-100 overflow-hidden">
15
+ <Sidebar />
16
+ <main className="flex-1 overflow-auto">
17
+ <Routes>
18
+ <Route path="/" element={<Navigate to="/agents" replace />} />
19
+ <Route path="/agents" element={<AgentMap />} />
20
+ <Route path="/phases" element={<PhasePipeline />} />
21
+ <Route path="/hooks" element={<HookInspector />} />
22
+ <Route path="/skills" element={<SkillsLibrary />} />
23
+ <Route path="/rules" element={<RulesMap />} />
24
+ <Route path="/standards" element={<Standards />} />
25
+ <Route path="/workflows" element={<Workflows />} />
26
+ <Route path="/state" element={<LiveState />} />
27
+ </Routes>
28
+ </main>
29
+ </div>
30
+ );
31
+ }
@@ -0,0 +1,11 @@
1
+ export default function DetailPanel({ open, title, onClose, children }) {
2
+ return (
3
+ <div className={`fixed top-0 right-0 h-full w-96 bg-gray-900 border-l border-gray-700 shadow-2xl transform transition-transform duration-200 ease-in-out z-50 ${open ? 'translate-x-0' : 'translate-x-full'}`}>
4
+ <div className="flex items-center justify-between p-4 border-b border-gray-700">
5
+ <h2 className="text-white font-semibold text-lg truncate">{title}</h2>
6
+ <button onClick={onClose} className="text-gray-400 hover:text-white text-xl leading-none">×</button>
7
+ </div>
8
+ <div className="p-4 overflow-y-auto h-[calc(100%-57px)]">{children}</div>
9
+ </div>
10
+ );
11
+ }
@@ -0,0 +1,17 @@
1
+ import { ReactFlow, Controls, MiniMap, Background } from '@xyflow/react';
2
+
3
+ export default function FlowGraph({ nodes, edges, nodeTypes, onNodeClick, fitView = true, className = '' }) {
4
+ return (
5
+ <div className={`w-full h-full ${className}`} style={{ minHeight: '500px' }}>
6
+ <ReactFlow
7
+ nodes={nodes} edges={edges} nodeTypes={nodeTypes} onNodeClick={onNodeClick}
8
+ fitView={fitView} proOptions={{ hideAttribution: true }}
9
+ defaultEdgeOptions={{ type: 'smoothstep', animated: false, style: { stroke: '#475569', strokeWidth: 1.5 } }}
10
+ >
11
+ <Background color="#1e293b" gap={20} />
12
+ <Controls position="bottom-right" />
13
+ <MiniMap nodeColor={(node) => node.data?.color || '#475569'} maskColor="rgba(0, 0, 0, 0.7)" position="bottom-left" />
14
+ </ReactFlow>
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,22 @@
1
+ import { useState } from 'react';
2
+
3
+ export default function SearchFilter({ placeholder = 'Search...', filters = [], onSearchChange, onFilterChange }) {
4
+ const [search, setSearch] = useState('');
5
+ function handleSearchChange(e) {
6
+ setSearch(e.target.value);
7
+ onSearchChange?.(e.target.value);
8
+ }
9
+ return (
10
+ <div className="flex items-center gap-3 p-3 bg-gray-900 border-b border-gray-800">
11
+ <input type="text" value={search} onChange={handleSearchChange} placeholder={placeholder}
12
+ className="flex-1 bg-gray-800 border border-gray-700 rounded-md px-3 py-1.5 text-sm text-gray-100 placeholder-gray-500 focus:outline-none focus:border-blue-500" />
13
+ {filters.map(({ name, label, options, value }) => (
14
+ <select key={name} value={value} onChange={(e) => onFilterChange?.(name, e.target.value)}
15
+ className="bg-gray-800 border border-gray-700 rounded-md px-2 py-1.5 text-sm text-gray-300 focus:outline-none focus:border-blue-500">
16
+ <option value="">{label}: All</option>
17
+ {options.map((opt) => (<option key={opt} value={opt}>{opt}</option>))}
18
+ </select>
19
+ ))}
20
+ </div>
21
+ );
22
+ }
@@ -0,0 +1,45 @@
1
+ import { NavLink } from 'react-router-dom';
2
+
3
+ const NAV_ITEMS = [
4
+ { to: '/agents', label: 'Agent Map', icon: '🗺️' },
5
+ { to: '/phases', label: 'Phases', icon: '⚡' },
6
+ { to: '/hooks', label: 'Hooks', icon: '🔗' },
7
+ { to: '/skills', label: 'Skills', icon: '🧩' },
8
+ { to: '/rules', label: 'Rules', icon: '📏' },
9
+ { to: '/standards', label: 'Standards', icon: '📋' },
10
+ { to: '/workflows', label: 'Workflows', icon: '🔄' },
11
+ { to: '/state', label: 'Live State', icon: '📊' },
12
+ ];
13
+
14
+ export default function Sidebar() {
15
+ return (
16
+ <nav className="w-52 flex-shrink-0 bg-gray-900 border-r border-gray-800 flex flex-col">
17
+ <div className="px-4 py-4 border-b border-gray-800">
18
+ <h1 className="text-sm font-semibold text-gray-300 tracking-wide uppercase">
19
+ morph-spec
20
+ </h1>
21
+ <p className="text-xs text-gray-500 mt-0.5">Dashboard</p>
22
+ </div>
23
+ <ul className="flex-1 py-2">
24
+ {NAV_ITEMS.map(({ to, label, icon }) => (
25
+ <li key={to}>
26
+ <NavLink
27
+ to={to}
28
+ className={({ isActive }) =>
29
+ [
30
+ 'flex items-center gap-2.5 px-4 py-2 text-sm transition-colors',
31
+ isActive
32
+ ? 'bg-blue-900/40 border-r-2 border-blue-500 text-blue-300'
33
+ : 'text-gray-400 hover:bg-gray-800 hover:text-gray-200',
34
+ ].join(' ')
35
+ }
36
+ >
37
+ <span className="text-base leading-none">{icon}</span>
38
+ <span>{label}</span>
39
+ </NavLink>
40
+ </li>
41
+ ))}
42
+ </ul>
43
+ </nav>
44
+ );
45
+ }
@@ -0,0 +1,15 @@
1
+ import { useState, useCallback } from 'react';
2
+
3
+ export function useDetailPanel() {
4
+ const [panel, setPanel] = useState({ open: false, title: '', content: null });
5
+
6
+ const openPanel = useCallback((title, content) => {
7
+ setPanel({ open: true, title, content });
8
+ }, []);
9
+
10
+ const closePanel = useCallback(() => {
11
+ setPanel((prev) => ({ ...prev, open: false }));
12
+ }, []);
13
+
14
+ return { panel, openPanel, closePanel };
15
+ }
@@ -0,0 +1,13 @@
1
+ import { StrictMode } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { BrowserRouter } from 'react-router-dom';
4
+ import App from './App.jsx';
5
+ import './styles/index.css';
6
+
7
+ createRoot(document.getElementById('root')).render(
8
+ <StrictMode>
9
+ <BrowserRouter>
10
+ <App />
11
+ </BrowserRouter>
12
+ </StrictMode>
13
+ );