coding-os 0.3.2__py3-none-any.whl
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.
- adapters/claude/README.md +6 -0
- adapters/claude/_install_helpers/extract_stacks.py +43 -0
- adapters/claude/_install_helpers/update_mcp_json.py +75 -0
- adapters/claude/adapter.yaml +164 -0
- adapters/claude/hooks/README.md +40 -0
- adapters/claude/hooks/agent_memory_sync.py +131 -0
- adapters/claude/hooks/ensure-agent-memory-link.sh +36 -0
- adapters/claude/hooks/sync-agent-memory.sh +21 -0
- adapters/claude/install.sh +86 -0
- adapters/claude/sdk_dispatcher.py +871 -0
- adapters/claude/settings.local.template.json +31 -0
- adapters/claude/settings.template.json +808 -0
- adapters/claude/update_mcp_json.py +85 -0
- adapters/codex/adapter.yaml +254 -0
- adapters/codex/chat_provider.py +230 -0
- adapters/codex/commands/formula-f1.md +129 -0
- adapters/codex/commands/formula-f10.md +100 -0
- adapters/codex/commands/formula-f11.md +123 -0
- adapters/codex/commands/formula-f2.md +139 -0
- adapters/codex/commands/formula-f3.md +127 -0
- adapters/codex/commands/formula-f4.md +101 -0
- adapters/codex/commands/formula-f5.md +135 -0
- adapters/codex/commands/formula-f6.md +147 -0
- adapters/codex/commands/formula-f7.md +111 -0
- adapters/codex/commands/formula-f8.md +133 -0
- adapters/codex/commands/formula-f9.md +112 -0
- adapters/codex/enable_codex_hooks.py +94 -0
- adapters/codex/ensure_codex_mcp.py +124 -0
- adapters/codex/hooks/codex-merge-hook-output.py +72 -0
- adapters/codex/hooks/codex-normalize-edit.py +96 -0
- adapters/codex/hooks/codex-postedit-dispatch.sh +75 -0
- adapters/codex/hooks/codex-posttool-dispatch.sh +70 -0
- adapters/codex/hooks/codex-preedit-dispatch.sh +83 -0
- adapters/codex/hooks/codex-pretool-dispatch.sh +82 -0
- adapters/codex/hooks/codex-sessionend-dispatch.sh +20 -0
- adapters/codex/hooks/codex-sessionstart-dispatch.sh +68 -0
- adapters/codex/hooks/codex-stop-dispatch.sh +73 -0
- adapters/codex/hooks/codex-userpromptsubmit-dispatch.sh +74 -0
- adapters/codex/hooks.template.json +208 -0
- adapters/codex/install.sh +83 -0
- adapters/codex/sdk_dispatcher.py +449 -0
- board_os/__init__.py +39 -0
- board_os/_agent_runtime.py +256 -0
- board_os/config.py +421 -0
- board_os/git_coherence.py +107 -0
- board_os/hub_adapter_manifest.py +140 -0
- board_os/mcp_tools.py +3228 -0
- board_os/migration.py +166 -0
- board_os/parser.py +317 -0
- board_os/presence.py +156 -0
- board_os/sync.py +320 -0
- board_os/transition_gates.py +224 -0
- board_os/transition_gates_cli.py +272 -0
- board_os/transition_gates_validator.py +551 -0
- board_os/verify_suites.py +126 -0
- board_os/verify_suites_cli.py +328 -0
- board_os/workflow.py +967 -0
- cli/__init__.py +0 -0
- cli/_data_types.py +248 -0
- cli/_init_helpers.py +587 -0
- cli/_resources.py +100 -0
- cli/adapter_registry.py +239 -0
- cli/add_stack.py +315 -0
- cli/aggregator.py +438 -0
- cli/board_commands.py +1218 -0
- cli/brain_commands.py +255 -0
- cli/cognition.py +345 -0
- cli/config_composer.py +349 -0
- cli/core_version.py +41 -0
- cli/cron_commands.py +278 -0
- cli/db_reset.py +298 -0
- cli/doc_commands.py +111 -0
- cli/doctor.py +2953 -0
- cli/doctor_board.py +365 -0
- cli/doctor_extras.py +1121 -0
- cli/doctor_graph.py +608 -0
- cli/doctor_tokens.py +254 -0
- cli/graph_commands.py +1265 -0
- cli/hook_renderer.py +393 -0
- cli/hub_commands.py +580 -0
- cli/list_adapters.py +79 -0
- cli/list_stacks.py +105 -0
- cli/logs_commands.py +89 -0
- cli/main.py +3070 -0
- cli/materialize_file.py +65 -0
- cli/mcp_start.py +153 -0
- cli/module_commands.py +513 -0
- cli/pr_commands.py +2024 -0
- cli/preset_commands.py +126 -0
- cli/preset_registry.py +171 -0
- cli/project_overrides.py +119 -0
- cli/registry.py +365 -0
- cli/remove_stack.py +492 -0
- cli/renderer.py +620 -0
- cli/setup.py +464 -0
- cli/skill_commands.py +689 -0
- cli/skill_registry.py +235 -0
- cli/skills_list.py +332 -0
- cli/stack_lint.py +351 -0
- cli/stack_registry.py +688 -0
- cli/subsystems.py +335 -0
- cli/sync_all.py +310 -0
- cli/tail_command.py +410 -0
- cli/update.py +608 -0
- cli/verify_since_edit.py +439 -0
- coding_os-0.3.2.dist-info/METADATA +508 -0
- coding_os-0.3.2.dist-info/RECORD +1304 -0
- coding_os-0.3.2.dist-info/WHEEL +5 -0
- coding_os-0.3.2.dist-info/entry_points.txt +5 -0
- coding_os-0.3.2.dist-info/licenses/LICENSE +201 -0
- coding_os-0.3.2.dist-info/top_level.txt +10 -0
- core/__init__.py +0 -0
- core/board_os/__init__.py +39 -0
- core/board_os/_agent_runtime.py +256 -0
- core/board_os/config.py +421 -0
- core/board_os/git_coherence.py +107 -0
- core/board_os/hub_adapter_manifest.py +140 -0
- core/board_os/mcp_tools.py +3228 -0
- core/board_os/migration.py +166 -0
- core/board_os/parser.py +317 -0
- core/board_os/presence.py +156 -0
- core/board_os/sync.py +320 -0
- core/board_os/transition-gates.yaml +176 -0
- core/board_os/transition_gates.py +224 -0
- core/board_os/transition_gates_cli.py +272 -0
- core/board_os/transition_gates_validator.py +551 -0
- core/board_os/verify-suites.yaml +113 -0
- core/board_os/verify_suites.py +126 -0
- core/board_os/verify_suites_cli.py +328 -0
- core/board_os/workflow.py +967 -0
- core/commands/board.md +27 -0
- core/commands/classify.md +23 -0
- core/commands/compose.md +23 -0
- core/commands/daily.md +31 -0
- core/commands/diagnose.md +7 -0
- core/commands/memory-search.md +23 -0
- core/commands/new-project.md +33 -0
- core/commands/retro.md +38 -0
- core/commands/review.md +14 -0
- core/commands/task.md +17 -0
- core/commands/verify.md +34 -0
- core/docs/thinking_os-final-edition.md +1449 -0
- core/doctor-config.yaml +74 -0
- core/graph_os/__init__.py +29 -0
- core/graph_os/backend.py +233 -0
- core/graph_os/backends/__init__.py +13 -0
- core/graph_os/backends/sqlite_backend.py +1053 -0
- core/graph_os/bench/__init__.py +17 -0
- core/graph_os/bench/fixtures.py +56 -0
- core/graph_os/bench/harness.py +95 -0
- core/graph_os/bench/persian_precision.py +142 -0
- core/graph_os/bench/scale_500k.py +120 -0
- core/graph_os/bench/token_cost.py +170 -0
- core/graph_os/bench/viewer_fps.py +110 -0
- core/graph_os/communities.py +410 -0
- core/graph_os/enterprise.py +218 -0
- core/graph_os/entry_points.py +226 -0
- core/graph_os/extractors/__init__.py +25 -0
- core/graph_os/extractors/code_generic.py +914 -0
- core/graph_os/extractors/code_go.py +1422 -0
- core/graph_os/extractors/code_json.py +340 -0
- core/graph_os/extractors/code_php.py +979 -0
- core/graph_os/extractors/code_python.py +1454 -0
- core/graph_os/extractors/code_shell.py +538 -0
- core/graph_os/extractors/code_toml.py +302 -0
- core/graph_os/extractors/code_ts.py +1665 -0
- core/graph_os/extractors/code_yaml.py +394 -0
- core/graph_os/extractors/contracts.py +1592 -0
- core/graph_os/extractors/md_links.py +890 -0
- core/graph_os/extractors/task_deps.py +345 -0
- core/graph_os/groups/__init__.py +22 -0
- core/graph_os/groups/cross_repo.py +156 -0
- core/graph_os/groups/manifest.py +141 -0
- core/graph_os/ingest/__init__.py +19 -0
- core/graph_os/ingest/base.py +306 -0
- core/graph_os/ingest/github.py +112 -0
- core/graph_os/ingest/zip.py +95 -0
- core/graph_os/toolchain.py +393 -0
- core/graph_os/tools/__init__.py +9 -0
- core/graph_os/tools/graph.py +5573 -0
- core/graph_os/tools/reindex_dispatch.py +730 -0
- core/graph_os/tree_sitter_overlay.py +235 -0
- core/graph_os/types.py +252 -0
- core/graph_os/vec_index.py +277 -0
- core/graph_os/viewer/__init__.py +12 -0
- core/graph_os/viewer/exporter.py +93 -0
- core/graph_os/viewer/template.py +189 -0
- core/hooks/_helpers/_paths.py +40 -0
- core/hooks/_helpers/advance_role.py +72 -0
- core/hooks/_helpers/auto_compose.py +228 -0
- core/hooks/_helpers/auto_validate_lessons.py +55 -0
- core/hooks/_helpers/branch_guard_check.py +796 -0
- core/hooks/_helpers/check_commit_message.py +108 -0
- core/hooks/_helpers/check_dangerous_rm.py +80 -0
- core/hooks/_helpers/check_git_bypass.py +154 -0
- core/hooks/_helpers/check_git_destructive.py +77 -0
- core/hooks/_helpers/check_settings_write.py +97 -0
- core/hooks/_helpers/consume_override.py +51 -0
- core/hooks/_helpers/context_budget.py +77 -0
- core/hooks/_helpers/cos_say_json.py +103 -0
- core/hooks/_helpers/destructive_edit_check.py +163 -0
- core/hooks/_helpers/detect_status_transition.py +82 -0
- core/hooks/_helpers/digest_regen.py +56 -0
- core/hooks/_helpers/doc_sync_check.py +498 -0
- core/hooks/_helpers/drain_embedding_outbox.py +52 -0
- core/hooks/_helpers/extract_additional_context.py +51 -0
- core/hooks/_helpers/extract_commit_msg_arg.py +74 -0
- core/hooks/_helpers/git_command_parse.py +424 -0
- core/hooks/_helpers/git_settings_fields.py +47 -0
- core/hooks/_helpers/graph_context_match.py +37 -0
- core/hooks/_helpers/graph_marker_check.py +70 -0
- core/hooks/_helpers/jit_recall.py +56 -0
- core/hooks/_helpers/json_field.py +41 -0
- core/hooks/_helpers/narrative_signal.py +59 -0
- core/hooks/_helpers/observation_count.py +31 -0
- core/hooks/_helpers/pre_commit_batch.py +177 -0
- core/hooks/_helpers/pre_commit_fake_input.py +42 -0
- core/hooks/_helpers/presence_gc.py +102 -0
- core/hooks/_helpers/presence_write.py +167 -0
- core/hooks/_helpers/recover_indirect.py +35 -0
- core/hooks/_helpers/routing_evolution.py +104 -0
- core/hooks/_helpers/session_recap.py +72 -0
- core/hooks/_helpers/skill_primer.py +229 -0
- core/hooks/_helpers/task_sync.py +59 -0
- core/hooks/_helpers/tool_failure_capture.py +147 -0
- core/hooks/_helpers/trajectory_autosnap.py +278 -0
- core/hooks/_helpers/trajectory_startup.py +62 -0
- core/hooks/_helpers/turn_summary.py +82 -0
- core/hooks/_helpers/validate_task_frontmatter.py +98 -0
- core/hooks/_helpers/wip_limit_check.py +103 -0
- core/hooks/_helpers/wip_lines.py +53 -0
- core/hooks/_helpers/work_log_append.py +89 -0
- core/hooks/_helpers/wrap_dispatch_output.py +82 -0
- core/hooks/advance-role.sh +48 -0
- core/hooks/agent-presence.sh +179 -0
- core/hooks/auto-brain-decay.sh +184 -0
- core/hooks/auto-compose-roles.sh +83 -0
- core/hooks/auto-graph-reconcile-shell.sh +119 -0
- core/hooks/auto-regen-doc-index.sh +120 -0
- core/hooks/auto-reindex-docs.sh +130 -0
- core/hooks/auto-task-sync.sh +56 -0
- core/hooks/auto-trace-rotate.sh +88 -0
- core/hooks/block-bad-patterns.sh +212 -0
- core/hooks/block-dangerous-commands.sh +182 -0
- core/hooks/block-hardcoded-literals.sh +90 -0
- core/hooks/block-migration-conflict.sh +114 -0
- core/hooks/block-protected-files.sh +129 -0
- core/hooks/block-secrets.sh +185 -0
- core/hooks/block-shared-tree-edit.sh +75 -0
- core/hooks/block-uv-heredoc.sh +78 -0
- core/hooks/branch-guard.sh +122 -0
- core/hooks/capture-observation.sh +76 -0
- core/hooks/capture-tool-failure.sh +24 -0
- core/hooks/capture-work-log.sh +89 -0
- core/hooks/check-agents-md-refs.sh +75 -0
- core/hooks/check-agents-md-size.sh +49 -0
- core/hooks/check-capture-worked.sh +148 -0
- core/hooks/check-doc-size.sh +61 -0
- core/hooks/check-mcp-extras.sh +92 -0
- core/hooks/check-state.sh +87 -0
- core/hooks/classify-task-mode.sh +103 -0
- core/hooks/cos-env.sh +1301 -0
- core/hooks/drain-embedding-outbox.sh +24 -0
- core/hooks/enforce-anti-ambiguity.sh +74 -0
- core/hooks/enforce-commit-message.sh +73 -0
- core/hooks/enforce-doc-anchor.sh +224 -0
- core/hooks/enforce-doc-sync.sh +206 -0
- core/hooks/enforce-graph-context.sh +89 -0
- core/hooks/enforce-graph-first-read.sh +94 -0
- core/hooks/enforce-memory-check.sh +128 -0
- core/hooks/enforce-rename-plan.sh +78 -0
- core/hooks/enforce-scaffold-boundary.sh +68 -0
- core/hooks/enforce-skill.sh +125 -0
- core/hooks/enforce-task-body.sh +52 -0
- core/hooks/enforce-task-start.sh +81 -0
- core/hooks/enforce-task-transition.sh +75 -0
- core/hooks/enforce-template.sh +143 -0
- core/hooks/enforce-verify.sh +112 -0
- core/hooks/enforce-wip-limit.sh +43 -0
- core/hooks/enforce-zoom.sh +69 -0
- core/hooks/ensure-hub-up.sh +67 -0
- core/hooks/inject-mcp-caller-session.sh +70 -0
- core/hooks/jit-recall.sh +65 -0
- core/hooks/link-commit-to-task.sh +143 -0
- core/hooks/lint-task.sh +40 -0
- core/hooks/nudge-docs-first.sh +71 -0
- core/hooks/nudge-git-mode.sh +29 -0
- core/hooks/nudge-graph-os.sh +118 -0
- core/hooks/nudge-learn-narrative.sh +36 -0
- core/hooks/nudge-model-routing.sh +32 -0
- core/hooks/nudge-reentry.sh +101 -0
- core/hooks/nudge-reuse-first.sh +68 -0
- core/hooks/nudge-task-discovery.sh +81 -0
- core/hooks/nudge-thinking-os.sh +109 -0
- core/hooks/pr-reap.sh +23 -0
- core/hooks/reclaim-sweep.sh +58 -0
- core/hooks/record-verify-auto.sh +77 -0
- core/hooks/record-verify.sh +74 -0
- core/hooks/regen-reminder.sh +104 -0
- core/hooks/registry.yaml +1262 -0
- core/hooks/remind-daily.sh +27 -0
- core/hooks/remind-dogfood.sh +70 -0
- core/hooks/remind-learn-validate.sh +94 -0
- core/hooks/rules-primer.sh +50 -0
- core/hooks/search-enforce-inventory.sh +108 -0
- core/hooks/search-verify-remaining.sh +132 -0
- core/hooks/session-context.sh +729 -0
- core/hooks/session-end.sh +145 -0
- core/hooks/session-skill-primer.sh +43 -0
- core/hooks/snapshot-transcript.sh +56 -0
- core/hooks/sync-task-current.sh +85 -0
- core/hooks/test-first-reminder.sh +120 -0
- core/hooks/test-governor.sh +173 -0
- core/hooks/thinking_os-gate.sh +52 -0
- core/hooks/track-backtrack.sh +35 -0
- core/hooks/track-discovery.sh +121 -0
- core/hooks/track-skill.sh +53 -0
- core/hooks/validate-task-frontmatter.sh +49 -0
- core/hooks/verify-rename-callers.sh +119 -0
- core/hooks/warn-abandoned-task.sh +99 -0
- core/hooks/warn-destructive-edit.sh +64 -0
- core/hooks/warn-diff-size.sh +43 -0
- core/hooks/warn-graph-empty.sh +81 -0
- core/hooks/warn-mcp-down.sh +190 -0
- core/hooks/write-state.sh +55 -0
- core/logging_os/__init__.py +33 -0
- core/logging_os/api.py +127 -0
- core/logging_os/bridge.py +80 -0
- core/logging_os/config.py +172 -0
- core/logging_os/fingerprint.py +25 -0
- core/logging_os/redact.py +53 -0
- core/logging_os/render.py +83 -0
- core/logging_os/sinks.py +164 -0
- core/rules/anti-overengineering.md +44 -0
- core/rules/api-contract-discipline.md +41 -0
- core/rules/dimension-registry.md +155 -0
- core/rules/git-workflow.md +57 -0
- core/rules/memory.md +46 -0
- core/rules/model-routing.md +22 -0
- core/rules/skill-enforcement.md +75 -0
- core/rules/test-discipline.md +38 -0
- core/rules/thinking_os.md +48 -0
- core/rules/transparency-banner.md +37 -0
- core/runtime_paths.yaml +36 -0
- core/scaffold_manifest.json +14430 -0
- core/scheduled/__init__.py +0 -0
- core/scheduled/_activity.py +126 -0
- core/scheduled/_state.py +113 -0
- core/scheduled/config.py +86 -0
- core/scheduled/dep_reconcile.py +135 -0
- core/scheduled/error_sweep.py +137 -0
- core/scheduled/nightly.py +930 -0
- core/scheduled/responsive_extract.py +65 -0
- core/schemas/adapter.schema.json +269 -0
- core/schemas/preset.schema.json +50 -0
- core/schemas/skill.schema.json +81 -0
- core/schemas/stack.schema.json +404 -0
- core/scripts/_lib.sh +9 -0
- core/scripts/docs-lint.sh +228 -0
- core/scripts/docs-nav-fix.sh +133 -0
- core/scripts/docs-staleness-check.sh +154 -0
- core/scripts/install-adapter.sh +266 -0
- core/scripts/link-stack-skills.sh +52 -0
- core/scripts/log-latest.sh +106 -0
- core/scripts/log-search.sh +89 -0
- core/scripts/log-write.sh +134 -0
- core/scripts/ref-resolve.sh +71 -0
- core/skills/a11y/SKILL.md +305 -0
- core/skills/a11y/assets/a11y-checklist.md +137 -0
- core/skills/a11y/references/aria-and-focus.md +247 -0
- core/skills/a11y/references/rn-accessibility.md +343 -0
- core/skills/a11y/references/screen-reader-testing.md +190 -0
- core/skills/agent-memory/SKILL.md +191 -0
- core/skills/agent-memory/assets/memory-checklist.md +21 -0
- core/skills/agent-memory/references/memory-recipes.md +57 -0
- core/skills/api-design/SKILL.md +232 -0
- core/skills/api-design/assets/api-design-checklist.md +110 -0
- core/skills/api-design/references/error-envelope.md +381 -0
- core/skills/api-design/references/idempotency-pagination.md +312 -0
- core/skills/api-design/references/rest-contracts.md +426 -0
- core/skills/auth-patterns/SKILL.md +352 -0
- core/skills/auth-patterns/assets/auth-checklist.md +118 -0
- core/skills/auth-patterns/references/jwt-and-service-tokens.md +343 -0
- core/skills/auth-patterns/references/passkeys-2fa.md +289 -0
- core/skills/auth-patterns/references/sessions-vs-jwt.md +230 -0
- core/skills/auth-patterns/scripts/cookie-flag-check.py +146 -0
- core/skills/backend-fundamentals/SKILL.md +238 -0
- core/skills/backend-fundamentals/assets/backend-checklist.md +27 -0
- core/skills/backend-fundamentals/references/backend-patterns.md +56 -0
- core/skills/backend-fundamentals/scripts/check_layering.py +83 -0
- core/skills/clean-code/SKILL.md +642 -0
- core/skills/clean-code/scripts/audit-fail-closed.py +167 -0
- core/skills/codebase-explorer/SKILL.md +89 -0
- core/skills/codebase-explorer/assets/reading-checklist.md +24 -0
- core/skills/codebase-explorer/references/reading-strategies.md +52 -0
- core/skills/codebase-explorer/scripts/outline.py +99 -0
- core/skills/db-design/SKILL.md +327 -0
- core/skills/db-design/assets/migration-template.sql +49 -0
- core/skills/db-design/references/migration-discipline.md +290 -0
- core/skills/db-design/references/postgres-patterns.md +340 -0
- core/skills/db-design/scripts/migration-safety.sh +150 -0
- core/skills/deployment-cicd/SKILL.md +260 -0
- core/skills/deployment-cicd/assets/deploy-checklist.md +26 -0
- core/skills/deployment-cicd/references/pipeline-and-release.md +54 -0
- core/skills/deployment-cicd/scripts/lint_workflow.py +79 -0
- core/skills/docker/SKILL.md +114 -0
- core/skills/docker/assets/dockerfile-checklist.md +31 -0
- core/skills/docker/references/compose-patterns.md +66 -0
- core/skills/docker/references/dockerfile-optimization.md +64 -0
- core/skills/docker/scripts/lint_dockerfile.sh +48 -0
- core/skills/docker/versions.json +16 -0
- core/skills/end-to-end-testing/SKILL.md +101 -0
- core/skills/end-to-end-testing/assets/e2e-checklist.md +23 -0
- core/skills/end-to-end-testing/references/maestro.md +63 -0
- core/skills/end-to-end-testing/references/playwright.md +68 -0
- core/skills/end-to-end-testing/scripts/lint_e2e.py +88 -0
- core/skills/end-to-end-testing/versions.json +16 -0
- core/skills/frontend-design/SKILL.md +76 -0
- core/skills/frontend-design/assets/design-checklist.md +29 -0
- core/skills/frontend-design/references/design-principles.md +65 -0
- core/skills/frontend-design/scripts/check_contrast.py +89 -0
- core/skills/frontend-fundamentals/SKILL.md +213 -0
- core/skills/frontend-fundamentals/assets/frontend-checklist.md +25 -0
- core/skills/frontend-fundamentals/references/rendering-and-state.md +66 -0
- core/skills/frontend-fundamentals/scripts/check_frontend.py +86 -0
- core/skills/graph-explorer/SKILL.md +215 -0
- core/skills/graph-explorer/scripts/explain-impact.sh +64 -0
- core/skills/graphql/SKILL.md +187 -0
- core/skills/grpc-microservices/SKILL.md +174 -0
- core/skills/hexagonal-architecture/SKILL.md +199 -0
- core/skills/hexagonal-architecture/assets/folder-scaffold.md +233 -0
- core/skills/hexagonal-architecture/references/anti-patterns.md +129 -0
- core/skills/hexagonal-architecture/references/go-fiber-layout.md +429 -0
- core/skills/hexagonal-architecture/references/python-fastapi-layout.md +453 -0
- core/skills/hexagonal-architecture/references/react-native-layout.md +428 -0
- core/skills/i18n/SKILL.md +126 -0
- core/skills/incident-response/SKILL.md +225 -0
- core/skills/incident-response/assets/incident-checklist.md +29 -0
- core/skills/incident-response/references/severity-and-runbook.md +53 -0
- core/skills/incident-response/scripts/classify_severity.py +86 -0
- core/skills/linux-sysadmin/SKILL.md +115 -0
- core/skills/linux-sysadmin/assets/hardening-checklist.md +29 -0
- core/skills/linux-sysadmin/references/ssh-hardening.md +62 -0
- core/skills/linux-sysadmin/references/systemd-and-services.md +77 -0
- core/skills/linux-sysadmin/scripts/triage.sh +50 -0
- core/skills/linux-sysadmin/versions.json +17 -0
- core/skills/llm-patterns/SKILL.md +410 -0
- core/skills/llm-patterns/assets/llm-feature-checklist.md +26 -0
- core/skills/llm-patterns/references/rag-and-evals.md +59 -0
- core/skills/llm-patterns/scripts/estimate_tokens.py +75 -0
- core/skills/messaging-queues/SKILL.md +142 -0
- core/skills/mobile-fundamentals/SKILL.md +406 -0
- core/skills/mobile-fundamentals/assets/mobile-launch-checklist.md +130 -0
- core/skills/mobile-fundamentals/references/navigation-and-deep-links.md +337 -0
- core/skills/mobile-fundamentals/references/offline-sync.md +339 -0
- core/skills/node-backend/SKILL.md +114 -0
- core/skills/node-backend/assets/node-checklist.md +25 -0
- core/skills/node-backend/references/async-and-errors.md +67 -0
- core/skills/node-backend/references/event-loop.md +65 -0
- core/skills/node-backend/scripts/check_package.py +78 -0
- core/skills/node-backend/versions.json +17 -0
- core/skills/observability/SKILL.md +289 -0
- core/skills/observability/assets/observability-checklist.md +27 -0
- core/skills/observability/references/instrumentation.md +57 -0
- core/skills/observability/scripts/lint_logging.py +77 -0
- core/skills/payments/SKILL.md +102 -0
- core/skills/performance/SKILL.md +305 -0
- core/skills/performance/assets/perf-checklist.md +143 -0
- core/skills/performance/references/mobile-performance.md +249 -0
- core/skills/performance/references/web-vitals.md +209 -0
- core/skills/php/SKILL.md +116 -0
- core/skills/php/assets/php-checklist.md +26 -0
- core/skills/php/references/modern-php.md +64 -0
- core/skills/php/references/security.md +72 -0
- core/skills/php/scripts/scan_php_smells.py +99 -0
- core/skills/php/versions.json +9 -0
- core/skills/pr-mode-driver/SKILL.md +65 -0
- core/skills/realtime-websockets/SKILL.md +152 -0
- core/skills/redis/SKILL.md +105 -0
- core/skills/redis/assets/redis-checklist.md +27 -0
- core/skills/redis/references/operations.md +66 -0
- core/skills/redis/references/patterns.md +62 -0
- core/skills/redis/scripts/analyze_info.py +101 -0
- core/skills/redis/versions.json +9 -0
- core/skills/search/SKILL.md +91 -0
- core/skills/search/references/grep.md +76 -0
- core/skills/search/scripts/verify-count.sh +73 -0
- core/skills/search-infra/SKILL.md +109 -0
- core/skills/security-mobile/SKILL.md +394 -0
- core/skills/security-mobile/assets/mobile-security-checklist.md +117 -0
- core/skills/security-mobile/references/masvs-l1-checklist.md +127 -0
- core/skills/security-web/SKILL.md +217 -0
- core/skills/security-web/assets/security-web-checklist.md +167 -0
- core/skills/security-web/references/owasp-top-10.md +551 -0
- core/skills/security-web/references/supply-chain.md +179 -0
- core/skills/security-web/scripts/csp-check.sh +153 -0
- core/skills/shell-scripting/SKILL.md +128 -0
- core/skills/shell-scripting/assets/script-checklist.md +33 -0
- core/skills/shell-scripting/references/argument-parsing.md +84 -0
- core/skills/shell-scripting/references/bash-robustness.md +78 -0
- core/skills/shell-scripting/scripts/lint_script.sh +53 -0
- core/skills/shell-scripting/scripts/new_script.py +131 -0
- core/skills/shell-scripting/versions.json +23 -0
- core/skills/sql-authoring/SKILL.md +104 -0
- core/skills/sql-authoring/assets/query-review-checklist.md +26 -0
- core/skills/sql-authoring/references/query-patterns.md +89 -0
- core/skills/sql-authoring/references/reading-explain.md +52 -0
- core/skills/sql-authoring/scripts/analyze_plan.py +100 -0
- core/skills/sql-authoring/versions.json +17 -0
- core/skills/state-management/SKILL.md +428 -0
- core/skills/state-management/references/tanstack-query-recipes.md +301 -0
- core/skills/state-management/references/zustand-recipes.md +364 -0
- core/skills/supabase/SKILL.md +108 -0
- core/skills/supabase/assets/supabase-checklist.md +26 -0
- core/skills/supabase/references/realtime-and-storage.md +55 -0
- core/skills/supabase/references/rls-and-auth.md +65 -0
- core/skills/supabase/scripts/check_rls.py +88 -0
- core/skills/supabase/versions.json +9 -0
- core/skills/task-driver/SKILL.md +272 -0
- core/skills/task-driver/scripts/task-lint.sh +163 -0
- core/skills/technical-writing/SKILL.md +85 -0
- core/skills/technical-writing/assets/doc-checklist.md +29 -0
- core/skills/technical-writing/references/doc-anatomy.md +53 -0
- core/skills/technical-writing/references/writing-craft.md +59 -0
- core/skills/technical-writing/scripts/new_doc.py +81 -0
- core/skills/terraform-k8s/SKILL.md +133 -0
- core/skills/testing-strategy/SKILL.md +266 -0
- core/skills/testing-strategy/assets/test-review-checklist.md +25 -0
- core/skills/testing-strategy/references/test-types.md +52 -0
- core/skills/testing-strategy/scripts/coverage_gate.py +79 -0
- core/skills/thinking_os/SKILL.md +288 -0
- core/skills/thinking_os/scripts/classify.sh +122 -0
- core/skills/typescript/SKILL.md +110 -0
- core/skills/typescript/assets/typescript-checklist.md +24 -0
- core/skills/typescript/references/strictness.md +53 -0
- core/skills/typescript/references/type-system.md +86 -0
- core/skills/typescript/scripts/check_tsconfig.py +92 -0
- core/skills/typescript/versions.json +9 -0
- core/subsystems.yaml +202 -0
- core/thinking_os/__init__.py +1 -0
- core/thinking_os/_agent_markers.py +32 -0
- core/thinking_os/agents/README.md +71 -0
- core/thinking_os/agents/analyst.md +139 -0
- core/thinking_os/agents/architect.md +127 -0
- core/thinking_os/agents/debugger.md +111 -0
- core/thinking_os/agents/deployer.md +112 -0
- core/thinking_os/agents/distiller.md +28 -0
- core/thinking_os/agents/documenter.md +101 -0
- core/thinking_os/agents/implementer.md +135 -0
- core/thinking_os/agents/internal/session_observer.md +39 -0
- core/thinking_os/agents/observer.md +100 -0
- core/thinking_os/agents/onboarder.md +81 -0
- core/thinking_os/agents/refactorer.md +123 -0
- core/thinking_os/agents/repairer.md +47 -0
- core/thinking_os/agents/researcher.md +129 -0
- core/thinking_os/agents/reviewer.md +147 -0
- core/thinking_os/agents/security_auditor.md +133 -0
- core/thinking_os/background.py +405 -0
- core/thinking_os/bootstrap_outcomes.py +200 -0
- core/thinking_os/budget.py +302 -0
- core/thinking_os/capture.py +495 -0
- core/thinking_os/cognition.py +516 -0
- core/thinking_os/cognition_schemas.py +517 -0
- core/thinking_os/compress.py +192 -0
- core/thinking_os/concepts.py +233 -0
- core/thinking_os/dashboard.py +159 -0
- core/thinking_os/database.py +2883 -0
- core/thinking_os/decay.py +393 -0
- core/thinking_os/digest.py +295 -0
- core/thinking_os/dispatcher.py +192 -0
- core/thinking_os/dispatcher_helpers.py +48 -0
- core/thinking_os/dispatchers/__init__.py +3 -0
- core/thinking_os/dispatchers/default.py +47 -0
- core/thinking_os/distill.py +192 -0
- core/thinking_os/doc_indexer.py +905 -0
- core/thinking_os/embeddings.py +943 -0
- core/thinking_os/formula_composer.py +556 -0
- core/thinking_os/gate_marker.py +75 -0
- core/thinking_os/graph.py +296 -0
- core/thinking_os/graph_indexer.py +360 -0
- core/thinking_os/health_check.py +517 -0
- core/thinking_os/impact.py +119 -0
- core/thinking_os/memory_gc.py +356 -0
- core/thinking_os/migrator_embeddings.py +318 -0
- core/thinking_os/precision.py +194 -0
- core/thinking_os/presets/registry.yaml +127 -0
- core/thinking_os/record_outcome.py +399 -0
- core/thinking_os/repair.py +105 -0
- core/thinking_os/retrieval_quality.py +239 -0
- core/thinking_os/roles/analyst.yaml +83 -0
- core/thinking_os/roles/architect.yaml +88 -0
- core/thinking_os/roles/debugger.yaml +71 -0
- core/thinking_os/roles/deployer.yaml +71 -0
- core/thinking_os/roles/documenter.yaml +72 -0
- core/thinking_os/roles/implementer.yaml +83 -0
- core/thinking_os/roles/observer.yaml +70 -0
- core/thinking_os/roles/refactorer.yaml +71 -0
- core/thinking_os/roles/researcher.yaml +72 -0
- core/thinking_os/roles/reviewer.yaml +79 -0
- core/thinking_os/roles/security_auditor.yaml +83 -0
- core/thinking_os/roles_state.py +168 -0
- core/thinking_os/sanitizer.py +320 -0
- core/thinking_os/server.py +3160 -0
- core/thinking_os/session_enrich.py +272 -0
- core/thinking_os/session_observe_worker.py +111 -0
- core/thinking_os/session_startup.py +74 -0
- core/thinking_os/session_summary.py +245 -0
- core/thinking_os/situations/registry.yaml +99 -0
- core/thinking_os/task_analyzer.py +462 -0
- core/thinking_os/task_parser.py +342 -0
- core/thinking_os/task_sync.py +73 -0
- core/thinking_os/tools/__init__.py +6 -0
- core/thinking_os/tools/_shared.py +947 -0
- core/thinking_os/tools/cognition.py +1867 -0
- core/thinking_os/tools/docs.py +770 -0
- core/thinking_os/tools/learning.py +2078 -0
- core/thinking_os/tools/logs.py +79 -0
- core/thinking_os/tools/memory.py +840 -0
- core/thinking_os/tools/metrics.py +200 -0
- core/thinking_os/tools/retrieve.py +415 -0
- core/thinking_os/tools/routing.py +658 -0
- core/thinking_os/tools/tasks.py +449 -0
- core/thinking_os/tools/trajectory.py +181 -0
- core/thinking_os/tracing.py +235 -0
- core/web/__init__.py +5 -0
- core/web/_cache.py +118 -0
- core/web/_deps.py +56 -0
- core/web/_envelope.py +85 -0
- core/web/_project_context.py +140 -0
- core/web/chat_providers.py +108 -0
- core/web/init_jobs.py +216 -0
- core/web/routes/__init__.py +25 -0
- core/web/routes/_bounded_read.py +76 -0
- core/web/routes/board.py +1089 -0
- core/web/routes/cognition.py +1838 -0
- core/web/routes/config.py +635 -0
- core/web/routes/graph.py +513 -0
- core/web/routes/health.py +180 -0
- core/web/routes/hooks.py +288 -0
- core/web/routes/hub.py +1219 -0
- core/web/routes/logs.py +374 -0
- core/web/routes/metrics.py +43 -0
- core/web/routes/observability.py +400 -0
- core/web/routes/patterns.py +227 -0
- core/web/routes/presence.py +609 -0
- core/web/routes/roles.py +446 -0
- core/web/routes/scheduled.py +261 -0
- core/web/routes/search.py +238 -0
- core/web/routes/sessions.py +220 -0
- core/web/routes/settings.py +363 -0
- core/web/routes/stream.py +547 -0
- core/web/security.py +157 -0
- core/web/server.py +283 -0
- graph_os/__init__.py +29 -0
- graph_os/backend.py +233 -0
- graph_os/backends/__init__.py +13 -0
- graph_os/backends/sqlite_backend.py +1053 -0
- graph_os/communities.py +410 -0
- graph_os/enterprise.py +218 -0
- graph_os/entry_points.py +226 -0
- graph_os/extractors/__init__.py +25 -0
- graph_os/extractors/code_generic.py +914 -0
- graph_os/extractors/code_go.py +1422 -0
- graph_os/extractors/code_json.py +340 -0
- graph_os/extractors/code_php.py +979 -0
- graph_os/extractors/code_python.py +1454 -0
- graph_os/extractors/code_shell.py +538 -0
- graph_os/extractors/code_toml.py +302 -0
- graph_os/extractors/code_ts.py +1665 -0
- graph_os/extractors/code_yaml.py +394 -0
- graph_os/extractors/contracts.py +1592 -0
- graph_os/extractors/md_links.py +890 -0
- graph_os/extractors/task_deps.py +345 -0
- graph_os/groups/__init__.py +22 -0
- graph_os/groups/cross_repo.py +156 -0
- graph_os/groups/manifest.py +141 -0
- graph_os/ingest/__init__.py +19 -0
- graph_os/ingest/base.py +306 -0
- graph_os/ingest/github.py +112 -0
- graph_os/ingest/zip.py +95 -0
- graph_os/toolchain.py +393 -0
- graph_os/tools/__init__.py +9 -0
- graph_os/tools/graph.py +5573 -0
- graph_os/tools/reindex_dispatch.py +730 -0
- graph_os/tree_sitter_overlay.py +235 -0
- graph_os/types.py +252 -0
- graph_os/vec_index.py +277 -0
- graph_os/viewer/__init__.py +12 -0
- graph_os/viewer/exporter.py +93 -0
- graph_os/viewer/template.py +189 -0
- scheduled/__init__.py +0 -0
- scheduled/_activity.py +126 -0
- scheduled/_state.py +113 -0
- scheduled/config.py +86 -0
- scheduled/dep_reconcile.py +135 -0
- scheduled/error_sweep.py +137 -0
- scheduled/nightly.py +930 -0
- scheduled/responsive_extract.py +65 -0
- scripts/__init__.py +4 -0
- scripts/_commit_msg_body.sh +31 -0
- scripts/_post_commit_body.sh +49 -0
- scripts/_pre_commit_body.sh +121 -0
- scripts/_prepare_commit_msg_body.sh +53 -0
- scripts/audit_mcp_tools.py +693 -0
- scripts/bench_sdk_dispatcher.py +177 -0
- scripts/capture_golden.py +169 -0
- scripts/check_graph_phantoms.py +75 -0
- scripts/dev/audit_doc_links.py +359 -0
- scripts/dev/audit_scaffold_module_tags.py +107 -0
- scripts/dev/backfill_doc_headers.py +328 -0
- scripts/dev/backfill_nav_lines.py +119 -0
- scripts/dev/fix_nav_placement.py +106 -0
- scripts/dev/inspect_sdk_options.py +45 -0
- scripts/dev/migrate_check_ids.py +170 -0
- scripts/dev/strip_purpose_blocks.py +154 -0
- scripts/dump_openapi.py +66 -0
- scripts/e2e_dispatch_tool.py +195 -0
- scripts/generate_manifest.py +166 -0
- scripts/golden_sections.py +20 -0
- scripts/graph_demo.py +161 -0
- scripts/install-git-hooks.sh +47 -0
- scripts/migrate_embeddings_minilm_to_bge_m3.py +84 -0
- scripts/operational_eval.py +445 -0
- scripts/probe_agent_session_resolver.py +59 -0
- scripts/prune_deleted_path.py +127 -0
- scripts/refactor_agent_dual_mode.py +171 -0
- scripts/refresh_skill_versions.py +302 -0
- scripts/regen_doc_index.py +209 -0
- scripts/regen_doctor_schema.py +62 -0
- scripts/regen_rules.py +94 -0
- scripts/rename_formulas_to_semantic.py +241 -0
- scripts/smoke_db_connections.py +183 -0
- scripts/smoke_doc_header.py +72 -0
- scripts/smoke_graph_e2e.py +374 -0
- scripts/smoke_sdk_dispatch.py +84 -0
- scripts/smoke_uid_resolver.py +164 -0
- scripts/verify_dispatchers.py +244 -0
- scripts/verify_phase_c_e2e.py +436 -0
- templates/__init__.py +6 -0
- templates/_base/Makefile.base +353 -0
- templates/_base/base.yaml +59 -0
- templates/_base/coding-os.yaml.template +39 -0
- templates/_base/dimension-registry.template.md +68 -0
- templates/_base/domain-config.template.json +46 -0
- templates/_base/fragments/anatomy-map.md.tmpl +11 -0
- templates/_base/fragments/context-discipline.md.tmpl +3 -0
- templates/_base/fragments/core-loop.md.tmpl +52 -0
- templates/_base/fragments/engineering-routing.md.tmpl +3 -0
- templates/_base/fragments/header.md.tmpl +6 -0
- templates/_base/fragments/identity.md.tmpl +3 -0
- templates/_base/fragments/principles.md.tmpl +3 -0
- templates/_base/fragments/retrieval-routing.md.tmpl +23 -0
- templates/_base/fragments/session-handoff.md.tmpl +3 -0
- templates/_base/fragments/skills.md.tmpl +3 -0
- templates/_base/fragments/ssot-map.md.tmpl +3 -0
- templates/_base/fragments/stop-conditions.md.tmpl +3 -0
- templates/_base/fragments/subagent-dispatch.md.tmpl +3 -0
- templates/_base/fragments/task-authoring.md.tmpl +69 -0
- templates/_base/fragments/task-logging.md.tmpl +8 -0
- templates/_base/fragments/tool-routing.md.tmpl +9 -0
- templates/_base/fragments/verification-matrix.md.tmpl +12 -0
- templates/_base/lang/dart/analysis_options.yaml +7 -0
- templates/_base/lang/php/phpcs.xml.dist +10 -0
- templates/_base/lang/python/pyproject.toml +19 -0
- templates/_base/lang/rust/clippy.toml +5 -0
- templates/_base/lang/rust/rustfmt.toml +3 -0
- templates/_base/lang/typescript/eslint.config.js +26 -0
- templates/_base/lang/typescript/tsconfig.json +15 -0
- templates/_base/lang/typescript/vitest.config.ts +10 -0
- templates/_base/scaffold/changes.log +1 -0
- templates/_base/scaffold/docs/00-index.md +55 -0
- templates/_base/scaffold/docs/_meta/feature-dependency-tree.md +30 -0
- templates/_base/scaffold/docs/_meta/foundation-map.md +56 -0
- templates/_base/scaffold/docs/_meta/questions.md +8 -0
- templates/_base/scaffold/docs/_meta/roadmap.md +33 -0
- templates/_base/scaffold/docs/api-contracts/00-index.md +58 -0
- templates/_base/scaffold/docs/api-contracts/error-format.md +58 -0
- templates/_base/scaffold/docs/architecture/00-index.md +42 -0
- templates/_base/scaffold/docs/architecture/adr/00-index.md +39 -0
- templates/_base/scaffold/docs/engineering/00-index.md +9 -0
- templates/_base/scaffold/docs/governance/00-index.md +55 -0
- templates/_base/scaffold/docs/governance/_templates/doc-cheat-sheet.md +202 -0
- templates/_base/scaffold/docs/governance/_templates/playbook-template.md +81 -0
- templates/_base/scaffold/docs/governance/_templates/post-mortem-template.md +85 -0
- templates/_base/scaffold/docs/governance/_templates/runbook-template.md +88 -0
- templates/_base/scaffold/docs/governance/_templates/security-review-template.md +111 -0
- templates/_base/scaffold/docs/governance/_templates/task-detail.md +61 -0
- templates/_base/scaffold/docs/governance/agent-workflow.md +101 -0
- templates/_base/scaffold/docs/governance/anatomy-contract.md +150 -0
- templates/_base/scaffold/docs/governance/critical-rules.md +224 -0
- templates/_base/scaffold/docs/governance/decision-records.md +58 -0
- templates/_base/scaffold/docs/governance/docs-first-protocol.md +157 -0
- templates/_base/scaffold/docs/governance/docs-system.md +151 -0
- templates/_base/scaffold/docs/governance/gdpr-compliance.md +66 -0
- templates/_base/scaffold/docs/governance/mcp-tool-inventory.md +112 -0
- templates/_base/scaffold/docs/governance/risk-register.md +26 -0
- templates/_base/scaffold/docs/governance/scaffold-boundary-contract.md +161 -0
- templates/_base/scaffold/docs/governance/task-lifecycle.md +125 -0
- templates/_base/scaffold/docs/governance/wrapper-derivation.md +50 -0
- templates/_base/scaffold/docs/insights/00-index.md +17 -0
- templates/_base/scaffold/docs/ops/00-index.md +59 -0
- templates/_base/scaffold/docs/ops/runbooks/00-index.md +9 -0
- templates/_base/scaffold/docs/playbooks/00-index.md +12 -0
- templates/_base/scaffold/docs/playbooks/research-validation.md +29 -0
- templates/_base/scaffold/docs/playbooks/security-review.md +41 -0
- templates/_base/scaffold/docs/prd/00-index.md +43 -0
- templates/_base/scaffold/docs/prd/01-snapshot-vision.md +56 -0
- templates/_base/scaffold/docs/workflow/workflow-guide.md +138 -0
- templates/_base/scaffold/src/shared/README.md +23 -0
- templates/_base/skill-enforcement.template.md +14 -0
- templates/_base/task-detail.template.md +61 -0
- templates/_presets/ai-saas.yaml +9 -0
- templates/_presets/django-next.yaml +8 -0
- templates/_presets/dotnet-react.yaml +8 -0
- templates/_presets/flutter-baas.yaml +8 -0
- templates/_presets/go-react.yaml +8 -0
- templates/_presets/hexagonal-product.yaml +16 -0
- templates/_presets/jamstack.yaml +8 -0
- templates/_presets/laravel-vue.yaml +8 -0
- templates/_presets/mean.yaml +8 -0
- templates/_presets/mern.yaml +9 -0
- templates/_presets/nest-angular.yaml +8 -0
- templates/_presets/nextjs-fastapi.yaml +10 -0
- templates/_presets/nuxt-fullstack.yaml +9 -0
- templates/_presets/pern.yaml +9 -0
- templates/_presets/rails-react.yaml +8 -0
- templates/_presets/rn-api.yaml +8 -0
- templates/_presets/rust-svelte.yaml +8 -0
- templates/_presets/spring-react.yaml +8 -0
- templates/_presets/t3-style.yaml +9 -0
- templates/_presets/tall.yaml +8 -0
- templates/_presets/wordpress-cms.yaml +8 -0
- templates/angular/rules/frontend.md +19 -0
- templates/angular/scaffold/docs/engineering/accessibility.md +46 -0
- templates/angular/scaffold/docs/engineering/angular-rules.md +35 -0
- templates/angular/scaffold/docs/playbooks/angular-app.md +42 -0
- templates/angular/scaffold/src/frontend/angular.json +52 -0
- templates/angular/scaffold/src/frontend/package.json +28 -0
- templates/angular/scaffold/src/frontend/src/app/app.component.ts +19 -0
- templates/angular/scaffold/src/frontend/src/app/app.config.ts +22 -0
- templates/angular/scaffold/src/frontend/src/app/app.routes.ts +8 -0
- templates/angular/scaffold/src/frontend/src/app/core/global-error-handler.ts +12 -0
- templates/angular/scaffold/src/frontend/src/app/health/health.component.ts +14 -0
- templates/angular/scaffold/src/frontend/src/app/health/health.service.spec.ts +16 -0
- templates/angular/scaffold/src/frontend/src/app/health/health.service.ts +10 -0
- templates/angular/scaffold/src/frontend/src/index.html +11 -0
- templates/angular/scaffold/src/frontend/src/main.ts +9 -0
- templates/angular/scaffold/src/frontend/src/styles.css +14 -0
- templates/angular/scaffold/src/frontend/tsconfig.app.json +8 -0
- templates/angular/scaffold/src/frontend/tsconfig.json +27 -0
- templates/angular/scaffold/src/frontend/tsconfig.spec.json +8 -0
- templates/angular/scaffold-boundary.yaml +27 -0
- templates/angular/skills/angular/SKILL.md +79 -0
- templates/angular/skills/angular/references/anatomy.md +69 -0
- templates/angular/stack.yaml +75 -0
- templates/aspnet-core/rules/backend.md +20 -0
- templates/aspnet-core/scaffold/docs/engineering/aspnet-core-rules.md +36 -0
- templates/aspnet-core/scaffold/docs/playbooks/aspnet-core-service.md +40 -0
- templates/aspnet-core/scaffold/src/backend/Backend.csproj +11 -0
- templates/aspnet-core/scaffold/src/backend/Backend.sln +27 -0
- templates/aspnet-core/scaffold/src/backend/Common/ExceptionHandlingMiddleware.cs +35 -0
- templates/aspnet-core/scaffold/src/backend/Features/Health/HealthEndpoints.cs +10 -0
- templates/aspnet-core/scaffold/src/backend/Features/Health/HealthService.cs +9 -0
- templates/aspnet-core/scaffold/src/backend/Program.cs +22 -0
- templates/aspnet-core/scaffold/src/backend/tests/Backend.Tests/Backend.Tests.csproj +22 -0
- templates/aspnet-core/scaffold/src/backend/tests/Backend.Tests/HealthServiceTests.cs +15 -0
- templates/aspnet-core/scaffold-boundary.yaml +24 -0
- templates/aspnet-core/skills/aspnet-core/SKILL.md +80 -0
- templates/aspnet-core/skills/aspnet-core/references/anatomy.md +65 -0
- templates/aspnet-core/stack.yaml +68 -0
- templates/astro/rules/frontend.md +20 -0
- templates/astro/scaffold/docs/engineering/astro-rules.md +40 -0
- templates/astro/scaffold/docs/playbooks/astro-app.md +57 -0
- templates/astro/scaffold/docs/playbooks/content-seo.md +37 -0
- templates/astro/scaffold/src/frontend/astro.config.mjs +10 -0
- templates/astro/scaffold/src/frontend/package.json +23 -0
- templates/astro/scaffold/src/frontend/src/components/Greeting.astro +13 -0
- templates/astro/scaffold/src/frontend/src/content/posts/hello.md +10 -0
- templates/astro/scaffold/src/frontend/src/content.config.ts +19 -0
- templates/astro/scaffold/src/frontend/src/lib/problem.test.ts +39 -0
- templates/astro/scaffold/src/frontend/src/lib/problem.ts +30 -0
- templates/astro/scaffold/src/frontend/src/pages/api/health.ts +13 -0
- templates/astro/scaffold/src/frontend/src/pages/index.astro +21 -0
- templates/astro/scaffold/src/frontend/tsconfig.json +9 -0
- templates/astro/scaffold/src/frontend/vitest.config.ts +10 -0
- templates/astro/scaffold-boundary.yaml +28 -0
- templates/astro/skills/astro/SKILL.md +71 -0
- templates/astro/skills/astro/references/anatomy.md +66 -0
- templates/astro/stack.yaml +75 -0
- templates/csharp-plain/scaffold/src/backend/Backend.csproj +12 -0
- templates/csharp-plain/scaffold/src/backend/Program.cs +1 -0
- templates/csharp-plain/scaffold-boundary.yaml +23 -0
- templates/csharp-plain/stack.yaml +50 -0
- templates/django/rules/backend.md +18 -0
- templates/django/scaffold/docs/engineering/anti-ambiguity.md +74 -0
- templates/django/scaffold/docs/engineering/backend-rules.md +133 -0
- templates/django/scaffold/docs/engineering/glossary.md +51 -0
- templates/django/scaffold/docs/engineering/logging-standards.md +107 -0
- templates/django/scaffold/docs/engineering/naming-conventions.md +68 -0
- templates/django/scaffold/docs/engineering/secrets-rotation-runbook.md +142 -0
- templates/django/scaffold/docs/playbooks/backend-api.md +119 -0
- templates/django/scaffold/src/backend/config/__init__.py +0 -0
- templates/django/scaffold/src/backend/config/settings.py +31 -0
- templates/django/scaffold/src/backend/config/urls.py +11 -0
- templates/django/scaffold/src/backend/config/wsgi.py +6 -0
- templates/django/scaffold/src/backend/manage.py +14 -0
- templates/django/scaffold/src/backend/pyproject.toml +37 -0
- templates/django/scaffold/src/backend/tests/test_health.py +4 -0
- templates/django/scaffold-boundary.yaml +25 -0
- templates/django/skills/python-django/SKILL.md +450 -0
- templates/django/skills/python-django/references/anatomy.md +117 -0
- templates/django/skills/python-django/scripts/new_endpoint.py +89 -0
- templates/django/stack.yaml +73 -0
- templates/fastapi/rules/backend.md +18 -0
- templates/fastapi/scaffold/docs/engineering/fastapi-rules.md +37 -0
- templates/fastapi/scaffold/docs/playbooks/fastapi-service.md +30 -0
- templates/fastapi/scaffold/src/backend/app/__init__.py +0 -0
- templates/fastapi/scaffold/src/backend/app/main.py +8 -0
- templates/fastapi/scaffold/src/backend/pyproject.toml +39 -0
- templates/fastapi/scaffold/src/backend/tests/test_health.py +11 -0
- templates/fastapi/scaffold-boundary.yaml +25 -0
- templates/fastapi/skills/python-fastapi/SKILL.md +75 -0
- templates/fastapi/skills/python-fastapi/references/anatomy.md +117 -0
- templates/fastapi/skills/python-fastapi/scripts/new_endpoint.py +101 -0
- templates/fastapi/stack.yaml +57 -0
- templates/flutter/rules/mobile.md +26 -0
- templates/flutter/scaffold/docs/engineering/flutter-rules.md +35 -0
- templates/flutter/scaffold/docs/playbooks/flutter-app.md +45 -0
- templates/flutter/scaffold/src/mobile/lib/core/error_mapper.dart +17 -0
- templates/flutter/scaffold/src/mobile/lib/core/router.dart +13 -0
- templates/flutter/scaffold/src/mobile/lib/main.dart +22 -0
- templates/flutter/scaffold/src/mobile/lib/screens/health_screen.dart +32 -0
- templates/flutter/scaffold/src/mobile/lib/services/health_service.dart +11 -0
- templates/flutter/scaffold/src/mobile/lib/state/health_provider.dart +13 -0
- templates/flutter/scaffold/src/mobile/pubspec.yaml +22 -0
- templates/flutter/scaffold/src/mobile/test/health_provider_test.dart +90 -0
- templates/flutter/scaffold-boundary.yaml +28 -0
- templates/flutter/skills/flutter/SKILL.md +76 -0
- templates/flutter/skills/flutter/references/anatomy.md +64 -0
- templates/flutter/stack.yaml +70 -0
- templates/go/rules/backend.md +19 -0
- templates/go/scaffold/docs/engineering/go-rules.md +45 -0
- templates/go/scaffold/docs/playbooks/go-service.md +30 -0
- templates/go/scaffold/src/backend/cmd/api/main.go +22 -0
- templates/go/scaffold/src/backend/cmd/api/main_test.go +20 -0
- templates/go/scaffold/src/backend/go.mod +3 -0
- templates/go/scaffold-boundary.yaml +25 -0
- templates/go/skills/go-patterns/SKILL.md +68 -0
- templates/go/skills/go-patterns/assets/go-checklist.md +29 -0
- templates/go/skills/go-patterns/references/anatomy.md +115 -0
- templates/go/skills/go-patterns/references/go-2026-idioms.md +92 -0
- templates/go/skills/go-patterns/scripts/new_endpoint.py +117 -0
- templates/go/skills/go-patterns/versions.json +16 -0
- templates/go/stack.yaml +54 -0
- templates/go-fiber/rules/backend.md +20 -0
- templates/go-fiber/scaffold/docs/engineering/fiber-rules.md +97 -0
- templates/go-fiber/scaffold/docs/playbooks/fiber-service.md +149 -0
- templates/go-fiber/scaffold/src/backend/cmd/api/main.go +21 -0
- templates/go-fiber/scaffold/src/backend/cmd/api/main_test.go +17 -0
- templates/go-fiber/scaffold/src/backend/go.mod +23 -0
- templates/go-fiber/scaffold/src/backend/go.sum +49 -0
- templates/go-fiber/scaffold-boundary.yaml +26 -0
- templates/go-fiber/skills/go-fiber/SKILL.md +203 -0
- templates/go-fiber/skills/go-fiber/assets/fiber-checklist.md +26 -0
- templates/go-fiber/skills/go-fiber/references/anatomy.md +116 -0
- templates/go-fiber/skills/go-fiber/references/fiber-v3-patterns.md +89 -0
- templates/go-fiber/skills/go-fiber/scripts/new_endpoint.py +107 -0
- templates/go-fiber/skills/go-fiber/versions.json +16 -0
- templates/go-fiber/stack.yaml +59 -0
- templates/go-plain/scaffold/src/backend/go.mod +3 -0
- templates/go-plain/scaffold/src/backend/main.go +7 -0
- templates/go-plain/scaffold-boundary.yaml +22 -0
- templates/go-plain/stack.yaml +51 -0
- templates/java-plain/scaffold/src/backend/mvnw +302 -0
- templates/java-plain/scaffold/src/backend/pom.xml +41 -0
- templates/java-plain/scaffold/src/backend/src/main/java/com/example/app/Main.java +10 -0
- templates/java-plain/scaffold-boundary.yaml +23 -0
- templates/java-plain/stack.yaml +51 -0
- templates/laravel/rules/backend.md +20 -0
- templates/laravel/scaffold/docs/engineering/laravel-rules.md +28 -0
- templates/laravel/scaffold/docs/playbooks/laravel-service.md +28 -0
- templates/laravel/scaffold/src/backend/app/Exceptions/Handler.php +27 -0
- templates/laravel/scaffold/src/backend/app/Http/Controllers/HealthController.php +15 -0
- templates/laravel/scaffold/src/backend/app/Support/HealthStatus.php +14 -0
- templates/laravel/scaffold/src/backend/composer.json +24 -0
- templates/laravel/scaffold/src/backend/phpunit.xml +10 -0
- templates/laravel/scaffold/src/backend/public/index.php +8 -0
- templates/laravel/scaffold/src/backend/routes/api.php +7 -0
- templates/laravel/scaffold/src/backend/tests/Unit/HealthStatusTest.php +16 -0
- templates/laravel/scaffold-boundary.yaml +23 -0
- templates/laravel/skills/laravel/SKILL.md +56 -0
- templates/laravel/skills/laravel/references/anatomy.md +65 -0
- templates/laravel/stack.yaml +66 -0
- templates/meta/rules/graph-first.md +27 -0
- templates/meta/rules/hook-author.md +19 -0
- templates/meta/rules/mcp-tool-author.md +18 -0
- templates/meta/rules/meta-engineering.md +17 -0
- templates/meta/scaffold-boundary.yaml +55 -0
- templates/meta/skills/claude-sdk-integration/SKILL.md +163 -0
- templates/meta/skills/claude-sdk-integration/assets/sdk-checklist.md +27 -0
- templates/meta/skills/claude-sdk-integration/scripts/check_model_ids.py +97 -0
- templates/meta/skills/graph-os-authoring/SKILL.md +278 -0
- templates/meta/skills/graph-os-authoring/assets/graph-os-checklist.md +25 -0
- templates/meta/skills/graph-os-authoring/scripts/new_extractor.py +76 -0
- templates/meta/skills/hook-authoring/SKILL.md +292 -0
- templates/meta/skills/hook-authoring/assets/hook-checklist.md +30 -0
- templates/meta/skills/hook-authoring/scripts/new_hook.sh +75 -0
- templates/meta/skills/mcp-tool-authoring/SKILL.md +301 -0
- templates/meta/skills/mcp-tool-authoring/assets/mcp-tool-checklist.md +29 -0
- templates/meta/skills/mcp-tool-authoring/scripts/new_tool.py +74 -0
- templates/meta/skills/meta-engineering/SKILL.md +151 -0
- templates/meta/skills/meta-engineering/assets/meta-edit-checklist.md +28 -0
- templates/meta/skills/meta-engineering/scripts/which_layer.py +61 -0
- templates/meta/skills/python-meta-server/SKILL.md +162 -0
- templates/meta/skills/python-meta-server/assets/meta-server-checklist.md +28 -0
- templates/meta/skills/python-meta-server/scripts/check_envelope.py +91 -0
- templates/meta/skills/react-vite-hub/SKILL.md +140 -0
- templates/meta/skills/react-vite-hub/assets/hub-ui-checklist.md +23 -0
- templates/meta/skills/react-vite-hub/scripts/check_vite_env.py +73 -0
- templates/meta/stack.yaml +119 -0
- templates/nestjs/rules/backend.md +20 -0
- templates/nestjs/scaffold/docs/engineering/nestjs-rules.md +33 -0
- templates/nestjs/scaffold/docs/playbooks/nestjs-service.md +39 -0
- templates/nestjs/scaffold/src/backend/nest-cli.json +5 -0
- templates/nestjs/scaffold/src/backend/package.json +28 -0
- templates/nestjs/scaffold/src/backend/src/app.module.ts +9 -0
- templates/nestjs/scaffold/src/backend/src/common/all-exceptions.filter.ts +59 -0
- templates/nestjs/scaffold/src/backend/src/health/health.controller.ts +14 -0
- templates/nestjs/scaffold/src/backend/src/health/health.module.ts +10 -0
- templates/nestjs/scaffold/src/backend/src/health/health.service.spec.ts +21 -0
- templates/nestjs/scaffold/src/backend/src/health/health.service.ts +9 -0
- templates/nestjs/scaffold/src/backend/src/main.ts +26 -0
- templates/nestjs/scaffold/src/backend/tsconfig.json +16 -0
- templates/nestjs/scaffold/src/backend/vitest.config.ts +9 -0
- templates/nestjs/scaffold-boundary.yaml +25 -0
- templates/nestjs/skills/nestjs/SKILL.md +67 -0
- templates/nestjs/skills/nestjs/references/anatomy.md +65 -0
- templates/nestjs/stack.yaml +68 -0
- templates/nextjs/rules/frontend.md +18 -0
- templates/nextjs/scaffold/docs/design/00-index.md +23 -0
- templates/nextjs/scaffold/docs/design/colors-tokens.md +141 -0
- templates/nextjs/scaffold/docs/design/components-patterns.md +159 -0
- templates/nextjs/scaffold/docs/design/motion-accessibility.md +137 -0
- templates/nextjs/scaffold/docs/design/typography-spacing.md +107 -0
- templates/nextjs/scaffold/docs/engineering/accessibility-web.md +56 -0
- templates/nextjs/scaffold/docs/engineering/copywriting-standard.md +102 -0
- templates/nextjs/scaffold/docs/engineering/formatting-rules.md +89 -0
- templates/nextjs/scaffold/docs/engineering/frontend-rendering-rules.md +80 -0
- templates/nextjs/scaffold/docs/engineering/frontend-rules.md +183 -0
- templates/nextjs/scaffold/docs/engineering/i18n-policy.md +99 -0
- templates/nextjs/scaffold/docs/pages-content-spec/00-index.md +78 -0
- templates/nextjs/scaffold/docs/playbooks/content-seo.md +55 -0
- templates/nextjs/scaffold/docs/playbooks/docs-governance.md +51 -0
- templates/nextjs/scaffold/docs/playbooks/frontend-ui.md +63 -0
- templates/nextjs/scaffold/src/frontend/app/layout.tsx +14 -0
- templates/nextjs/scaffold/src/frontend/app/page.tsx +3 -0
- templates/nextjs/scaffold/src/frontend/eslint.config.js +17 -0
- templates/nextjs/scaffold/src/frontend/lib/greeting.test.ts +9 -0
- templates/nextjs/scaffold/src/frontend/lib/greeting.ts +3 -0
- templates/nextjs/scaffold/src/frontend/package.json +28 -0
- templates/nextjs/scaffold/src/frontend/tsconfig.json +18 -0
- templates/nextjs/scaffold/src/frontend/vitest.config.ts +10 -0
- templates/nextjs/scaffold-boundary.yaml +30 -0
- templates/nextjs/skills/nextjs-react/SKILL.md +485 -0
- templates/nextjs/skills/nextjs-react/references/anatomy.md +116 -0
- templates/nextjs/skills/nextjs-react/scripts/new_component.py +72 -0
- templates/nextjs/stack.yaml +81 -0
- templates/node-express/rules/backend.md +20 -0
- templates/node-express/scaffold/docs/engineering/express-rules.md +30 -0
- templates/node-express/scaffold/docs/playbooks/express-service.md +35 -0
- templates/node-express/scaffold/src/backend/package.json +24 -0
- templates/node-express/scaffold/src/backend/src/index.ts +17 -0
- templates/node-express/scaffold/src/backend/src/middleware/error-handler.ts +12 -0
- templates/node-express/scaffold/src/backend/src/routes/health.test.ts +33 -0
- templates/node-express/scaffold/src/backend/src/routes/health.ts +7 -0
- templates/node-express/scaffold/src/backend/tsconfig.json +15 -0
- templates/node-express/scaffold/src/backend/types/express-bootstrap.d.ts +21 -0
- templates/node-express/scaffold-boundary.yaml +25 -0
- templates/node-express/skills/node-express/SKILL.md +70 -0
- templates/node-express/skills/node-express/references/anatomy.md +63 -0
- templates/node-express/stack.yaml +63 -0
- templates/python/scaffold/docs/engineering/python-rules.md +27 -0
- templates/python/scaffold/docs/playbooks/python-library.md +35 -0
- templates/python/stack.yaml +60 -0
- templates/rails/rules/backend.md +10 -0
- templates/rails/scaffold/docs/engineering/rails-rules.md +33 -0
- templates/rails/scaffold/docs/playbooks/rails-service.md +42 -0
- templates/rails/scaffold/src/backend/Gemfile +12 -0
- templates/rails/scaffold/src/backend/app/controllers/application_controller.rb +26 -0
- templates/rails/scaffold/src/backend/app/controllers/health_controller.rb +6 -0
- templates/rails/scaffold/src/backend/app/models/health.rb +6 -0
- templates/rails/scaffold/src/backend/config/application.rb +12 -0
- templates/rails/scaffold/src/backend/config/boot.rb +3 -0
- templates/rails/scaffold/src/backend/config/routes.rb +4 -0
- templates/rails/scaffold/src/backend/config.ru +5 -0
- templates/rails/scaffold/src/backend/spec/rails_helper.rb +18 -0
- templates/rails/scaffold/src/backend/spec/requests/health_spec.rb +24 -0
- templates/rails/scaffold-boundary.yaml +25 -0
- templates/rails/skills/rails/SKILL.md +62 -0
- templates/rails/skills/rails/references/anatomy.md +71 -0
- templates/rails/stack.yaml +72 -0
- templates/react-native/rules/mobile.md +26 -0
- templates/react-native/scaffold/docs/engineering/accessibility-mobile.md +95 -0
- templates/react-native/scaffold/docs/engineering/mobile-rules.md +56 -0
- templates/react-native/scaffold/docs/engineering/offline-first.md +61 -0
- templates/react-native/scaffold/docs/playbooks/mobile-app.md +49 -0
- templates/react-native/scaffold/src/mobile/App.tsx +9 -0
- templates/react-native/scaffold/src/mobile/eslint.config.js +17 -0
- templates/react-native/scaffold/src/mobile/package.json +23 -0
- templates/react-native/scaffold/src/mobile/src/greeting.test.ts +9 -0
- templates/react-native/scaffold/src/mobile/src/greeting.ts +3 -0
- templates/react-native/scaffold/src/mobile/tsconfig.json +17 -0
- templates/react-native/scaffold/src/mobile/vitest.config.ts +10 -0
- templates/react-native/scaffold-boundary.yaml +30 -0
- templates/react-native/skills/react-native-mobile/SKILL.md +119 -0
- templates/react-native/skills/react-native-mobile/assets/rn-mobile-checklist.md +28 -0
- templates/react-native/skills/react-native-mobile/references/anatomy.md +140 -0
- templates/react-native/skills/react-native-mobile/references/rn-2026-practices.md +54 -0
- templates/react-native/skills/react-native-mobile/scripts/new_screen.py +73 -0
- templates/react-native/skills/react-native-mobile/versions.json +16 -0
- templates/react-native/skills/react-native-patterns/SKILL.md +512 -0
- templates/react-native/skills/react-native-patterns/assets/rn-review-checklist.md +26 -0
- templates/react-native/skills/react-native-patterns/references/anatomy.md +62 -0
- templates/react-native/skills/react-native-patterns/references/list-performance.md +70 -0
- templates/react-native/skills/react-native-patterns/scripts/scan_rn_perf.py +77 -0
- templates/react-native/stack.yaml +70 -0
- templates/ruby-plain/scaffold/src/backend/Gemfile +8 -0
- templates/ruby-plain/scaffold/src/backend/main.rb +3 -0
- templates/ruby-plain/scaffold-boundary.yaml +23 -0
- templates/ruby-plain/stack.yaml +50 -0
- templates/rust-axum/rules/backend.md +20 -0
- templates/rust-axum/scaffold/docs/engineering/rust-axum-rules.md +35 -0
- templates/rust-axum/scaffold/docs/playbooks/rust-axum-service.md +43 -0
- templates/rust-axum/scaffold/src/backend/Cargo.toml +20 -0
- templates/rust-axum/scaffold/src/backend/src/app.rs +12 -0
- templates/rust-axum/scaffold/src/backend/src/error.rs +48 -0
- templates/rust-axum/scaffold/src/backend/src/main.rs +24 -0
- templates/rust-axum/scaffold/src/backend/src/routes/health.rs +37 -0
- templates/rust-axum/scaffold/src/backend/src/routes/mod.rs +2 -0
- templates/rust-axum/scaffold-boundary.yaml +25 -0
- templates/rust-axum/skills/rust/SKILL.md +73 -0
- templates/rust-axum/skills/rust/references/anatomy.md +63 -0
- templates/rust-axum/stack.yaml +65 -0
- templates/rust-plain/scaffold/src/backend/Cargo.toml +6 -0
- templates/rust-plain/scaffold/src/backend/src/main.rs +3 -0
- templates/rust-plain/scaffold-boundary.yaml +23 -0
- templates/rust-plain/stack.yaml +51 -0
- templates/spring-boot/rules/backend.md +20 -0
- templates/spring-boot/scaffold/docs/engineering/spring-boot-rules.md +35 -0
- templates/spring-boot/scaffold/docs/playbooks/spring-boot-service.md +45 -0
- templates/spring-boot/scaffold/src/backend/mvnw +302 -0
- templates/spring-boot/scaffold/src/backend/pom.xml +69 -0
- templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/Application.java +16 -0
- templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/common/GlobalExceptionHandler.java +31 -0
- templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/health/HealthController.java +22 -0
- templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/health/HealthService.java +12 -0
- templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/health/HealthStatus.java +4 -0
- templates/spring-boot/scaffold/src/backend/src/test/java/com/example/app/health/HealthServiceTest.java +15 -0
- templates/spring-boot/scaffold-boundary.yaml +26 -0
- templates/spring-boot/skills/spring-boot/SKILL.md +84 -0
- templates/spring-boot/skills/spring-boot/references/anatomy.md +63 -0
- templates/spring-boot/stack.yaml +65 -0
- templates/svelte-sveltekit/rules/frontend.md +20 -0
- templates/svelte-sveltekit/scaffold/docs/engineering/svelte-sveltekit-rules.md +37 -0
- templates/svelte-sveltekit/scaffold/docs/playbooks/svelte-sveltekit-app.md +36 -0
- templates/svelte-sveltekit/scaffold/src/frontend/package.json +22 -0
- templates/svelte-sveltekit/scaffold/src/frontend/src/app.html +12 -0
- templates/svelte-sveltekit/scaffold/src/frontend/src/hooks.server.ts +14 -0
- templates/svelte-sveltekit/scaffold/src/frontend/src/lib/components/Greeting.svelte +6 -0
- templates/svelte-sveltekit/scaffold/src/frontend/src/lib/stores/count.test.ts +26 -0
- templates/svelte-sveltekit/scaffold/src/frontend/src/lib/stores/count.ts +4 -0
- templates/svelte-sveltekit/scaffold/src/frontend/src/routes/+layout.svelte +24 -0
- templates/svelte-sveltekit/scaffold/src/frontend/src/routes/+page.svelte +9 -0
- templates/svelte-sveltekit/scaffold/src/frontend/src/routes/+page.ts +7 -0
- templates/svelte-sveltekit/scaffold/src/frontend/src/routes/health/+server.ts +7 -0
- templates/svelte-sveltekit/scaffold/src/frontend/svelte.config.js +10 -0
- templates/svelte-sveltekit/scaffold/src/frontend/tsconfig.json +7 -0
- templates/svelte-sveltekit/scaffold/src/frontend/vite.config.ts +7 -0
- templates/svelte-sveltekit/scaffold/src/frontend/vitest.config.ts +11 -0
- templates/svelte-sveltekit/scaffold-boundary.yaml +29 -0
- templates/svelte-sveltekit/skills/svelte/SKILL.md +90 -0
- templates/svelte-sveltekit/skills/svelte/references/anatomy.md +62 -0
- templates/svelte-sveltekit/stack.yaml +70 -0
- templates/typescript-plain/scaffold/src/index.ts +3 -0
- templates/typescript-plain/scaffold/tsconfig.json +13 -0
- templates/typescript-plain/scaffold-boundary.yaml +22 -0
- templates/typescript-plain/stack.yaml +44 -0
- templates/vue-nuxt/rules/frontend.md +19 -0
- templates/vue-nuxt/scaffold/docs/engineering/nuxt-rules.md +30 -0
- templates/vue-nuxt/scaffold/docs/playbooks/nuxt-app.md +29 -0
- templates/vue-nuxt/scaffold/src/frontend/app.vue +3 -0
- templates/vue-nuxt/scaffold/src/frontend/nuxt.config.ts +11 -0
- templates/vue-nuxt/scaffold/src/frontend/package.json +20 -0
- templates/vue-nuxt/scaffold/src/frontend/pages/index.test.ts +19 -0
- templates/vue-nuxt/scaffold/src/frontend/pages/index.vue +11 -0
- templates/vue-nuxt/scaffold/src/frontend/vitest.config.ts +12 -0
- templates/vue-nuxt/scaffold-boundary.yaml +26 -0
- templates/vue-nuxt/skills/vue-nuxt/SKILL.md +57 -0
- templates/vue-nuxt/skills/vue-nuxt/references/anatomy.md +60 -0
- templates/vue-nuxt/stack.yaml +61 -0
- templates/wordpress/rules/backend.md +19 -0
- templates/wordpress/scaffold/docs/engineering/wordpress-rules.md +28 -0
- templates/wordpress/scaffold/docs/playbooks/wordpress-service.md +29 -0
- templates/wordpress/scaffold/src/backend/composer.json +17 -0
- templates/wordpress/scaffold/src/backend/phpcs.xml.dist +11 -0
- templates/wordpress/scaffold/src/backend/phpunit.xml +10 -0
- templates/wordpress/scaffold/src/backend/plugin/inc/health.php +8 -0
- templates/wordpress/scaffold/src/backend/plugin/plugin.php +28 -0
- templates/wordpress/scaffold/src/backend/tests/HealthStatusTest.php +15 -0
- templates/wordpress/scaffold/src/backend/theme/functions.php +18 -0
- templates/wordpress/scaffold/src/backend/theme/style.css +11 -0
- templates/wordpress/scaffold-boundary.yaml +23 -0
- templates/wordpress/skills/wordpress/SKILL.md +110 -0
- templates/wordpress/skills/wordpress/assets/wp-checklist.md +28 -0
- templates/wordpress/skills/wordpress/references/wp-development.md +75 -0
- templates/wordpress/skills/wordpress/references/wp-security.md +68 -0
- templates/wordpress/skills/wordpress/scripts/scan_wp_smells.py +91 -0
- templates/wordpress/skills/wordpress/versions.json +16 -0
- templates/wordpress/stack.yaml +60 -0
- thinking_os/__init__.py +1 -0
- thinking_os/_agent_markers.py +32 -0
- thinking_os/background.py +405 -0
- thinking_os/bootstrap_outcomes.py +200 -0
- thinking_os/budget.py +302 -0
- thinking_os/capture.py +495 -0
- thinking_os/cognition.py +516 -0
- thinking_os/cognition_schemas.py +517 -0
- thinking_os/compress.py +192 -0
- thinking_os/concepts.py +233 -0
- thinking_os/dashboard.py +159 -0
- thinking_os/database.py +2883 -0
- thinking_os/decay.py +393 -0
- thinking_os/digest.py +295 -0
- thinking_os/dispatcher.py +192 -0
- thinking_os/dispatcher_helpers.py +48 -0
- thinking_os/dispatchers/__init__.py +3 -0
- thinking_os/dispatchers/default.py +47 -0
- thinking_os/distill.py +192 -0
- thinking_os/doc_indexer.py +905 -0
- thinking_os/embeddings.py +943 -0
- thinking_os/formula_composer.py +556 -0
- thinking_os/gate_marker.py +75 -0
- thinking_os/graph.py +296 -0
- thinking_os/graph_indexer.py +360 -0
- thinking_os/health_check.py +517 -0
- thinking_os/impact.py +119 -0
- thinking_os/memory_gc.py +356 -0
- thinking_os/migrator_embeddings.py +318 -0
- thinking_os/precision.py +194 -0
- thinking_os/record_outcome.py +399 -0
- thinking_os/repair.py +105 -0
- thinking_os/retrieval_quality.py +239 -0
- thinking_os/roles_state.py +168 -0
- thinking_os/sanitizer.py +320 -0
- thinking_os/server.py +3160 -0
- thinking_os/session_enrich.py +272 -0
- thinking_os/session_observe_worker.py +111 -0
- thinking_os/session_startup.py +74 -0
- thinking_os/session_summary.py +245 -0
- thinking_os/task_analyzer.py +462 -0
- thinking_os/task_parser.py +342 -0
- thinking_os/task_sync.py +73 -0
- thinking_os/tools/__init__.py +6 -0
- thinking_os/tools/_shared.py +947 -0
- thinking_os/tools/cognition.py +1867 -0
- thinking_os/tools/docs.py +770 -0
- thinking_os/tools/learning.py +2078 -0
- thinking_os/tools/logs.py +79 -0
- thinking_os/tools/memory.py +840 -0
- thinking_os/tools/metrics.py +200 -0
- thinking_os/tools/retrieve.py +415 -0
- thinking_os/tools/routing.py +658 -0
- thinking_os/tools/tasks.py +449 -0
- thinking_os/tools/trajectory.py +181 -0
- thinking_os/tracing.py +235 -0
- web/__init__.py +5 -0
- web/_cache.py +118 -0
- web/_deps.py +56 -0
- web/_envelope.py +85 -0
- web/_project_context.py +140 -0
- web/chat_providers.py +108 -0
- web/init_jobs.py +216 -0
- web/routes/__init__.py +25 -0
- web/routes/_bounded_read.py +76 -0
- web/routes/board.py +1089 -0
- web/routes/cognition.py +1838 -0
- web/routes/config.py +635 -0
- web/routes/graph.py +513 -0
- web/routes/health.py +180 -0
- web/routes/hooks.py +288 -0
- web/routes/hub.py +1219 -0
- web/routes/logs.py +374 -0
- web/routes/metrics.py +43 -0
- web/routes/observability.py +400 -0
- web/routes/patterns.py +227 -0
- web/routes/presence.py +609 -0
- web/routes/roles.py +446 -0
- web/routes/scheduled.py +261 -0
- web/routes/search.py +238 -0
- web/routes/sessions.py +220 -0
- web/routes/settings.py +363 -0
- web/routes/stream.py +547 -0
- web/security.py +157 -0
- web/server.py +283 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: db-design
|
|
3
|
+
description: Design and evolve PostgreSQL schemas that survive scale and refactors. Use when modeling a new domain, choosing between normalization and denormalization, designing indexes for known query patterns, writing migrations safely, picking ORM-vs-raw-SQL trade-offs, deciding on soft delete vs hard delete, or evaluating NoSQL document/KV/wide-column for a use case. Targets PostgreSQL 16+ as the default; calls out MongoDB / Redis / DynamoDB where they're the better fit.
|
|
4
|
+
tier: cross-cutting
|
|
5
|
+
domain: [data, backend]
|
|
6
|
+
last_reviewed: "2026-05-11"
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Database Design — PostgreSQL First
|
|
11
|
+
|
|
12
|
+
A practical design playbook for the project's stack: PostgreSQL as the system of record, accessed by the Go+Fiber business core and the Python+FastAPI AI adapter, with hexagonal repositories isolating the rest of the codebase from schema specifics.
|
|
13
|
+
|
|
14
|
+
## When to Use This Skill
|
|
15
|
+
|
|
16
|
+
- Modeling the schema for a new bounded context (orders, users, lessons, payments).
|
|
17
|
+
- Adding a column or table that will see growth.
|
|
18
|
+
- Choosing PK / FK shapes (UUID? bigint? prefixed string?).
|
|
19
|
+
- Designing indexes after seeing query patterns or EXPLAIN output.
|
|
20
|
+
- Writing migrations that touch live data (never just on a fresh DB).
|
|
21
|
+
- Picking ORM (sqlc / GORM / SQLAlchemy / Drizzle) vs raw SQL for a feature.
|
|
22
|
+
- Deciding on soft delete vs hard delete + audit table.
|
|
23
|
+
- Evaluating Redis (cache/queue) vs Postgres (LISTEN/NOTIFY, advisory locks) for a side-channel.
|
|
24
|
+
|
|
25
|
+
Skip when: prototyping with a sqlite that will be thrown away. Use this skill before the throw-away gets promoted.
|
|
26
|
+
|
|
27
|
+
## The Three Rules
|
|
28
|
+
|
|
29
|
+
1. **Constraints in the database, not the application.** `NOT NULL`, `CHECK`, `UNIQUE`, `FOREIGN KEY` enforced by Postgres survive bugs in the app, replays of stale code, and direct DBA fixes. Application-only invariants are constantly violated by accident.
|
|
30
|
+
2. **Migrations are forward-only and additive.** Never drop a column the same release you stop writing to it. Two-phase: stop writing → wait → drop. See [references/migration-discipline.md](references/migration-discipline.md).
|
|
31
|
+
3. **Your queries determine your indexes, not the other way around.** Don't index speculatively; index after you see EXPLAIN output for the queries that matter.
|
|
32
|
+
|
|
33
|
+
## Modeling Choices
|
|
34
|
+
|
|
35
|
+
### Primary Keys
|
|
36
|
+
|
|
37
|
+
| Style | Pros | Cons | Use when |
|
|
38
|
+
|---|---|---|---|
|
|
39
|
+
| **bigint identity** | Compact, sequential, fast B-tree, predictable | Leaks count, predictable, one-DB-only | Internal high-volume tables (audit log, events). |
|
|
40
|
+
| **UUID v7** (time-ordered) | Globally unique, mergeable, sortable | 16 bytes, slightly bigger indexes | Default for user-visible entities. Postgres 18 has built-in `uuidv7()`; on 16/17 use `pg_uuidv7` extension or app-side. |
|
|
41
|
+
| **UUID v4** (random) | Globally unique, no info leakage | Index bloat from random insertion order, 4× page splits vs v7 | Avoid for primary keys at scale. Fine for IDs that never get indexed. |
|
|
42
|
+
| **Prefixed text** (`ord_8h2k4n9d3p7q`) | Self-documenting in logs, debug-friendly | App-side ID generation, slightly larger | Public API surface (Stripe pattern). Pair with a UUID v7 internally if needed. |
|
|
43
|
+
|
|
44
|
+
**Default for this project**: prefixed text IDs (`usr_`, `ord_`, `lsn_`, `pay_`) generated app-side from UUID v7 + base32. Internally, the column is `TEXT NOT NULL PRIMARY KEY`. Postgres handles text PKs well at this size.
|
|
45
|
+
|
|
46
|
+
### Foreign Keys
|
|
47
|
+
|
|
48
|
+
ALWAYS declare them. ALWAYS index them.
|
|
49
|
+
|
|
50
|
+
```sql
|
|
51
|
+
-- Postgres does NOT auto-index foreign key columns. Forgetting this
|
|
52
|
+
-- is the #1 cause of slow DELETE / UPDATE on the parent table.
|
|
53
|
+
CREATE TABLE order_items (
|
|
54
|
+
id TEXT PRIMARY KEY,
|
|
55
|
+
order_id TEXT NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
|
|
56
|
+
sku TEXT NOT NULL,
|
|
57
|
+
quantity INT NOT NULL CHECK (quantity > 0),
|
|
58
|
+
UNIQUE (order_id, sku)
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE INDEX idx_order_items_order_id ON order_items(order_id);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Cascade rules — pick deliberately:
|
|
65
|
+
|
|
66
|
+
- `ON DELETE CASCADE` — the child has no meaning without the parent (line items without an order).
|
|
67
|
+
- `ON DELETE RESTRICT` — refuse the delete if children exist (default; force the app to clean up).
|
|
68
|
+
- `ON DELETE SET NULL` — the FK is optional; preserve the child (e.g., assigned-by user gets nulled on user delete).
|
|
69
|
+
|
|
70
|
+
### Nullability
|
|
71
|
+
|
|
72
|
+
Default: `NOT NULL` on every column. Add nullability only with a written reason. `NULL` means "we don't know" — distinct from "we know it's absent" (use a sentinel or separate flag).
|
|
73
|
+
|
|
74
|
+
Common mistakes: `email VARCHAR(255)` nullable when "user without email" is impossible → fix data + make it `NOT NULL`.
|
|
75
|
+
|
|
76
|
+
### Time Columns
|
|
77
|
+
|
|
78
|
+
```sql
|
|
79
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
80
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
81
|
+
deleted_at TIMESTAMPTZ, -- soft delete (see below)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- ALWAYS `TIMESTAMPTZ`, never `TIMESTAMP` (without TZ). The latter loses information at the boundary and bites you in 3 years.
|
|
85
|
+
- Update `updated_at` via trigger so app bugs can't forget:
|
|
86
|
+
```sql
|
|
87
|
+
CREATE OR REPLACE FUNCTION set_updated_at() RETURNS trigger AS $$
|
|
88
|
+
BEGIN NEW.updated_at = NOW(); RETURN NEW; END;
|
|
89
|
+
$$ LANGUAGE plpgsql;
|
|
90
|
+
|
|
91
|
+
CREATE TRIGGER orders_set_updated_at BEFORE UPDATE ON orders
|
|
92
|
+
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Soft Delete vs Hard Delete
|
|
96
|
+
|
|
97
|
+
Soft delete (`deleted_at TIMESTAMPTZ`) when:
|
|
98
|
+
|
|
99
|
+
- Compliance / audit requires keeping records.
|
|
100
|
+
- Users can "undo" deletes within a window.
|
|
101
|
+
- Foreign-key cleanup is impractical.
|
|
102
|
+
|
|
103
|
+
Hard delete when:
|
|
104
|
+
|
|
105
|
+
- GDPR right-to-be-forgotten kicks in.
|
|
106
|
+
- Storage cost > legal/business value.
|
|
107
|
+
- The data was always ephemeral (sessions, OTPs).
|
|
108
|
+
|
|
109
|
+
**Soft delete pitfalls**:
|
|
110
|
+
|
|
111
|
+
- Every query needs `WHERE deleted_at IS NULL` — easy to forget. Mitigate with a view: `CREATE VIEW active_orders AS SELECT * FROM orders WHERE deleted_at IS NULL;` and treat the view as the default.
|
|
112
|
+
- Unique constraints break: `UNIQUE(email)` on a soft-deleted row blocks re-registration. Use `UNIQUE(email) WHERE deleted_at IS NULL` (partial unique index).
|
|
113
|
+
|
|
114
|
+
```sql
|
|
115
|
+
CREATE UNIQUE INDEX users_email_active_unique
|
|
116
|
+
ON users(email) WHERE deleted_at IS NULL;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Money
|
|
120
|
+
|
|
121
|
+
```sql
|
|
122
|
+
amount BIGINT NOT NULL, -- minor units (cents)
|
|
123
|
+
currency CHAR(3) NOT NULL, -- ISO 4217: USD, EUR, IRR
|
|
124
|
+
CHECK (amount >= 0 OR allow_negative)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
NEVER use `FLOAT` / `REAL` / `DOUBLE PRECISION` for money. NEVER use `NUMERIC` without a written reason (slow + complex; integer cents covers 99% of cases).
|
|
128
|
+
|
|
129
|
+
For exotic currencies (JPY has no minor unit; KWD has 3 digits), store the actual minor-unit count and document per-currency multiplication factor in app code.
|
|
130
|
+
|
|
131
|
+
### Enums vs Lookup Tables vs CHECK
|
|
132
|
+
|
|
133
|
+
Three options for "status" columns:
|
|
134
|
+
|
|
135
|
+
```sql
|
|
136
|
+
-- (a) Postgres native ENUM — compact, fast, hard to evolve
|
|
137
|
+
CREATE TYPE order_status AS ENUM ('pending', 'paid', 'shipped', 'cancelled');
|
|
138
|
+
|
|
139
|
+
-- (b) CHECK constraint with TEXT — flexible, slightly bigger
|
|
140
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'paid', 'shipped', 'cancelled'))
|
|
141
|
+
|
|
142
|
+
-- (c) Lookup table with FK — most flexible, joins required
|
|
143
|
+
status_id INT NOT NULL REFERENCES order_statuses(id)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Rule of thumb**:
|
|
147
|
+
|
|
148
|
+
- **(b) CHECK + TEXT** is the right default. Easy to add values (just update the constraint), readable in queries, doesn't need joins.
|
|
149
|
+
- **(a) ENUM** when set is truly fixed and shows up in millions of rows.
|
|
150
|
+
- **(c) Lookup table** when the set has metadata (label, color, ordering) the app needs to render.
|
|
151
|
+
|
|
152
|
+
Avoid mixing: pick one per concept project-wide.
|
|
153
|
+
|
|
154
|
+
### JSON Columns
|
|
155
|
+
|
|
156
|
+
Postgres `JSONB` is genuinely useful for:
|
|
157
|
+
|
|
158
|
+
- **Settings / preferences** with no fixed schema and no querying needs.
|
|
159
|
+
- **Webhook payloads** archived for replay / debugging.
|
|
160
|
+
- **Polymorphic event bodies** in an event-store table.
|
|
161
|
+
|
|
162
|
+
NOT for:
|
|
163
|
+
|
|
164
|
+
- Anything you'll filter on frequently. Use a real column.
|
|
165
|
+
- Anything with a stable schema. That's just a table — make it one.
|
|
166
|
+
- Money. Always real columns.
|
|
167
|
+
|
|
168
|
+
If you must filter on JSONB, add a GIN index:
|
|
169
|
+
|
|
170
|
+
```sql
|
|
171
|
+
CREATE INDEX idx_orders_meta_gin ON orders USING GIN (metadata jsonb_path_ops);
|
|
172
|
+
-- Use jsonb_path_ops for ?, ?| , ?& operators (smaller index than the default).
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Polymorphic Associations — Don't
|
|
176
|
+
|
|
177
|
+
```sql
|
|
178
|
+
-- ANTI-PATTERN: comments table polymorphic on (target_type, target_id)
|
|
179
|
+
CREATE TABLE comments (
|
|
180
|
+
target_type TEXT, -- 'post' | 'video' | 'order'
|
|
181
|
+
target_id TEXT,
|
|
182
|
+
body TEXT,
|
|
183
|
+
-- impossible to FK; impossible to JOIN cleanly
|
|
184
|
+
);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Replace with separate tables: `post_comments`, `video_comments`, `order_comments`. Yes, more tables. Yes, real FKs work. Yes, this pays off.
|
|
188
|
+
|
|
189
|
+
If the polymorphism is genuine (any user-content can be commented on), use `comments` + a `comment_targets` join table per target type, all with proper FKs.
|
|
190
|
+
|
|
191
|
+
## Indexing Strategy
|
|
192
|
+
|
|
193
|
+
### Read the Query First
|
|
194
|
+
|
|
195
|
+
Don't index speculatively. Find the slow query, run `EXPLAIN (ANALYZE, BUFFERS)`, see the plan, then add the index.
|
|
196
|
+
|
|
197
|
+
```sql
|
|
198
|
+
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
|
|
199
|
+
SELECT id, total FROM orders
|
|
200
|
+
WHERE user_id = $1 AND status = 'paid'
|
|
201
|
+
ORDER BY created_at DESC LIMIT 20;
|
|
202
|
+
|
|
203
|
+
-- Look for:
|
|
204
|
+
-- "Seq Scan on orders" → missing index
|
|
205
|
+
-- "Rows Removed by Filter: <high>" → wrong index
|
|
206
|
+
-- "Sort Method: external merge" → spilling to disk; add index that satisfies ORDER BY
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Index Types
|
|
210
|
+
|
|
211
|
+
| Type | Use for |
|
|
212
|
+
|---|---|
|
|
213
|
+
| **B-tree** (default) | Equality + range + ORDER BY. Most common. |
|
|
214
|
+
| **Hash** | Equality only; rarely worth it (B-tree is fine). |
|
|
215
|
+
| **GIN** | Full-text, JSONB, arrays — "contains" semantics. |
|
|
216
|
+
| **GiST** | Geometric, ranges, full-text (older). |
|
|
217
|
+
| **BRIN** | Huge append-only tables sorted by insertion (audit logs, time-series). 1000× smaller than B-tree. |
|
|
218
|
+
|
|
219
|
+
### Composite Indexes — Order Matters
|
|
220
|
+
|
|
221
|
+
Match the WHERE + ORDER BY of your query. The leftmost columns are usable for partial matches; rightward columns are not.
|
|
222
|
+
|
|
223
|
+
```sql
|
|
224
|
+
-- Query: WHERE user_id = $1 AND status = 'paid' ORDER BY created_at DESC
|
|
225
|
+
CREATE INDEX idx_orders_user_status_created
|
|
226
|
+
ON orders(user_id, status, created_at DESC);
|
|
227
|
+
-- Order: equality cols first, then range/ORDER BY col last.
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Partial Indexes
|
|
231
|
+
|
|
232
|
+
Index only rows that matter. Massive size reduction for "active" / "pending" subsets.
|
|
233
|
+
|
|
234
|
+
```sql
|
|
235
|
+
-- Common: only paid orders — most queries filter on this.
|
|
236
|
+
CREATE INDEX idx_orders_paid_user
|
|
237
|
+
ON orders(user_id, created_at DESC)
|
|
238
|
+
WHERE status = 'paid';
|
|
239
|
+
|
|
240
|
+
-- Common: only undeleted rows.
|
|
241
|
+
CREATE INDEX idx_users_email_active
|
|
242
|
+
ON users(email) WHERE deleted_at IS NULL;
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Covering Indexes (INCLUDE)
|
|
246
|
+
|
|
247
|
+
When your query selects 2 small columns and filters on a 3rd, INCLUDE lets the index satisfy the query without a heap fetch.
|
|
248
|
+
|
|
249
|
+
```sql
|
|
250
|
+
CREATE INDEX idx_orders_user_paid_covering
|
|
251
|
+
ON orders(user_id) INCLUDE (id, total)
|
|
252
|
+
WHERE status = 'paid';
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### What Not to Index
|
|
256
|
+
|
|
257
|
+
- Columns with low cardinality (`is_active` boolean) — usually a partial index on the rare value works.
|
|
258
|
+
- Columns rarely filtered on.
|
|
259
|
+
- Tables that are 99% writes, 1% reads (background queues, audit append).
|
|
260
|
+
- Anything you can't see used in `pg_stat_user_indexes` after a week — drop it.
|
|
261
|
+
|
|
262
|
+
### Maintenance
|
|
263
|
+
|
|
264
|
+
```sql
|
|
265
|
+
-- Weekly:
|
|
266
|
+
SELECT schemaname, relname, indexrelname, idx_scan, idx_tup_read, idx_tup_fetch
|
|
267
|
+
FROM pg_stat_user_indexes
|
|
268
|
+
ORDER BY idx_scan ASC;
|
|
269
|
+
-- Drop indexes with idx_scan = 0 after a full week of normal traffic.
|
|
270
|
+
|
|
271
|
+
-- VACUUM + ANALYZE on a regular schedule (autovacuum usually fine; tune
|
|
272
|
+
-- per-table for very-large or hot tables).
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
For the full migration playbook (online additive changes, expand-contract, backfills, NOT NULL adds, FK adds), see [references/migration-discipline.md](references/migration-discipline.md).
|
|
276
|
+
|
|
277
|
+
For Postgres-specific patterns (advisory locks, LISTEN/NOTIFY, full-text search, pgvector for embeddings, partitioning), see [references/postgres-patterns.md](references/postgres-patterns.md).
|
|
278
|
+
|
|
279
|
+
## ORM vs Raw SQL Trade-Off
|
|
280
|
+
|
|
281
|
+
Pick per-query, not per-codebase:
|
|
282
|
+
|
|
283
|
+
| Use ORM (sqlc / SQLAlchemy / Drizzle / GORM) when | Use raw SQL when |
|
|
284
|
+
|---|---|
|
|
285
|
+
| CRUD on a single row by PK | Multi-table joins with non-trivial filters |
|
|
286
|
+
| Simple list with 1–2 filters | Aggregations, window functions, CTEs |
|
|
287
|
+
| Inserts / updates with all columns | Bulk operations (`COPY`, `INSERT ... SELECT`) |
|
|
288
|
+
| Mocking is critical (test isolation) | EXPLAIN-tuned hot paths |
|
|
289
|
+
| Code-generated typed clients available | Anything where you'd write SQL anyway, then translate to ORM |
|
|
290
|
+
|
|
291
|
+
**This project**: in Go, `sqlc` (compile-time SQL→typed Go) for everything except trivial CRUD. In Python, `asyncpg` + thin handcrafted queries; SQLAlchemy Core (NOT ORM) when you need composable query building. Avoid ActiveRecord-style ORM (Django ORM, GORM eager loading, SQLAlchemy ORM) — they hide the actual queries until prod.
|
|
292
|
+
|
|
293
|
+
## N+1 Detection
|
|
294
|
+
|
|
295
|
+
The single most common performance bug. Detect via:
|
|
296
|
+
|
|
297
|
+
1. **Logging**: log every query with timing. `SELECT * FROM orders WHERE id = X` repeated 100 times = N+1.
|
|
298
|
+
2. **Linting**: `pg_qualstats` extension flags hot patterns.
|
|
299
|
+
3. **Test assertion**: `assert query_count(do_thing) <= 5`. Fails the build when N+1 sneaks in.
|
|
300
|
+
|
|
301
|
+
Fix:
|
|
302
|
+
|
|
303
|
+
- ORM: eager load (`prefetch_related`, `joinedload`, `JOIN FETCH`, `Includes`).
|
|
304
|
+
- Raw SQL: `JOIN` or `WITH ... SELECT ... FROM unnest($1)` for batch lookups.
|
|
305
|
+
|
|
306
|
+
## Connection Pool Sanity
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
PgBouncer (transaction mode) → Postgres
|
|
310
|
+
↑
|
|
311
|
+
Application pool (sqlc / asyncpg) — small (10–20 conns per replica)
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Rules:
|
|
315
|
+
|
|
316
|
+
- App pool max ≪ Postgres `max_connections`. With PgBouncer in front, you can have 1000 app connections multiplexed onto 50 actual Postgres conns.
|
|
317
|
+
- Idle timeout < server idle-in-transaction timeout. Avoid orphaned transactions.
|
|
318
|
+
- Per-tenant pool? No. Use one pool, set search_path / RLS policy per request.
|
|
319
|
+
|
|
320
|
+
## Source Material
|
|
321
|
+
|
|
322
|
+
- *PostgreSQL Documentation* (16/17/18) — the only canonical source for Postgres specifics. Don't trust Stack Overflow for performance; do trust the docs.
|
|
323
|
+
- *Designing Data-Intensive Applications* (Kleppmann) — the storage-and-retrieval chapters are timeless.
|
|
324
|
+
- *The Art of PostgreSQL* (Dimitri Fontaine) — practical Postgres patterns.
|
|
325
|
+
- Markus Winand — *use-the-index-luke.com* — definitive index reference.
|
|
326
|
+
- Brandur Leach — schema migration write-ups (heroku/stripe era).
|
|
327
|
+
- Sidekiq author Mike Perham — background-job patterns leveraging Postgres LISTEN/NOTIFY.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
-- migrations/NNN_<short_description>.sql
|
|
2
|
+
-- ---------------------------------------------------------------------
|
|
3
|
+
-- Migration template — copy this when authoring a new schema change.
|
|
4
|
+
--
|
|
5
|
+
-- Phase: <expand | migrate | contract>
|
|
6
|
+
-- Backward compatible with previous release: <yes | no, blocker: ...>
|
|
7
|
+
-- Lock duration estimate: <e.g., <100ms ACCESS EXCLUSIVE>
|
|
8
|
+
-- Rewrites table: <yes | no>
|
|
9
|
+
-- Backfill: <none | inline | background-job NAME>
|
|
10
|
+
-- Rollback path: <new migration NNN+k that reverses>
|
|
11
|
+
-- ---------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
-- Fail fast if we cannot acquire locks promptly.
|
|
14
|
+
SET LOCK_TIMEOUT = '5s';
|
|
15
|
+
SET STATEMENT_TIMEOUT = '60s';
|
|
16
|
+
|
|
17
|
+
BEGIN;
|
|
18
|
+
|
|
19
|
+
-- ============================================================
|
|
20
|
+
-- 1. SCHEMA CHANGES (DDL) — keep each statement short
|
|
21
|
+
-- ============================================================
|
|
22
|
+
|
|
23
|
+
-- Example: add a new column (instant on PG 11+ with constant default).
|
|
24
|
+
ALTER TABLE orders
|
|
25
|
+
ADD COLUMN coupon_code TEXT;
|
|
26
|
+
|
|
27
|
+
-- Example: add NOT VALID constraint (no full-table scan now).
|
|
28
|
+
-- ALTER TABLE orders
|
|
29
|
+
-- ADD CONSTRAINT orders_coupon_format
|
|
30
|
+
-- CHECK (coupon_code ~ '^[A-Z0-9]{4,16}$') NOT VALID;
|
|
31
|
+
|
|
32
|
+
-- ============================================================
|
|
33
|
+
-- 2. NEW INDEXES (must be CONCURRENTLY, NOT inside transaction)
|
|
34
|
+
-- ============================================================
|
|
35
|
+
-- IMPORTANT: CREATE INDEX CONCURRENTLY cannot run inside BEGIN.
|
|
36
|
+
-- Some migration runners (sqitch, dbmate) support marking a migration as
|
|
37
|
+
-- "no-transaction" — use that flag and put concurrent ops in a separate
|
|
38
|
+
-- migration file.
|
|
39
|
+
|
|
40
|
+
-- See: migrations/NNN+1_create_idx_orders_coupon_code.sql
|
|
41
|
+
|
|
42
|
+
COMMIT;
|
|
43
|
+
|
|
44
|
+
-- ============================================================
|
|
45
|
+
-- 3. POST-DEPLOY (separate migration file, after app rolls out)
|
|
46
|
+
-- ============================================================
|
|
47
|
+
-- - Validate constraints: ALTER TABLE ... VALIDATE CONSTRAINT ...
|
|
48
|
+
-- - Drop old columns (only after a full deploy soak)
|
|
49
|
+
-- - Backfill (separate background job, not inline DDL)
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# Migration Discipline — Zero-Downtime Schema Changes
|
|
2
|
+
|
|
3
|
+
The patterns for changing schema on a live database. Every migration here assumes:
|
|
4
|
+
|
|
5
|
+
1. Multiple app replicas running.
|
|
6
|
+
2. App version N and N+1 may run simultaneously during deploy.
|
|
7
|
+
3. You cannot pause writes.
|
|
8
|
+
4. Postgres ≥ 13 (most patterns work back to 9.6).
|
|
9
|
+
|
|
10
|
+
If you have downtime windows, you can skip half the dance. Document explicitly when an `ACCESS EXCLUSIVE LOCK` operation is acceptable.
|
|
11
|
+
|
|
12
|
+
## The Two Laws
|
|
13
|
+
|
|
14
|
+
1. **Forward only.** Migrations don't have a `down()`. Mistakes are fixed by writing a NEW migration that undoes the change. Reversibility encourages laziness; forward-only forces care.
|
|
15
|
+
2. **Each release is backward-compatible with the previous one.** App N+1 can run against the old schema. App N can run against the new schema. NEVER both directions broken at once.
|
|
16
|
+
|
|
17
|
+
## Expand-Contract — the Universal Pattern
|
|
18
|
+
|
|
19
|
+
Most schema changes follow this three-phase release cycle:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Release 1: EXPAND
|
|
23
|
+
- Add new schema (column / table / index) without removing old.
|
|
24
|
+
- App N still uses old; app N+1 (rolled out next) writes BOTH old + new.
|
|
25
|
+
|
|
26
|
+
Release 2: MIGRATE
|
|
27
|
+
- Backfill data from old → new.
|
|
28
|
+
- App writes both, reads from new (fall back to old if absent).
|
|
29
|
+
|
|
30
|
+
Release 3: CONTRACT
|
|
31
|
+
- Stop writing to old.
|
|
32
|
+
- Drop old column / table / index after a soak period.
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Three releases for a rename. Yes, really. Examples below.
|
|
36
|
+
|
|
37
|
+
## Adding a Column — Easy
|
|
38
|
+
|
|
39
|
+
Postgres ≥ 11 with no DEFAULT or with a constant DEFAULT: instant. No table rewrite.
|
|
40
|
+
|
|
41
|
+
```sql
|
|
42
|
+
-- Migration v42 — INSTANT, no lock.
|
|
43
|
+
ALTER TABLE orders ADD COLUMN coupon_code TEXT;
|
|
44
|
+
|
|
45
|
+
-- With a constant default (PG 11+) — also INSTANT.
|
|
46
|
+
ALTER TABLE orders ADD COLUMN priority SMALLINT NOT NULL DEFAULT 5;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
⚠️ Volatile DEFAULT (e.g., `NOW()`, function call) DOES rewrite. Use a backfill instead.
|
|
50
|
+
|
|
51
|
+
## Adding NOT NULL to Existing Column — 3-Phase
|
|
52
|
+
|
|
53
|
+
Cannot just `ALTER COLUMN ... SET NOT NULL` on a populated nullable column without scanning the whole table.
|
|
54
|
+
|
|
55
|
+
```sql
|
|
56
|
+
-- Phase 1 (release 1): app starts writing the value.
|
|
57
|
+
-- Schema unchanged.
|
|
58
|
+
|
|
59
|
+
-- Phase 2 (release 2): backfill in batches OFFLINE or via background job.
|
|
60
|
+
UPDATE orders SET status = 'pending' WHERE status IS NULL;
|
|
61
|
+
|
|
62
|
+
-- Phase 3 (release 3): now safe to constrain.
|
|
63
|
+
-- Use NOT VALID to skip the full-table check at the lock-acquisition moment:
|
|
64
|
+
ALTER TABLE orders
|
|
65
|
+
ADD CONSTRAINT orders_status_not_null CHECK (status IS NOT NULL) NOT VALID;
|
|
66
|
+
ALTER TABLE orders VALIDATE CONSTRAINT orders_status_not_null;
|
|
67
|
+
-- VALIDATE acquires a SHARE UPDATE EXCLUSIVE lock — readers + writers continue.
|
|
68
|
+
|
|
69
|
+
-- Optional cleanup (release 4): convert CHECK → NOT NULL.
|
|
70
|
+
ALTER TABLE orders ALTER COLUMN status SET NOT NULL;
|
|
71
|
+
ALTER TABLE orders DROP CONSTRAINT orders_status_not_null;
|
|
72
|
+
-- The SET NOT NULL above is now FAST because PG sees the validated CHECK.
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Adding a Foreign Key — 2-Phase
|
|
76
|
+
|
|
77
|
+
```sql
|
|
78
|
+
-- Phase 1: add the FK as NOT VALID. Doesn't lock-scan the whole table.
|
|
79
|
+
ALTER TABLE order_items
|
|
80
|
+
ADD CONSTRAINT order_items_order_id_fk
|
|
81
|
+
FOREIGN KEY (order_id) REFERENCES orders(id) NOT VALID;
|
|
82
|
+
|
|
83
|
+
-- Phase 2: validate later (separate migration / background).
|
|
84
|
+
ALTER TABLE order_items VALIDATE CONSTRAINT order_items_order_id_fk;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Adding an Index — Always CONCURRENTLY
|
|
88
|
+
|
|
89
|
+
```sql
|
|
90
|
+
-- WRONG — locks writes for minutes on a big table.
|
|
91
|
+
CREATE INDEX idx_orders_user ON orders(user_id);
|
|
92
|
+
|
|
93
|
+
-- RIGHT — no write block, scans + builds in background.
|
|
94
|
+
CREATE INDEX CONCURRENTLY idx_orders_user ON orders(user_id);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Caveats:
|
|
98
|
+
|
|
99
|
+
- `CONCURRENTLY` cannot run inside a transaction. If your migration framework wraps each migration in a tx, escape it (e.g., Alembic: `with op.get_context().autocommit_block(): op.execute(...)`)
|
|
100
|
+
- Failed concurrent build leaves an INVALID index. Drop and retry: `DROP INDEX CONCURRENTLY IF EXISTS idx_name;`
|
|
101
|
+
|
|
102
|
+
## Renaming a Column — 3-Phase
|
|
103
|
+
|
|
104
|
+
```sql
|
|
105
|
+
-- Release 1: ADD NEW COLUMN, dual-write.
|
|
106
|
+
ALTER TABLE users ADD COLUMN full_name TEXT;
|
|
107
|
+
-- App writes BOTH `name` and `full_name`. Reads from `name`.
|
|
108
|
+
|
|
109
|
+
-- Release 2: BACKFILL + READ from new.
|
|
110
|
+
UPDATE users SET full_name = name WHERE full_name IS NULL;
|
|
111
|
+
-- App reads `full_name`, falls back to `name` if NULL.
|
|
112
|
+
-- App still writes both.
|
|
113
|
+
|
|
114
|
+
-- Release 3: STOP writing old.
|
|
115
|
+
-- App writes only `full_name`. Reads only `full_name`.
|
|
116
|
+
|
|
117
|
+
-- Release 4: DROP old column.
|
|
118
|
+
ALTER TABLE users DROP COLUMN name;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Same pattern for renaming a table — three releases at minimum.
|
|
122
|
+
|
|
123
|
+
## Renaming a Table — 3-Phase via View
|
|
124
|
+
|
|
125
|
+
Faster alternative:
|
|
126
|
+
|
|
127
|
+
```sql
|
|
128
|
+
-- Release 1: rename + create a view at the old name.
|
|
129
|
+
ALTER TABLE legacy_users RENAME TO users;
|
|
130
|
+
CREATE VIEW legacy_users AS SELECT * FROM users;
|
|
131
|
+
|
|
132
|
+
-- Release 2: app updated to use new name.
|
|
133
|
+
|
|
134
|
+
-- Release 3: drop the view.
|
|
135
|
+
DROP VIEW legacy_users;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The view is updatable for simple cases. Stops working for complex queries; test thoroughly.
|
|
139
|
+
|
|
140
|
+
## Dropping a Column — 2-Phase
|
|
141
|
+
|
|
142
|
+
```sql
|
|
143
|
+
-- Release 1: app stops reading + writing the column.
|
|
144
|
+
|
|
145
|
+
-- Release 2 (after a soak period — at least one full deploy + observation):
|
|
146
|
+
ALTER TABLE orders DROP COLUMN deprecated_status;
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Postgres 11+ marks the column as dropped without rewriting the table; rewrite happens at the next `VACUUM FULL` or `pg_repack`.
|
|
150
|
+
|
|
151
|
+
## Dropping an Index — Always CONCURRENTLY
|
|
152
|
+
|
|
153
|
+
```sql
|
|
154
|
+
DROP INDEX CONCURRENTLY IF EXISTS idx_orders_old;
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Backfills — Batch It
|
|
158
|
+
|
|
159
|
+
Never run a single `UPDATE` over a billion-row table. The undo log explodes; replicas lag; vacuum can't keep up.
|
|
160
|
+
|
|
161
|
+
```sql
|
|
162
|
+
-- Migration runner: kick off background job, NOT inline.
|
|
163
|
+
|
|
164
|
+
-- Background worker, in batches of 10k:
|
|
165
|
+
DO $$
|
|
166
|
+
DECLARE
|
|
167
|
+
rows_updated INT := 1;
|
|
168
|
+
BEGIN
|
|
169
|
+
WHILE rows_updated > 0 LOOP
|
|
170
|
+
WITH batch AS (
|
|
171
|
+
SELECT id FROM orders
|
|
172
|
+
WHERE coupon_code IS NULL
|
|
173
|
+
LIMIT 10000
|
|
174
|
+
FOR UPDATE SKIP LOCKED
|
|
175
|
+
)
|
|
176
|
+
UPDATE orders o
|
|
177
|
+
SET coupon_code = COALESCE(o.legacy_promo, '')
|
|
178
|
+
FROM batch
|
|
179
|
+
WHERE o.id = batch.id;
|
|
180
|
+
|
|
181
|
+
GET DIAGNOSTICS rows_updated = ROW_COUNT;
|
|
182
|
+
PERFORM pg_sleep(0.1); -- breathe; let replication catch up
|
|
183
|
+
END LOOP;
|
|
184
|
+
END $$;
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
For backfills measured in millions of rows, prefer a dedicated CLI command + checkpoint table that records progress, so re-running picks up where it left off.
|
|
188
|
+
|
|
189
|
+
## Type Changes — Almost Always Add-and-Migrate
|
|
190
|
+
|
|
191
|
+
Changing `INT` → `BIGINT` on a wide table rewrites everything. Don't.
|
|
192
|
+
|
|
193
|
+
Pattern:
|
|
194
|
+
|
|
195
|
+
```sql
|
|
196
|
+
-- Phase 1: add new column with the new type.
|
|
197
|
+
ALTER TABLE events ADD COLUMN id_v2 BIGINT;
|
|
198
|
+
-- App dual-writes id and id_v2.
|
|
199
|
+
|
|
200
|
+
-- Phase 2: backfill.
|
|
201
|
+
UPDATE events SET id_v2 = id::bigint WHERE id_v2 IS NULL;
|
|
202
|
+
|
|
203
|
+
-- Phase 3: switch FK targets to id_v2 (per related table).
|
|
204
|
+
-- Phase 4: drop id, rename id_v2 → id.
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Locking Behavior Cheat Sheet
|
|
208
|
+
|
|
209
|
+
| Operation | Lock acquired | Blocks |
|
|
210
|
+
|---|---|---|
|
|
211
|
+
| `ADD COLUMN` (no default or constant default) | `ACCESS EXCLUSIVE` for milliseconds | Everything briefly |
|
|
212
|
+
| `ADD COLUMN` (volatile default) | `ACCESS EXCLUSIVE` for table rewrite | Everything for minutes |
|
|
213
|
+
| `ALTER COLUMN ... SET NOT NULL` (without prior CHECK) | `ACCESS EXCLUSIVE` for full scan | Everything |
|
|
214
|
+
| `ALTER COLUMN ... SET NOT NULL` (with validated CHECK) | `ACCESS EXCLUSIVE` for milliseconds | Briefly |
|
|
215
|
+
| `ADD CONSTRAINT ... NOT VALID` | `ACCESS EXCLUSIVE` for milliseconds | Briefly |
|
|
216
|
+
| `VALIDATE CONSTRAINT` | `SHARE UPDATE EXCLUSIVE` | DDL only |
|
|
217
|
+
| `CREATE INDEX` | `SHARE` | Writes |
|
|
218
|
+
| `CREATE INDEX CONCURRENTLY` | `SHARE UPDATE EXCLUSIVE` | DDL only |
|
|
219
|
+
| `DROP COLUMN` | `ACCESS EXCLUSIVE` for milliseconds | Briefly |
|
|
220
|
+
| `DROP INDEX` | `ACCESS EXCLUSIVE` for milliseconds | Briefly |
|
|
221
|
+
| `DROP INDEX CONCURRENTLY` | `SHARE UPDATE EXCLUSIVE` | DDL only |
|
|
222
|
+
| `ALTER TABLE ... RENAME` | `ACCESS EXCLUSIVE` for milliseconds | Briefly |
|
|
223
|
+
| `TRUNCATE` | `ACCESS EXCLUSIVE` | Everything |
|
|
224
|
+
|
|
225
|
+
The dangerous ones are the `ACCESS EXCLUSIVE for ... full scan / rewrite` rows. Those are the ones you must dance around.
|
|
226
|
+
|
|
227
|
+
## Migration Tooling Conventions
|
|
228
|
+
|
|
229
|
+
Whatever tool you use (Goose, Atlas, Alembic, Flyway, dbmate, sqitch), establish:
|
|
230
|
+
|
|
231
|
+
1. **One migration per file**, named `NNN_description.sql` (NNN monotonic).
|
|
232
|
+
2. **Migrations are append-only** — never edit an applied migration. Mistake → write a new one that fixes it.
|
|
233
|
+
3. **Schema dump checked in** — run `pg_dump --schema-only --no-owner` after each migration; commit. PR review then sees the actual end state, not just the diff.
|
|
234
|
+
4. **Migrations applied in CI** — every PR runs `migrate up` against a fresh DB. If it fails, build fails.
|
|
235
|
+
5. **`SET LOCK_TIMEOUT` on every migration** — fail fast if you can't acquire the lock:
|
|
236
|
+
```sql
|
|
237
|
+
SET LOCK_TIMEOUT = '5s';
|
|
238
|
+
SET STATEMENT_TIMEOUT = '60s';
|
|
239
|
+
|
|
240
|
+
ALTER TABLE orders ADD COLUMN coupon_code TEXT;
|
|
241
|
+
```
|
|
242
|
+
6. **Migrations are idempotent where possible**: `CREATE INDEX IF NOT EXISTS`, `ALTER TABLE ... IF NOT EXISTS COLUMN`, `DROP IF EXISTS`. Re-running a failed migration shouldn't error.
|
|
243
|
+
|
|
244
|
+
## Per-PR Checklist
|
|
245
|
+
|
|
246
|
+
Before approving a migration PR, the reviewer asks:
|
|
247
|
+
|
|
248
|
+
- [ ] Lock duration: which lock, on which tables, for how long?
|
|
249
|
+
- [ ] Table rewrite: yes/no? If yes, scheduled for off-hours?
|
|
250
|
+
- [ ] Backfill: inline vs background job? Batched? Idempotent? Recoverable?
|
|
251
|
+
- [ ] App compatibility: does the previous release still work after this migration applies?
|
|
252
|
+
- [ ] Rollback plan: what's the new migration we'd write if this one is wrong?
|
|
253
|
+
- [ ] Index added concurrently? Index removed concurrently?
|
|
254
|
+
- [ ] `LOCK_TIMEOUT` set?
|
|
255
|
+
- [ ] Tested on prod-sized dataset (or at least same shape)?
|
|
256
|
+
|
|
257
|
+
A "no" without a written justification = block.
|
|
258
|
+
|
|
259
|
+
## Postgres-Specific Gotchas
|
|
260
|
+
|
|
261
|
+
- **`SERIAL` columns implicitly create a sequence + DEFAULT + UNIQUE**. Modern code uses `GENERATED BY DEFAULT AS IDENTITY` (cleaner, owns the sequence properly).
|
|
262
|
+
- **`CITEXT`** for case-insensitive text is fine but breaks the GIN index pattern. Consider lowercasing in the column itself with a generated column.
|
|
263
|
+
- **Generated columns** (`GENERATED ALWAYS AS ... STORED`) are cheap and let you index a derived value. Use for `lower(email)`, JSON extracts, etc.
|
|
264
|
+
- **`pg_repack` / `pg_squeeze`** for online table rewrite when you absolutely must. Better than `VACUUM FULL` (which locks).
|
|
265
|
+
- **Replication lag**: most patterns assume primary-replica setup. If a backfill is heavy, throttle it (the `pg_sleep(0.1)` above) and watch `pg_stat_replication`.
|
|
266
|
+
|
|
267
|
+
## Anti-Patterns
|
|
268
|
+
|
|
269
|
+
1. **Editing a previously applied migration**. Now app version on prod and dev have different schema histories. Tools detect this and refuse to run.
|
|
270
|
+
2. **Single-step rename / type change**. Always 3-phase.
|
|
271
|
+
3. **`ACCESS EXCLUSIVE` operation in a long transaction**. Holds the lock for the entire transaction. Always one statement per migration when locking.
|
|
272
|
+
4. **DEFAULT value backfill via `UPDATE ... WHERE col IS NULL`** on a live large table. Batch + sleep, or use a separate background job.
|
|
273
|
+
5. **Concurrent index without `IF NOT EXISTS`** then re-running after failure. Picks up the old INVALID index — drop first.
|
|
274
|
+
6. **No `LOCK_TIMEOUT`**. The migration hangs forever waiting for a long-running query, blocking everything new. Always 5–10s default.
|
|
275
|
+
|
|
276
|
+
## Rollback Reality Check
|
|
277
|
+
|
|
278
|
+
You don't have one. The "rollback" is "write another migration that undoes". Plan migrations so this is possible:
|
|
279
|
+
|
|
280
|
+
- Don't `DROP COLUMN` until the column has been unused for a full deploy cycle. The "undo" of a drop is the data — gone.
|
|
281
|
+
- Rename via add-and-deprecate, not via in-place rename.
|
|
282
|
+
- Test the new code with the OLD schema (CI step: deploy app version N+1 against schema version N). Catches "I forgot to roll out the migration first" bugs.
|
|
283
|
+
|
|
284
|
+
## References
|
|
285
|
+
|
|
286
|
+
- [PostgreSQL "Strong Consistency, No SQL" — locking patterns](https://www.postgresql.org/docs/current/explicit-locking.html)
|
|
287
|
+
- [Strong's blog — *Safer Postgres migrations*](https://www.thatguyfromdelhi.com/2024/03/safer-postgres-migrations.html)
|
|
288
|
+
- [GitLab — *Avoid downtime in migrations*](https://docs.gitlab.com/ee/development/migration_style_guide.html)
|
|
289
|
+
- [Stripe — *Online migrations at scale*](https://stripe.com/blog/online-migrations) — the canonical write-up.
|
|
290
|
+
- `lock_timeout` reference: <https://www.postgresql.org/docs/current/runtime-config-client.html>
|