@polymorphism-tech/morph-spec 9.8.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.
- package/CLAUDE.md +12 -10
- package/README.md +4 -4
- package/bin/morph-spec.js +40 -43
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +28 -36
- package/docs/QUICKSTART.md +31 -191
- package/framework/CLAUDE.md +24 -30
- package/framework/MORPH.md +47 -123
- package/framework/agents.json +6 -374
- package/framework/commands/morph-apply.md +1 -1
- package/framework/commands/morph-archive.md +4 -3
- package/framework/commands/morph-hotfix.md +8 -30
- package/framework/commands/morph-infra.md +2 -2
- package/framework/commands/morph-media.md +10 -9
- package/framework/commands/morph-preflight.md +3 -3
- package/framework/commands/morph-review.md +15 -0
- package/framework/commands/morph-status.md +1 -1
- package/framework/docs/CLI.md +84 -95
- package/framework/evals/review-checklist.md +45 -53
- package/framework/hooks/README.md +4 -4
- package/framework/hooks/claude-code/core/README.md +1 -1
- package/framework/hooks/claude-code/core/denylist.json +4 -4
- package/framework/hooks/claude-code/core/gate-guard.js +9 -0
- package/framework/hooks/claude-code/core/masked-exit.js +49 -0
- package/framework/hooks/claude-code/core/state-sync.js +4 -1
- package/framework/hooks/claude-code/core/telemetry-log.js +1 -2
- package/framework/hooks/claude-code/core/test-budget.js +10 -70
- package/framework/hooks/claude-code/core/validate-completion.js +11 -24
- package/framework/hooks/claude-code/core/worktree-context.js +5 -22
- package/framework/hooks/claude-code/core/worktree-create.js +6 -45
- package/framework/hooks/claude-code/core/worktree-env-inject.js +2 -10
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/gate-event.js +2 -2
- package/framework/hooks/shared/graph-refresh.js +20 -3
- package/framework/hooks/shared/heavy-command.js +32 -1
- package/framework/hooks/shared/heavy-config.js +1 -1
- package/framework/hooks/shared/next-step.js +63 -24
- package/framework/hooks/shared/phase-utils.js +6 -9
- package/framework/hooks/shared/report-progress.js +86 -0
- package/framework/hooks/shared/state-reader.js +3 -2
- package/framework/hooks/statusline.js +332 -0
- package/framework/mcp/registry.json +4 -4
- package/framework/phases.json +32 -10
- package/framework/rules/ai-agents-standards.md +10 -2
- package/framework/rules/csharp-standards.md +4 -0
- package/framework/rules/data-standards.md +1 -1
- package/framework/rules/ef-standards.md +20 -0
- package/framework/rules/frontend-standards.md +1 -1
- package/framework/rules/hangfire-standards.md +1 -1
- package/framework/rules/implement-report.md +25 -0
- package/framework/rules/infrastructure-standards.md +2 -0
- package/framework/rules/neon-auth-standards.md +1 -1
- package/framework/rules/neon-standards.md +3 -3
- package/framework/rules/nextjs-standards.md +7 -0
- package/framework/rules/plan-grammar.md +53 -0
- package/framework/rules/ui-design.md +27 -0
- package/framework/schemas/config.schema.json +11 -18
- package/framework/schemas/feature.schema.json +7 -1
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/create-umbraco-lp/references/umbraco-lp-patterns.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +2 -2
- package/framework/skills/core/morph-apply/SKILL.md +39 -166
- package/framework/skills/core/morph-apply/references/debugging.md +8 -0
- package/framework/skills/core/morph-apply/references/hotfix.md +42 -0
- package/framework/skills/core/morph-apply/references/machine.md +29 -0
- package/framework/skills/core/{morph-media/SKILL.md → morph-apply/references/media.md} +11 -74
- package/framework/skills/core/morph-apply/references/review.md +65 -0
- package/framework/skills/core/morph-plan/SKILL.md +49 -109
- package/framework/skills/core/morph-plan/references/critique.md +43 -0
- package/framework/skills/core/morph-plan/references/interview.md +37 -0
- package/framework/skills/core/morph-uiux/SKILL.md +47 -64
- package/framework/skills/core/morph-uiux/surfaces.json +32 -0
- package/framework/standards/STANDARDS.json +51 -28
- package/framework/standards/STANDARDS.meta.json +16 -19
- package/framework/standards/ai-agents/agent-session.md +2 -3
- package/framework/standards/ai-agents/context-providers.md +2 -2
- package/framework/standards/ai-agents/durable-workflows-hitl.md +2 -2
- package/framework/standards/ai-agents/providers/model-registry.md +2 -2
- package/framework/standards/ai-agents/rag-custom-pgvector.md +7 -6
- package/framework/standards/ai-agents/setup.md +1 -1
- package/framework/standards/ai-agents/tool-adapters.md +2 -2
- package/framework/standards/architecture/stack-baseline.md +70 -0
- package/framework/standards/backend/database/postgresql/database.md +22 -1
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +33 -1
- package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +2 -1
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +12 -13
- package/framework/standards/frontend/design-system/ai-image-generation.md +51 -12
- package/framework/standards/frontend/design-system/ai-video-generation.md +50 -4
- package/framework/standards/frontend/design-system/art-direction.md +2 -2
- package/framework/standards/frontend/scroll-driven/frame-scrub.md +12 -2
- package/framework/standards/frontend/scroll-driven/scroll-components.md +76 -4
- package/framework/standards/infrastructure/docker/local-compose-isolation.md +2 -2
- package/framework/standards/infrastructure/neon/neon-pgvector.md +62 -20
- package/framework/standards/infrastructure/neon/neon-platform.md +61 -0
- package/framework/standards/infrastructure/neon/neon-setup.md +14 -13
- package/framework/standards/integration/mcp/mcp-tools.md +20 -20
- package/framework/templates/REGISTRY.json +1 -2
- package/framework/templates/context/ARCHITECTURE.md +1 -1
- package/framework/templates/docs/plan.md +15 -12
- package/framework/templates/docs/ui-mockups.md +17 -105
- package/framework/templates/infrastructure/docker/docker-compose.template.yml +1 -1
- package/package.json +1 -1
- package/src/commands/e2e/e2e.js +88 -23
- package/src/commands/graph/diff.js +74 -0
- package/src/commands/graph/status.js +1 -1
- package/src/commands/observability/cost.js +2 -4
- package/src/commands/observability/telemetry.js +1 -1
- package/src/commands/project/doctor.js +23 -39
- package/src/commands/project/fleet.js +5 -6
- package/src/commands/project/init.js +63 -36
- package/src/commands/project/stack-scan.js +3 -42
- package/src/commands/project/stack-set.js +26 -0
- package/src/commands/project/status.js +12 -13
- package/src/commands/project/update.js +39 -3
- package/src/commands/project/worktree.js +3 -14
- package/src/commands/state/advance.js +17 -17
- package/src/commands/state/approve.js +0 -6
- package/src/commands/state/archive.js +27 -1
- package/src/commands/state/auto-approval.js +2 -2
- package/src/commands/state/create.js +1 -6
- package/src/commands/state/gate-check.js +38 -31
- package/src/commands/state/gate-decision.js +3 -2
- package/src/commands/state/next.js +1 -0
- package/src/commands/state/recap.js +67 -0
- package/src/commands/state/report-check.js +36 -178
- package/src/commands/validation/plan-check.js +16 -11
- package/src/commands/validation/validate-feature.js +3 -3
- package/src/commands/validation/verify.js +3 -6
- package/src/core/paths/output-schema.js +3 -3
- package/src/core/state/state-manager.js +2 -4
- package/src/dashboard/app/components/CommandPalette.jsx +2 -5
- package/src/dashboard/app/components/GatePauses.jsx +116 -0
- package/src/dashboard/app/components/SessionMap.jsx +77 -0
- package/src/dashboard/app/pages/Activity.jsx +4 -0
- package/src/dashboard/app/pages/AgentMap.jsx +1 -2
- package/src/dashboard/app/pages/FeatureDetail.jsx +129 -186
- package/src/dashboard/app/pages/Features.jsx +7 -7
- package/src/dashboard/app/pages/PhasePipeline.jsx +1 -1
- package/src/dashboard/app/pages/Portfolio.jsx +40 -5
- package/src/dashboard/scanner/activity-scanner.js +29 -0
- package/src/dashboard/scanner/agents-scanner.js +11 -14
- package/src/dashboard/scanner/features-scanner.js +45 -24
- package/src/dashboard/scanner/project-api.js +11 -2
- package/src/dashboard/scanner/skills-scanner.js +11 -1
- package/src/lib/detectors/index.js +1 -1
- package/src/lib/e2e/applicability.js +3 -1
- package/src/lib/git/tree-state.js +1 -16
- package/src/lib/graph/diff-tree.js +127 -0
- package/src/lib/graph/graphify-runtime.js +12 -5
- package/src/lib/installers/memory-installer.js +3 -3
- package/src/lib/installers/rules-installer.js +57 -0
- package/src/lib/installers/stack-assets.js +17 -0
- package/src/lib/installers/stack-sync.js +219 -0
- package/src/lib/plan/checks.js +61 -109
- package/src/lib/plan/critique.js +28 -0
- package/src/lib/plan/media.js +42 -0
- package/src/lib/plan/plan-html.js +125 -0
- package/src/lib/plan/plan-parser.js +34 -45
- package/src/lib/recap/piper.js +36 -0
- package/src/lib/recap/recap.js +232 -0
- package/src/lib/review-reports.js +28 -4
- package/src/lib/risk-detector.js +90 -11
- package/src/lib/specs/screen-checklist.js +33 -48
- package/src/lib/stack/dotnet-build-ignores.js +8 -9
- package/src/lib/telemetry/metrics.js +27 -29
- package/src/lib/validators/reuse/reuse-validator.js +1 -9
- package/src/lib/validators/verify-runner.js +0 -7
- package/src/lib/worktree/fleet-scanner.js +7 -20
- package/src/lib/worktree/worktree-audit.js +0 -37
- package/src/scripts/setup-infra.js +15 -50
- package/src/utils/agents-installer.js +27 -201
- package/src/utils/hooks-installer.js +11 -95
- package/framework/hooks/claude-code/core/warn-bash-source-write.js +0 -23
- package/framework/hooks/claude-code/statusline.py +0 -699
- package/framework/hooks/claude-code/statusline.sh +0 -11
- package/framework/hooks/shared/agent-reap.js +0 -74
- package/framework/hooks/shared/slice-progress.js +0 -110
- package/framework/skills/core/morph-hotfix/SKILL.md +0 -133
- package/framework/skills/core/morph-machine/SKILL.md +0 -46
- package/framework/skills/core/morph-review/SKILL.md +0 -129
- package/framework/skills/core/morph-standards/SKILL.md +0 -52
- package/framework/standards/PROVENANCE.json +0 -119
- package/framework/standards/infrastructure/neon/neon-pgrag.md +0 -243
- package/src/commands/project/worktree-reap.js +0 -34
- package/src/commands/state/handoff.js +0 -65
- package/src/commands/validation/mutate.js +0 -263
- package/src/commands/validation/scout-check.js +0 -28
- package/src/lib/generators/handoff-generator.js +0 -172
- package/src/lib/mutation/adapters.js +0 -79
- package/src/lib/mutation/commands.js +0 -61
- package/src/lib/mutation/dotnet-introspection.js +0 -281
- package/src/lib/mutation/manifest.js +0 -144
- package/src/lib/mutation/plan.js +0 -44
- package/src/lib/mutation/report.js +0 -68
- package/src/lib/mutation/runner.js +0 -301
- package/src/lib/mutation/schemata.js +0 -60
- package/src/lib/mutation/snapshot.js +0 -65
- package/src/lib/mutation/subset.js +0 -109
- package/src/lib/mutation/trx.js +0 -50
- package/src/lib/scout/scout-check.js +0 -293
- package/src/lib/validators/traceability-check.js +0 -103
- package/src/lib/worktree/agent-reaper.js +0 -247
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "1.0.0",
|
|
3
|
-
"_note": "Standards distilled from an external source. The source is not a dependency at runtime: it lives in another repository and is not needed to use the framework. The same mechanism covers content distilled into a SKILL — an entry declares `standards`, `skills`, or both, and every declared name must resolve. This file exists so drift is detectable instead of silent. Pin `sourceTree` when distilling, and re-pin deliberately after reviewing what changed. See test/framework/standards-provenance.test.js.",
|
|
4
|
-
"sources": [
|
|
5
|
-
{
|
|
6
|
-
"id": "morph-lp-cinematic",
|
|
7
|
-
"repo": "morph-HUB",
|
|
8
|
-
"path": "skills/morph-lp-cinematic",
|
|
9
|
-
"envVar": "MORPH_HUB",
|
|
10
|
-
"defaultCheckout": "R:/Polymorphism Tech/repos/morph-HUB",
|
|
11
|
-
"sourceTree": "2987b44241cae479b1aedc63f689cdcd6ef6fb94",
|
|
12
|
-
"sourceCommit": "c4c9164",
|
|
13
|
-
"distilledOn": "2026-08-21",
|
|
14
|
-
"distilledFrom": [
|
|
15
|
-
"references/build-stack.md",
|
|
16
|
-
"references/component-recipes.md",
|
|
17
|
-
"references/premium-finish.md",
|
|
18
|
-
"references/seo-and-qa.md",
|
|
19
|
-
"references/image-prompt.md",
|
|
20
|
-
"references/seedance-scrub-prompt.md",
|
|
21
|
-
"references/seedance-loop-prompt.md"
|
|
22
|
-
],
|
|
23
|
-
"notDistilled": [
|
|
24
|
-
"references/last-mile.md",
|
|
25
|
-
"references/copy-and-messaging.md",
|
|
26
|
-
"references/section-blueprint.md"
|
|
27
|
-
],
|
|
28
|
-
"notDistilledReason": "Deliberate split: a standard carries knowledge, a skill carries process. Deploy and copy strategy stay with the skill. `references/gates.md` LEFT this list on 2026-09-09: the reason that kept it out was \"a skill carries process\", and the destination is now a skill — see the \"cinematic-lp\" source below, which distils it into morph-media. Review of 2026-09-29 (source c4c9164): only tool-independent facts were ported (the scrub_frames manifest contract for frame-scrub, chained clips for ai-video-generation); the rest was already in the standards or stays with the skill (ffmpeg-to-media_tool swaps, model prices, SKILL.md, gates.md, assets/).",
|
|
29
|
-
"standards": [
|
|
30
|
-
"frontend-scroll-driven-frame-scrub",
|
|
31
|
-
"frontend-scroll-driven-smooth-scroll",
|
|
32
|
-
"frontend-scroll-driven-scroll-components",
|
|
33
|
-
"frontend-design-system-premium-finish",
|
|
34
|
-
"frontend-design-system-ai-image-generation",
|
|
35
|
-
"frontend-design-system-ai-video-generation",
|
|
36
|
-
"frontend-seo-meta-schema-audit"
|
|
37
|
-
],
|
|
38
|
-
"skills": []
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"id": "morph-image",
|
|
42
|
-
"repo": "morph-HUB",
|
|
43
|
-
"path": "skills/morph-image",
|
|
44
|
-
"envVar": "MORPH_HUB",
|
|
45
|
-
"defaultCheckout": "R:/Polymorphism Tech/repos/morph-HUB",
|
|
46
|
-
"sourceTree": "e55dcf307278583120601c3c5d55118302335f7b",
|
|
47
|
-
"sourceCommit": "c4c9164",
|
|
48
|
-
"distilledOn": "2026-09-09",
|
|
49
|
-
"distilledFrom": [
|
|
50
|
-
"SKILL.md"
|
|
51
|
-
],
|
|
52
|
-
"notDistilled": [
|
|
53
|
-
"skill.json",
|
|
54
|
-
"evals/"
|
|
55
|
-
],
|
|
56
|
-
"notDistilledReason": "Manifest and eval fixtures of the source skill: packaging of the origin, not knowledge. The MCP tool names of the source were also NOT carried over — morph-media is about the authoring decisions, and a tool table pinned to one MCP server would rot on its own.",
|
|
57
|
-
"standards": [],
|
|
58
|
-
"skills": [
|
|
59
|
-
"morph-media"
|
|
60
|
-
]
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"id": "cinematic-lp",
|
|
64
|
-
"repo": "morph-HUB",
|
|
65
|
-
"path": "skills/cinematic-lp/references",
|
|
66
|
-
"envVar": "MORPH_HUB",
|
|
67
|
-
"defaultCheckout": "R:/Polymorphism Tech/repos/morph-HUB",
|
|
68
|
-
"sourceTree": "3c557425d649ed477bf6645b9297b6d1d72ae4a3",
|
|
69
|
-
"sourceCommit": "c4c9164",
|
|
70
|
-
"distilledOn": "2026-09-09",
|
|
71
|
-
"distilledFrom": [
|
|
72
|
-
"gates.md"
|
|
73
|
-
],
|
|
74
|
-
"notDistilled": [
|
|
75
|
-
"build-stack.md",
|
|
76
|
-
"component-recipes.md",
|
|
77
|
-
"copy-and-messaging.md",
|
|
78
|
-
"image-prompt.md",
|
|
79
|
-
"last-mile.md",
|
|
80
|
-
"mcp-setup.md",
|
|
81
|
-
"premium-finish.md",
|
|
82
|
-
"section-blueprint.md",
|
|
83
|
-
"seo-and-qa.md",
|
|
84
|
-
"video-loop-examples.md",
|
|
85
|
-
"video-loop-prompt.md",
|
|
86
|
-
"video-scrub-prompt.md"
|
|
87
|
-
],
|
|
88
|
-
"notDistilledReason": "Only the HITL gate mechanics were distilled: the N-option picker, \"rejection goes back to the same step\", and \"show MOVEMENT, never a still\". The rest is either already a standard (the frame-scrub / smooth-scroll / premium-finish family, from the morph-lp-cinematic source above) or build/deploy strategy that belongs to the calling workflow. Review of 2026-09-29 (source c4c9164): gates.md did not change; the changes were in image-prompt.md and mcp-setup.md, both not distilled. Re-pinned only.",
|
|
89
|
-
"standards": [],
|
|
90
|
-
"skills": [
|
|
91
|
-
"morph-media"
|
|
92
|
-
]
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
"id": "brand-design",
|
|
96
|
-
"repo": "morph-HUB",
|
|
97
|
-
"path": "skills/brand-design/references",
|
|
98
|
-
"envVar": "MORPH_HUB",
|
|
99
|
-
"defaultCheckout": "R:/Polymorphism Tech/repos/morph-HUB",
|
|
100
|
-
"sourceTree": "7b637a08e931d8b7ba5be7fc75b851d89cd6e6f4",
|
|
101
|
-
"sourceCommit": "c4c9164",
|
|
102
|
-
"distilledOn": "2026-09-09",
|
|
103
|
-
"distilledFrom": [
|
|
104
|
-
"image-generation.md"
|
|
105
|
-
],
|
|
106
|
-
"notDistilled": [
|
|
107
|
-
"brand-book.md",
|
|
108
|
-
"checklist.md",
|
|
109
|
-
"example-identidade-visual.md",
|
|
110
|
-
"phases.md"
|
|
111
|
-
],
|
|
112
|
-
"notDistilledReason": "Only the image-per-phase map and the \"concept, never the final vector\" rule were distilled. The narrative prompt recipes were NOT copied verbatim: they are bound to one brand pipeline, and morph-media carries the prompt STRUCTURE instead, which survives the model changing. Brand book, checklist and phases are the process of another skill. Review of 2026-09-29 (source c4c9164): the image-per-phase table and the \"concept, never the final vector\" rule are unchanged (the text now says \"image model\" instead of Gemini); what was added is morph-assets call mechanics (project_set, @brand, outputPath, models, variants, dryRun), tool-bound and kept out on purpose. Re-pinned only.",
|
|
113
|
-
"standards": [],
|
|
114
|
-
"skills": [
|
|
115
|
-
"morph-media"
|
|
116
|
-
]
|
|
117
|
-
}
|
|
118
|
-
]
|
|
119
|
-
}
|
|
@@ -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 |
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { reapAgentWorktrees } from '../../lib/worktree/agent-reaper.js';
|
|
3
|
-
|
|
4
|
-
const label = (item) => item.path ?? item.branch ?? item.hex;
|
|
5
|
-
|
|
6
|
-
function printReport(out) {
|
|
7
|
-
const mode = out.dryRun ? ' (simulação)' : '';
|
|
8
|
-
console.log(chalk.bold(`\nWorktrees de sub-agent${mode} — graça de ${out.graceMinutes} min\n`));
|
|
9
|
-
if (out.busy) console.log(chalk.yellow(' ⏳ outro reaper está em execução; nada foi feito\n'));
|
|
10
|
-
|
|
11
|
-
for (const item of out.wouldReap ?? []) console.log(chalk.cyan(` → removeria: ${label(item)}`));
|
|
12
|
-
for (const item of out.reaped) console.log(chalk.green(` ✓ removido: ${label(item)}${item.backup ? chalk.gray(` (backup: ${item.backup})`) : ''}`));
|
|
13
|
-
for (const item of out.preserved) {
|
|
14
|
-
console.log(chalk.yellow(` ⚠ preservado: ${label(item)} — ${item.reason}${item.detail ? `: ${item.detail}` : ''}`));
|
|
15
|
-
}
|
|
16
|
-
if (out.active) console.log(chalk.gray(` ${out.active} agente(s) ainda ativo(s), intocado(s)`));
|
|
17
|
-
const nothing = !out.reaped.length && !out.preserved.length && !out.active && !(out.wouldReap ?? []).length;
|
|
18
|
-
if (nothing && !out.busy) console.log(chalk.green(' ✓ nenhuma worktree de sub-agent sobrando'));
|
|
19
|
-
console.log();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function worktreeReapCommand(options = {}) {
|
|
23
|
-
const grace = options.grace === undefined ? undefined : Number(options.grace);
|
|
24
|
-
if (grace !== undefined && !(Number.isFinite(grace) && grace >= 0)) {
|
|
25
|
-
console.error(chalk.red(`--grace precisa ser um número de minutos >= 0 (recebi "${options.grace}")`));
|
|
26
|
-
process.exit(2);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const out = await reapAgentWorktrees(options.cwd || process.cwd(), { dryRun: options.dryRun === true, graceMinutes: grace });
|
|
30
|
-
if (options.json) console.log(JSON.stringify(out));
|
|
31
|
-
else if (out.ok) printReport(out);
|
|
32
|
-
else console.log(chalk.gray(` fora de um repositório git — nada a fazer (${out.error})`));
|
|
33
|
-
return out;
|
|
34
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { buildHandoff, writeHandoff } from '../../lib/generators/handoff-generator.js';
|
|
3
|
-
import { resolveFeatureTree } from '../../lib/worktree/feature-truth.js';
|
|
4
|
-
|
|
5
|
-
// With a live worktree the root copy is a stale birth skeleton: build and write in the
|
|
6
|
-
// owning tree (`resolveFeatureTree`) unless `--here` forces the cwd.
|
|
7
|
-
export function handoffCommand(featureName, options = {}) {
|
|
8
|
-
const cwd = process.cwd();
|
|
9
|
-
|
|
10
|
-
const owner = options.here ? { source: 'cwd', tree: cwd, branch: null, worktree: null } : resolveFeatureTree(featureName, cwd);
|
|
11
|
-
|
|
12
|
-
if (owner.source === 'none') {
|
|
13
|
-
if (options.json) {
|
|
14
|
-
console.log(JSON.stringify({ error: 'feature-not-found', feature: featureName }));
|
|
15
|
-
} else {
|
|
16
|
-
console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
|
|
17
|
-
}
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (owner.source === 'branch-only') {
|
|
22
|
-
// The handoff points at files on disk; a truth materialized in no tree is refused.
|
|
23
|
-
const hint = `morph-spec worktree setup ${featureName} (ou: git checkout ${owner.branch})`;
|
|
24
|
-
if (options.json) {
|
|
25
|
-
console.log(JSON.stringify({ error: 'feature-not-in-tree', feature: featureName, branch: owner.branch, hint }));
|
|
26
|
-
} else {
|
|
27
|
-
console.error(chalk.red(`\n❌ "${featureName}" está commitada em \`${owner.branch}\`, mas não está materializada em árvore nenhuma.`));
|
|
28
|
-
console.error(chalk.gray(` ${hint}\n`));
|
|
29
|
-
}
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const tree = owner.tree;
|
|
34
|
-
const result = buildHandoff(featureName, tree, { worktree: owner.worktree });
|
|
35
|
-
if (!result) {
|
|
36
|
-
if (options.json) {
|
|
37
|
-
console.log(JSON.stringify({ error: 'feature-not-found', feature: featureName, tree }));
|
|
38
|
-
} else {
|
|
39
|
-
console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
|
|
40
|
-
}
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const path = writeHandoff(featureName, tree, { worktree: owner.worktree });
|
|
45
|
-
if (!path) {
|
|
46
|
-
if (options.json) {
|
|
47
|
-
console.log(JSON.stringify({ error: 'write-failed', feature: featureName, tree }));
|
|
48
|
-
} else {
|
|
49
|
-
console.error(chalk.red(`\n❌ Could not write handoff.md for ${featureName}\n`));
|
|
50
|
-
}
|
|
51
|
-
process.exit(1);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (options.json) {
|
|
55
|
-
console.log(JSON.stringify({ path, feature: featureName, tree, source: owner.source, ...result.meta }));
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
console.log(chalk.green(`\n✅ Handoff gerado: ${path}`));
|
|
60
|
-
if (tree !== cwd) {
|
|
61
|
-
console.log(chalk.yellow(` resolvido para ${tree} — a cópia da raiz é esqueleto de nascimento, não a verdade.`));
|
|
62
|
-
}
|
|
63
|
-
console.log(chalk.gray(` fase ${result.meta.phase} · fatias ${result.meta.slicesDone}/${result.meta.slicesTotal} · ${result.meta.generatedAt}`));
|
|
64
|
-
console.log(chalk.gray(' A próxima sessão lê este documento antes de continuar (ponteiros, não cópias).\n'));
|
|
65
|
-
}
|