@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.
Files changed (202) hide show
  1. package/CLAUDE.md +12 -10
  2. package/README.md +4 -4
  3. package/bin/morph-spec.js +40 -43
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +28 -36
  6. package/docs/QUICKSTART.md +31 -191
  7. package/framework/CLAUDE.md +24 -30
  8. package/framework/MORPH.md +47 -123
  9. package/framework/agents.json +6 -374
  10. package/framework/commands/morph-apply.md +1 -1
  11. package/framework/commands/morph-archive.md +4 -3
  12. package/framework/commands/morph-hotfix.md +8 -30
  13. package/framework/commands/morph-infra.md +2 -2
  14. package/framework/commands/morph-media.md +10 -9
  15. package/framework/commands/morph-preflight.md +3 -3
  16. package/framework/commands/morph-review.md +15 -0
  17. package/framework/commands/morph-status.md +1 -1
  18. package/framework/docs/CLI.md +84 -95
  19. package/framework/evals/review-checklist.md +45 -53
  20. package/framework/hooks/README.md +4 -4
  21. package/framework/hooks/claude-code/core/README.md +1 -1
  22. package/framework/hooks/claude-code/core/denylist.json +4 -4
  23. package/framework/hooks/claude-code/core/gate-guard.js +9 -0
  24. package/framework/hooks/claude-code/core/masked-exit.js +49 -0
  25. package/framework/hooks/claude-code/core/state-sync.js +4 -1
  26. package/framework/hooks/claude-code/core/telemetry-log.js +1 -2
  27. package/framework/hooks/claude-code/core/test-budget.js +10 -70
  28. package/framework/hooks/claude-code/core/validate-completion.js +11 -24
  29. package/framework/hooks/claude-code/core/worktree-context.js +5 -22
  30. package/framework/hooks/claude-code/core/worktree-create.js +6 -45
  31. package/framework/hooks/claude-code/core/worktree-env-inject.js +2 -10
  32. package/framework/hooks/shared/e2e-check.js +0 -0
  33. package/framework/hooks/shared/gate-event.js +2 -2
  34. package/framework/hooks/shared/graph-refresh.js +20 -3
  35. package/framework/hooks/shared/heavy-command.js +32 -1
  36. package/framework/hooks/shared/heavy-config.js +1 -1
  37. package/framework/hooks/shared/next-step.js +63 -24
  38. package/framework/hooks/shared/phase-utils.js +6 -9
  39. package/framework/hooks/shared/report-progress.js +86 -0
  40. package/framework/hooks/shared/state-reader.js +3 -2
  41. package/framework/hooks/statusline.js +332 -0
  42. package/framework/mcp/registry.json +4 -4
  43. package/framework/phases.json +32 -10
  44. package/framework/rules/ai-agents-standards.md +10 -2
  45. package/framework/rules/csharp-standards.md +4 -0
  46. package/framework/rules/data-standards.md +1 -1
  47. package/framework/rules/ef-standards.md +20 -0
  48. package/framework/rules/frontend-standards.md +1 -1
  49. package/framework/rules/hangfire-standards.md +1 -1
  50. package/framework/rules/implement-report.md +25 -0
  51. package/framework/rules/infrastructure-standards.md +2 -0
  52. package/framework/rules/neon-auth-standards.md +1 -1
  53. package/framework/rules/neon-standards.md +3 -3
  54. package/framework/rules/nextjs-standards.md +7 -0
  55. package/framework/rules/plan-grammar.md +53 -0
  56. package/framework/rules/ui-design.md +27 -0
  57. package/framework/schemas/config.schema.json +11 -18
  58. package/framework/schemas/feature.schema.json +7 -1
  59. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  60. package/framework/skills/core/create-umbraco-lp/references/umbraco-lp-patterns.md +1 -1
  61. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +2 -2
  62. package/framework/skills/core/morph-apply/SKILL.md +39 -166
  63. package/framework/skills/core/morph-apply/references/debugging.md +8 -0
  64. package/framework/skills/core/morph-apply/references/hotfix.md +42 -0
  65. package/framework/skills/core/morph-apply/references/machine.md +29 -0
  66. package/framework/skills/core/{morph-media/SKILL.md → morph-apply/references/media.md} +11 -74
  67. package/framework/skills/core/morph-apply/references/review.md +65 -0
  68. package/framework/skills/core/morph-plan/SKILL.md +49 -109
  69. package/framework/skills/core/morph-plan/references/critique.md +43 -0
  70. package/framework/skills/core/morph-plan/references/interview.md +37 -0
  71. package/framework/skills/core/morph-uiux/SKILL.md +47 -64
  72. package/framework/skills/core/morph-uiux/surfaces.json +32 -0
  73. package/framework/standards/STANDARDS.json +51 -28
  74. package/framework/standards/STANDARDS.meta.json +16 -19
  75. package/framework/standards/ai-agents/agent-session.md +2 -3
  76. package/framework/standards/ai-agents/context-providers.md +2 -2
  77. package/framework/standards/ai-agents/durable-workflows-hitl.md +2 -2
  78. package/framework/standards/ai-agents/providers/model-registry.md +2 -2
  79. package/framework/standards/ai-agents/rag-custom-pgvector.md +7 -6
  80. package/framework/standards/ai-agents/setup.md +1 -1
  81. package/framework/standards/ai-agents/tool-adapters.md +2 -2
  82. package/framework/standards/architecture/stack-baseline.md +70 -0
  83. package/framework/standards/backend/database/postgresql/database.md +22 -1
  84. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +33 -1
  85. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +2 -1
  86. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +12 -13
  87. package/framework/standards/frontend/design-system/ai-image-generation.md +51 -12
  88. package/framework/standards/frontend/design-system/ai-video-generation.md +50 -4
  89. package/framework/standards/frontend/design-system/art-direction.md +2 -2
  90. package/framework/standards/frontend/scroll-driven/frame-scrub.md +12 -2
  91. package/framework/standards/frontend/scroll-driven/scroll-components.md +76 -4
  92. package/framework/standards/infrastructure/docker/local-compose-isolation.md +2 -2
  93. package/framework/standards/infrastructure/neon/neon-pgvector.md +62 -20
  94. package/framework/standards/infrastructure/neon/neon-platform.md +61 -0
  95. package/framework/standards/infrastructure/neon/neon-setup.md +14 -13
  96. package/framework/standards/integration/mcp/mcp-tools.md +20 -20
  97. package/framework/templates/REGISTRY.json +1 -2
  98. package/framework/templates/context/ARCHITECTURE.md +1 -1
  99. package/framework/templates/docs/plan.md +15 -12
  100. package/framework/templates/docs/ui-mockups.md +17 -105
  101. package/framework/templates/infrastructure/docker/docker-compose.template.yml +1 -1
  102. package/package.json +1 -1
  103. package/src/commands/e2e/e2e.js +88 -23
  104. package/src/commands/graph/diff.js +74 -0
  105. package/src/commands/graph/status.js +1 -1
  106. package/src/commands/observability/cost.js +2 -4
  107. package/src/commands/observability/telemetry.js +1 -1
  108. package/src/commands/project/doctor.js +23 -39
  109. package/src/commands/project/fleet.js +5 -6
  110. package/src/commands/project/init.js +63 -36
  111. package/src/commands/project/stack-scan.js +3 -42
  112. package/src/commands/project/stack-set.js +26 -0
  113. package/src/commands/project/status.js +12 -13
  114. package/src/commands/project/update.js +39 -3
  115. package/src/commands/project/worktree.js +3 -14
  116. package/src/commands/state/advance.js +17 -17
  117. package/src/commands/state/approve.js +0 -6
  118. package/src/commands/state/archive.js +27 -1
  119. package/src/commands/state/auto-approval.js +2 -2
  120. package/src/commands/state/create.js +1 -6
  121. package/src/commands/state/gate-check.js +38 -31
  122. package/src/commands/state/gate-decision.js +3 -2
  123. package/src/commands/state/next.js +1 -0
  124. package/src/commands/state/recap.js +67 -0
  125. package/src/commands/state/report-check.js +36 -178
  126. package/src/commands/validation/plan-check.js +16 -11
  127. package/src/commands/validation/validate-feature.js +3 -3
  128. package/src/commands/validation/verify.js +3 -6
  129. package/src/core/paths/output-schema.js +3 -3
  130. package/src/core/state/state-manager.js +2 -4
  131. package/src/dashboard/app/components/CommandPalette.jsx +2 -5
  132. package/src/dashboard/app/components/GatePauses.jsx +116 -0
  133. package/src/dashboard/app/components/SessionMap.jsx +77 -0
  134. package/src/dashboard/app/pages/Activity.jsx +4 -0
  135. package/src/dashboard/app/pages/AgentMap.jsx +1 -2
  136. package/src/dashboard/app/pages/FeatureDetail.jsx +129 -186
  137. package/src/dashboard/app/pages/Features.jsx +7 -7
  138. package/src/dashboard/app/pages/PhasePipeline.jsx +1 -1
  139. package/src/dashboard/app/pages/Portfolio.jsx +40 -5
  140. package/src/dashboard/scanner/activity-scanner.js +29 -0
  141. package/src/dashboard/scanner/agents-scanner.js +11 -14
  142. package/src/dashboard/scanner/features-scanner.js +45 -24
  143. package/src/dashboard/scanner/project-api.js +11 -2
  144. package/src/dashboard/scanner/skills-scanner.js +11 -1
  145. package/src/lib/detectors/index.js +1 -1
  146. package/src/lib/e2e/applicability.js +3 -1
  147. package/src/lib/git/tree-state.js +1 -16
  148. package/src/lib/graph/diff-tree.js +127 -0
  149. package/src/lib/graph/graphify-runtime.js +12 -5
  150. package/src/lib/installers/memory-installer.js +3 -3
  151. package/src/lib/installers/rules-installer.js +57 -0
  152. package/src/lib/installers/stack-assets.js +17 -0
  153. package/src/lib/installers/stack-sync.js +219 -0
  154. package/src/lib/plan/checks.js +61 -109
  155. package/src/lib/plan/critique.js +28 -0
  156. package/src/lib/plan/media.js +42 -0
  157. package/src/lib/plan/plan-html.js +125 -0
  158. package/src/lib/plan/plan-parser.js +34 -45
  159. package/src/lib/recap/piper.js +36 -0
  160. package/src/lib/recap/recap.js +232 -0
  161. package/src/lib/review-reports.js +28 -4
  162. package/src/lib/risk-detector.js +90 -11
  163. package/src/lib/specs/screen-checklist.js +33 -48
  164. package/src/lib/stack/dotnet-build-ignores.js +8 -9
  165. package/src/lib/telemetry/metrics.js +27 -29
  166. package/src/lib/validators/reuse/reuse-validator.js +1 -9
  167. package/src/lib/validators/verify-runner.js +0 -7
  168. package/src/lib/worktree/fleet-scanner.js +7 -20
  169. package/src/lib/worktree/worktree-audit.js +0 -37
  170. package/src/scripts/setup-infra.js +15 -50
  171. package/src/utils/agents-installer.js +27 -201
  172. package/src/utils/hooks-installer.js +11 -95
  173. package/framework/hooks/claude-code/core/warn-bash-source-write.js +0 -23
  174. package/framework/hooks/claude-code/statusline.py +0 -699
  175. package/framework/hooks/claude-code/statusline.sh +0 -11
  176. package/framework/hooks/shared/agent-reap.js +0 -74
  177. package/framework/hooks/shared/slice-progress.js +0 -110
  178. package/framework/skills/core/morph-hotfix/SKILL.md +0 -133
  179. package/framework/skills/core/morph-machine/SKILL.md +0 -46
  180. package/framework/skills/core/morph-review/SKILL.md +0 -129
  181. package/framework/skills/core/morph-standards/SKILL.md +0 -52
  182. package/framework/standards/PROVENANCE.json +0 -119
  183. package/framework/standards/infrastructure/neon/neon-pgrag.md +0 -243
  184. package/src/commands/project/worktree-reap.js +0 -34
  185. package/src/commands/state/handoff.js +0 -65
  186. package/src/commands/validation/mutate.js +0 -263
  187. package/src/commands/validation/scout-check.js +0 -28
  188. package/src/lib/generators/handoff-generator.js +0 -172
  189. package/src/lib/mutation/adapters.js +0 -79
  190. package/src/lib/mutation/commands.js +0 -61
  191. package/src/lib/mutation/dotnet-introspection.js +0 -281
  192. package/src/lib/mutation/manifest.js +0 -144
  193. package/src/lib/mutation/plan.js +0 -44
  194. package/src/lib/mutation/report.js +0 -68
  195. package/src/lib/mutation/runner.js +0 -301
  196. package/src/lib/mutation/schemata.js +0 -60
  197. package/src/lib/mutation/snapshot.js +0 -65
  198. package/src/lib/mutation/subset.js +0 -109
  199. package/src/lib/mutation/trx.js +0 -50
  200. package/src/lib/scout/scout-check.js +0 -293
  201. package/src/lib/validators/traceability-check.js +0 -103
  202. package/src/lib/worktree/agent-reaper.js +0 -247
@@ -5,7 +5,7 @@
5
5
  > **Keywords:** pinned gallery, horizontal scroll, modal, lightbox, parallax, count-up, reveal, scroll progress, accordion
6
6
  > **Load When:** ui-designer active, or building a scroll-driven marketing page
7
7
 
8
- **Verified against:** GSAP 3.13 (ScrollTrigger, matchMedia, context) + React 18 + Lenis 1.x, shipped to production. Last-verified: 2026-08-21.
8
+ **Verified against:** GSAP 3.13 (ScrollTrigger, matchMedia, context) + React 18 + Lenis 1.x, shipped to production. Last-verified: 2026-10-27.
9
9
 
10
10
  ---
11
11
 
@@ -114,6 +114,19 @@ useEffect(() => {
114
114
 
115
115
  **Render overlays outside any pinned section.** A pin applies a `transform` to its container, which becomes the containing block for `position: fixed` and breaks the overlay. Put the modal in a fragment as a sibling of the section.
116
116
 
117
+ The markup: the backdrop closes on click, the panel stops propagation so a click inside does not close it, and the dialog carries its role.
118
+
119
+ ```jsx
120
+ {active !== null && (
121
+ <div className={`lmodal${shown ? ' in' : ''}`} onClick={close} role="dialog" aria-modal="true">
122
+ <div className="lmodal__panel" data-lenis-prevent onClick={(e) => e.stopPropagation()}>
123
+ <button className="lmodal__close" onClick={close} aria-label="Close">×</button>
124
+ {/* content */}
125
+ </div>
126
+ </div>
127
+ )}
128
+ ```
129
+
117
130
  **Mark the scrollable panel `data-lenis-prevent`.** Stopping the smooth scroller is not enough: while stopped it calls `preventDefault()` on any `touchmove` that reaches it, so a panel with `overflow-y: auto` scrolls with the wheel and is frozen under a finger. Whatever sits at the bottom of the panel, usually the CTA, becomes unreachable on a phone. See `frontend/scroll-driven/smooth-scroll.md`, Section 3.
118
131
 
119
132
  ```jsx
@@ -199,6 +212,8 @@ Format for the locale at write time (the decimal comma above is pt-BR). Never an
199
212
 
200
213
  ## Section 7: Persistent Elements
201
214
 
215
+ These live at the app root, outside every section, and repeat on almost every marketing page.
216
+
202
217
  **Slim translucent nav** that gains a background once scrolled:
203
218
 
204
219
  ```jsx
@@ -208,6 +223,19 @@ useEffect(() => {
208
223
  window.addEventListener('scroll', onScroll, { passive: true })
209
224
  return () => window.removeEventListener('scroll', onScroll)
210
225
  }, [])
226
+ return (
227
+ <nav className={`nav${solid ? ' nav--solid' : ''}`}>
228
+ <a className="nav__logo" href="#top"><span>{BRAND}</span></a>
229
+ <div className="nav__links">{/* anchors */}</div>
230
+ <a className="btn btn-accent" href="#contact">{CTA}</a>
231
+ </nav>
232
+ )
233
+ ```
234
+
235
+ ```css
236
+ .nav { position: fixed; top: 0; inset-inline: 0; z-index: 100; display: flex; align-items: center;
237
+ justify-content: space-between; padding: 16px clamp(16px,5vw,48px); transition: background .3s, backdrop-filter .3s; }
238
+ .nav--solid { background: rgba(14,11,12,.7); backdrop-filter: blur(10px); border-bottom: 1px solid var(--hair); }
211
239
  ```
212
240
 
213
241
  **Scroll progress bar** that prefers the smooth scroller when present:
@@ -225,20 +253,64 @@ useEffect(() => {
225
253
  }, [])
226
254
  ```
227
255
 
256
+ ```jsx
257
+ return <div className="scroll-progress" ref={ref} />
258
+ ```
259
+
260
+ ```css
261
+ .scroll-progress { position: fixed; top: 0; left: 0; z-index: 101; height: 3px; width: 100%;
262
+ transform: scaleX(0); transform-origin: 0 50%; background: linear-gradient(90deg, var(--accent), var(--accent-soft)); }
263
+ ```
264
+
228
265
  Transform-based progress (`scaleX` with `transform-origin: 0 50%`) stays on the compositor. Animating `width` does not.
229
266
 
267
+ **Floating chat button.** A fixed exit channel to the business's messaging app, always within reach. It is also the fallback when the lead form fails. For WhatsApp, a `wa.me` deep link with a prefilled message:
268
+
269
+ ```jsx
270
+ <a className="chat-float" href={`https://wa.me/${PHONE}?text=${encodeURIComponent(MESSAGE)}`}
271
+ target="_blank" rel="noopener noreferrer" aria-label="Chat on WhatsApp">
272
+ <svg viewBox="0 0 24 24" width="26" height="26" aria-hidden="true">{/* icon path */}</svg>
273
+ </a>
274
+ ```
275
+
276
+ ```css
277
+ .chat-float { position: fixed; right: 20px; bottom: 20px; z-index: 90; width: 56px; height: 56px;
278
+ display: grid; place-items: center; border-radius: 50%; background: #25d366; color: #fff;
279
+ box-shadow: 0 8px 24px rgba(0,0,0,.35); transition: transform .25s; }
280
+ .chat-float:hover { transform: translateY(-3px) scale(1.05); }
281
+ ```
282
+
283
+ Keep its z-index below the nav and overlays, and check that it does not cover a CTA on mobile.
284
+
230
285
  ---
231
286
 
232
287
  ## Section 8: Accordion
233
288
 
234
- Use native `<details>`. It provides toggle, keyboard support and accessibility for free.
289
+ Use native `<details>`. It provides toggle, keyboard support and accessibility for free. On a landing page the FAQ sits right before the form, to clear objections.
290
+
291
+ ```jsx
292
+ const FAQ = [{ q: '...', a: '...' }]
293
+ return (
294
+ <section className="section faq" id="faq">
295
+ <h2>{TITLE}</h2>
296
+ {FAQ.map((f) => (
297
+ <details className="faq__item" key={f.q}>
298
+ <summary>{f.q}<span className="faq__icon" aria-hidden="true">+</span></summary>
299
+ <p>{f.a}</p>
300
+ </details>
301
+ ))}
302
+ </section>
303
+ )
304
+ ```
235
305
 
236
306
  ```css
307
+ .faq__item { border-bottom: 1px solid var(--hair); padding: 18px 0; }
237
308
  .faq__item summary { cursor: pointer; list-style: none; display: flex;
238
- justify-content: space-between; align-items: center; }
309
+ justify-content: space-between; align-items: center; font-family: var(--serif); font-size: 1.15rem; }
239
310
  .faq__item summary::-webkit-details-marker { display: none; }
240
- .faq__item .faq__icon { transition: transform .3s; }
311
+ .faq__item .faq__icon { transition: transform .3s; color: var(--accent); }
241
312
  .faq__item[open] .faq__icon { transform: rotate(45deg); }
313
+ .faq__item p { margin: 14px 0 0; color: var(--fg-dim); max-width: 70ch; }
242
314
  ```
243
315
 
244
316
  Native `<details>` cannot animate its own height. If height animation is required, drive the inner content with GSAP rather than replacing the element with a custom widget.
@@ -5,7 +5,7 @@
5
5
  > **Keywords:** docker compose, worktree, ports, container_name, POSTGRES_PORT, COMPOSE_PROJECT_NAME, local dev, e2e stack
6
6
  > **Load When:** a compose file, a dev-server port, or a worktree stack is being written or debugged
7
7
 
8
- **Verified against:** Docker Compose v2 + morph-spec 8.34 (dedicated stack per worktree). Last-verified: 2026-09-08.
8
+ **Verified against:** Docker Compose v2 + morph-spec 8.34 (dedicated stack per worktree). The `pgvector/pgvector:pg17` tag was confirmed on Docker Hub; the image was not run. Last-verified: 2026-10-30.
9
9
 
10
10
  ---
11
11
 
@@ -86,7 +86,7 @@ services:
86
86
  timeout: 5s
87
87
  retries: 12
88
88
  postgres:
89
- image: postgres:15-alpine
89
+ image: pgvector/pgvector:pg17
90
90
  ports:
91
91
  - "${POSTGRES_PORT:-5432}:5432"
92
92
  environment:
@@ -2,10 +2,10 @@
2
2
 
3
3
  > **Scope:** neon, dotnet-vsa
4
4
  > **Layer:** 1 (on scope)
5
- > **Keywords:** pgvector, vector, embeddings, similarity search, HNSW, cosine
5
+ > **Keywords:** pgvector, vector, embeddings, similarity search, HNSW, cosine, hybrid search, busca híbrida, RRF, BM25, full-text, lakebase, pg_search
6
6
  > **Load When:** pgvector or embedding keywords detected
7
7
 
8
- **Verified against:** .NET 10 (SDK 10.0.400-preview) + Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3 + Pgvector.EntityFrameworkCore 0.3.0 + Microsoft.Extensions.AI 10.9.0 (ai-pin 2026-09-08). The entity, configuration, DbContext, search-handler and raw-Npgsql blocks compile with `TreatWarningsAsErrors` (handler over the `Result`/`IHandler` of `result-pattern.md`/`vertical-slice.md`), and the handler's query shape was translated with `ToQueryString()` to `ORDER BY d.embedding <=> @query`; the SQL (index DDL, `ef_search`, the two SQL functions) is documentary, checked against the pgvector README. Last-verified: 2026-10-03.
8
+ **Verified against:** .NET 10 (SDK 10.0.400-preview) + Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3 + Pgvector.EntityFrameworkCore 0.3.0 + Microsoft.Extensions.AI 10.9.0 (ai-pin 2026-09-08). The entity, configuration, DbContext, search-handler and raw-Npgsql blocks compile with `TreatWarningsAsErrors` (handler over the `Result`/`IHandler` of `result-pattern.md`/`vertical-slice.md`), and the handler's query shape was translated with `ToQueryString()` to `ORDER BY d.embedding <=> @query`; the SQL (index DDL, `ef_search`, `match_documents`) is documentary, checked against the pgvector README; `hybrid_search` ran on PGlite 0.5.13, not on a Neon compute; the `unaccent` dictionary in a text search configuration is what the Neon `unaccent` page describes (only `unaccent.rules` is closed); Lakebase Search read from the Neon docs. Last-verified: 2026-10-30.
9
9
 
10
10
  ---
11
11
 
@@ -218,38 +218,80 @@ $$;
218
218
 
219
219
  ## Hybrid Search (Vector + Full-Text)
220
220
 
221
- Blends the vector score with `ts_rank`. Same rule as above: a SQL function, justified in `plan.md` (`## Decisões`).
221
+ Semantic search alone misses exact terms (SKU, name, code, error message). Keyword search alone misses paraphrases. Run both and fuse the **ranks** with Reciprocal Rank Fusion: cosine distance and text rank live on different scales, so a weighted sum of the two scores is meaningless. Same rule as above: a SQL function, justified in `plan.md` (`## Decisões`).
222
+
223
+ The default runs on Neon and on the local Docker Postgres alike: native full-text search over a generated `tsvector` with a GIN index. Computing `to_tsvector` inline in the query never uses the index. Content in pt-BR needs its own configuration, or `devolucao` never matches `devolução`:
224
+
225
+ ```sql
226
+ CREATE EXTENSION IF NOT EXISTS unaccent;
227
+
228
+ CREATE TEXT SEARCH CONFIGURATION pt_unaccent (COPY = portuguese);
229
+ ALTER TEXT SEARCH CONFIGURATION pt_unaccent
230
+ ALTER MAPPING FOR hword, hword_part, word WITH unaccent, portuguese_stem;
231
+
232
+ ALTER TABLE documents ADD COLUMN search_tsv tsvector
233
+ GENERATED ALWAYS AS (to_tsvector('pt_unaccent', title || ' ' || content)) STORED;
234
+
235
+ CREATE INDEX idx_documents_search_tsv ON documents USING gin (search_tsv);
236
+ ```
222
237
 
223
238
  ```sql
224
239
  CREATE OR REPLACE FUNCTION hybrid_search(
225
240
  query_text text,
226
241
  query_embedding vector(1536),
227
242
  match_count int DEFAULT 10,
228
- text_weight float DEFAULT 0.3,
229
- vector_weight float DEFAULT 0.7
230
- ) RETURNS TABLE (id uuid, title text, content text, score float)
243
+ candidate_count int DEFAULT 50,
244
+ rrf_k int DEFAULT 60
245
+ ) RETURNS TABLE (id uuid, title text, content text, score double precision)
231
246
  LANGUAGE sql STABLE AS $$
232
247
  WITH vector_results AS (
233
- SELECT id, title, content,
234
- 1 - (embedding <=> query_embedding) AS vector_score
235
- FROM documents
236
- ORDER BY embedding <=> query_embedding LIMIT match_count * 2
248
+ SELECT c.id, row_number() OVER (ORDER BY c.distance) AS rank
249
+ FROM (
250
+ SELECT d.id, d.embedding <=> query_embedding AS distance
251
+ FROM documents d
252
+ ORDER BY distance
253
+ LIMIT candidate_count
254
+ ) c
237
255
  ),
238
256
  text_results AS (
239
- SELECT id, title, content,
240
- ts_rank(to_tsvector('english', content), plainto_tsquery('english', query_text)) AS text_score
241
- FROM documents
242
- WHERE to_tsvector('english', content) @@ plainto_tsquery('english', query_text)
243
- LIMIT match_count * 2
257
+ SELECT c.id, row_number() OVER (ORDER BY c.text_score DESC) AS rank
258
+ FROM (
259
+ SELECT d.id, ts_rank_cd(d.search_tsv, q.query) AS text_score
260
+ FROM documents d, websearch_to_tsquery('pt_unaccent', query_text) AS q(query)
261
+ WHERE d.search_tsv @@ q.query
262
+ ORDER BY text_score DESC
263
+ LIMIT candidate_count
264
+ ) c
265
+ ),
266
+ fused AS (
267
+ SELECT COALESCE(v.id, t.id) AS id,
268
+ COALESCE(1.0 / (rrf_k + v.rank), 0) + COALESCE(1.0 / (rrf_k + t.rank), 0) AS score
269
+ FROM vector_results v
270
+ FULL OUTER JOIN text_results t ON v.id = t.id
244
271
  )
245
- SELECT COALESCE(v.id, t.id), COALESCE(v.title, t.title), COALESCE(v.content, t.content),
246
- (COALESCE(v.vector_score, 0) * vector_weight + COALESCE(t.text_score, 0) * text_weight) AS score
247
- FROM vector_results v FULL OUTER JOIN text_results t ON v.id = t.id
248
- ORDER BY score DESC LIMIT match_count;
272
+ SELECT d.id, d.title, d.content, f.score::double precision
273
+ FROM fused f
274
+ JOIN documents d ON d.id = f.id
275
+ ORDER BY f.score DESC
276
+ LIMIT match_count;
249
277
  $$;
250
278
  ```
251
279
 
252
- For Portuguese content use the `'portuguese'` text search configuration in both `to_tsvector` and `plainto_tsquery`.
280
+ - Multi-tenant table: filter the tenant in **both** inner queries, never only after the fusion.
281
+ - `websearch_to_tsquery` accepts raw user text. `to_tsquery` errors on plain phrases.
282
+ - Both the SQL above and its behaviour (accent-insensitive match, exact code ranked first, empty keyword branch) were run on PGlite 0.5.13 (PostgreSQL 18, pgvector 0.8.7).
283
+
284
+ ### Lakebase Search (Neon-only upgrade)
285
+
286
+ `pg_search` (ParadeDB) is gone from Neon: installs blocked on 2026-03-19, removed on 2026-09-21. Its replacement is `lakebase_text` (PostgreSQL 16+), which adds real BM25 ranking on the same `tsvector` column. `lakebase_vector` adds the `lakebase_ann` index over the same `vector` columns for scale. Neither exists in the local Docker Postgres, so adopting one is an ADR in `plan.md` (`## Decisões`) that says how dev and tests run. Reach for them only when an eval shows `ts_rank_cd` ranks badly, or the corpus outgrows HNSW.
287
+
288
+ Traps of `lakebase_text`:
289
+
290
+ - `<@>` only scores: filter with `@@` in the `WHERE`, or every row comes back.
291
+ - The score is negative: `ORDER BY score` ascending, best first. RRF is unaffected, since it reads ranks.
292
+ - `to_bm25query` takes the index name, because the corpus statistics live in the index.
293
+ - Create the index after the initial load and run `VACUUM` after bulk loads. The statistics are not MVCC-versioned, so scores can shift under a concurrent `VACUUM`.
294
+ - There is no fuzzy match (`pg_trgm` covers typos) and no `paradedb.snippet()` (`ts_headline` covers highlighting).
253
295
 
254
296
  ## Npgsql Vector Type Handler
255
297
 
@@ -0,0 +1,61 @@
1
+ # Neon — o que a plataforma entrega pronto
2
+
3
+ > **Scope:** neon
4
+ > **Layer:** 1 (resumo injetado pela rule `neon-standards`; lido no plano antes de contratar serviço novo)
5
+ > **Keywords:** neon, plataforma, branch, snapshot, PITR, restore, object storage, s3, ai gateway, read replica, slow query, query tuning, ip allow, protected branch, região, neon cli
6
+ > **Load When:** projeto com `neon` precisa de arquivo, gateway de LLM, ambiente descartável, rede de segurança de migration, diagnóstico de consulta ou leitura pesada
7
+
8
+ **Verified against:** Neon docs lidas em 2026-10-30 (regions, plans, backup-restore, branch-expiration, s3-compatibility, ai-gateway, neon-mcp-server, functions) + CLI `neon` 8.14.0. Nenhum bloco deste standard foi executado contra um projeto. Last-verified: 2026-10-30.
9
+
10
+ ---
11
+
12
+ Antes de escrever código ou contratar serviço, confira se o Neon do projeto já resolve. Preço, plano e status mudam rápido: em dúvida, `mcp__neon__search_docs`.
13
+
14
+ ## Região decide o catálogo
15
+
16
+ A região é fixa na criação do projeto; mudar é criar outro projeto e migrar. Postgres e Auth existem em todas. O resto não:
17
+
18
+ | Região | Storage, Functions, AI Gateway, Realtime |
19
+ | --- | --- |
20
+ | `aws-us-east-1`, `aws-us-east-2`, `aws-eu-central-1`, `aws-ap-southeast-1` | Sim |
21
+ | `aws-sa-east-1`, `aws-us-west-2`, `aws-eu-west-2`, `aws-ap-southeast-2` | Não |
22
+
23
+ `neon projects get <id>` mostra o `region_id`. Projeto em São Paulo fica sem esses quatro produtos: pese isso antes de escolher a região pela latência.
24
+
25
+ ## Necessidade → o que usar
26
+
27
+ | Necessidade | No Neon | Pegadinha |
28
+ | --- | --- | --- |
29
+ | Testar migration ou dado real sem tocar produção | Branch com `--expires-at` (máx. 30 dias), `neon branches reset --parent` para recomeçar | Reset sobrescreve o branch, sem backup. `--schema-only` está em beta e não tem pai, logo não tem reset |
30
+ | Ensaiar migration | MCP `prepare_database_migration` → `complete_database_migration` | Aplica SQL em branch temporário: confere o SQL gerado pelo `dotnet ef migrations script --idempotent`, não substitui o `dotnet ef` |
31
+ | Ver o que mudou no schema | `neon branches schema-diff`, `neon diff`, MCP `compare_database_schema` | Compara, não aplica |
32
+ | Rede de segurança de migration com `degrau:` | Snapshot manual antes de aplicar (MCP `create_snapshot`, `neon snapshots`); volta por PITR dentro da janela | Janela default curta (6 h no Free, 1 dia nos pagos, ajustável). Só root branch. Branch restaurado de snapshot perde PITR |
33
+ | Arquivo do usuário, mídia gerada | Object Storage, S3-compatible, GA | `$0,023/GB-mês`. Lifecycle e versioning são guardados, não aplicados. Sem notificação de bucket. Cliente .NET por S3 path-style não testado aqui |
34
+ | Uma credencial para vários modelos de LLM | AI Gateway, OpenAI-compatible, GA | Plano pago e crédito pré-pago. Foge do padrão de provider direto do `model-registry`: exige ADR |
35
+ | Busca por termo em escala | Lakebase Search (`infrastructure-neon-pgvector#lakebase-search-neon-only-upgrade`) | Só existe no Neon |
36
+ | Consulta lenta | MCP `list_slow_queries`, `explain_sql_statement`, `prepare_query_tuning` → `complete_query_tuning`; `pg_stat_statements` | Histórico some quando o compute suspende. `query tuning` testa índice em branch |
37
+ | Relatório pesado sem pesar no primário | Read replica, com connection string própria | Eventualmente consistente, mesma região, cobra compute |
38
+ | Fechar o banco ao IP da VPS | IP Allow, só plano Scale | Incompatível com Neon Auth e Data API: quem usa Auth não liga |
39
+ | Impedir que apaguem produção | Protected branch (Launch: 2, Scale: 5) | Filhos ganham senha nova e scripts de CI quebram |
40
+ | Alerta e métrica fora do console | Export OTel/Datadog, só Scale, em beta | Lacuna enquanto o compute está suspenso |
41
+
42
+ ## O que não adotar nesta stack
43
+
44
+ - **Neon Functions para job .NET:** só JS/TS, e a doc diz "They aren't a job queue". Serve para schedule em UTC que faz POST num endpoint idempotente.
45
+ - **Data API:** o EF Core já é o acesso. Sem autorização própria além de `GRANT`/RLS.
46
+ - **Realtime:** beta, sem RLS, SDK só TypeScript.
47
+ - **Neon Local:** é proxy para a nuvem, não Postgres local. Dev segue no Docker Compose (`infrastructure-docker-local-compose-isolation`).
48
+ - **Private Networking:** exige o cliente na AWS, na mesma região. A VPS não está.
49
+ - **Logical replication sem necessidade real:** reinicia computes e `wal_level` é irreversível.
50
+
51
+ ## MCP em produção
52
+
53
+ A doc do Neon é explícita: "Never connect MCP agents to production databases". O agente trabalha em branch. O servidor expõe tools destrutivas, e toda escrita em produção passa por um humano, com snapshot antes quando houver `degrau:`.
54
+
55
+ ## CLI
56
+
57
+ O pacote agora é `neon` (`npm i -g neon`, Node 20.19+). `neonctl` segue funcionando como o mesmo binário. Login é `neon login`. Comandos úteis no dia a dia: `neon branches`, `neon diff`, `neon snapshots`, `neon psql`, `neon logs`, `neon buckets`, `neon connection-string`, `neon checkout`, `neon env pull`. `neon.ts` (`neon config init`) declara branches em TypeScript: útil no front, opcional em projeto .NET, que lê `user-secrets`.
58
+
59
+ ## Fora do catálogo
60
+
61
+ `pg_search` foi removido, `pgrag` e `plv8` estão deprecados, `pgmq` e Apache AGE não estão na lista de extensões. Lista viva: `docs/extensions/pg-extensions`.
@@ -2,10 +2,10 @@
2
2
 
3
3
  > **Scope:** neon
4
4
  > **Layer:** 0 (resumo injetado pela rule `neon-standards` em `**/neon/**`, `**/database/**` e migrations `.sql`; texto completo sob demanda via `morph-spec standards --find`)
5
- > **Keywords:** neon, serverless postgres, branching, scale-to-zero, connection string, neonctl
5
+ > **Keywords:** neon, serverless postgres, branching, scale-to-zero, connection string, neon cli, neonctl
6
6
  > **Load When:** neon stack detected
7
7
 
8
- **Verified against:** .NET 10 (SDK 10.0.400-preview) + Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3 + neonctl. The DbContext registration, design-time factory and cold-start blocks compile with `TreatWarningsAsErrors`; that Npgsql 10 rejects `postgresql://` URIs and marks `Trust Server Certificate` as "no longer needed and does nothing" was measured on 10.0.3; the suspend-timeout API and `--cu` ranges were checked against the Neon docs (context7). neonctl commands are documentary. Last-verified: 2026-10-03.
8
+ **Verified against:** .NET 10 (SDK 10.0.400-preview) + Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3 + neonctl. The DbContext registration, design-time factory and cold-start blocks compile with `TreatWarningsAsErrors`; that Npgsql 10 rejects `postgresql://` URIs and marks `Trust Server Certificate` as "no longer needed and does nothing" was measured on 10.0.3; the suspend-timeout API and `--cu` ranges were checked against the Neon docs (context7). `neon` CLI commands are documentary; the top-level commands were read from `neon --help` 8.14.0. Last-verified: 2026-10-30.
9
9
 
10
10
  ---
11
11
 
@@ -18,19 +18,20 @@ Stack: .NET + Neon Serverless Postgres
18
18
  - NEVER hardcode connection strings or commit them in `appsettings*.json` -- user-secrets in development, environment variables in Coolify
19
19
  - ALWAYS enable SSL (`SSL Mode=Require`) for all connections
20
20
  - ALWAYS configure retry policies for cold-start resilience
21
- - NEVER leave branches without expiration -- set TTL for dev/CI branches
21
+ - NEVER leave branches without expiration -- set TTL for dev/CI branches (`--expires-at`, 30 days at most)
22
+ - ALWAYS take a snapshot before applying a migration with `degrau:` to production (`infrastructure-neon-platform`)
22
23
 
23
24
  ## Neon CLI Setup
24
25
 
25
26
  ```bash
26
- # Install neonctl globally
27
- npm install -g neonctl
27
+ # Install neon globally
28
+ npm install -g neon
28
29
 
29
30
  # Authenticate (opens browser)
30
- neonctl auth
31
+ neon login
31
32
 
32
33
  # Verify connection
33
- neonctl projects list
34
+ neon projects list
34
35
  ```
35
36
 
36
37
  ## Connection Strings
@@ -130,24 +131,24 @@ Neon branches are copy-on-write clones of your database -- instant, zero-cost un
130
131
 
131
132
  ```bash
132
133
  # List branches
133
- neonctl branches list --project-id <project-id>
134
+ neon branches list --project-id <project-id>
134
135
 
135
136
  # Create feature branch from main
136
- neonctl branches create --project-id <project-id> \
137
+ neon branches create --project-id <project-id> \
137
138
  --name feature/my-feature \
138
139
  --parent main
139
140
 
140
141
  # Create branch with auto-expiration (CI/CD)
141
- neonctl branches create --project-id <project-id> \
142
+ neon branches create --project-id <project-id> \
142
143
  --name ci-test-run-42 \
143
144
  --parent main \
144
145
  --expires-at "2027-01-01T00:00:00Z"
145
146
 
146
147
  # Reset branch to parent state
147
- neonctl branches reset feature/my-feature --parent --project-id <project-id>
148
+ neon branches reset feature/my-feature --parent --project-id <project-id>
148
149
 
149
150
  # Delete branch
150
- neonctl branches delete feature/my-feature --project-id <project-id>
151
+ neon branches delete feature/my-feature --project-id <project-id>
151
152
  ```
152
153
 
153
154
  ### Branch Strategy
@@ -189,7 +190,7 @@ Set it when the branch (and its compute) is created; `main` already exists, so i
189
190
 
190
191
  ```bash
191
192
  # New branch with a 10-minute suspend timeout and an autoscaling range
192
- neonctl branches create --project-id <project-id> \
193
+ neon branches create --project-id <project-id> \
193
194
  --name feature/my-feature \
194
195
  --parent main \
195
196
  --suspend-timeout 600 \
@@ -5,7 +5,7 @@
5
5
  > **Keywords:** mcp, model-context-protocol, mcp-tools, context7, playwright, mcp-client
6
6
  > **Load When:** an MCP tool is used in any morph-spec phase
7
7
 
8
- **Verified against:** Claude Code 2.1.282 MCP tooling — context7, Playwright (as plugin and as a project MCP server); GitHub via `gh` CLI; Neon via its MCP or `neonctl`; Microsoft Learn MCP (`https://learn.microsoft.com/api/mcp`, tools listed by `tools/list` on 2026-10-17). Last-verified: 2026-10-17.
8
+ **Verified against:** Claude Code 2.1.282 MCP tooling — context7, Playwright (as plugin and as a project MCP server); GitHub via `gh` CLI; Neon via its MCP or `neon`; Microsoft Learn MCP (`https://learn.microsoft.com/api/mcp`, tools listed by `tools/list` on 2026-10-17). Last-verified: 2026-10-30.
9
9
 
10
10
  ---
11
11
 
@@ -19,7 +19,7 @@ In a morph persona the grant follows the same rule: the installer emits one `mcp
19
19
 
20
20
  ## MCP Availability Detection
21
21
 
22
- Before using any MCP tool, check if it's available in the current session. There is no "list MCPs" command: attempt the most common operation, and Claude Code reports a tool that doesn't exist. GitHub and Neon are not checked this way — o morph-spec NÃO usa MCP do GitHub nem do Neon: use o `gh` CLI (`gh repo view --json name,defaultBranchRef,languages`) e o `neonctl` + `psql` (`neonctl connection-string` dá a URL do banco) via Bash.
22
+ Before using any MCP tool, check if it's available in the current session. There is no "list MCPs" command: attempt the most common operation, and Claude Code reports a tool that doesn't exist. GitHub and Neon are not checked this way — o morph-spec NÃO usa MCP do GitHub nem do Neon: use o `gh` CLI (`gh repo view --json name,defaultBranchRef,languages`) e o `neon` + `psql` (`neon connection-string` dá a URL do banco) via Bash.
23
23
 
24
24
  ```javascript
25
25
  await mcp__context7__resolve-library-id({ libraryName: "react" });
@@ -136,7 +136,7 @@ Fallback: manual image creation, stock photos, or placeholder divs.
136
136
 
137
137
  | Tool | Use Case | Example |
138
138
  |------|----------|---------|
139
- | **Neon CLI (`neonctl`) / psql** | Database schema, tables, relationships, RLS | `psql <DB_URL> -c "SELECT ..."` |
139
+ | **Neon CLI (`neon`) / psql** | Database schema, tables, relationships, RLS | `psql <DB_URL> -c "SELECT ..."` |
140
140
  | **Context7** | Library docs for architecture decisions | `mcp__context7__query-docs()` |
141
141
  | **Microsoft Learn** (stack .NET) | Official docs for a .NET/EF Core/MAF decision (limits, what is new, migration) | `mcp__microsoft-learn__microsoft_docs_search({ query })` |
142
142
  | **GitHub CLI (`gh`)** | Check existing code patterns, PRs | `gh search code` (Bash) |
@@ -145,25 +145,25 @@ Fallback: manual image creation, stock photos, or placeholder divs.
145
145
  # === SCHEMA ANALYSIS (Critical for contracts.cs) ===
146
146
 
147
147
  # 0. Get Neon DB connection string
148
- neonctl connection-string
148
+ neon connection-string
149
149
  # → e.g.: postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/neondb?sslmode=require
150
150
 
151
151
  # 1. List all tables
152
- pg_dump $(neonctl connection-string) --schema-only --schema public 2>/dev/null | grep "CREATE TABLE"
152
+ pg_dump $(neon connection-string) --schema-only --schema public 2>/dev/null | grep "CREATE TABLE"
153
153
 
154
154
  # 2. Get schema for each relevant table
155
- psql $(neonctl connection-string) -c "SELECT column_name, data_type, is_nullable, column_default \
155
+ psql $(neon connection-string) -c "SELECT column_name, data_type, is_nullable, column_default \
156
156
  FROM information_schema.columns WHERE table_name = 'leads' ORDER BY ordinal_position"
157
157
 
158
158
  # 3. Get foreign key relationships
159
- psql $(neonctl connection-string) -c "SELECT tc.table_name, kcu.column_name, ccu.table_name AS foreign_table, \
159
+ psql $(neon connection-string) -c "SELECT tc.table_name, kcu.column_name, ccu.table_name AS foreign_table, \
160
160
  ccu.column_name AS foreign_column FROM information_schema.table_constraints tc \
161
161
  JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name \
162
162
  JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name \
163
163
  WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = 'leads'"
164
164
 
165
165
  # 4. Check RLS policies (security-critical)
166
- psql $(neonctl connection-string) -c "SELECT tablename, policyname, cmd, qual FROM pg_policies WHERE tablename = 'leads'"
166
+ psql $(neon connection-string) -c "SELECT tablename, policyname, cmd, qual FROM pg_policies WHERE tablename = 'leads'"
167
167
  ```
168
168
 
169
169
  **Fallback (Neon database not accessible):**
@@ -211,7 +211,7 @@ gh issue create --title "F1: Create Entity Lead" \
211
211
 
212
212
  | Tool | Use Case | Example |
213
213
  |------|----------|---------|
214
- | **Neon CLI (`neonctl`) / psql** | Run migrations, create RLS policies | `dotnet ef database update` |
214
+ | **Neon CLI (`neon`) / psql** | Run migrations, create RLS policies | `dotnet ef database update` |
215
215
  | **GitHub CLI (`gh`)** | Create PR, push branches | `gh pr create` (Bash) |
216
216
  | **Context7** | Look up API usage during coding | `mcp__context7__query-docs()` |
217
217
  | **Microsoft Learn** (stack .NET) | Current .NET 10 / EF Core / ASP.NET Core / MAF API: search, then fetch the page when the excerpt is cut | `mcp__microsoft-learn__microsoft_docs_search({ query })` → `microsoft_docs_fetch({ url })`; `microsoft_code_sample_search` for snippets |
@@ -230,10 +230,10 @@ dotnet ef migrations add AddStatusToLeads
230
230
  dotnet ef database update
231
231
 
232
232
  # Verify schema after migration
233
- psql $(neonctl connection-string) -c "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'leads'"
233
+ psql $(neon connection-string) -c "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'leads'"
234
234
 
235
235
  # Verify RLS policies
236
- psql $(neonctl connection-string) -c "SELECT policyname, cmd, qual FROM pg_policies WHERE tablename = 'leads'"
236
+ psql $(neon connection-string) -c "SELECT policyname, cmd, qual FROM pg_policies WHERE tablename = 'leads'"
237
237
  ```
238
238
 
239
239
  Look up the API while coding, then smoke test the deployed feature: the snapshot shows whether the page renders, the console messages catch JavaScript errors and failed API calls, and the screenshot goes to the slice report (`3-implement/reports/F{n}.md`). Vercel covers deployment status, logs and environment variables.
@@ -270,7 +270,7 @@ PRs/issues: sempre `gh` CLI (Bash). Deployments fallback: `vercel` CLI.
270
270
 
271
271
  | Need | MCP Tool | Native Alternative |
272
272
  |------|----------|--------------------|
273
- | Database schema | Neon CLI (`neonctl`) / psql | Grep queries + Read types |
273
+ | Database schema | Neon CLI (`neon`) / psql | Grep queries + Read types |
274
274
  | Repo metadata / issues / PRs | Bash `gh` CLI | WebFetch `api.github.com` (read-only) |
275
275
  | Library docs | Context7 | WebSearch + WebFetch |
276
276
  | Live page preview | Playwright MCP | WebFetch URL |
@@ -335,26 +335,26 @@ await mcp__playwright__browser_file_upload({ ref: "s1e20", paths: ["/path/to/fil
335
335
 
336
336
  ---
337
337
 
338
- ### Neon: Full Schema Discovery (via neonctl + psql)
338
+ ### Neon: Full Schema Discovery (via neon + psql)
339
339
 
340
- > **Primary:** Neon CLI (`neonctl`) + psql connecting to Neon database.
341
- > **Connection:** Always use `neonctl connection-string` to get the DB URL.
340
+ > **Primary:** Neon CLI (`neon`) + psql connecting to Neon database.
341
+ > **Connection:** Always use `neon connection-string` to get the DB URL.
342
342
 
343
343
  ```bash
344
344
  # Complete workflow for Phase 3 schema analysis
345
345
 
346
346
  # 1. Get Neon DB URL
347
- neonctl connection-string # → pooled connection string
347
+ neon connection-string # → pooled connection string
348
348
 
349
349
  # 2. List all tables
350
- pg_dump $(neonctl connection-string) --schema-only --schema public 2>/dev/null | grep "CREATE TABLE"
350
+ pg_dump $(neon connection-string) --schema-only --schema public 2>/dev/null | grep "CREATE TABLE"
351
351
 
352
352
  # 3. For each relevant table:
353
- psql $(neonctl connection-string) -c "SELECT column_name, data_type, is_nullable, column_default \
353
+ psql $(neon connection-string) -c "SELECT column_name, data_type, is_nullable, column_default \
354
354
  FROM information_schema.columns WHERE table_name = 'TABLE_NAME' ORDER BY ordinal_position"
355
355
 
356
356
  # 4. Get relationships
357
- psql $(neonctl connection-string) -c "SELECT tc.table_name, kcu.column_name, ccu.table_name AS foreign_table \
357
+ psql $(neon connection-string) -c "SELECT tc.table_name, kcu.column_name, ccu.table_name AS foreign_table \
358
358
  FROM information_schema.table_constraints tc \
359
359
  JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name \
360
360
  JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name \
@@ -397,7 +397,7 @@ gh api repos/{owner}/{repo}/branches --jq '.[].name'
397
397
  ## Security Considerations
398
398
 
399
399
  - **Never pass secrets** in MCP tool parameters (API keys, tokens, passwords)
400
- - **Neon** uses neonctl/psql — use database branches for development, not production
400
+ - **Neon** uses neon/psql — use database branches for development, not production
401
401
  - **GitHub via `gh` CLI** herda as permissões do login do `gh auth login` (keyring) — sem PAT em env var, sem Docker
402
402
  - **Always validate tool responses** before using in contracts or code generation
403
403
 
@@ -332,10 +332,9 @@
332
332
  "path": "docs/ui-mockups.md",
333
333
  "category": "documentation",
334
334
  "phase": "uiux",
335
- "description": "Wireframes and layout specifications with ASCII mockups and responsive breakpoints",
335
+ "description": "Por tela: protótipo HTML, direção escolhida, checklist de tela de 5 itens, componentes e fluxo",
336
336
  "outputName": "mockups.md",
337
337
  "placeholders": [
338
- "DATE",
339
338
  "FEATURE_NAME"
340
339
  ],
341
340
  "deprecated": false,
@@ -88,7 +88,7 @@
88
88
  ## Centralidade (grafo de codebase)
89
89
 
90
90
  Símbolos com mais conexões depois do saneamento — o que quebra mais se mudar.
91
- Detalhe de um símbolo: `morph-spec graph explain <nome>`.
91
+ Detalhe de um símbolo: `morph-spec graph explain <nome>` (sem grafo, símbolo ausente ou ambíguo: `grep -rn <nome>`).
92
92
 
93
93
  | Símbolo | Arquivo | Grau |
94
94
  |---------|---------|------|
@@ -7,6 +7,8 @@
7
7
 
8
8
  <O que dói hoje, para quem, e como se percebe. Duas a cinco frases.>
9
9
 
10
+ Resultado buscado: <o estado depois: o que muda, para quem, como se percebe.>
11
+
10
12
  ## Fora de escopo
11
13
 
12
14
  - <o que esta feature deliberadamente não faz>
@@ -15,10 +17,21 @@
15
17
 
16
18
  - <o que foi assumido sem prova; "nenhuma" vale>
17
19
 
20
+ ## Padrões assumidos
21
+
22
+ <!-- Valor de baixo risco que você decidiu sem perguntar, numerado: o usuário veta por número ("veta 2").
23
+ Auth, credencial, permissão, pagamento e apagar dado nunca entram aqui: viram pergunta. "nenhum" vale. -->
24
+
25
+ 1. <padrão e o valor escolhido>
26
+
27
+ <!-- Opcional, só se algo muda de estado: uma seção "Estados" (h2) com uma transição por linha,
28
+ "- origem → destino: gatilho". O plan-check desenha a máquina em 2-plan/plan.html. -->
29
+
18
30
  ## Cenários
19
31
 
20
32
  <!-- Um cenário por comportamento observável. `prova:` é teste | e2e | eval | manual | leitura.
21
33
  `prova: teste` exige `risco:` regra | dinheiro | contrato | concorrência | dado | regressão; sem risco, `leitura`.
34
+ `degrau:` migrar | irreversível quando um revert não desfaz (toda migration é migrar); sem a linha, refazer.
22
35
  Cenário que fala de arquivo, grep ou texto exige a linha "> Por que artefato:" logo abaixo. -->
23
36
 
24
37
  - **C1** — Dado <estado>, quando <ação>, então <resultado observável>.
@@ -56,19 +69,9 @@ nenhum
56
69
  |---|---|---|---|
57
70
  | <conceito> | REUSAR | <arquivo ou símbolo existente> | |
58
71
 
59
- ## Fatias
60
-
61
- <!-- Uma fatia = uma unidade de entrega (com ou sem dispatch), relatório em 3-implement/reports/Fn.md.
62
- arquivos ≤ 8; superfície e depende são opcionais; toda Cn é coberta por alguma fatia. -->
63
-
64
- ### F1 — <título>
65
- - persona: dotnet-senior
66
- - standards: <id>
67
- - arquivos: <caminho/a.cs>, <caminho/b.cs>
68
- - cobre: C1
69
-
70
72
  ## Contrato de implementação
71
73
 
72
- <Assinaturas, records, enums e rotas que as fatias precisam honrar.>
74
+ - **Instrumentos:** <o que falta para provar sozinho: ferramenta, acesso, dado, ambiente; "nenhuma lacuna" vale.>
75
+ - <Assinaturas, records, enums e rotas que a implementação honra; runtime do e2e; baseline de teste como comando.>
73
76
 
74
77
  ## Errata