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,230 @@
|
|
|
1
|
+
# Server Sessions vs JWTs — Decision + Implementation
|
|
2
|
+
|
|
3
|
+
The choice that shapes every other auth decision. Read once; refer to the table when you're tempted to switch mid-design.
|
|
4
|
+
|
|
5
|
+
## The Honest Comparison
|
|
6
|
+
|
|
7
|
+
| Concern | Server sessions (opaque token) | JWT (signed claims) |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| **Storage** | DB row per session | None server-side (or blocklist) |
|
|
10
|
+
| **Read cost / request** | DB lookup or Redis hit | Verify signature (~µs) |
|
|
11
|
+
| **Revocation** | Instant (`UPDATE sessions SET revoked_at = NOW()`) | Hard — short TTL or blocklist |
|
|
12
|
+
| **Token size** | ~32 bytes opaque | 200-1000 bytes |
|
|
13
|
+
| **Logout from all devices** | `DELETE WHERE user_id = X` | Per-user `iat_min` revocation epoch |
|
|
14
|
+
| **Multi-service trust** | Need shared session store / call-back endpoint | Self-contained — verify signature |
|
|
15
|
+
| **Audit / observability** | Easy — sessions table is the source of truth | Harder — need usage tracking |
|
|
16
|
+
| **Mobile-friendly** | Yes — opaque token in Keychain | Yes — opaque token in Keychain |
|
|
17
|
+
| **Browser-friendly** | Cookies + CSRF defense | Cookies (CSRF), header (XSS), localStorage (XSS+disk) |
|
|
18
|
+
| **Attack surface on theft** | One DB lookup → revoked | Valid until expiry; revocation hard |
|
|
19
|
+
| **Cross-domain SSO** | Hard (cookies are origin-scoped) | Easier (just verify the token) |
|
|
20
|
+
| **Operational complexity** | Low (one DB) | Medium (key rotation, JWKS, blocklist) |
|
|
21
|
+
|
|
22
|
+
## Decision Tree
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
Single trust domain (one product, one team's services)?
|
|
26
|
+
├─ Yes → Server sessions
|
|
27
|
+
│ └─ Need to call other internal services with user identity?
|
|
28
|
+
│ └─ Yes → Mint short-lived JWT at the API gateway / business backend.
|
|
29
|
+
│ The CLIENT never sees a JWT.
|
|
30
|
+
│
|
|
31
|
+
└─ No (multiple distinct trust domains, third-party callers)
|
|
32
|
+
└─ JWT — short-lived, signed, with key rotation
|
|
33
|
+
└─ Need revocation? → Blocklist or `iat_min` per-user epoch.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Server Session Implementation
|
|
37
|
+
|
|
38
|
+
### Schema
|
|
39
|
+
|
|
40
|
+
```sql
|
|
41
|
+
CREATE TABLE sessions (
|
|
42
|
+
id TEXT PRIMARY KEY, -- public token (e.g. "ses_8h2k...")
|
|
43
|
+
token_hash TEXT NOT NULL, -- SHA-256 of id (defense-in-depth: DB dump = no usable tokens)
|
|
44
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
45
|
+
family_id TEXT NOT NULL, -- shared with refresh tokens for theft detection
|
|
46
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
47
|
+
last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
48
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
49
|
+
revoked_at TIMESTAMPTZ, -- NULL while active
|
|
50
|
+
user_agent TEXT,
|
|
51
|
+
ip INET,
|
|
52
|
+
scopes TEXT[] NOT NULL DEFAULT '{}' -- granted scopes
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
CREATE INDEX idx_sessions_user_active ON sessions(user_id) WHERE revoked_at IS NULL;
|
|
56
|
+
CREATE INDEX idx_sessions_token_hash ON sessions(token_hash);
|
|
57
|
+
|
|
58
|
+
-- Sweep job (hourly): delete sessions revoked > 30 days ago.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The token format: `ses_<32 random chars from URL-safe alphabet>`. The DB stores `SHA-256(token)` and only validates by hash — even a full DB dump doesn't yield usable tokens.
|
|
62
|
+
|
|
63
|
+
### Verify Middleware (Go + Fiber)
|
|
64
|
+
|
|
65
|
+
```go
|
|
66
|
+
func RequireSession(store SessionStore) fiber.Handler {
|
|
67
|
+
return func(c fiber.Ctx) error {
|
|
68
|
+
token := bearerToken(c.Get("Authorization"))
|
|
69
|
+
if token == "" {
|
|
70
|
+
return apperr.Unauthenticated(c, "missing_token", "")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
hash := sha256Hex(token)
|
|
74
|
+
sess, err := store.LookupActive(c.Context(), hash)
|
|
75
|
+
if err != nil {
|
|
76
|
+
return apperr.Unauthenticated(c, "invalid_token", "")
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Update last_seen async (don't block the request).
|
|
80
|
+
go store.TouchAsync(sess.ID)
|
|
81
|
+
|
|
82
|
+
c.Locals("user_id", sess.UserID)
|
|
83
|
+
c.Locals("scopes", sess.Scopes)
|
|
84
|
+
return c.Next()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Cache hot sessions in Redis with a short TTL (60s) to absorb the read load. Cache invalidation = delete by ID on revoke.
|
|
90
|
+
|
|
91
|
+
### Verify Middleware (Python + FastAPI)
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from fastapi import Depends, HTTPException, Header
|
|
95
|
+
|
|
96
|
+
async def require_session(
|
|
97
|
+
authorization: str = Header(...),
|
|
98
|
+
store: SessionStore = Depends(get_session_store),
|
|
99
|
+
) -> Actor:
|
|
100
|
+
token = bearer_token(authorization)
|
|
101
|
+
if not token:
|
|
102
|
+
raise HTTPException(401, detail="missing_token")
|
|
103
|
+
sess = await store.lookup_active(sha256_hex(token))
|
|
104
|
+
if not sess:
|
|
105
|
+
raise HTTPException(401, detail="invalid_token")
|
|
106
|
+
asyncio.create_task(store.touch(sess.id))
|
|
107
|
+
return Actor(user_id=sess.user_id, scopes=sess.scopes)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## JWT Implementation (Internal Service-to-Service)
|
|
111
|
+
|
|
112
|
+
When the Go backend calls the Python AI adapter, it mints a short-lived JWT:
|
|
113
|
+
|
|
114
|
+
```go
|
|
115
|
+
import "github.com/golang-jwt/jwt/v5"
|
|
116
|
+
|
|
117
|
+
type ServiceClaims struct {
|
|
118
|
+
Scope []string `json:"scope"`
|
|
119
|
+
jwt.RegisteredClaims
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
func MintServiceToken(privKey ed25519.PrivateKey, kid, userID string, scopes []string) (string, error) {
|
|
123
|
+
now := time.Now()
|
|
124
|
+
claims := ServiceClaims{
|
|
125
|
+
Scope: scopes,
|
|
126
|
+
RegisteredClaims: jwt.RegisteredClaims{
|
|
127
|
+
Subject: userID,
|
|
128
|
+
Issuer: "business-api",
|
|
129
|
+
Audience: jwt.ClaimStrings{"ai-adapter"},
|
|
130
|
+
IssuedAt: jwt.NewNumericDate(now),
|
|
131
|
+
ExpiresAt: jwt.NewNumericDate(now.Add(5 * time.Minute)),
|
|
132
|
+
NotBefore: jwt.NewNumericDate(now.Add(-30 * time.Second)), // clock skew
|
|
133
|
+
ID: uuid.NewString(), // jti for replay tracking
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
tok := jwt.NewWithClaims(jwt.SigningMethodEdDSA, claims)
|
|
137
|
+
tok.Header["kid"] = kid
|
|
138
|
+
return tok.SignedString(privKey)
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Verify (Python side):
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
import jwt
|
|
146
|
+
import httpx
|
|
147
|
+
from cachetools import TTLCache
|
|
148
|
+
|
|
149
|
+
JWKS_CACHE: TTLCache = TTLCache(maxsize=4, ttl=600)
|
|
150
|
+
|
|
151
|
+
async def get_jwks(issuer: str) -> dict:
|
|
152
|
+
if issuer in JWKS_CACHE:
|
|
153
|
+
return JWKS_CACHE[issuer]
|
|
154
|
+
async with httpx.AsyncClient(timeout=5) as client:
|
|
155
|
+
resp = await client.get(f"{issuer}/.well-known/jwks.json")
|
|
156
|
+
resp.raise_for_status()
|
|
157
|
+
jwks = resp.json()
|
|
158
|
+
JWKS_CACHE[issuer] = jwks
|
|
159
|
+
return jwks
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
async def verify_service_token(token: str) -> dict:
|
|
163
|
+
unverified = jwt.get_unverified_header(token)
|
|
164
|
+
kid = unverified.get("kid")
|
|
165
|
+
if not kid:
|
|
166
|
+
raise jwt.InvalidTokenError("missing kid")
|
|
167
|
+
|
|
168
|
+
jwks = await get_jwks("https://business-api.app.com")
|
|
169
|
+
key = next((k for k in jwks["keys"] if k["kid"] == kid), None)
|
|
170
|
+
if not key:
|
|
171
|
+
raise jwt.InvalidTokenError("unknown kid")
|
|
172
|
+
|
|
173
|
+
public_key = jwt.algorithms.OKPAlgorithm.from_jwk(key)
|
|
174
|
+
payload = jwt.decode(
|
|
175
|
+
token,
|
|
176
|
+
public_key,
|
|
177
|
+
algorithms=["EdDSA"],
|
|
178
|
+
audience="ai-adapter",
|
|
179
|
+
issuer="https://business-api.app.com",
|
|
180
|
+
leeway=30, # clock skew tolerance
|
|
181
|
+
options={"require": ["sub", "iat", "exp", "aud", "iss"]},
|
|
182
|
+
)
|
|
183
|
+
return payload # {"sub": "usr_…", "scope": [...], ...}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Algorithm Selection — 2026
|
|
187
|
+
|
|
188
|
+
- **EdDSA (Ed25519)** — first choice. Small keys, fast, no parameter footguns.
|
|
189
|
+
- **RS256** — broadly compatible; pick if EdDSA support is missing in any consumer library.
|
|
190
|
+
- **ES256** — fine alternative; popular in WebAuthn ecosystem.
|
|
191
|
+
- **HS256** — only for symmetric scenarios where the verifier is the issuer. NEVER share the secret across trust boundaries.
|
|
192
|
+
- **`alg: none`** — every library MUST reject. If yours doesn't, switch libraries.
|
|
193
|
+
|
|
194
|
+
### Key Rotation
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
business-api/
|
|
198
|
+
/.well-known/jwks.json → { keys: [ {kid:"2026-04", ...}, {kid:"2026-03", ...} ] }
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
- Mint with current `kid`.
|
|
202
|
+
- Publish current + previous in JWKS for the lifetime of the longest-lived token.
|
|
203
|
+
- Rotate quarterly (or after any suspected key compromise).
|
|
204
|
+
- Verifiers cache JWKS for 10 min, refresh on `kid` miss.
|
|
205
|
+
|
|
206
|
+
## Hybrid Pattern (This Project)
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
Client (RN) ──[opaque session]──► Go API
|
|
210
|
+
│
|
|
211
|
+
│ Mint JWT { sub: user_id, scope, exp:5m, kid }
|
|
212
|
+
▼
|
|
213
|
+
FastAPI AI adapter (verifies via JWKS)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Best of both:
|
|
217
|
+
|
|
218
|
+
- Client always uses opaque sessions (revocable, simple to wipe).
|
|
219
|
+
- Service-to-service uses short JWTs (stateless, scoped, no extra DB hop on the AI adapter).
|
|
220
|
+
- AI adapter never sees the long-lived session token, so a compromise of the AI service doesn't expose user sessions.
|
|
221
|
+
|
|
222
|
+
## What NOT to Do
|
|
223
|
+
|
|
224
|
+
1. **Long-lived JWT as the only client credential** — leaks last forever.
|
|
225
|
+
2. **Session ID in URL query string** — leaks via referrers, logs, browser history.
|
|
226
|
+
3. **JWT in localStorage** for browser apps — XSS reads it.
|
|
227
|
+
4. **Stateless JWT for the user-facing API** without a path to revocation.
|
|
228
|
+
5. **Storing JWT secret in env vars accessible to client-side build** — pretty obvious mistake but seen in practice.
|
|
229
|
+
6. **Using HS256 across services owned by different teams** — shared secret = no trust boundary.
|
|
230
|
+
7. **Validating only signature, not `aud`/`iss`/`exp`** — token from one context valid in another.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Audit Set-Cookie usage for missing security flags.
|
|
3
|
+
|
|
4
|
+
Scans Python (Django + FastAPI + raw Werkzeug/Flask), TypeScript (Express,
|
|
5
|
+
Next.js Route Handlers, Hono), and Go (Fiber, stdlib net/http) source
|
|
6
|
+
files for cookie-setting calls without Secure/HttpOnly/SameSite.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python cookie-flag-check.py [paths...]
|
|
10
|
+
python cookie-flag-check.py --json [paths...]
|
|
11
|
+
|
|
12
|
+
Exit code 1 if any finding.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
import json
|
|
19
|
+
import re
|
|
20
|
+
import sys
|
|
21
|
+
from dataclasses import asdict, dataclass
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
# Lightweight regex audit — not a full parser. Trade-off: occasional false
|
|
25
|
+
# positive worth the simplicity. Run with --json in CI; review findings.
|
|
26
|
+
|
|
27
|
+
# Python: response.set_cookie(...), Cookie('...'), HttpResponse(...).set_cookie
|
|
28
|
+
PY_COOKIE_PATTERNS = [
|
|
29
|
+
re.compile(r"\.set_cookie\s*\("),
|
|
30
|
+
re.compile(r"response\.cookies\s*\["),
|
|
31
|
+
re.compile(r"morsel\s*=\s*Morsel"),
|
|
32
|
+
]
|
|
33
|
+
PY_REQUIRED_FLAGS = ["httponly", "secure", "samesite"]
|
|
34
|
+
|
|
35
|
+
# TypeScript / JS: res.cookie(...), res.setHeader('Set-Cookie', ...), cookies().set(...)
|
|
36
|
+
TS_COOKIE_PATTERNS = [
|
|
37
|
+
re.compile(r"\bres\.cookie\s*\("),
|
|
38
|
+
re.compile(r"\bsetHeader\s*\(\s*['\"]Set-Cookie['\"]"),
|
|
39
|
+
re.compile(r"\bcookies\(\)\.set\s*\("),
|
|
40
|
+
]
|
|
41
|
+
TS_REQUIRED_FLAGS = ["httpOnly", "secure", "sameSite"]
|
|
42
|
+
|
|
43
|
+
# Go: c.Cookie(&fiber.Cookie{...}), http.SetCookie(...)
|
|
44
|
+
GO_COOKIE_PATTERNS = [
|
|
45
|
+
re.compile(r"\bc\.Cookie\s*\(&fiber\.Cookie"),
|
|
46
|
+
re.compile(r"\bhttp\.SetCookie\s*\("),
|
|
47
|
+
]
|
|
48
|
+
GO_REQUIRED_FLAGS = ["HttpOnly", "Secure", "SameSite"]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class Finding:
|
|
53
|
+
path: str
|
|
54
|
+
line: int
|
|
55
|
+
missing: list[str]
|
|
56
|
+
snippet: str
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _audit_block(text: str, start: int, required: list[str], window: int = 12) -> list[str]:
|
|
60
|
+
"""From `start`, scan up to `window` lines forward; return missing flags."""
|
|
61
|
+
lines = text.splitlines()
|
|
62
|
+
end = min(len(lines), start + window)
|
|
63
|
+
block = "\n".join(lines[start:end]).lower()
|
|
64
|
+
missing = [f for f in required if f.lower() not in block]
|
|
65
|
+
return missing
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def audit_file(path: Path) -> list[Finding]:
|
|
69
|
+
findings: list[Finding] = []
|
|
70
|
+
try:
|
|
71
|
+
text = path.read_text(encoding="utf-8")
|
|
72
|
+
except UnicodeDecodeError:
|
|
73
|
+
return findings
|
|
74
|
+
|
|
75
|
+
ext = path.suffix.lower()
|
|
76
|
+
if ext in {".py"}:
|
|
77
|
+
patterns, required = PY_COOKIE_PATTERNS, PY_REQUIRED_FLAGS
|
|
78
|
+
elif ext in {".ts", ".tsx", ".js", ".jsx", ".mts", ".mjs"}:
|
|
79
|
+
patterns, required = TS_COOKIE_PATTERNS, TS_REQUIRED_FLAGS
|
|
80
|
+
elif ext in {".go"}:
|
|
81
|
+
patterns, required = GO_COOKIE_PATTERNS, GO_REQUIRED_FLAGS
|
|
82
|
+
else:
|
|
83
|
+
return findings
|
|
84
|
+
|
|
85
|
+
lines = text.splitlines()
|
|
86
|
+
for i, line in enumerate(lines):
|
|
87
|
+
for pat in patterns:
|
|
88
|
+
if pat.search(line):
|
|
89
|
+
missing = _audit_block(text, i, required)
|
|
90
|
+
if missing:
|
|
91
|
+
findings.append(
|
|
92
|
+
Finding(
|
|
93
|
+
path=str(path),
|
|
94
|
+
line=i + 1,
|
|
95
|
+
missing=missing,
|
|
96
|
+
snippet=line.strip()[:120],
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
break # one finding per line max
|
|
100
|
+
return findings
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def main() -> int:
|
|
104
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
105
|
+
parser.add_argument("paths", nargs="*", default=["."])
|
|
106
|
+
parser.add_argument("--json", action="store_true")
|
|
107
|
+
parser.add_argument(
|
|
108
|
+
"--exclude", default=".venv,venv,node_modules,.build,dist,__pycache__,.git,vendor"
|
|
109
|
+
)
|
|
110
|
+
args = parser.parse_args()
|
|
111
|
+
|
|
112
|
+
excluded = set(s for s in args.exclude.split(",") if s)
|
|
113
|
+
target_files: list[Path] = []
|
|
114
|
+
for root in args.paths:
|
|
115
|
+
p = Path(root)
|
|
116
|
+
if p.is_file():
|
|
117
|
+
target_files.append(p)
|
|
118
|
+
elif p.is_dir():
|
|
119
|
+
for f in p.rglob("*"):
|
|
120
|
+
if not f.is_file():
|
|
121
|
+
continue
|
|
122
|
+
if any(part in excluded for part in f.parts):
|
|
123
|
+
continue
|
|
124
|
+
if f.suffix.lower() in {".py", ".ts", ".tsx", ".js", ".jsx", ".mts", ".mjs", ".go"}:
|
|
125
|
+
target_files.append(f)
|
|
126
|
+
|
|
127
|
+
findings: list[Finding] = []
|
|
128
|
+
for f in target_files:
|
|
129
|
+
findings.extend(audit_file(f))
|
|
130
|
+
|
|
131
|
+
if args.json:
|
|
132
|
+
json.dump([asdict(x) for x in findings], sys.stdout, indent=2)
|
|
133
|
+
sys.stdout.write("\n")
|
|
134
|
+
else:
|
|
135
|
+
if not findings:
|
|
136
|
+
print(f"[cookie-flag-check] OK: {len(target_files)} files scanned, no findings.")
|
|
137
|
+
else:
|
|
138
|
+
print(f"[cookie-flag-check] FOUND {len(findings)} finding(s):\n")
|
|
139
|
+
for f in findings:
|
|
140
|
+
print(f" {f.path}:{f.line} missing={','.join(f.missing)} | {f.snippet}")
|
|
141
|
+
|
|
142
|
+
return 1 if findings else 0
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
if __name__ == "__main__":
|
|
146
|
+
sys.exit(main())
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-fundamentals
|
|
3
|
+
tier: layer
|
|
4
|
+
domain: [backend]
|
|
5
|
+
description: Stack-agnostic backend patterns. Use when writing or modifying any server-side code (HTTP handler, DB query, background job, auth/middleware, webhook) regardless of language or framework. Covers services/selectors split, idempotency, error envelopes, migration discipline, N+1 avoidance, scale-aware design, auth guardrails, and logging hygiene.
|
|
6
|
+
globs: "backend/**/*"
|
|
7
|
+
paths: ["backend/**/*"]
|
|
8
|
+
context: fork
|
|
9
|
+
depends_on:
|
|
10
|
+
- clean-code
|
|
11
|
+
allowed-tools:
|
|
12
|
+
- Read
|
|
13
|
+
- Grep
|
|
14
|
+
- Glob
|
|
15
|
+
- Edit
|
|
16
|
+
- Write
|
|
17
|
+
last_reviewed: "2026-05-11"
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Backend Fundamentals — Stack-Agnostic Patterns
|
|
22
|
+
|
|
23
|
+
Universal guidance that holds for Django, FastAPI, Go (stdlib + Fiber), Rails, NestJS, Spring, and any other server-side framework. Framework-specific layering (DRF ViewSets, Pydantic `Depends`, Fiber middleware chain) lives in the stack-specific skill that `depends_on: [backend-fundamentals]`.
|
|
24
|
+
|
|
25
|
+
Loaded automatically when `enforce-skill.sh` routes a file under `backend/` that matches a stack skill.
|
|
26
|
+
|
|
27
|
+
## 0. Scale mindset (think before writing)
|
|
28
|
+
|
|
29
|
+
Every handler, query, and API must be written as if it will be called by 1,000 concurrent users on a 50M-row table. Before writing:
|
|
30
|
+
|
|
31
|
+
- **How many rows does this touch?** Unknown → run `EXPLAIN ANALYZE` or ask.
|
|
32
|
+
- **How many callers at once?** Single-user admin page vs. public endpoint changes everything.
|
|
33
|
+
- **Where's the bottleneck?** DB index miss · network hop · CPU work.
|
|
34
|
+
- **What's the latency budget?** Default P99 < 500 ms; surface the number in the PR description.
|
|
35
|
+
- **What happens if step 3 of 5 fails?** Transactions · idempotency key · compensating action.
|
|
36
|
+
|
|
37
|
+
Code that works on 10 rows but collapses on 10 M is a production incident waiting for traffic. Correct answer to "will this scale?" is a number, not "yes".
|
|
38
|
+
|
|
39
|
+
## 1. Service / selector split
|
|
40
|
+
|
|
41
|
+
Business logic lives in **services** (write path — mutates state, encapsulates a transaction). Read-only DB queries live in **selectors** (pure functions, cached when possible). Controllers / views / handlers only:
|
|
42
|
+
|
|
43
|
+
1. Parse and validate the request.
|
|
44
|
+
2. Call a service or selector.
|
|
45
|
+
3. Shape the response.
|
|
46
|
+
|
|
47
|
+
No ORM calls in controllers. No business rules in serializers. No DB writes in selectors. This split makes unit testing trivial (mock the service boundary) and keeps transaction boundaries visible.
|
|
48
|
+
|
|
49
|
+
## 2. Standard response envelope
|
|
50
|
+
|
|
51
|
+
Every handler returns **one** of:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{ "ok": true, "data": <T> }
|
|
55
|
+
{ "ok": false, "error": { "code": "<UPPER_SNAKE>", "message": "<human>", "retryable": true|false } }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Error codes come from a **project-level registry** (list every code in one file, e.g. `backend/errors.py` or `docs/api-contracts/error-codes.md`). Never invent codes on the fly — if a new case doesn't fit an existing code, add the new code to the registry first, then reference it.
|
|
59
|
+
|
|
60
|
+
`retryable` tells the client whether retry helps: transient/infrastructure errors `true`, validation/permission/not_found `false`. Prevents infinite retry loops on deterministic failures.
|
|
61
|
+
|
|
62
|
+
## 3. Idempotency — every state-changing call
|
|
63
|
+
|
|
64
|
+
Every endpoint that mutates state MUST accept (or derive) an idempotency key:
|
|
65
|
+
|
|
66
|
+
- Webhook → key = `<provider>:<event_id>` (Stripe, Square, GitHub, ...).
|
|
67
|
+
- Internal service call → key = `sha256(normalized_input_json)`.
|
|
68
|
+
- User-initiated → key = `Idempotency-Key` header (RFC 8594-style).
|
|
69
|
+
|
|
70
|
+
Persist the key **before** side effects. Three states: `processing`, `processed`, `failed`. If the key already exists as `processing`/`processed`, return the stored response — do NOT re-apply the operation. Multi-table writes MUST run inside a single transaction; on rollback, also roll back the idempotency row.
|
|
71
|
+
|
|
72
|
+
Without this discipline: double-charge, duplicate fulfillment, duplicate email sends. It's the single most common production bug on payment / webhook paths.
|
|
73
|
+
|
|
74
|
+
## 4. N+1 query prevention
|
|
75
|
+
|
|
76
|
+
If you see a `for` loop with a DB call inside, it's wrong:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# WRONG — 1 query + N queries
|
|
80
|
+
for order in orders:
|
|
81
|
+
order.customer = db.get_customer(order.customer_id)
|
|
82
|
+
|
|
83
|
+
# RIGHT — 2 queries total
|
|
84
|
+
customer_ids = {o.customer_id for o in orders}
|
|
85
|
+
customers = db.get_customers_by_ids(customer_ids)
|
|
86
|
+
customer_by_id = {c.id: c for c in customers}
|
|
87
|
+
for order in orders:
|
|
88
|
+
order.customer = customer_by_id[order.customer_id]
|
|
89
|
+
|
|
90
|
+
# OR use ORM join/prefetch:
|
|
91
|
+
orders = Order.objects.select_related("customer") # Django
|
|
92
|
+
orders = db.query(Order).options(joinedload(Order.customer)) # SQLAlchemy
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Rule: before a loop over DB rows, materialize the join batch. ORMs have `select_related` / `prefetch_related` / `joinedload` / `Preload` — learn the one for your stack.
|
|
96
|
+
|
|
97
|
+
## 5. Indexes on every WHERE / JOIN / ORDER BY
|
|
98
|
+
|
|
99
|
+
If a column appears in `WHERE`, `JOIN`, or `ORDER BY` on a table expected to have > 10K rows, it MUST have an index. Verify with `EXPLAIN ANALYZE` on the real DB (not a fresh dev DB with 10 rows — fake stats lie).
|
|
100
|
+
|
|
101
|
+
For composite predicates, the index column order matters: most-selective-first for equality, then range. E.g., `WHERE user_id = ? AND created_at > ?` wants `(user_id, created_at)`, not `(created_at, user_id)`.
|
|
102
|
+
|
|
103
|
+
No "full table scan" on production-sized tables is acceptable. Index maintenance cost ≪ scan cost once data grows.
|
|
104
|
+
|
|
105
|
+
## 6. Pagination — never return all rows
|
|
106
|
+
|
|
107
|
+
Offset pagination is fine for small admin lists (LIMIT + OFFSET up to page 50). **Cursor-based pagination is required** when:
|
|
108
|
+
|
|
109
|
+
- Result set > 10K rows, or
|
|
110
|
+
- Deep pages are common (page 500+), or
|
|
111
|
+
- Inserts happen concurrently (offset drifts).
|
|
112
|
+
|
|
113
|
+
Cursor = opaque token encoding the last-seen sort key (e.g., base64-encoded `(created_at, id)` tuple). Return `next_cursor` in the response envelope; client echoes it back as `cursor=` in the next call.
|
|
114
|
+
|
|
115
|
+
Hard cap: MAX 100 rows per page. Client-supplied `limit` > 100 is rejected as `VALIDATION_ERROR`.
|
|
116
|
+
|
|
117
|
+
## 7. Transactions — atomicity for multi-step writes
|
|
118
|
+
|
|
119
|
+
Any operation that writes to ≥ 2 tables (or inserts to 1 and updates another) MUST run inside one transaction:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
with db.transaction():
|
|
123
|
+
idempotency_row = create_idempotency_row(key, status="processing")
|
|
124
|
+
order = create_order(payload)
|
|
125
|
+
inventory_reserve(order.items)
|
|
126
|
+
# If any step raises, ALL rollback — no partial state.
|
|
127
|
+
idempotency_row.status = "processed"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Transactions should be **short**. Never hold an open transaction while calling an external API (Stripe, email provider, S3). Pattern: (1) short DB tx to stage, (2) release connection, (3) external call, (4) short DB tx to commit. Long-held transactions exhaust connection pools under load.
|
|
131
|
+
|
|
132
|
+
## 8. Migrations — append-only, forward-safe
|
|
133
|
+
|
|
134
|
+
- **Append-only.** New tables / columns → new migration. Never edit a past migration that's been deployed.
|
|
135
|
+
- **Forward-safe.** Every migration must be applicable to a database where previous migrations ran. Destructive changes (drop column, rename) need a two-step dance: deploy code that doesn't use the column → migration drops it → deploy next release.
|
|
136
|
+
- **Idempotent.** `CREATE TABLE IF NOT EXISTS`, `CREATE INDEX IF NOT EXISTS`, `INSERT ... ON CONFLICT DO NOTHING`. Re-applying a migration on the same DB must be safe.
|
|
137
|
+
- **Reversible when practical.** Every migration file has a `down` / `revert` section. Data migrations are the exception — document why revert is manual.
|
|
138
|
+
- **No secrets in migrations.** API keys, JWTs, service-role credentials go via vault / dashboard / env. Document the manual step as a comment in the closest related migration.
|
|
139
|
+
|
|
140
|
+
## 9. Auth / permissions — default deny
|
|
141
|
+
|
|
142
|
+
- **Default deny.** No endpoint is public unless explicitly marked. Framework defaults (Django's `IsAuthenticated`, FastAPI's `Depends(get_current_user)`, Fiber's auth middleware) go at the router/app level, exemptions are the ones with decorators.
|
|
143
|
+
- **Identity vs. authorization.** "Who is this request?" is authentication (JWT / session). "Can they do X to Y?" is authorization (RBAC / row-level). Keep them in separate layers — a service method receives `user_id` and re-checks permissions, doesn't trust the controller.
|
|
144
|
+
- **Row-level security.** For multi-tenant data, every query that touches a tenant-scoped table MUST filter by tenant_id in WHERE. The DB layer (RLS in Postgres, filter in ORM manager) is the last line, not the only line.
|
|
145
|
+
- **Re-verify before destructive ops.** Email-change, password-reset, account-delete: require recent re-auth (timestamp on the session < 5 min old) regardless of existing login.
|
|
146
|
+
|
|
147
|
+
## 10. Logging — step-numbered, redacted, correlatable
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
log.info("🟣 STEP 1 — validating input", extra={"trace_id": trace_id, "user_id": user_id})
|
|
151
|
+
log.info("✅ STEP 1 OK — 3 items")
|
|
152
|
+
log.info("🟣 STEP 2 — charging gateway")
|
|
153
|
+
log.info("🔥 FATAL — gateway error %s", err_code, extra={"trace_id": trace_id})
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- Every log line carries `trace_id` (from request header or generated) so a support ticket can be traced end-to-end.
|
|
157
|
+
- **Redact PII and secrets.** Allow-list of fields to log; everything else masked. Never log raw request/response JSON on payment or auth paths.
|
|
158
|
+
- Emoji step markers (🟣 start, ✅ ok, ⚠️ warn, 🔥 fatal) make grep easier and reduce the temptation to write `print("got here")` debug code.
|
|
159
|
+
|
|
160
|
+
## 11. External calls — timeouts, retries, circuit breakers
|
|
161
|
+
|
|
162
|
+
Any call to a system you don't control (payment gateway, email provider, S3, third-party API):
|
|
163
|
+
|
|
164
|
+
- **Timeouts.** Hard timeout < your endpoint's budget. Never "default" timeout (which is often 30–60 s on HTTP libs). Pick a number and justify it.
|
|
165
|
+
- **Retries.** Only on idempotent operations. Exponential backoff with jitter. Cap at 3 attempts. Non-idempotent call failures propagate to the caller as `transient` with `retryable=true` so the caller decides.
|
|
166
|
+
- **Circuit breaker.** If > N failures in window W, trip the breaker and fast-fail for cool-down period C. Libraries: `pybreaker`, `hystrix`, `gobreaker`. Don't hand-roll.
|
|
167
|
+
- **Never hold DB connection during external call.** Release, call, reacquire.
|
|
168
|
+
|
|
169
|
+
## 12. Async jobs & background work
|
|
170
|
+
|
|
171
|
+
Any operation > 2 s (email, heavy compute, external aggregation, report generation) MUST be queued:
|
|
172
|
+
|
|
173
|
+
- **Don't make the user wait.** Return `202 Accepted` with a job id; client polls or subscribes for result.
|
|
174
|
+
- **Job contract:** a job is a pure function of its payload. Jobs MUST be idempotent (same payload replayed → same result).
|
|
175
|
+
- **Dead letter queue.** After N retries, job moves to DLQ with full context. Alert on DLQ size > 0.
|
|
176
|
+
- **Observability.** Per-job `trace_id` propagates from the enqueueing request; job logs and HTTP logs correlate.
|
|
177
|
+
|
|
178
|
+
## 13. Audit events — high-value actions only
|
|
179
|
+
|
|
180
|
+
Write an audit row for high-value actions: subscription create/change/cancel, payment success/failure, refund, admin override, security-sensitive config change. Schema:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
id | occurred_at | actor_type | actor_id | action | subject_type | subject_id | summary | correlation_id
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
NEVER put secrets / PII in the summary. Audit rows are read by support, compliance, and ops — they must be safe to render on a dashboard.
|
|
187
|
+
|
|
188
|
+
Anti-pattern: writing an audit row for every GET. Audit volume should correlate with state change, not traffic.
|
|
189
|
+
|
|
190
|
+
## 14. Request validation — at the edge, once
|
|
191
|
+
|
|
192
|
+
Validate once, at the HTTP boundary, using the framework's schema system (Pydantic, DRF Serializer, go-playground/validator, class-validator). Downstream services assume valid input.
|
|
193
|
+
|
|
194
|
+
Reject on failure with `VALIDATION_ERROR` + field-level details so the client can show per-field feedback. No generic "invalid input" — list every failing field.
|
|
195
|
+
|
|
196
|
+
## 15. Rate limiting — for public endpoints
|
|
197
|
+
|
|
198
|
+
Any public endpoint (no auth, or user-auth without workspace scope) needs rate limiting. Strategy:
|
|
199
|
+
|
|
200
|
+
- Per-IP for unauthenticated endpoints.
|
|
201
|
+
- Per-user-id for authenticated endpoints.
|
|
202
|
+
- Burst + sustained (e.g., 20 req / 1 min burst, 200 req / 1 hour sustained).
|
|
203
|
+
- Return `429 Too Many Requests` with `Retry-After` header.
|
|
204
|
+
|
|
205
|
+
Store counters in Redis or the framework's rate-limit module. Never in application memory (breaks under horizontal scale).
|
|
206
|
+
|
|
207
|
+
## 16. Pre-commit / PR checklist
|
|
208
|
+
|
|
209
|
+
Before opening a PR touching a backend file:
|
|
210
|
+
|
|
211
|
+
- [ ] No N+1 (greped for `for .* in .*: .*db\.` / `for .* in .*: .*\.objects\.` patterns)
|
|
212
|
+
- [ ] Response envelope consistent with project registry
|
|
213
|
+
- [ ] Idempotency for mutation endpoints
|
|
214
|
+
- [ ] Index verified via `EXPLAIN ANALYZE` on the matching table
|
|
215
|
+
- [ ] Transaction wraps multi-table writes
|
|
216
|
+
- [ ] Logs step-numbered, PII redacted, `trace_id` plumbed
|
|
217
|
+
- [ ] External calls have explicit timeouts
|
|
218
|
+
- [ ] Unit tests for service; integration test for the handler happy path + one error path
|
|
219
|
+
- [ ] Migration is append-only and idempotent (if touched)
|
|
220
|
+
|
|
221
|
+
## References
|
|
222
|
+
|
|
223
|
+
Stack-specific specializations extend this skill via `depends_on: [backend-fundamentals]` — your project's stack skill (python-django / python-fastapi / go-patterns / go-fiber) is present when that stack is installed.
|
|
224
|
+
|
|
225
|
+
## Tooling
|
|
226
|
+
|
|
227
|
+
Flag framework/ORM leakage into domain/service code (keep the core framework-free):
|
|
228
|
+
`python3 scripts/check_layering.py src/backend/services/*.py`
|
|
229
|
+
|
|
230
|
+
## See also
|
|
231
|
+
|
|
232
|
+
- [references/backend-patterns.md](references/backend-patterns.md) — layering, idempotency, errors, N+1, migrations.
|
|
233
|
+
- [assets/backend-checklist.md](assets/backend-checklist.md) — the review gate.
|
|
234
|
+
- [hexagonal-architecture](../hexagonal-architecture/SKILL.md) · [api-design](../api-design/SKILL.md) · [sql-authoring](../sql-authoring/SKILL.md).
|
|
235
|
+
|
|
236
|
+
Universal principles from [clean-code](../clean-code/SKILL.md) still apply — this skill does not relax any of them.
|
|
237
|
+
|
|
238
|
+
Cross-service code placement: promote a helper reused by a second service into `src/shared/<lang>/`, and route cross-language types through `src/shared/contracts/` only — see [clean-code](../clean-code/SKILL.md) § 7 and the `docs/engineering/project-anatomy.md` SSOT.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<!-- domain:BACKEND | layer:asset | ssot:false | updated:2026-06-04 -->
|
|
2
|
+
# Backend Review Checklist
|
|
3
|
+
|
|
4
|
+
Run when writing or reviewing server-side code.
|
|
5
|
+
|
|
6
|
+
## Layering
|
|
7
|
+
- [ ] Handler is thin: parse/validate → call service → format response.
|
|
8
|
+
- [ ] Service holds the business rules, framework-free (no HTTP/request objects).
|
|
9
|
+
- [ ] Repository is the only place with SQL/ORM.
|
|
10
|
+
- [ ] `python3 scripts/check_layering.py <service/domain files>` → `clean`.
|
|
11
|
+
|
|
12
|
+
## Correctness
|
|
13
|
+
- [ ] State-changing operations are idempotent (key/upsert); webhooks tolerate duplicates.
|
|
14
|
+
- [ ] Errors return one consistent envelope + correct status; no stack traces leaked.
|
|
15
|
+
- [ ] Input validated at the boundary; output shape matches the contract.
|
|
16
|
+
|
|
17
|
+
## Scale
|
|
18
|
+
- [ ] No N+1 (batched/joined); every list endpoint paginated.
|
|
19
|
+
- [ ] Queries are index-backed; assume the table grows 1000×.
|
|
20
|
+
- [ ] Slow/retryable work offloaded to a queue, not the request thread.
|
|
21
|
+
|
|
22
|
+
## Data
|
|
23
|
+
- [ ] Migrations backward-compatible (expand→contract); no drop the live code reads.
|
|
24
|
+
- [ ] No PII/secrets in logs (ids/redaction).
|
|
25
|
+
|
|
26
|
+
## Verify
|
|
27
|
+
- [ ] Matrix-targeted tests for what changed (test-discipline), error paths covered.
|