@mrciphersmith/keryx 0.2.9
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 +351 -0
- package/dist/cli.js +48427 -0
- package/dist/proxy-worker.js +381 -0
- package/package.json +63 -0
- package/src/gdgraph/affected.test.ts +100 -0
- package/src/gdgraph/affected.ts +135 -0
- package/src/gdgraph/build-integrity.test.ts +193 -0
- package/src/gdgraph/build-lang.test.ts +399 -0
- package/src/gdgraph/build.test.ts +120 -0
- package/src/gdgraph/build.ts +804 -0
- package/src/gdgraph/config.test.ts +47 -0
- package/src/gdgraph/config.ts +113 -0
- package/src/gdgraph/core-sources.test.ts +99 -0
- package/src/gdgraph/core-sources.ts +20 -0
- package/src/gdgraph/enrich.ts +79 -0
- package/src/gdgraph/fallback.test.ts +153 -0
- package/src/gdgraph/find.test.ts +78 -0
- package/src/gdgraph/find.ts +107 -0
- package/src/gdgraph/pagerank.ts +129 -0
- package/src/gdgraph/path.test.ts +56 -0
- package/src/gdgraph/path.ts +112 -0
- package/src/gdgraph/query.ts +133 -0
- package/src/gdgraph/repomap.test.ts +110 -0
- package/src/gdgraph/repomap.ts +193 -0
- package/src/gdgraph/service.test.ts +59 -0
- package/src/gdgraph/service.ts +51 -0
- package/src/gdgraph/staleness.ts +20 -0
- package/src/gdgraph/symbol.test.ts +89 -0
- package/src/gdgraph/symbol.ts +123 -0
- package/src/gdgraph/symbols-capability.test.ts +41 -0
- package/src/gdgraph/symbols-capability.ts +49 -0
- package/src/gdgraph/target.ts +56 -0
- package/src/gdgraph/treesitter/adapter.test.ts +249 -0
- package/src/gdgraph/treesitter/adapter.ts +213 -0
- package/src/gdgraph/treesitter/extract.test.ts +278 -0
- package/src/gdgraph/treesitter/extract.ts +389 -0
- package/src/gdgraph/treesitter/grammars.ts +110 -0
- package/src/gdgraph/treesitter/no-treesitter-import.test.ts +51 -0
- package/src/gdgraph/treesitter/resolve-calls.test.ts +38 -0
- package/src/gdgraph/types.ts +63 -0
- package/src/gdskills/bundled/rules/core/api-contracts.mdc +148 -0
- package/src/gdskills/bundled/rules/core/async-patterns.mdc +185 -0
- package/src/gdskills/bundled/rules/core/clean-architecture.mdc +163 -0
- package/src/gdskills/bundled/rules/core/code-review-ai-assistant.mdc +49 -0
- package/src/gdskills/bundled/rules/core/code-review-b091-profile.mdc +48 -0
- package/src/gdskills/bundled/rules/core/code-style-patterns.mdc +54 -0
- package/src/gdskills/bundled/rules/core/commit-message-formatting.mdc +25 -0
- package/src/gdskills/bundled/rules/core/database-patterns.mdc +162 -0
- package/src/gdskills/bundled/rules/core/documentation-management.mdc +106 -0
- package/src/gdskills/bundled/rules/core/error-handling.mdc +163 -0
- package/src/gdskills/bundled/rules/core/execution-metrics.md +99 -0
- package/src/gdskills/bundled/rules/core/frontend-assistant.mdc +40 -0
- package/src/gdskills/bundled/rules/core/git-rules.mdc +37 -0
- package/src/gdskills/bundled/rules/core/gproject-contracts.mdc +198 -0
- package/src/gdskills/bundled/rules/core/implementation-doc-mandate.mdc +149 -0
- package/src/gdskills/bundled/rules/core/implementation-plans.mdc +58 -0
- package/src/gdskills/bundled/rules/core/jobs-documentation.mdc +221 -0
- package/src/gdskills/bundled/rules/core/mobx-store-template.mdc +561 -0
- package/src/gdskills/bundled/rules/core/model-selection.mdc +53 -0
- package/src/gdskills/bundled/rules/core/nestjs-dto.mdc +50 -0
- package/src/gdskills/bundled/rules/core/playwright-testing.mdc +321 -0
- package/src/gdskills/bundled/rules/core/requirements-management.mdc +35 -0
- package/src/gdskills/bundled/rules/core/requirements-package-standard.mdc +103 -0
- package/src/gdskills/bundled/rules/core/review-agent-profile.mdc +49 -0
- package/src/gdskills/bundled/rules/core/review-strict-profile.mdc +44 -0
- package/src/gdskills/bundled/rules/core/rule-management-workflow.mdc +62 -0
- package/src/gdskills/bundled/rules/core/security-baseline.mdc +155 -0
- package/src/gdskills/bundled/rules/core/shared-definitions.mdc +79 -0
- package/src/gdskills/bundled/rules/core/skill-lifecycle.mdc +55 -0
- package/src/gdskills/bundled/rules/core/skills-storage-workflow.mdc +88 -0
- package/src/gdskills/bundled/rules/core/solid-principles.mdc +149 -0
- package/src/gdskills/bundled/rules/core/storybook-guidelines.mdc +36 -0
- package/src/gdskills/bundled/rules/core/subagent-context-construction.md +107 -0
- package/src/gdskills/bundled/rules/core/subagent-status-protocol.md +169 -0
- package/src/gdskills/bundled/rules/core/tdd-workflow.mdc +96 -0
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.codex.md +47 -0
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.cursor.md +55 -0
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.md +352 -0
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.opencode.md +39 -0
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.zed.md +29 -0
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.codex.md +567 -0
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.cursor.md +567 -0
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.md +655 -0
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.opencode.md +567 -0
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.zed.md +567 -0
- package/src/gdskills/bundled/skills/orchestration/context-collector/input-contract.schema.json +134 -0
- package/src/gdskills/bundled/skills/orchestration/context-collector/orchestrator-prompt.md +183 -0
- package/src/gdskills/bundled/skills/orchestration/context-collector/output-contract.schema.json +208 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.codex.md +1412 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.cursor.md +1412 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.detail.md +735 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.md +468 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.opencode.md +1412 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.zed.md +1412 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/analysis-request.md +62 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/analysis-request.template.md +79 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/input-contract.schema.json +247 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/orchestrator-prompt.md +362 -0
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/output-contract.schema.json +87 -0
- package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.codex.md +105 -0
- package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.cursor.md +105 -0
- package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.md +165 -0
- package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/SKILL.md +379 -0
- package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/input-contract.schema.json +33 -0
- package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/output-contract.schema.json +41 -0
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.codex.md +307 -0
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.cursor.md +307 -0
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.md +373 -0
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.opencode.md +307 -0
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.zed.md +307 -0
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/input-contract.schema.json +130 -0
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/issue-request.template.md +50 -0
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/orchestrator-prompt.md +155 -0
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/output-contract.schema.json +61 -0
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.codex.md +365 -0
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.cursor.md +365 -0
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.md +373 -0
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.opencode.md +365 -0
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.zed.md +365 -0
- package/src/gdskills/bundled/skills/orchestration/job-documenter/input-contract.schema.json +55 -0
- package/src/gdskills/bundled/skills/orchestration/job-documenter/output-contract.schema.json +58 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.codex.md +1701 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.cursor.md +1701 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.md +1734 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.opencode.md +1701 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.zed.md +1701 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/input-contract.schema.json +188 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/orchestrator-prompt.md +179 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/output-contract.schema.json +103 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/state.schema.json +164 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.codex.md +395 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.cursor.md +395 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.md +556 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.opencode.md +395 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.zed.md +395 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/input-contract.schema.json +204 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/orchestrator-prompt.md +206 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/output-contract.schema.json +51 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/task-request.template.md +111 -0
- package/src/gdskills/bundled/skills/planning/autodoc-analyst/SKILL.md +163 -0
- package/src/gdskills/bundled/skills/planning/autodoc-architect/SKILL.md +161 -0
- package/src/gdskills/bundled/skills/planning/autodoc-assembler/SKILL.md +128 -0
- package/src/gdskills/bundled/skills/planning/autodoc-orchestrator/SKILL.md +321 -0
- package/src/gdskills/bundled/skills/planning/autodoc-scanner/SKILL.md +166 -0
- package/src/gdskills/bundled/skills/planning/autodoc-writer/SKILL.md +253 -0
- package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.claude.md +46 -0
- package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.codex.md +90 -0
- package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.cursor.md +90 -0
- package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.md +90 -0
- package/src/gdskills/bundled/skills/planning/consistency-checker/SKILL.codex.md +33 -0
- package/src/gdskills/bundled/skills/planning/consistency-checker/SKILL.cursor.md +33 -0
- package/src/gdskills/bundled/skills/planning/consistency-checker/SKILL.md +190 -0
- package/src/gdskills/bundled/skills/planning/docpack-orchestrator/SKILL.md +142 -0
- package/src/gdskills/bundled/skills/planning/docpack-orchestrator/input-contract.schema.json +31 -0
- package/src/gdskills/bundled/skills/planning/docpack-orchestrator/output-contract.schema.json +31 -0
- package/src/gdskills/bundled/skills/planning/docpack-review/SKILL.md +80 -0
- package/src/gdskills/bundled/skills/planning/docpack-review/input-contract.schema.json +20 -0
- package/src/gdskills/bundled/skills/planning/docpack-review/output-contract.schema.json +36 -0
- package/src/gdskills/bundled/skills/planning/interview/SKILL.codex.md +181 -0
- package/src/gdskills/bundled/skills/planning/interview/SKILL.cursor.md +181 -0
- package/src/gdskills/bundled/skills/planning/interview/SKILL.md +187 -0
- package/src/gdskills/bundled/skills/planning/interviewer/SKILL.claude.md +94 -0
- package/src/gdskills/bundled/skills/planning/interviewer/SKILL.codex.md +99 -0
- package/src/gdskills/bundled/skills/planning/interviewer/SKILL.cursor.md +99 -0
- package/src/gdskills/bundled/skills/planning/interviewer/SKILL.md +105 -0
- package/src/gdskills/bundled/skills/planning/patterns-researcher/SKILL.codex.md +33 -0
- package/src/gdskills/bundled/skills/planning/patterns-researcher/SKILL.cursor.md +33 -0
- package/src/gdskills/bundled/skills/planning/patterns-researcher/SKILL.md +237 -0
- package/src/gdskills/bundled/skills/planning/planner/SKILL.codex.md +33 -0
- package/src/gdskills/bundled/skills/planning/planner/SKILL.cursor.md +33 -0
- package/src/gdskills/bundled/skills/planning/planner/SKILL.md +190 -0
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.codex.md +193 -0
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.cursor.md +193 -0
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.md +193 -0
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.opencode.md +193 -0
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.zed.md +193 -0
- package/src/gdskills/bundled/skills/planning/prd-creator/input-contract.schema.json +63 -0
- package/src/gdskills/bundled/skills/planning/prd-creator/output-contract.schema.json +175 -0
- package/src/gdskills/bundled/skills/planning/problem-definer/SKILL.codex.md +31 -0
- package/src/gdskills/bundled/skills/planning/problem-definer/SKILL.cursor.md +31 -0
- package/src/gdskills/bundled/skills/planning/problem-definer/SKILL.md +153 -0
- package/src/gdskills/bundled/skills/planning/project-discovery/SKILL.codex.md +32 -0
- package/src/gdskills/bundled/skills/planning/project-discovery/SKILL.cursor.md +32 -0
- package/src/gdskills/bundled/skills/planning/project-discovery/SKILL.md +166 -0
- package/src/gdskills/bundled/skills/planning/spec-writer/SKILL.codex.md +44 -0
- package/src/gdskills/bundled/skills/planning/spec-writer/SKILL.cursor.md +44 -0
- package/src/gdskills/bundled/skills/planning/spec-writer/SKILL.md +243 -0
- package/src/gdskills/bundled/skills/planning/stack-advisor/SKILL.codex.md +43 -0
- package/src/gdskills/bundled/skills/planning/stack-advisor/SKILL.cursor.md +43 -0
- package/src/gdskills/bundled/skills/planning/stack-advisor/SKILL.md +193 -0
- package/src/gdskills/bundled/skills/platform/agent-entrypoint-distiller/SKILL.md +47 -0
- package/src/gdskills/bundled/skills/platform/claude-md-management/SKILL.codex.md +87 -0
- package/src/gdskills/bundled/skills/platform/claude-md-management/SKILL.cursor.md +87 -0
- package/src/gdskills/bundled/skills/platform/claude-md-management/SKILL.md +87 -0
- package/src/gdskills/bundled/skills/platform/hookify/SKILL.codex.md +100 -0
- package/src/gdskills/bundled/skills/platform/hookify/SKILL.cursor.md +100 -0
- package/src/gdskills/bundled/skills/platform/hookify/SKILL.md +100 -0
- package/src/gdskills/bundled/skills/quality/changelog/SKILL.claude.md +45 -0
- package/src/gdskills/bundled/skills/quality/changelog/SKILL.codex.md +84 -0
- package/src/gdskills/bundled/skills/quality/changelog/SKILL.cursor.md +84 -0
- package/src/gdskills/bundled/skills/quality/changelog/SKILL.md +84 -0
- package/src/gdskills/bundled/skills/quality/commit/SKILL.codex.md +66 -0
- package/src/gdskills/bundled/skills/quality/commit/SKILL.cursor.md +66 -0
- package/src/gdskills/bundled/skills/quality/commit/SKILL.md +66 -0
- package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.claude.md +40 -0
- package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.codex.md +66 -0
- package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.cursor.md +66 -0
- package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.md +66 -0
- package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.claude.md +45 -0
- package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.codex.md +81 -0
- package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.cursor.md +81 -0
- package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.md +81 -0
- package/src/gdskills/bundled/skills/quality/deploy/SKILL.claude.md +42 -0
- package/src/gdskills/bundled/skills/quality/deploy/SKILL.codex.md +70 -0
- package/src/gdskills/bundled/skills/quality/deploy/SKILL.cursor.md +70 -0
- package/src/gdskills/bundled/skills/quality/deploy/SKILL.md +70 -0
- package/src/gdskills/bundled/skills/quality/metaproject-security/SKILL.md +103 -0
- package/src/gdskills/bundled/skills/quality/perf-check/SKILL.claude.md +48 -0
- package/src/gdskills/bundled/skills/quality/perf-check/SKILL.codex.md +83 -0
- package/src/gdskills/bundled/skills/quality/perf-check/SKILL.cursor.md +83 -0
- package/src/gdskills/bundled/skills/quality/perf-check/SKILL.md +83 -0
- package/src/gdskills/bundled/skills/quality/pr/SKILL.codex.md +75 -0
- package/src/gdskills/bundled/skills/quality/pr/SKILL.cursor.md +75 -0
- package/src/gdskills/bundled/skills/quality/pr/SKILL.md +75 -0
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.codex.md +364 -0
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.cursor.md +295 -0
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.md +378 -0
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.opencode.md +364 -0
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.zed.md +38 -0
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/input-contract.schema.json +53 -0
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/output-contract.schema.json +46 -0
- package/src/gdskills/bundled/skills/quality/push/SKILL.codex.md +52 -0
- package/src/gdskills/bundled/skills/quality/push/SKILL.cursor.md +52 -0
- package/src/gdskills/bundled/skills/quality/push/SKILL.md +52 -0
- package/src/gdskills/bundled/skills/quality/security-audit/SKILL.claude.md +40 -0
- package/src/gdskills/bundled/skills/quality/security-audit/SKILL.codex.md +61 -0
- package/src/gdskills/bundled/skills/quality/security-audit/SKILL.cursor.md +61 -0
- package/src/gdskills/bundled/skills/quality/security-audit/SKILL.md +61 -0
- package/src/gdskills/bundled/skills/quality/test-gen/SKILL.claude.md +30 -0
- package/src/gdskills/bundled/skills/quality/test-gen/SKILL.codex.md +75 -0
- package/src/gdskills/bundled/skills/quality/test-gen/SKILL.cursor.md +75 -0
- package/src/gdskills/bundled/skills/quality/test-gen/SKILL.md +75 -0
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.codex.md +64 -0
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.cursor.md +74 -0
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.md +339 -0
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.opencode.md +48 -0
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.zed.md +44 -0
- package/src/gdskills/bundled/skills/quality/tests-creator/input-contract.schema.json +121 -0
- package/src/gdskills/bundled/skills/quality/tests-creator/output-contract.schema.json +127 -0
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.codex.md +204 -0
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.cursor.md +204 -0
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.md +203 -0
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.opencode.md +204 -0
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.zed.md +204 -0
- package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.codex.md +209 -0
- package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.cursor.md +209 -0
- package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.md +208 -0
- package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.opencode.md +209 -0
- package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.zed.md +209 -0
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.codex.md +263 -0
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.cursor.md +263 -0
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.md +258 -0
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.opencode.md +263 -0
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.zed.md +263 -0
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.codex.md +175 -0
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.cursor.md +175 -0
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.md +168 -0
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.opencode.md +175 -0
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.zed.md +175 -0
- package/src/gdskills/bundled/skills/review/review-architecture/SKILL.md +360 -0
- package/src/gdskills/bundled/skills/review/review-backend/SKILL.md +337 -0
- package/src/gdskills/bundled/skills/review/review-clean-code/SKILL.md +477 -0
- package/src/gdskills/bundled/skills/review/review-core-boundaries/SKILL.md +93 -0
- package/src/gdskills/bundled/skills/review/review-flow-graph/SKILL.md +119 -0
- package/src/gdskills/bundled/skills/review/review-frontend/SKILL.md +595 -0
- package/src/gdskills/bundled/skills/review/review-frontend-conventions/SKILL.md +144 -0
- package/src/gdskills/bundled/skills/review/review-highload/SKILL.md +519 -0
- package/src/gdskills/bundled/skills/review/review-logic/SKILL.md +323 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +927 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/input-contract.schema.json +153 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/output-contract.schema.json +77 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/review-context.schema.json +389 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-finding.schema.json +189 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-input.schema.json +241 -0
- package/src/gdskills/bundled/skills/review/review-performance/SKILL.md +344 -0
- package/src/gdskills/bundled/skills/review/review-pr-feedback/SKILL.md +327 -0
- package/src/gdskills/bundled/skills/review/review-security-code/SKILL.md +348 -0
- package/src/gdskills/bundled/skills/review/review-strict/SKILL.md +328 -0
- package/src/gdskills/bundled/skills/review/review-style/SKILL.md +343 -0
- package/src/gdskills/bundled/skills/review/review-testing-practices/SKILL.md +134 -0
- package/src/gdskills/bundled/skills/shared/git-merge-base.md +33 -0
- package/src/gdskills/contracts/agent-event.schema.json +32 -0
- package/src/gdskills/contracts/orchestrator-state.schema.json +58 -0
- package/src/gdskills/contracts/review-finding.schema.json +59 -0
- package/src/gdskills/contracts/subagent-dispatch.schema.json +123 -0
- package/src/gdskills/contracts/subagent-result.schema.json +136 -0
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: review-frontend
|
|
3
|
+
description: "Use when a frontend review is requested, checking React component patterns, MobX state management (observer, actions, computed, reactions, lifecycle), View-Store boundaries, and TypeScript safety in changed frontend code. NOT for backend patterns, security vulnerabilities, performance bottlenecks, or cross-layer architecture."
|
|
4
|
+
triggers:
|
|
5
|
+
- "review frontend"
|
|
6
|
+
- "frontend review"
|
|
7
|
+
- "review React"
|
|
8
|
+
- "review MobX"
|
|
9
|
+
- "review store"
|
|
10
|
+
- "review components"
|
|
11
|
+
- dispatched by review-orchestrator
|
|
12
|
+
metadata:
|
|
13
|
+
author: "MrCipherSmith"
|
|
14
|
+
version: "1.1.0"
|
|
15
|
+
category: "review"
|
|
16
|
+
license: "MIT"
|
|
17
|
+
compatibility: "cursor,codex,zed,opencode,claude"
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Review: Frontend (React + MobX + TypeScript)
|
|
21
|
+
|
|
22
|
+
## Purpose
|
|
23
|
+
|
|
24
|
+
Validates frontend-specific patterns in the changed code of the current branch. Covers React component correctness (observer wrapping, MVVM boundary, useEffect misuse, accessibility basics, key props), full MobX store patterns (structure, member ordering, accessibility modifiers, observable collections, reactions, async actions, bidirectional sync, lifecycle, API placement), and TypeScript safety.
|
|
25
|
+
|
|
26
|
+
This skill consolidates what was previously split between `code-style-review` (frontend parts) and `code-mobx-store-review`. It supersedes both for frontend changes.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Input Contract
|
|
31
|
+
|
|
32
|
+
| Field | Required | Description |
|
|
33
|
+
|-------|----------|-------------|
|
|
34
|
+
| Branch / diff range | No | Defaults to merge-base..HEAD + uncommitted changes |
|
|
35
|
+
| Explicit commit hash/range | No | Review only that range when provided |
|
|
36
|
+
| `JOB_NAME` | No | Job name when dispatched by orchestrator |
|
|
37
|
+
| `CONTEXT_PATH` | No | Path to context doc when dispatched by orchestrator |
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Scope Boundaries
|
|
42
|
+
|
|
43
|
+
| Concern | This skill | Use instead |
|
|
44
|
+
|---------|-----------|-------------|
|
|
45
|
+
| React component patterns (observer, MVVM, useEffect, keys, a11y) | YES | — |
|
|
46
|
+
| MobX store: structure, actions, computed, reactions, lifecycle | YES | — |
|
|
47
|
+
| MobX: observable collections, bidirectional sync, disposers | YES | — |
|
|
48
|
+
| View↔Store boundary violations | YES | — |
|
|
49
|
+
| TypeScript safety in frontend code (no any, I* prefix, ?./??/!) | YES | — |
|
|
50
|
+
| Backend patterns, NestJS, server-side logic | NO | `review-logic`, `review-architecture` |
|
|
51
|
+
| Cross-layer architecture (service layer design, module boundaries) | NO | `review-architecture` |
|
|
52
|
+
| Security vulnerabilities (XSS, injection, auth gaps) | NO | `review-security-code` |
|
|
53
|
+
| Performance bottlenecks (N+1, bundle size, re-render frequency) | NO | `review-performance` |
|
|
54
|
+
| Code style, naming outside frontend conventions | NO | `code-style-review` |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Iron Laws
|
|
59
|
+
|
|
60
|
+
1. **Every observable mutation outside an action or `runInAction` is at minimum a `major` finding.** No exception for "small stores" or "simple assignments".
|
|
61
|
+
2. **Missing `observer()` on a component that reads MobX observables is always a `blocker`.** The component will not react to state changes — this is a silent, runtime correctness bug.
|
|
62
|
+
3. **An API call in a component is always a `blocker`.** API/IO belongs in private store methods, not in JSX, hooks, or event handlers within the component file.
|
|
63
|
+
4. **`public` keyword on any class member is always an error.** The ESLint rule `@typescript-eslint/explicit-member-accessibility` with `"no-public"` forbids it.
|
|
64
|
+
5. **Inter-store callbacks (`onChangeX`, `handleX`, `syncX`) without `private` are always a `major`.** Ask: "Is this called from JSX?" If no — it must be `private`.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Scope Detection
|
|
69
|
+
|
|
70
|
+
See shared script: `skills/shared/git-merge-base.md`
|
|
71
|
+
|
|
72
|
+
Run the script from that file to determine `MERGE_BASE` (`BASE_SHA`) and `SCOPE` before proceeding.
|
|
73
|
+
|
|
74
|
+
### Commands to collect the review slice
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git status
|
|
78
|
+
git log --oneline "${BASE_SHA}..HEAD"
|
|
79
|
+
git diff --stat --name-status "${BASE_SHA}..HEAD"
|
|
80
|
+
git diff "${BASE_SHA}..HEAD"
|
|
81
|
+
|
|
82
|
+
# Include uncommitted changes (default mode):
|
|
83
|
+
git diff --stat --name-status "${BASE_SHA}"
|
|
84
|
+
git diff "${BASE_SHA}"
|
|
85
|
+
git ls-files --others --exclude-standard
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
For explicit hash/range mode:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
git diff --stat --name-status <FROM_SHA>..<TO_SHA>
|
|
92
|
+
git diff <FROM_SHA>..<TO_SHA>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Step 0: Read Project CLAUDE.md
|
|
98
|
+
|
|
99
|
+
Before running the checklist, scan the project for CLAUDE.md files that define project-specific conventions:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Project root
|
|
103
|
+
cat PROJECT_DIR/CLAUDE.md 2>/dev/null
|
|
104
|
+
|
|
105
|
+
# Module-level overrides (common in monorepos and large SPAs)
|
|
106
|
+
find PROJECT_DIR/src -name "CLAUDE.md" -maxdepth 3 2>/dev/null | xargs cat 2>/dev/null
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Extract and note:
|
|
110
|
+
- MobX patterns that differ from defaults (decorator style, lifecycle names, store init patterns)
|
|
111
|
+
- Naming conventions (store suffix, file casing, interface prefix rules)
|
|
112
|
+
- Style guides and their enforcement level
|
|
113
|
+
- Links to external documentation
|
|
114
|
+
- Any patterns explicitly declared as project standard — follow them, do NOT flag as violations
|
|
115
|
+
- Any patterns explicitly declared as anti-patterns — flag them even if not in this skill's generic checklist
|
|
116
|
+
|
|
117
|
+
**Resolution rule:** When a project CLAUDE.md pattern conflicts with this skill's generic checklist, the CLAUDE.md pattern wins — unless it violates an Iron Law.
|
|
118
|
+
|
|
119
|
+
If no CLAUDE.md is found, proceed normally. CLAUDE.md is optional and non-blocking.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Review Checklist
|
|
124
|
+
|
|
125
|
+
### Part A: React Component Patterns
|
|
126
|
+
|
|
127
|
+
#### A1. MobX Observer Wrapping
|
|
128
|
+
|
|
129
|
+
- [ ] Every component that reads a MobX observable (directly from a store, or from `useLocalObservable`) MUST be wrapped in `observer(ComponentName)` or be a class component extending `React.Component` with `observer` applied
|
|
130
|
+
- [ ] `observer` must wrap the **entire** component, not just a sub-section
|
|
131
|
+
- [ ] HOC composition order: `observer` should be the **outermost** wrapper (applied last): `observer(withRouter(MyComponent))` — NOT `withRouter(observer(MyComponent))`
|
|
132
|
+
- [ ] Conditional reading of observables is still observable access — `if (store.isLoaded)` triggers tracking; wrapper is required regardless of conditionality
|
|
133
|
+
|
|
134
|
+
Flags:
|
|
135
|
+
- Component reads `store.*` or `useLocalObservable` result but is not wrapped in `observer` — **blocker**
|
|
136
|
+
- `observer` applied inside another HOC wrapper instead of outside — **major**
|
|
137
|
+
|
|
138
|
+
#### A2. MVVM Boundary (Business Logic in Store, Not Component)
|
|
139
|
+
|
|
140
|
+
- [ ] Business logic MUST live in Store/Service, not in component
|
|
141
|
+
- [ ] IO (API calls, file reads, WebSocket messages) MUST originate from private store methods
|
|
142
|
+
- [ ] Component event handlers must only call store action methods — no logic between the event and the store call
|
|
143
|
+
- [ ] Computed/derived values MUST be `@computed` getters in the store, not inline derivations in the component body
|
|
144
|
+
|
|
145
|
+
Flags:
|
|
146
|
+
- `fetch()` / `axios` / `httpClient` call directly in component (hook or handler) — **blocker**
|
|
147
|
+
- Business logic (conditionals, transformations, validation) inside a component event handler instead of a store method — **major**
|
|
148
|
+
- Derived value computed inline in component that could be a `@computed` getter — **minor**
|
|
149
|
+
|
|
150
|
+
#### A3. useEffect Misuse
|
|
151
|
+
|
|
152
|
+
- [ ] `useEffect` must not contain business logic
|
|
153
|
+
- [ ] `useEffect` must not call `store.init()`, `store.load()`, or `store.onMount()` — lifecycle initialization is the parent store's responsibility
|
|
154
|
+
- [ ] `useEffect` must not contain API calls or IO
|
|
155
|
+
- [ ] `useEffect` used to synchronize component state with store state is a sign the component should be an `observer` instead
|
|
156
|
+
- [ ] Every `useEffect` that creates a subscription, timer, or listener MUST return a cleanup function
|
|
157
|
+
|
|
158
|
+
Flags:
|
|
159
|
+
- `useEffect` calls `store.init()` or `store.loadX()` — **major**
|
|
160
|
+
- `useEffect` contains `fetch()` or IO — **blocker** (API in component)
|
|
161
|
+
- `useEffect` contains business logic / state derivation — **major**
|
|
162
|
+
- `useEffect` creates a subscription/timer/listener with no cleanup return — **major** (memory leak)
|
|
163
|
+
|
|
164
|
+
#### A4. Key Props on Lists
|
|
165
|
+
|
|
166
|
+
- [ ] Every `.map()` rendering React elements MUST have a `key` prop on the root returned element
|
|
167
|
+
- [ ] Keys must be stable, unique identifiers — not array index when the list can reorder or filter
|
|
168
|
+
- [ ] Key must be on the element returned by `.map()`, not a child inside it
|
|
169
|
+
|
|
170
|
+
Flags:
|
|
171
|
+
- Missing `key` prop on list — **major** (causes reconciliation bugs)
|
|
172
|
+
- `key={index}` on a list that can reorder, filter, or paginate — **minor**
|
|
173
|
+
|
|
174
|
+
#### A5. Accessibility Basics
|
|
175
|
+
|
|
176
|
+
- [ ] `<img>` tags MUST have `alt` attribute (can be `alt=""` for decorative images, must be descriptive for content images)
|
|
177
|
+
- [ ] Interactive elements (`<button>`, `<a>`) with no visible text content MUST have `aria-label` or `aria-labelledby`
|
|
178
|
+
- [ ] Form inputs MUST have an associated `<label>` (via `htmlFor` + `id`, or `aria-label`)
|
|
179
|
+
- [ ] `role="button"` on a `<div>` or `<span>` without `tabIndex={0}` and keyboard handler — prefer a real `<button>`
|
|
180
|
+
- [ ] `onClick` on non-interactive elements without keyboard equivalent
|
|
181
|
+
|
|
182
|
+
Flags:
|
|
183
|
+
- `<img>` without `alt` — **major**
|
|
184
|
+
- Interactive element without accessible name — **major**
|
|
185
|
+
- Non-semantic interactive element without keyboard support — **minor**
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
### Part B: MobX Store Patterns
|
|
190
|
+
|
|
191
|
+
#### B1. Store Structure
|
|
192
|
+
|
|
193
|
+
- [ ] Store class MUST call `makeObservable(this)` in the constructor
|
|
194
|
+
- [ ] Observable state MUST use `@observable`, `@observable.shallow`, `@observable.ref`, or `@observable.struct` decorators
|
|
195
|
+
- [ ] Derived values MUST live in `@computed` getters, not recomputed in components or plain methods
|
|
196
|
+
- [ ] `@observable.ref` is preferred for large external objects or objects that manage their own reactivity
|
|
197
|
+
|
|
198
|
+
Flags:
|
|
199
|
+
- `makeObservable(this)` missing from constructor — **blocker**
|
|
200
|
+
- Observable state missing `@observable` decorator — **blocker**
|
|
201
|
+
- Derived value in plain method instead of `@computed` — **minor**
|
|
202
|
+
|
|
203
|
+
#### B2. Member Ordering
|
|
204
|
+
|
|
205
|
+
The canonical class member order (flag deviations):
|
|
206
|
+
|
|
207
|
+
1. `private` fields (internal state, disposers, injected deps as `private readonly`)
|
|
208
|
+
2. Public fields (`@observable`, `readonly`, public plain props)
|
|
209
|
+
3. `constructor`
|
|
210
|
+
4. Public methods: `@computed` getters, lifecycle (`init`, `dispose`, `onMount`, `onUnmount`), public helpers/selectors, public `@action.bound` UI entrypoints
|
|
211
|
+
5. `private` methods
|
|
212
|
+
|
|
213
|
+
Flags:
|
|
214
|
+
- Constructor before field declarations — **minor**
|
|
215
|
+
- Private methods before public methods — **minor**
|
|
216
|
+
- `@action.bound` public method buried among private methods — **minor**
|
|
217
|
+
|
|
218
|
+
#### B3. Member Accessibility Modifiers
|
|
219
|
+
|
|
220
|
+
ESLint rule: `@typescript-eslint/explicit-member-accessibility: ["error", { accessibility: "no-public" }]` — the word `public` is **forbidden** on any class member.
|
|
221
|
+
|
|
222
|
+
Correct accessibility:
|
|
223
|
+
- *(no modifier)*: observable fields, computed getters, lifecycle methods, public helper methods, public `@action.bound` UI methods
|
|
224
|
+
- `private`: internal state (`disposed`, `initialized`, `_value`), helper methods, API-call methods (`fetchX`, `performX`), inter-store callbacks (`onChangeX`, `onFireX`, `handleX`, `syncX`)
|
|
225
|
+
- `private readonly`: constructor-injected dependencies, immutable configuration (`service`, `context`, `id`)
|
|
226
|
+
- `readonly`: immutable public identity fields (`pipelineType`, `contextActions`)
|
|
227
|
+
- `protected`: only in abstract base classes for extension points
|
|
228
|
+
|
|
229
|
+
Decision rule for inter-store callbacks: ask "Is this called from JSX or a React event handler?" If NO — it is `private`.
|
|
230
|
+
|
|
231
|
+
Flags:
|
|
232
|
+
- `public` keyword on any member — **blocker** (ESLint error)
|
|
233
|
+
- `onChangeX`, `onFireX`, `handleX`, `syncX` without `private` — **major**
|
|
234
|
+
- Missing `private` on internal state or helper methods — **major**
|
|
235
|
+
- Missing `private readonly` on injected dependencies — **minor**
|
|
236
|
+
|
|
237
|
+
#### B4. Observable Collections
|
|
238
|
+
|
|
239
|
+
- [ ] `IObservableArray` MUST be mutated in place using MobX methods (`.replace()`, `.push()`, `.splice()`, etc.) inside `runInAction` — never reassigned
|
|
240
|
+
- [ ] `ObservableMap` MUST be mutated using `.set()`, `.delete()`, `.merge()`, `.replace()` — never reassigned
|
|
241
|
+
- [ ] Deep `@observable` on a large external object/instance should use `@observable.ref` instead
|
|
242
|
+
|
|
243
|
+
Flags:
|
|
244
|
+
- `IObservableArray` field reassigned instead of using `.replace()` — **major**
|
|
245
|
+
- `ObservableMap` field reassigned instead of `.replace()` or `.merge()` — **major**
|
|
246
|
+
- Observable mutation outside `runInAction` in async context — **blocker** (Iron Law 1)
|
|
247
|
+
|
|
248
|
+
#### B5. Reactions and Disposers
|
|
249
|
+
|
|
250
|
+
- [ ] Every `autorun`, `reaction`, or `when` created in the store MUST be disposed in `dispose()`
|
|
251
|
+
- [ ] Disposers MUST be stored in `private disposers: IReactionDisposer[]`
|
|
252
|
+
- [ ] `dispose()` MUST call `this.disposers.forEach(d => d())` (or equivalent)
|
|
253
|
+
- [ ] Stores with async operations MUST have a `disposed` guard: check `if (this.disposed) return` after each `await`
|
|
254
|
+
|
|
255
|
+
Flags:
|
|
256
|
+
- `autorun` / `reaction` / `when` without disposer in `dispose()` — **major**
|
|
257
|
+
- Missing `dispose()` in a store that creates reactions — **major**
|
|
258
|
+
- Missing `disposed` guard in async store methods — **major**
|
|
259
|
+
- `private disposers: IReactionDisposer[]` missing when reactions are used — **minor**
|
|
260
|
+
|
|
261
|
+
#### B6. Actions and Async
|
|
262
|
+
|
|
263
|
+
**Public methods (UI entrypoints):**
|
|
264
|
+
- [ ] Public mutating methods called from React components or route handlers MUST be `@action.bound`
|
|
265
|
+
- [ ] Public `@action.bound` methods MUST stay thin: optional guard → delegate to private method
|
|
266
|
+
- [ ] Public non-mutating helpers/selectors must NOT be `@action.bound` (unnecessary and misleading)
|
|
267
|
+
- [ ] Arrow method on a class used as an event handler alternative: acceptable when context must escape but generally prefer `@action.bound`
|
|
268
|
+
|
|
269
|
+
**Private async methods:**
|
|
270
|
+
- [ ] State mutations after `await` MUST be wrapped in `runInAction()`
|
|
271
|
+
- [ ] Private async methods that own loading/error flags MUST use `try/catch/finally`
|
|
272
|
+
- [ ] `catch (err: unknown)` MUST be used — NOT `catch (err: any)` or untyped `catch (err)`
|
|
273
|
+
- [ ] `finally` block MUST reset loading flags (e.g., `this.isLoading = false`) inside `runInAction`
|
|
274
|
+
|
|
275
|
+
Flags:
|
|
276
|
+
- Public UI method missing `@action.bound` — **major**
|
|
277
|
+
- Public helper method marked `@action.bound` but does not mutate state — **minor**
|
|
278
|
+
- Public async action doing API/IO directly instead of delegating to private — **major**
|
|
279
|
+
- State mutation after `await` outside `runInAction` — **blocker** (Iron Law 1)
|
|
280
|
+
- Missing `try/catch/finally` on private async method owning loading flags — **major**
|
|
281
|
+
- `catch (err: any)` instead of `catch (err: unknown)` — **minor**
|
|
282
|
+
|
|
283
|
+
#### B7. Inter-Store Callbacks and Internal Handlers
|
|
284
|
+
|
|
285
|
+
Methods serving as callbacks between stores or internal event handlers MUST be `private`.
|
|
286
|
+
|
|
287
|
+
Patterns that MUST be `private` unless called from JSX:
|
|
288
|
+
- `onChangeEditorState(state)`
|
|
289
|
+
- `onFireExecutorChange()`
|
|
290
|
+
- `onChangeX(value)`
|
|
291
|
+
- `handleX()`
|
|
292
|
+
- `syncX()`
|
|
293
|
+
|
|
294
|
+
The test: "Is this method called from JSX or passed as a React event handler prop?" If NO — it is `private`, full stop.
|
|
295
|
+
|
|
296
|
+
Flags:
|
|
297
|
+
- Public method matching `onChangeX`, `onFireX`, `handleX`, `syncX` naming not called from components — **major**
|
|
298
|
+
- Inter-store callback without `private` — **major**
|
|
299
|
+
- `@action.bound` on a `private` method that is not passed as a callback reference — **minor**
|
|
300
|
+
|
|
301
|
+
#### B8. Bidirectional Sync Bounce Protection
|
|
302
|
+
|
|
303
|
+
When two stores synchronize state in both directions, at least one direction MUST have an equality guard (`if (newValue !== currentValue)`) before writing to the other store. Without this, changes bounce indefinitely.
|
|
304
|
+
|
|
305
|
+
Flags:
|
|
306
|
+
- Bidirectional store sync without equality guard — **blocker**
|
|
307
|
+
- Store A writes to Store B in a callback from Store B without `!==` check — **blocker**
|
|
308
|
+
- Truthy guard (`if (value)`) on optional/nullable field instead of equality check in sync logic — **major**
|
|
309
|
+
|
|
310
|
+
#### B9. API Calls Placement
|
|
311
|
+
|
|
312
|
+
- [ ] API/IO calls belong in `private` store methods only
|
|
313
|
+
- [ ] Public `@action.bound` methods are thin: guard-check → delegate to private method
|
|
314
|
+
- [ ] Components MUST NOT call APIs directly (fetch, axios, httpClient, service.callX) — even inside `useEffect`
|
|
315
|
+
|
|
316
|
+
Flags:
|
|
317
|
+
- API call inside a public `@action.bound` method body — **major**
|
|
318
|
+
- API call in a component (hook, handler, useEffect) — **blocker** (Iron Law 3)
|
|
319
|
+
|
|
320
|
+
#### B10. Lifecycle Initialization and Disposal
|
|
321
|
+
|
|
322
|
+
- [ ] `init()` / `onMount()` of a child store is called from the **parent store's** `init()` / `onMount()`, NOT from a component `useEffect`
|
|
323
|
+
- [ ] Components must NOT trigger store data loading via `useEffect` (e.g., `useEffect(() => { store.load() }, [])`)
|
|
324
|
+
- [ ] Parent store's `onUnmount()` / `dispose()` MUST call `childStore.dispose()` to prevent stale-state updates
|
|
325
|
+
- [ ] Store `dispose()` MUST set `this.disposed = true` before canceling async work
|
|
326
|
+
|
|
327
|
+
Flags:
|
|
328
|
+
- Component `useEffect` calls `store.loadX()`, `store.init()`, or `store.onMount()` — **major**
|
|
329
|
+
- Parent store does not call `child.dispose()` in `onUnmount()` / `dispose()` — **major**
|
|
330
|
+
- Missing `disposed` flag in store with async operations — **major**
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
### Part C: TypeScript Safety
|
|
335
|
+
|
|
336
|
+
- [ ] No `any` type in changed code — use `unknown` + type guards or specific types
|
|
337
|
+
- [ ] No `as any` or `as unknown as T` unsafe double-cast without a comment explaining why
|
|
338
|
+
- [ ] No `!` non-null assertion without a comment proving the value cannot be null/undefined at that point
|
|
339
|
+
- [ ] Props interface MUST use `I` prefix: `interface IMyComponentProps { ... }`
|
|
340
|
+
- [ ] Prefer optional chaining (`?.`) and nullish coalescing (`??`) over `!` assertions
|
|
341
|
+
- [ ] `catch (err: unknown)` — typed error handling, not `catch (err)` or `catch (err: any)`
|
|
342
|
+
|
|
343
|
+
Flags:
|
|
344
|
+
- `any` type in new code — **major**
|
|
345
|
+
- `!` non-null assertion without justification comment — **minor**
|
|
346
|
+
- Props interface without `I` prefix — **minor**
|
|
347
|
+
- `catch (err: any)` — **minor**
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
### Part D: Project-Specific Patterns (populated from CLAUDE.md in Step 0)
|
|
352
|
+
|
|
353
|
+
When Step 0 finds project-specific patterns, apply them here. The examples below are drawn from a real frontend CLAUDE.md and illustrate what to look for and how to apply project conventions.
|
|
354
|
+
|
|
355
|
+
#### D1. `currentState` @computed Pattern
|
|
356
|
+
|
|
357
|
+
Some projects define a canonical `currentState` computed getter for dirty-checking, save, and snapshot:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
@computed get currentState() {
|
|
361
|
+
return toJS({
|
|
362
|
+
name: this.name,
|
|
363
|
+
isEnabled: this.isEnabled,
|
|
364
|
+
// ...
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
- `toJS()` is required when the returned object contains observable arrays or maps
|
|
370
|
+
- `isEqual(this.currentState, savedState)` is the canonical dirty-check pattern
|
|
371
|
+
- If the project defines this pattern, flag its absence in stores that have save/cancel/dirty-check UX — **minor**
|
|
372
|
+
- Returning observables directly from `currentState` without `toJS()` when the result is passed outside the store — **major**
|
|
373
|
+
- Composite stores should compose child stores' `currentState` rather than re-declaring child state — flag manual re-declaration as **minor**
|
|
374
|
+
|
|
375
|
+
#### D2. Composite Store Pattern
|
|
376
|
+
|
|
377
|
+
Projects with root stores holding child stores may define rules for child store reference types:
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
class RootStore {
|
|
381
|
+
// Fixed child stores: plain property (NOT @observable — identity never changes)
|
|
382
|
+
readonly childA = new ChildAStore(this);
|
|
383
|
+
|
|
384
|
+
// Swappable child stores: @observable.shallow (identity can change, internals self-manage)
|
|
385
|
+
@observable.shallow childB: ChildBStore | null = null;
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
- Fixed child stores must NOT be `@observable` — they never change identity; deep observation is wasted overhead — **minor** if violated
|
|
390
|
+
- Swappable stores MUST use `@observable.shallow`, not `@observable` — deep observation of child store internals causes double-tracking — **major** if using `@observable` on swappable stores
|
|
391
|
+
- Context interface (callbacks the child calls back into the parent) should be passed as arrow functions, not raw store references — flag raw store reference leak as **minor**
|
|
392
|
+
|
|
393
|
+
#### D3. Inter-Store Method Style: Arrow Functions vs. @action.bound
|
|
394
|
+
|
|
395
|
+
When a project CLAUDE.md defines which binding style to use for methods passed between stores:
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
// Inter-store callback: arrow function property (auto-bound; no @action.bound needed)
|
|
399
|
+
handleChildChange = (value: string) => {
|
|
400
|
+
runInAction(() => { this.value = value; });
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
// UI entrypoint called from JSX: @action.bound
|
|
404
|
+
@action.bound
|
|
405
|
+
submit() { ... }
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
If the project follows this distinction:
|
|
409
|
+
- Arrow function for store-to-store methods: correct — do NOT flag
|
|
410
|
+
- `@action.bound` on an inter-store method: **minor** (stylistically wrong per project convention, functionally OK)
|
|
411
|
+
- Neither arrow nor `@action.bound` on a mutating method — **major** (Iron Laws still apply regardless of style choice)
|
|
412
|
+
|
|
413
|
+
#### D4. React Hooks to Avoid (MobX Equivalents)
|
|
414
|
+
|
|
415
|
+
When a project CLAUDE.md explicitly forbids certain hooks in favor of MobX equivalents:
|
|
416
|
+
|
|
417
|
+
| Forbidden Pattern | MobX Replacement | Severity if found |
|
|
418
|
+
|-------------------|-----------------|-------------------|
|
|
419
|
+
| `useState` for store-managed state | `@observable` in store | major |
|
|
420
|
+
| `useMemo` for derived store values | `@computed` getter | major |
|
|
421
|
+
| `useCallback` wrapping a store method | `@action.bound` or arrow method | minor |
|
|
422
|
+
|
|
423
|
+
Flag only when the hook manages state that belongs in a store. Local UI-only state (`useState` for a controlled input that never persists) is acceptable.
|
|
424
|
+
|
|
425
|
+
#### D5. Store Initialization in Components
|
|
426
|
+
|
|
427
|
+
When a project defines a canonical store initialization pattern:
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
// Canonical: useLocalObservable with lazy initializer (store created once, not on every render)
|
|
431
|
+
const store = useLocalObservable(() => props.store ?? new ComponentStore(props.service));
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
- `new Store()` directly in the component body — **major** (store recreated on every render)
|
|
435
|
+
- Store created with `useMemo` instead of `useLocalObservable` — **minor** (not observable-aware; `useLocalObservable` is the correct primitive)
|
|
436
|
+
- `useLocalObservable(() => props.store)` when the store is always provided externally is acceptable
|
|
437
|
+
|
|
438
|
+
#### D6. Store Lifecycle Bridge via useEffect
|
|
439
|
+
|
|
440
|
+
When a project routes store lifecycle through `useEffect` as a documented pattern:
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
useEffect(() => {
|
|
444
|
+
store.onMount();
|
|
445
|
+
return () => store.onUnmount();
|
|
446
|
+
}, [store]);
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
This IS the correct lifecycle bridge in projects that use this pattern — do NOT flag as an A3 violation. The A3 rule ("useEffect must not call store.init()") targets implicit data-loading, not explicit lifecycle hooks.
|
|
450
|
+
|
|
451
|
+
Distinction:
|
|
452
|
+
- `useEffect(() => { store.onMount(); return () => store.onUnmount(); }, [store])` — correct lifecycle bridge — **do not flag**
|
|
453
|
+
- `useEffect(() => { store.loadData(); }, [])` — data trigger in component — **major** (A3 violation regardless of project conventions)
|
|
454
|
+
|
|
455
|
+
#### D7. JSX and Naming Conventions
|
|
456
|
+
|
|
457
|
+
When a project CLAUDE.md defines JSX and naming rules:
|
|
458
|
+
|
|
459
|
+
- String props in JSX must use braces: `label={"Save"}` not `label="Save"` — flag as **minor** if the project mandates this
|
|
460
|
+
- Boolean props without explicit value: `<Button disabled />` not `<Button disabled={true} />` — **minor** if the project mandates this
|
|
461
|
+
- Store file naming: `kebab-case.store.ts`; class name ending in `Store` — flag deviations as **minor**
|
|
462
|
+
- FC and ReactNode must be imported from `react`, not from `@types/react` directly — **minor** if project mandates it
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## Output Contract
|
|
467
|
+
|
|
468
|
+
### Class scope — required for `blocker` and `major`
|
|
469
|
+
|
|
470
|
+
Every `blocker` and `major` finding must carry `class_scope`: **every** site that
|
|
471
|
+
holds the shape you found, and **how you enumerated them** — the grep or query
|
|
472
|
+
you ran, or the guard that derives the set.
|
|
473
|
+
|
|
474
|
+
A finding anchored to one `file:line` is a claim about one site. The recorded
|
|
475
|
+
history of this repository is that a fix then repairs that site and leaves its
|
|
476
|
+
siblings: one writer of five, one operator instruction of four, six readers of
|
|
477
|
+
eight. Each was found by the *next* review round, which is why reviews here have
|
|
478
|
+
run to seven and four rounds instead of one.
|
|
479
|
+
|
|
480
|
+
```yaml
|
|
481
|
+
class_scope:
|
|
482
|
+
sites: ["src/lib/shell-config.ts:60", "src/session/store.ts:133"]
|
|
483
|
+
enumeration_method: "grep for the config-path resolvers; 7 writers, 2 unguarded"
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
"I checked the others" is not an enumeration method. A single-entry `sites` list
|
|
487
|
+
is a claim that the class has exactly one member — make it deliberately, because
|
|
488
|
+
`review-finding.schema.json` accepts it and the next round tests it.
|
|
489
|
+
|
|
490
|
+
`minor` and `info` may omit it: enumerating the class for every low-severity
|
|
491
|
+
observation is theatre, not rigour.
|
|
492
|
+
|
|
493
|
+
### Status line (first line of response)
|
|
494
|
+
|
|
495
|
+
```
|
|
496
|
+
STATUS: DONE | DONE_WITH_CONCERNS | NEEDS_CONTEXT | BLOCKED
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
- `DONE` — review complete, findings (if any) are below
|
|
500
|
+
- `DONE_WITH_CONCERNS` — one or more `blocker` or `major` findings found
|
|
501
|
+
- `NEEDS_CONTEXT` — cannot assess a finding without additional context not present in the diff (e.g., parent store file not changed but referenced)
|
|
502
|
+
- `BLOCKED` — cannot run git commands or access the repo
|
|
503
|
+
|
|
504
|
+
### Report structure
|
|
505
|
+
|
|
506
|
+
```markdown
|
|
507
|
+
STATUS: DONE_WITH_CONCERNS
|
|
508
|
+
|
|
509
|
+
## Frontend Review
|
|
510
|
+
|
|
511
|
+
### Scope
|
|
512
|
+
- Branch: `<BRANCH>`
|
|
513
|
+
- Parent ref: `<PARENT>`
|
|
514
|
+
- Merge-base: `<BASE_SHA>`
|
|
515
|
+
- Scope mode: default-with-uncommitted | explicit-hash-range
|
|
516
|
+
- Changed files reviewed: <N>
|
|
517
|
+
|
|
518
|
+
### Summary
|
|
519
|
+
- Blockers: <N>
|
|
520
|
+
- Major: <N>
|
|
521
|
+
- Minor: <N>
|
|
522
|
+
- Info: <N>
|
|
523
|
+
|
|
524
|
+
### Findings
|
|
525
|
+
|
|
526
|
+
### [F-001] Title
|
|
527
|
+
- **Severity**: blocker | major | minor | info
|
|
528
|
+
- **File**: path/to/file.ts:line
|
|
529
|
+
- **Rule**: Part A3 — useEffect Misuse | Part B6 — Actions and Async | etc.
|
|
530
|
+
- **Problem**: what is wrong in the code
|
|
531
|
+
- **Why it matters**: concrete impact (silent non-reactivity, stale state, memory leak, etc.)
|
|
532
|
+
- **Fix**: concrete suggestion
|
|
533
|
+
- **Patch** (optional):
|
|
534
|
+
```diff
|
|
535
|
+
- wrong line
|
|
536
|
+
+ correct line
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Clean Areas
|
|
540
|
+
[List checklist sections with no findings, confirming they were checked]
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### Severity definitions
|
|
544
|
+
|
|
545
|
+
| Severity | Meaning |
|
|
546
|
+
|----------|---------|
|
|
547
|
+
| `blocker` | Silent correctness bug or Iron Law violation; component will not behave correctly or store will corrupt state |
|
|
548
|
+
| `major` | Pattern violation that will cause bugs under realistic usage or future changes |
|
|
549
|
+
| `minor` | Convention deviation or defensive gap; does not cause immediate bugs but reduces maintainability |
|
|
550
|
+
| `info` | Observation worth noting; no concrete bug in current code |
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## Red Flags Table
|
|
555
|
+
|
|
556
|
+
Stop and re-read these rules if you are thinking:
|
|
557
|
+
|
|
558
|
+
| Rationalization | Why it's wrong |
|
|
559
|
+
|---|---|
|
|
560
|
+
| "The store is small, no need for full observer wrapping" | Missing observer() is a blocker regardless of store size — Iron Law 2 |
|
|
561
|
+
| "The mutation happens in a non-async method, so runInAction isn't needed" | Mutations outside action/runInAction are always at least major — Iron Law 1 |
|
|
562
|
+
| "I'll mark the API call in component as minor to avoid friction" | API in component is always a blocker — Iron Law 3 |
|
|
563
|
+
| "The `public` keyword is just a style issue, I'll call it minor" | It's an ESLint error that will fail CI — it is a blocker |
|
|
564
|
+
| "This inter-store callback works fine as public" | Iron Law 5: if it's not called from JSX, it must be private |
|
|
565
|
+
| "No spec compliance check needed for this skill" | Correct — this skill covers Stage 2 (code quality) only; spec compliance is handled by the orchestrator or review-logic |
|
|
566
|
+
| "I can suggest adding useCallback everywhere for safety" | With MobX+observer, useCallback is rarely needed and adds noise; only flag when concretely justified |
|
|
567
|
+
| "The bidirectional sync looks fine, no equality guard needed" | Bidirectional sync without equality guard is a blocker — infinite loop risk |
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
## Job Context Awareness
|
|
572
|
+
|
|
573
|
+
When dispatched by `job-orchestrator` or `review-orchestrator` as part of a job pipeline, the prompt MAY include:
|
|
574
|
+
|
|
575
|
+
```
|
|
576
|
+
JOB_NAME: <job-name>
|
|
577
|
+
CONTEXT_PATH: <JOBS_ROOT>/<job-name>/ai/context.md
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
If provided and the file exists, read the context document before starting the review. Use it to:
|
|
581
|
+
- Understand which MobX version and decorator configuration the project uses (legacy decorators vs. `makeObservable`)
|
|
582
|
+
- Identify custom base store classes or lifecycle conventions that differ from defaults
|
|
583
|
+
- Understand which accessibility standard the project targets (WCAG 2.1 AA vs. custom)
|
|
584
|
+
- Identify intentional patterns that appear to violate rules but are documented exceptions
|
|
585
|
+
- Validate findings against documented project-specific conventions
|
|
586
|
+
|
|
587
|
+
If the file does not exist or is not provided, proceed normally — context is optional and non-blocking.
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
## Orchestrated Review Contract
|
|
591
|
+
|
|
592
|
+
When dispatched by `review-orchestrator`, follow the provided `reviewer-input.schema.json` payload. Return a `REVIEW_RESULT` object compatible with `skills/review-orchestrator/reviewer-finding.schema.json`, then a concise markdown summary. Keep findings evidence-based, include concrete `suggested_fix` for every blocker/major, and return `NEEDS_CONTEXT` instead of guessing when required context is missing.
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|