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,381 @@
|
|
|
1
|
+
# Error Envelope — RFC 9457 Problem Details
|
|
2
|
+
|
|
3
|
+
The contract for every non-2xx response. Updated to RFC 9457 (March 2024, replaces RFC 7807). Used by the project's Go backend, FastAPI AI adapter, and surfaces straight into the React Native client's error handling.
|
|
4
|
+
|
|
5
|
+
## The Envelope
|
|
6
|
+
|
|
7
|
+
```http
|
|
8
|
+
HTTP/1.1 422 Unprocessable Entity
|
|
9
|
+
Content-Type: application/problem+json
|
|
10
|
+
Content-Language: en
|
|
11
|
+
|
|
12
|
+
{
|
|
13
|
+
"type": "https://api.app.com/problems/validation-failed",
|
|
14
|
+
"title": "Validation failed",
|
|
15
|
+
"status": 422,
|
|
16
|
+
"detail": "The 'email' field must be a valid email address.",
|
|
17
|
+
"instance": "/users",
|
|
18
|
+
"code": "validation_failed",
|
|
19
|
+
"errors": [
|
|
20
|
+
{
|
|
21
|
+
"field": "email",
|
|
22
|
+
"code": "invalid_email",
|
|
23
|
+
"message": "must contain '@' and a domain"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"field": "age",
|
|
27
|
+
"code": "out_of_range",
|
|
28
|
+
"message": "must be between 13 and 120"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"request_id": "req_8h2k4n9d3p7q",
|
|
32
|
+
"documentation_url": "https://docs.app.com/errors/validation-failed"
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Field Definitions
|
|
37
|
+
|
|
38
|
+
| Field | Required | Stable across calls? | Description |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `type` | yes | yes (per error class) | URI identifying the problem type. Treat as primary key. |
|
|
41
|
+
| `title` | yes | yes (per type) | Short human description. Frozen for a given `type`. |
|
|
42
|
+
| `status` | yes | yes (per type) | The HTTP status, repeated in body for client convenience. |
|
|
43
|
+
| `detail` | no | no (varies per occurrence) | Specific human explanation. Safe to render to users. |
|
|
44
|
+
| `instance` | no | no | URI of the specific occurrence (typically the request path). |
|
|
45
|
+
| `code` | yes (project convention) | yes (per type) | Short machine token. Snake_case. Stable across versions. |
|
|
46
|
+
| `errors[]` | conditional | structure stable | Field-level validation breakdown. Required for 422 validation failures. |
|
|
47
|
+
| `request_id` | yes (project convention) | no | Correlation id; matches `X-Request-Id` header. |
|
|
48
|
+
| `documentation_url` | no | yes | Optional link to docs page for this error class. |
|
|
49
|
+
|
|
50
|
+
### `type` URI Convention
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
https://api.app.com/problems/<problem-slug>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The URI does NOT need to dereference (RFC 9457 explicitly allows non-resolving URIs). But if you do publish docs there, use `documentation_url` to point to them so clients can deep-link without ambiguity.
|
|
57
|
+
|
|
58
|
+
### `code` vs `type` — Why Both?
|
|
59
|
+
|
|
60
|
+
- `type` is the wire format for machines that route on URLs / categorize problems.
|
|
61
|
+
- `code` is the project's snake_case shorthand. Easier to switch on in client code:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
switch (error.code) {
|
|
65
|
+
case 'insufficient_funds': return showTopUpFlow();
|
|
66
|
+
case 'rate_limited': return scheduleRetry(error.retry_after);
|
|
67
|
+
case 'validation_failed': return highlightFields(error.errors);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Pick `code` first for client logic; `type` is the formal identifier.
|
|
72
|
+
|
|
73
|
+
## Error Catalogue
|
|
74
|
+
|
|
75
|
+
Maintain a **single source of truth** of error codes per service. New errors require a PR review like any other contract change.
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
# docs/errors/catalogue.yaml — checked into the repo
|
|
79
|
+
errors:
|
|
80
|
+
- code: validation_failed
|
|
81
|
+
type: https://api.app.com/problems/validation-failed
|
|
82
|
+
title: Validation failed
|
|
83
|
+
status: 422
|
|
84
|
+
notes: Use when request is well-formed but business rules reject it.
|
|
85
|
+
|
|
86
|
+
- code: insufficient_funds
|
|
87
|
+
type: https://api.app.com/problems/insufficient-funds
|
|
88
|
+
title: Insufficient funds
|
|
89
|
+
status: 402
|
|
90
|
+
notes: Account balance below required amount.
|
|
91
|
+
|
|
92
|
+
- code: rate_limited
|
|
93
|
+
type: https://api.app.com/problems/rate-limited
|
|
94
|
+
title: Too many requests
|
|
95
|
+
status: 429
|
|
96
|
+
extra_fields:
|
|
97
|
+
- retry_after_seconds
|
|
98
|
+
notes: Always include retry_after_seconds and Retry-After header.
|
|
99
|
+
|
|
100
|
+
- code: unauthenticated
|
|
101
|
+
type: https://api.app.com/problems/unauthenticated
|
|
102
|
+
title: Authentication required
|
|
103
|
+
status: 401
|
|
104
|
+
|
|
105
|
+
- code: forbidden
|
|
106
|
+
type: https://api.app.com/problems/forbidden
|
|
107
|
+
title: Access denied
|
|
108
|
+
status: 403
|
|
109
|
+
|
|
110
|
+
- code: not_found
|
|
111
|
+
type: https://api.app.com/problems/not-found
|
|
112
|
+
title: Resource not found
|
|
113
|
+
status: 404
|
|
114
|
+
|
|
115
|
+
- code: conflict
|
|
116
|
+
type: https://api.app.com/problems/conflict
|
|
117
|
+
title: Conflict with current state
|
|
118
|
+
status: 409
|
|
119
|
+
notes: Lost updates, duplicate creates, state-machine violations.
|
|
120
|
+
|
|
121
|
+
- code: idempotency_key_collision
|
|
122
|
+
type: https://api.app.com/problems/idempotency-key-collision
|
|
123
|
+
title: Idempotency key reused with different request
|
|
124
|
+
status: 409
|
|
125
|
+
notes: Same key, different body → reject not replay.
|
|
126
|
+
|
|
127
|
+
- code: dependency_unavailable
|
|
128
|
+
type: https://api.app.com/problems/dependency-unavailable
|
|
129
|
+
title: Upstream service unavailable
|
|
130
|
+
status: 503
|
|
131
|
+
extra_fields:
|
|
132
|
+
- retry_after_seconds
|
|
133
|
+
- dependency_name
|
|
134
|
+
|
|
135
|
+
- code: internal_error
|
|
136
|
+
type: https://api.app.com/problems/internal-error
|
|
137
|
+
title: Unexpected server error
|
|
138
|
+
status: 500
|
|
139
|
+
notes: Last-resort. detail must NOT leak stack/SQL/path info.
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
CI rule: any 4xx/5xx response in production logs whose `code` is not in the catalogue → fail the build / page on-call. Forces the catalogue to stay in sync with reality.
|
|
143
|
+
|
|
144
|
+
## Domain Error → HTTP Status Mapping
|
|
145
|
+
|
|
146
|
+
The hexagonal application layer raises domain errors; the inbound HTTP adapter maps them. Centralize the mapping in one helper.
|
|
147
|
+
|
|
148
|
+
```go
|
|
149
|
+
// pkg/apperr/from_domain.go
|
|
150
|
+
package apperr
|
|
151
|
+
|
|
152
|
+
import (
|
|
153
|
+
"errors"
|
|
154
|
+
|
|
155
|
+
"github.com/gofiber/fiber/v3"
|
|
156
|
+
"myapp/internal/domain/order"
|
|
157
|
+
"myapp/internal/domain/user"
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
func FromDomainError(c fiber.Ctx, err error) error {
|
|
161
|
+
var (
|
|
162
|
+
notFoundErr *user.NotFoundError
|
|
163
|
+
inactiveErr *user.InactiveError
|
|
164
|
+
invalidStateErr *order.InvalidStateError
|
|
165
|
+
balanceErr *order.InsufficientBalanceError
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
switch {
|
|
169
|
+
case errors.As(err, ¬FoundErr):
|
|
170
|
+
return Problem(c, 404, "not_found", err.Error())
|
|
171
|
+
case errors.As(err, &inactiveErr):
|
|
172
|
+
return Problem(c, 403, "forbidden", "account is inactive")
|
|
173
|
+
case errors.As(err, &invalidStateErr):
|
|
174
|
+
return Problem(c, 409, "conflict", err.Error())
|
|
175
|
+
case errors.As(err, &balanceErr):
|
|
176
|
+
return Problem(c, 402, "insufficient_funds", err.Error())
|
|
177
|
+
default:
|
|
178
|
+
// Unknown domain error → log full, return generic to client.
|
|
179
|
+
c.Locals("internal_error", err)
|
|
180
|
+
return Problem(c, 500, "internal_error", "unexpected error")
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
# src/ai_adapter/delivery/http/error_handlers.py
|
|
187
|
+
from fastapi import FastAPI, Request
|
|
188
|
+
from fastapi.responses import JSONResponse
|
|
189
|
+
|
|
190
|
+
from ai_adapter.application.usecase.send_message import (
|
|
191
|
+
ConversationNotFound,
|
|
192
|
+
MessageTooLong,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def install(app: FastAPI) -> None:
|
|
197
|
+
@app.exception_handler(ConversationNotFound)
|
|
198
|
+
async def conv_not_found(request: Request, exc: ConversationNotFound):
|
|
199
|
+
return _problem(request, 404, "conversation_not_found", str(exc))
|
|
200
|
+
|
|
201
|
+
@app.exception_handler(MessageTooLong)
|
|
202
|
+
async def msg_too_long(request: Request, exc: MessageTooLong):
|
|
203
|
+
return _problem(request, 422, "validation_failed", str(exc),
|
|
204
|
+
errors=[{"field": "user_text", "code": "too_long",
|
|
205
|
+
"message": str(exc)}])
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _problem(request: Request, status: int, code: str, detail: str, **extra) -> JSONResponse:
|
|
209
|
+
body = {
|
|
210
|
+
"type": f"https://api.app.com/problems/{code.replace('_', '-')}",
|
|
211
|
+
"title": _TITLE_BY_CODE[code],
|
|
212
|
+
"status": status,
|
|
213
|
+
"detail": detail,
|
|
214
|
+
"instance": str(request.url.path),
|
|
215
|
+
"code": code,
|
|
216
|
+
"request_id": request.headers.get("X-Request-Id", ""),
|
|
217
|
+
**extra,
|
|
218
|
+
}
|
|
219
|
+
return JSONResponse(
|
|
220
|
+
body,
|
|
221
|
+
status_code=status,
|
|
222
|
+
headers={"Content-Type": "application/problem+json"},
|
|
223
|
+
)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Validation Errors — `errors[]` Shape
|
|
227
|
+
|
|
228
|
+
For 422 (and sometimes 400) where multiple field problems exist:
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"type": "https://api.app.com/problems/validation-failed",
|
|
233
|
+
"title": "Validation failed",
|
|
234
|
+
"status": 422,
|
|
235
|
+
"code": "validation_failed",
|
|
236
|
+
"detail": "2 fields failed validation",
|
|
237
|
+
"errors": [
|
|
238
|
+
{
|
|
239
|
+
"field": "items[0].quantity",
|
|
240
|
+
"code": "min_value",
|
|
241
|
+
"message": "must be at least 1",
|
|
242
|
+
"constraint": { "min": 1 }
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"field": "promo_code",
|
|
246
|
+
"code": "expired",
|
|
247
|
+
"message": "promo code WELCOME10 expired on 2026-04-01"
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Per-error fields:
|
|
254
|
+
|
|
255
|
+
- `field` — JSON pointer or dotted path. Arrays use `[N]`.
|
|
256
|
+
- `code` — short token, e.g. `required`, `min_value`, `max_length`, `invalid_format`, `not_in_enum`.
|
|
257
|
+
- `message` — human-readable, safe to render.
|
|
258
|
+
- `constraint` (optional) — machine-readable bounds for client highlighting.
|
|
259
|
+
|
|
260
|
+
Always include the FULL list, not just the first failure. UX wants to highlight all bad fields at once.
|
|
261
|
+
|
|
262
|
+
## Status Code Decision Tree (for raisers)
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
Did the request fail before hitting business logic?
|
|
266
|
+
├─ Yes → 4xx
|
|
267
|
+
│ ├─ Auth missing → 401
|
|
268
|
+
│ ├─ Auth present but no permission → 403
|
|
269
|
+
│ ├─ Resource doesn't exist (or hide existence) → 404
|
|
270
|
+
│ ├─ HTTP method wrong for URL → 405
|
|
271
|
+
│ ├─ Body unparseable / type wrong → 400
|
|
272
|
+
│ └─ Body parsed but semantically invalid → 422
|
|
273
|
+
│
|
|
274
|
+
└─ No, it failed during business logic
|
|
275
|
+
├─ State conflict (lost update, duplicate) → 409
|
|
276
|
+
├─ Insufficient resource (balance, quota) → 402 (payment) | 403 (perm) | 422 (rule)
|
|
277
|
+
├─ Concurrent modification (ETag mismatch) → 412
|
|
278
|
+
├─ Rate limit hit → 429 (with Retry-After)
|
|
279
|
+
├─ Upstream service down → 502/503/504
|
|
280
|
+
└─ Truly unexpected → 500
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## What NEVER Goes in `detail`
|
|
284
|
+
|
|
285
|
+
- Stack traces.
|
|
286
|
+
- File paths (`/var/app/src/handlers/foo.py:142`).
|
|
287
|
+
- SQL fragments.
|
|
288
|
+
- Internal table or column names.
|
|
289
|
+
- Class names of internal exceptions.
|
|
290
|
+
- Information that would help an attacker (which user exists, which permission is missing).
|
|
291
|
+
|
|
292
|
+
The right way: log the full error server-side with `request_id` + payload, then return generic `detail` to the client. Support reads logs by `request_id`.
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
# CORRECT
|
|
296
|
+
logger.error("DB integrity error on user create", extra={
|
|
297
|
+
"request_id": req_id, "email_hash": h(email), "error": str(exc),
|
|
298
|
+
})
|
|
299
|
+
raise ConflictError("an account with this email already exists")
|
|
300
|
+
|
|
301
|
+
# WRONG
|
|
302
|
+
return JSONResponse({"detail": str(exc)}, status_code=409)
|
|
303
|
+
# detail = 'duplicate key value violates unique constraint "users_email_key"'
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## RN Client Side — Consuming the Envelope
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
// src/infrastructure/http/apiClient.ts
|
|
310
|
+
import axios, { AxiosError } from 'axios';
|
|
311
|
+
|
|
312
|
+
export interface ApiProblem {
|
|
313
|
+
type: string;
|
|
314
|
+
title: string;
|
|
315
|
+
status: number;
|
|
316
|
+
detail?: string;
|
|
317
|
+
code: string;
|
|
318
|
+
errors?: Array<{ field: string; code: string; message: string }>;
|
|
319
|
+
request_id?: string;
|
|
320
|
+
retry_after_seconds?: number;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export class ApiError extends Error {
|
|
324
|
+
constructor(public problem: ApiProblem) {
|
|
325
|
+
super(problem.title);
|
|
326
|
+
this.name = 'ApiError';
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export const api = axios.create({ baseURL: 'https://api.app.com' });
|
|
331
|
+
|
|
332
|
+
api.interceptors.response.use(
|
|
333
|
+
(res) => res,
|
|
334
|
+
(err: AxiosError<ApiProblem>) => {
|
|
335
|
+
if (err.response?.data?.code) {
|
|
336
|
+
return Promise.reject(new ApiError(err.response.data));
|
|
337
|
+
}
|
|
338
|
+
// Network error, timeout, non-conforming server, etc.
|
|
339
|
+
return Promise.reject(new ApiError({
|
|
340
|
+
type: 'https://api.app.com/problems/network',
|
|
341
|
+
title: 'Network error',
|
|
342
|
+
status: 0,
|
|
343
|
+
code: 'network_error',
|
|
344
|
+
detail: err.message,
|
|
345
|
+
}));
|
|
346
|
+
},
|
|
347
|
+
);
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Then in screens / use cases, switch on `error.problem.code`:
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
try {
|
|
354
|
+
await placeOrder.execute(input);
|
|
355
|
+
} catch (e) {
|
|
356
|
+
if (e instanceof ApiError) {
|
|
357
|
+
switch (e.problem.code) {
|
|
358
|
+
case 'insufficient_funds': return navigation.navigate('TopUp');
|
|
359
|
+
case 'rate_limited': return showToast('Too fast, retrying…');
|
|
360
|
+
case 'validation_failed': return highlightFields(e.problem.errors);
|
|
361
|
+
default: return showToast(e.problem.title);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
throw e;
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## CI Enforcement
|
|
369
|
+
|
|
370
|
+
Three checks worth running:
|
|
371
|
+
|
|
372
|
+
1. **Catalogue completeness**: scan source for `code: "..."` literals; assert every one is in the YAML catalogue.
|
|
373
|
+
2. **Envelope shape**: every error response in integration tests is asserted against the JSON Schema for ProblemDetails.
|
|
374
|
+
3. **No leaked detail**: regex any error response body for SQL keywords (`SELECT`, `INSERT`, `constraint`), file paths (`/var/`, `/app/`), Python tracebacks (`Traceback`, `File "/`).
|
|
375
|
+
|
|
376
|
+
## References
|
|
377
|
+
|
|
378
|
+
- [RFC 9457 — Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457.html) (2024).
|
|
379
|
+
- [RFC 9745 — The Deprecation HTTP Header Field](https://www.rfc-editor.org/rfc/rfc9745.html) (2024).
|
|
380
|
+
- [JSON:API errors spec](https://jsonapi.org/format/#errors) — alternative envelope shape; useful comparison.
|
|
381
|
+
- Stripe Errors guide — <https://stripe.com/docs/api/errors>.
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# Idempotency + Pagination — Implementation Patterns
|
|
2
|
+
|
|
3
|
+
The two patterns most APIs get wrong. Both are simple in theory; both fail in subtle ways at scale.
|
|
4
|
+
|
|
5
|
+
## Idempotency
|
|
6
|
+
|
|
7
|
+
### Why It's Mandatory
|
|
8
|
+
|
|
9
|
+
Networks drop responses. Mobile clients on bad LTE retry. Load balancers fail over mid-request. Without an idempotency contract, a single user tap can become two charges.
|
|
10
|
+
|
|
11
|
+
The fix is a small protocol the client and server both follow:
|
|
12
|
+
|
|
13
|
+
1. Client generates a random key per logical operation.
|
|
14
|
+
2. Client sends the key on every retry of that operation.
|
|
15
|
+
3. Server stores `(key, response)` after the first successful execution.
|
|
16
|
+
4. On any retry with the same key, server returns the stored response without re-executing the side effect.
|
|
17
|
+
|
|
18
|
+
### The Contract
|
|
19
|
+
|
|
20
|
+
```http
|
|
21
|
+
POST /payments
|
|
22
|
+
Idempotency-Key: 8e0f7b1d-2a44-4c7f-9b2e-1c5d6e7f8a9b
|
|
23
|
+
Content-Type: application/json
|
|
24
|
+
|
|
25
|
+
{ "amount": 4200, "currency": "USD", "source": "card_xyz" }
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Server responses:
|
|
29
|
+
|
|
30
|
+
| Scenario | Status | Header |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| First call, success | 201 | normal |
|
|
33
|
+
| First call, error | 4xx/5xx | normal |
|
|
34
|
+
| Retry, original was success | 201 | `X-Idempotent-Replay: true` |
|
|
35
|
+
| Retry, original was 5xx | re-execute | (stored 5xx is NOT a final result) |
|
|
36
|
+
| Retry, different body, same key | 409 | `code: idempotency_key_collision` |
|
|
37
|
+
|
|
38
|
+
**Key rules**:
|
|
39
|
+
|
|
40
|
+
- Only store FINAL outcomes (2xx, 4xx). 5xx and timeouts → safe to re-execute on retry.
|
|
41
|
+
- Compare body hash on retry — if body differs, refuse with 409 (don't silently return old response for new request).
|
|
42
|
+
- TTL the stored entry. 24 hours is industry default. Long enough for legitimate retries, short enough to bound storage.
|
|
43
|
+
- Return the SAME response on replay — same status, same headers (esp `Location`), same body.
|
|
44
|
+
|
|
45
|
+
### Storage Schema (PostgreSQL)
|
|
46
|
+
|
|
47
|
+
```sql
|
|
48
|
+
CREATE TABLE idempotency_keys (
|
|
49
|
+
key TEXT PRIMARY KEY,
|
|
50
|
+
user_id TEXT NOT NULL, -- scope to caller
|
|
51
|
+
request_method TEXT NOT NULL,
|
|
52
|
+
request_path TEXT NOT NULL,
|
|
53
|
+
request_body_hash TEXT NOT NULL, -- SHA-256 of canonicalized body
|
|
54
|
+
response_status INT NOT NULL,
|
|
55
|
+
response_headers JSONB NOT NULL,
|
|
56
|
+
response_body BYTEA NOT NULL,
|
|
57
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
58
|
+
completed_at TIMESTAMPTZ, -- NULL while in-flight
|
|
59
|
+
locked_until TIMESTAMPTZ -- in-flight lock
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
CREATE INDEX idx_idempotency_keys_user_path
|
|
63
|
+
ON idempotency_keys (user_id, request_path);
|
|
64
|
+
CREATE INDEX idx_idempotency_keys_created
|
|
65
|
+
ON idempotency_keys (created_at);
|
|
66
|
+
|
|
67
|
+
-- Sweep job (cron, every hour) — drop entries older than 24h.
|
|
68
|
+
DELETE FROM idempotency_keys WHERE created_at < NOW() - INTERVAL '24 hours';
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### In-Flight Collision
|
|
72
|
+
|
|
73
|
+
If two requests with the same key arrive simultaneously (genuinely; client retries the request before the first response):
|
|
74
|
+
|
|
75
|
+
1. First request acquires the row lock (`INSERT … ON CONFLICT DO NOTHING`).
|
|
76
|
+
2. Second request sees the row exists with `completed_at IS NULL`.
|
|
77
|
+
3. Second request waits up to N seconds for `completed_at` to be set.
|
|
78
|
+
4. If filled in time → return that response.
|
|
79
|
+
5. If timeout → return 409 `idempotency_key_in_flight` (client retries shortly).
|
|
80
|
+
|
|
81
|
+
```go
|
|
82
|
+
// Pseudocode for the lock dance:
|
|
83
|
+
func (s *Store) Begin(ctx context.Context, key, userID, method, path, bodyHash string) (existing *Stored, acquired bool, err error) {
|
|
84
|
+
// Try to insert a placeholder.
|
|
85
|
+
res, err := s.db.Exec(ctx, `
|
|
86
|
+
INSERT INTO idempotency_keys (key, user_id, request_method, request_path,
|
|
87
|
+
request_body_hash, response_status, response_headers,
|
|
88
|
+
response_body, locked_until)
|
|
89
|
+
VALUES ($1, $2, $3, $4, $5, 0, '{}', '\x00', NOW() + INTERVAL '30 seconds')
|
|
90
|
+
ON CONFLICT (key) DO NOTHING
|
|
91
|
+
`, key, userID, method, path, bodyHash)
|
|
92
|
+
if err != nil { return nil, false, err }
|
|
93
|
+
if res.RowsAffected() == 1 {
|
|
94
|
+
return nil, true, nil // We acquired the lock; caller proceeds to execute.
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Someone else owns the key. Read what they have.
|
|
98
|
+
row := s.db.QueryRow(ctx, `
|
|
99
|
+
SELECT request_body_hash, completed_at, response_status,
|
|
100
|
+
response_headers, response_body
|
|
101
|
+
FROM idempotency_keys WHERE key = $1
|
|
102
|
+
`, key)
|
|
103
|
+
var stored Stored
|
|
104
|
+
var hash string
|
|
105
|
+
var completedAt sql.NullTime
|
|
106
|
+
if err := row.Scan(&hash, &completedAt, &stored.Status,
|
|
107
|
+
&stored.Headers, &stored.Body); err != nil {
|
|
108
|
+
return nil, false, err
|
|
109
|
+
}
|
|
110
|
+
if hash != bodyHash {
|
|
111
|
+
return nil, false, ErrKeyCollision
|
|
112
|
+
}
|
|
113
|
+
if !completedAt.Valid {
|
|
114
|
+
return nil, false, ErrInFlight
|
|
115
|
+
}
|
|
116
|
+
return &stored, false, nil
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Scoping Keys
|
|
121
|
+
|
|
122
|
+
Idempotency keys are scoped to `(user_id, method, path)` — NOT global. Prevents:
|
|
123
|
+
|
|
124
|
+
- A malicious caller from "claiming" a key another user is about to send.
|
|
125
|
+
- The same key being legitimately reused for `POST /orders` and `POST /payments` by different consumers.
|
|
126
|
+
|
|
127
|
+
## Pagination — Cursor Pattern (Default)
|
|
128
|
+
|
|
129
|
+
### The Contract
|
|
130
|
+
|
|
131
|
+
Request:
|
|
132
|
+
|
|
133
|
+
```http
|
|
134
|
+
GET /orders?limit=20&cursor=eyJpZCI6Im9yZF9hYmMiLCJjcmVhdGVkX2F0IjoiMjAyNi0wNC0yNlQxNDozMDowMFoifQ
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Response:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"data": [
|
|
142
|
+
{ "id": "ord_b1", "created_at": "2026-04-26T14:25:00Z", ... },
|
|
143
|
+
{ "id": "ord_b2", "created_at": "2026-04-26T14:24:00Z", ... },
|
|
144
|
+
...
|
|
145
|
+
],
|
|
146
|
+
"page": {
|
|
147
|
+
"next_cursor": "eyJpZCI6Im9yZF9iMjAiLCJjcmVhdGVkX2F0IjoiMjAyNi0wNC0yNlQxNDoxMDowMFoifQ",
|
|
148
|
+
"has_more": true
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Rules:
|
|
154
|
+
|
|
155
|
+
- `limit`: integer, default 20, max 100. Reject larger values.
|
|
156
|
+
- `cursor`: opaque base64 of internal state. Do NOT promise a parseable shape; it's a black box for clients.
|
|
157
|
+
- `next_cursor: null` when no more results.
|
|
158
|
+
- `has_more: false` is authoritative; clients should stop iterating.
|
|
159
|
+
|
|
160
|
+
### Cursor Encoding
|
|
161
|
+
|
|
162
|
+
The cursor encodes the SORT KEY of the last row returned. For "newest first":
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
import base64
|
|
166
|
+
import json
|
|
167
|
+
from datetime import datetime
|
|
168
|
+
|
|
169
|
+
def encode_cursor(last_id: str, last_created_at: datetime) -> str:
|
|
170
|
+
payload = json.dumps({
|
|
171
|
+
"id": last_id,
|
|
172
|
+
"created_at": last_created_at.isoformat() + "Z",
|
|
173
|
+
}, separators=(",", ":"))
|
|
174
|
+
return base64.urlsafe_b64encode(payload.encode()).decode()
|
|
175
|
+
|
|
176
|
+
def decode_cursor(cursor: str | None) -> dict | None:
|
|
177
|
+
if not cursor:
|
|
178
|
+
return None
|
|
179
|
+
try:
|
|
180
|
+
data = json.loads(base64.urlsafe_b64decode(cursor.encode()))
|
|
181
|
+
except (ValueError, json.JSONDecodeError):
|
|
182
|
+
raise ValueError("invalid cursor")
|
|
183
|
+
if "id" not in data or "created_at" not in data:
|
|
184
|
+
raise ValueError("invalid cursor")
|
|
185
|
+
return data
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### The SQL — Tuple Comparison Pattern
|
|
189
|
+
|
|
190
|
+
For "ORDER BY created_at DESC, id DESC" (stable sort even when timestamps tie):
|
|
191
|
+
|
|
192
|
+
```sql
|
|
193
|
+
SELECT id, created_at, total, status
|
|
194
|
+
FROM orders
|
|
195
|
+
WHERE user_id = $1
|
|
196
|
+
AND ($2::TIMESTAMPTZ IS NULL OR (created_at, id) < ($2::TIMESTAMPTZ, $3::TEXT))
|
|
197
|
+
ORDER BY created_at DESC, id DESC
|
|
198
|
+
LIMIT $4 + 1; -- fetch one extra to detect has_more
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Wrapper code:
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
async def list_orders(
|
|
205
|
+
user_id: str,
|
|
206
|
+
limit: int = 20,
|
|
207
|
+
cursor: str | None = None,
|
|
208
|
+
) -> tuple[list[Order], str | None]:
|
|
209
|
+
cursor_data = decode_cursor(cursor)
|
|
210
|
+
after_created = cursor_data["created_at"] if cursor_data else None
|
|
211
|
+
after_id = cursor_data["id"] if cursor_data else None
|
|
212
|
+
|
|
213
|
+
rows = await db.fetch(
|
|
214
|
+
"""
|
|
215
|
+
SELECT id, created_at, total, status
|
|
216
|
+
FROM orders
|
|
217
|
+
WHERE user_id = $1
|
|
218
|
+
AND ($2::TIMESTAMPTZ IS NULL OR (created_at, id) < ($2, $3))
|
|
219
|
+
ORDER BY created_at DESC, id DESC
|
|
220
|
+
LIMIT $4
|
|
221
|
+
""",
|
|
222
|
+
user_id, after_created, after_id, limit + 1,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
has_more = len(rows) > limit
|
|
226
|
+
page = rows[:limit]
|
|
227
|
+
next_cursor = (
|
|
228
|
+
encode_cursor(page[-1]["id"], page[-1]["created_at"])
|
|
229
|
+
if has_more and page else None
|
|
230
|
+
)
|
|
231
|
+
return [Order.from_row(r) for r in page], next_cursor
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Why Cursor Beats Offset
|
|
235
|
+
|
|
236
|
+
Offset (`?page=3&size=20`) suffers from:
|
|
237
|
+
|
|
238
|
+
1. **Race conditions**: items inserted between page 2 and 3 → duplicates or skips.
|
|
239
|
+
2. **Performance**: `OFFSET 50000` makes the DB skip 50000 rows every request.
|
|
240
|
+
3. **Page-jump unreliability**: page numbers shift as data changes.
|
|
241
|
+
|
|
242
|
+
Cursor is stable: each cursor encodes a precise position. Even if 1000 new rows arrive, your cursor still picks up exactly where you stopped.
|
|
243
|
+
|
|
244
|
+
### When Offset Is OK
|
|
245
|
+
|
|
246
|
+
Small (<10k row), fixed datasets where users genuinely want "go to page 7". Admin dashboards, audit log views with date filters that bound the set. Document the limit clearly.
|
|
247
|
+
|
|
248
|
+
```http
|
|
249
|
+
GET /admin/audit-events?page=7&size=50
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Backward Pagination
|
|
253
|
+
|
|
254
|
+
If you need both directions (rare in mobile lists, common in chat):
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"data": [...],
|
|
259
|
+
"page": {
|
|
260
|
+
"next_cursor": "eyJ...",
|
|
261
|
+
"prev_cursor": "eyJ...",
|
|
262
|
+
"has_more": true
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Implement with the same tuple-comparison trick but reversed sort, then re-reverse the result list before returning.
|
|
268
|
+
|
|
269
|
+
### Counts? No.
|
|
270
|
+
|
|
271
|
+
Resist the urge to return `total: 12345` on paginated endpoints. `SELECT COUNT(*)` against a large table is expensive and gets stale immediately. If you genuinely need a count, expose it as a separate endpoint with explicit caching (`/orders/count`, cached 60s).
|
|
272
|
+
|
|
273
|
+
If users want a sense of "how much is left", show "Loading more…" or "1–20 of many" instead of a precise count.
|
|
274
|
+
|
|
275
|
+
### Pagination Anti-Patterns
|
|
276
|
+
|
|
277
|
+
1. **No max limit** — `?limit=10000` ships 10k rows, OOMs the server.
|
|
278
|
+
2. **Cursor that's actually an offset** — defeats the purpose; race conditions return.
|
|
279
|
+
3. **Returning the last page as `cursor: null` and an empty `data`** — if there's nothing more, just say so on the prior page.
|
|
280
|
+
4. **Cursor that includes user-modifiable fields** — clients tamper, break sort, get duplicate or missing rows.
|
|
281
|
+
5. **Different pagination per endpoint** — pick cursor and use everywhere.
|
|
282
|
+
6. **GraphQL `first/after` confusion** — if using Relay-style, follow the spec exactly.
|
|
283
|
+
|
|
284
|
+
## Combined: Both at Once
|
|
285
|
+
|
|
286
|
+
A single mutating list operation (rare, but exists — bulk import) needs both:
|
|
287
|
+
|
|
288
|
+
```http
|
|
289
|
+
POST /imports/orders
|
|
290
|
+
Idempotency-Key: 8e0f7b1d-2a44-4c7f-9b2e-1c5d6e7f8a9b
|
|
291
|
+
Content-Type: application/json
|
|
292
|
+
|
|
293
|
+
{
|
|
294
|
+
"items": [...500 orders...],
|
|
295
|
+
"cursor_after_failure": null
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Server:
|
|
300
|
+
|
|
301
|
+
1. Idempotency check at the top.
|
|
302
|
+
2. Process items in chunks; if a chunk fails, return `cursor_after_failure: <token>` so client can resume from that point.
|
|
303
|
+
3. On idempotent retry, return the original outcome including any `cursor_after_failure`.
|
|
304
|
+
|
|
305
|
+
Most APIs don't need this complexity. But when you do, do it right.
|
|
306
|
+
|
|
307
|
+
## References
|
|
308
|
+
|
|
309
|
+
- Stripe API — Idempotent requests: <https://stripe.com/docs/api/idempotent_requests>
|
|
310
|
+
- Stripe API — Pagination: <https://stripe.com/docs/api/pagination>
|
|
311
|
+
- IETF draft — The Idempotency-Key HTTP Header Field: <https://datatracker.ietf.org/doc/draft-ietf-httpapi-idempotency-key-header/>
|
|
312
|
+
- Slack Engineering — "Evolving API Pagination at Slack" (still current): <https://slack.engineering/evolving-api-pagination-at-slack/>
|