oh-my-customcodex 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +327 -0
- package/dist/cli/index.js +32054 -0
- package/dist/index.js +5469 -0
- package/package.json +89 -0
- package/templates/.claude/agents/arch-documenter.md +38 -0
- package/templates/.claude/agents/arch-speckit-agent.md +66 -0
- package/templates/.claude/agents/be-django-expert.md +47 -0
- package/templates/.claude/agents/be-express-expert.md +31 -0
- package/templates/.claude/agents/be-fastapi-expert.md +45 -0
- package/templates/.claude/agents/be-go-backend-expert.md +45 -0
- package/templates/.claude/agents/be-nestjs-expert.md +29 -0
- package/templates/.claude/agents/be-springboot-expert.md +42 -0
- package/templates/.claude/agents/db-alembic-expert.md +73 -0
- package/templates/.claude/agents/db-postgres-expert.md +38 -0
- package/templates/.claude/agents/db-redis-expert.md +38 -0
- package/templates/.claude/agents/db-supabase-expert.md +37 -0
- package/templates/.claude/agents/de-airflow-expert.md +48 -0
- package/templates/.claude/agents/de-dbt-expert.md +36 -0
- package/templates/.claude/agents/de-kafka-expert.md +83 -0
- package/templates/.claude/agents/de-pipeline-expert.md +34 -0
- package/templates/.claude/agents/de-snowflake-expert.md +38 -0
- package/templates/.claude/agents/de-spark-expert.md +38 -0
- package/templates/.claude/agents/fe-design-expert.md +120 -0
- package/templates/.claude/agents/fe-flutter-agent.md +48 -0
- package/templates/.claude/agents/fe-svelte-agent.md +33 -0
- package/templates/.claude/agents/fe-vercel-agent.md +40 -0
- package/templates/.claude/agents/fe-vuejs-agent.md +34 -0
- package/templates/.claude/agents/infra-aws-expert.md +49 -0
- package/templates/.claude/agents/infra-docker-expert.md +49 -0
- package/templates/.claude/agents/lang-golang-expert.md +46 -0
- package/templates/.claude/agents/lang-java21-expert.md +42 -0
- package/templates/.claude/agents/lang-kotlin-expert.md +45 -0
- package/templates/.claude/agents/lang-python-expert.md +45 -0
- package/templates/.claude/agents/lang-rust-expert.md +45 -0
- package/templates/.claude/agents/lang-typescript-expert.md +45 -0
- package/templates/.claude/agents/mgr-claude-code-bible.md +62 -0
- package/templates/.claude/agents/mgr-creator.md +57 -0
- package/templates/.claude/agents/mgr-gitnerd.md +50 -0
- package/templates/.claude/agents/mgr-sauron.md +163 -0
- package/templates/.claude/agents/mgr-supplier.md +39 -0
- package/templates/.claude/agents/mgr-updater.md +40 -0
- package/templates/.claude/agents/qa-engineer.md +36 -0
- package/templates/.claude/agents/qa-planner.md +78 -0
- package/templates/.claude/agents/qa-writer.md +32 -0
- package/templates/.claude/agents/sec-codeql-expert.md +56 -0
- package/templates/.claude/agents/slack-cli-expert.md +98 -0
- package/templates/.claude/agents/souls/lang-golang-expert.soul.md +21 -0
- package/templates/.claude/agents/sys-memory-keeper.md +123 -0
- package/templates/.claude/agents/sys-naggy.md +76 -0
- package/templates/.claude/agents/tool-bun-expert.md +26 -0
- package/templates/.claude/agents/tool-npm-expert.md +31 -0
- package/templates/.claude/agents/tool-optimizer.md +37 -0
- package/templates/.claude/agents/wiki-curator.md +72 -0
- package/templates/.claude/config/required-plugins.json +30 -0
- package/templates/.claude/contexts/dev.md +20 -0
- package/templates/.claude/contexts/ecomode.md +110 -0
- package/templates/.claude/contexts/index.yaml +41 -0
- package/templates/.claude/contexts/research.md +28 -0
- package/templates/.claude/contexts/review.md +23 -0
- package/templates/.claude/hooks/hooks.json +533 -0
- package/templates/.claude/hooks/scripts/adaptive-harness-scan.sh +45 -0
- package/templates/.claude/hooks/scripts/agent-start-recorder.sh +40 -0
- package/templates/.claude/hooks/scripts/agent-teams-advisor.sh +76 -0
- package/templates/.claude/hooks/scripts/audit-log.sh +64 -0
- package/templates/.claude/hooks/scripts/auto-continue-guard.sh +33 -0
- package/templates/.claude/hooks/scripts/content-hash-validator.sh +75 -0
- package/templates/.claude/hooks/scripts/context-budget-advisor.sh +107 -0
- package/templates/.claude/hooks/scripts/cost-cap-advisor.sh +71 -0
- package/templates/.claude/hooks/scripts/cwd-change-detector.sh +36 -0
- package/templates/.claude/hooks/scripts/eval-core-batch-save.sh +46 -0
- package/templates/.claude/hooks/scripts/feedback-collector.sh +92 -0
- package/templates/.claude/hooks/scripts/file-change-validator.sh +26 -0
- package/templates/.claude/hooks/scripts/git-delegation-guard.sh +57 -0
- package/templates/.claude/hooks/scripts/model-escalation-advisor.sh +106 -0
- package/templates/.claude/hooks/scripts/omcodex-auto-update.sh +4 -0
- package/templates/.claude/hooks/scripts/omcustom-auto-update.sh +177 -0
- package/templates/.claude/hooks/scripts/rtk-intercept.sh +77 -0
- package/templates/.claude/hooks/scripts/rule-deletion-guard.sh +60 -0
- package/templates/.claude/hooks/scripts/schema-validator.sh +106 -0
- package/templates/.claude/hooks/scripts/secret-filter.sh +100 -0
- package/templates/.claude/hooks/scripts/session-autofix-prompt.sh +34 -0
- package/templates/.claude/hooks/scripts/session-autofix.sh +146 -0
- package/templates/.claude/hooks/scripts/session-env-check.sh +254 -0
- package/templates/.claude/hooks/scripts/skill-extractor-analyzer.sh +49 -0
- package/templates/.claude/hooks/scripts/stage-blocker.sh +16 -0
- package/templates/.claude/hooks/scripts/stale-todo-scanner.sh +91 -0
- package/templates/.claude/hooks/scripts/stall-detection-advisor.sh +112 -0
- package/templates/.claude/hooks/scripts/stop-console-audit.sh +46 -0
- package/templates/.claude/hooks/scripts/stuck-detector.sh +199 -0
- package/templates/.claude/hooks/scripts/task-outcome-recorder.sh +119 -0
- package/templates/.claude/hooks/scripts/task-state-precompact.sh +58 -0
- package/templates/.claude/hooks/scripts/user-prompt-preprocessor.sh +32 -0
- package/templates/.claude/hooks/skill-count-reminder.sh +34 -0
- package/templates/.claude/install-hooks.sh +100 -0
- package/templates/.claude/ontology/agents.yaml +546 -0
- package/templates/.claude/ontology/graphs/agent-skill.json +102 -0
- package/templates/.claude/ontology/graphs/full-graph.json +629 -0
- package/templates/.claude/ontology/graphs/routing.json +112 -0
- package/templates/.claude/ontology/graphs/skill-rule.json +78 -0
- package/templates/.claude/ontology/rules.yaml +251 -0
- package/templates/.claude/ontology/schema.yaml +144 -0
- package/templates/.claude/ontology/skills.yaml +575 -0
- package/templates/.claude/rules/MAY-optimization.md +42 -0
- package/templates/.claude/rules/MUST-agent-design.md +340 -0
- package/templates/.claude/rules/MUST-agent-identification.md +77 -0
- package/templates/.claude/rules/MUST-agent-teams.md +293 -0
- package/templates/.claude/rules/MUST-completion-verification.md +112 -0
- package/templates/.claude/rules/MUST-continuous-improvement.md +69 -0
- package/templates/.claude/rules/MUST-enforcement-policy.md +50 -0
- package/templates/.claude/rules/MUST-intent-transparency.md +74 -0
- package/templates/.claude/rules/MUST-language-policy.md +28 -0
- package/templates/.claude/rules/MUST-orchestrator-coordination.md +399 -0
- package/templates/.claude/rules/MUST-parallel-execution.md +184 -0
- package/templates/.claude/rules/MUST-permissions.md +32 -0
- package/templates/.claude/rules/MUST-safety.md +23 -0
- package/templates/.claude/rules/MUST-sync-verification.md +145 -0
- package/templates/.claude/rules/MUST-tool-identification.md +97 -0
- package/templates/.claude/rules/SHOULD-ecomode.md +123 -0
- package/templates/.claude/rules/SHOULD-error-handling.md +33 -0
- package/templates/.claude/rules/SHOULD-hud-statusline.md +51 -0
- package/templates/.claude/rules/SHOULD-interaction.md +77 -0
- package/templates/.claude/rules/SHOULD-memory-integration.md +371 -0
- package/templates/.claude/rules/SHOULD-ontology-rag-routing.md +49 -0
- package/templates/.claude/rules/SHOULD-wiki-sync.md +73 -0
- package/templates/.claude/rules/index.yaml +141 -0
- package/templates/.claude/schemas/tool-inputs.json +62 -0
- package/templates/.claude/skills/action-validator/SKILL.md +89 -0
- package/templates/.claude/skills/adaptive-harness/SKILL.md +335 -0
- package/templates/.claude/skills/adversarial-review/SKILL.md +80 -0
- package/templates/.claude/skills/agora/SKILL.md +194 -0
- package/templates/.claude/skills/airflow-best-practices/SKILL.md +94 -0
- package/templates/.claude/skills/alembic-best-practices/SKILL.md +295 -0
- package/templates/.claude/skills/ambiguity-gate/SKILL.md +94 -0
- package/templates/.claude/skills/analysis/SKILL.md +223 -0
- package/templates/.claude/skills/audit-agents/SKILL.md +118 -0
- package/templates/.claude/skills/aws-best-practices/SKILL.md +281 -0
- package/templates/.claude/skills/claude-code-bible/SKILL.md +93 -0
- package/templates/.claude/skills/claude-code-bible/scripts/fetch-docs.js +244 -0
- package/templates/.claude/skills/claude-native/SKILL.md +215 -0
- package/templates/.claude/skills/codex-exec/SKILL.md +206 -0
- package/templates/.claude/skills/codex-exec/scripts/codex-wrapper.cjs +430 -0
- package/templates/.claude/skills/create-agent/SKILL.md +94 -0
- package/templates/.claude/skills/cve-triage/SKILL.md +91 -0
- package/templates/.claude/skills/dag-orchestration/SKILL.md +201 -0
- package/templates/.claude/skills/dbt-best-practices/SKILL.md +55 -0
- package/templates/.claude/skills/de-lead-routing/SKILL.md +230 -0
- package/templates/.claude/skills/deep-plan/SKILL.md +344 -0
- package/templates/.claude/skills/deep-verify/SKILL.md +111 -0
- package/templates/.claude/skills/dev-lead-routing/SKILL.md +161 -0
- package/templates/.claude/skills/dev-refactor/SKILL.md +234 -0
- package/templates/.claude/skills/dev-review/SKILL.md +172 -0
- package/templates/.claude/skills/django-best-practices/SKILL.md +334 -0
- package/templates/.claude/skills/docker-best-practices/SKILL.md +276 -0
- package/templates/.claude/skills/evaluator-optimizer/SKILL.md +421 -0
- package/templates/.claude/skills/fastapi-best-practices/SKILL.md +271 -0
- package/templates/.claude/skills/fix-refs/SKILL.md +109 -0
- package/templates/.claude/skills/flutter-best-practices/SKILL.md +325 -0
- package/templates/.claude/skills/gemini-exec/SKILL.md +215 -0
- package/templates/.claude/skills/gemini-exec/scripts/gemini-wrapper.cjs +485 -0
- package/templates/.claude/skills/go-backend-best-practices/SKILL.md +135 -0
- package/templates/.claude/skills/go-best-practices/SKILL.md +204 -0
- package/templates/.claude/skills/hada-scout/SKILL.md +92 -0
- package/templates/.claude/skills/harness-eval/SKILL.md +95 -0
- package/templates/.claude/skills/harness-synthesizer/SKILL.md +145 -0
- package/templates/.claude/skills/help/SKILL.md +127 -0
- package/templates/.claude/skills/idea/SKILL.md +88 -0
- package/templates/.claude/skills/impeccable-design/SKILL.md +173 -0
- package/templates/.claude/skills/intent-detection/SKILL.md +293 -0
- package/templates/.claude/skills/intent-detection/patterns/agent-triggers.yaml +438 -0
- package/templates/.claude/skills/java21-best-practices/SKILL.md +190 -0
- package/templates/.claude/skills/jinja2-prompts/SKILL.md +86 -0
- package/templates/.claude/skills/kafka-best-practices/SKILL.md +53 -0
- package/templates/.claude/skills/kotlin-best-practices/SKILL.md +257 -0
- package/templates/.claude/skills/lists/SKILL.md +80 -0
- package/templates/.claude/skills/memory-management/SKILL.md +196 -0
- package/templates/.claude/skills/memory-recall/SKILL.md +172 -0
- package/templates/.claude/skills/memory-save/SKILL.md +128 -0
- package/templates/.claude/skills/model-escalation/SKILL.md +62 -0
- package/templates/.claude/skills/monitoring-setup/SKILL.md +215 -0
- package/templates/.claude/skills/multi-model-verification/SKILL.md +130 -0
- package/templates/.claude/skills/npm-audit/SKILL.md +74 -0
- package/templates/.claude/skills/npm-publish/SKILL.md +65 -0
- package/templates/.claude/skills/npm-version/SKILL.md +104 -0
- package/templates/.claude/skills/omcodex-auto-improve/SKILL.md +136 -0
- package/templates/.claude/skills/omcodex-feedback/SKILL.md +205 -0
- package/templates/.claude/skills/omcodex-improve-report/SKILL.md +65 -0
- package/templates/.claude/skills/omcodex-loop/SKILL.md +45 -0
- package/templates/.claude/skills/omcodex-release-notes/SKILL.md +117 -0
- package/templates/.claude/skills/omcodex-takeover/SKILL.md +115 -0
- package/templates/.claude/skills/omcodex-web/SKILL.md +95 -0
- package/templates/.claude/skills/optimize-analyze/SKILL.md +57 -0
- package/templates/.claude/skills/optimize-bundle/SKILL.md +69 -0
- package/templates/.claude/skills/optimize-report/SKILL.md +76 -0
- package/templates/.claude/skills/peer-messaging/SKILL.md +59 -0
- package/templates/.claude/skills/pipeline/SKILL.md +103 -0
- package/templates/.claude/skills/pipeline-architecture-patterns/SKILL.md +84 -0
- package/templates/.claude/skills/pipeline-guards/SKILL.md +173 -0
- package/templates/.claude/skills/post-release-followup/SKILL.md +134 -0
- package/templates/.claude/skills/postgres-best-practices/SKILL.md +67 -0
- package/templates/.claude/skills/pr-auto-improve/SKILL.md +129 -0
- package/templates/.claude/skills/professor-triage/SKILL.md +321 -0
- package/templates/.claude/skills/python-best-practices/SKILL.md +223 -0
- package/templates/.claude/skills/qa-lead-routing/SKILL.md +104 -0
- package/templates/.claude/skills/react-best-practices/SKILL.md +102 -0
- package/templates/.claude/skills/reasoning-sandwich/SKILL.md +64 -0
- package/templates/.claude/skills/redis-best-practices/SKILL.md +84 -0
- package/templates/.claude/skills/release-plan/SKILL.md +207 -0
- package/templates/.claude/skills/research/SKILL.md +493 -0
- package/templates/.claude/skills/result-aggregation/SKILL.md +165 -0
- package/templates/.claude/skills/rtk-exec/SKILL.md +199 -0
- package/templates/.claude/skills/rtk-exec/scripts/rtk-wrapper.cjs +377 -0
- package/templates/.claude/skills/rust-best-practices/SKILL.md +268 -0
- package/templates/.claude/skills/sauron-watch/SKILL.md +239 -0
- package/templates/.claude/skills/scout/SKILL.md +250 -0
- package/templates/.claude/skills/sdd/SKILL.md +24 -0
- package/templates/.claude/skills/sdd-dev/SKILL.md +257 -0
- package/templates/.claude/skills/sdd-development/SKILL.md +24 -0
- package/templates/.claude/skills/secretary-routing/SKILL.md +132 -0
- package/templates/.claude/skills/skill-extractor/SKILL.md +155 -0
- package/templates/.claude/skills/skills-sh-search/SKILL.md +210 -0
- package/templates/.claude/skills/snowflake-best-practices/SKILL.md +66 -0
- package/templates/.claude/skills/spark-best-practices/SKILL.md +53 -0
- package/templates/.claude/skills/springboot-best-practices/SKILL.md +74 -0
- package/templates/.claude/skills/springboot-best-practices/examples/config-properties-example.java +22 -0
- package/templates/.claude/skills/springboot-best-practices/examples/controller-example.java +28 -0
- package/templates/.claude/skills/springboot-best-practices/examples/controller-test-example.java +33 -0
- package/templates/.claude/skills/springboot-best-practices/examples/entity-example.java +22 -0
- package/templates/.claude/skills/springboot-best-practices/examples/exception-handler-example.java +30 -0
- package/templates/.claude/skills/springboot-best-practices/examples/repository-example.java +17 -0
- package/templates/.claude/skills/springboot-best-practices/examples/repository-test-example.java +23 -0
- package/templates/.claude/skills/springboot-best-practices/examples/security-config-example.java +27 -0
- package/templates/.claude/skills/springboot-best-practices/examples/service-example.java +33 -0
- package/templates/.claude/skills/status/SKILL.md +155 -0
- package/templates/.claude/skills/structured-dev-cycle/SKILL.md +200 -0
- package/templates/.claude/skills/stuck-recovery/SKILL.md +80 -0
- package/templates/.claude/skills/supabase-postgres-best-practices/SKILL.md +100 -0
- package/templates/.claude/skills/systematic-debugging/SKILL.md +288 -0
- package/templates/.claude/skills/systematic-debugging/condition-based-waiting-example.ts +278 -0
- package/templates/.claude/skills/systematic-debugging/condition-based-waiting.md +240 -0
- package/templates/.claude/skills/systematic-debugging/defense-in-depth.md +252 -0
- package/templates/.claude/skills/systematic-debugging/find-polluter.sh +147 -0
- package/templates/.claude/skills/systematic-debugging/root-cause-tracing.md +87 -0
- package/templates/.claude/skills/task-decomposition/SKILL.md +197 -0
- package/templates/.claude/skills/typescript-best-practices/SKILL.md +322 -0
- package/templates/.claude/skills/update-docs/SKILL.md +142 -0
- package/templates/.claude/skills/update-external/SKILL.md +169 -0
- package/templates/.claude/skills/vercel-deploy/SKILL.md +75 -0
- package/templates/.claude/skills/web-design-guidelines/SKILL.md +119 -0
- package/templates/.claude/skills/wiki/SKILL.md +426 -0
- package/templates/.claude/skills/wiki-rag/SKILL.md +154 -0
- package/templates/.claude/skills/worker-reviewer-pipeline/SKILL.md +165 -0
- package/templates/.claude/skills/writing-clearly-and-concisely/SKILL.md +66 -0
- package/templates/.claude/statusline.sh +380 -0
- package/templates/.claude/uninstall-hooks.sh +52 -0
- package/templates/.github/workflows/wiki-sync.yml +132 -0
- package/templates/AGENTS.md.en +255 -0
- package/templates/AGENTS.md.ko +255 -0
- package/templates/CLAUDE.md +263 -0
- package/templates/CLAUDE.md.en +256 -0
- package/templates/CLAUDE.md.ko +256 -0
- package/templates/deprecated-files.json +10 -0
- package/templates/guides/agents-md-quality/README.md +110 -0
- package/templates/guides/airflow/README.md +47 -0
- package/templates/guides/alembic/README.md +438 -0
- package/templates/guides/aws/common-patterns.md +169 -0
- package/templates/guides/aws/index.yaml +26 -0
- package/templates/guides/aws/well-architected.md +143 -0
- package/templates/guides/cc-token-saver/README.md +97 -0
- package/templates/guides/claude-code/01-overview.md +42 -0
- package/templates/guides/claude-code/03-tools.md +107 -0
- package/templates/guides/claude-code/04-agent-skills.md +90 -0
- package/templates/guides/claude-code/05-agent-sdk.md +129 -0
- package/templates/guides/claude-code/06-mcp.md +165 -0
- package/templates/guides/claude-code/07-prompt-engineering.md +100 -0
- package/templates/guides/claude-code/08-testing.md +56 -0
- package/templates/guides/claude-code/09-guardrails.md +78 -0
- package/templates/guides/claude-code/10-monitoring.md +87 -0
- package/templates/guides/claude-code/11-sub-agents.md +159 -0
- package/templates/guides/claude-code/12-workflow-patterns.md +182 -0
- package/templates/guides/claude-code/13-cli-flags.md +151 -0
- package/templates/guides/claude-code/index.yaml +61 -0
- package/templates/guides/dbt/README.md +32 -0
- package/templates/guides/django-best-practices/README.md +476 -0
- package/templates/guides/docker/compose-best-practices.md +284 -0
- package/templates/guides/docker/dockerfile-best-practices.md +262 -0
- package/templates/guides/docker/index.yaml +26 -0
- package/templates/guides/drizzle-orm/README.md +69 -0
- package/templates/guides/elements-of-style/elements-of-style.html +2609 -0
- package/templates/guides/fastapi/best-practices.md +232 -0
- package/templates/guides/fastapi/index.yaml +21 -0
- package/templates/guides/flutter/architecture.md +141 -0
- package/templates/guides/flutter/fundamentals.md +119 -0
- package/templates/guides/flutter/index.yaml +44 -0
- package/templates/guides/flutter/performance.md +119 -0
- package/templates/guides/flutter/security.md +120 -0
- package/templates/guides/flutter/state-management.md +144 -0
- package/templates/guides/flutter/testing.md +155 -0
- package/templates/guides/git-worktree-workflow/README.md +138 -0
- package/templates/guides/go-backend/index.yaml +26 -0
- package/templates/guides/go-backend/project-layout.md +243 -0
- package/templates/guides/go-backend/uber-style.md +212 -0
- package/templates/guides/golang/concurrency.md +282 -0
- package/templates/guides/golang/effective-go.md +309 -0
- package/templates/guides/golang/error-handling.md +250 -0
- package/templates/guides/golang/index.yaml +27 -0
- package/templates/guides/hook-data-flow/README.md +135 -0
- package/templates/guides/iceberg/README.md +49 -0
- package/templates/guides/impeccable-design/color-and-contrast.md +278 -0
- package/templates/guides/impeccable-design/index.yaml +12 -0
- package/templates/guides/impeccable-design/motion-design.md +390 -0
- package/templates/guides/impeccable-design/typography.md +386 -0
- package/templates/guides/impeccable-design/ux-writing.md +400 -0
- package/templates/guides/index.yaml +265 -0
- package/templates/guides/java21/index.yaml +29 -0
- package/templates/guides/java21/java-style-guide.md +248 -0
- package/templates/guides/java21/modern-java21.md +303 -0
- package/templates/guides/kafka/README.md +32 -0
- package/templates/guides/kotlin/coding-conventions.md +247 -0
- package/templates/guides/kotlin/idioms.md +234 -0
- package/templates/guides/kotlin/index.yaml +26 -0
- package/templates/guides/multi-model-routing/README.md +101 -0
- package/templates/guides/multi-provider-exec/README.md +83 -0
- package/templates/guides/postgres/README.md +58 -0
- package/templates/guides/python/index.yaml +26 -0
- package/templates/guides/python/pep8-style-guide.md +202 -0
- package/templates/guides/python/zen-of-python.md +79 -0
- package/templates/guides/redis/README.md +50 -0
- package/templates/guides/rust/error-handling.md +262 -0
- package/templates/guides/rust/index.yaml +26 -0
- package/templates/guides/rust/ownership.md +180 -0
- package/templates/guides/skill-bundle-design/README.md +106 -0
- package/templates/guides/slack-cli/README.md +145 -0
- package/templates/guides/snowflake/README.md +32 -0
- package/templates/guides/spark/README.md +32 -0
- package/templates/guides/springboot/best-practices.md +361 -0
- package/templates/guides/springboot/index.yaml +22 -0
- package/templates/guides/supabase-postgres/README.md +32 -0
- package/templates/guides/supabase-postgres/index.yaml +19 -0
- package/templates/guides/typescript/advanced-types.md +225 -0
- package/templates/guides/typescript/index.yaml +26 -0
- package/templates/guides/typescript/type-system.md +219 -0
- package/templates/guides/web-design/accessibility.md +66 -0
- package/templates/guides/web-design/index.yaml +20 -0
- package/templates/guides/web-design/performance.md +102 -0
- package/templates/guides/web-scraping/README.md +926 -0
- package/templates/guides/web-scraping/index.yaml +19 -0
- package/templates/guides/worktree-lifecycle/README.md +104 -0
- package/templates/index.yaml +18 -0
- package/templates/manifest.json +49 -0
- package/templates/workflows/auto-dev.yaml +46 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# Effective Go Reference
|
|
2
|
+
|
|
3
|
+
> Source: https://go.dev/doc/effective_go
|
|
4
|
+
|
|
5
|
+
## Introduction
|
|
6
|
+
|
|
7
|
+
Go is a new language. Although it borrows ideas from existing languages, it has unusual properties that make effective Go programs different in character from programs written in its relatives. A straightforward translation of a C++ or Java program into Go is unlikely to produce a satisfactory result—Java programs are written in Java, not Go.
|
|
8
|
+
|
|
9
|
+
## Formatting
|
|
10
|
+
|
|
11
|
+
Use `gofmt` (or `goimports`) to format all Go code. This eliminates formatting debates and ensures consistency.
|
|
12
|
+
|
|
13
|
+
Key points:
|
|
14
|
+
- Indentation: tabs, not spaces
|
|
15
|
+
- No line length limit (but break long lines sensibly)
|
|
16
|
+
- Fewer parentheses than C/Java
|
|
17
|
+
|
|
18
|
+
## Commentary
|
|
19
|
+
|
|
20
|
+
Go provides C-style `/* */` block comments and C++-style `//` line comments.
|
|
21
|
+
|
|
22
|
+
- Package comments: precede package clause, block comment for multi-line
|
|
23
|
+
- Doc comments: precede declarations, complete sentences starting with name
|
|
24
|
+
- `godoc` extracts documentation from comments
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
```go
|
|
28
|
+
// Package regexp implements a simple library for regular expressions.
|
|
29
|
+
package regexp
|
|
30
|
+
|
|
31
|
+
// Compile parses a regular expression and returns, if successful,
|
|
32
|
+
// a Regexp that can be used to match against text.
|
|
33
|
+
func Compile(str string) (*Regexp, error) {
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Names
|
|
37
|
+
|
|
38
|
+
### Package Names
|
|
39
|
+
|
|
40
|
+
- Short, concise, lowercase, single-word names
|
|
41
|
+
- No underscores or mixedCaps
|
|
42
|
+
- Name is the base name of its source directory
|
|
43
|
+
- Don't stutter: `bufio.Reader`, not `bufio.BufReader`
|
|
44
|
+
|
|
45
|
+
### Getters
|
|
46
|
+
|
|
47
|
+
- Don't use "Get" prefix
|
|
48
|
+
- `owner := obj.Owner()` not `obj.GetOwner()`
|
|
49
|
+
- Setters can use "Set": `obj.SetOwner(user)`
|
|
50
|
+
|
|
51
|
+
### Interface Names
|
|
52
|
+
|
|
53
|
+
- One-method interfaces: method name + "-er" suffix
|
|
54
|
+
- `Reader`, `Writer`, `Formatter`, `Notifier`
|
|
55
|
+
|
|
56
|
+
### MixedCaps
|
|
57
|
+
|
|
58
|
+
- Use `MixedCaps` or `mixedCaps` rather than underscores
|
|
59
|
+
- Exported: `MixedCaps` (capital first letter)
|
|
60
|
+
- Unexported: `mixedCaps` (lowercase first letter)
|
|
61
|
+
|
|
62
|
+
## Control Structures
|
|
63
|
+
|
|
64
|
+
### If
|
|
65
|
+
|
|
66
|
+
```go
|
|
67
|
+
// With initialization statement
|
|
68
|
+
if err := file.Chmod(0664); err != nil {
|
|
69
|
+
log.Print(err)
|
|
70
|
+
return err
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Avoid unnecessary else
|
|
74
|
+
if err != nil {
|
|
75
|
+
return err
|
|
76
|
+
}
|
|
77
|
+
// continue normal flow
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### For
|
|
81
|
+
|
|
82
|
+
```go
|
|
83
|
+
// Like C's for
|
|
84
|
+
for init; condition; post { }
|
|
85
|
+
|
|
86
|
+
// Like C's while
|
|
87
|
+
for condition { }
|
|
88
|
+
|
|
89
|
+
// Like C's for(;;)
|
|
90
|
+
for { }
|
|
91
|
+
|
|
92
|
+
// Range over slice
|
|
93
|
+
for key, value := range oldMap {
|
|
94
|
+
newMap[key] = value
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Range over string (runes)
|
|
98
|
+
for pos, char := range "日本語" {
|
|
99
|
+
fmt.Printf("character %c starts at byte position %d\n", char, pos)
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Switch
|
|
104
|
+
|
|
105
|
+
```go
|
|
106
|
+
// No automatic fallthrough
|
|
107
|
+
switch c {
|
|
108
|
+
case ' ', '?', '&', '=', '#', '+', '%':
|
|
109
|
+
return true
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Type switch
|
|
113
|
+
switch t := t.(type) {
|
|
114
|
+
case bool:
|
|
115
|
+
fmt.Printf("boolean %t\n", t)
|
|
116
|
+
case int:
|
|
117
|
+
fmt.Printf("integer %d\n", t)
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Functions
|
|
122
|
+
|
|
123
|
+
### Multiple Return Values
|
|
124
|
+
|
|
125
|
+
```go
|
|
126
|
+
func (file *File) Write(b []byte) (n int, err error)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Named Result Parameters
|
|
130
|
+
|
|
131
|
+
```go
|
|
132
|
+
func ReadFull(r Reader, buf []byte) (n int, err error) {
|
|
133
|
+
for len(buf) > 0 && err == nil {
|
|
134
|
+
var nr int
|
|
135
|
+
nr, err = r.Read(buf)
|
|
136
|
+
n += nr
|
|
137
|
+
buf = buf[nr:]
|
|
138
|
+
}
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Defer
|
|
144
|
+
|
|
145
|
+
```go
|
|
146
|
+
func Contents(filename string) (string, error) {
|
|
147
|
+
f, err := os.Open(filename)
|
|
148
|
+
if err != nil {
|
|
149
|
+
return "", err
|
|
150
|
+
}
|
|
151
|
+
defer f.Close() // f.Close will run when we're finished.
|
|
152
|
+
// ...
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Data
|
|
157
|
+
|
|
158
|
+
### Allocation with new
|
|
159
|
+
|
|
160
|
+
`new(T)` allocates zeroed storage for a new item of type `T` and returns its address, a value of type `*T`.
|
|
161
|
+
|
|
162
|
+
```go
|
|
163
|
+
p := new(SyncedBuffer) // type *SyncedBuffer
|
|
164
|
+
var v SyncedBuffer // type SyncedBuffer
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Allocation with make
|
|
168
|
+
|
|
169
|
+
`make(T, args)` creates slices, maps, and channels only. It returns an initialized (not zeroed) value of type `T` (not `*T`).
|
|
170
|
+
|
|
171
|
+
```go
|
|
172
|
+
make([]int, 10, 100) // slice with len=10, cap=100
|
|
173
|
+
make(map[string]int) // map
|
|
174
|
+
make(chan int, 100) // buffered channel
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Arrays and Slices
|
|
178
|
+
|
|
179
|
+
```go
|
|
180
|
+
// Array - fixed size, value type
|
|
181
|
+
var a [10]int
|
|
182
|
+
|
|
183
|
+
// Slice - dynamic size, reference to array
|
|
184
|
+
s := make([]int, 10)
|
|
185
|
+
s = append(s, 1, 2, 3)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Maps
|
|
189
|
+
|
|
190
|
+
```go
|
|
191
|
+
m := make(map[string]int)
|
|
192
|
+
m["key"] = 42
|
|
193
|
+
|
|
194
|
+
// Comma ok idiom
|
|
195
|
+
if val, ok := m["key"]; ok {
|
|
196
|
+
// key exists
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
delete(m, "key")
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Methods
|
|
203
|
+
|
|
204
|
+
### Pointer vs Value Receivers
|
|
205
|
+
|
|
206
|
+
```go
|
|
207
|
+
// Value receiver - operates on copy
|
|
208
|
+
func (s MyStruct) ValueMethod() { }
|
|
209
|
+
|
|
210
|
+
// Pointer receiver - can modify, avoids copy
|
|
211
|
+
func (s *MyStruct) PointerMethod() { }
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Rule: If any method needs a pointer receiver, all methods on that type should have pointer receivers.
|
|
215
|
+
|
|
216
|
+
## Interfaces
|
|
217
|
+
|
|
218
|
+
```go
|
|
219
|
+
type Reader interface {
|
|
220
|
+
Read(p []byte) (n int, err error)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
type Writer interface {
|
|
224
|
+
Write(p []byte) (n int, err error)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Composition
|
|
228
|
+
type ReadWriter interface {
|
|
229
|
+
Reader
|
|
230
|
+
Writer
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Embedding
|
|
235
|
+
|
|
236
|
+
```go
|
|
237
|
+
type ReadWriter struct {
|
|
238
|
+
*Reader // embedded
|
|
239
|
+
*Writer // embedded
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Concurrency
|
|
244
|
+
|
|
245
|
+
### Goroutines
|
|
246
|
+
|
|
247
|
+
```go
|
|
248
|
+
go list.Sort() // run list.Sort concurrently
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Channels
|
|
252
|
+
|
|
253
|
+
```go
|
|
254
|
+
ci := make(chan int) // unbuffered channel of integers
|
|
255
|
+
cj := make(chan int, 0) // unbuffered channel of integers
|
|
256
|
+
cs := make(chan *os.File, 100) // buffered channel of pointers to Files
|
|
257
|
+
|
|
258
|
+
c <- 1 // send
|
|
259
|
+
v := <-c // receive
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Select
|
|
263
|
+
|
|
264
|
+
```go
|
|
265
|
+
select {
|
|
266
|
+
case v := <-ch1:
|
|
267
|
+
fmt.Println("received from ch1:", v)
|
|
268
|
+
case ch2 <- 42:
|
|
269
|
+
fmt.Println("sent to ch2")
|
|
270
|
+
default:
|
|
271
|
+
fmt.Println("no communication")
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Errors
|
|
276
|
+
|
|
277
|
+
```go
|
|
278
|
+
type error interface {
|
|
279
|
+
Error() string
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Creating errors
|
|
283
|
+
errors.New("message")
|
|
284
|
+
fmt.Errorf("operation failed: %w", err)
|
|
285
|
+
|
|
286
|
+
// Checking errors
|
|
287
|
+
if err != nil {
|
|
288
|
+
return err
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Panic and Recover
|
|
293
|
+
|
|
294
|
+
```go
|
|
295
|
+
func server(workChan <-chan *Work) {
|
|
296
|
+
for work := range workChan {
|
|
297
|
+
go safelyDo(work)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
func safelyDo(work *Work) {
|
|
302
|
+
defer func() {
|
|
303
|
+
if err := recover(); err != nil {
|
|
304
|
+
log.Println("work failed:", err)
|
|
305
|
+
}
|
|
306
|
+
}()
|
|
307
|
+
do(work)
|
|
308
|
+
}
|
|
309
|
+
```
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Go Error Handling
|
|
2
|
+
|
|
3
|
+
> Reference for error handling patterns in Go
|
|
4
|
+
|
|
5
|
+
## Error Interface
|
|
6
|
+
|
|
7
|
+
```go
|
|
8
|
+
type error interface {
|
|
9
|
+
Error() string
|
|
10
|
+
}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Errors are values. They can be stored, passed, and compared.
|
|
14
|
+
|
|
15
|
+
## Creating Errors
|
|
16
|
+
|
|
17
|
+
### Simple Errors
|
|
18
|
+
|
|
19
|
+
```go
|
|
20
|
+
import "errors"
|
|
21
|
+
|
|
22
|
+
err := errors.New("something went wrong")
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Formatted Errors
|
|
26
|
+
|
|
27
|
+
```go
|
|
28
|
+
import "fmt"
|
|
29
|
+
|
|
30
|
+
err := fmt.Errorf("failed to process %s: %v", filename, err)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Custom Error Types
|
|
34
|
+
|
|
35
|
+
```go
|
|
36
|
+
type MyError struct {
|
|
37
|
+
Code int
|
|
38
|
+
Message string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func (e *MyError) Error() string {
|
|
42
|
+
return fmt.Sprintf("error %d: %s", e.Code, e.Message)
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Handling Errors
|
|
47
|
+
|
|
48
|
+
### Basic Pattern
|
|
49
|
+
|
|
50
|
+
```go
|
|
51
|
+
result, err := doSomething()
|
|
52
|
+
if err != nil {
|
|
53
|
+
return err
|
|
54
|
+
}
|
|
55
|
+
// use result
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Adding Context
|
|
59
|
+
|
|
60
|
+
```go
|
|
61
|
+
result, err := doSomething()
|
|
62
|
+
if err != nil {
|
|
63
|
+
return fmt.Errorf("doSomething failed: %w", err)
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Multiple Returns
|
|
68
|
+
|
|
69
|
+
```go
|
|
70
|
+
func divide(a, b float64) (float64, error) {
|
|
71
|
+
if b == 0 {
|
|
72
|
+
return 0, errors.New("division by zero")
|
|
73
|
+
}
|
|
74
|
+
return a / b, nil
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Error Wrapping (Go 1.13+)
|
|
79
|
+
|
|
80
|
+
### Wrapping Errors
|
|
81
|
+
|
|
82
|
+
```go
|
|
83
|
+
// Use %w verb to wrap
|
|
84
|
+
if err != nil {
|
|
85
|
+
return fmt.Errorf("operation failed: %w", err)
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Unwrapping Errors
|
|
90
|
+
|
|
91
|
+
```go
|
|
92
|
+
// errors.Unwrap returns the wrapped error
|
|
93
|
+
inner := errors.Unwrap(err)
|
|
94
|
+
|
|
95
|
+
// errors.Is checks if any error in chain matches
|
|
96
|
+
if errors.Is(err, os.ErrNotExist) {
|
|
97
|
+
// handle file not found
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// errors.As finds first error matching type
|
|
101
|
+
var pathErr *os.PathError
|
|
102
|
+
if errors.As(err, &pathErr) {
|
|
103
|
+
fmt.Println("failed path:", pathErr.Path)
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Sentinel Errors
|
|
108
|
+
|
|
109
|
+
```go
|
|
110
|
+
var (
|
|
111
|
+
ErrNotFound = errors.New("not found")
|
|
112
|
+
ErrUnauthorized = errors.New("unauthorized")
|
|
113
|
+
ErrInvalid = errors.New("invalid input")
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
func fetch(id string) (*Item, error) {
|
|
117
|
+
item, ok := store[id]
|
|
118
|
+
if !ok {
|
|
119
|
+
return nil, ErrNotFound
|
|
120
|
+
}
|
|
121
|
+
return item, nil
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Usage
|
|
125
|
+
item, err := fetch("123")
|
|
126
|
+
if errors.Is(err, ErrNotFound) {
|
|
127
|
+
// handle not found
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Error Handling Strategies
|
|
132
|
+
|
|
133
|
+
### Fail Fast
|
|
134
|
+
|
|
135
|
+
```go
|
|
136
|
+
func process() error {
|
|
137
|
+
if err := step1(); err != nil {
|
|
138
|
+
return err
|
|
139
|
+
}
|
|
140
|
+
if err := step2(); err != nil {
|
|
141
|
+
return err
|
|
142
|
+
}
|
|
143
|
+
return step3()
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Deferred Cleanup
|
|
148
|
+
|
|
149
|
+
```go
|
|
150
|
+
func processFile(path string) (err error) {
|
|
151
|
+
f, err := os.Open(path)
|
|
152
|
+
if err != nil {
|
|
153
|
+
return err
|
|
154
|
+
}
|
|
155
|
+
defer func() {
|
|
156
|
+
if cerr := f.Close(); cerr != nil && err == nil {
|
|
157
|
+
err = cerr
|
|
158
|
+
}
|
|
159
|
+
}()
|
|
160
|
+
// process file
|
|
161
|
+
return nil
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Error Aggregation
|
|
166
|
+
|
|
167
|
+
```go
|
|
168
|
+
type MultiError []error
|
|
169
|
+
|
|
170
|
+
func (m MultiError) Error() string {
|
|
171
|
+
var msgs []string
|
|
172
|
+
for _, err := range m {
|
|
173
|
+
msgs = append(msgs, err.Error())
|
|
174
|
+
}
|
|
175
|
+
return strings.Join(msgs, "; ")
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
func validateAll(items []Item) error {
|
|
179
|
+
var errs MultiError
|
|
180
|
+
for _, item := range items {
|
|
181
|
+
if err := validate(item); err != nil {
|
|
182
|
+
errs = append(errs, err)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if len(errs) > 0 {
|
|
186
|
+
return errs
|
|
187
|
+
}
|
|
188
|
+
return nil
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Panic and Recover
|
|
193
|
+
|
|
194
|
+
### When to Panic
|
|
195
|
+
|
|
196
|
+
- Unrecoverable errors during initialization
|
|
197
|
+
- Programming errors (nil pointer, out of bounds)
|
|
198
|
+
- Violation of invariants
|
|
199
|
+
|
|
200
|
+
```go
|
|
201
|
+
func MustCompile(pattern string) *Regexp {
|
|
202
|
+
re, err := Compile(pattern)
|
|
203
|
+
if err != nil {
|
|
204
|
+
panic(err)
|
|
205
|
+
}
|
|
206
|
+
return re
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Recovering from Panic
|
|
211
|
+
|
|
212
|
+
```go
|
|
213
|
+
func safeCall(fn func()) (err error) {
|
|
214
|
+
defer func() {
|
|
215
|
+
if r := recover(); r != nil {
|
|
216
|
+
err = fmt.Errorf("panic recovered: %v", r)
|
|
217
|
+
}
|
|
218
|
+
}()
|
|
219
|
+
fn()
|
|
220
|
+
return nil
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Package Boundary Rule
|
|
225
|
+
|
|
226
|
+
- Convert panics to errors at package boundaries
|
|
227
|
+
- Don't let panics escape your API
|
|
228
|
+
|
|
229
|
+
```go
|
|
230
|
+
func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
|
|
231
|
+
defer func() {
|
|
232
|
+
if err := recover(); err != nil {
|
|
233
|
+
log.Printf("panic: %v\n%s", err, debug.Stack())
|
|
234
|
+
http.Error(w, "Internal Server Error", 500)
|
|
235
|
+
}
|
|
236
|
+
}()
|
|
237
|
+
// handle request
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Best Practices
|
|
242
|
+
|
|
243
|
+
1. **Handle errors immediately** after the call
|
|
244
|
+
2. **Add context** when propagating errors
|
|
245
|
+
3. **Use error wrapping** with `%w` for error chains
|
|
246
|
+
4. **Define sentinel errors** for known conditions
|
|
247
|
+
5. **Don't ignore errors** (at minimum, log them)
|
|
248
|
+
6. **Prefer errors over panics** in library code
|
|
249
|
+
7. **Document error returns** in function comments
|
|
250
|
+
8. **Test error paths** as thoroughly as success paths
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Golang Guide
|
|
2
|
+
|
|
3
|
+
metadata:
|
|
4
|
+
name: golang
|
|
5
|
+
description: Go language reference documentation
|
|
6
|
+
|
|
7
|
+
source:
|
|
8
|
+
type: external
|
|
9
|
+
origin: go.dev
|
|
10
|
+
url: https://go.dev/doc/effective_go
|
|
11
|
+
last_fetched: "2026-01-22"
|
|
12
|
+
|
|
13
|
+
documents:
|
|
14
|
+
- name: effective-go
|
|
15
|
+
path: ./effective-go.md
|
|
16
|
+
description: Effective Go - official best practices guide
|
|
17
|
+
|
|
18
|
+
- name: concurrency
|
|
19
|
+
path: ./concurrency.md
|
|
20
|
+
description: Concurrency patterns and practices
|
|
21
|
+
|
|
22
|
+
- name: error-handling
|
|
23
|
+
path: ./error-handling.md
|
|
24
|
+
description: Error handling patterns
|
|
25
|
+
|
|
26
|
+
used_by:
|
|
27
|
+
- lang-golang-expert
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Hook Data Flow: Stall Detection Pipeline
|
|
2
|
+
|
|
3
|
+
Added in v0.78.0. Documents the three-script pipeline that detects stalled parallel agents and emits R009 Adaptive Parallel Splitting advisories.
|
|
4
|
+
|
|
5
|
+
Related rule: `.claude/rules/MUST-parallel-execution.md` (R009 Adaptive Parallel Splitting section)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
When multiple agents run in parallel, one agent may take significantly longer than its peers. The stall detection pipeline identifies this condition at the moment any agent completes and advises the orchestrator to spawn independent pending tasks immediately — without cancelling the stalled agent.
|
|
12
|
+
|
|
13
|
+
The pipeline spans two hook events and three scripts:
|
|
14
|
+
|
|
15
|
+
| Event | Script | Role |
|
|
16
|
+
|-------|--------|------|
|
|
17
|
+
| SubagentStart | `agent-start-recorder.sh` | Record spawn timestamp |
|
|
18
|
+
| SubagentStop (1st) | `task-outcome-recorder.sh` | Read start time, record outcome with duration |
|
|
19
|
+
| SubagentStop (2nd) | `stall-detection-advisor.sh` | Read start times, compare durations, emit advisory, consume start entry |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Data Flow
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
SubagentStart event
|
|
27
|
+
└─ agent-start-recorder.sh
|
|
28
|
+
reads: stdin JSON (agent_type, model, description)
|
|
29
|
+
writes: /tmp/.claude-agent-starts-$PPID (appends 1 JSON line)
|
|
30
|
+
|
|
31
|
+
SubagentStop event [hooks execute in array order — ordering is critical]
|
|
32
|
+
│
|
|
33
|
+
├─ [1] task-outcome-recorder.sh
|
|
34
|
+
│ reads: stdin JSON (agent_type, model, outcome)
|
|
35
|
+
│ reads: /tmp/.claude-agent-starts-$PPID (duration calc — entry still present)
|
|
36
|
+
│ writes: /tmp/.claude-task-outcomes-$PPID (appends 1 JSON line with duration_seconds)
|
|
37
|
+
│ writes: stderr (on failure only)
|
|
38
|
+
│
|
|
39
|
+
└─ [2] stall-detection-advisor.sh
|
|
40
|
+
reads: stdin JSON (agent_type, model, description)
|
|
41
|
+
reads: /tmp/.claude-agent-starts-$PPID (finds matching start entry for duration)
|
|
42
|
+
reads: /tmp/.claude-agent-durations-$PPID (peer durations for average calculation)
|
|
43
|
+
writes: /tmp/.claude-agent-durations-$PPID (appends completed agent's duration)
|
|
44
|
+
writes: /tmp/.claude-agent-starts-$PPID (removes consumed start entry)
|
|
45
|
+
writes: stderr (advisory block if stall detected — R021 advisory-only)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Stall Detection Logic
|
|
49
|
+
|
|
50
|
+
At SubagentStop, after at least one peer has already completed:
|
|
51
|
+
|
|
52
|
+
1. Calculate `avg_duration` from all entries in `.claude-agent-durations-$PPID`
|
|
53
|
+
2. Set `stall_threshold = avg_duration * 2`
|
|
54
|
+
3. Scan `.claude-agent-starts-$PPID` for agents not yet in the duration file (still running)
|
|
55
|
+
4. For each still-running agent where `elapsed > stall_threshold`, emit advisory to stderr
|
|
56
|
+
|
|
57
|
+
The current agent's duration is recorded *after* stall detection so it does not inflate the average for its own check.
|
|
58
|
+
|
|
59
|
+
### Advisory Output Format
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
─── [Stall Detection Advisory] ───────────────────────────
|
|
63
|
+
Stalled: {agent_type}:{model} ({elapsed}s elapsed, 2x avg {avg_duration}s)
|
|
64
|
+
Description: {description}
|
|
65
|
+
⚡ Consider spawning independent pending tasks immediately
|
|
66
|
+
R009 Adaptive Parallel Splitting applies
|
|
67
|
+
──────────────────────────────────────────────────────────
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Shared Files
|
|
73
|
+
|
|
74
|
+
| File | Writer | Readers | Lifecycle |
|
|
75
|
+
|------|--------|---------|-----------|
|
|
76
|
+
| `/tmp/.claude-agent-starts-$PPID` | `agent-start-recorder.sh` (append) | `task-outcome-recorder.sh` (read), `stall-detection-advisor.sh` (read + remove entry) | Session-scoped via PPID; ring buffer 50 entries; entry removed after `stall-detection-advisor` consumes it |
|
|
77
|
+
| `/tmp/.claude-task-outcomes-$PPID` | `task-outcome-recorder.sh` (append) | `feedback-collector.sh`, `eval-core-batch-save.sh` (at Stop) | Session-scoped via PPID; ring buffer 50 entries |
|
|
78
|
+
| `/tmp/.claude-agent-durations-$PPID` | `stall-detection-advisor.sh` (append) | `stall-detection-advisor.sh` (read for average calculation) | Session-scoped via PPID; ring buffer 50 entries |
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Execution Order Requirements
|
|
83
|
+
|
|
84
|
+
The SubagentStop hook array in `hooks.json` defines a strict ordering:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
"SubagentStop": [
|
|
88
|
+
{ "command": "bash .claude/hooks/scripts/task-outcome-recorder.sh" },
|
|
89
|
+
{ "command": "bash .claude/hooks/scripts/stall-detection-advisor.sh" },
|
|
90
|
+
...
|
|
91
|
+
]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**task-outcome-recorder MUST run before stall-detection-advisor.**
|
|
95
|
+
|
|
96
|
+
Reason: `stall-detection-advisor.sh` removes the matching start entry from `.claude-agent-starts-$PPID` after reading it (to prevent re-matching on the next SubagentStop). If the order were reversed, `task-outcome-recorder.sh` would find no start entry for the agent and would always record `duration_seconds=0`.
|
|
97
|
+
|
|
98
|
+
If the order is swapped:
|
|
99
|
+
- `task-outcome-recorder` records `duration_seconds=0` for all agents
|
|
100
|
+
- Model escalation decisions based on duration become unreliable
|
|
101
|
+
- No other visible error — silent data corruption
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Temp File Lifecycle
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
Session start (PPID assigned)
|
|
109
|
+
│
|
|
110
|
+
├─ First SubagentStart → .claude-agent-starts-$PPID created
|
|
111
|
+
│
|
|
112
|
+
├─ First SubagentStop → .claude-task-outcomes-$PPID created
|
|
113
|
+
│ .claude-agent-durations-$PPID created
|
|
114
|
+
│
|
|
115
|
+
├─ Each SubagentStop → start entry consumed (removed by stall-detection-advisor)
|
|
116
|
+
│ duration entry appended
|
|
117
|
+
│ outcome entry appended
|
|
118
|
+
│
|
|
119
|
+
└─ Session end (PPID released)
|
|
120
|
+
Files remain in /tmp — OS cleans up on reboot
|
|
121
|
+
Ring buffers cap each file at 50 lines to bound growth
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
PPID (parent process ID) is used rather than PID (`$$`) to scope files to the current GPT Codex + OMX session rather than to individual script invocations. All three scripts use `${PPID}` consistently.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Design Principles
|
|
129
|
+
|
|
130
|
+
- **Advisory-only (R021):** All three scripts exit 0 unconditionally. A missing `jq` binary causes silent pass-through, not a blocked hook.
|
|
131
|
+
- **PPID scoping:** Isolates temp files per GPT Codex + OMX session. Multiple concurrent sessions do not interfere.
|
|
132
|
+
- **Ring buffers:** Each temp file is capped at 50 lines via `tail -50` after each append. Prevents unbounded growth in long sessions with many agents.
|
|
133
|
+
- **grep -F for pattern matching:** Fixed-string matching in `agent-start-recorder` and `task-outcome-recorder` avoids regex injection from agent type names.
|
|
134
|
+
- **Self-exclusion from average:** `stall-detection-advisor` reads the duration file *before* appending its own entry, so the completing agent is never compared against itself.
|
|
135
|
+
- **Sibling preservation:** When removing a start entry, `awk` removes only the first matching line — preserving sibling entries when multiple agents of the same type run in parallel.
|