@polymorphism-tech/morph-spec 7.0.0 → 7.1.1

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 (89) hide show
  1. package/README.md +368 -368
  2. package/claude-plugin.json +14 -14
  3. package/docs/CHEATSHEET.md +199 -199
  4. package/docs/QUICKSTART.md +200 -200
  5. package/framework/CLAUDE.md +1 -1
  6. package/framework/MORPH.md +4 -1
  7. package/framework/agents.json +132 -127
  8. package/framework/rubrics/backend.json +41 -36
  9. package/framework/rules/ai-agents-standards.md +45 -15
  10. package/framework/rules/neon-standards.md +25 -26
  11. package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
  12. package/framework/skills/core/morph-plan/SKILL.md +3 -1
  13. package/framework/skills/core/morph-stack-scan/SKILL.md +3 -3
  14. package/framework/standards/STANDARDS.json +1729 -1133
  15. package/framework/standards/ai-agents/agent-session.md +160 -0
  16. package/framework/standards/ai-agents/batching.md +193 -0
  17. package/framework/standards/ai-agents/context-providers.md +188 -0
  18. package/framework/standards/ai-agents/mcp-server.md +250 -0
  19. package/framework/standards/ai-agents/mcp-tools.md +197 -0
  20. package/framework/standards/ai-agents/middleware-patterns.md +207 -0
  21. package/framework/standards/ai-agents/modalities-image-gen.md +173 -0
  22. package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -0
  23. package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -0
  24. package/framework/standards/ai-agents/modalities-vision.md +201 -0
  25. package/framework/standards/ai-agents/multi-agent-patterns.md +155 -0
  26. package/framework/standards/ai-agents/production.md +114 -258
  27. package/framework/standards/ai-agents/prompts-in-db.md +214 -0
  28. package/framework/standards/ai-agents/providers/model-registry.md +158 -0
  29. package/framework/standards/ai-agents/rag-custom-pgvector.md +243 -0
  30. package/framework/standards/ai-agents/service-tier-flex.md +135 -0
  31. package/framework/standards/ai-agents/setup.md +142 -316
  32. package/framework/standards/ai-agents/structured-output.md +249 -0
  33. package/framework/standards/ai-agents/sweet-spot.md +109 -0
  34. package/framework/standards/ai-agents/workflows.md +114 -284
  35. package/framework/standards/architecture/vertical-slice/vertical-slice.md +439 -429
  36. package/framework/standards/backend/api/validation.md +92 -88
  37. package/framework/standards/backend/database/postgresql/database.md +336 -332
  38. package/framework/standards/backend/database/vector-search-rag.md +599 -541
  39. package/framework/standards/backend/dotnet/fluent-validation-vsa.md +4 -0
  40. package/framework/standards/backend/dotnet/result-pattern.md +4 -0
  41. package/framework/standards/backend/dotnet/scalar-ui.md +176 -172
  42. package/framework/standards/backend/dotnet/scrutor.md +4 -0
  43. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +310 -274
  44. package/framework/standards/backend/integrations/asaas/asaas-api.md +260 -216
  45. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +354 -350
  46. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +30 -19
  47. package/framework/standards/backend/integrations/resend/resend-email.md +400 -385
  48. package/framework/standards/data/nosql/cache/redis.md +106 -97
  49. package/framework/standards/data/nosql/cosmos-db.md +127 -118
  50. package/framework/standards/data/vector-search/rag-chunking.md +113 -104
  51. package/framework/standards/frontend/design-system/ai-image-generation.md +4 -0
  52. package/framework/standards/frontend/design-system/animations.md +164 -160
  53. package/framework/standards/frontend/design-system/naming.md +68 -64
  54. package/framework/standards/frontend/gsap/gsap-core.md +14 -8
  55. package/framework/standards/frontend/gsap/gsap-plugins.md +26 -21
  56. package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +9 -7
  57. package/framework/standards/frontend/nextjs/app-router.md +127 -123
  58. package/framework/standards/frontend/nextjs/components.md +136 -132
  59. package/framework/standards/frontend/nextjs/data-fetching.md +130 -126
  60. package/framework/standards/frontend/nextjs/forms.md +134 -128
  61. package/framework/standards/frontend/nextjs/motion-patterns.md +328 -322
  62. package/framework/standards/frontend/nextjs/naming-conventions.md +71 -67
  63. package/framework/standards/frontend/nextjs/nextjs-patterns.md +229 -225
  64. package/framework/standards/frontend/nextjs/project-structure.md +106 -102
  65. package/framework/standards/frontend/nextjs/state-management.md +76 -72
  66. package/framework/standards/frontend/nextjs/testing.md +115 -111
  67. package/framework/standards/infrastructure/docker/easypanel-deploy.md +196 -192
  68. package/framework/standards/infrastructure/neon/neon-pgrag.md +6 -2
  69. package/framework/standards/infrastructure/neon/neon-pgvector.md +4 -0
  70. package/framework/standards/infrastructure/neon/neon-setup.md +5 -1
  71. package/framework/standards/integration/mcp/mcp-tools.md +471 -462
  72. package/framework/templates/CLAUDE.md.core.template +1 -1
  73. package/framework/templates/REGISTRY.json +1745 -1239
  74. package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -0
  75. package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -0
  76. package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -0
  77. package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -0
  78. package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -0
  79. package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -0
  80. package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -0
  81. package/framework/templates/code/dotnet/backend/repository.cs +3 -10
  82. package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -0
  83. package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -0
  84. package/package.json +89 -83
  85. package/src/core/templates/template-registry.js +289 -256
  86. package/src/lib/generators/context-generator.js +516 -518
  87. package/src/lib/generators/scaffold-generator.js +23 -26
  88. package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +0 -310
  89. package/framework/templates/integrations/semantic-kernel-neon.cs +0 -125
@@ -1,97 +1,106 @@
1
- # Data Standard: Redis Cache (Azure Cache for Redis)
2
-
3
- ## Overview
4
- Distributed cache for session data, rate limiting, and frequently-read data.
5
-
6
- ## Setup
7
- ```xml
8
- <PackageReference Include="StackExchange.Redis" Version="2.*" />
9
- <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.*" />
10
- ```
11
-
12
- ```csharp
13
- // Program.cs
14
- builder.Services.AddStackExchangeRedisCache(opts =>
15
- {
16
- opts.Configuration = config["Redis:ConnectionString"]; // from Key Vault
17
- opts.InstanceName = "myapp:"; // Prefix to avoid key collisions
18
- });
19
- ```
20
-
21
- ## Cache-Aside Pattern
22
- ```csharp
23
- public class CachedProductService : IProductService
24
- {
25
- private readonly IDistributedCache _cache;
26
- private readonly IProductRepository _repository;
27
-
28
- public async Task<Product?> GetAsync(Guid id, CancellationToken ct = default)
29
- {
30
- var cacheKey = $"product:{id}";
31
-
32
- // Try cache first
33
- var cached = await _cache.GetStringAsync(cacheKey, ct);
34
- if (cached != null)
35
- return JsonSerializer.Deserialize<Product>(cached);
36
-
37
- // Cache miss → read from DB
38
- var product = await _repository.GetAsync(id, ct);
39
- if (product == null) return null;
40
-
41
- // Cache with TTL
42
- await _cache.SetStringAsync(cacheKey,
43
- JsonSerializer.Serialize(product),
44
- new DistributedCacheEntryOptions
45
- {
46
- AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15),
47
- SlidingExpiration = TimeSpan.FromMinutes(5)
48
- }, ct);
49
-
50
- return product;
51
- }
52
-
53
- public async Task InvalidateAsync(Guid id, CancellationToken ct = default)
54
- => await _cache.RemoveAsync($"product:{id}", ct);
55
- }
56
- ```
57
-
58
- ## TTL Strategy
59
- | Data Type | TTL | Rationale |
60
- |-----------|-----|-----------|
61
- | User session | 30 min sliding | Active session window |
62
- | Product catalog | 15 min absolute | Inventory changes |
63
- | Rate limit counters | 1 min | Per-minute limiting |
64
- | Computed aggregates | 1 hour | Expensive query results |
65
- | Reference data | 24 hours | Config rarely changes |
66
-
67
- ## Key Naming Convention
68
- ```
69
- {service}:{entity}:{id}
70
- {service}:{entity}:list:{filter}
71
- {service}:ratelimit:{userId}:{endpoint}
72
-
73
- Examples:
74
- product:detail:550e8400-e29b-41d4-a716
75
- product:list:category:electronics
76
- auth:ratelimit:user123:login
77
- ```
78
-
79
- ## Rate Limiting Pattern
80
- ```csharp
81
- public async Task<bool> IsRateLimitedAsync(string userId, string action, int maxPerMinute)
82
- {
83
- var key = $"ratelimit:{action}:{userId}:{DateTime.UtcNow:yyyyMMddHHmm}";
84
- var db = _redis.GetDatabase();
85
-
86
- var count = await db.StringIncrementAsync(key);
87
- if (count == 1) await db.KeyExpireAsync(key, TimeSpan.FromMinutes(1));
88
-
89
- return count > maxPerMinute;
90
- }
91
- ```
92
-
93
- ## Anti-Patterns
94
- - Never cache sensitive data (passwords, tokens, PII) without encryption
95
- - Never use Redis as primary store — it's a cache, not a database
96
- - Never omit TTL — unbounded keys fill memory
97
- - Never catch RedisException silently — degrade gracefully to DB
1
+ # Data Standard: Redis Cache (Azure Cache for Redis)
2
+
3
+ > **Scope:** data-nosql-cache
4
+ > **Layer:** 2
5
+ > **Keywords:** redis, cache, distributed-cache, session, rate-limiting, stackexchange-redis, azure-cache
6
+ > **Load When:** caching, session storage, or rate limiting is in scope
7
+
8
+ **Verified against:** .NET 10 + StackExchange.Redis 2.x + Microsoft.Extensions.Caching.StackExchangeRedis. Last-verified: 2026-05-20.
9
+
10
+ ---
11
+
12
+ ## Overview
13
+ Distributed cache for session data, rate limiting, and frequently-read data.
14
+
15
+ ## Setup
16
+ ```xml
17
+ <PackageReference Include="StackExchange.Redis" Version="2.*" />
18
+ <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.*" />
19
+ ```
20
+
21
+ ```csharp
22
+ // Program.cs
23
+ builder.Services.AddStackExchangeRedisCache(opts =>
24
+ {
25
+ opts.Configuration = config["Redis:ConnectionString"]; // from Key Vault
26
+ opts.InstanceName = "myapp:"; // Prefix to avoid key collisions
27
+ });
28
+ ```
29
+
30
+ ## Cache-Aside Pattern
31
+ ```csharp
32
+ public class CachedProductService : IProductService
33
+ {
34
+ private readonly IDistributedCache _cache;
35
+ private readonly IProductRepository _repository;
36
+
37
+ public async Task<Product?> GetAsync(Guid id, CancellationToken ct = default)
38
+ {
39
+ var cacheKey = $"product:{id}";
40
+
41
+ // Try cache first
42
+ var cached = await _cache.GetStringAsync(cacheKey, ct);
43
+ if (cached != null)
44
+ return JsonSerializer.Deserialize<Product>(cached);
45
+
46
+ // Cache miss → read from DB
47
+ var product = await _repository.GetAsync(id, ct);
48
+ if (product == null) return null;
49
+
50
+ // Cache with TTL
51
+ await _cache.SetStringAsync(cacheKey,
52
+ JsonSerializer.Serialize(product),
53
+ new DistributedCacheEntryOptions
54
+ {
55
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15),
56
+ SlidingExpiration = TimeSpan.FromMinutes(5)
57
+ }, ct);
58
+
59
+ return product;
60
+ }
61
+
62
+ public async Task InvalidateAsync(Guid id, CancellationToken ct = default)
63
+ => await _cache.RemoveAsync($"product:{id}", ct);
64
+ }
65
+ ```
66
+
67
+ ## TTL Strategy
68
+ | Data Type | TTL | Rationale |
69
+ |-----------|-----|-----------|
70
+ | User session | 30 min sliding | Active session window |
71
+ | Product catalog | 15 min absolute | Inventory changes |
72
+ | Rate limit counters | 1 min | Per-minute limiting |
73
+ | Computed aggregates | 1 hour | Expensive query results |
74
+ | Reference data | 24 hours | Config rarely changes |
75
+
76
+ ## Key Naming Convention
77
+ ```
78
+ {service}:{entity}:{id}
79
+ {service}:{entity}:list:{filter}
80
+ {service}:ratelimit:{userId}:{endpoint}
81
+
82
+ Examples:
83
+ product:detail:550e8400-e29b-41d4-a716
84
+ product:list:category:electronics
85
+ auth:ratelimit:user123:login
86
+ ```
87
+
88
+ ## Rate Limiting Pattern
89
+ ```csharp
90
+ public async Task<bool> IsRateLimitedAsync(string userId, string action, int maxPerMinute)
91
+ {
92
+ var key = $"ratelimit:{action}:{userId}:{DateTime.UtcNow:yyyyMMddHHmm}";
93
+ var db = _redis.GetDatabase();
94
+
95
+ var count = await db.StringIncrementAsync(key);
96
+ if (count == 1) await db.KeyExpireAsync(key, TimeSpan.FromMinutes(1));
97
+
98
+ return count > maxPerMinute;
99
+ }
100
+ ```
101
+
102
+ ## Anti-Patterns
103
+ - Never cache sensitive data (passwords, tokens, PII) without encryption
104
+ - Never use Redis as primary store — it's a cache, not a database
105
+ - Never omit TTL — unbounded keys fill memory
106
+ - Never catch RedisException silently — degrade gracefully to DB
@@ -1,118 +1,127 @@
1
- # Data Standard: Azure Cosmos DB
2
-
3
- ## Overview
4
- NoSQL document database — use for high-throughput, globally distributed, or schema-flexible data.
5
-
6
- ## When to Use Cosmos DB
7
- ✅ Event store (append-only, high write throughput)
8
- ✅ User activity/session data (variable schema)
9
- ✅ Multi-region writes required
10
- ✅ JSON documents with flexible schema
11
- ❌ Relational data with complex joins (use Azure SQL)
12
- ❌ Small datasets (cost inefficient)
13
-
14
- ## Container Design
15
- ```json
16
- {
17
- "partitionKey": "/tenantId",
18
- "indexingPolicy": {
19
- "includedPaths": [{ "path": "/*" }],
20
- "excludedPaths": [
21
- { "path": "/largePayload/*" },
22
- { "path": "/_etag/?" }
23
- ]
24
- }
25
- }
26
- ```
27
-
28
- ### Partition Key Strategy
29
- - High cardinality: userId, tenantId, orderId
30
- - Even distribution: avoid hot partitions (e.g., /status = "active" for 90% of docs)
31
- - Query alignment: partition key should appear in most queries
32
-
33
- ## SDK Setup
34
- ```csharp
35
- // Program.cs
36
- builder.Services.AddSingleton(sp =>
37
- new CosmosClient(
38
- config["CosmosDb:ConnectionString"],
39
- new CosmosClientOptions
40
- {
41
- SerializerOptions = new CosmosSerializationOptions
42
- {
43
- PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
44
- },
45
- ApplicationName = "MyApp"
46
- }));
47
-
48
- builder.Services.AddSingleton<ICosmosRepository<Order>>(sp =>
49
- new CosmosRepository<Order>(
50
- sp.GetRequiredService<CosmosClient>(),
51
- config["CosmosDb:DatabaseId"],
52
- "orders"));
53
- ```
54
-
55
- ## Repository Pattern
56
- ```csharp
57
- public class CosmosRepository<T> where T : CosmosDocument
58
- {
59
- private readonly Container _container;
60
-
61
- public async Task<T?> GetAsync(string id, string partitionKey)
62
- {
63
- try
64
- {
65
- var response = await _container.ReadItemAsync<T>(id, new PartitionKey(partitionKey));
66
- return response.Resource;
67
- }
68
- catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
69
- {
70
- return null;
71
- }
72
- }
73
-
74
- public async Task<IReadOnlyList<T>> QueryAsync(string sql, Dictionary<string, object>? parameters = null)
75
- {
76
- var query = new QueryDefinition(sql);
77
- if (parameters != null)
78
- foreach (var (k, v) in parameters) query = query.WithParameter(k, v);
79
-
80
- var results = new List<T>();
81
- using var feed = _container.GetItemQueryIterator<T>(query);
82
- while (feed.HasMoreResults)
83
- {
84
- var page = await feed.ReadNextAsync();
85
- results.AddRange(page);
86
- }
87
- return results;
88
- }
89
-
90
- public async Task UpsertAsync(T document)
91
- => await _container.UpsertItemAsync(document, new PartitionKey(document.PartitionKey));
92
- }
93
- ```
94
-
95
- ## Document Base Class
96
- ```csharp
97
- public abstract class CosmosDocument
98
- {
99
- [JsonPropertyName("id")]
100
- public string Id { get; set; } = Guid.NewGuid().ToString();
101
-
102
- [JsonPropertyName("_partitionKey")]
103
- public abstract string PartitionKey { get; }
104
-
105
- [JsonPropertyName("type")]
106
- public string Type => GetType().Name;
107
-
108
- [JsonPropertyName("createdAt")]
109
- public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
110
- }
111
- ```
112
-
113
- ## Cost Optimization
114
- - Enable TTL on transient data (session, temp tokens)
115
- - Use serverless mode for dev/test environments
116
- - Index only queried paths (exclude large blobs)
117
- - Batch operations with TransactionalBatch for same partition
118
- - Use bulk execution for large imports
1
+ # Data Standard: Azure Cosmos DB
2
+
3
+ > **Scope:** data-nosql
4
+ > **Layer:** 2
5
+ > **Keywords:** cosmos-db, nosql, document-database, event-store, partition-key, azure-cosmos
6
+ > **Load When:** a NoSQL document store, event store, or globally distributed data is in scope
7
+
8
+ **Verified against:** .NET 10 + Microsoft.Azure.Cosmos SDK v3. Last-verified: 2026-05-20.
9
+
10
+ ---
11
+
12
+ ## Overview
13
+ NoSQL document database — use for high-throughput, globally distributed, or schema-flexible data.
14
+
15
+ ## When to Use Cosmos DB
16
+ ✅ Event store (append-only, high write throughput)
17
+ ✅ User activity/session data (variable schema)
18
+ ✅ Multi-region writes required
19
+ ✅ JSON documents with flexible schema
20
+ ❌ Relational data with complex joins (use Azure SQL)
21
+ ❌ Small datasets (cost inefficient)
22
+
23
+ ## Container Design
24
+ ```json
25
+ {
26
+ "partitionKey": "/tenantId",
27
+ "indexingPolicy": {
28
+ "includedPaths": [{ "path": "/*" }],
29
+ "excludedPaths": [
30
+ { "path": "/largePayload/*" },
31
+ { "path": "/_etag/?" }
32
+ ]
33
+ }
34
+ }
35
+ ```
36
+
37
+ ### Partition Key Strategy
38
+ - High cardinality: userId, tenantId, orderId
39
+ - Even distribution: avoid hot partitions (e.g., /status = "active" for 90% of docs)
40
+ - Query alignment: partition key should appear in most queries
41
+
42
+ ## SDK Setup
43
+ ```csharp
44
+ // Program.cs
45
+ builder.Services.AddSingleton(sp =>
46
+ new CosmosClient(
47
+ config["CosmosDb:ConnectionString"],
48
+ new CosmosClientOptions
49
+ {
50
+ SerializerOptions = new CosmosSerializationOptions
51
+ {
52
+ PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
53
+ },
54
+ ApplicationName = "MyApp"
55
+ }));
56
+
57
+ builder.Services.AddSingleton<ICosmosRepository<Order>>(sp =>
58
+ new CosmosRepository<Order>(
59
+ sp.GetRequiredService<CosmosClient>(),
60
+ config["CosmosDb:DatabaseId"],
61
+ "orders"));
62
+ ```
63
+
64
+ ## Repository Pattern
65
+ ```csharp
66
+ public class CosmosRepository<T> where T : CosmosDocument
67
+ {
68
+ private readonly Container _container;
69
+
70
+ public async Task<T?> GetAsync(string id, string partitionKey)
71
+ {
72
+ try
73
+ {
74
+ var response = await _container.ReadItemAsync<T>(id, new PartitionKey(partitionKey));
75
+ return response.Resource;
76
+ }
77
+ catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
78
+ {
79
+ return null;
80
+ }
81
+ }
82
+
83
+ public async Task<IReadOnlyList<T>> QueryAsync(string sql, Dictionary<string, object>? parameters = null)
84
+ {
85
+ var query = new QueryDefinition(sql);
86
+ if (parameters != null)
87
+ foreach (var (k, v) in parameters) query = query.WithParameter(k, v);
88
+
89
+ var results = new List<T>();
90
+ using var feed = _container.GetItemQueryIterator<T>(query);
91
+ while (feed.HasMoreResults)
92
+ {
93
+ var page = await feed.ReadNextAsync();
94
+ results.AddRange(page);
95
+ }
96
+ return results;
97
+ }
98
+
99
+ public async Task UpsertAsync(T document)
100
+ => await _container.UpsertItemAsync(document, new PartitionKey(document.PartitionKey));
101
+ }
102
+ ```
103
+
104
+ ## Document Base Class
105
+ ```csharp
106
+ public abstract class CosmosDocument
107
+ {
108
+ [JsonPropertyName("id")]
109
+ public string Id { get; set; } = Guid.NewGuid().ToString();
110
+
111
+ [JsonPropertyName("_partitionKey")]
112
+ public abstract string PartitionKey { get; }
113
+
114
+ [JsonPropertyName("type")]
115
+ public string Type => GetType().Name;
116
+
117
+ [JsonPropertyName("createdAt")]
118
+ public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
119
+ }
120
+ ```
121
+
122
+ ## Cost Optimization
123
+ - Enable TTL on transient data (session, temp tokens)
124
+ - Use serverless mode for dev/test environments
125
+ - Index only queried paths (exclude large blobs)
126
+ - Batch operations with TransactionalBatch for same partition
127
+ - Use bulk execution for large imports