@polymorphism-tech/morph-spec 4.13.0 → 4.15.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.
- package/CLAUDE.md +7 -7
- package/README.md +9 -7
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +6 -7
- package/docs/QUICKSTART.md +1 -1
- package/framework/agents/ai-agents/ai-system-architect.md +2 -0
- package/framework/agents/ai-agents/vector-search-expert.md +233 -0
- package/framework/agents/architecture/seo-growth-hacker.md +2 -0
- package/framework/agents/architecture/standards-architect.md +3 -0
- package/framework/agents/backend/dotnet-senior.md +3 -0
- package/framework/agents/backend/ef-modeler.md +2 -0
- package/framework/agents/backend/hangfire-orchestrator.md +2 -0
- package/framework/agents/backend/ms-agent-expert.md +2 -0
- package/framework/agents/backend/supabase-expert.md +256 -0
- package/framework/agents/frontend/css-specialist.md +2 -0
- package/framework/agents/frontend/nextjs-expert.md +3 -0
- package/framework/agents/frontend/ui-ux-designer.md +3 -1
- package/framework/agents/infrastructure/infra-architect.md +3 -0
- package/framework/agents/integrations/asaas-financial.md +2 -0
- package/framework/agents/integrations/clerk-auth.md +2 -0
- package/framework/agents/integrations/resend-email.md +2 -0
- package/framework/agents.json +1077 -1040
- package/framework/commands/morph-apply.md +0 -2
- package/framework/commands/morph-preflight.md +192 -247
- package/framework/commands/morph-proposal.md +210 -238
- package/framework/commands/morph-status.md +72 -92
- package/framework/phases.json +162 -162
- package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +2 -2
- package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/code-quality-reviewer-prompt.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +143 -170
- package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
- package/package.json +1 -1
- package/src/utils/agents-installer.js +58 -18
- package/framework/agents/integrations/hangfire-integration.md +0 -69
package/CLAUDE.md
CHANGED
|
@@ -51,16 +51,16 @@ No build step — pure ESM JavaScript, runs directly via Node.js 18+.
|
|
|
51
51
|
- `installers/` — Agents, skills, hooks installers for target projects
|
|
52
52
|
- **`src/utils/`** — Shared utilities (logger, banner, file-copier, claude-settings-manager, etc.)
|
|
53
53
|
- **`framework/`** — Metadata installed into target projects (READ-ONLY at runtime):
|
|
54
|
-
- `agents.json` (v4.0.0
|
|
55
|
-
- `phases.json` (
|
|
56
|
-
- `standards/STANDARDS.json`
|
|
57
|
-
- `hooks/claude-code/` — Hook scripts (
|
|
54
|
+
- `agents.json` (v4.0.0)
|
|
55
|
+
- `phases.json` (7 phases incl. sync)
|
|
56
|
+
- `standards/STANDARDS.json`
|
|
57
|
+
- `hooks/claude-code/` — Hook scripts (fail-open design)
|
|
58
58
|
- `skills/` — Morph skills (level-0-meta + level-1-workflows)
|
|
59
59
|
- `templates/` — Handlebars templates for code generation
|
|
60
60
|
|
|
61
61
|
### Key Architectural Patterns
|
|
62
62
|
|
|
63
|
-
**Dual-layer phase tracking:** Phase is derived from filesystem (`derivePhase()` scans for highest-numbered phase folder) — state.json only overrides for lightweight phases (
|
|
63
|
+
**Dual-layer phase tracking:** Phase is derived from filesystem (`derivePhase()` scans for highest-numbered phase folder) — state.json only overrides for lightweight phases (sync).
|
|
64
64
|
|
|
65
65
|
**Output schema as single source of truth:** `src/core/paths/output-schema.js` defines all output types. Run `npm run generate` after modifying it to update derived reference files.
|
|
66
66
|
|
|
@@ -70,12 +70,12 @@ No build step — pure ESM JavaScript, runs directly via Node.js 18+.
|
|
|
70
70
|
|
|
71
71
|
**Atomic state writes:** `state-manager.js` writes to a process-ID temp file then renames, preventing corruption from concurrent CLI invocations.
|
|
72
72
|
|
|
73
|
-
**Stack-aware filtering:** Assets declare `stacks: ['dotnet'
|
|
73
|
+
**Stack-aware filtering:** Assets declare `stacks: ['dotnet']` in YAML frontmatter. `setup-infra.js` reads `config.json → project.stack`, splits into tags, and installs only matching assets. `stacks: ['*']` = universal.
|
|
74
74
|
|
|
75
75
|
### Phase Sequence
|
|
76
76
|
|
|
77
77
|
```
|
|
78
|
-
proposal →
|
|
78
|
+
proposal → [uiux] → design → plan → tasks → implement → [sync]
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
Phases in brackets are optional. Approval gates exist at: proposal, design, plan, tasks, uiux.
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Spec-driven development framework for multi-stack projects. Turns feature requests into implementation-ready code through structured, AI-orchestrated phases.
|
|
4
4
|
|
|
5
5
|
**Package:** `@polymorphism-tech/morph-spec`
|
|
6
|
-
**Version:** 4.
|
|
6
|
+
**Version:** 4.15.0
|
|
7
7
|
**Requires:** Node.js 18+, Claude Code
|
|
8
8
|
|
|
9
9
|
---
|
|
@@ -88,7 +88,7 @@ your-project/
|
|
|
88
88
|
Features move through structured phases. Some are optional depending on feature type.
|
|
89
89
|
|
|
90
90
|
```
|
|
91
|
-
proposal →
|
|
91
|
+
proposal → [uiux] → design → plan → tasks → implement → [sync]
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
Phases in brackets are optional. `uiux` applies to UI-heavy features. `sync` is a post-implementation reconciliation step.
|
|
@@ -101,14 +101,16 @@ Phases in brackets are optional. `uiux` applies to UI-heavy features. `sync` is
|
|
|
101
101
|
| Proposal | `0-proposal/` | `proposal.md` |
|
|
102
102
|
| UI/UX | `1-ui/` | `design-system.md`, `mockups.md`, `components.md`, `flows.md` |
|
|
103
103
|
| Design | `2-design/` | `spec.md`, `contracts.cs`, `decisions.md` |
|
|
104
|
-
|
|
|
105
|
-
|
|
|
104
|
+
| Plan | `3-plan/` | `plan.md` |
|
|
105
|
+
| Tasks | `4-tasks/` | `tasks.md` |
|
|
106
|
+
| Implement | `5-implement/` | `recap.md` |
|
|
106
107
|
|
|
107
108
|
|
|
108
109
|
### Approval gates
|
|
109
110
|
|
|
110
|
-
- **Design gate** — Spec must be approved before moving to
|
|
111
|
-
- **
|
|
111
|
+
- **Design gate** — Spec must be approved before moving to Plan.
|
|
112
|
+
- **Plan gate** — Plan must be approved before moving to Tasks.
|
|
113
|
+
- **Tasks gate** — Task list must be approved before implementation starts.
|
|
112
114
|
|
|
113
115
|
Check gate status:
|
|
114
116
|
|
|
@@ -362,4 +364,4 @@ Code generated by morph-spec (contracts, templates, implementation output) belon
|
|
|
362
364
|
|
|
363
365
|
---
|
|
364
366
|
|
|
365
|
-
*morph-spec v4.
|
|
367
|
+
*morph-spec v4.15.0 by [Polymorphism Tech](https://polymorphism.tech)*
|
package/claude-plugin.json
CHANGED
package/docs/CHEATSHEET.md
CHANGED
|
@@ -17,7 +17,7 @@ morph-spec --version
|
|
|
17
17
|
## Phase workflow
|
|
18
18
|
|
|
19
19
|
```
|
|
20
|
-
proposal →
|
|
20
|
+
proposal → [uiux] → design → plan → tasks → implement → [sync]
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Phases in brackets are optional.
|
|
@@ -25,13 +25,12 @@ Phases in brackets are optional.
|
|
|
25
25
|
| Phase | Directory | Output files | Gate |
|
|
26
26
|
|-------|-----------|--------------|------|
|
|
27
27
|
| proposal | `0-proposal/` | `proposal.md` | ✅ Approval |
|
|
28
|
-
| setup | *(no output)* | context loaded | — |
|
|
29
28
|
| uiux *(optional)* | `1-ui/` | `design-system.md`, `mockups.md`, `components.md`, `flows.md` | ✅ Approval |
|
|
30
29
|
| design | `2-design/` | `spec.md`, `contracts.cs`, `decisions.md` | ✅ Approval |
|
|
31
|
-
|
|
|
32
|
-
| tasks | `
|
|
33
|
-
| implement | `
|
|
34
|
-
| sync *(optional)* |
|
|
30
|
+
| plan | `3-plan/` | `plan.md` | ✅ Approval |
|
|
31
|
+
| tasks | `4-tasks/` | `tasks.md` | ✅ Approval |
|
|
32
|
+
| implement | `5-implement/` | code + `recap.md` | — |
|
|
33
|
+
| sync *(optional)* | — | standards updated | — |
|
|
35
34
|
|
|
36
35
|
---
|
|
37
36
|
|
|
@@ -197,4 +196,4 @@ These files are never edited directly. Use CLI commands or `morph-spec update` i
|
|
|
197
196
|
|
|
198
197
|
---
|
|
199
198
|
|
|
200
|
-
*morph-spec v4.
|
|
199
|
+
*morph-spec v4.15.0 by Polymorphism Tech*
|
package/docs/QUICKSTART.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
name: ai-system-architect
|
|
3
3
|
description: AI System Architect specialist for designing multi-agent systems, LLM orchestration, RAG pipelines, and Semantic Kernel patterns. Use when designing AI agent architectures, implementing LLM-powered features, building RAG pipelines, or integrating Microsoft Agent Framework.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
color: orange
|
|
6
|
+
effort: high
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# AI System Architect
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vector-search-expert
|
|
3
|
+
description: Vector Search & RAG specialist for embedding pipelines, pgvector indexes, semantic search, hybrid search, and retrieval-augmented generation. Use when implementing embedding generation, vector similarity search, RAG pipelines, or hybrid full-text + vector search.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
color: yellow
|
|
6
|
+
effort: medium
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Vector Search & RAG Specialist
|
|
10
|
+
|
|
11
|
+
Expert in embedding pipelines, pgvector, semantic search, and retrieval-augmented generation.
|
|
12
|
+
|
|
13
|
+
> **Ref:** `framework/standards/backend/database/vector-search-rag.md` — Chunking, embedding, retrieval patterns
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Embedding Pipeline
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Documents → Chunking → Embedding → pgvector Storage → Retrieval → LLM
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Chunking Strategies
|
|
24
|
+
|
|
25
|
+
| Strategy | Method | Best For | Chunk Size |
|
|
26
|
+
|----------|--------|----------|------------|
|
|
27
|
+
| **Paragraph** | Split by `\n\n` | General text | 200-500 tokens |
|
|
28
|
+
| **Markdown Headers** | Split by `#`, `##` | Documentation | Variable |
|
|
29
|
+
| **Token-based** | Fixed token windows | Uniform chunks | 256-512 tokens |
|
|
30
|
+
| **Semantic** | Cosine similarity threshold | Highest quality | Variable |
|
|
31
|
+
|
|
32
|
+
**Always overlap:** 10-20% overlap between chunks prevents context loss at boundaries.
|
|
33
|
+
|
|
34
|
+
```csharp
|
|
35
|
+
// Simple paragraph chunker
|
|
36
|
+
public static IEnumerable<string> ChunkByParagraph(string text, int maxTokens = 500)
|
|
37
|
+
{
|
|
38
|
+
var paragraphs = text.Split("\n\n", StringSplitOptions.RemoveEmptyEntries);
|
|
39
|
+
var current = new StringBuilder();
|
|
40
|
+
var currentTokens = 0;
|
|
41
|
+
|
|
42
|
+
foreach (var para in paragraphs)
|
|
43
|
+
{
|
|
44
|
+
var paraTokens = EstimateTokens(para);
|
|
45
|
+
if (currentTokens + paraTokens > maxTokens && current.Length > 0)
|
|
46
|
+
{
|
|
47
|
+
yield return current.ToString().Trim();
|
|
48
|
+
current.Clear();
|
|
49
|
+
currentTokens = 0;
|
|
50
|
+
}
|
|
51
|
+
current.AppendLine(para);
|
|
52
|
+
currentTokens += paraTokens;
|
|
53
|
+
}
|
|
54
|
+
if (current.Length > 0) yield return current.ToString().Trim();
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Embedding Generation
|
|
61
|
+
|
|
62
|
+
```csharp
|
|
63
|
+
// Using Microsoft.Extensions.AI
|
|
64
|
+
public class EmbeddingService(IEmbeddingGenerator<string, Embedding<float>> generator)
|
|
65
|
+
{
|
|
66
|
+
public async Task<float[]> GenerateAsync(string text, CancellationToken ct = default)
|
|
67
|
+
{
|
|
68
|
+
var result = await generator.GenerateAsync([text], cancellationToken: ct);
|
|
69
|
+
return result[0].Vector.ToArray();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public async Task<IReadOnlyList<float[]>> GenerateBatchAsync(
|
|
73
|
+
IEnumerable<string> texts, CancellationToken ct = default)
|
|
74
|
+
{
|
|
75
|
+
var result = await generator.GenerateAsync(texts.ToList(), cancellationToken: ct);
|
|
76
|
+
return result.Select(e => e.Vector.ToArray()).ToList();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Registration
|
|
81
|
+
builder.Services.AddEmbeddingGenerator(b => b
|
|
82
|
+
.UseOpenTelemetry()
|
|
83
|
+
.UseLogging()
|
|
84
|
+
.Use(new OpenAIEmbeddingGenerator(
|
|
85
|
+
new OpenAIClient(apiKey),
|
|
86
|
+
"text-embedding-3-small"))); // 1536 dimensions
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## pgvector Storage & Search
|
|
92
|
+
|
|
93
|
+
### Table schema
|
|
94
|
+
|
|
95
|
+
```sql
|
|
96
|
+
CREATE TABLE public.embeddings (
|
|
97
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
98
|
+
source_id UUID NOT NULL,
|
|
99
|
+
source_type TEXT NOT NULL, -- 'document', 'faq', 'article'
|
|
100
|
+
chunk_index INT NOT NULL,
|
|
101
|
+
content TEXT NOT NULL,
|
|
102
|
+
embedding vector(1536) NOT NULL,
|
|
103
|
+
metadata JSONB DEFAULT '{}'::jsonb,
|
|
104
|
+
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
|
105
|
+
UNIQUE(source_id, chunk_index)
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
-- HNSW index (fast, recommended for < 1M vectors)
|
|
109
|
+
CREATE INDEX idx_embeddings_hnsw ON public.embeddings
|
|
110
|
+
USING hnsw (embedding vector_cosine_ops)
|
|
111
|
+
WITH (m = 16, ef_construction = 64);
|
|
112
|
+
|
|
113
|
+
-- IVFFlat index (better for > 1M vectors)
|
|
114
|
+
-- CREATE INDEX idx_embeddings_ivf ON public.embeddings
|
|
115
|
+
-- USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Similarity search
|
|
119
|
+
|
|
120
|
+
```sql
|
|
121
|
+
-- Cosine similarity (1 = identical, 0 = unrelated)
|
|
122
|
+
SELECT id, content, metadata,
|
|
123
|
+
1 - (embedding <=> $1::vector) AS similarity
|
|
124
|
+
FROM public.embeddings
|
|
125
|
+
WHERE 1 - (embedding <=> $1::vector) > 0.78
|
|
126
|
+
ORDER BY embedding <=> $1::vector
|
|
127
|
+
LIMIT 5;
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Hybrid search (vector + full-text)
|
|
131
|
+
|
|
132
|
+
```sql
|
|
133
|
+
-- Combine vector similarity with PostgreSQL full-text search
|
|
134
|
+
CREATE OR REPLACE FUNCTION hybrid_search(
|
|
135
|
+
query_text TEXT,
|
|
136
|
+
query_embedding vector(1536),
|
|
137
|
+
match_count INT DEFAULT 5,
|
|
138
|
+
vector_weight FLOAT DEFAULT 0.7,
|
|
139
|
+
text_weight FLOAT DEFAULT 0.3
|
|
140
|
+
)
|
|
141
|
+
RETURNS TABLE (id UUID, content TEXT, score FLOAT)
|
|
142
|
+
LANGUAGE plpgsql AS $$
|
|
143
|
+
BEGIN
|
|
144
|
+
RETURN QUERY
|
|
145
|
+
WITH vector_results AS (
|
|
146
|
+
SELECT e.id, e.content,
|
|
147
|
+
1 - (e.embedding <=> query_embedding) AS vscore
|
|
148
|
+
FROM public.embeddings e
|
|
149
|
+
ORDER BY e.embedding <=> query_embedding
|
|
150
|
+
LIMIT match_count * 3
|
|
151
|
+
),
|
|
152
|
+
text_results AS (
|
|
153
|
+
SELECT e.id, e.content,
|
|
154
|
+
ts_rank(to_tsvector('english', e.content), plainto_tsquery('english', query_text)) AS tscore
|
|
155
|
+
FROM public.embeddings e
|
|
156
|
+
WHERE to_tsvector('english', e.content) @@ plainto_tsquery('english', query_text)
|
|
157
|
+
LIMIT match_count * 3
|
|
158
|
+
)
|
|
159
|
+
SELECT COALESCE(v.id, t.id),
|
|
160
|
+
COALESCE(v.content, t.content),
|
|
161
|
+
(COALESCE(v.vscore, 0) * vector_weight + COALESCE(t.tscore, 0) * text_weight) AS score
|
|
162
|
+
FROM vector_results v
|
|
163
|
+
FULL OUTER JOIN text_results t ON v.id = t.id
|
|
164
|
+
ORDER BY score DESC
|
|
165
|
+
LIMIT match_count;
|
|
166
|
+
END;
|
|
167
|
+
$$;
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## RAG Tool for Agent Framework
|
|
173
|
+
|
|
174
|
+
```csharp
|
|
175
|
+
public class KnowledgeBaseTool(
|
|
176
|
+
EmbeddingService embeddings,
|
|
177
|
+
ISupabaseClient supabase)
|
|
178
|
+
{
|
|
179
|
+
[Description("Search the knowledge base for relevant information")]
|
|
180
|
+
public async Task<string> SearchAsync(
|
|
181
|
+
[Description("Natural language search query")] string query,
|
|
182
|
+
[Description("Maximum results to return")] int topK = 5,
|
|
183
|
+
CancellationToken ct = default)
|
|
184
|
+
{
|
|
185
|
+
var embedding = await embeddings.GenerateAsync(query, ct);
|
|
186
|
+
|
|
187
|
+
var results = await supabase.Rpc("match_embeddings", new
|
|
188
|
+
{
|
|
189
|
+
query_embedding = embedding,
|
|
190
|
+
match_threshold = 0.78,
|
|
191
|
+
match_count = topK
|
|
192
|
+
}, ct);
|
|
193
|
+
|
|
194
|
+
return string.Join("\n\n---\n\n",
|
|
195
|
+
results.Select(r => $"[Score: {r.Similarity:F2}]\n{r.Content}"));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Index Selection Guide
|
|
203
|
+
|
|
204
|
+
| Vectors | Recommended | Why |
|
|
205
|
+
|---------|-------------|-----|
|
|
206
|
+
| < 10K | No index (sequential scan) | Index overhead not worth it |
|
|
207
|
+
| 10K - 1M | HNSW (m=16, ef=64) | Fast, good recall |
|
|
208
|
+
| 1M+ | IVFFlat (lists=sqrt(n)) | Lower memory, acceptable recall |
|
|
209
|
+
|
|
210
|
+
### Tuning HNSW
|
|
211
|
+
|
|
212
|
+
- `m` (connections per node): higher = better recall, more memory. Default 16.
|
|
213
|
+
- `ef_construction` (build-time search depth): higher = better index, slower build. Default 64.
|
|
214
|
+
- `ef_search` (query-time): `SET hnsw.ef_search = 100;` for better recall at query time.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Checklist
|
|
219
|
+
|
|
220
|
+
- [ ] Chunking strategy selected and tested with real data
|
|
221
|
+
- [ ] Chunk overlap configured (10-20%)
|
|
222
|
+
- [ ] Embedding model chosen (text-embedding-3-small for cost, text-embedding-3-large for quality)
|
|
223
|
+
- [ ] pgvector extension enabled
|
|
224
|
+
- [ ] HNSW or IVFFlat index created based on vector count
|
|
225
|
+
- [ ] Similarity threshold tuned (start at 0.78, adjust by domain)
|
|
226
|
+
- [ ] Hybrid search implemented if full-text relevance matters
|
|
227
|
+
- [ ] Batch embedding for initial ingestion (not one-by-one)
|
|
228
|
+
- [ ] RLS policies on embeddings table
|
|
229
|
+
- [ ] Source tracking (source_id + source_type) for updates/deletes
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
name: seo-growth-hacker
|
|
3
3
|
description: SEO and Growth specialist for technical SEO, Core Web Vitals optimization, content strategy, and organic growth for SaaS and landing pages. Use when optimizing for search engine ranking, improving Lighthouse scores, implementing SEO for Next.js pages, or planning content-driven growth.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
color: pink
|
|
6
|
+
effort: medium
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# SEO Growth Hacker
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
name: standards-architect
|
|
3
3
|
description: Standards Architect (Tier 1 Orchestrator) that enforces MORPH-SPEC naming conventions, coding standards, and cross-cutting compliance across all outputs. Always active in MORPH-SPEC workflows. Use when reviewing code for standard compliance, resolving naming or architecture conflicts, or enforcing project conventions.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
color: red
|
|
6
|
+
effort: high
|
|
7
|
+
permissionMode: acceptEdits
|
|
5
8
|
---
|
|
6
9
|
|
|
7
10
|
# Standards Architect
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: supabase-expert
|
|
3
|
+
description: Supabase & PostgreSQL specialist for RLS policies, auth integration, pgvector, Realtime subscriptions, Edge Functions, and migration management. Use when designing database schemas, implementing Row Level Security, setting up auth flows, or working with pgvector embeddings.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
stacks:
|
|
6
|
+
- supabase
|
|
7
|
+
color: teal
|
|
8
|
+
effort: medium
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Supabase & PostgreSQL Specialist
|
|
12
|
+
|
|
13
|
+
Expert in Supabase auth, Row Level Security, Realtime, Edge Functions, and pgvector.
|
|
14
|
+
|
|
15
|
+
> **Ref:** `framework/standards/infrastructure/supabase/` — RLS, auth, storage, pgvector standards
|
|
16
|
+
|
|
17
|
+
## Connection Pooling
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
# Direct connection (migrations only)
|
|
21
|
+
postgresql://postgres:[password]@db.[project].supabase.co:5432/postgres
|
|
22
|
+
|
|
23
|
+
# PgBouncer (application — ALWAYS use this)
|
|
24
|
+
postgresql://postgres.[project]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Rule:** Application code ALWAYS connects via PgBouncer (port 6543). Direct connections (port 5432) only for migrations and schema changes.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Row Level Security (RLS)
|
|
32
|
+
|
|
33
|
+
### Enable RLS on every table
|
|
34
|
+
|
|
35
|
+
```sql
|
|
36
|
+
ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Common RLS Patterns
|
|
40
|
+
|
|
41
|
+
```sql
|
|
42
|
+
-- User owns the row
|
|
43
|
+
CREATE POLICY "Users can view own documents"
|
|
44
|
+
ON public.documents FOR SELECT
|
|
45
|
+
USING (auth.uid() = user_id);
|
|
46
|
+
|
|
47
|
+
-- User can insert own rows
|
|
48
|
+
CREATE POLICY "Users can insert own documents"
|
|
49
|
+
ON public.documents FOR INSERT
|
|
50
|
+
WITH CHECK (auth.uid() = user_id);
|
|
51
|
+
|
|
52
|
+
-- User can update own rows
|
|
53
|
+
CREATE POLICY "Users can update own documents"
|
|
54
|
+
ON public.documents FOR UPDATE
|
|
55
|
+
USING (auth.uid() = user_id)
|
|
56
|
+
WITH CHECK (auth.uid() = user_id);
|
|
57
|
+
|
|
58
|
+
-- User can delete own rows
|
|
59
|
+
CREATE POLICY "Users can delete own documents"
|
|
60
|
+
ON public.documents FOR DELETE
|
|
61
|
+
USING (auth.uid() = user_id);
|
|
62
|
+
|
|
63
|
+
-- Service role bypass (for backend API)
|
|
64
|
+
CREATE POLICY "Service role full access"
|
|
65
|
+
ON public.documents FOR ALL
|
|
66
|
+
USING (auth.role() = 'service_role');
|
|
67
|
+
|
|
68
|
+
-- Team-based access
|
|
69
|
+
CREATE POLICY "Team members can view"
|
|
70
|
+
ON public.documents FOR SELECT
|
|
71
|
+
USING (
|
|
72
|
+
team_id IN (
|
|
73
|
+
SELECT team_id FROM public.team_members
|
|
74
|
+
WHERE user_id = auth.uid()
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### RLS with Clerk JWT (custom claims)
|
|
80
|
+
|
|
81
|
+
```sql
|
|
82
|
+
-- Extract Clerk user ID from JWT
|
|
83
|
+
CREATE OR REPLACE FUNCTION auth.clerk_user_id()
|
|
84
|
+
RETURNS TEXT AS $$
|
|
85
|
+
SELECT coalesce(
|
|
86
|
+
current_setting('request.jwt.claims', true)::json->>'sub',
|
|
87
|
+
''
|
|
88
|
+
);
|
|
89
|
+
$$ LANGUAGE sql STABLE;
|
|
90
|
+
|
|
91
|
+
-- Use in RLS policies
|
|
92
|
+
CREATE POLICY "Clerk users own rows"
|
|
93
|
+
ON public.documents FOR ALL
|
|
94
|
+
USING (clerk_user_id = auth.clerk_user_id());
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Migrations
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Create new migration
|
|
103
|
+
npx supabase migration new create_documents_table
|
|
104
|
+
|
|
105
|
+
# Apply locally
|
|
106
|
+
npx supabase db reset
|
|
107
|
+
|
|
108
|
+
# Push to remote
|
|
109
|
+
npx supabase db push
|
|
110
|
+
|
|
111
|
+
# Diff local vs remote
|
|
112
|
+
npx supabase db diff --use-migra
|
|
113
|
+
|
|
114
|
+
# Lint for common issues
|
|
115
|
+
npx supabase db lint --level warning
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Migration file structure
|
|
119
|
+
|
|
120
|
+
```sql
|
|
121
|
+
-- supabase/migrations/20240101000000_create_documents_table.sql
|
|
122
|
+
|
|
123
|
+
CREATE TABLE public.documents (
|
|
124
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
125
|
+
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
126
|
+
title TEXT NOT NULL,
|
|
127
|
+
content TEXT,
|
|
128
|
+
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
|
129
|
+
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
-- Always enable RLS
|
|
133
|
+
ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
|
|
134
|
+
|
|
135
|
+
-- Always add indexes for filtered columns
|
|
136
|
+
CREATE INDEX idx_documents_user_id ON public.documents(user_id);
|
|
137
|
+
CREATE INDEX idx_documents_created_at ON public.documents(created_at DESC);
|
|
138
|
+
|
|
139
|
+
-- RLS policies
|
|
140
|
+
CREATE POLICY "Users manage own documents"
|
|
141
|
+
ON public.documents FOR ALL
|
|
142
|
+
USING (auth.uid() = user_id)
|
|
143
|
+
WITH CHECK (auth.uid() = user_id);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## pgvector (Embeddings)
|
|
149
|
+
|
|
150
|
+
### Setup
|
|
151
|
+
|
|
152
|
+
```sql
|
|
153
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
154
|
+
|
|
155
|
+
CREATE TABLE public.embeddings (
|
|
156
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
157
|
+
document_id UUID REFERENCES public.documents(id) ON DELETE CASCADE,
|
|
158
|
+
content TEXT NOT NULL,
|
|
159
|
+
embedding vector(1536) NOT NULL, -- OpenAI text-embedding-3-small
|
|
160
|
+
metadata JSONB DEFAULT '{}'::jsonb,
|
|
161
|
+
created_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
-- HNSW index for fast similarity search (cosine distance)
|
|
165
|
+
CREATE INDEX idx_embeddings_vector ON public.embeddings
|
|
166
|
+
USING hnsw (embedding vector_cosine_ops)
|
|
167
|
+
WITH (m = 16, ef_construction = 64);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Similarity search function
|
|
171
|
+
|
|
172
|
+
```sql
|
|
173
|
+
CREATE OR REPLACE FUNCTION match_embeddings(
|
|
174
|
+
query_embedding vector(1536),
|
|
175
|
+
match_threshold FLOAT DEFAULT 0.78,
|
|
176
|
+
match_count INT DEFAULT 5
|
|
177
|
+
)
|
|
178
|
+
RETURNS TABLE (
|
|
179
|
+
id UUID,
|
|
180
|
+
content TEXT,
|
|
181
|
+
metadata JSONB,
|
|
182
|
+
similarity FLOAT
|
|
183
|
+
)
|
|
184
|
+
LANGUAGE plpgsql AS $$
|
|
185
|
+
BEGIN
|
|
186
|
+
RETURN QUERY
|
|
187
|
+
SELECT
|
|
188
|
+
e.id,
|
|
189
|
+
e.content,
|
|
190
|
+
e.metadata,
|
|
191
|
+
1 - (e.embedding <=> query_embedding) AS similarity
|
|
192
|
+
FROM public.embeddings e
|
|
193
|
+
WHERE 1 - (e.embedding <=> query_embedding) > match_threshold
|
|
194
|
+
ORDER BY e.embedding <=> query_embedding
|
|
195
|
+
LIMIT match_count;
|
|
196
|
+
END;
|
|
197
|
+
$$;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Realtime Subscriptions
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
// Subscribe to changes on a table
|
|
206
|
+
const channel = supabase
|
|
207
|
+
.channel('documents-changes')
|
|
208
|
+
.on('postgres_changes',
|
|
209
|
+
{ event: '*', schema: 'public', table: 'documents', filter: `user_id=eq.${userId}` },
|
|
210
|
+
(payload) => {
|
|
211
|
+
console.log('Change:', payload.eventType, payload.new);
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
.subscribe();
|
|
215
|
+
|
|
216
|
+
// Cleanup
|
|
217
|
+
channel.unsubscribe();
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Rule:** Always filter subscriptions by user/team — never subscribe to full table changes.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Storage (File Uploads)
|
|
225
|
+
|
|
226
|
+
```sql
|
|
227
|
+
-- Create bucket
|
|
228
|
+
INSERT INTO storage.buckets (id, name, public)
|
|
229
|
+
VALUES ('avatars', 'avatars', true);
|
|
230
|
+
|
|
231
|
+
-- RLS for storage
|
|
232
|
+
CREATE POLICY "Users upload own avatar"
|
|
233
|
+
ON storage.objects FOR INSERT
|
|
234
|
+
WITH CHECK (
|
|
235
|
+
bucket_id = 'avatars' AND
|
|
236
|
+
auth.uid()::text = (storage.foldername(name))[1]
|
|
237
|
+
);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Checklist
|
|
243
|
+
|
|
244
|
+
- [ ] PgBouncer (port 6543) used for all application connections
|
|
245
|
+
- [ ] RLS enabled on ALL public tables
|
|
246
|
+
- [ ] RLS policies cover SELECT, INSERT, UPDATE, DELETE
|
|
247
|
+
- [ ] Service role policy exists for backend API access
|
|
248
|
+
- [ ] Migrations use `npx supabase migration new` (not manual SQL)
|
|
249
|
+
- [ ] Indexes on all frequently filtered columns
|
|
250
|
+
- [ ] pgvector: HNSW index with appropriate m/ef_construction values
|
|
251
|
+
- [ ] Realtime subscriptions filtered by user/team
|
|
252
|
+
- [ ] Storage buckets have RLS policies
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
*MORPH-SPEC by Polymorphism Tech*
|