@polymorphism-tech/morph-spec 4.21.0 → 5.0.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 +57 -71
- package/README.md +2 -2
- package/bin/morph-spec.js +224 -491
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +55 -38
- package/framework/MORPH.md +244 -0
- package/framework/agents.json +127 -1183
- package/framework/commands/morph-apply.md +56 -240
- package/framework/commands/morph-archive.md +48 -85
- package/framework/commands/morph-preflight.md +7 -7
- package/framework/commands/morph-proposal.md +35 -191
- package/framework/commands/morph-status.md +19 -50
- package/framework/commands/morph-troubleshoot.md +2 -2
- package/framework/evals/rubrics/README.md +44 -0
- package/framework/evals/rubrics/architecture.md +46 -0
- package/framework/evals/rubrics/code-quality.md +50 -0
- package/framework/evals/rubrics/contracts.md +47 -0
- package/framework/evals/rubrics/test-coverage.md +50 -0
- package/framework/evals/scenarios/dotnet-crud.yaml +42 -0
- package/framework/evals/scenarios/nextjs-auth.yaml +38 -0
- package/framework/evals/suites/standard.yaml +5 -0
- package/framework/evals/trace-schema.md +67 -0
- package/framework/hooks/claude-code/core/README.md +3 -0
- package/framework/hooks/claude-code/core/denylist.json +14 -0
- package/framework/hooks/claude-code/{pre-tool-use → core}/enforce-phase-writes.js +5 -5
- package/framework/hooks/claude-code/core/post-edit-typecheck.js +69 -0
- package/framework/hooks/claude-code/core/pre-bash-denylist.js +29 -0
- package/framework/hooks/claude-code/{pre-tool-use → core}/protect-spec-files.js +4 -6
- package/framework/hooks/claude-code/{stop → core}/validate-completion.js +13 -82
- package/framework/hooks/shared/phase-utils.js +20 -28
- package/framework/hooks/shared/state-reader.js +4 -5
- package/framework/{skills/level-0-meta/mcp-registry.json → mcp/registry.json} +254 -210
- package/framework/phases.json +40 -114
- package/framework/rubrics/eval-rubric.json +66 -0
- package/framework/skills/README.md +39 -64
- package/framework/skills/core/README.md +3 -0
- package/framework/skills/core/morph-brainstorming/SKILL.md +102 -0
- package/framework/skills/core/morph-eval/SKILL.md +57 -0
- package/framework/skills/core/morph-implement/SKILL.md +83 -0
- package/framework/skills/core/morph-plan/SKILL.md +64 -0
- package/framework/skills/core/morph-review/SKILL.md +62 -0
- package/framework/skills/core/morph-stack-scan/SKILL.md +109 -0
- package/framework/skills/core/morph-standards/SKILL.md +49 -0
- package/framework/standards/STANDARDS.json +32 -0
- package/framework/standards/frontend/design-system/ai-image-generation.md +244 -0
- package/framework/standards/integration/mcp/mcp-tools.md +48 -0
- package/framework/templates/CLAUDE.md.core.guide.md +29 -0
- package/framework/templates/CLAUDE.md.core.template +22 -0
- package/framework/templates/REGISTRY.json +4 -4
- package/framework/workflows/configs/fast-track.json +5 -10
- package/framework/workflows/configs/full.json +4 -8
- package/framework/workflows/configs/quick.json +32 -0
- package/framework/workflows/configs/standard.json +57 -64
- package/package.json +7 -6
- package/src/commands/mcp/mcp-setup.js +58 -31
- package/src/commands/project/doctor.js +69 -70
- package/src/commands/project/init.js +26 -5
- package/src/commands/project/status.js +18 -19
- package/src/commands/state/approve.js +1 -1
- package/src/commands/validation/validate-feature.js +18 -112
- package/src/core/paths/output-schema.js +133 -151
- package/src/core/state/phase-state-machine.js +10 -24
- package/src/core/state/state-manager.js +17 -17
- package/src/core/workflows/workflow-detector.js +214 -31
- package/src/core/workflows/workflow-router.js +204 -0
- package/src/dashboard/app/pages/AgentMap.jsx +32 -33
- package/src/dashboard/app/pages/LiveState.jsx +1 -1
- package/src/dashboard/app/pages/PhasePipeline.jsx +2 -4
- package/src/dashboard/app/pages/SkillsLibrary.jsx +2 -3
- package/src/dashboard/app/pages/Workflows.jsx +2 -2
- package/src/dashboard/scanner/agents-scanner.js +30 -35
- package/src/lib/agents/metrics-aggregator.js +1 -1
- package/src/lib/agents/output-collector.js +7 -8
- package/src/lib/context/context-builder.js +289 -0
- package/src/lib/detectors/claude-config-detector.js +19 -3
- package/src/lib/generators/context-generator.js +20 -42
- package/src/lib/generators/index.js +1 -0
- package/src/lib/generators/mandate-generator.js +512 -0
- package/src/lib/generators/metadata-extractor.js +1 -1
- package/src/lib/generators/recap-generator.js +3 -4
- package/src/lib/installers/mcp-installer.js +300 -92
- package/src/lib/phase-chain/phase-validator.js +36 -40
- package/src/lib/stack/stack-profile.js +74 -91
- package/src/lib/tasks/task-parser.js +1 -1
- package/src/lib/tasks/wave-resolver.js +353 -0
- package/src/lib/validators/checkpoint-persistence.js +2 -2
- package/src/lib/validators/content/cross-phase-validator.js +281 -0
- package/src/lib/validators/content/index.js +1 -0
- package/src/lib/validators/shared/emit-validator-dispatch.js +6 -56
- package/src/scripts/global-install.js +2 -27
- package/src/utils/agents-installer.js +224 -447
- package/src/utils/claude-settings-manager.js +57 -15
- package/src/utils/file-copier.js +1 -0
- package/src/utils/hooks-installer.js +15 -117
- package/src/utils/skills-installer.js +12 -18
- package/bin/detect-agents.js +0 -226
- package/bin/task-manager.js +0 -1036
- package/framework/agents/README.md +0 -13
- package/framework/agents/ai-agents/ai-system-architect.md +0 -194
- package/framework/agents/ai-agents/vector-search-expert.md +0 -247
- package/framework/agents/architecture/architecture-expert.md +0 -98
- package/framework/agents/architecture/morph-spec-architect.md +0 -66
- package/framework/agents/architecture/packages-validator.md +0 -89
- package/framework/agents/architecture/security-expert.md +0 -79
- package/framework/agents/architecture/seo-growth-hacker.md +0 -168
- package/framework/agents/architecture/standards-architect.md +0 -153
- package/framework/agents/backend/dotnet-senior.md +0 -163
- package/framework/agents/backend/ef-modeler.md +0 -119
- package/framework/agents/backend/hangfire-orchestrator.md +0 -133
- package/framework/agents/backend/ms-agent-expert.md +0 -55
- package/framework/agents/backend/neon-expert.md +0 -379
- package/framework/agents/frontend/css-specialist.md +0 -89
- package/framework/agents/frontend/design-system-validator.md +0 -100
- package/framework/agents/frontend/gsap-animator.md +0 -131
- package/framework/agents/frontend/nextjs-component-validator.md +0 -97
- package/framework/agents/frontend/nextjs-expert.md +0 -201
- package/framework/agents/frontend/ui-designer.md +0 -259
- package/framework/agents/infrastructure/infra-architect.md +0 -215
- package/framework/agents/integrations/asaas-financial.md +0 -138
- package/framework/agents/integrations/neon-auth.md +0 -151
- package/framework/agents/integrations/resend-email.md +0 -127
- package/framework/hooks/claude-code/post-tool-use/agent-complete.js +0 -122
- package/framework/hooks/claude-code/post-tool-use/dispatch.js +0 -363
- package/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +0 -78
- package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +0 -194
- package/framework/hooks/claude-code/pre-compact/save-morph-context.js +0 -199
- package/framework/hooks/claude-code/pre-tool-use/task-tracking-guard.js +0 -55
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +0 -323
- package/framework/hooks/claude-code/session-start/post-compact-restore.js +0 -41
- package/framework/hooks/claude-code/session-start/resume-context.js +0 -77
- package/framework/hooks/claude-code/teammate-idle/teammate-idle.js +0 -90
- package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +0 -114
- package/framework/hooks/shared/compact-restore.js +0 -123
- package/framework/hooks/shared/dispatch-helpers.js +0 -147
- package/framework/hooks/shared/skill-reminder-helpers.js +0 -79
- package/framework/hooks/shared/stale-task-reset.js +0 -57
- package/framework/hooks/shared/worktree-helpers.js +0 -75
- package/framework/skills/level-0-meta/README.md +0 -7
- package/framework/skills/level-0-meta/morph-agent-teams/SKILL.md +0 -472
- package/framework/skills/level-0-meta/morph-brainstorming/SKILL.md +0 -174
- package/framework/skills/level-0-meta/morph-brainstorming/references/proposal-example.md +0 -138
- package/framework/skills/level-0-meta/morph-checklist/SKILL.md +0 -145
- package/framework/skills/level-0-meta/morph-code-review/SKILL.md +0 -250
- package/framework/skills/level-0-meta/morph-code-review/references/review-example.md +0 -164
- package/framework/skills/level-0-meta/morph-code-review/references/review-guidelines.md +0 -100
- package/framework/skills/level-0-meta/morph-code-review/scripts/scan-csharp.mjs +0 -151
- package/framework/skills/level-0-meta/morph-code-review-nextjs/SKILL.md +0 -165
- package/framework/skills/level-0-meta/morph-code-review-nextjs/references/review-example-nextjs.md +0 -254
- package/framework/skills/level-0-meta/morph-code-review-nextjs/scripts/scan-nextjs.mjs +0 -189
- package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +0 -344
- package/framework/skills/level-0-meta/morph-frontend-review/scripts/scan-accessibility.mjs +0 -376
- package/framework/skills/level-0-meta/morph-init/SKILL.md +0 -537
- package/framework/skills/level-0-meta/morph-parallel-dispatch/SKILL.md +0 -225
- package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +0 -382
- package/framework/skills/level-0-meta/morph-post-implementation/scripts/detect-dev-server.mjs +0 -153
- package/framework/skills/level-0-meta/morph-post-implementation/scripts/detect-stack.mjs +0 -234
- package/framework/skills/level-0-meta/morph-simulation-checklist/SKILL.md +0 -106
- package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +0 -243
- package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +0 -169
- package/framework/skills/level-0-meta/morph-verification-before-completion/SKILL.md +0 -148
- package/framework/skills/level-0-meta/morph-verification-before-completion/scripts/check-phase-outputs.mjs +0 -110
- package/framework/skills/level-1-workflows/README.md +0 -7
- package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +0 -269
- package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +0 -453
- package/framework/skills/level-1-workflows/morph-phase-design/references/architecture-analysis-guide.md +0 -44
- package/framework/skills/level-1-workflows/morph-phase-design/references/spec-authoring-guide.md +0 -55
- package/framework/skills/level-1-workflows/morph-phase-design/references/spec-example.md +0 -253
- package/framework/skills/level-1-workflows/morph-phase-implement/.morph/logs/activity.json +0 -38
- package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +0 -493
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/code-quality-reviewer-prompt.md +0 -50
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/implementer-prompt.md +0 -46
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/spec-reviewer-prompt.md +0 -47
- package/framework/skills/level-1-workflows/morph-phase-implement/references/recap-example.md +0 -132
- package/framework/skills/level-1-workflows/morph-phase-implement/references/vsa-implementation-guide.md +0 -92
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +0 -257
- package/framework/skills/level-1-workflows/morph-phase-tasks/.morph/logs/activity.json +0 -14
- package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +0 -291
- package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +0 -143
- package/framework/skills/level-1-workflows/morph-phase-tasks/references/tasks-example.md +0 -404
- package/framework/skills/level-1-workflows/morph-phase-tasks/scripts/validate-tasks.mjs +0 -112
- package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +0 -788
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +0 -147
- package/framework/squad-templates/backend-only.json +0 -47
- package/framework/squad-templates/frontend-only.json +0 -56
- package/framework/squad-templates/full-stack.json +0 -74
- package/src/commands/agents/agent-metrics.js +0 -174
- package/src/commands/agents/audit-dispatch.js +0 -82
- package/src/commands/agents/detect-agents.js +0 -275
- package/src/commands/agents/dispatch-agents.js +0 -461
- package/src/commands/agents/index.js +0 -13
- package/src/commands/agents/manage-agents.js +0 -352
- package/src/commands/agents/project-metrics.js +0 -74
- package/src/commands/phase/phase-reset.js +0 -74
- package/src/commands/scope/escalate.js +0 -217
- package/src/commands/state/advance-phase.js +0 -600
- package/src/commands/state/phase-runner.js +0 -215
- package/src/commands/state/state.js +0 -444
- package/src/commands/task/expand.js +0 -100
- package/src/commands/tasks/index.js +0 -4
- package/src/commands/tasks/task.js +0 -105
- package/src/commands/templates/index.js +0 -5
- package/src/commands/templates/template-render.js +0 -93
- package/src/commands/trust/trust.js +0 -118
- package/src/lib/agents/agents-manager.js +0 -349
- package/src/lib/build/build-runner.js +0 -99
- package/src/lib/checkpoints/checkpoint-hooks.js +0 -111
- package/src/lib/contracts/sprint-contract-generator.js +0 -137
- package/src/lib/scope/impact-analyzer.js +0 -106
- package/src/lib/trust/trust-manager.js +0 -157
- package/src/utils/tier-helpers.js +0 -24
- /package/framework/hooks/claude-code/{post-tool-use → core}/loop-detect.js +0 -0
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ef-modeler
|
|
3
|
-
description: Entity Framework Modeler specialist for database schema design, EF Core migrations, DbContext configuration, and ORM patterns including IDbContextFactory. Use when designing database models, creating EF Core migrations, configuring DbContext, or implementing repository patterns with EF Core.
|
|
4
|
-
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
-
stacks:
|
|
6
|
-
- dotnet
|
|
7
|
-
color: teal
|
|
8
|
-
effort: medium
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# EF Modeler
|
|
12
|
-
|
|
13
|
-
Entity Framework Core specialist for database modeling, entities, configurations, and migrations.
|
|
14
|
-
|
|
15
|
-
## Standards
|
|
16
|
-
|
|
17
|
-
*(No external standard files — patterns are embedded in this agent prompt.)*
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Entity Pattern
|
|
22
|
-
|
|
23
|
-
```csharp
|
|
24
|
-
// Private setters + factory method + domain state methods
|
|
25
|
-
public sealed class ProcessingJob
|
|
26
|
-
{
|
|
27
|
-
private ProcessingJob() { } // EF constructor
|
|
28
|
-
|
|
29
|
-
public Guid Id { get; private set; }
|
|
30
|
-
public string OriginalPhotoUrl { get; private set; } = default!;
|
|
31
|
-
public string? ProcessedPhotoUrl { get; private set; }
|
|
32
|
-
public ProcessingStatus Status { get; private set; }
|
|
33
|
-
public int RetryCount { get; private set; }
|
|
34
|
-
public DateTime CreatedAt { get; private set; }
|
|
35
|
-
public DateTime UpdatedAt { get; private set; }
|
|
36
|
-
|
|
37
|
-
// Factory method — enforces invariants at creation
|
|
38
|
-
public static ProcessingJob Create(string originalPhotoUrl)
|
|
39
|
-
{
|
|
40
|
-
ArgumentException.ThrowIfNullOrEmpty(originalPhotoUrl);
|
|
41
|
-
return new() { Id = Guid.NewGuid(), OriginalPhotoUrl = originalPhotoUrl,
|
|
42
|
-
Status = ProcessingStatus.Pending, CreatedAt = DateTime.UtcNow,
|
|
43
|
-
UpdatedAt = DateTime.UtcNow };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Domain state methods — encapsulate transitions
|
|
47
|
-
public void MarkProcessing() => (Status, UpdatedAt) = (ProcessingStatus.Processing, DateTime.UtcNow);
|
|
48
|
-
|
|
49
|
-
public void MarkCompleted(string processedUrl)
|
|
50
|
-
{
|
|
51
|
-
ProcessedPhotoUrl = processedUrl;
|
|
52
|
-
Status = ProcessingStatus.Completed;
|
|
53
|
-
UpdatedAt = DateTime.UtcNow;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
public void MarkFailed() { RetryCount++; Status = RetryCount >= 3 ? ProcessingStatus.Failed : ProcessingStatus.Pending;
|
|
57
|
-
UpdatedAt = DateTime.UtcNow; }
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Configuration Pattern
|
|
62
|
-
|
|
63
|
-
```csharp
|
|
64
|
-
// One IEntityTypeConfiguration per entity — never configure in OnModelCreating
|
|
65
|
-
public sealed class ProcessingJobConfiguration : IEntityTypeConfiguration<ProcessingJob>
|
|
66
|
-
{
|
|
67
|
-
public void Configure(EntityTypeBuilder<ProcessingJob> builder)
|
|
68
|
-
{
|
|
69
|
-
builder.HasKey(j => j.Id);
|
|
70
|
-
builder.Property(j => j.OriginalPhotoUrl).HasMaxLength(500).IsRequired();
|
|
71
|
-
builder.Property(j => j.ProcessedPhotoUrl).HasMaxLength(500);
|
|
72
|
-
builder.Property(j => j.Status).HasConversion<int>();
|
|
73
|
-
builder.Property(j => j.CreatedAt).HasDefaultValueSql("GETUTCDATE()");
|
|
74
|
-
builder.HasIndex(j => j.Status); // index frequently filtered columns
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Migration Checklist
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
# 1. Create migration
|
|
83
|
-
dotnet ef migrations add AddProcessingJob --project src/Infrastructure --startup-project src/Web
|
|
84
|
-
|
|
85
|
-
# 2. Review generated migration — check Up() and Down() for correctness
|
|
86
|
-
# 3. Apply
|
|
87
|
-
dotnet ef database update --project src/Infrastructure --startup-project src/Web
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
- Never use `EnsureCreated()` in production — always explicit migrations
|
|
91
|
-
- Never edit a migration that's been applied to a shared environment — add a new one
|
|
92
|
-
- Soft-delete columns: add nullable `DeletedAt`, filter in repository (`HasQueryFilter`)
|
|
93
|
-
|
|
94
|
-
## IDbContextFactory (Background Jobs)
|
|
95
|
-
|
|
96
|
-
```csharp
|
|
97
|
-
// DbContext is HTTP-scoped — background jobs MUST use IDbContextFactory
|
|
98
|
-
public class PhotoProcessingJob(IDbContextFactory<AppDbContext> dbFactory)
|
|
99
|
-
{
|
|
100
|
-
public async Task ProcessAsync(Guid jobId, CancellationToken ct)
|
|
101
|
-
{
|
|
102
|
-
await using var db = await dbFactory.CreateDbContextAsync(ct);
|
|
103
|
-
var job = await db.ProcessingJobs.FindAsync([jobId], ct)
|
|
104
|
-
?? throw new InvalidOperationException($"Job {jobId} not found");
|
|
105
|
-
job.MarkProcessing();
|
|
106
|
-
await db.SaveChangesAsync(ct);
|
|
107
|
-
// ... process ...
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Collaborates With
|
|
113
|
-
|
|
114
|
-
- **dotnet-senior** — service layer consuming repositories
|
|
115
|
-
- **infra-architect** — Database provisioning (Docker/EasyPanel)
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: hangfire-orchestrator
|
|
3
|
-
description: Hangfire Orchestrator specialist for background job design, recurring task scheduling, queue management, and idempotent job patterns in .NET. Use when implementing background jobs, scheduling recurring tasks, managing job queues, or integrating Hangfire with .NET services.
|
|
4
|
-
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
-
stacks:
|
|
6
|
-
- hangfire
|
|
7
|
-
color: teal
|
|
8
|
-
effort: medium
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Hangfire Orchestrator
|
|
12
|
-
|
|
13
|
-
Especialista em background jobs, tarefas agendadas e processamento assíncrono com Hangfire.
|
|
14
|
-
|
|
15
|
-
## .NET 10 Compatibility
|
|
16
|
-
- Hangfire.AspNetCore: **>= 1.8.22** (required for .NET 10)
|
|
17
|
-
|
|
18
|
-
## Why Hangfire
|
|
19
|
-
|
|
20
|
-
| Aspect | Benefit |
|
|
21
|
-
|--------|---------|
|
|
22
|
-
| Cost | Free (in-process, no external service) |
|
|
23
|
-
| Dashboard | Built-in web UI |
|
|
24
|
-
| Debugging | Local debugging, no emulator needed |
|
|
25
|
-
| Complexity | Low — runs inside your .NET app |
|
|
26
|
-
| Deployment | Works with any hosting (Docker, EasyPanel, VPS) |
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Setup
|
|
31
|
-
|
|
32
|
-
```csharp
|
|
33
|
-
// Program.cs
|
|
34
|
-
builder.Services.AddHangfire(config => config
|
|
35
|
-
.SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
|
|
36
|
-
.UseSimpleAssemblyNameTypeSerializer()
|
|
37
|
-
.UseRecommendedSerializerSettings()
|
|
38
|
-
.UseSqlServerStorage(connString, new SqlServerStorageOptions
|
|
39
|
-
{
|
|
40
|
-
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
|
|
41
|
-
QueuePollInterval = TimeSpan.Zero,
|
|
42
|
-
UseRecommendedIsolationLevel = true,
|
|
43
|
-
DisableGlobalLocks = true
|
|
44
|
-
}));
|
|
45
|
-
|
|
46
|
-
builder.Services.AddHangfireServer(options =>
|
|
47
|
-
{
|
|
48
|
-
options.WorkerCount = Environment.ProcessorCount * 2;
|
|
49
|
-
options.Queues = new[] { "critical", "default", "low" };
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
app.UseHangfireDashboard("/hangfire", new DashboardOptions
|
|
53
|
-
{
|
|
54
|
-
Authorization = new[] { new HangfireAuthorizationFilter() }
|
|
55
|
-
});
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Job Types
|
|
59
|
-
|
|
60
|
-
| Type | API | Example |
|
|
61
|
-
|------|-----|---------|
|
|
62
|
-
| **Fire-and-Forget** | `BackgroundJob.Enqueue<T>(...)` | Send email |
|
|
63
|
-
| **Delayed** | `BackgroundJob.Schedule<T>(..., TimeSpan)` | Abandoned cart check |
|
|
64
|
-
| **Recurring** | `RecurringJob.AddOrUpdate<T>(..., cron)` | Daily report |
|
|
65
|
-
| **Continuation** | `BackgroundJob.ContinueJobWith(id, ...)` | Post-import notify |
|
|
66
|
-
|
|
67
|
-
### Common Cron Expressions
|
|
68
|
-
`"0 * * * *"` hourly | `"*/5 * * * *"` every 5m | `"0 8 * * 1-5"` 8am weekdays | `"0 0 1 * *"` monthly
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## CRITICAL: Scoped Repository Pattern
|
|
73
|
-
|
|
74
|
-
**Hangfire jobs run OUTSIDE the HTTP request.** The scoped DbContext does NOT exist.
|
|
75
|
-
|
|
76
|
-
```csharp
|
|
77
|
-
// ✅ ALWAYS use Factory
|
|
78
|
-
public class OrderProcessorJob(IOrderRepositoryFactory repoFactory, ILogger<OrderProcessorJob> logger)
|
|
79
|
-
{
|
|
80
|
-
[AutomaticRetry(Attempts = 3, DelaysInSeconds = new[] { 60, 300, 900 })]
|
|
81
|
-
public async Task ProcessAsync(Guid orderId, CancellationToken ct)
|
|
82
|
-
{
|
|
83
|
-
await using var repo = repoFactory.CreateScoped(); // Isolated DbContext
|
|
84
|
-
var order = await repo.GetByIdAsync(orderId, ct);
|
|
85
|
-
if (order == null || order.Status >= OrderStatus.Completed) return; // Idempotent
|
|
86
|
-
order.MarkAsProcessed();
|
|
87
|
-
await repo.UpdateAsync(order, ct);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// ❌ NEVER inject repository directly — DbContext will be disposed
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Retry & Error Handling
|
|
95
|
-
|
|
96
|
-
```csharp
|
|
97
|
-
[AutomaticRetry(Attempts = 5, DelaysInSeconds = new[] { 60, 300, 900, 3600, 7200 })]
|
|
98
|
-
[Queue("critical")]
|
|
99
|
-
public async Task ProcessPaymentAsync(int orderId)
|
|
100
|
-
{
|
|
101
|
-
try { await _paymentService.ProcessAsync(orderId); }
|
|
102
|
-
catch (PaymentGatewayException ex) { _logger.LogWarning(ex, "..."); throw; } // Rethrow for retry
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## Dashboard Authorization
|
|
107
|
-
|
|
108
|
-
```csharp
|
|
109
|
-
public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter
|
|
110
|
-
{
|
|
111
|
-
public bool Authorize(DashboardContext context)
|
|
112
|
-
{
|
|
113
|
-
var http = context.GetHttpContext();
|
|
114
|
-
return http.User.Identity?.IsAuthenticated == true && http.User.IsInRole("Admin");
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## Checklist
|
|
122
|
-
- [ ] Uses `IRepositoryFactory` (NOT direct repository)
|
|
123
|
-
- [ ] `await using` for dispose
|
|
124
|
-
- [ ] Job is idempotent (safe to retry)
|
|
125
|
-
- [ ] AutomaticRetry configured
|
|
126
|
-
- [ ] Queue defined (critical/default/low)
|
|
127
|
-
- [ ] CancellationToken propagated
|
|
128
|
-
- [ ] Dashboard protected with auth
|
|
129
|
-
- [ ] Timezone set for recurring jobs
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ms-agent-expert
|
|
3
|
-
description: Microsoft Agent Framework Expert for Semantic Kernel, AI extensions, function calling, MCP/A2A protocols, and agentic pipeline implementation. Use when building AI agents with Semantic Kernel, implementing tool/plugin calling, designing multi-agent workflows, or integrating LLMs with .NET services.
|
|
4
|
-
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
-
stacks:
|
|
6
|
-
- dotnet
|
|
7
|
-
- semantic-kernel
|
|
8
|
-
- ms-agents
|
|
9
|
-
color: yellow
|
|
10
|
-
effort: medium
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Agent Framework Expert
|
|
14
|
-
|
|
15
|
-
## Identity
|
|
16
|
-
|
|
17
|
-
Microsoft Agent Framework specialist for .NET 10. Implements AI agents, tools, workflows, and middleware.
|
|
18
|
-
|
|
19
|
-
## Knowledge Base (Consult These)
|
|
20
|
-
|
|
21
|
-
- `framework/standards/ai-agents/setup.md` - Agent configuration, DI, tools, streaming
|
|
22
|
-
- `framework/standards/ai-agents/workflows.md` - Sequential, parallel, conditional workflows
|
|
23
|
-
- `framework/standards/ai-agents/production.md` - Middleware, A2A, MCP, caching, observability
|
|
24
|
-
|
|
25
|
-
## Responsibilities
|
|
26
|
-
|
|
27
|
-
- Configure agents per setup.md patterns (ChatClientAgent, keyed services)
|
|
28
|
-
- Design workflows per workflows.md orchestration patterns
|
|
29
|
-
- Implement middleware per production.md (error handling, logging, retry)
|
|
30
|
-
- Use recommended models from setup.md (gpt-4o-mini default)
|
|
31
|
-
|
|
32
|
-
## Prompt Template
|
|
33
|
-
|
|
34
|
-
When working on AI agent tasks:
|
|
35
|
-
1. Consult `setup.md` for agent configuration, tools, and DI registration
|
|
36
|
-
2. Follow `workflows.md` for orchestration (sequential, parallel, conditional)
|
|
37
|
-
3. Apply `production.md` for middleware, observability, and production patterns
|
|
38
|
-
4. Use Microsoft.Extensions.AI for IChatClient/IEmbeddingGenerator abstractions (stable). MAF packages (`Microsoft.Agents.AI.*`) are not yet published on NuGet — use `IChatClient` directly until MAF reaches GA.
|
|
39
|
-
|
|
40
|
-
## When to Use
|
|
41
|
-
|
|
42
|
-
- AI/LLM integration requests
|
|
43
|
-
- Agent workflow design
|
|
44
|
-
- Tool/function calling implementation
|
|
45
|
-
- Agent middleware and observability
|
|
46
|
-
|
|
47
|
-
## Collaborates With
|
|
48
|
-
|
|
49
|
-
- ai-system-architect - Overall AI strategy
|
|
50
|
-
- dotnet-senior - Backend integration
|
|
51
|
-
- infra-architect - Infrastructure provisioning (Docker/EasyPanel)
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: neon-expert
|
|
3
|
-
description: Neon PostgreSQL & AI Data specialist for connection pooling, RLS policies with Neon Auth JWT, EF Core migrations, pgvector embeddings, pgrag RAG pipelines, database branching, and scale-to-zero configuration. Use when designing database schemas, implementing Row Level Security, setting up vector search, or managing Neon branches.
|
|
4
|
-
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
-
stacks:
|
|
6
|
-
- neon
|
|
7
|
-
color: green
|
|
8
|
-
effort: medium
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Neon PostgreSQL & AI Data Specialist
|
|
12
|
-
|
|
13
|
-
Expert in Neon serverless Postgres: connection pooling, RLS with Neon Auth JWT, EF Core migrations, pgvector, pgrag, database branching, and scale-to-zero.
|
|
14
|
-
|
|
15
|
-
> **Ref:** `framework/standards/infrastructure/neon/` — connection pooling, RLS, pgvector, pgrag standards
|
|
16
|
-
|
|
17
|
-
## Connection Pooling
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
# Direct connection (migrations, pg_dump, schema changes only)
|
|
21
|
-
postgresql://user:password@ep-cool-darkness-123456.us-east-2.aws.neon.tech/dbname?sslmode=require
|
|
22
|
-
|
|
23
|
-
# Pooled connection (application — ALWAYS use this)
|
|
24
|
-
postgresql://user:password@ep-cool-darkness-123456-pooler.us-east-2.aws.neon.tech/dbname?sslmode=require
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
**Rule:** Application code ALWAYS connects via the `-pooler` endpoint. Direct connections only for migrations and schema changes.
|
|
28
|
-
|
|
29
|
-
### Get connection strings via CLI
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
# Direct (default)
|
|
33
|
-
neonctl connection-string
|
|
34
|
-
|
|
35
|
-
# Pooled (for application use)
|
|
36
|
-
neonctl connection-string --pooled
|
|
37
|
-
|
|
38
|
-
# Specific branch
|
|
39
|
-
neonctl connection-string feature/user-auth --pooled
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### PgBouncer settings (Neon-managed, not configurable)
|
|
43
|
-
|
|
44
|
-
- `pool_mode=transaction` — connections returned after each transaction
|
|
45
|
-
- `max_client_conn=10000`
|
|
46
|
-
- `default_pool_size=0.9 * max_connections`
|
|
47
|
-
|
|
48
|
-
### Pooled connection limitations
|
|
49
|
-
|
|
50
|
-
Transaction mode restricts: `SET`/`RESET`, `LISTEN`/`NOTIFY`, SQL-level prepared statements, persistent temp tables. Use explicit schema references instead of `SET search_path`.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Row Level Security (RLS)
|
|
55
|
-
|
|
56
|
-
### Enable RLS on every table
|
|
57
|
-
|
|
58
|
-
```sql
|
|
59
|
-
ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### RLS with Neon Auth JWT
|
|
63
|
-
|
|
64
|
-
Neon provides `auth.user_id()` via the `pg_session_jwt` extension. It extracts the `sub` claim from the validated JWT automatically. Neon Auth issues these JWTs — no external provider needed.
|
|
65
|
-
|
|
66
|
-
```sql
|
|
67
|
-
-- User owns the row
|
|
68
|
-
CREATE POLICY "Users can view own documents"
|
|
69
|
-
ON public.documents FOR SELECT TO authenticated
|
|
70
|
-
USING (auth.user_id() = user_id);
|
|
71
|
-
|
|
72
|
-
-- User can insert own rows
|
|
73
|
-
CREATE POLICY "Users can insert own documents"
|
|
74
|
-
ON public.documents FOR INSERT TO authenticated
|
|
75
|
-
WITH CHECK (auth.user_id() = user_id);
|
|
76
|
-
|
|
77
|
-
-- User can update own rows
|
|
78
|
-
CREATE POLICY "Users can update own documents"
|
|
79
|
-
ON public.documents FOR UPDATE TO authenticated
|
|
80
|
-
USING (auth.user_id() = user_id)
|
|
81
|
-
WITH CHECK (auth.user_id() = user_id);
|
|
82
|
-
|
|
83
|
-
-- User can delete own rows
|
|
84
|
-
CREATE POLICY "Users can delete own documents"
|
|
85
|
-
ON public.documents FOR DELETE TO authenticated
|
|
86
|
-
USING (auth.user_id() = user_id);
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Team-based access
|
|
90
|
-
|
|
91
|
-
```sql
|
|
92
|
-
CREATE POLICY "Team members can view"
|
|
93
|
-
ON public.documents FOR SELECT
|
|
94
|
-
USING (
|
|
95
|
-
team_id IN (
|
|
96
|
-
SELECT team_id FROM public.team_members
|
|
97
|
-
WHERE user_id = auth.user_id()
|
|
98
|
-
)
|
|
99
|
-
);
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## Migrations (EF Core)
|
|
105
|
-
|
|
106
|
-
Neon uses standard PostgreSQL — migrations are managed via EF Core, NOT a proprietary CLI.
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
# Create migration
|
|
110
|
-
dotnet ef migrations add CreateDocumentsTable --project src/Infrastructure --startup-project src/Web
|
|
111
|
-
|
|
112
|
-
# Apply migration (use DIRECT connection string, not pooled)
|
|
113
|
-
dotnet ef database update --project src/Infrastructure --startup-project src/Web
|
|
114
|
-
|
|
115
|
-
# Review generated migration before applying — check Up() and Down()
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Connection string in appsettings
|
|
119
|
-
|
|
120
|
-
```json
|
|
121
|
-
{
|
|
122
|
-
"ConnectionStrings": {
|
|
123
|
-
"DefaultConnection": "Host=ep-cool-darkness-123456-pooler.us-east-2.aws.neon.tech;Database=dbname;Username=user;Password=password;SSL Mode=Require",
|
|
124
|
-
"MigrationConnection": "Host=ep-cool-darkness-123456.us-east-2.aws.neon.tech;Database=dbname;Username=user;Password=password;SSL Mode=Require"
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
**Rule:** Register two connection strings — pooled for application, direct for migrations. Configure `DbContext` to use `MigrationConnection` only in migration tooling.
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## pgvector (Embeddings)
|
|
134
|
-
|
|
135
|
-
### Setup
|
|
136
|
-
|
|
137
|
-
```sql
|
|
138
|
-
CREATE EXTENSION IF NOT EXISTS vector;
|
|
139
|
-
|
|
140
|
-
CREATE TABLE public.embeddings (
|
|
141
|
-
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
142
|
-
document_id UUID REFERENCES public.documents(id) ON DELETE CASCADE,
|
|
143
|
-
content TEXT NOT NULL,
|
|
144
|
-
embedding vector(1536) NOT NULL, -- OpenAI text-embedding-3-small
|
|
145
|
-
metadata JSONB DEFAULT '{}'::jsonb,
|
|
146
|
-
created_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
-- Optimize memory before index creation
|
|
150
|
-
SET maintenance_work_mem = '2 GB'; -- max 50-60% of compute RAM
|
|
151
|
-
SET max_parallel_maintenance_workers = 7;
|
|
152
|
-
|
|
153
|
-
-- HNSW index for fast similarity search (cosine distance)
|
|
154
|
-
CREATE INDEX idx_embeddings_vector ON public.embeddings
|
|
155
|
-
USING hnsw (embedding vector_cosine_ops)
|
|
156
|
-
WITH (m = 16, ef_construction = 64);
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### Similarity search function
|
|
160
|
-
|
|
161
|
-
```sql
|
|
162
|
-
CREATE OR REPLACE FUNCTION match_embeddings(
|
|
163
|
-
query_embedding vector(1536),
|
|
164
|
-
match_threshold FLOAT DEFAULT 0.78,
|
|
165
|
-
match_count INT DEFAULT 5
|
|
166
|
-
)
|
|
167
|
-
RETURNS TABLE (
|
|
168
|
-
id UUID,
|
|
169
|
-
content TEXT,
|
|
170
|
-
metadata JSONB,
|
|
171
|
-
similarity FLOAT
|
|
172
|
-
)
|
|
173
|
-
LANGUAGE plpgsql AS $$
|
|
174
|
-
BEGIN
|
|
175
|
-
RETURN QUERY
|
|
176
|
-
SELECT
|
|
177
|
-
e.id,
|
|
178
|
-
e.content,
|
|
179
|
-
e.metadata,
|
|
180
|
-
1 - (e.embedding <=> query_embedding) AS similarity
|
|
181
|
-
FROM public.embeddings e
|
|
182
|
-
WHERE 1 - (e.embedding <=> query_embedding) > match_threshold
|
|
183
|
-
ORDER BY e.embedding <=> query_embedding
|
|
184
|
-
LIMIT match_count;
|
|
185
|
-
END;
|
|
186
|
-
$$;
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### C# — Semantic Kernel vector store with Neon
|
|
190
|
-
|
|
191
|
-
```csharp
|
|
192
|
-
// NuGet: Microsoft.SemanticKernel, Npgsql.EntityFrameworkCore.PostgreSQL, pgvector
|
|
193
|
-
using Microsoft.SemanticKernel;
|
|
194
|
-
using Microsoft.SemanticKernel.Connectors.Postgres;
|
|
195
|
-
using Npgsql;
|
|
196
|
-
|
|
197
|
-
// Register the Postgres vector store
|
|
198
|
-
var dataSource = new NpgsqlDataSourceBuilder(connectionString)
|
|
199
|
-
.UseVector()
|
|
200
|
-
.Build();
|
|
201
|
-
|
|
202
|
-
builder.Services.AddPostgresVectorStore(dataSource);
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## pgrag (SQL-Native RAG Pipeline)
|
|
208
|
-
|
|
209
|
-
pgrag is an experimental Neon extension for building end-to-end RAG pipelines entirely in SQL.
|
|
210
|
-
|
|
211
|
-
### Setup
|
|
212
|
-
|
|
213
|
-
```sql
|
|
214
|
-
SET neon.allow_unstable_extensions = 'true';
|
|
215
|
-
|
|
216
|
-
CREATE EXTENSION IF NOT EXISTS rag CASCADE;
|
|
217
|
-
CREATE EXTENSION IF NOT EXISTS rag_bge_small_en_v15 CASCADE; -- local embeddings
|
|
218
|
-
CREATE EXTENSION IF NOT EXISTS rag_jina_reranker_v1_tiny_en CASCADE; -- local reranker
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Text extraction
|
|
222
|
-
|
|
223
|
-
```sql
|
|
224
|
-
-- Extract text from PDF, DOCX, or HTML
|
|
225
|
-
SELECT rag.text_from_pdf(pdf_bytea);
|
|
226
|
-
SELECT rag.text_from_docx(docx_bytea);
|
|
227
|
-
SELECT rag.markdown_from_html(html_text);
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
### Chunking
|
|
231
|
-
|
|
232
|
-
```sql
|
|
233
|
-
-- Character-based chunking
|
|
234
|
-
SELECT unnest(rag.chunks_by_character_count(fulltext, 1000, 200)) AS chunk
|
|
235
|
-
FROM documents;
|
|
236
|
-
|
|
237
|
-
-- Token-based chunking (model-aware)
|
|
238
|
-
SELECT unnest(rag_bge_small_en_v15.chunks_by_token_count(fulltext, 192, 8)) AS chunk
|
|
239
|
-
FROM documents;
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Embedding generation
|
|
243
|
-
|
|
244
|
-
```sql
|
|
245
|
-
-- Local embeddings (BGE small, 384 dimensions — no API key needed)
|
|
246
|
-
INSERT INTO embeddings (doc_id, chunk, embedding)
|
|
247
|
-
SELECT id, chunk, rag_bge_small_en_v15.embedding_for_passage(chunk)
|
|
248
|
-
FROM chunks;
|
|
249
|
-
|
|
250
|
-
-- OpenAI embeddings (1536 dimensions — requires OPENAI_API_KEY)
|
|
251
|
-
INSERT INTO embeddings (doc_id, chunk, embedding)
|
|
252
|
-
SELECT id, chunk, rag.openai_text_embedding_3_small(chunk)
|
|
253
|
-
FROM chunks;
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### Search with reranking
|
|
257
|
-
|
|
258
|
-
```sql
|
|
259
|
-
-- Step 1: Vector similarity search
|
|
260
|
-
WITH candidates AS (
|
|
261
|
-
SELECT chunk, embedding <=> rag_bge_small_en_v15.embedding_for_query('my question') AS distance
|
|
262
|
-
FROM embeddings
|
|
263
|
-
ORDER BY distance
|
|
264
|
-
LIMIT 20
|
|
265
|
-
),
|
|
266
|
-
-- Step 2: Rerank for precision
|
|
267
|
-
ranked AS (
|
|
268
|
-
SELECT chunk, rag_jina_reranker_v1_tiny_en.rerank_distance('my question', chunk) AS rerank_distance
|
|
269
|
-
FROM candidates
|
|
270
|
-
ORDER BY rerank_distance
|
|
271
|
-
LIMIT 5
|
|
272
|
-
)
|
|
273
|
-
SELECT * FROM ranked;
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Chat completion (answer generation)
|
|
277
|
-
|
|
278
|
-
```sql
|
|
279
|
-
SELECT rag.openai_chat_completion(json_object(
|
|
280
|
-
'model': 'gpt-4o-mini',
|
|
281
|
-
'messages': json_array(
|
|
282
|
-
json_object('role': 'system', 'content': 'Answer based on the provided context.'),
|
|
283
|
-
json_object('role': 'user', 'content': 'Context: ' || context_chunks || E'\n\nQuestion: ' || user_question)
|
|
284
|
-
)
|
|
285
|
-
)) -> 'choices' -> 0 -> 'message' -> 'content' AS answer;
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
---
|
|
289
|
-
|
|
290
|
-
## Database Branching
|
|
291
|
-
|
|
292
|
-
Neon branches are copy-on-write clones of your database — instant, zero-cost until data diverges.
|
|
293
|
-
|
|
294
|
-
### Branch workflow
|
|
295
|
-
|
|
296
|
-
```bash
|
|
297
|
-
# Create a feature branch from main
|
|
298
|
-
neonctl branches create --name feature/user-auth
|
|
299
|
-
|
|
300
|
-
# Create a branch from a specific point in time
|
|
301
|
-
neonctl branches create --name data-recovery --parent 2024-07-11T10:00:00Z
|
|
302
|
-
|
|
303
|
-
# Create a schema-only branch (no data)
|
|
304
|
-
neonctl branches create --name preview/pr-42 --schema-only
|
|
305
|
-
|
|
306
|
-
# List all branches
|
|
307
|
-
neonctl branches list
|
|
308
|
-
|
|
309
|
-
# Compare schema differences
|
|
310
|
-
neonctl branches schema-diff production feature/user-auth
|
|
311
|
-
|
|
312
|
-
# Reset branch to parent (re-sync with main)
|
|
313
|
-
neonctl branches reset feature/user-auth --parent
|
|
314
|
-
|
|
315
|
-
# Delete branch
|
|
316
|
-
neonctl branches delete feature/user-auth
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
### Branch strategy
|
|
320
|
-
|
|
321
|
-
| Branch | Purpose | Lifecycle |
|
|
322
|
-
|--------|---------|-----------|
|
|
323
|
-
| `main` | Production database | Permanent |
|
|
324
|
-
| `dev` | Shared development | Permanent |
|
|
325
|
-
| `preview/pr-{n}` | PR preview environments | Ephemeral (delete on merge) |
|
|
326
|
-
| `staging` | Pre-production validation | Permanent |
|
|
327
|
-
|
|
328
|
-
**Rule:** Always create `--schema-only` branches for PR previews to avoid copying production data. Use `neonctl branches schema-diff` before merging migration branches.
|
|
329
|
-
|
|
330
|
-
---
|
|
331
|
-
|
|
332
|
-
## Scale-to-Zero
|
|
333
|
-
|
|
334
|
-
Neon auto-suspends inactive computes after 5 minutes of inactivity (Free plan, fixed). Reactivation takes ~200-500ms on first query.
|
|
335
|
-
|
|
336
|
-
### Configuration
|
|
337
|
-
|
|
338
|
-
- **Free plan:** 5-minute suspend timeout (not configurable)
|
|
339
|
-
- **Paid plans:** Configurable timeout or disable scale-to-zero entirely
|
|
340
|
-
- **Computes > 16 CU:** Always active (no auto-suspend)
|
|
341
|
-
|
|
342
|
-
### Cold start mitigation
|
|
343
|
-
|
|
344
|
-
```csharp
|
|
345
|
-
// Use connection retry logic in .NET
|
|
346
|
-
builder.Services.AddDbContext<AppDbContext>(options =>
|
|
347
|
-
options.UseNpgsql(connectionString, npgsqlOptions =>
|
|
348
|
-
{
|
|
349
|
-
npgsqlOptions.EnableRetryOnFailure(
|
|
350
|
-
maxRetryCount: 3,
|
|
351
|
-
maxRetryDelay: TimeSpan.FromSeconds(5),
|
|
352
|
-
errorCodesToAdd: null);
|
|
353
|
-
npgsqlOptions.CommandTimeout(30);
|
|
354
|
-
}));
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
**Rule:** Always configure retry logic in application code. The first connection after auto-suspend may take 200-500ms. For latency-sensitive production workloads on paid plans, disable scale-to-zero.
|
|
358
|
-
|
|
359
|
-
---
|
|
360
|
-
|
|
361
|
-
## Checklist
|
|
362
|
-
|
|
363
|
-
- [ ] Pooled connection (`-pooler` endpoint) used for all application connections
|
|
364
|
-
- [ ] Direct connection used only for migrations and schema changes
|
|
365
|
-
- [ ] RLS enabled on ALL public tables
|
|
366
|
-
- [ ] RLS policies use `auth.user_id()` via `pg_session_jwt` extension
|
|
367
|
-
- [ ] RLS policies cover SELECT, INSERT, UPDATE, DELETE
|
|
368
|
-
- [ ] EF Core migrations use direct connection string
|
|
369
|
-
- [ ] Indexes on all frequently filtered columns
|
|
370
|
-
- [ ] pgvector: HNSW index with `maintenance_work_mem` tuned before creation
|
|
371
|
-
- [ ] pgrag: extensions installed with `neon.allow_unstable_extensions = 'true'`
|
|
372
|
-
- [ ] Database branches created for PR previews (`--schema-only`)
|
|
373
|
-
- [ ] Branch cleanup automated on PR merge
|
|
374
|
-
- [ ] Connection retry logic configured for scale-to-zero cold starts
|
|
375
|
-
- [ ] `neonctl branches schema-diff` run before merging migration branches
|
|
376
|
-
|
|
377
|
-
---
|
|
378
|
-
|
|
379
|
-
*MORPH-SPEC by Polymorphism Tech*
|