@polymorphism-tech/morph-spec 7.9.3 → 8.0.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 (213) hide show
  1. package/CLAUDE.md +2 -2
  2. package/README.md +31 -2
  3. package/bin/morph-spec.js +50 -2
  4. package/bin/validate.js +379 -379
  5. package/claude-plugin.json +1 -1
  6. package/docs/CHEATSHEET.md +38 -1
  7. package/docs/QUICKSTART.md +60 -1
  8. package/framework/CLAUDE.md +13 -2
  9. package/framework/MORPH.md +38 -2
  10. package/framework/agents.json +22 -3
  11. package/framework/commands/commit.md +166 -166
  12. package/framework/commands/morph-hotfix.md +39 -0
  13. package/framework/commands/morph-infra.md +215 -215
  14. package/framework/commands/morph-preflight.md +205 -205
  15. package/framework/commands/morph-troubleshoot.md +124 -124
  16. package/framework/hooks/README.md +25 -10
  17. package/framework/hooks/claude-code/core/gate-guard.js +4 -2
  18. package/framework/hooks/claude-code/core/loop-detect.js +2 -1
  19. package/framework/hooks/claude-code/core/post-edit-typecheck.js +14 -5
  20. package/framework/hooks/claude-code/core/tasks-json-guard.js +4 -2
  21. package/framework/hooks/claude-code/core/validate-completion.js +1 -1
  22. package/framework/hooks/claude-code/core/worktree-context.js +160 -0
  23. package/framework/hooks/claude-code/statusline.py +679 -679
  24. package/framework/hooks/claude-code/statusline.sh +11 -11
  25. package/framework/hooks/git/commit-msg/conventional-commits.sh +33 -33
  26. package/framework/hooks/git/pre-commit/agents.sh +25 -25
  27. package/framework/hooks/git/pre-commit/orchestrator.sh +64 -64
  28. package/framework/hooks/git/pre-commit/specs.sh +50 -50
  29. package/framework/hooks/git/pre-push/run-tests.sh +44 -44
  30. package/framework/hooks/shared/activity-logger.js +160 -160
  31. package/framework/hooks/shared/build-check.js +2 -2
  32. package/framework/hooks/shared/hook-response.js +17 -5
  33. package/framework/hooks/shared/payload-utils.js +42 -0
  34. package/framework/hooks/shared/state-reader.js +22 -2
  35. package/framework/hooks/shared/stdin-reader.js +26 -26
  36. package/framework/rubrics/backend.json +41 -41
  37. package/framework/rules/ai-agents-standards.md +45 -45
  38. package/framework/rules/dotnet-templates.md +86 -86
  39. package/framework/rules/frontend-standards.md +13 -13
  40. package/framework/rules/infrastructure-standards.md +27 -27
  41. package/framework/rules/neon-standards.md +25 -25
  42. package/framework/rules/nextjs-standards.md +20 -20
  43. package/framework/rules/nextjs-templates.md +40 -40
  44. package/framework/schemas/feature.schema.json +95 -1
  45. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  46. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  47. package/framework/skills/core/morph-apply/SKILL.md +39 -8
  48. package/framework/skills/core/morph-brainstorming/SKILL.md +9 -1
  49. package/framework/skills/core/morph-eval/SKILL.md +6 -1
  50. package/framework/skills/core/morph-hotfix/SKILL.md +136 -0
  51. package/framework/skills/core/morph-implement/SKILL.md +8 -4
  52. package/framework/skills/core/morph-plan/SKILL.md +5 -1
  53. package/framework/skills/core/morph-proposal/SKILL.md +24 -1
  54. package/framework/skills/core/morph-review/SKILL.md +3 -2
  55. package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
  56. package/framework/skills/core/morph-standards/SKILL.md +1 -1
  57. package/framework/standards/STANDARDS.json +7 -2
  58. package/framework/standards/ai-agents/agent-session.md +160 -160
  59. package/framework/standards/ai-agents/batching.md +193 -193
  60. package/framework/standards/ai-agents/context-providers.md +188 -188
  61. package/framework/standards/ai-agents/mcp-server.md +250 -250
  62. package/framework/standards/ai-agents/mcp-tools.md +197 -197
  63. package/framework/standards/ai-agents/middleware-patterns.md +207 -207
  64. package/framework/standards/ai-agents/modalities-image-gen.md +173 -173
  65. package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -171
  66. package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -181
  67. package/framework/standards/ai-agents/modalities-vision.md +201 -201
  68. package/framework/standards/ai-agents/multi-agent-patterns.md +155 -155
  69. package/framework/standards/ai-agents/production.md +275 -275
  70. package/framework/standards/ai-agents/prompts-in-db.md +214 -214
  71. package/framework/standards/ai-agents/providers/model-registry.md +158 -158
  72. package/framework/standards/ai-agents/service-tier-flex.md +135 -135
  73. package/framework/standards/ai-agents/structured-output.md +249 -249
  74. package/framework/standards/ai-agents/sweet-spot.md +109 -109
  75. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +45 -3
  76. package/framework/templates/.idea/morph-templates.xml +92 -0
  77. package/framework/templates/.vscode/morph-templates.code-snippets +186 -0
  78. package/framework/templates/IDE-SNIPPETS.md +262 -262
  79. package/framework/templates/REGISTRY.json +0 -62
  80. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
  81. package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -39
  82. package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -68
  83. package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -117
  84. package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -95
  85. package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -61
  86. package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -107
  87. package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -58
  88. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +281 -281
  89. package/framework/templates/code/dotnet/database/migration.cs +83 -83
  90. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -21
  91. package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
  92. package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
  93. package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -15
  94. package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -58
  95. package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
  96. package/framework/templates/code/typescript/contracts.ts +167 -167
  97. package/framework/templates/docs/clarifications.md +253 -253
  98. package/framework/templates/docs/schema-analysis.md +119 -119
  99. package/framework/templates/docs/ui-components.md +52 -52
  100. package/framework/templates/docs/ui-design-system.md +76 -76
  101. package/framework/templates/docs/ui-flows.md +167 -167
  102. package/framework/templates/docs/ui-mockups.md +98 -98
  103. package/framework/templates/feature/decisions.md +122 -122
  104. package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -43
  105. package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
  106. package/framework/templates/frontend/nextjs/env.mjs.hbs +32 -32
  107. package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -56
  108. package/framework/templates/frontend/nextjs/page.tsx.hbs +22 -22
  109. package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
  110. package/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -54
  111. package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
  112. package/framework/templates/infrastructure/docker/docker-compose.template.yml +50 -50
  113. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  114. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  115. package/framework/templates/infrastructure/github/README.md +56 -56
  116. package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
  117. package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
  118. package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
  119. package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
  120. package/framework/templates/integrations/asaas-client.cs +387 -387
  121. package/framework/templates/integrations/asaas-webhook.cs +351 -351
  122. package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -76
  123. package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -100
  124. package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -95
  125. package/framework/templates/project/validate.js +120 -120
  126. package/framework/templates/state.template.json +17 -17
  127. package/framework/templates/ui/design-system.css +226 -226
  128. package/package.json +1 -1
  129. package/src/commands/dashboard/dashboard.js +53 -53
  130. package/src/commands/index.js +13 -13
  131. package/src/commands/mcp/mcp-setup.js +519 -519
  132. package/src/commands/project/checkpoint.js +209 -209
  133. package/src/commands/project/doctor.js +4 -2
  134. package/src/commands/project/init.js +46 -2
  135. package/src/commands/project/update.js +5 -3
  136. package/src/commands/project/worktree.js +1005 -46
  137. package/src/commands/state/advance.js +17 -2
  138. package/src/commands/state/approve.js +18 -1
  139. package/src/commands/state/create.js +158 -14
  140. package/src/commands/state/retype.js +126 -0
  141. package/src/commands/state/score.js +4 -0
  142. package/src/commands/tasks/dag.js +32 -0
  143. package/src/commands/validation/index.js +1 -0
  144. package/src/commands/validation/validate-feature.js +33 -5
  145. package/src/commands/validation/verify.js +190 -0
  146. package/src/core/state/phase-state-machine.js +197 -197
  147. package/src/core/state/state-manager.js +35 -10
  148. package/src/core/templates/template-renderer.js +477 -477
  149. package/src/core/work-types.js +79 -0
  150. package/src/dashboard/app/components/DetailPanel.jsx +11 -11
  151. package/src/dashboard/app/components/FlowGraph.jsx +17 -17
  152. package/src/dashboard/app/components/SearchFilter.jsx +22 -22
  153. package/src/dashboard/app/hooks/useDetailPanel.js +15 -15
  154. package/src/dashboard/app/main.jsx +13 -13
  155. package/src/dashboard/app/pages/AgentMap.jsx +370 -370
  156. package/src/dashboard/app/pages/HookInspector.jsx +418 -418
  157. package/src/dashboard/app/pages/LiveState.jsx +11 -1
  158. package/src/dashboard/app/pages/PhasePipeline.jsx +408 -408
  159. package/src/dashboard/app/pages/RulesMap.jsx +273 -273
  160. package/src/dashboard/app/pages/SkillsLibrary.jsx +366 -366
  161. package/src/dashboard/app/pages/Standards.jsx +332 -332
  162. package/src/dashboard/app/styles/index.css +47 -47
  163. package/src/dashboard/index.html +12 -12
  164. package/src/dashboard/package.json +24 -24
  165. package/src/dashboard/scanner/hooks-scanner.js +41 -41
  166. package/src/dashboard/scanner/phases-scanner.js +15 -15
  167. package/src/dashboard/scanner/rubrics-scanner.js +12 -12
  168. package/src/dashboard/scanner/rules-scanner.js +37 -37
  169. package/src/dashboard/scanner/skills-scanner.js +43 -43
  170. package/src/dashboard/scanner/squads-scanner.js +13 -13
  171. package/src/dashboard/scanner/standards-scanner.js +26 -26
  172. package/src/dashboard/scanner/state-scanner.js +42 -0
  173. package/src/dashboard/vite-plugin-morph-data.js +17 -17
  174. package/src/dashboard/vite.config.js +24 -24
  175. package/src/lib/agents/metrics-aggregator.js +56 -56
  176. package/src/lib/agents/metrics-calculator.js +125 -125
  177. package/src/lib/agents/output-collector.js +73 -73
  178. package/src/lib/detectors/claude-config-detector.js +152 -152
  179. package/src/lib/detectors/design-system-detector.js +231 -231
  180. package/src/lib/detectors/index.js +217 -217
  181. package/src/lib/generators/architecture-scanner.js +639 -639
  182. package/src/lib/generators/design-system-generator.js +508 -508
  183. package/src/lib/generators/index.js +13 -13
  184. package/src/lib/generators/settings-generator.js +209 -209
  185. package/src/lib/hooks/hook-executor.js +167 -167
  186. package/src/lib/installers/mcp-installer.js +719 -719
  187. package/src/lib/installers/memory-installer.js +1 -1
  188. package/src/lib/risk-detector.js +16 -0
  189. package/src/lib/tasks/dispatch-planner.js +122 -4
  190. package/src/lib/tasks/mermaid-renderer.js +132 -0
  191. package/src/lib/tasks/task-classifier.js +30 -30
  192. package/src/lib/tasks/task-parser.js +209 -209
  193. package/src/lib/tasks/test-runner.js +27 -6
  194. package/src/lib/validators/architecture/architecture-validator.js +259 -259
  195. package/src/lib/validators/checkpoint-persistence.js +39 -39
  196. package/src/lib/validators/contracts/contract-compliance-validator.js +274 -274
  197. package/src/lib/validators/css/css-validator.js +340 -340
  198. package/src/lib/validators/packages/package-validator.js +347 -347
  199. package/src/lib/validators/shared/emit-validator-dispatch.js +14 -14
  200. package/src/lib/validators/shared/issue-counter.js +14 -14
  201. package/src/lib/validators/validation-runner.js +349 -349
  202. package/src/lib/validators/verify-runner.js +322 -0
  203. package/src/lib/work-type-detector.js +143 -0
  204. package/src/scripts/setup-infra.js +32 -5
  205. package/src/utils/agent-id-mapper.js +11 -11
  206. package/src/utils/agents-installer.js +10 -6
  207. package/src/utils/claude-settings-manager.js +300 -300
  208. package/src/utils/file-copier.js +43 -0
  209. package/src/utils/hooks-installer.js +41 -11
  210. package/src/utils/skills-installer.js +174 -174
  211. package/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +0 -113
  212. package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +0 -80
  213. package/src/lib/tasks/wave-resolver.js +0 -353
@@ -1,83 +1,83 @@
1
- // ============================================================
2
- // EF CORE MIGRATION TEMPLATE
3
- // Generated by MORPH Framework
4
- // ============================================================
5
-
6
- using Microsoft.EntityFrameworkCore.Migrations;
7
-
8
- #nullable disable
9
-
10
- namespace {{NAMESPACE}}.Infrastructure.Data.Migrations;
11
-
12
- /// <inheritdoc />
13
- public partial class Add{{pascalCase FEATURE_NAME}} : Migration
14
- {
15
- /// <inheritdoc />
16
- protected override void Up(MigrationBuilder migrationBuilder)
17
- {
18
- migrationBuilder.CreateTable(
19
- name: "{{pascalCase FEATURE_NAME}}s",
20
- columns: table => new
21
- {
22
- Id = table.Column<int>(type: "int", nullable: false)
23
- .Annotation("SqlServer:Identity", "1, 1"),
24
- Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
25
- Status = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
26
- CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false,
27
- defaultValueSql: "GETUTCDATE()"),
28
- UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true)
29
- },
30
- constraints: table =>
31
- {
32
- table.PrimaryKey("PK_{{pascalCase FEATURE_NAME}}s", x => x.Id);
33
- });
34
-
35
- // Indexes
36
- migrationBuilder.CreateIndex(
37
- name: "IX_{{pascalCase FEATURE_NAME}}s_Name",
38
- table: "{{pascalCase FEATURE_NAME}}s",
39
- column: "Name");
40
-
41
- migrationBuilder.CreateIndex(
42
- name: "IX_{{pascalCase FEATURE_NAME}}s_Status",
43
- table: "{{pascalCase FEATURE_NAME}}s",
44
- column: "Status");
45
-
46
- migrationBuilder.CreateIndex(
47
- name: "IX_{{pascalCase FEATURE_NAME}}s_CreatedAt",
48
- table: "{{pascalCase FEATURE_NAME}}s",
49
- column: "CreatedAt");
50
- }
51
-
52
- /// <inheritdoc />
53
- protected override void Down(MigrationBuilder migrationBuilder)
54
- {
55
- migrationBuilder.DropTable(
56
- name: "{{pascalCase FEATURE_NAME}}s");
57
- }
58
- }
59
-
60
- // ============================================================
61
- // HOW TO CREATE A MIGRATION
62
- // ============================================================
63
- //
64
- // 1. Add your entity to AppDbContext:
65
- //
66
- // public DbSet<{{pascalCase FEATURE_NAME}}> {{pascalCase FEATURE_NAME}}s => Set<{{pascalCase FEATURE_NAME}}>();
67
- //
68
- // 2. Add your configuration:
69
- //
70
- // protected override void OnModelCreating(ModelBuilder modelBuilder)
71
- // {
72
- // modelBuilder.ApplyConfiguration(new {{pascalCase FEATURE_NAME}}Configuration());
73
- // }
74
- //
75
- // 3. Run migration command:
76
- //
77
- // dotnet ef migrations add Add{{pascalCase FEATURE_NAME}} -p src/{{NAMESPACE}}.Infrastructure -s src/{{NAMESPACE}}.Web
78
- //
79
- // 4. Apply migration:
80
- //
81
- // dotnet ef database update -p src/{{NAMESPACE}}.Infrastructure -s src/{{NAMESPACE}}.Web
82
- //
83
- // ============================================================
1
+ // ============================================================
2
+ // EF CORE MIGRATION TEMPLATE
3
+ // Generated by MORPH Framework
4
+ // ============================================================
5
+
6
+ using Microsoft.EntityFrameworkCore.Migrations;
7
+
8
+ #nullable disable
9
+
10
+ namespace {{NAMESPACE}}.Infrastructure.Data.Migrations;
11
+
12
+ /// <inheritdoc />
13
+ public partial class Add{{pascalCase FEATURE_NAME}} : Migration
14
+ {
15
+ /// <inheritdoc />
16
+ protected override void Up(MigrationBuilder migrationBuilder)
17
+ {
18
+ migrationBuilder.CreateTable(
19
+ name: "{{pascalCase FEATURE_NAME}}s",
20
+ columns: table => new
21
+ {
22
+ Id = table.Column<int>(type: "int", nullable: false)
23
+ .Annotation("SqlServer:Identity", "1, 1"),
24
+ Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
25
+ Status = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
26
+ CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false,
27
+ defaultValueSql: "GETUTCDATE()"),
28
+ UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true)
29
+ },
30
+ constraints: table =>
31
+ {
32
+ table.PrimaryKey("PK_{{pascalCase FEATURE_NAME}}s", x => x.Id);
33
+ });
34
+
35
+ // Indexes
36
+ migrationBuilder.CreateIndex(
37
+ name: "IX_{{pascalCase FEATURE_NAME}}s_Name",
38
+ table: "{{pascalCase FEATURE_NAME}}s",
39
+ column: "Name");
40
+
41
+ migrationBuilder.CreateIndex(
42
+ name: "IX_{{pascalCase FEATURE_NAME}}s_Status",
43
+ table: "{{pascalCase FEATURE_NAME}}s",
44
+ column: "Status");
45
+
46
+ migrationBuilder.CreateIndex(
47
+ name: "IX_{{pascalCase FEATURE_NAME}}s_CreatedAt",
48
+ table: "{{pascalCase FEATURE_NAME}}s",
49
+ column: "CreatedAt");
50
+ }
51
+
52
+ /// <inheritdoc />
53
+ protected override void Down(MigrationBuilder migrationBuilder)
54
+ {
55
+ migrationBuilder.DropTable(
56
+ name: "{{pascalCase FEATURE_NAME}}s");
57
+ }
58
+ }
59
+
60
+ // ============================================================
61
+ // HOW TO CREATE A MIGRATION
62
+ // ============================================================
63
+ //
64
+ // 1. Add your entity to AppDbContext:
65
+ //
66
+ // public DbSet<{{pascalCase FEATURE_NAME}}> {{pascalCase FEATURE_NAME}}s => Set<{{pascalCase FEATURE_NAME}}>();
67
+ //
68
+ // 2. Add your configuration:
69
+ //
70
+ // protected override void OnModelCreating(ModelBuilder modelBuilder)
71
+ // {
72
+ // modelBuilder.ApplyConfiguration(new {{pascalCase FEATURE_NAME}}Configuration());
73
+ // }
74
+ //
75
+ // 3. Run migration command:
76
+ //
77
+ // dotnet ef migrations add Add{{pascalCase FEATURE_NAME}} -p src/{{NAMESPACE}}.Infrastructure -s src/{{NAMESPACE}}.Web
78
+ //
79
+ // 4. Apply migration:
80
+ //
81
+ // dotnet ef database update -p src/{{NAMESPACE}}.Infrastructure -s src/{{NAMESPACE}}.Web
82
+ //
83
+ // ============================================================
@@ -1,21 +1,21 @@
1
- using {{pascalCase PROJECT_NAME}}.Abstractions;
2
- using {{pascalCase PROJECT_NAME}}.Constants;
3
- using {{pascalCase PROJECT_NAME}}.Extensions;
4
- namespace {{pascalCase PROJECT_NAME}}.Features.{{pascalCase FEATURE_NAME}}Feature.{{pascalCase SLICE_NAME}};
5
-
6
- internal sealed class {{pascalCase SLICE_NAME}}Endpoint : IApiEndpoint
7
- {
8
- public void MapEndpoint(IEndpointRouteBuilder app)
9
- {
10
- app.MapPost("{{kebabCase FEATURE_NAME}}s", async (IHandler<{{pascalCase SLICE_NAME}}Request, Result<{{pascalCase SLICE_NAME}}Response>> handler, {{pascalCase SLICE_NAME}}Request command, CancellationToken cancellationToken) =>
11
- {
12
- var result = await handler.HandleAsync(command, cancellationToken);
13
- return result.Match(
14
- onSuccess: () => Results.Ok(result.Value),
15
- onFailure: error => Results.BadRequest(error));
16
- })
17
- .WithTags(ApiTags.{{pascalCase FEATURE_NAME}}s)
18
- .Produces<{{pascalCase SLICE_NAME}}Response>(StatusCodes.Status200OK)
19
- .Produces(StatusCodes.Status400BadRequest);
20
- }
21
- }
1
+ using {{pascalCase PROJECT_NAME}}.Abstractions;
2
+ using {{pascalCase PROJECT_NAME}}.Constants;
3
+ using {{pascalCase PROJECT_NAME}}.Extensions;
4
+ namespace {{pascalCase PROJECT_NAME}}.Features.{{pascalCase FEATURE_NAME}}Feature.{{pascalCase SLICE_NAME}};
5
+
6
+ internal sealed class {{pascalCase SLICE_NAME}}Endpoint : IApiEndpoint
7
+ {
8
+ public void MapEndpoint(IEndpointRouteBuilder app)
9
+ {
10
+ app.MapPost("{{kebabCase FEATURE_NAME}}s", async (IHandler<{{pascalCase SLICE_NAME}}Request, Result<{{pascalCase SLICE_NAME}}Response>> handler, {{pascalCase SLICE_NAME}}Request command, CancellationToken cancellationToken) =>
11
+ {
12
+ var result = await handler.HandleAsync(command, cancellationToken);
13
+ return result.Match(
14
+ onSuccess: () => Results.Ok(result.Value),
15
+ onFailure: error => Results.BadRequest(error));
16
+ })
17
+ .WithTags(ApiTags.{{pascalCase FEATURE_NAME}}s)
18
+ .Produces<{{pascalCase SLICE_NAME}}Response>(StatusCodes.Status200OK)
19
+ .Produces(StatusCodes.Status400BadRequest);
20
+ }
21
+ }
@@ -1,4 +1,4 @@
1
- namespace {{pascalCase PROJECT_NAME}}.Features.{{pascalCase FEATURE_NAME}}Feature.{{pascalCase SLICE_NAME}};
2
-
3
- // TODO: Add properties matching the {{pascalCase SLICE_NAME}} command
4
- public sealed record {{pascalCase SLICE_NAME}}Request();
1
+ namespace {{pascalCase PROJECT_NAME}}.Features.{{pascalCase FEATURE_NAME}}Feature.{{pascalCase SLICE_NAME}};
2
+
3
+ // TODO: Add properties matching the {{pascalCase SLICE_NAME}} command
4
+ public sealed record {{pascalCase SLICE_NAME}}Request();
@@ -1,4 +1,4 @@
1
- namespace {{pascalCase PROJECT_NAME}}.Features.{{pascalCase FEATURE_NAME}}Feature.{{pascalCase SLICE_NAME}};
2
-
3
- // TODO: Add properties matching the {{pascalCase SLICE_NAME}} response
4
- public sealed record {{pascalCase SLICE_NAME}}Response(Guid Id);
1
+ namespace {{pascalCase PROJECT_NAME}}.Features.{{pascalCase FEATURE_NAME}}Feature.{{pascalCase SLICE_NAME}};
2
+
3
+ // TODO: Add properties matching the {{pascalCase SLICE_NAME}} response
4
+ public sealed record {{pascalCase SLICE_NAME}}Response(Guid Id);
@@ -1,15 +1,15 @@
1
- using FluentValidation;
2
-
3
- namespace {{pascalCase PROJECT_NAME}}.Features.{{pascalCase FEATURE_NAME}}Feature.{{pascalCase SLICE_NAME}};
4
-
5
- public class {{pascalCase SLICE_NAME}}Validator : AbstractValidator<{{pascalCase SLICE_NAME}}Request>
6
- {
7
- public {{pascalCase SLICE_NAME}}Validator()
8
- {
9
- // TODO: Add validation rules for {{pascalCase SLICE_NAME}}Request properties
10
- // Example:
11
- // RuleFor(c => c.Name)
12
- // .NotEmpty().WithMessage("Name is required")
13
- // .MaximumLength(200).WithMessage("Name must not exceed 200 characters");
14
- }
15
- }
1
+ using FluentValidation;
2
+
3
+ namespace {{pascalCase PROJECT_NAME}}.Features.{{pascalCase FEATURE_NAME}}Feature.{{pascalCase SLICE_NAME}};
4
+
5
+ public class {{pascalCase SLICE_NAME}}Validator : AbstractValidator<{{pascalCase SLICE_NAME}}Request>
6
+ {
7
+ public {{pascalCase SLICE_NAME}}Validator()
8
+ {
9
+ // TODO: Add validation rules for {{pascalCase SLICE_NAME}}Request properties
10
+ // Example:
11
+ // RuleFor(c => c.Name)
12
+ // .NotEmpty().WithMessage("Name is required")
13
+ // .MaximumLength(200).WithMessage("Name must not exceed 200 characters");
14
+ }
15
+ }
@@ -1,58 +1,58 @@
1
- -- TEMPLATE: agent-prompts-migration.sql
2
- -- PURPOSE: Creates the agent_prompts table for runtime-editable, versioned agent instructions.
3
- -- READS STANDARD: ai-agents-prompts-in-db
4
- -- PLACEHOLDERS:
5
- -- {{SCHEMA}} — target schema (default: public)
6
- -- LAST-VERIFIED: 2026-05-19
7
-
8
- -- ============================================================
9
- -- 1. TABLE
10
- -- ============================================================
11
-
12
- CREATE TABLE {{SCHEMA}}.agent_prompts (
13
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
14
- agent_key text NOT NULL,
15
- version int NOT NULL,
16
- content text NOT NULL,
17
- is_active boolean NOT NULL DEFAULT false,
18
- created_at timestamptz NOT NULL DEFAULT now()
19
- );
20
-
21
- COMMENT ON TABLE {{SCHEMA}}.agent_prompts IS 'Runtime-editable, versioned system prompts for AI agents.';
22
- COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.agent_key IS 'Logical identifier for the agent (e.g. ''proposal-agent'').';
23
- COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.version IS 'Monotonically increasing per agent_key. Never reuse a version number.';
24
- COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.content IS 'Immutable system-prompt text. UPDATE of this column is forbidden — insert a new row instead.';
25
- COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.is_active IS 'Exactly one row per agent_key may have is_active = true (enforced by ix_agent_prompts_active).';
26
- COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.created_at IS 'Audit timestamp. Set at insert time, never updated.';
27
-
28
- -- ============================================================
29
- -- 2. INDEXES
30
- -- ============================================================
31
-
32
- -- Unique partial index: enforces at DB level that only one active prompt
33
- -- exists per agent_key. Any attempt to INSERT a second active row for the
34
- -- same key will fail with a unique-constraint violation.
35
- CREATE UNIQUE INDEX ix_agent_prompts_active
36
- ON {{SCHEMA}}.agent_prompts (agent_key)
37
- WHERE is_active;
38
-
39
- -- Regular index for the PromptRepository lookup (agent_key + is_active filter).
40
- CREATE INDEX ix_agent_prompts_agent_key
41
- ON {{SCHEMA}}.agent_prompts (agent_key);
42
-
43
- -- Unique index: prevents duplicate version numbers per agent_key.
44
- CREATE UNIQUE INDEX ix_agent_prompts_agent_key_version
45
- ON {{SCHEMA}}.agent_prompts (agent_key, version);
46
-
47
- -- ============================================================
48
- -- 3. SEED (optional — remove if managed via backoffice)
49
- -- ============================================================
50
-
51
- -- INSERT INTO {{SCHEMA}}.agent_prompts (agent_key, version, content, is_active)
52
- -- VALUES ('my-agent', 1, 'You are a helpful assistant.', true);
53
-
54
- -- ============================================================
55
- -- ROLLBACK
56
- -- ============================================================
57
-
58
- -- DROP TABLE IF EXISTS {{SCHEMA}}.agent_prompts CASCADE;
1
+ -- TEMPLATE: agent-prompts-migration.sql
2
+ -- PURPOSE: Creates the agent_prompts table for runtime-editable, versioned agent instructions.
3
+ -- READS STANDARD: ai-agents-prompts-in-db
4
+ -- PLACEHOLDERS:
5
+ -- {{SCHEMA}} — target schema (default: public)
6
+ -- LAST-VERIFIED: 2026-05-19
7
+
8
+ -- ============================================================
9
+ -- 1. TABLE
10
+ -- ============================================================
11
+
12
+ CREATE TABLE {{SCHEMA}}.agent_prompts (
13
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
14
+ agent_key text NOT NULL,
15
+ version int NOT NULL,
16
+ content text NOT NULL,
17
+ is_active boolean NOT NULL DEFAULT false,
18
+ created_at timestamptz NOT NULL DEFAULT now()
19
+ );
20
+
21
+ COMMENT ON TABLE {{SCHEMA}}.agent_prompts IS 'Runtime-editable, versioned system prompts for AI agents.';
22
+ COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.agent_key IS 'Logical identifier for the agent (e.g. ''proposal-agent'').';
23
+ COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.version IS 'Monotonically increasing per agent_key. Never reuse a version number.';
24
+ COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.content IS 'Immutable system-prompt text. UPDATE of this column is forbidden — insert a new row instead.';
25
+ COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.is_active IS 'Exactly one row per agent_key may have is_active = true (enforced by ix_agent_prompts_active).';
26
+ COMMENT ON COLUMN {{SCHEMA}}.agent_prompts.created_at IS 'Audit timestamp. Set at insert time, never updated.';
27
+
28
+ -- ============================================================
29
+ -- 2. INDEXES
30
+ -- ============================================================
31
+
32
+ -- Unique partial index: enforces at DB level that only one active prompt
33
+ -- exists per agent_key. Any attempt to INSERT a second active row for the
34
+ -- same key will fail with a unique-constraint violation.
35
+ CREATE UNIQUE INDEX ix_agent_prompts_active
36
+ ON {{SCHEMA}}.agent_prompts (agent_key)
37
+ WHERE is_active;
38
+
39
+ -- Regular index for the PromptRepository lookup (agent_key + is_active filter).
40
+ CREATE INDEX ix_agent_prompts_agent_key
41
+ ON {{SCHEMA}}.agent_prompts (agent_key);
42
+
43
+ -- Unique index: prevents duplicate version numbers per agent_key.
44
+ CREATE UNIQUE INDEX ix_agent_prompts_agent_key_version
45
+ ON {{SCHEMA}}.agent_prompts (agent_key, version);
46
+
47
+ -- ============================================================
48
+ -- 3. SEED (optional — remove if managed via backoffice)
49
+ -- ============================================================
50
+
51
+ -- INSERT INTO {{SCHEMA}}.agent_prompts (agent_key, version, content, is_active)
52
+ -- VALUES ('my-agent', 1, 'You are a helpful assistant.', true);
53
+
54
+ -- ============================================================
55
+ -- ROLLBACK
56
+ -- ============================================================
57
+
58
+ -- DROP TABLE IF EXISTS {{SCHEMA}}.agent_prompts CASCADE;
@@ -1,91 +1,91 @@
1
- -- TEMPLATE: pgvector-embeddings-migration.sql
2
- -- PURPOSE: Creates the kb_embeddings table for custom RAG — chunk storage with pgvector.
3
- -- READS STANDARD: ai-agents-rag-custom-pgvector
4
- -- PLACEHOLDERS:
5
- -- {{SCHEMA}} — target schema (default: public)
6
- -- LAST-VERIFIED: 2026-05-19
7
- --
8
- -- PREREQUISITES:
9
- -- - pgvector extension enabled in Neon (see infrastructure-neon-pgvector).
10
- -- - NpgsqlDataSourceBuilder.UseVector() called in the project's DB setup.
11
- --
12
- -- DIMENSION NOTE:
13
- -- embedding vector(1536) matches text-embedding-3-small (default 1536 dimensions).
14
- -- If the project uses a different embedding model, adjust the dimension to match.
15
- -- NEVER mix embedding models on a single column — vectors live in different spaces.
16
-
17
- -- ============================================================
18
- -- 1. EXTENSION
19
- -- ============================================================
20
-
21
- CREATE EXTENSION IF NOT EXISTS vector;
22
-
23
- -- ============================================================
24
- -- 2. TABLE
25
- -- ============================================================
26
-
27
- CREATE TABLE {{SCHEMA}}.kb_embeddings (
28
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
29
- tenant_id uuid NOT NULL,
30
- source text NOT NULL, -- document identifier or source URL
31
- chunk_index int NOT NULL, -- position of this chunk within the source document
32
- content text NOT NULL, -- chunk text returned to the agent as context
33
- embedding vector(1536) NOT NULL, -- vector dimension must match embedding model
34
- metadata jsonb NOT NULL DEFAULT '{}',
35
- created_at timestamptz NOT NULL DEFAULT now()
36
- );
37
-
38
- COMMENT ON TABLE {{SCHEMA}}.kb_embeddings IS 'RAG knowledge base — chunk text and pgvector embeddings for semantic search.';
39
- COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.tenant_id IS 'Tenant partition. Every query MUST filter on this column. Never query across tenants.';
40
- COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.source IS 'Document identifier or URL. Used for citation and re-indexing detection.';
41
- COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.chunk_index IS 'Zero-based position of this chunk within the source document.';
42
- COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.content IS 'Chunk text returned to the agent. Plain text, no markup.';
43
- COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.embedding IS 'Float vector. Dimension MUST match the embedding model declared in model-registry.json.';
44
- COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.metadata IS 'Arbitrary JSON metadata (section headers, page numbers, doc type, etc.). Used for filtering.';
45
-
46
- -- ============================================================
47
- -- 3. INDEXES
48
- -- ============================================================
49
-
50
- -- HNSW index for cosine similarity — production-grade recall, no training data required.
51
- -- vector_cosine_ops: use <=> operator (cosine distance, ascending = most similar first).
52
- -- m=16, ef_construction=64 are pgvector defaults. Tune per infrastructure-neon-pgvector §HNSW Parameters.
53
- CREATE INDEX ix_kb_embeddings_hnsw
54
- ON {{SCHEMA}}.kb_embeddings
55
- USING hnsw (embedding vector_cosine_ops)
56
- WITH (m = 16, ef_construction = 64);
57
-
58
- -- Index for the mandatory tenant_id filter (applied in every search query).
59
- CREATE INDEX ix_kb_embeddings_tenant
60
- ON {{SCHEMA}}.kb_embeddings (tenant_id);
61
-
62
- -- Composite index for source-level operations (re-indexing, deletion by document).
63
- CREATE INDEX ix_kb_embeddings_source
64
- ON {{SCHEMA}}.kb_embeddings (tenant_id, source);
65
-
66
- -- ============================================================
67
- -- 4. ROW-LEVEL SECURITY (multi-tenant)
68
- -- ============================================================
69
-
70
- -- RLS enforces tenant isolation at the database level as a second line of defence.
71
- -- The application already filters on tenant_id in every query; RLS is the backstop.
72
- --
73
- -- See templates/code/sql/postgresql-rls-policy.sql for the policy pattern that
74
- -- binds app.current_tenant_id (a session-level setting) to the RLS policy.
75
- --
76
- -- Uncomment and adapt once RLS is wired in the project:
77
- --
78
- -- ALTER TABLE {{SCHEMA}}.kb_embeddings ENABLE ROW LEVEL SECURITY;
79
- --
80
- -- CREATE POLICY kb_embeddings_tenant_isolation
81
- -- ON {{SCHEMA}}.kb_embeddings
82
- -- USING (tenant_id = current_setting('app.current_tenant_id')::uuid);
83
-
84
- -- ============================================================
85
- -- ROLLBACK
86
- -- ============================================================
87
-
88
- -- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_hnsw;
89
- -- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_tenant;
90
- -- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_source;
91
- -- DROP TABLE IF EXISTS {{SCHEMA}}.kb_embeddings CASCADE;
1
+ -- TEMPLATE: pgvector-embeddings-migration.sql
2
+ -- PURPOSE: Creates the kb_embeddings table for custom RAG — chunk storage with pgvector.
3
+ -- READS STANDARD: ai-agents-rag-custom-pgvector
4
+ -- PLACEHOLDERS:
5
+ -- {{SCHEMA}} — target schema (default: public)
6
+ -- LAST-VERIFIED: 2026-05-19
7
+ --
8
+ -- PREREQUISITES:
9
+ -- - pgvector extension enabled in Neon (see infrastructure-neon-pgvector).
10
+ -- - NpgsqlDataSourceBuilder.UseVector() called in the project's DB setup.
11
+ --
12
+ -- DIMENSION NOTE:
13
+ -- embedding vector(1536) matches text-embedding-3-small (default 1536 dimensions).
14
+ -- If the project uses a different embedding model, adjust the dimension to match.
15
+ -- NEVER mix embedding models on a single column — vectors live in different spaces.
16
+
17
+ -- ============================================================
18
+ -- 1. EXTENSION
19
+ -- ============================================================
20
+
21
+ CREATE EXTENSION IF NOT EXISTS vector;
22
+
23
+ -- ============================================================
24
+ -- 2. TABLE
25
+ -- ============================================================
26
+
27
+ CREATE TABLE {{SCHEMA}}.kb_embeddings (
28
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
29
+ tenant_id uuid NOT NULL,
30
+ source text NOT NULL, -- document identifier or source URL
31
+ chunk_index int NOT NULL, -- position of this chunk within the source document
32
+ content text NOT NULL, -- chunk text returned to the agent as context
33
+ embedding vector(1536) NOT NULL, -- vector dimension must match embedding model
34
+ metadata jsonb NOT NULL DEFAULT '{}',
35
+ created_at timestamptz NOT NULL DEFAULT now()
36
+ );
37
+
38
+ COMMENT ON TABLE {{SCHEMA}}.kb_embeddings IS 'RAG knowledge base — chunk text and pgvector embeddings for semantic search.';
39
+ COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.tenant_id IS 'Tenant partition. Every query MUST filter on this column. Never query across tenants.';
40
+ COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.source IS 'Document identifier or URL. Used for citation and re-indexing detection.';
41
+ COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.chunk_index IS 'Zero-based position of this chunk within the source document.';
42
+ COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.content IS 'Chunk text returned to the agent. Plain text, no markup.';
43
+ COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.embedding IS 'Float vector. Dimension MUST match the embedding model declared in model-registry.json.';
44
+ COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.metadata IS 'Arbitrary JSON metadata (section headers, page numbers, doc type, etc.). Used for filtering.';
45
+
46
+ -- ============================================================
47
+ -- 3. INDEXES
48
+ -- ============================================================
49
+
50
+ -- HNSW index for cosine similarity — production-grade recall, no training data required.
51
+ -- vector_cosine_ops: use <=> operator (cosine distance, ascending = most similar first).
52
+ -- m=16, ef_construction=64 are pgvector defaults. Tune per infrastructure-neon-pgvector §HNSW Parameters.
53
+ CREATE INDEX ix_kb_embeddings_hnsw
54
+ ON {{SCHEMA}}.kb_embeddings
55
+ USING hnsw (embedding vector_cosine_ops)
56
+ WITH (m = 16, ef_construction = 64);
57
+
58
+ -- Index for the mandatory tenant_id filter (applied in every search query).
59
+ CREATE INDEX ix_kb_embeddings_tenant
60
+ ON {{SCHEMA}}.kb_embeddings (tenant_id);
61
+
62
+ -- Composite index for source-level operations (re-indexing, deletion by document).
63
+ CREATE INDEX ix_kb_embeddings_source
64
+ ON {{SCHEMA}}.kb_embeddings (tenant_id, source);
65
+
66
+ -- ============================================================
67
+ -- 4. ROW-LEVEL SECURITY (multi-tenant)
68
+ -- ============================================================
69
+
70
+ -- RLS enforces tenant isolation at the database level as a second line of defence.
71
+ -- The application already filters on tenant_id in every query; RLS is the backstop.
72
+ --
73
+ -- See templates/code/sql/postgresql-rls-policy.sql for the policy pattern that
74
+ -- binds app.current_tenant_id (a session-level setting) to the RLS policy.
75
+ --
76
+ -- Uncomment and adapt once RLS is wired in the project:
77
+ --
78
+ -- ALTER TABLE {{SCHEMA}}.kb_embeddings ENABLE ROW LEVEL SECURITY;
79
+ --
80
+ -- CREATE POLICY kb_embeddings_tenant_isolation
81
+ -- ON {{SCHEMA}}.kb_embeddings
82
+ -- USING (tenant_id = current_setting('app.current_tenant_id')::uuid);
83
+
84
+ -- ============================================================
85
+ -- ROLLBACK
86
+ -- ============================================================
87
+
88
+ -- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_hnsw;
89
+ -- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_tenant;
90
+ -- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_source;
91
+ -- DROP TABLE IF EXISTS {{SCHEMA}}.kb_embeddings CASCADE;