@skill-graph/cli 0.5.6
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/CHANGELOG.md +247 -0
- package/LICENSE +200 -0
- package/NOTICE +62 -0
- package/README.md +398 -0
- package/SKILL_GRAPH.md +443 -0
- package/bin/skill-graph.js +374 -0
- package/docs/ADOPTION.md +117 -0
- package/docs/CONFORMANCE.md +66 -0
- package/docs/PRIMER.md +384 -0
- package/docs/QUICKSTART-30MIN.md +333 -0
- package/docs/ROUTING-METRICS.md +120 -0
- package/docs/SKILL-MD-FORMAT-COMPATIBILITY.md +127 -0
- package/docs/SKILL_AUDIT_CHECKLIST.md +199 -0
- package/docs/SKILL_AUDIT_LOOP.md +195 -0
- package/docs/SKILL_METADATA_PROTOCOL.md +609 -0
- package/docs/_archived/marketplace-publication-priority-2026-05-18.md +239 -0
- package/docs/adr/0001-predicate-set.md +69 -0
- package/docs/adr/0002-json-ld-context.md +82 -0
- package/docs/adr/0003-ontoclean-rigidity-tags.md +65 -0
- package/docs/adr/0004-persistent-identifiers.md +74 -0
- package/docs/adr/0005-freshness-consolidation.md +70 -0
- package/docs/adr/0006-revise-predicate-rename.md +105 -0
- package/docs/adr/0007-audit-loop-cadence.md +99 -0
- package/docs/adr/0008-skill-surface-split-and-curation-policy.md +93 -0
- package/docs/category-consumers.md +168 -0
- package/docs/concept-map.md +194 -0
- package/docs/diagrams/drift-states.mmd +21 -0
- package/docs/diagrams/manifest-pipeline.mmd +25 -0
- package/docs/diagrams/routing-harness.mmd +41 -0
- package/docs/diagrams/starter-graph.mmd +53 -0
- package/docs/field-decision-guide.md +315 -0
- package/docs/field-rationale.md +211 -0
- package/docs/field-reference.generated.md +624 -0
- package/docs/field-reference.md +1426 -0
- package/docs/glossary.md +190 -0
- package/docs/head-noun-glossary.md +63 -0
- package/docs/images/audit-phases.png +0 -0
- package/docs/images/drift-states.png +0 -0
- package/docs/images/graded-mode.png +0 -0
- package/docs/images/manifest-pipeline.png +0 -0
- package/docs/images/routing-harness.png +0 -0
- package/docs/images/skill-anatomy.png +0 -0
- package/docs/images/starter-graph.png +0 -0
- package/docs/images/system-model.png +0 -0
- package/docs/integrations/github-actions.md +155 -0
- package/docs/manifest-field-mapping.md +443 -0
- package/docs/marketplace-publication-queue.generated.md +240 -0
- package/docs/marketplace-release-agent-prompt.md +82 -0
- package/docs/marketplace-skill-candidate-list.md +272 -0
- package/docs/marketplace-syndication.md +222 -0
- package/docs/migration-sample-review.md +155 -0
- package/docs/migrations/v4-to-v5.md +168 -0
- package/docs/migrations/v5-to-v6.md +221 -0
- package/docs/name-exceptions.yaml +37 -0
- package/docs/plans/marketplace-p1-public-migration-plan.md +41 -0
- package/docs/plans/multi-root-workspace.md +148 -0
- package/docs/plans/scripts-roadmap.md +107 -0
- package/docs/plans/v4-schema-bump.md +160 -0
- package/docs/plans/wave-2-extraction.md +122 -0
- package/docs/positioning-vs-marketplaces.md +175 -0
- package/docs/proposals/skill-audit-loop-positioning.md +160 -0
- package/docs/quality-doctrine.md +138 -0
- package/docs/recommended-skills.md +150 -0
- package/docs/research/skill-comprehension-eval-research.md +1830 -0
- package/docs/research/skill-retrieval-evidence.md +66 -0
- package/docs/skill-metadata-protocol.md +471 -0
- package/docs/skills-sh-maintainer-cleanup-request.md +80 -0
- package/examples/audits/a11y/findings.md +52 -0
- package/examples/audits/a11y/scorecard.md +21 -0
- package/examples/audits/a11y/verdict.md +44 -0
- package/examples/audits/debugging/findings.md +59 -0
- package/examples/audits/debugging/scorecard.md +22 -0
- package/examples/audits/debugging/verdict.md +33 -0
- package/examples/audits/documentation/findings.md +59 -0
- package/examples/audits/documentation/scorecard.md +22 -0
- package/examples/audits/documentation/verdict.md +33 -0
- package/examples/evals/a11y.json +140 -0
- package/examples/evals/api-design.json +52 -0
- package/examples/evals/code-review.json +52 -0
- package/examples/evals/data-modeling.json +52 -0
- package/examples/evals/database-migration.json +52 -0
- package/examples/evals/debugging.json +118 -0
- package/examples/evals/dependency-architecture.json +52 -0
- package/examples/evals/design-system-architecture.json +52 -0
- package/examples/evals/error-tracking.json +52 -0
- package/examples/evals/event-contract-design.json +52 -0
- package/examples/evals/form-ux-architecture.json +52 -0
- package/examples/evals/framework-fit-analysis.json +52 -0
- package/examples/evals/graph-audit.json +139 -0
- package/examples/evals/information-architecture.json +52 -0
- package/examples/evals/interaction-feedback.json +52 -0
- package/examples/evals/interaction-patterns.json +52 -0
- package/examples/evals/layout-composition.json +52 -0
- package/examples/evals/lint-overlay.json +117 -0
- package/examples/evals/microcopy.json +52 -0
- package/examples/evals/observability-modeling.json +52 -0
- package/examples/evals/pattern-recognition.json +96 -0
- package/examples/evals/performance-engineering.json +52 -0
- package/examples/evals/refactor.json +128 -0
- package/examples/evals/semiotics.json +52 -0
- package/examples/evals/skill-infrastructure.json +96 -0
- package/examples/evals/skill-router.json +140 -0
- package/examples/evals/skill-router.routing.json +113 -0
- package/examples/evals/system-interface-contracts.json +52 -0
- package/examples/evals/task-analysis.json +52 -0
- package/examples/evals/testing-strategy.json +118 -0
- package/examples/evals/type-safety.json +249 -0
- package/examples/evals/visual-design-foundations.json +52 -0
- package/examples/evals/webhook-integration.json +52 -0
- package/examples/exports/a11y.skill-md.md +80 -0
- package/examples/exports/debugging.skill-md.md +80 -0
- package/examples/exports/refactor.skill-md.md +78 -0
- package/examples/exports/testing-strategy.skill-md.md +81 -0
- package/examples/projects/markdown-static-site/README.md +115 -0
- package/examples/projects/markdown-static-site/skills/content-source-router/SKILL.md +131 -0
- package/examples/projects/markdown-static-site/skills/image-optimization-pipeline-config/SKILL.md +132 -0
- package/examples/projects/markdown-static-site/skills/link-rot-detection/SKILL.md +103 -0
- package/examples/projects/markdown-static-site/skills/markdown-post-frontmatter-validation/SKILL.md +133 -0
- package/examples/projects/markdown-static-site/skills/migrate-posts-to-v2-frontmatter/SKILL.md +140 -0
- package/examples/projects/saas-stripe-postgres/README.md +208 -0
- package/examples/projects/saas-stripe-postgres/db/migrations/0004_canonicalize_orders.sql +37 -0
- package/examples/projects/saas-stripe-postgres/db/schema.sql +112 -0
- package/examples/projects/saas-stripe-postgres/skills/migrate-orders-to-canonical-schema/SKILL.md +149 -0
- package/examples/projects/saas-stripe-postgres/skills/nextjs-server-action-validation/SKILL.md +154 -0
- package/examples/projects/saas-stripe-postgres/skills/payment-provider-router/SKILL.md +153 -0
- package/examples/projects/saas-stripe-postgres/skills/postgres-rls-pattern/SKILL.md +163 -0
- package/examples/projects/saas-stripe-postgres/skills/stripe-webhook-signature-verification/SKILL.md +137 -0
- package/examples/protocol/skill-metadata-template.md +301 -0
- package/examples/protocol/skills.manifest.sample.json +13245 -0
- package/examples/skill-metadata-template.md +317 -0
- package/examples/skills.manifest.sample.json +13519 -0
- package/examples/tests/v3-1-skos-fixture/SKILL.md +93 -0
- package/marketplace/README.md +17 -0
- package/marketplace/skills/a11y/SKILL.md +66 -0
- package/marketplace/skills/acid-fundamentals/SKILL.md +106 -0
- package/marketplace/skills/agent-engineering/SKILL.md +386 -0
- package/marketplace/skills/agent-eval-design/SKILL.md +55 -0
- package/marketplace/skills/ai-native-development/SKILL.md +294 -0
- package/marketplace/skills/api-design/SKILL.md +60 -0
- package/marketplace/skills/architecture-decision-records/SKILL.md +55 -0
- package/marketplace/skills/background-jobs/SKILL.md +265 -0
- package/marketplace/skills/bounded-context-mapping/SKILL.md +55 -0
- package/marketplace/skills/cap-theorem-tradeoffs/SKILL.md +127 -0
- package/marketplace/skills/client-server-boundary/SKILL.md +187 -0
- package/marketplace/skills/code-review/SKILL.md +120 -0
- package/marketplace/skills/color-system-design/SKILL.md +43 -0
- package/marketplace/skills/component-architecture/SKILL.md +126 -0
- package/marketplace/skills/compression/SKILL.md +112 -0
- package/marketplace/skills/conceptual-modeling/SKILL.md +181 -0
- package/marketplace/skills/connection-pooling/SKILL.md +105 -0
- package/marketplace/skills/constraint-awareness/SKILL.md +287 -0
- package/marketplace/skills/content-monitor/SKILL.md +209 -0
- package/marketplace/skills/context-engineering/SKILL.md +320 -0
- package/marketplace/skills/context-graph/SKILL.md +174 -0
- package/marketplace/skills/context-management/SKILL.md +174 -0
- package/marketplace/skills/context-window/SKILL.md +239 -0
- package/marketplace/skills/contract-testing/SKILL.md +120 -0
- package/marketplace/skills/cron-scheduling/SKILL.md +223 -0
- package/marketplace/skills/dark-mode-implementation/SKILL.md +47 -0
- package/marketplace/skills/data-modeling/SKILL.md +59 -0
- package/marketplace/skills/data-modeling-fundamentals/SKILL.md +117 -0
- package/marketplace/skills/database-migration/SKILL.md +429 -0
- package/marketplace/skills/debugging/SKILL.md +67 -0
- package/marketplace/skills/dependency-architecture/SKILL.md +58 -0
- package/marketplace/skills/design-module-composition/SKILL.md +43 -0
- package/marketplace/skills/design-system-architecture/SKILL.md +61 -0
- package/marketplace/skills/design-thinking/SKILL.md +44 -0
- package/marketplace/skills/diagnosis/SKILL.md +296 -0
- package/marketplace/skills/diff-analysis/SKILL.md +188 -0
- package/marketplace/skills/e2e-test-design/SKILL.md +113 -0
- package/marketplace/skills/entity-relationship-modeling/SKILL.md +218 -0
- package/marketplace/skills/epistemic-grounding/SKILL.md +112 -0
- package/marketplace/skills/error-boundary/SKILL.md +235 -0
- package/marketplace/skills/error-tracking/SKILL.md +261 -0
- package/marketplace/skills/eval-driven-development/SKILL.md +147 -0
- package/marketplace/skills/evaluation/SKILL.md +113 -0
- package/marketplace/skills/event-contract-design/SKILL.md +60 -0
- package/marketplace/skills/event-storming/SKILL.md +56 -0
- package/marketplace/skills/form-ux-architecture/SKILL.md +60 -0
- package/marketplace/skills/framework-fit-analysis/SKILL.md +59 -0
- package/marketplace/skills/frontend-architecture/SKILL.md +43 -0
- package/marketplace/skills/generative-ui/SKILL.md +118 -0
- package/marketplace/skills/graph-audit/SKILL.md +81 -0
- package/marketplace/skills/guardrails/SKILL.md +118 -0
- package/marketplace/skills/hooks-patterns/SKILL.md +185 -0
- package/marketplace/skills/http-semantics/SKILL.md +136 -0
- package/marketplace/skills/ideation/SKILL.md +41 -0
- package/marketplace/skills/indexing-strategy/SKILL.md +108 -0
- package/marketplace/skills/information-architecture/SKILL.md +59 -0
- package/marketplace/skills/integration-test-design/SKILL.md +111 -0
- package/marketplace/skills/intent-recognition/SKILL.md +136 -0
- package/marketplace/skills/interaction-feedback/SKILL.md +59 -0
- package/marketplace/skills/interaction-patterns/SKILL.md +59 -0
- package/marketplace/skills/journey-mapping/SKILL.md +41 -0
- package/marketplace/skills/keywords/SKILL.md +213 -0
- package/marketplace/skills/knowledge-modeling/SKILL.md +232 -0
- package/marketplace/skills/layout-composition/SKILL.md +59 -0
- package/marketplace/skills/linguistics/SKILL.md +429 -0
- package/marketplace/skills/lint-overlay/SKILL.md +76 -0
- package/marketplace/skills/mental-models/SKILL.md +126 -0
- package/marketplace/skills/merge-queue/SKILL.md +94 -0
- package/marketplace/skills/methodology/SKILL.md +317 -0
- package/marketplace/skills/microcopy/SKILL.md +232 -0
- package/marketplace/skills/middleware-patterns/SKILL.md +363 -0
- package/marketplace/skills/mobile-responsive-ux/SKILL.md +287 -0
- package/marketplace/skills/mutation-testing/SKILL.md +112 -0
- package/marketplace/skills/naming-conventions/SKILL.md +112 -0
- package/marketplace/skills/observability-modeling/SKILL.md +59 -0
- package/marketplace/skills/ontology-modeling/SKILL.md +67 -0
- package/marketplace/skills/owasp-security/SKILL.md +153 -0
- package/marketplace/skills/pattern-recognition/SKILL.md +472 -0
- package/marketplace/skills/performance-budgets/SKILL.md +185 -0
- package/marketplace/skills/performance-engineering/SKILL.md +58 -0
- package/marketplace/skills/performance-testing/SKILL.md +125 -0
- package/marketplace/skills/printify/SKILL.md +42 -0
- package/marketplace/skills/prioritization/SKILL.md +118 -0
- package/marketplace/skills/problem-framing/SKILL.md +41 -0
- package/marketplace/skills/problem-locating-solving/SKILL.md +203 -0
- package/marketplace/skills/project-knowledge-extraction/SKILL.md +54 -0
- package/marketplace/skills/prompt-craft/SKILL.md +134 -0
- package/marketplace/skills/prompt-injection-defense/SKILL.md +132 -0
- package/marketplace/skills/property-based-testing/SKILL.md +100 -0
- package/marketplace/skills/prototyping/SKILL.md +43 -0
- package/marketplace/skills/query-optimization/SKILL.md +144 -0
- package/marketplace/skills/real-time-updates/SKILL.md +324 -0
- package/marketplace/skills/ref-patterns/SKILL.md +284 -0
- package/marketplace/skills/refactor/SKILL.md +65 -0
- package/marketplace/skills/rendering-models/SKILL.md +142 -0
- package/marketplace/skills/replication-patterns/SKILL.md +110 -0
- package/marketplace/skills/research-synthesis/SKILL.md +41 -0
- package/marketplace/skills/route-handler-design/SKILL.md +347 -0
- package/marketplace/skills/schema-evolution/SKILL.md +140 -0
- package/marketplace/skills/security-fundamentals/SKILL.md +139 -0
- package/marketplace/skills/semantic-center/SKILL.md +194 -0
- package/marketplace/skills/semantic-relations/SKILL.md +250 -0
- package/marketplace/skills/semantics/SKILL.md +366 -0
- package/marketplace/skills/semiotics/SKILL.md +230 -0
- package/marketplace/skills/seo-strategy/SKILL.md +260 -0
- package/marketplace/skills/server-actions-design/SKILL.md +243 -0
- package/marketplace/skills/server-components-design/SKILL.md +190 -0
- package/marketplace/skills/sharding-strategy/SKILL.md +123 -0
- package/marketplace/skills/shopify/SKILL.md +42 -0
- package/marketplace/skills/skill-infrastructure/SKILL.md +320 -0
- package/marketplace/skills/skill-router/SKILL.md +71 -0
- package/marketplace/skills/skill-scaffold/SKILL.md +105 -0
- package/marketplace/skills/snapshot-testing/SKILL.md +120 -0
- package/marketplace/skills/spec-driven-development/SKILL.md +148 -0
- package/marketplace/skills/state-machine-modeling/SKILL.md +56 -0
- package/marketplace/skills/state-management/SKILL.md +134 -0
- package/marketplace/skills/streaming-architecture/SKILL.md +194 -0
- package/marketplace/skills/summarization/SKILL.md +156 -0
- package/marketplace/skills/suspense-patterns/SKILL.md +265 -0
- package/marketplace/skills/system-interface-contracts/SKILL.md +59 -0
- package/marketplace/skills/task-analysis/SKILL.md +201 -0
- package/marketplace/skills/taxonomy-design/SKILL.md +66 -0
- package/marketplace/skills/test-coverage-strategy/SKILL.md +108 -0
- package/marketplace/skills/test-doubles-design/SKILL.md +98 -0
- package/marketplace/skills/test-driven-development/SKILL.md +96 -0
- package/marketplace/skills/testing-strategy/SKILL.md +67 -0
- package/marketplace/skills/theme-system-design/SKILL.md +43 -0
- package/marketplace/skills/tool-call-flow/SKILL.md +229 -0
- package/marketplace/skills/tool-call-strategy/SKILL.md +292 -0
- package/marketplace/skills/transaction-isolation/SKILL.md +98 -0
- package/marketplace/skills/type-safety/SKILL.md +177 -0
- package/marketplace/skills/typography-system/SKILL.md +43 -0
- package/marketplace/skills/usability-testing/SKILL.md +43 -0
- package/marketplace/skills/user-research/SKILL.md +43 -0
- package/marketplace/skills/vercel-composition-patterns/SKILL.md +157 -0
- package/marketplace/skills/version-control/SKILL.md +233 -0
- package/marketplace/skills/visual-design-foundations/SKILL.md +59 -0
- package/marketplace/skills/visual-hierarchy/SKILL.md +43 -0
- package/marketplace/skills/webhook-integration/SKILL.md +331 -0
- package/marketplace/skills/writing-humanizer/SKILL.md +380 -0
- package/package.json +67 -0
- package/schemas/manifest.schema.json +811 -0
- package/schemas/manifest.v2.schema.json +164 -0
- package/schemas/manifest.v3.schema.json +758 -0
- package/schemas/manifest.v4.schema.json +755 -0
- package/schemas/manifest.v5.schema.json +755 -0
- package/schemas/manifest.v6.schema.json +811 -0
- package/schemas/skill.context.jsonld +279 -0
- package/schemas/skill.schema.json +919 -0
- package/schemas/skill.v2.schema.json +201 -0
- package/schemas/skill.v3.schema.json +827 -0
- package/schemas/skill.v4.schema.json +822 -0
- package/schemas/skill.v5.schema.json +830 -0
- package/schemas/skill.v6.schema.json +946 -0
- package/schemas/vocabulary/keywords.json +180 -0
- package/schemas/vocabulary/workspace_tags.json +23 -0
- package/scripts/__tests__/migrate-skill-v2-to-v3.test.js +161 -0
- package/scripts/__tests__/migrate-skill-v3-to-v4.test.js +158 -0
- package/scripts/__tests__/test-export-parser-drift.js +149 -0
- package/scripts/__tests__/test-marketplace-export.js +114 -0
- package/scripts/__tests__/test-router-paths.js +82 -0
- package/scripts/__tests__/test-stability-promotion.js +244 -0
- package/scripts/__tests__/test-v3-1-alias-contract.js +109 -0
- package/scripts/__tests__/test-v3-1-skos-runtime.js +116 -0
- package/scripts/backfill-schema-version.js +198 -0
- package/scripts/build-field-reference.js +160 -0
- package/scripts/build-retrieval-baseline.js +511 -0
- package/scripts/check-markdown-links.js +211 -0
- package/scripts/check-protocol-consistency.js +979 -0
- package/scripts/export-marketplace-skills.js +610 -0
- package/scripts/export-skill.js +374 -0
- package/scripts/generate-manifest.js +787 -0
- package/scripts/lib/alias-contract.js +83 -0
- package/scripts/lib/audit-prompt-builder.js +771 -0
- package/scripts/lib/mock-grader.js +134 -0
- package/scripts/lib/parse-frontmatter.js +429 -0
- package/scripts/lib/roots.js +119 -0
- package/scripts/lint/check-archetype-sections.js +185 -0
- package/scripts/lint/check-category-enum.js +83 -0
- package/scripts/lint/check-routing-eval.js +146 -0
- package/scripts/lint/check-routing-quality.js +211 -0
- package/scripts/lint/check-stability-promotion.js +220 -0
- package/scripts/lint/format-code-frame.js +206 -0
- package/scripts/marketplace-install.js +125 -0
- package/scripts/migrate-category-to-enum.js +169 -0
- package/scripts/migrate-skill-v2-to-v3.js +424 -0
- package/scripts/migrate-skill-v3-to-v4.js +200 -0
- package/scripts/migrate-skill-v5-to-v6.js +304 -0
- package/scripts/restructure-by-category.js +85 -0
- package/scripts/seed-publication-classification.js +282 -0
- package/scripts/skill-audit.js +893 -0
- package/scripts/skill-graph-drift.js +483 -0
- package/scripts/skill-graph-route.js +766 -0
- package/scripts/skill-graph-routing-eval.js +393 -0
- package/scripts/skill-lint.js +1317 -0
- package/scripts/skill-overlap.js +213 -0
- package/scripts/verify-skill-md-export.js +201 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: generative-ui
|
|
3
|
+
description: "Use when reasoning about the pattern where a language model emits, as structured output, a description of UI components or a UI sub-tree that an application then renders for the user: the typed-schema component palette, the structured-output mechanism (JSON Schema, function-calling) that constrains emission to renderable specs, the application-side render pipeline that turns the spec into pixels, the interaction loop by which user actions on the rendered UI flow back into the next turn, the security boundary between model-author and application-renderer, and the difference between this and adjacent patterns (chat with markdown, prebuilt-widget routing, RSC streaming, model-emits-code). Do NOT use for the page-level rendering taxonomy (use rendering-models), the protocol cycle of tool calls (use tool-call-flow), the trust boundary against untrusted content (use prompt-injection-defense), or general component-library architecture (use design-system-architecture)."
|
|
4
|
+
license: MIT
|
|
5
|
+
allowed-tools: Read Grep
|
|
6
|
+
metadata:
|
|
7
|
+
metadata: "{\"schema_version\":6,\"version\":\"1.0.0\",\"type\":\"capability\",\"category\":\"agent\",\"domain\":\"agent/ui\",\"scope\":\"reference\",\"owner\":\"skill-graph-maintainer\",\"freshness\":\"2026-05-16\",\"drift_check\":\"{\\\\\\\"last_verified\\\\\\\":\\\\\\\"2026-05-16\\\\\\\"}\",\"eval_artifacts\":\"planned\",\"eval_state\":\"unverified\",\"routing_eval\":\"absent\",\"comprehension_state\":\"present\",\"stability\":\"experimental\",\"keywords\":\"[\\\\\\\"generative UI\\\\\\\",\\\\\\\"generative interface\\\\\\\",\\\\\\\"structured output\\\\\\\",\\\\\\\"component schema\\\\\\\",\\\\\\\"typed UI spec\\\\\\\",\\\\\\\"JSON Schema\\\\\\\",\\\\\\\"function calling UI\\\\\\\",\\\\\\\"RSC streaming UI\\\\\\\",\\\\\\\"model-rendered components\\\\\\\",\\\\\\\"assistant UI\\\\\\\",\\\\\\\"chat UI components\\\\\\\"]\",\"triggers\":\"[\\\\\\\"the assistant should show a chart not a paragraph\\\\\\\",\\\\\\\"how does the model render a card\\\\\\\",\\\\\\\"structured output for UI\\\\\\\",\\\\\\\"is it safe to render what the model returned\\\\\\\",\\\\\\\"should this be a tool call or a UI emission\\\\\\\"]\",\"examples\":\"[\\\\\\\"design the component schema for an assistant that can render a date picker, a chart, or a confirmation card depending on the question\\\\\\\",\\\\\\\"decide whether the model should emit a UI spec or call a tool that returns prerendered HTML\\\\\\\",\\\\\\\"explain why the model's output must be schema-validated before rendering\\\\\\\",\\\\\\\"design the interaction loop so a user clicking a button in a model-rendered card produces a follow-up turn the model can reason about\\\\\\\"]\",\"anti_examples\":\"[\\\\\\\"design the JSON shape of an HTTP API endpoint (use api-design)\\\\\\\",\\\\\\\"decide the page-level rendering model (CSR vs SSR vs RSC) (use rendering-models)\\\\\\\",\\\\\\\"design the design-system component library itself (use design-system-architecture)\\\\\\\"]\",\"relations\":\"{\\\\\\\"related\\\\\\\":[\\\\\\\"tool-call-flow\\\\\\\",\\\\\\\"rendering-models\\\\\\\",\\\\\\\"client-server-boundary\\\\\\\",\\\\\\\"prompt-injection-defense\\\\\\\",\\\\\\\"api-design\\\\\\\",\\\\\\\"type-safety\\\\\\\"],\\\\\\\"boundary\\\\\\\":[{\\\\\\\"skill\\\\\\\":\\\\\\\"tool-call-flow\\\\\\\",\\\\\\\"reason\\\\\\\":\\\\\\\"tool-call-flow owns the protocol cycle by which a model invokes external capabilities and receives results; this skill owns the pattern where the model's output is itself a UI specification rendered by the application. The two compose — a UI spec may be emitted via a tool-call-flow-shaped mechanism — but the conceptual surfaces differ.\\\\\\\"},{\\\\\\\"skill\\\\\\\":\\\\\\\"rendering-models\\\\\\\",\\\\\\\"reason\\\\\\\":\\\\\\\"rendering-models owns the page-level rendering taxonomy (CSR/SSR/SSG/RSC/streaming); this skill owns the model→spec→component pipeline that operates inside any of those rendering models. They compose.\\\\\\\"},{\\\\\\\"skill\\\\\\\":\\\\\\\"prompt-injection-defense\\\\\\\",\\\\\\\"reason\\\\\\\":\\\\\\\"prompt-injection-defense owns the security property that a system must preserve against attacker-controlled directives in model input; this skill owns the rendering pattern whose threat surface includes rendering attacker-influenced output. The two skills are read together for security analysis.\\\\\\\"},{\\\\\\\"skill\\\\\\\":\\\\\\\"api-design\\\\\\\",\\\\\\\"reason\\\\\\\":\\\\\\\"api-design owns the external HTTP request/response surface; this skill owns the model-to-renderer schema surface. Both are typed contracts, but between different actors.\\\\\\\"},{\\\\\\\"skill\\\\\\\":\\\\\\\"design-system-architecture\\\\\\\",\\\\\\\"reason\\\\\\\":\\\\\\\"design-system-architecture owns the component library and its tokens; this skill consumes a design system as the component palette the model can draw from.\\\\\\\"}],\\\\\\\"verify_with\\\\\\\":[\\\\\\\"api-design\\\\\\\",\\\\\\\"type-safety\\\\\\\",\\\\\\\"prompt-injection-defense\\\\\\\"]}\",\"mental_model\":\"|\",\"purpose\":\"|\",\"boundary\":\"|\",\"analogy\":\"Generative UI is to a model-rendered interface what a building's framework is to a tenant's customization — the architect (application) lays the structural floor plan, frames the walls, and provides a catalog of approved fixtures (component palette); the tenant (model) picks which fixtures to install where for this particular layout, but cannot punch new holes in load-bearing walls or wire fixtures that don't exist in the catalog. The freedom is in the composition; the safety is in the structure.\",\"misconception\":\"|\",\"concept\":\"{\\\\\\\"definition\\\\\\\":\\\\\\\"Generative UI is the pattern in which a language model emits, as structured output constrained by a typed schema, a specification of a UI component or sub-tree that an application then renders for the user. The model's output is not a chat response, not a tool call asking for execution, and not raw code — it is a typed instance of a component-vocabulary schema. The application owns the rendering, the interaction layer, and the visual design; the model owns the choice of which components to compose and with what data. The pattern depends on three contracts holding simultaneously: the schema (the typed component vocabulary the model and application share), the generation constraint (the model's emission is restricted to valid instances of the schema), and the render policy (the application renders only what the schema describes, with no escape to model-authored markup or code).\\\\\\\",\\\\\\\"mental_model\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"purpose\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"boundary\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"taxonomy\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"analogy\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"misconception\\\\\\\":\\\\\\\"|\\\\\\\"}\",\"skill_graph_source_repo\":\"https://github.com/jacob-balslev/skill-graph\",\"skill_graph_protocol\":\"Skill Metadata Protocol v5\",\"skill_graph_project\":\"Skill Graph\",\"skill_graph_canonical_skill\":\"skills/generative-ui/SKILL.md\"}"
|
|
8
|
+
skill_graph_source_repo: "https://github.com/jacob-balslev/skill-graph"
|
|
9
|
+
skill_graph_protocol: Skill Metadata Protocol v4
|
|
10
|
+
skill_graph_project: Skill Graph
|
|
11
|
+
skill_graph_canonical_skill: skills/generative-ui/SKILL.md
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Generative UI
|
|
15
|
+
|
|
16
|
+
## Coverage
|
|
17
|
+
|
|
18
|
+
The pattern where a language model emits, as structured output constrained by a typed schema, a specification of a UI component or sub-tree that an application then renders for the user. Covers the three load-bearing contracts (component schema, generation constraint, render pipeline), the interaction loop that closes the cycle from user action back into the model's next turn, the trust boundary that makes the rendering safe under adversarial input, the taxonomy by palette openness / generation mechanism / rendering location / interactivity / trust posture, and the distinction from adjacent patterns (chat with markdown, prebuilt-widget routing, RSC streaming as a transport, model-emits-code which is something else).
|
|
19
|
+
|
|
20
|
+
## Philosophy
|
|
21
|
+
|
|
22
|
+
The conventional model-to-user pipeline is: model emits text; user reads text. Generative UI inverts this: model emits a typed component specification; application renders the specification; user sees a UI surface authored by the application's design system but composed by the model.
|
|
23
|
+
|
|
24
|
+
This indirection is what makes the pattern simultaneously safe and expressive. Safe, because the application owns the rendering — the model can only ask the application to render components the application has chosen to expose, with data the schema permits. Expressive, because the model can compose components, choose presentations per response, and adapt to the question at hand without the developer pre-building every variant.
|
|
25
|
+
|
|
26
|
+
The discipline is in the three contracts. The schema must be small enough to be a coherent design vocabulary but expressive enough to cover the assistant's responses. The generation constraint must be reliable enough that the model's emission is always renderable. The render pipeline must enforce schema validation, design-system compliance, and security policies independently of what the model intended. When all three hold, generative UI lets a language model author the choice of what to show without ever touching the rendering surface.
|
|
27
|
+
|
|
28
|
+
## The Three Load-Bearing Contracts
|
|
29
|
+
|
|
30
|
+
| Contract | Owner | Defines | Failure mode if absent |
|
|
31
|
+
|---|---|---|---|
|
|
32
|
+
| Component schema | Application developer | The typed vocabulary the model may emit and the application will render | Model emits unrenderable specs; design inconsistency |
|
|
33
|
+
| Generation constraint | Model + API | The mechanism that forces the model's output to be a valid schema instance | Specs fail validation; retry loops; production flake |
|
|
34
|
+
| Render pipeline | Application | The code that turns a validated spec into pixels with design-system and security policies enforced | Model output reaches the DOM unchecked; security and design break |
|
|
35
|
+
|
|
36
|
+
## Generation Mechanisms Compared
|
|
37
|
+
|
|
38
|
+
| Mechanism | How it works | Reliability | Cost |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| Grammar-constrained decoding | Logits are masked at decode time so only schema-valid tokens emit | Highest — schema-valid by construction | Higher decode cost; requires vendor support |
|
|
41
|
+
| Function calling | Each component is a function in the tool list; props are arguments | High — schema-valid in most cases; occasional mis-typed argument | Standard tool-use latency |
|
|
42
|
+
| Free-form + post-validation | Model emits JSON unconstrained; validator retries on failure | Lowest — retries are common | Cheapest to implement, most variance in production |
|
|
43
|
+
|
|
44
|
+
Production-grade generative UI uses grammar-constrained decoding (OpenAI Structured Outputs, Anthropic tool-use with strict schemas, Gemini response schema) or function calling. Free-form with post-validation should be considered a prototype mechanism.
|
|
45
|
+
|
|
46
|
+
## The Render Pipeline
|
|
47
|
+
|
|
48
|
+
A schema-validated spec is the *input* to the render pipeline, not the output of it. The pipeline performs:
|
|
49
|
+
|
|
50
|
+
1. **Schema validation.** Confirm the spec matches the published JSON Schema or TypeScript type for the component vocabulary. Reject (and either retry or fall back) anything that doesn't.
|
|
51
|
+
2. **Component lookup.** Map the spec's `type` discriminator to the application's registered component implementation. A spec asking for a component the application doesn't ship is a routing error, not a permission to render arbitrary content.
|
|
52
|
+
3. **Props validation.** Validate the spec's props against the component's TypeScript type independently of the schema — defense in depth against schema drift.
|
|
53
|
+
4. **Safety policy.** For every prop that could be a security boundary — image URLs, link targets, embedded content, HTML strings — apply per-component policy (origin allowlist, URL sanitization, length cap, recursion-depth limit). The schema describes structure; the safety policy describes acceptable content.
|
|
54
|
+
5. **Recursive render.** Render the component with the validated props; for nested components in props, recurse through the same pipeline.
|
|
55
|
+
6. **Interaction wiring.** Wire interactive elements (buttons, inputs) to the application's event-routing layer, which encodes user actions as structured events the model can read in its next turn.
|
|
56
|
+
|
|
57
|
+
This pipeline is the entire load-bearing surface of generative UI's safety. The model's "intent" does not authorize rendering; the pipeline does.
|
|
58
|
+
|
|
59
|
+
## The Interaction Loop
|
|
60
|
+
|
|
61
|
+
For interactive generative UI, every interactive component needs three definitions:
|
|
62
|
+
|
|
63
|
+
| Definition | Example for a Confirm button | Why it matters |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| Action shape | `{ kind: 'confirm', component_id: string, accepted: boolean }` | The model needs a typed event in the next turn |
|
|
66
|
+
| Encoding in history | A user-role message with `content: [{ type: 'ui_event', event: <action shape> }]` (Anthropic) or equivalent | The model reads it the same way it reads any other turn |
|
|
67
|
+
| Side-effect policy | Confirming requires an additional tool call gated by user identity, never auto-executed from the click | The click is a user signal, not authorization for the destructive operation |
|
|
68
|
+
|
|
69
|
+
A generative UI with interactive components but no interaction-loop definition is one-way: the user clicks and nothing happens. A generative UI that auto-executes destructive actions on click is a prompt-injection-defense failure waiting to happen. The middle path — click produces a structured event the model reasons about, the model emits a tool call that goes through normal authorization — is the discipline.
|
|
70
|
+
|
|
71
|
+
## Vendor And Framework Examples
|
|
72
|
+
|
|
73
|
+
| Implementation | Provided by | Mechanism |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| OpenAI Structured Outputs | OpenAI | Grammar-constrained decoding against a JSON Schema |
|
|
76
|
+
| OpenAI Assistants tools | OpenAI | Function calling where each function returns a UI fragment |
|
|
77
|
+
| Anthropic tool use with strict schemas | Anthropic | Function-calling-style tool list with schema-constrained inputs |
|
|
78
|
+
| Gemini response schema | Google | Response constrained to a typed schema |
|
|
79
|
+
| Vercel AI SDK `streamUI` | Vercel | RSC streaming of components selected by function calling |
|
|
80
|
+
| LangChain structured chat | LangChain | Pydantic-typed structured output |
|
|
81
|
+
| OpenRouter / generic JSON mode | Multiple | Free-form JSON with post-validation, falling back to retry |
|
|
82
|
+
|
|
83
|
+
Citing one vendor's API as the canonical pattern is a category error; the pattern predates and outlives any single implementation. Use whichever mechanism the chosen model supports most reliably.
|
|
84
|
+
|
|
85
|
+
## Verification
|
|
86
|
+
|
|
87
|
+
After applying this skill, verify:
|
|
88
|
+
- [ ] The component palette is a published, typed schema (JSON Schema, TypeScript discriminated union, or equivalent) — not an informal convention.
|
|
89
|
+
- [ ] The generation mechanism is grammar-constrained decoding or function calling — not free-form-with-retry in production.
|
|
90
|
+
- [ ] Every spec the model emits is validated against the schema by the render pipeline before any component is invoked — the model's emission alone does not authorize rendering.
|
|
91
|
+
- [ ] Per-component safety policies are enforced: image URLs pass an origin allowlist; link targets are sanitized; content-length is bounded; nested specs terminate in finite depth.
|
|
92
|
+
- [ ] Every interactive component has a defined action shape, history encoding, and side-effect policy. Auto-executing destructive actions on rendered-component clicks is forbidden.
|
|
93
|
+
- [ ] The render pipeline never executes model-authored markup, HTML, or code. The only thing the model authors is a typed selection from the palette.
|
|
94
|
+
- [ ] The pattern is used for open-ended assistant responses, not for known repeated workflows where traditional UI design is the better fit.
|
|
95
|
+
- [ ] Accessibility (keyboard navigation, ARIA roles, focus management) is the responsibility of the application's component implementations — generative UI does not produce accessible UI for free, only delegates it to the design system.
|
|
96
|
+
|
|
97
|
+
## Do NOT Use When
|
|
98
|
+
|
|
99
|
+
| Instead of this skill | Use | Why |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| Designing the page-level rendering model (CSR vs SSR vs RSC vs streaming) | `rendering-models` | rendering-models owns the page-rendering taxonomy; this skill operates inside any of those models |
|
|
102
|
+
| Designing the protocol cycle of a tool call | `tool-call-flow` | tool-call-flow owns the model↔runtime cycle; this skill owns the model→render-pipeline pattern |
|
|
103
|
+
| Defending against attacker-controlled directives in model input | `prompt-injection-defense` | prompt-injection-defense owns the security property; this skill owns the rendering pattern that must preserve it |
|
|
104
|
+
| Designing the component library itself (tokens, primitives, composition) | `design-system-architecture` | design-system-architecture owns the library; this skill consumes it as the palette |
|
|
105
|
+
| Designing the JSON shape of an HTTP API endpoint | `api-design` | api-design owns the request/response surface; this skill owns the model-to-renderer schema |
|
|
106
|
+
| Evaluating model accuracy on a specific task | `eval-driven-development` | eval-driven-development owns measurement; this skill owns the pattern being evaluated |
|
|
107
|
+
|
|
108
|
+
## Key Sources
|
|
109
|
+
|
|
110
|
+
- React Team. [Server Components RFC](https://github.com/reactjs/rfcs/blob/main/text/0188-server-components.md). The architectural basis for streaming UI from server to client used by several generative-UI implementations.
|
|
111
|
+
- OpenAI. [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Canonical reference for grammar-constrained decoding against JSON Schema — one of the primary mechanisms for the generation-constraint contract.
|
|
112
|
+
- Anthropic. [Tool use overview](https://docs.anthropic.com/en/docs/build-with-claude/tool-use). Tool-use with input schemas as a function-calling-style mechanism for emitting typed UI specs.
|
|
113
|
+
- JSON Schema. [Draft 2020-12 specification](https://json-schema.org/draft/2020-12/json-schema-core). The schema language commonly used to type the component palette.
|
|
114
|
+
- Google. [Gemini structured output / response schema documentation](https://ai.google.dev/gemini-api/docs/structured-output). Third-vendor implementation of the same generation-constraint contract.
|
|
115
|
+
- Vercel. [AI SDK `streamUI` documentation](https://sdk.vercel.ai/docs/ai-sdk-rsc/streaming-react-components). One implementation example of the pattern delivered over React Server Components streaming — cited as a worked implementation, not as the pattern itself.
|
|
116
|
+
- Nielsen Norman Group. [Generative UI and Outcome-Oriented Design](https://www.nngroup.com/articles/generative-ui/). Practitioner framing of where generative UI fits in the broader UX landscape.
|
|
117
|
+
- Schick, T., et al. (2023). ["Toolformer: Language Models Can Teach Themselves to Use Tools"](https://arxiv.org/abs/2302.04761). Background on the structured-emission research thread that enabled reliable typed model outputs.
|
|
118
|
+
- Karpathy, A. [LLM OS framing](https://twitter.com/karpathy/status/1723140519554105733). Conceptual framing in which generative UI is one of the rendering surfaces of an LLM-as-OS — useful for situating the pattern in a broader architecture.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: graph-audit
|
|
3
|
+
description: "Use when checking that every SKILL.md conforms to the schema, that manifest entries match authored frontmatter, or that relation targets point at real sibling skills. Covers schema conformance, manifest sync, relation integrity, eval-artifact coherence, grounding presence, and name-directory parity. Do NOT use for general code review, runtime agent debugging, or auditing non-skill files."
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: "Markdown, JSON Schema, Node.js"
|
|
6
|
+
allowed-tools: Read Grep Bash
|
|
7
|
+
metadata:
|
|
8
|
+
metadata: "{\"schema_version\":6,\"version\":\"1.0.0\",\"type\":\"capability\",\"category\":\"quality\",\"domain\":\"quality/audit\",\"scope\":\"codebase\",\"owner\":\"skill-graph-maintainer\",\"freshness\":\"2026-04-18\",\"drift_check\":\"{\\\\\\\"last_verified\\\\\\\":\\\\\\\"2026-05-13\\\\\\\",\\\\\\\"truth_source_hashes\\\\\\\":{\\\\\\\"schemas/skill.schema.json\\\\\\\":\\\\\\\"370a021a129cba5b54cd15daaaa934fbb172df306dc0095608ea4a5607fe2526\\\\\\\",\\\\\\\"schemas/manifest.schema.json\\\\\\\":\\\\\\\"b5181764e0b645d01a8b6918c78463e53a2f28669a6883365c3a1d132323c066\\\\\\\",\\\\\\\"docs/skill-metadata-protocol.md\\\\\\\":\\\\\\\"bce8933a4f4f6386e36e618f2de97f0f6feb864a4c1aaeec225291110e7f8a76\\\\\\\",\\\\\\\"scripts/skill-lint.js\\\\\\\":\\\\\\\"3a78f75f8921542b91dc619cd41bde29bf379de3c16bdcf3653c854ecbe9fa29\\\\\\\",\\\\\\\"scripts/lib/alias-contract.js\\\\\\\":\\\\\\\"ab7b4f15c13caf1ff1f3205e285415b086f7b6cbc3fcfaba982a590cc56b49cd\\\\\\\",\\\\\\\"scripts/check-protocol-consistency.js\\\\\\\":\\\\\\\"0ff39406d36e7a9e51c176f657f4f426d8bd5a3fe6411d28b9e9a93dc7d89f29\\\\\\\",\\\\\\\"scripts/generate-manifest.js\\\\\\\":\\\\\\\"9d7bbbdae440fdb1763d61ffa7bda10c9efae92359d1c2139d0e971582d59e0e\\\\\\\",\\\\\\\"examples/evals/graph-audit.json\\\\\\\":\\\\\\\"8edab7bc057c65c8fd43f6ca17863c7a12ea831f6eb2158f1b2fde2ba03ad4b2\\\\\\\"}}\",\"eval_artifacts\":\"present\",\"eval_state\":\"passing\",\"routing_eval\":\"present\",\"stability\":\"experimental\",\"keywords\":\"[\\\\\\\"skill audit\\\\\\\",\\\\\\\"manifest audit\\\\\\\",\\\\\\\"schema validation\\\\\\\",\\\\\\\"skill consistency\\\\\\\",\\\\\\\"graph audit\\\\\\\",\\\\\\\"metadata check\\\\\\\",\\\\\\\"skill frontmatter check\\\\\\\",\\\\\\\"broken relation\\\\\\\",\\\\\\\"skill drift\\\\\\\",\\\\\\\"audit my skills\\\\\\\"]\",\"triggers\":\"[\\\\\\\"graph-audit\\\\\\\"]\",\"paths\":\"[\\\\\\\"skills/**/SKILL.md\\\\\\\",\\\\\\\"schemas/*.json\\\\\\\",\\\\\\\"examples/skills.manifest.sample.json\\\\\\\"]\",\"examples\":\"[\\\\\\\"audit all skills for schema conformance and broken relation targets\\\\\\\",\\\\\\\"the manifest sample drifted from the generator — find the mismatch\\\\\\\",\\\\\\\"check that every `scope: codebase` skill has a populated grounding block\\\\\\\",\\\\\\\"which skills declare a relations target that doesn't exist in the library?\\\\\\\"]\",\"anti_examples\":\"[\\\\\\\"diagnose why the @/components import cycle broke the build\\\\\\\",\\\\\\\"my agent is stuck in a loop — what's wrong?\\\\\\\",\\\\\\\"write a reference doc explaining what the lint-checker pipeline does\\\\\\\"]\",\"relations\":\"{\\\\\\\"boundary\\\\\\\":[{\\\\\\\"skill\\\\\\\":\\\\\\\"refactor\\\\\\\",\\\\\\\"reason\\\\\\\":\\\\\\\"refactor changes skill body structure; graph-audit is read-only metadata verification\\\\\\\"},{\\\\\\\"skill\\\\\\\":\\\\\\\"debugging\\\\\\\",\\\\\\\"reason\\\\\\\":\\\\\\\"debugging chases a specific runtime failure; graph-audit is bulk static verification of every skill\\\\\\\"}],\\\\\\\"verify_with\\\\\\\":[\\\\\\\"testing-strategy\\\\\\\"]}\",\"grounding\":\"{\\\\\\\"domain_object\\\\\\\":\\\\\\\"Skill Metadata Protocol and Skill Graph manifest consistency\\\\\\\",\\\\\\\"grounding_mode\\\\\\\":\\\\\\\"repo_specific\\\\\\\",\\\\\\\"truth_sources\\\\\\\":[\\\\\\\"schemas/skill.schema.json\\\\\\\",\\\\\\\"schemas/manifest.schema.json\\\\\\\",\\\\\\\"docs/skill-metadata-protocol.md\\\\\\\",\\\\\\\"scripts/skill-lint.js\\\\\\\",\\\\\\\"scripts/lib/alias-contract.js\\\\\\\",\\\\\\\"scripts/check-protocol-consistency.js\\\\\\\",\\\\\\\"scripts/generate-manifest.js\\\\\\\",\\\\\\\"examples/evals/graph-audit.json\\\\\\\"],\\\\\\\"failure_modes\\\\\\\":[\\\\\\\"schema_drift\\\\\\\",\\\\\\\"manifest_sample_out_of_sync\\\\\\\",\\\\\\\"broken_relation_targets\\\\\\\",\\\\\\\"eval_artifacts_mismatch\\\\\\\",\\\\\\\"name_directory_mismatch\\\\\\\"],\\\\\\\"evidence_priority\\\\\\\":\\\\\\\"repo_code_first\\\\\\\"}\",\"skill_graph_source_repo\":\"https://github.com/jacob-balslev/skill-graph\",\"skill_graph_protocol\":\"Skill Metadata Protocol v5\",\"skill_graph_project\":\"Skill Graph\",\"skill_graph_canonical_skill\":\"skills/graph-audit/SKILL.md\"}"
|
|
9
|
+
skill_graph_source_repo: "https://github.com/jacob-balslev/skill-graph"
|
|
10
|
+
skill_graph_protocol: Skill Metadata Protocol v4
|
|
11
|
+
skill_graph_project: Skill Graph
|
|
12
|
+
skill_graph_canonical_skill: skills/graph-audit/SKILL.md
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Graph Audit
|
|
16
|
+
|
|
17
|
+
## Coverage
|
|
18
|
+
|
|
19
|
+
- Schema conformance: checking that every `skills/<name>/SKILL.md` validates against `schemas/skill.schema.json` without errors
|
|
20
|
+
- Manifest sync: verifying that `examples/skills.manifest.sample.json` matches the output of `scripts/generate-manifest.js` run against the current skills
|
|
21
|
+
- Relation integrity: confirming that every target named under `relations.*` corresponds to a real sibling skill directory and uses the right predicate semantics (`related`/`broader`/`boundary`/`disjoint_with`/`verify_with`/`depends_on`)
|
|
22
|
+
- Eval artifact coherence: ensuring that `eval_artifacts: present` is backed by a real eval artifact under `examples/evals/` that names the skill in its `skill_name` field
|
|
23
|
+
- Grounding presence: confirming that every `scope: codebase` skill has a fully populated `grounding` block with `domain_object`, `grounding_mode`, `truth_sources`, `failure_modes`, and `evidence_priority`
|
|
24
|
+
- Name-directory parity: checking that a skill's `name` field matches the name of the parent directory (required for SKILL.md compatibility)
|
|
25
|
+
|
|
26
|
+
## Philosophy
|
|
27
|
+
|
|
28
|
+
Skill graphs fail silently. A broken relation or a drifted enum value does not crash the agent — it just makes retrieval subtly wrong, and subtly-wrong retrieval is worse than a crash because nothing tells you to look. The audit's job is to turn every silent bug into a loud one before the graph accumulates enough drift that agents can no longer trust its edges.
|
|
29
|
+
|
|
30
|
+
## Key Files
|
|
31
|
+
|
|
32
|
+
| File | Line range | Purpose |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `schemas/skill.schema.json` | whole file | Enforces the frontmatter schema for every SKILL.md |
|
|
35
|
+
| `schemas/manifest.schema.json` | whole file | Enforces the compiled manifest shape |
|
|
36
|
+
| `docs/skill-metadata-protocol.md` | §§ Archetype, Requiredness, Schema Versioning | Source of truth for field semantics and the archetype section map |
|
|
37
|
+
| `scripts/skill-lint.js` | 91–114 (`AUTHORED_FIELDS_MUST_FLOW`), 149–202 (`checkSchemaParity`), 175–250 (`validateAgainstSchema`) | The canonical audit runner. Implements the six dimensions listed in Coverage plus five more: parent-directory-matches-name, cross-schema parity, sample-manifest conformance, generator parity, and routing-quality rules. See README § Validation for the full eleven-check list. |
|
|
38
|
+
| `scripts/lib/alias-contract.js` | whole file | Shared v3.1 alias-parity guard used by lint and manifest generation so preferred/legacy fields cannot diverge silently |
|
|
39
|
+
| `scripts/check-protocol-consistency.js` | C1–C7 checks | Cross-artifact protocol checker. Complementary to `skill-lint.js` — lint validates per-skill correctness; this validates that the protocol documents themselves remain consistent with the schemas. |
|
|
40
|
+
| `examples/skills.manifest.sample.json` | whole file | Generator-produced sample; lint fails if this drifts from `generate-manifest.js` output |
|
|
41
|
+
|
|
42
|
+
## Evals
|
|
43
|
+
|
|
44
|
+
This skill ships a comprehension-eval artifact at [`examples/evals/graph-audit.json`](https://github.com/jacob-balslev/skill-graph/blob/main/examples/evals/graph-audit.json) covering all six audit dimensions listed under Coverage. The `Verification` checklist below is the deterministic per-file audit gate; the eval file is how this skill's concept comprehension is graded by `scripts/skill-audit.js --graded`.
|
|
45
|
+
|
|
46
|
+
## Verification
|
|
47
|
+
|
|
48
|
+
Run the lint script to execute all audit checks:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
node scripts/skill-lint.js
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For a single skill:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
node scripts/skill-lint.js skills/<name>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
For the full audit including the skill-metadata-template:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
node scripts/skill-lint.js --include-template
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Exit code 0 means all checks passed. Exit code 1 means at least one check failed; each failure identifies the specific file and check.
|
|
67
|
+
|
|
68
|
+
- [ ] All SKILL.md files pass schema validation
|
|
69
|
+
- [ ] Manifest sample matches generator output
|
|
70
|
+
- [ ] All relation targets exist as real sibling skill directories
|
|
71
|
+
- [ ] All `eval_artifacts: present` skills have a matching eval artifact
|
|
72
|
+
- [ ] All `scope: codebase` skills have a complete `grounding` block
|
|
73
|
+
- [ ] Every skill's `name` field matches its parent directory name (SKILL.md compatibility)
|
|
74
|
+
|
|
75
|
+
## Do NOT Use When
|
|
76
|
+
|
|
77
|
+
| Use instead | When |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `documentation` | The task is authoring or restructuring skill prose, not auditing metadata |
|
|
80
|
+
| `refactor` | The task is restructuring skill body sections while keeping the contract stable |
|
|
81
|
+
| `debugging` | The task is chasing a runtime failure in an agent, not validating graph metadata |
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: guardrails
|
|
3
|
+
description: "Use when planning or executing operations that touch protected files, credentials, destructive git commands, destructive SQL, PII, secrets, or irreversible system mutations. Covers proactive policy plus reactive pattern blocking for dangerous operations, data exfiltration, and unsafe mutations. Do NOT use for application input validation, user RBAC, or general code logic review (use `code-review`)."
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: "Markdown, Git, agent-skill runtimes"
|
|
6
|
+
allowed-tools: Read Grep Bash
|
|
7
|
+
metadata:
|
|
8
|
+
metadata: "{\"schema_version\":6,\"version\":\"1.0.0\",\"type\":\"capability\",\"category\":\"quality\",\"domain\":\"quality/safety\",\"scope\":\"portable\",\"owner\":\"skill-graph-maintainer\",\"freshness\":\"2026-03-28\",\"drift_check\":\"{\\\\\\\"last_verified\\\\\\\":\\\\\\\"2026-03-28\\\\\\\"}\",\"eval_artifacts\":\"planned\",\"eval_state\":\"unverified\",\"routing_eval\":\"absent\",\"stability\":\"experimental\",\"keywords\":\"[\\\\\\\"guardrails\\\\\\\",\\\\\\\"tripwire\\\\\\\",\\\\\\\"safety gate\\\\\\\",\\\\\\\"force push\\\\\\\",\\\\\\\"secret detection\\\\\\\",\\\\\\\"destructive action\\\\\\\",\\\\\\\"protected files\\\\\\\",\\\\\\\"circuit breaker\\\\\\\"]\",\"triggers\":\"[\\\\\\\"guardrails-skill\\\\\\\",\\\\\\\"security-skill\\\\\\\"]\",\"relations\":\"{\\\\\\\"related\\\\\\\":[\\\\\\\"intent-recognition\\\\\\\"]}\",\"portability\":\"{\\\\\\\"readiness\\\\\\\":\\\\\\\"scripted\\\\\\\",\\\\\\\"targets\\\\\\\":[\\\\\\\"skill-md\\\\\\\"]}\",\"lifecycle\":\"{\\\\\\\"stale_after_days\\\\\\\":90,\\\\\\\"review_cadence\\\\\\\":\\\\\\\"quarterly\\\\\\\"}\",\"skill_graph_source_repo\":\"https://github.com/jacob-balslev/skill-graph\",\"skill_graph_protocol\":\"Skill Metadata Protocol v5\",\"skill_graph_project\":\"Skill Graph\",\"skill_graph_canonical_skill\":\"skills/guardrails/SKILL.md\"}"
|
|
9
|
+
skill_graph_source_repo: "https://github.com/jacob-balslev/skill-graph"
|
|
10
|
+
skill_graph_protocol: Skill Metadata Protocol v4
|
|
11
|
+
skill_graph_project: Skill Graph
|
|
12
|
+
skill_graph_canonical_skill: skills/guardrails/SKILL.md
|
|
13
|
+
---
|
|
14
|
+
# Guardrails
|
|
15
|
+
|
|
16
|
+
## Domain Context
|
|
17
|
+
|
|
18
|
+
**What is this skill?** This skill provides a unified framework for proactive and reactive agent safety. It bridges agent-governance (proactive policy) and tripwire-guardrails.py (reactive pattern blocking) to prevent dangerous operations, data exfiltration, and irreversible system mutations. Use when planning operations that touch protected files (.env, credentials), performing git mutations (force push, reset), running destructive SQL, or working with PII and secrets. Do NOT use for application-level input validation (use zod-validation) or user RBAC (use nextauth-patterns). Do NOT use for general code logic review (use code-logic).
|
|
19
|
+
|
|
20
|
+
> The safety layer that catches what logic misses. Guardrails are the final circuit breaker between intent and execution.
|
|
21
|
+
|
|
22
|
+
## Key Files
|
|
23
|
+
|
|
24
|
+
| File | Purpose |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `agent-orchestration/logs/tripwire.jsonl` | audit-traceability**: Every guardrail trigger is an immutable log event in . |
|
|
27
|
+
| `scripts/hooks/tripwire-guardrails.py` | > **Source:** |
|
|
28
|
+
## Coverage
|
|
29
|
+
|
|
30
|
+
This skill covers the two-layer defense model (proactive governance + reactive tripwires), protected operations for git mutations (force push, hard reset, clean), filesystem and secret detection (`.env` writes, API key patterns, private key blocks), SQL safety (unbounded DELETE/UPDATE, DROP TABLE), the three enforcement tiers (CRITICAL/HIGH/WARN with exit codes), the verification protocol for pre-checking high-risk operations, and drift traps where agents attempt to bypass safety gates. It bridges `agent-governance` (proactive policy) with `tripwire-guardrails.py` (reactive pattern blocking).
|
|
31
|
+
|
|
32
|
+
## Philosophy
|
|
33
|
+
|
|
34
|
+
Agents with broad tool access will eventually execute dangerous operations -- not from malice but from inference errors, ambiguous instructions, or optimistic assumptions about reversibility. Guardrails exist to make the irreversible harder to reach than the safe alternative. The two-layer model ensures that even when governance approves an intent, the reactive tripwire layer still scans the actual action for secrets, destructive patterns, and protected file writes. Without this skill, agents default to "allowed means safe" -- which is how secrets get committed, production tables get dropped, and force pushes destroy remote history.
|
|
35
|
+
|
|
36
|
+
## Cross-Domain Synergy
|
|
37
|
+
Guardrails provide the enforcement layer for all high-risk operations:
|
|
38
|
+
- **agent-governance**: Proactively declares what is allowed; Guardrails reactively blocks what is dangerous even if "allowed" (e.g., a regex match for a secret in a permitted file write).
|
|
39
|
+
- **deterministic**: Enforces that mutations are not only correct but also safe and traceable.
|
|
40
|
+
- **audit-traceability**: Every guardrail trigger is an immutable log event in `agent-orchestration/logs/tripwire.jsonl`.
|
|
41
|
+
|
|
42
|
+
## 1. The Two Layers of Defense
|
|
43
|
+
|
|
44
|
+
| Layer | Type | Mechanism | Focus |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| **Governance** | Proactive | Policy files (JSON) | Intent, Trust, Permissions |
|
|
47
|
+
| **Guardrails** | Reactive | regex patterns (Python) | Arguments, Content, Side-effects |
|
|
48
|
+
|
|
49
|
+
The canonical sequence: Governance approves the **Intent** -> Hook runner fires Guardrails -> Guardrails inspects the **Action**.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 2. Protected Operations (Tripwires)
|
|
54
|
+
|
|
55
|
+
Any operation matching these patterns triggers a block or high-severity warning.
|
|
56
|
+
|
|
57
|
+
### Git Mutations
|
|
58
|
+
- **Force Push**: `git push --force` or `-f` is hard-blocked. Use `--force-with-lease` or request explicit user bypass.
|
|
59
|
+
- **Hard Reset**: `git reset --hard` is blocked if it discards uncommitted work in non-tmp directories.
|
|
60
|
+
- **Clean**: `git clean -f` requires verification of untracked files.
|
|
61
|
+
|
|
62
|
+
### Filesystem & Secrets
|
|
63
|
+
- **Protected Files**: Writes to `.env*`, `credentials.json`, `id_rsa`, or any `.pem`/`.key` files are critical-blocked.
|
|
64
|
+
- **Secret Detection**: The content of every `Write` call is scanned for:
|
|
65
|
+
- OpenAI/Anthropic keys (`sk-...`)
|
|
66
|
+
- GitHub tokens (`ghp_...`)
|
|
67
|
+
- Stripe live keys (`sk_live_...`)
|
|
68
|
+
- Private key block sentinels (`BEGIN ... PRIVATE KEY`)
|
|
69
|
+
|
|
70
|
+
### SQL Execution
|
|
71
|
+
- **Unbounded Mutation**: `DELETE FROM` or `UPDATE` without a `WHERE` clause is blocked.
|
|
72
|
+
- **Schema Destruction**: `DROP TABLE` or `ALTER TABLE ... DROP COLUMN` is blocked in production contexts.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 3. Enforcement Tiers
|
|
77
|
+
|
|
78
|
+
| Tier | Exit Code | Action | User Message |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| **CRITICAL** | 1 | Hard Block | "TRIPWIRE [CRITICAL]: [Reason]. Operation aborted." |
|
|
81
|
+
| **HIGH** | 1 | Hard Block | "TRIPWIRE [HIGH]: Avoid this pattern. Use [Alternative]." |
|
|
82
|
+
| **WARN** | 2 | Soft Warning | "ADVISORY: This pattern is risky. Proceed with caution." |
|
|
83
|
+
|
|
84
|
+
> **Source:** `scripts/hooks/tripwire-guardrails.py`
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Verification
|
|
89
|
+
|
|
90
|
+
Before performing a high-risk operation, run the **Guardrails Pre-Check**:
|
|
91
|
+
|
|
92
|
+
1. **Scan for Secrets**: Manually grep your proposed output for any strings matching secret patterns.
|
|
93
|
+
2. **Path Verification**: Confirm the target path is not in the `PROTECTED_FILE_PATTERNS` list.
|
|
94
|
+
3. **Intent Alignment**: Ensure your `agent-governance` intent (read-only/mutation/destructive) matches the risk tier of the action.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 5. Drift Traps
|
|
99
|
+
|
|
100
|
+
| Trap | Why it fails | Correct Approach |
|
|
101
|
+
|---|---|---|
|
|
102
|
+
| Bypassing hooks with `--no-verify` | This is a guardrail violation in itself. | Fix the underlying issue that triggers the hook. |
|
|
103
|
+
| Using Bash to edit secrets | Evasion via `sed` or `perl` is still caught by content tripwires. | Use the `Edit` tool so the system can track the diff. |
|
|
104
|
+
| Assuming "allowed" means "safe" | An agent with `destructive` permission can still commit a secret by accident. | Guardrails scan content regardless of permission tier. |
|
|
105
|
+
|
|
106
|
+
## Do NOT Use When
|
|
107
|
+
|
|
108
|
+
| Instead of this skill | Use | Why |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| Application-level input validation (form fields, Zod schemas) | `zod-validation` | Guardrails protects the agent layer; Zod protects the application layer |
|
|
111
|
+
| User RBAC, session auth, route protection | `nextauth-patterns` | Auth concerns are application-level, not agent-safety-level |
|
|
112
|
+
| General code logic review (TypeScript correctness) | `code-logic` | Code review catches logic bugs; guardrails catches dangerous operations |
|
|
113
|
+
| Writing or debugging hook implementation code | `hook-patterns` | Hook-patterns owns how hooks are built; guardrails describes what they enforce |
|
|
114
|
+
| Proactive agent policy declaration (trust scores, intent classification) | `agent-governance` | Governance declares what is allowed; guardrails reactively blocks what is dangerous |
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
*Version 1.1.0 — Updated 2026-03-28. Added Coverage, Philosophy, Do NOT Use When sections. Renamed Verification Protocol to standard Verification heading.*
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hooks-patterns
|
|
3
|
+
description: "Use when reasoning about React Hooks as a discipline: when a render is the right shape for state, why the Rules of Hooks exist as a compile-time invariant, how the dependency array encodes a contract between closure and rerender, when useEffect is the wrong primitive, the distinction between derived state and stored state, when to extract a custom hook, and when memoization (useMemo, useCallback) is a footgun rather than a fix. Covers React 18+ semantics including automatic batching and concurrent rendering. Do NOT use for general React rendering models (use rendering-models), for the client/server boundary (use client-server-boundary), for component composition (use component-architecture), or for state location decisions across the application (use state-management)."
|
|
4
|
+
license: MIT
|
|
5
|
+
allowed-tools: Read Grep
|
|
6
|
+
metadata:
|
|
7
|
+
metadata: "{\"schema_version\":6,\"version\":\"1.0.0\",\"type\":\"capability\",\"category\":\"engineering\",\"domain\":\"engineering/frontend\",\"scope\":\"reference\",\"owner\":\"skill-graph-maintainer\",\"freshness\":\"2026-05-16\",\"drift_check\":\"{\\\\\\\"last_verified\\\\\\\":\\\\\\\"2026-05-16\\\\\\\"}\",\"eval_artifacts\":\"planned\",\"eval_state\":\"unverified\",\"routing_eval\":\"absent\",\"comprehension_state\":\"present\",\"stability\":\"experimental\",\"keywords\":\"[\\\\\\\"React Hooks\\\\\\\",\\\\\\\"Rules of Hooks\\\\\\\",\\\\\\\"useEffect dependencies\\\\\\\",\\\\\\\"useState\\\\\\\",\\\\\\\"useMemo when not to\\\\\\\",\\\\\\\"useCallback footgun\\\\\\\",\\\\\\\"custom hooks extraction\\\\\\\",\\\\\\\"derived state\\\\\\\",\\\\\\\"stale closure\\\\\\\",\\\\\\\"effect cleanup\\\\\\\",\\\\\\\"React 18 automatic batching\\\\\\\",\\\\\\\"concurrent rendering\\\\\\\",\\\\\\\"useEvent useEffectEvent\\\\\\\"]\",\"triggers\":\"[\\\\\\\"is this hook safe to call here\\\\\\\",\\\\\\\"why does my useEffect run twice\\\\\\\",\\\\\\\"do I need useMemo here\\\\\\\",\\\\\\\"dependency array warning\\\\\\\",\\\\\\\"should this be state or derived\\\\\\\",\\\\\\\"extract this into a custom hook\\\\\\\"]\",\"examples\":\"[\\\\\\\"review a useEffect whose dependency array is missing a variable and decide whether to add it, hoist the value, or rethink whether an effect is needed at all\\\\\\\",\\\\\\\"decide whether a derived value should live in useState plus useEffect, or simply be computed during render\\\\\\\",\\\\\\\"explain why the Rules of Hooks are a compile-time invariant, not just a convention\\\\\\\",\\\\\\\"audit a component for unnecessary useMemo / useCallback wrappers that don't actually prevent rerenders\\\\\\\"]\",\"anti_examples\":\"[\\\\\\\"choose between Server Components and Client Components for a new page (use client-server-boundary)\\\\\\\",\\\\\\\"decide where the application's order list lives in memory across routes (use state-management)\\\\\\\",\\\\\\\"design the public API of a reusable component library primitive (use component-architecture)\\\\\\\",\\\\\\\"pick between SSR, SSG, and ISR for a route (use rendering-models)\\\\\\\",\\\\\\\"decide how to layer primitives, composites, and product-specific components (use component-architecture)\\\\\\\"]\",\"relations\":\"{\\\\\\\"related\\\\\\\":[\\\\\\\"rendering-models\\\\\\\",\\\\\\\"client-server-boundary\\\\\\\",\\\\\\\"component-architecture\\\\\\\",\\\\\\\"state-management\\\\\\\"],\\\\\\\"boundary\\\\\\\":[{\\\\\\\"skill\\\\\\\":\\\\\\\"state-management\\\\\\\",\\\\\\\"reason\\\\\\\":\\\\\\\"state-management owns the question of where state lives across the application (server, client, URL, persistent); hooks-patterns owns the in-component discipline of expressing state with the hook primitives.\\\\\\\"},{\\\\\\\"skill\\\\\\\":\\\\\\\"client-server-boundary\\\\\\\",\\\\\\\"reason\\\\\\\":\\\\\\\"client-server-boundary owns the serialization and 'use client' / 'use server' contract; hooks-patterns owns the rules of hook usage on the client side of that boundary.\\\\\\\"}],\\\\\\\"verify_with\\\\\\\":[\\\\\\\"code-review\\\\\\\",\\\\\\\"testing-strategy\\\\\\\"]}\",\"mental_model\":\"|\",\"purpose\":\"|\",\"boundary\":\"|\",\"analogy\":\"Hooks are to function components what stack frames are to function calls — they let a function remember things across calls without breaking referential transparency from the outside, by tracking state in a slot array indexed by call order, and the Rules of Hooks are the same kind of invariant as 'do not goto into the middle of a stack frame': violating them produces undefined behavior masked by garbage collection rather than visible crashes.\",\"misconception\":\"|\",\"concept\":\"{\\\\\\\"definition\\\\\\\":\\\\\\\"Hooks are the React primitives that let a function component participate in the render/commit lifecycle: subscribe to state, schedule effects, read context, and reference mutable values across renders. The Rules of Hooks — call at the top level, call only from React functions — are not style guidance but the precondition that lets React match each hook call to its slot in the fiber tree by call order alone.\\\\\\\",\\\\\\\"mental_model\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"purpose\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"boundary\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"taxonomy\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"analogy\\\\\\\":\\\\\\\"|\\\\\\\",\\\\\\\"misconception\\\\\\\":\\\\\\\"|\\\\\\\"}\",\"skill_graph_source_repo\":\"https://github.com/jacob-balslev/skill-graph\",\"skill_graph_protocol\":\"Skill Metadata Protocol v5\",\"skill_graph_project\":\"Skill Graph\",\"skill_graph_canonical_skill\":\"skills/hooks-patterns/SKILL.md\"}"
|
|
8
|
+
skill_graph_source_repo: "https://github.com/jacob-balslev/skill-graph"
|
|
9
|
+
skill_graph_protocol: Skill Metadata Protocol v4
|
|
10
|
+
skill_graph_project: Skill Graph
|
|
11
|
+
skill_graph_canonical_skill: skills/hooks-patterns/SKILL.md
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Hooks Patterns
|
|
15
|
+
|
|
16
|
+
## Coverage
|
|
17
|
+
|
|
18
|
+
The discipline of using React Hooks correctly: why the Rules of Hooks are a compile-time invariant rather than a convention, how the dependency array encodes a contract between a closure and the next render, when `useEffect` is the wrong primitive (and what the right one is), the difference between *derived* values and *stored* values, the three legitimate reasons to extract a custom hook, when `useMemo` and `useCallback` actually prevent rerenders and when they merely add overhead, and the React 18+ semantics that change the calculus: automatic batching, concurrent rendering, and the still-experimental `useEffectEvent` separation of "reactive" from "non-reactive" effect logic.
|
|
19
|
+
|
|
20
|
+
## Philosophy
|
|
21
|
+
|
|
22
|
+
A React component is a function from props and state to a description of UI. Hooks are the primitives that let the function remember things across calls without breaking referential transparency from the outside — to the calling renderer, each render is a fresh function call producing fresh output; to the component, `useState` returns "the same" state across renders.
|
|
23
|
+
|
|
24
|
+
This illusion is held together by a single mechanism: **React identifies hooks by call order**. The first `useState` call in a render is matched to slot 0 of the fiber's hook list, the second to slot 1, and so on. The Rules of Hooks exist to keep that call order stable across renders. A conditional `useState` would shift the slot indices and corrupt the state of every later hook in the component. The lint rule that flags conditional hooks is not enforcing style; it is preventing a class of memory-corruption bug from compiling.
|
|
25
|
+
|
|
26
|
+
Once that foundation is internalized, every other "discipline" rule around hooks falls out of it: dependency arrays exist because hooks capture closures over the render's props and state, and a stale closure is a referential bug. `useEffect` exists for **synchronizing** with systems outside React, not for general "do this when X changes" logic — most uses are better expressed as derived values during render. Custom hooks exist when stateful logic must be **reused across components**, not as a stylistic preference for shorter component bodies. `useMemo` and `useCallback` exist to stabilize referential identity for downstream `React.memo` or hook dependency arrays, not as general performance optimizations.
|
|
27
|
+
|
|
28
|
+
The discipline is to ask, at each hook call, *what invariant am I expressing?* — and to reach for the cheapest primitive that expresses it. Most stale-closure bugs, most "why does my effect run twice" mysteries, and most over-memoized components come from reaching for hooks as a generic toolkit rather than as primitives with specific semantics.
|
|
29
|
+
|
|
30
|
+
## Rules of Hooks — Why They Are a Compile-Time Invariant
|
|
31
|
+
|
|
32
|
+
The two rules:
|
|
33
|
+
|
|
34
|
+
1. Only call hooks at the top level. Not inside conditions, loops, or nested functions.
|
|
35
|
+
2. Only call hooks from React function components or from other hooks. Not from regular functions, event handlers, or class methods.
|
|
36
|
+
|
|
37
|
+
The mechanism they protect:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
// First render
|
|
41
|
+
const [a, setA] = useState(0); // slot 0
|
|
42
|
+
const [b, setB] = useState(''); // slot 1
|
|
43
|
+
useEffect(() => {...}, [a]); // slot 2
|
|
44
|
+
|
|
45
|
+
// Second render — what if the second hook is conditional?
|
|
46
|
+
const [a, setA] = useState(0); // slot 0
|
|
47
|
+
if (a > 0) {
|
|
48
|
+
const [b, setB] = useState(''); // SOMETIMES slot 1, SOMETIMES skipped
|
|
49
|
+
}
|
|
50
|
+
useEffect(() => {...}, [a]); // either slot 1 OR slot 2 — slot mismatch
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
React does not store hooks by name. It stores them by call-order index. A conditional hook makes the index of every later hook depend on the condition. State and effect state get reassigned to wrong slots, and the component starts reading another hook's state — a classic memory-corruption pattern, except in JavaScript with garbage collection it surfaces as silent bugs rather than crashes.
|
|
54
|
+
|
|
55
|
+
`eslint-plugin-react-hooks` and the React runtime in development mode both enforce these rules. The cost of violating them is not lint-failure aesthetics; it is undefined behavior.
|
|
56
|
+
|
|
57
|
+
## The Dependency Array — A Closure Contract
|
|
58
|
+
|
|
59
|
+
Every callback you pass to `useEffect`, `useMemo`, `useCallback`, and similar hooks **captures the variables in scope at the time of the render that produced it**. The dependency array is the contract that says: "the next render's callback should replace this one if any of these values changed; otherwise keep using the cached one."
|
|
60
|
+
|
|
61
|
+
Three failure modes:
|
|
62
|
+
|
|
63
|
+
1. **Missing dependency (stale closure).** The callback references `x` but `x` is not in the array. The effect runs with the value of `x` from the render where the effect was last created — which may be many renders behind reality. Symptom: "the value seems frozen" or "this used to update and now doesn't."
|
|
64
|
+
|
|
65
|
+
2. **Reference-unstable dependency (over-firing).** The callback depends on an object, array, or function that is *re-created on every render*. The dependency array compares by `Object.is`, so a new array literal `[a, b]` is never `===` to the previous one. The effect re-runs every render even when the meaningful values didn't change.
|
|
66
|
+
|
|
67
|
+
3. **Disabled lint (silent drift).** `// eslint-disable-next-line react-hooks/exhaustive-deps`. The escape hatch exists, but every use should be a documented exception with a comment explaining why the missing dependency is intentional. Most production stale-closure bugs trace to silent disables.
|
|
68
|
+
|
|
69
|
+
The right fix depends on the case:
|
|
70
|
+
|
|
71
|
+
- **Missing dep**: add it. If adding it causes an infinite loop, the loop was already a latent bug — the effect was running every render and producing new state, you just hadn't noticed because the deps were lying about it.
|
|
72
|
+
- **Reference-unstable dep**: lift the value up (define it outside the component, or pass it as a prop), memoize it with `useMemo` / `useCallback` at its source, or refactor so the effect depends on a primitive (string, number) rather than a reference.
|
|
73
|
+
- **Genuinely-don't-want-to-react**: the React team's answer is `useEffectEvent` (RFC stage as of writing) — separate the "reactive" reads from the "latest snapshot" reads. Until that lands, a `useRef` mirror of the value is the documented escape hatch.
|
|
74
|
+
|
|
75
|
+
## When `useEffect` Is the Wrong Primitive
|
|
76
|
+
|
|
77
|
+
`useEffect` is for **synchronizing the component with an external system**: a DOM subscription, a network request, a timer, a third-party widget. It is not for "do this calculation when X changes." Most of the patterns below are mis-uses:
|
|
78
|
+
|
|
79
|
+
| Pattern | What it does | Better primitive |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `useState(initial); useEffect(() => setState(derive(props)), [props])` | Stores a derived value in state, then re-syncs on prop change | Compute during render: `const derived = derive(props);` |
|
|
82
|
+
| `useState; useEffect(() => setState(...))` triggered by a prop change to reset | Resets local state when a prop changes | Use the `key` prop to remount, or lift state up |
|
|
83
|
+
| `useEffect(() => { fetchData().then(setData) }, [])` for initial data | Imperative fetch-on-mount | Server Components, React Query / SWR, or Suspense data fetching |
|
|
84
|
+
| `useEffect(() => onChange?.(value), [value])` to notify parent | Re-syncs parent state from child effect | Call `onChange` in the event handler that changed `value` |
|
|
85
|
+
| `useEffect(() => { const id = setTimeout(...); return () => clearTimeout(id) }, [...])` to debounce | Effect-driven debounce | Custom `useDebouncedValue` hook, or library |
|
|
86
|
+
|
|
87
|
+
The React docs' essay [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect) is the canonical taxonomy of effect misuse. The pattern: every `useEffect` is a code smell until it has earned its place by genuinely synchronizing with something React doesn't own.
|
|
88
|
+
|
|
89
|
+
## Derived Values vs Stored Values
|
|
90
|
+
|
|
91
|
+
A value is *derived* if it can be computed from other values you already have (props, state, refs). A value is *stored* if it has its own lifecycle — set by an event, persisted across renders, and not recoverable from other inputs.
|
|
92
|
+
|
|
93
|
+
Stored:
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
const [draft, setDraft] = useState('');
|
|
97
|
+
<input value={draft} onChange={e => setDraft(e.target.value)} />
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Derived (no extra `useState` needed):
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
const fullName = `${firstName} ${lastName}`; // from props
|
|
104
|
+
const isValid = email.includes('@') && password.length >= 8; // from state
|
|
105
|
+
const filteredItems = items.filter(i => i.tag === activeTag); // from props+state
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The rule: if the value can be computed during render, compute it during render. State exists to remember things across renders; it is not a cache for computation. Storing a derived value in state introduces a two-step update cycle: render → effect → setState → rerender, where a single render with inline computation would have sufficed.
|
|
109
|
+
|
|
110
|
+
When derived computation is expensive enough to matter, that's what `useMemo` is for — and *only then*, because for cheap computations the overhead of `useMemo` (a deps check, an array allocation, a callback closure) exceeds the cost of re-running the computation.
|
|
111
|
+
|
|
112
|
+
## Custom Hooks — When and Why
|
|
113
|
+
|
|
114
|
+
Three legitimate reasons to extract a custom hook:
|
|
115
|
+
|
|
116
|
+
1. **Reuse across components.** The same stateful logic is needed in two or more components. Extract it once, import it twice.
|
|
117
|
+
2. **Name the abstraction.** A sequence of `useState` + `useEffect` + `useCallback` whose collective purpose is "track the window's scroll position" deserves to be named `useScrollPosition`. The name is documentation.
|
|
118
|
+
3. **Encapsulate a state machine.** A reducer plus its bound actions is a contained unit; `useFormDraft` is clearer at the call site than the seven hooks it composes.
|
|
119
|
+
|
|
120
|
+
Anti-patterns:
|
|
121
|
+
|
|
122
|
+
- **Extracting because the component is "too long".** Length is not a smell. Hooks have one-call-site-per-component semantics; splitting a 200-line component's hooks into three custom hooks that are each called from one place produces three indirections and no reuse.
|
|
123
|
+
- **Extracting to "follow the pattern".** Custom hooks are not architecture; they are factorization. If the factor isn't reused or doesn't have a useful name, it's noise.
|
|
124
|
+
- **Extracting effects without their state.** A custom hook that takes a callback and runs it in `useEffect` is almost always wrong — the callback closes over the caller's state, and you've just hidden the dependency-array problem from view.
|
|
125
|
+
|
|
126
|
+
Library precedent: `react-use`, `usehooks-ts`, `@tanstack/react-query`, `swr` — these libraries are entirely composed of named, reusable custom hooks. They are the existence proof of what custom hooks earn their keep doing.
|
|
127
|
+
|
|
128
|
+
## `useMemo` and `useCallback` — Footgun Cases
|
|
129
|
+
|
|
130
|
+
These hooks have two valid jobs:
|
|
131
|
+
|
|
132
|
+
1. **Stabilize referential identity** for a value that will be a dependency of another hook, or a prop to a `React.memo`-wrapped child.
|
|
133
|
+
2. **Skip expensive computation** when the inputs haven't changed.
|
|
134
|
+
|
|
135
|
+
For everything else, they are net negative — they add a deps-check cost, an allocation, and a closure, in exchange for no observable benefit.
|
|
136
|
+
|
|
137
|
+
| Case | `useMemo` adds value? |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `const total = items.reduce(...)` where items has 5 entries | No |
|
|
140
|
+
| `const total = items.reduce(...)` where items has 50,000 entries | Yes (if rerender frequency is high) |
|
|
141
|
+
| `const onClick = useCallback(() => ..., [...])` passed to a normal child | No — the child re-renders anyway when its parent re-renders |
|
|
142
|
+
| `const onClick = useCallback(() => ..., [...])` passed to `React.memo(Child)` | Yes — keeps the memo equality check from breaking |
|
|
143
|
+
| `const opts = useMemo(() => ({ a, b }), [a, b])` used in another hook's deps | Yes — without it, the outer hook over-fires |
|
|
144
|
+
| `const opts = useMemo(() => ({ a, b }), [a, b])` never used as a dep | No |
|
|
145
|
+
|
|
146
|
+
The compiler (React Compiler, formerly React Forget) when generally available will auto-memoize where beneficial and eliminate this discipline as a manual concern. Until then, the rule is: don't memoize until you have evidence — a profiler trace, a benchmark, or a `React.memo`'d consumer — that memoization is preventing real work.
|
|
147
|
+
|
|
148
|
+
## React 18+ Semantics That Change Hook Reasoning
|
|
149
|
+
|
|
150
|
+
- **Automatic batching.** All state updates inside any callback (event handlers, promises, timeouts, async functions) are batched into a single re-render in React 18+. Pre-React-18, only updates inside React event handlers batched. The discipline change: stop reaching for `flushSync` to force separate updates; conversely, don't write code that depends on updates *not* batching.
|
|
151
|
+
- **Concurrent rendering.** A render can be interrupted, abandoned, or replayed. Two consequences: (1) render functions must be pure — no side effects, no I/O, no `Date.now()`-driven branching that won't survive replay; (2) effects run *after* the render commits, not after every render function call.
|
|
152
|
+
- **Strict Mode double-invocation in development.** React 18 in dev mounts every component twice, runs every effect twice, to surface non-idempotent effects. Effects that don't clean up properly (subscribe without unsubscribe, fetch without abort) misbehave under this regimen — that's a bug Strict Mode is *showing* you, not a bug Strict Mode is *causing*.
|
|
153
|
+
- **`useEffectEvent` (RFC, partial).** Separates a callback's *latest snapshot* read from the effect's reactive dependencies. The right primitive for "use the current value of X inside this effect but don't re-fire when X changes." Until stable, the workaround is a `useRef` mirror updated in a `useEffect`.
|
|
154
|
+
|
|
155
|
+
## Verification
|
|
156
|
+
|
|
157
|
+
After applying this skill, verify:
|
|
158
|
+
|
|
159
|
+
- [ ] Every hook is called at the top level of the component or another hook, with no conditional or loop wrapping.
|
|
160
|
+
- [ ] Every dependency array is exhaustive (eslint-plugin-react-hooks passes), with documented exceptions only.
|
|
161
|
+
- [ ] Each `useEffect` synchronizes with something React doesn't own; computational logic lives in render or in event handlers.
|
|
162
|
+
- [ ] No state holds a value that could be derived during render.
|
|
163
|
+
- [ ] Custom hooks have either ≥2 call sites or a meaningful name that earns its existence.
|
|
164
|
+
- [ ] `useMemo` / `useCallback` wrap only values that (a) stabilize identity for a downstream consumer or (b) skip provably-expensive work.
|
|
165
|
+
- [ ] Effects clean up: every subscribe has unsubscribe, every fetch has abort, every timer has clear.
|
|
166
|
+
|
|
167
|
+
## Grounding Sources
|
|
168
|
+
|
|
169
|
+
- React docs — [Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks). The official statement of the two rules and their rationale.
|
|
170
|
+
- React docs — [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect). The canonical taxonomy of `useEffect` misuse.
|
|
171
|
+
- React docs — [Reusing Logic with Custom Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks). The official guidance on when extraction is warranted.
|
|
172
|
+
- Abramov, D. — [A Complete Guide to useEffect](https://overreacted.io/a-complete-guide-to-useeffect/). The stale-closure model and the closure-over-render mental model.
|
|
173
|
+
- React RFC — [`useEffectEvent`](https://github.com/reactjs/rfcs/pull/220). The reactive/non-reactive separation for effect dependencies.
|
|
174
|
+
- React 18 working group — [Automatic batching for fewer renders in React 18](https://github.com/reactwg/react-18/discussions/21).
|
|
175
|
+
- Markbåge, S. & Clark, A. — React 18 announcement post on concurrent rendering invariants.
|
|
176
|
+
|
|
177
|
+
## Do NOT Use When
|
|
178
|
+
|
|
179
|
+
| Instead of this skill | Use | Why |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| Choosing between Server Components, Client Components, and where to draw the boundary | `client-server-boundary` | client-server-boundary owns the serialization contract and the `'use client'` / `'use server'` rules; hooks-patterns operates on the client side of that boundary. |
|
|
182
|
+
| Deciding where the application's state should live (server, client, URL, persistent storage) | `state-management` | state-management owns the location and ownership decision; hooks-patterns owns the local discipline once you've decided client-component state is the right home. |
|
|
183
|
+
| Designing a reusable component library's API surface | `component-architecture` | component-architecture owns primitive/composite/product layering; hooks-patterns is one component's internal logic. |
|
|
184
|
+
| Picking SSR vs SSG vs ISR for a route | `rendering-models` | rendering-models owns the rendering-strategy decision; hooks-patterns has nothing to say about it. |
|
|
185
|
+
| Suspense for data fetching and streaming UI patterns | `suspense-patterns` | suspense-patterns owns the boundary-and-fallback discipline; hooks-patterns covers the underlying hook primitives but not the Suspense boundary protocol. |
|