@polymorphism-tech/morph-spec 10.0.0 → 10.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 (46) hide show
  1. package/CLAUDE.md +2 -0
  2. package/README.md +2 -2
  3. package/claude-plugin.json +1 -1
  4. package/docs/CHEATSHEET.md +28 -36
  5. package/docs/QUICKSTART.md +31 -191
  6. package/framework/CLAUDE.md +2 -2
  7. package/framework/MORPH.md +2 -2
  8. package/framework/commands/morph-preflight.md +3 -3
  9. package/framework/docs/CLI.md +1 -1
  10. package/framework/hooks/shared/next-step.js +2 -2
  11. package/framework/mcp/registry.json +4 -4
  12. package/framework/rules/ai-agents-standards.md +1 -1
  13. package/framework/rules/data-standards.md +1 -1
  14. package/framework/rules/hangfire-standards.md +1 -1
  15. package/framework/rules/neon-auth-standards.md +1 -1
  16. package/framework/rules/neon-standards.md +3 -3
  17. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  18. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  19. package/framework/skills/core/morph-apply/SKILL.md +4 -3
  20. package/framework/skills/core/morph-plan/SKILL.md +19 -13
  21. package/framework/skills/core/morph-plan/references/critique.md +11 -8
  22. package/framework/skills/core/morph-plan/references/interview.md +18 -6
  23. package/framework/skills/core/morph-uiux/SKILL.md +1 -1
  24. package/framework/standards/STANDARDS.json +20 -24
  25. package/framework/standards/STANDARDS.meta.json +12 -19
  26. package/framework/standards/ai-agents/rag-custom-pgvector.md +1 -0
  27. package/framework/standards/architecture/stack-baseline.md +26 -3
  28. package/framework/standards/backend/database/postgresql/database.md +22 -1
  29. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +33 -1
  30. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +2 -1
  31. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +10 -9
  32. package/framework/standards/infrastructure/docker/local-compose-isolation.md +2 -2
  33. package/framework/standards/infrastructure/neon/neon-pgvector.md +62 -20
  34. package/framework/standards/infrastructure/neon/neon-platform.md +61 -0
  35. package/framework/standards/infrastructure/neon/neon-setup.md +14 -13
  36. package/framework/standards/integration/mcp/mcp-tools.md +20 -20
  37. package/framework/templates/docs/plan.md +4 -1
  38. package/framework/templates/infrastructure/docker/docker-compose.template.yml +1 -1
  39. package/package.json +1 -1
  40. package/src/commands/state/auto-approval.js +1 -1
  41. package/src/commands/state/create.js +1 -1
  42. package/src/commands/state/gate-check.js +2 -2
  43. package/src/lib/detectors/index.js +1 -1
  44. package/src/lib/installers/memory-installer.js +1 -1
  45. package/src/lib/plan/checks.js +8 -1
  46. package/framework/standards/infrastructure/neon/neon-pgrag.md +0 -243
@@ -1,243 +0,0 @@
1
- # Neon pgrag Standard
2
-
3
- > **Scope:** neon
4
- > **Layer:** 2 (on keyword)
5
- > **Keywords:** pgrag, rag, chunking, embedding, reranking, retrieval
6
- > **Load When:** pgrag or in-database RAG keywords detected
7
-
8
- **Verified against:** Neon pgrag (`rag` extension family — experimental, see Core Rules). Last-verified: 2026-05-20.
9
-
10
- ---
11
-
12
- Stack: Neon Serverless Postgres
13
-
14
- ## Core Rules
15
-
16
- - pgrag is EXPERIMENTAL -- API may change between Neon releases
17
- - ALWAYS enable unstable extensions before installing: `SET neon.allow_unstable_extensions='true'`
18
- - Use pgrag for simple, self-contained RAG pipelines (PDF ingestion, chunking, search)
19
- - Use application-level custom RAG (a typed MAF tool over pgvector — see standard ai-agents-rag-custom-pgvector) for complex workflows requiring custom logic, multi-model orchestration, or .NET integration
20
- - NEVER use pgrag local embeddings (384 dims) when your application uses a different embedding model -- dimension mismatch breaks search
21
-
22
- ## Install pgrag
23
-
24
- ```sql
25
- -- Enable unstable extensions (required)
26
- SET neon.allow_unstable_extensions='true';
27
-
28
- -- Core extension
29
- CREATE EXTENSION IF NOT EXISTS rag CASCADE;
30
-
31
- -- Local embedding model (bge-small-en-v1.5, 384 dimensions, 33M params)
32
- CREATE EXTENSION IF NOT EXISTS rag_bge_small_en_v15 CASCADE;
33
-
34
- -- Local reranker (jina-reranker-v1-tiny-en, 33M params)
35
- CREATE EXTENSION IF NOT EXISTS rag_jina_reranker_v1_tiny_en CASCADE;
36
- ```
37
-
38
- ## Text Extraction
39
-
40
- Extract text from binary documents directly in SQL:
41
-
42
- ```sql
43
- -- Extract text from PDF
44
- SELECT rag.text_from_pdf(pg_read_binary_file('/path/to/document.pdf'));
45
-
46
- -- Extract text from DOCX
47
- SELECT rag.text_from_docx(pg_read_binary_file('/path/to/document.docx'));
48
-
49
- -- Convert HTML to Markdown
50
- SELECT rag.markdown_from_html('<h1>Title</h1><p>Content here</p>');
51
- ```
52
-
53
- ### From a Documents Table
54
-
55
- ```sql
56
- CREATE TABLE raw_documents (
57
- id SERIAL PRIMARY KEY,
58
- filename TEXT NOT NULL,
59
- content BYTEA NOT NULL,
60
- extracted_text TEXT
61
- );
62
-
63
- -- Extract text on insert
64
- UPDATE raw_documents
65
- SET extracted_text = rag.text_from_pdf(content)
66
- WHERE filename LIKE '%.pdf' AND extracted_text IS NULL;
67
- ```
68
-
69
- ## Chunking Strategies
70
-
71
- ### Character-Based Chunking
72
-
73
- Splits text by character count with overlap for context continuity:
74
-
75
- ```sql
76
- -- Split into chunks of 1000 chars with 200 char overlap
77
- SELECT unnest(
78
- rag.chunks_by_character_count(
79
- 'Your long document text here...',
80
- 1000, -- max_chars per chunk
81
- 200 -- overlap chars
82
- )
83
- );
84
- ```
85
-
86
- ### Token-Based Chunking
87
-
88
- Uses the bge-small-en-v1.5 tokenizer for model-aware splitting:
89
-
90
- ```sql
91
- -- Split into chunks of 512 tokens with 50 token overlap
92
- SELECT unnest(
93
- rag_bge_small_en_v15.chunks_by_token_count(
94
- 'Your long document text here...',
95
- 512, -- max_tokens per chunk
96
- 50 -- overlap tokens
97
- )
98
- );
99
- ```
100
-
101
- ## Embedding Generation
102
-
103
- ### Local Embeddings (bge-small-en-v1.5)
104
-
105
- Zero-cost, runs on the database server. Produces 384-dimension vectors:
106
-
107
- ```sql
108
- -- Embedding for a document passage (includes "passage:" prefix internally)
109
- SELECT rag_bge_small_en_v15.embedding_for_passage('Neon is a serverless Postgres platform');
110
-
111
- -- Embedding for a search query (includes "query:" prefix internally)
112
- SELECT rag_bge_small_en_v15.embedding_for_query('What is Neon?');
113
- ```
114
-
115
- ### OpenAI Embeddings (text-embedding-3-small)
116
-
117
- Remote API call, produces 1536-dimension vectors:
118
-
119
- ```sql
120
- -- Set API key (per session)
121
- SET neon.ai_api_key = 'sk-...';
122
-
123
- -- Generate embedding via OpenAI
124
- SELECT rag.openai_text_embedding_3_small('Neon is a serverless Postgres platform');
125
- ```
126
-
127
- ## Full RAG Pipeline Example
128
-
129
- ```sql
130
- -- 1. Create chunks table
131
- CREATE TABLE chunks (
132
- id SERIAL PRIMARY KEY,
133
- document_id INT REFERENCES raw_documents(id),
134
- chunk_text TEXT NOT NULL,
135
- embedding vector(384)
136
- );
137
-
138
- -- 2. Chunk and embed a document
139
- WITH doc AS (
140
- SELECT id, rag.text_from_pdf(content) AS full_text
141
- FROM raw_documents WHERE id = 1
142
- ),
143
- chunked AS (
144
- SELECT doc.id AS document_id, unnest(
145
- rag.chunks_by_character_count(doc.full_text, 1000, 200)
146
- ) AS chunk_text
147
- FROM doc
148
- )
149
- INSERT INTO chunks (document_id, chunk_text, embedding)
150
- SELECT document_id, chunk_text,
151
- rag_bge_small_en_v15.embedding_for_passage(chunk_text)
152
- FROM chunked;
153
-
154
- -- 3. Create HNSW index
155
- CREATE INDEX idx_chunks_embedding ON chunks
156
- USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);
157
- ```
158
-
159
- ## Similarity Search
160
-
161
- ```sql
162
- -- Find top 10 similar chunks
163
- SELECT id, chunk_text,
164
- 1 - (embedding <=> rag_bge_small_en_v15.embedding_for_query('What is Neon?')) AS similarity
165
- FROM chunks
166
- ORDER BY embedding <=> rag_bge_small_en_v15.embedding_for_query('What is Neon?')
167
- LIMIT 10;
168
- ```
169
-
170
- ## Reranking
171
-
172
- Reranking refines initial vector search results using a cross-encoder model for higher accuracy:
173
-
174
- ```sql
175
- -- Rerank top 10 vector results down to top 5
176
- WITH vector_matches AS (
177
- SELECT id, chunk_text,
178
- 1 - (embedding <=> rag_bge_small_en_v15.embedding_for_query('What is Neon?')) AS similarity
179
- FROM chunks
180
- ORDER BY embedding <=> rag_bge_small_en_v15.embedding_for_query('What is Neon?')
181
- LIMIT 10
182
- )
183
- SELECT id, chunk_text, similarity,
184
- rag_jina_reranker_v1_tiny_en.rerank_distance('What is Neon?', chunk_text) AS rerank_score
185
- FROM vector_matches
186
- ORDER BY rerank_score ASC
187
- LIMIT 5;
188
- ```
189
-
190
- ## LLM Integration in SQL
191
-
192
- Send context + question to an LLM directly from SQL:
193
-
194
- ```sql
195
- -- Set API key
196
- SET neon.ai_api_key = 'sk-...';
197
-
198
- -- Ask a question with retrieved context
199
- WITH context AS (
200
- SELECT string_agg(chunk_text, E'\n---\n') AS combined_context
201
- FROM (
202
- SELECT chunk_text FROM chunks
203
- ORDER BY embedding <=> rag_bge_small_en_v15.embedding_for_query('What is Neon?')
204
- LIMIT 5
205
- ) top_chunks
206
- )
207
- SELECT rag.openai_chat_completion(
208
- json_build_object(
209
- 'model', 'gpt-4o',
210
- 'messages', json_build_array(
211
- json_build_object('role', 'system', 'content',
212
- 'Answer based on the provided context. If unsure, say so.'),
213
- json_build_object('role', 'user', 'content',
214
- format('Context:\n%s\n\nQuestion: What is Neon?', context.combined_context))
215
- )
216
- )
217
- ) FROM context;
218
- ```
219
-
220
- ## When to Use pgrag vs Application-Level RAG
221
-
222
- | Factor | pgrag (In-Database) | SK + pgvector (Application) |
223
- |--------|---------------------|----------------------------|
224
- | Setup complexity | Minimal -- SQL only | Requires .NET service layer |
225
- | Embedding model | Local (384d) or OpenAI | Any model via SK connectors |
226
- | Reranking | Built-in (Jina) | Custom implementation |
227
- | Custom logic | Limited to SQL | Full C# flexibility |
228
- | Multi-model orchestration | Not supported | Native SK capability |
229
- | Production readiness | Experimental | Stable (SK GA) |
230
- | Cost | Zero for local models | API costs for remote models |
231
- | Best for | Prototyping, simple RAG, SQL-only environments | Production .NET applications, complex pipelines |
232
-
233
- **Recommendation:** Start with pgrag for prototyping and validation. Migrate to custom RAG (a typed MAF vector-search tool over pgvector — see ai-agents-rag-custom-pgvector) for production .NET applications that need custom retrieval logic, multi-model orchestration, or MAF agent integration.
234
-
235
- ## Common Mistakes
236
-
237
- | Wrong | Right | Why |
238
- |-------|-------|-----|
239
- | Missing `neon.allow_unstable_extensions` | `SET neon.allow_unstable_extensions='true'` | pgrag won't install without it |
240
- | Mixing local (384d) and OpenAI (1536d) embeddings | Use one model consistently per column | Dimension mismatch breaks similarity search |
241
- | No HNSW index on chunks table | Create index after initial data load | Full table scan on every search |
242
- | Using pgrag in production without testing | Validate with representative data first | Extension is experimental, may change |
243
- | Storing API key in SQL scripts | Use session variables or environment config | Keys in scripts leak to version control |