@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,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
# yaml-language-server: $schema=https://skillgraph.dev/schemas/skill.v4.schema.json
|
|
3
|
+
schema_version: 4
|
|
4
|
+
name: link-rot-detection
|
|
5
|
+
description: "Use when authoring or reviewing a periodic-scan job that walks every external link in a markdown content set and flags 404s, redirects to unrelated content, and connection failures. Activate this skill whenever the task says 'check our links' or mentions a link-rot scan, broken-link audit, or link-health report. Do NOT use for live runtime link checking inside the rendered page (use a frontend a11y / UX skill) or for chasing a specific broken-link incident from a user report (use debugging)."
|
|
6
|
+
version: 0.1.0
|
|
7
|
+
type: capability
|
|
8
|
+
category: content
|
|
9
|
+
domain: content/maintenance
|
|
10
|
+
scope: portable
|
|
11
|
+
owner: markdown-static-site-maintainer
|
|
12
|
+
freshness: "2026-05-06"
|
|
13
|
+
drift_check:
|
|
14
|
+
last_verified: "2026-05-06"
|
|
15
|
+
eval_artifacts: none
|
|
16
|
+
eval_state: unverified
|
|
17
|
+
routing_eval: absent
|
|
18
|
+
stability: experimental
|
|
19
|
+
license: MIT
|
|
20
|
+
compatibility:
|
|
21
|
+
runtimes:
|
|
22
|
+
- node
|
|
23
|
+
node: ">=20"
|
|
24
|
+
notes: "Portable across any markdown-content project; no codebase grounding required."
|
|
25
|
+
allowed-tools: Read Grep Bash
|
|
26
|
+
keywords:
|
|
27
|
+
- link rot
|
|
28
|
+
- link-rot detection
|
|
29
|
+
- broken link audit
|
|
30
|
+
- link health
|
|
31
|
+
- dead link scan
|
|
32
|
+
- 404 audit
|
|
33
|
+
- external link check
|
|
34
|
+
- periodic scan
|
|
35
|
+
- markdown link extraction
|
|
36
|
+
- link-rot report
|
|
37
|
+
triggers:
|
|
38
|
+
- link-rot-detection
|
|
39
|
+
examples:
|
|
40
|
+
- "design a periodic link-rot scan that runs nightly and posts a report"
|
|
41
|
+
- "review the link-rot detector — does it handle redirects correctly?"
|
|
42
|
+
- "explain how to test the link-rot scanner against a fixture set without hitting the network"
|
|
43
|
+
- "should the scan retry on transient 5xx, or only flag persistent failures?"
|
|
44
|
+
anti_examples:
|
|
45
|
+
- "validate this internal route in the live app"
|
|
46
|
+
- "the link to example.com just broke for one user"
|
|
47
|
+
- "design the rendering of broken-link badges in the UI"
|
|
48
|
+
relations:
|
|
49
|
+
boundary:
|
|
50
|
+
- skill: documentation
|
|
51
|
+
reason: "documentation writes prose about link-health policy; this skill enforces the detection primitive in code"
|
|
52
|
+
- skill: debugging
|
|
53
|
+
reason: "debugging chases a specific reported broken link; this skill is the periodic audit applied before user reports"
|
|
54
|
+
- skill: refactor
|
|
55
|
+
reason: "refactor changes scanner code shape; this skill enforces the detection contract that any refactor must preserve"
|
|
56
|
+
verify_with:
|
|
57
|
+
- testing-strategy
|
|
58
|
+
portability:
|
|
59
|
+
readiness: scripted
|
|
60
|
+
targets:
|
|
61
|
+
- skill-md
|
|
62
|
+
workspace_tags:
|
|
63
|
+
- content
|
|
64
|
+
- markdown
|
|
65
|
+
lifecycle:
|
|
66
|
+
stale_after_days: 180
|
|
67
|
+
review_cadence: quarterly
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
# Link-Rot Detection
|
|
71
|
+
|
|
72
|
+
## Coverage
|
|
73
|
+
|
|
74
|
+
- Markdown link extraction — pulling every `[text](url)` and `[text][ref]` reference link out of every `.md` and `.mdx` file in the content tree
|
|
75
|
+
- External vs internal classification — what counts as external (different host) and what gets skipped (relative path, anchor link, mailto, tel)
|
|
76
|
+
- Status-code interpretation — 200 is healthy, 301/308 is a redirect (record the new URL but don't fail), 302/307 is transient (re-check next run), 404/410 is dead (flag), 5xx is transient (retry with backoff before flagging)
|
|
77
|
+
- Soft-404 detection — pages that return HTTP 200 but render an "unknown page" interstitial (compare body length / content against known soft-404 patterns)
|
|
78
|
+
- Rate-limiting and politeness — concurrent request budget per origin host, honoring `robots.txt` crawl-delay, exponential backoff on 429
|
|
79
|
+
- Reporting shape — the scanner's output is a structured report (JSON + markdown summary), not a live alert; the report is the audit artifact
|
|
80
|
+
|
|
81
|
+
## Philosophy
|
|
82
|
+
|
|
83
|
+
External links rot. Every site that's older than two years has at least a few. The choice is between knowing about them on a schedule or finding out from a user. A periodic scan with a published report turns link health into a maintenance task instead of an emergency. The discipline is to be conservative — distinguish persistent failures (404 across 3 runs) from transient ones (one 503 on a Tuesday) — and to never let the scanner itself become a denial-of-service vector against the targets it's checking.
|
|
84
|
+
|
|
85
|
+
## Verification
|
|
86
|
+
|
|
87
|
+
Before merging any change to the link-rot scanner or its config:
|
|
88
|
+
|
|
89
|
+
- [ ] The scanner extracts every link in `[text](url)` and `[text][ref]` form from `.md` and `.mdx` files; reference links resolve their targets before classification
|
|
90
|
+
- [ ] Internal links (relative paths, same-host absolute, anchors, mailto, tel) are explicitly excluded — confirmed by a fixture test with mixed link types
|
|
91
|
+
- [ ] Persistent failures are distinguished from transient ones — a link is only flagged after N consecutive failures across separate runs (default N=3)
|
|
92
|
+
- [ ] The scanner respects per-host concurrency limits and honors `robots.txt` crawl-delay; a single host getting many requests in tight sequence is a bug
|
|
93
|
+
- [ ] Soft-404 detection has a defined pattern set and an explicit "unknown" bucket for cases that don't match any known soft-404
|
|
94
|
+
- [ ] The scanner produces both a JSON report (machine-readable) and a markdown summary (human-readable) with link, status code, last-seen-OK timestamp, and recommendation
|
|
95
|
+
|
|
96
|
+
## Do NOT Use When
|
|
97
|
+
|
|
98
|
+
| Use instead | When |
|
|
99
|
+
|---|---|
|
|
100
|
+
| (a frontend a11y / UX skill) | The task is rendering a "this link may be broken" badge in the live UI |
|
|
101
|
+
| `debugging` | A specific link broke for a specific user and you need to reproduce |
|
|
102
|
+
| `documentation` | The task is writing the link-health policy doc, not the scanner |
|
|
103
|
+
| `refactor` | The task is restructuring the scanner without changing the detection contract |
|
package/examples/projects/markdown-static-site/skills/markdown-post-frontmatter-validation/SKILL.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
# yaml-language-server: $schema=https://skillgraph.dev/schemas/skill.v4.schema.json
|
|
3
|
+
schema_version: 4
|
|
4
|
+
name: markdown-post-frontmatter-validation
|
|
5
|
+
description: "Use when authoring or reviewing the frontmatter of a markdown post — checking required fields (title, date, slug, tags), validating against the content schema in `lib/content/schema.ts`, catching ambiguous date formats or tags not in the controlled vocabulary, and ensuring the slug matches the file path. Activate this skill whenever the task touches files under `content/posts/**/*.md`, the `parsePostFrontmatter()` helper, or any code path that reads YAML frontmatter from a content file. Do NOT use for general YAML schema design (use a generic schema-design skill) or for chasing a specific build-time validation failure (use debugging)."
|
|
6
|
+
version: 0.1.0
|
|
7
|
+
type: capability
|
|
8
|
+
category: content
|
|
9
|
+
domain: content/markdown/frontmatter
|
|
10
|
+
scope: codebase
|
|
11
|
+
owner: markdown-static-site-maintainer
|
|
12
|
+
freshness: "2026-05-06"
|
|
13
|
+
drift_check:
|
|
14
|
+
last_verified: "2026-05-06"
|
|
15
|
+
eval_artifacts: none
|
|
16
|
+
eval_state: unverified
|
|
17
|
+
routing_eval: absent
|
|
18
|
+
stability: experimental
|
|
19
|
+
license: MIT
|
|
20
|
+
compatibility:
|
|
21
|
+
runtimes:
|
|
22
|
+
- node
|
|
23
|
+
node: ">=20"
|
|
24
|
+
notes: "Astro / Next / Eleventy / Hugo all read YAML frontmatter; the validation pattern is portable across them."
|
|
25
|
+
allowed-tools: Read Grep
|
|
26
|
+
keywords:
|
|
27
|
+
- markdown frontmatter
|
|
28
|
+
- post frontmatter
|
|
29
|
+
- frontmatter validation
|
|
30
|
+
- content schema
|
|
31
|
+
- parsePostFrontmatter
|
|
32
|
+
- YAML frontmatter
|
|
33
|
+
- title required
|
|
34
|
+
- tag vocabulary
|
|
35
|
+
- slug mismatch
|
|
36
|
+
- date format
|
|
37
|
+
- controlled vocabulary
|
|
38
|
+
- markdown post metadata
|
|
39
|
+
triggers:
|
|
40
|
+
- markdown-post-frontmatter-validation
|
|
41
|
+
paths:
|
|
42
|
+
- "content/posts/**/*.md"
|
|
43
|
+
- "lib/content/schema.ts"
|
|
44
|
+
- "lib/content/parse-frontmatter.ts"
|
|
45
|
+
- "!**/*.test.md"
|
|
46
|
+
examples:
|
|
47
|
+
- "validate the frontmatter of a new post against our content schema"
|
|
48
|
+
- "why does the build fail when I add a tag like `Politics` (capital P)?"
|
|
49
|
+
- "review this post's frontmatter — is the date format correct?"
|
|
50
|
+
- "explain how the slug is derived from the file path"
|
|
51
|
+
anti_examples:
|
|
52
|
+
- "design a YAML schema for a different domain"
|
|
53
|
+
- "the build is failing — what's the actual error?"
|
|
54
|
+
- "rewrite parsePostFrontmatter for performance"
|
|
55
|
+
relations:
|
|
56
|
+
boundary:
|
|
57
|
+
- skill: documentation
|
|
58
|
+
reason: "documentation writes prose explaining the frontmatter format; this skill enforces the validation contract in code"
|
|
59
|
+
- skill: debugging
|
|
60
|
+
reason: "debugging chases a specific build-time validation failure from logs; this skill is the authoring discipline applied before failure"
|
|
61
|
+
- skill: refactor
|
|
62
|
+
reason: "refactor changes code shape; this skill enforces a specific validation contract that must survive any refactor"
|
|
63
|
+
verify_with:
|
|
64
|
+
- testing-strategy
|
|
65
|
+
grounding:
|
|
66
|
+
domain_object: "Markdown post frontmatter — the YAML block at the top of every content file that drives the site's index, routing, and rendering"
|
|
67
|
+
grounding_mode: repo_specific
|
|
68
|
+
truth_sources:
|
|
69
|
+
- content/posts/_template.md
|
|
70
|
+
- lib/content/schema.ts
|
|
71
|
+
- lib/content/parse-frontmatter.ts
|
|
72
|
+
failure_modes:
|
|
73
|
+
- missing_required_title_field
|
|
74
|
+
- ambiguous_date_format_no_timezone
|
|
75
|
+
- tag_not_in_controlled_vocabulary
|
|
76
|
+
- slug_mismatch_with_file_path
|
|
77
|
+
- frontmatter_block_not_terminated
|
|
78
|
+
evidence_priority: repo_code_first
|
|
79
|
+
portability:
|
|
80
|
+
readiness: scripted
|
|
81
|
+
targets:
|
|
82
|
+
- skill-md
|
|
83
|
+
workspace_tags:
|
|
84
|
+
- content
|
|
85
|
+
- static-site
|
|
86
|
+
- markdown
|
|
87
|
+
lifecycle:
|
|
88
|
+
stale_after_days: 90
|
|
89
|
+
review_cadence: quarterly
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
# Markdown Post Frontmatter Validation
|
|
93
|
+
|
|
94
|
+
## Coverage
|
|
95
|
+
|
|
96
|
+
- Required-field enforcement — every post must declare `title`, `date`, `slug`, and `tags`; missing fields fail the build at parse time
|
|
97
|
+
- Date format discipline — ISO 8601 with explicit timezone (`2026-05-06T12:00:00Z`); ambiguous formats like `2026-05-06` or `5/6/26` are rejected
|
|
98
|
+
- Slug-to-path consistency — the `slug` field must match the post's directory name; out-of-sync slugs cause silent route conflicts
|
|
99
|
+
- Controlled-vocabulary tagging — every tag in the post's `tags` array must appear in `lib/content/tag-vocabulary.ts`; lowercase, hyphen-separated, no synonyms
|
|
100
|
+
- Schema evolution — when `lib/content/schema.ts` changes, every post's frontmatter is re-validated; existing posts that violate the new schema are flagged before the next build runs
|
|
101
|
+
- Reserved-field protection — fields like `_id`, `_internal`, or any underscore-prefixed key are reserved for the build pipeline and rejected in author-facing frontmatter
|
|
102
|
+
|
|
103
|
+
## Philosophy
|
|
104
|
+
|
|
105
|
+
The frontmatter block is the contract every post makes with the site's index, the router, and the renderer. If that contract is loose — if posts can omit fields, use ambiguous dates, or invent ad-hoc tags — the index drifts, routes silently overlap, and the search surface degrades. The cost of catching frontmatter bugs at build time is one re-run; the cost of catching them in production is a broken page or a missing entry in the archive. The rule is: validate at parse time, fail loud, and keep the schema small enough that authors can hold it in their head.
|
|
106
|
+
|
|
107
|
+
## Key Files
|
|
108
|
+
|
|
109
|
+
| File | Purpose |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `content/posts/_template.md` | The canonical template every new post copies — its frontmatter is the worked example of every required field |
|
|
112
|
+
| `lib/content/schema.ts` | The TypeScript schema (Zod or equivalent) that runtime validation calls |
|
|
113
|
+
| `lib/content/parse-frontmatter.ts` | The thin wrapper that reads the YAML block and runs `schema.parse()` — the failure surface for build-time errors |
|
|
114
|
+
|
|
115
|
+
## Verification
|
|
116
|
+
|
|
117
|
+
Before merging any change to a post's frontmatter or to the schema:
|
|
118
|
+
|
|
119
|
+
- [ ] Every post has the four required fields: `title`, `date`, `slug`, `tags`
|
|
120
|
+
- [ ] `date` is ISO 8601 with timezone (no naked `YYYY-MM-DD`, no locale-formatted dates)
|
|
121
|
+
- [ ] `slug` matches the post's directory name exactly — not derived from `title` at runtime
|
|
122
|
+
- [ ] Every tag in `tags` is present in `lib/content/tag-vocabulary.ts` (run `npm run check:tags` to confirm)
|
|
123
|
+
- [ ] No underscore-prefixed fields (`_id`, `_internal`, etc.) — those are reserved for the pipeline
|
|
124
|
+
- [ ] Schema changes (`lib/content/schema.ts`) are paired with a `npm run validate:posts` pass against the entire `content/posts/**/*.md` set
|
|
125
|
+
|
|
126
|
+
## Do NOT Use When
|
|
127
|
+
|
|
128
|
+
| Use instead | When |
|
|
129
|
+
|---|---|
|
|
130
|
+
| (a generic schema-design skill) | The task is designing a new YAML schema for an unrelated domain |
|
|
131
|
+
| `debugging` | A specific build is failing and you need to reproduce the validation error from logs |
|
|
132
|
+
| `documentation` | The task is writing a runbook or contributor doc about the frontmatter format |
|
|
133
|
+
| `refactor` | The task is restructuring `parse-frontmatter.ts` without changing the validation contract |
|
package/examples/projects/markdown-static-site/skills/migrate-posts-to-v2-frontmatter/SKILL.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
# yaml-language-server: $schema=https://skillgraph.dev/schemas/skill.v4.schema.json
|
|
3
|
+
schema_version: 4
|
|
4
|
+
name: migrate-posts-to-v2-frontmatter
|
|
5
|
+
description: "Use when migrating every existing post in `content/posts/**/*.md` to the v2 frontmatter schema — adding the new required `summary` field, normalizing `tags` to the controlled vocabulary, converting bare-date `date` strings to ISO 8601 with timezone, and re-validating every post against the v2 schema before the next build runs. Activate this skill whenever the task references migration `0007-frontmatter-v2`, the v2 frontmatter rollout, or asks how to safely change a required-field set across a populated content tree without breaking the build. Do NOT use for unrelated migrations (use a generic content-migration skill or write a fresh one) or for general schema-design questions (use a schema-design skill)."
|
|
6
|
+
version: 0.1.0
|
|
7
|
+
type: workflow
|
|
8
|
+
category: content
|
|
9
|
+
domain: content/migrations
|
|
10
|
+
scope: codebase
|
|
11
|
+
owner: markdown-static-site-maintainer
|
|
12
|
+
freshness: "2026-05-06"
|
|
13
|
+
drift_check:
|
|
14
|
+
last_verified: "2026-05-06"
|
|
15
|
+
eval_artifacts: none
|
|
16
|
+
eval_state: unverified
|
|
17
|
+
routing_eval: absent
|
|
18
|
+
stability: experimental
|
|
19
|
+
license: MIT
|
|
20
|
+
compatibility:
|
|
21
|
+
runtimes:
|
|
22
|
+
- node
|
|
23
|
+
node: ">=20"
|
|
24
|
+
notes: "Markdown content tree under content/posts/; assumes Zod or similar runtime validator."
|
|
25
|
+
allowed-tools: Read Grep Bash
|
|
26
|
+
keywords:
|
|
27
|
+
- migrate posts
|
|
28
|
+
- frontmatter v2 migration
|
|
29
|
+
- 0007 frontmatter v2
|
|
30
|
+
- content schema migration
|
|
31
|
+
- tag vocabulary normalization
|
|
32
|
+
- bare-date conversion
|
|
33
|
+
- safe content migration
|
|
34
|
+
- post backfill
|
|
35
|
+
- frontmatter migration
|
|
36
|
+
triggers:
|
|
37
|
+
- migrate-posts-to-v2-frontmatter
|
|
38
|
+
paths:
|
|
39
|
+
- "scripts/migrate-frontmatter-v2.ts"
|
|
40
|
+
- "lib/content/schema.ts"
|
|
41
|
+
- "lib/content/tag-vocabulary.ts"
|
|
42
|
+
examples:
|
|
43
|
+
- "run the v2 frontmatter migration on every post in `content/posts/`"
|
|
44
|
+
- "the v2 migration's tag-normalization step is rejecting some valid tags — what's safe to do?"
|
|
45
|
+
- "verify that every post passes the v2 schema before flipping the validator"
|
|
46
|
+
- "design migration 0008 to drop the legacy `excerpt` field now that `summary` is canonical"
|
|
47
|
+
anti_examples:
|
|
48
|
+
- "design a new frontmatter schema for a different domain"
|
|
49
|
+
- "the migration is failing in CI — what's wrong?"
|
|
50
|
+
- "write the v2 frontmatter doc for new contributors"
|
|
51
|
+
relations:
|
|
52
|
+
boundary:
|
|
53
|
+
- skill: documentation
|
|
54
|
+
reason: "documentation writes prose explaining the schema migration; this workflow is the procedural enforcement"
|
|
55
|
+
- skill: debugging
|
|
56
|
+
reason: "debugging chases a specific migration failure from logs; this workflow is the pre-failure procedure"
|
|
57
|
+
- skill: refactor
|
|
58
|
+
reason: "refactor changes code shape with no behavior change; a content-schema migration changes the validation contract — different problem, different gates"
|
|
59
|
+
verify_with:
|
|
60
|
+
- testing-strategy
|
|
61
|
+
depends_on:
|
|
62
|
+
- skill: testing-strategy
|
|
63
|
+
min_version: "^1.0.0"
|
|
64
|
+
grounding:
|
|
65
|
+
domain_object: "The 0007 frontmatter-v2 migration — a multi-step procedure that adds a required field, normalizes the tag vocabulary, converts bare-date strings to ISO 8601, and re-validates every post against the v2 schema before the validator is flipped"
|
|
66
|
+
grounding_mode: repo_specific
|
|
67
|
+
truth_sources:
|
|
68
|
+
- scripts/migrate-frontmatter-v2.ts
|
|
69
|
+
- lib/content/schema.ts
|
|
70
|
+
- lib/content/tag-vocabulary.ts
|
|
71
|
+
failure_modes:
|
|
72
|
+
- validator_flipped_before_backfill_complete
|
|
73
|
+
- tag_normalization_drops_a_valid_tag_silently
|
|
74
|
+
- bare_date_conversion_picks_wrong_timezone
|
|
75
|
+
- migration_runs_outside_dry_run_gate_first
|
|
76
|
+
- rollback_step_overwrites_authored_summary_field
|
|
77
|
+
evidence_priority: repo_code_first
|
|
78
|
+
portability:
|
|
79
|
+
readiness: scripted
|
|
80
|
+
targets:
|
|
81
|
+
- skill-md
|
|
82
|
+
workspace_tags:
|
|
83
|
+
- content
|
|
84
|
+
- static-site
|
|
85
|
+
- migrations
|
|
86
|
+
lifecycle:
|
|
87
|
+
stale_after_days: 30
|
|
88
|
+
review_cadence: quarterly
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
# Migrate Posts to v2 Frontmatter
|
|
92
|
+
|
|
93
|
+
## Coverage
|
|
94
|
+
|
|
95
|
+
- The four-phase pattern for adding a required field to a populated content tree — *add as nullable → backfill from existing data → verify → flip the validator to require it* — and why collapsing any two phases into one is unsafe
|
|
96
|
+
- The backfill query — generating a `summary` from each post's first paragraph, with a per-post manual-override fallback for cases where the auto-summary is wrong
|
|
97
|
+
- The verification gate between backfill and validator-flip — running `validate-posts.ts` against the entire `content/posts/**/*.md` tree must return zero errors before the schema is updated
|
|
98
|
+
- The tag-normalization step — mapping every tag to its canonical form in `tag-vocabulary.ts`, with a deny-list for tags that should be removed entirely (e.g., legacy synonyms now folded into a canonical tag)
|
|
99
|
+
- The dry-run gate — the migration script always runs in dry-run by default, printing the diff per post; the `--apply` flag is opt-in and never the CI default
|
|
100
|
+
- The rollback path — what `ROLLBACK.md` for this migration looks like and why "regenerate every summary" is wrong (overwrites authored summaries); the correct rollback restores the per-post `.bak` file the migration writes alongside each edit
|
|
101
|
+
|
|
102
|
+
## Philosophy
|
|
103
|
+
|
|
104
|
+
A content-schema migration is a rare migration where being careful is cheaper than being clever. The temptation to combine the four phases into one "atomic" pass fails because the backfill produces some surprising auto-summaries, the human reviewer needs time to override them, and flipping the validator before the human pass is done means every build between then and the override fails. The four-phase pattern is verbose but unambiguous: each phase has a clear success criterion, each phase is re-runnable, and the rollback at any phase is well-defined. Pay the verbosity cost; the alternative is a build outage on a non-emergency migration.
|
|
105
|
+
|
|
106
|
+
## Workflow
|
|
107
|
+
|
|
108
|
+
Each step has a clear precondition and a clear success criterion. Do not skip steps; the steps exist because skipping them is how content migrations corrupt authored data.
|
|
109
|
+
|
|
110
|
+
| Step | Precondition | Action | Success criterion |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| 1. Add nullable `summary` | The schema has no `summary` field | `lib/content/schema.ts`: add `summary: z.string().optional()` (no `required`). Deploy. | The schema accepts posts both with and without `summary`; the build does not fail on existing posts. |
|
|
113
|
+
| 2. Backfill | Step 1 deployed | Run `scripts/migrate-frontmatter-v2.ts --apply --field summary` which generates a draft summary per post from the first paragraph and writes a `.bak` for each modified file. | Verification query reports 0 posts where `summary` is null or empty. |
|
|
114
|
+
| 3. Human review of auto-summaries | Step 2 success | Each post author reviews their auto-summary. Override by editing the post's frontmatter manually; the migration script will not re-run on a post whose `summary` was edited after step 2's `.bak` was written. | Author sign-off recorded in `audits/0007-frontmatter-v2/sign-off.md`. |
|
|
115
|
+
| 4. Flip the validator | Step 3 sign-off committed | `lib/content/schema.ts`: change `summary: z.string().optional()` to `summary: z.string().min(40)` (required, with a minimum length). Deploy. | Builds fail on any post that doesn't pass the v2 schema; the failure surface is the build log, not user-facing pages. |
|
|
116
|
+
|
|
117
|
+
### When to back out
|
|
118
|
+
|
|
119
|
+
- Step 2 backfill produces too many surprising auto-summaries → reduce the auto-summary rule (e.g., first-sentence-only); the migration is still safe to resume from the same `.bak` set.
|
|
120
|
+
- Step 3 reveals that some posts genuinely have no extractable summary → those posts need authored summaries before step 4; do NOT flip the validator with placeholder summaries in place.
|
|
121
|
+
- Step 4 is flipped and the build fails on a post whose summary was edited but didn't trip the `min(40)` floor → revert step 4 (`.optional()` again), have the author rewrite the summary, re-flip.
|
|
122
|
+
|
|
123
|
+
## Verification
|
|
124
|
+
|
|
125
|
+
- [ ] Step 1 added the field as `.optional()`, not as required
|
|
126
|
+
- [ ] Step 2 was run with `--apply` only after a `--dry-run` was reviewed (the dry-run output is committed under `audits/0007-frontmatter-v2/dry-run.md`)
|
|
127
|
+
- [ ] Step 2's `.bak` files exist for every modified post and are committed (so rollback is a one-command restore)
|
|
128
|
+
- [ ] Step 3 sign-off is recorded for every post in `content/posts/**/*.md` — no post moved past step 3 without explicit author confirmation
|
|
129
|
+
- [ ] Step 4 was applied AFTER step 3 sign-off — never before, even if the author backlog is taking longer than expected
|
|
130
|
+
- [ ] The rollback path in `ROLLBACK.md` does NOT include "regenerate every summary" — that overwrites authored content. Rollback is `mv <post>.md.bak <post>.md` per file, with the `.bak`s already committed.
|
|
131
|
+
- [ ] An end-to-end CI test runs the migration in dry-run mode against the live `content/posts/` set and reports the diff in the PR description before any human merges step 4
|
|
132
|
+
|
|
133
|
+
## Do NOT Use When
|
|
134
|
+
|
|
135
|
+
| Use instead | When |
|
|
136
|
+
|---|---|
|
|
137
|
+
| `markdown-post-frontmatter-validation` | The task is reviewing or authoring a single post's frontmatter, not the migration that adds a new required field |
|
|
138
|
+
| `debugging` | A specific migration step is failing in CI and you need to reproduce |
|
|
139
|
+
| `documentation` | The task is writing a runbook or contributor doc about the migration |
|
|
140
|
+
| (a generic migration skill) | The task is a different content migration with no relation to the v2 frontmatter rollout |
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# saas-stripe-postgres — Skill Graph Example Project
|
|
2
|
+
|
|
3
|
+
This directory is an OSS specimen demonstrating Skill Graph on a realistic SaaS stack: Next.js App Router + Stripe webhooks + Postgres with row-level security. It is a documentation artifact, not a maintained starter kit.
|
|
4
|
+
|
|
5
|
+
**Purpose:** Show developers how to author, relate, and route skills for a payment-integrated, multi-tenant SaaS — so they can build their own skill library using the same patterns.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Skill Graph Structure
|
|
10
|
+
|
|
11
|
+
Five specimen skills, each representing a distinct layer of the stack:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
stripe-webhook-signature-verification
|
|
15
|
+
│ depends_on ──────────────────────────────────────┐
|
|
16
|
+
│ boundary with nextjs-server-action-validation │
|
|
17
|
+
│ verify_with nextjs-server-action-validation │
|
|
18
|
+
▼ ▼
|
|
19
|
+
payment-provider-router postgres-rls-pattern
|
|
20
|
+
│ depends_on │ verify_with
|
|
21
|
+
│ stripe-webhook-signature-verification│ migrate-orders-to-canonical-schema
|
|
22
|
+
▼ ▼
|
|
23
|
+
nextjs-server-action-validation migrate-orders-to-canonical-schema
|
|
24
|
+
│ depends_on postgres-rls-pattern │ depends_on postgres-rls-pattern
|
|
25
|
+
│ boundary stripe-webhook-... │ boundary payment-provider-router
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
| Skill | Type | Scope | Domain |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| `stripe-webhook-signature-verification` | capability | portable | engineering/payments |
|
|
31
|
+
| `postgres-rls-pattern` | capability | portable | engineering/database |
|
|
32
|
+
| `nextjs-server-action-validation` | capability | portable | engineering/web |
|
|
33
|
+
| `payment-provider-router` | router | portable | engineering/payments |
|
|
34
|
+
| `migrate-orders-to-canonical-schema` | workflow | codebase | engineering/database |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Routing Trace
|
|
39
|
+
|
|
40
|
+
**Query:** "How do I safely handle a Stripe webhook in a Next.js API route?"
|
|
41
|
+
|
|
42
|
+
This is the kind of question that activates multiple skills in sequence. Here is the routing trace showing which skills fire and why:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Input: "How do I safely handle a Stripe webhook in a Next.js API route?"
|
|
46
|
+
|
|
47
|
+
Step 1 — Router resolves candidates:
|
|
48
|
+
MATCH stripe-webhook-signature-verification
|
|
49
|
+
trigger: "stripe-webhook-signature-verification"
|
|
50
|
+
keywords: ["stripe webhook signature verification",
|
|
51
|
+
"webhook hmac verification",
|
|
52
|
+
"stripe constructEvent"]
|
|
53
|
+
score: HIGH
|
|
54
|
+
|
|
55
|
+
MATCH payment-provider-router
|
|
56
|
+
keywords: ["payment event routing", "stripe event type dispatch"]
|
|
57
|
+
score: MEDIUM
|
|
58
|
+
|
|
59
|
+
NO MATCH nextjs-server-action-validation
|
|
60
|
+
anti_examples: ["validate the stripe-signature header in a
|
|
61
|
+
webhook route handler"]
|
|
62
|
+
→ excluded by anti_example match
|
|
63
|
+
|
|
64
|
+
NO MATCH postgres-rls-pattern
|
|
65
|
+
→ no keyword/trigger overlap with webhook routing
|
|
66
|
+
|
|
67
|
+
Step 2 — Relation graph consulted:
|
|
68
|
+
stripe-webhook-signature-verification.depends_on → postgres-rls-pattern
|
|
69
|
+
(idempotency key INSERT runs inside orgQuery)
|
|
70
|
+
→ postgres-rls-pattern co-activated at lower priority
|
|
71
|
+
|
|
72
|
+
stripe-webhook-signature-verification.boundary → payment-provider-router
|
|
73
|
+
(verification is a precondition for routing)
|
|
74
|
+
→ payment-provider-router activated as step 2
|
|
75
|
+
|
|
76
|
+
Step 3 — Activation order:
|
|
77
|
+
1. stripe-webhook-signature-verification ← verify authenticity
|
|
78
|
+
2. payment-provider-router ← route to handler
|
|
79
|
+
3. postgres-rls-pattern ← query layer (co-activated)
|
|
80
|
+
|
|
81
|
+
Output: Three skills activated in dependency order.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Paste-able verification** (run from `examples/projects/saas-stripe-postgres/`):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Verify the 5 skills pass schema validation (run from skill-graph repo root)
|
|
88
|
+
cd ~/Development/skill-graph
|
|
89
|
+
node scripts/skill-lint.js \
|
|
90
|
+
examples/projects/saas-stripe-postgres/skills/stripe-webhook-signature-verification/SKILL.md \
|
|
91
|
+
examples/projects/saas-stripe-postgres/skills/postgres-rls-pattern/SKILL.md \
|
|
92
|
+
examples/projects/saas-stripe-postgres/skills/nextjs-server-action-validation/SKILL.md \
|
|
93
|
+
examples/projects/saas-stripe-postgres/skills/payment-provider-router/SKILL.md \
|
|
94
|
+
examples/projects/saas-stripe-postgres/skills/migrate-orders-to-canonical-schema/SKILL.md
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Expected output (all 5 pass T5):
|
|
98
|
+
```
|
|
99
|
+
OK [T5] stripe-webhook-signature-verification/SKILL.md
|
|
100
|
+
OK [T5] postgres-rls-pattern/SKILL.md
|
|
101
|
+
OK [T5] nextjs-server-action-validation/SKILL.md
|
|
102
|
+
OK [T5] payment-provider-router/SKILL.md
|
|
103
|
+
OK [T5] migrate-orders-to-canonical-schema/SKILL.md
|
|
104
|
+
5 file(s) checked, 0 error(s)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## What Each Skill Demonstrates
|
|
110
|
+
|
|
111
|
+
### `stripe-webhook-signature-verification` — Skill Graph Contract: Pushy Description + Negative Boundary
|
|
112
|
+
|
|
113
|
+
The description reads as a command: "Use when validating incoming Stripe webhook requests... Do NOT use for general HTTP signature validation (use a generic crypto-signature skill)."
|
|
114
|
+
|
|
115
|
+
This is the Skill Graph pattern for descriptions: pushy trigger phrase + explicit negative boundary. Claude tends to under-trigger skills with polite descriptions ("This skill provides..."). Command-form descriptions force the router to match.
|
|
116
|
+
|
|
117
|
+
### `postgres-rls-pattern` — Skill Graph Contract: Portability
|
|
118
|
+
|
|
119
|
+
`scope: portable` + `portability.readiness: portable` declares this skill is codebase-agnostic. The orgQuery wrapper pattern works on any Postgres + Node.js project without modification.
|
|
120
|
+
|
|
121
|
+
### `nextjs-server-action-validation` — Skill Graph Contract: Anti-Examples
|
|
122
|
+
|
|
123
|
+
The `anti_examples` field prevents false positives:
|
|
124
|
+
```yaml
|
|
125
|
+
anti_examples:
|
|
126
|
+
- "validate the stripe-signature header in a webhook route handler"
|
|
127
|
+
```
|
|
128
|
+
Without this, the router might activate this skill for a webhook validation query — both are about "validation". The anti_example explicitly signals: if the user is asking about `stripe-signature`, route to `stripe-webhook-signature-verification` instead.
|
|
129
|
+
|
|
130
|
+
### `payment-provider-router` — Skill Graph Contract: Router Archetype + Depends-On
|
|
131
|
+
|
|
132
|
+
`type: router` activates the router archetype section map: `## Coverage`, `## Routing Rules`, `## Do NOT Use When` (no Philosophy section). The `depends_on` relation declares that `stripe-webhook-signature-verification` must run before this router sees the event.
|
|
133
|
+
|
|
134
|
+
### `migrate-orders-to-canonical-schema` — Skill Graph Contract: Grounding
|
|
135
|
+
|
|
136
|
+
`scope: codebase` + `grounding.truth_sources` anchors this skill to actual files in the example project (`db/migrations/0004_canonicalize_orders.sql`, `db/schema.sql`). When those files change, the drift sentinel flags the skill as potentially stale. This is how Skill Graph prevents skills from becoming documentation that drifts from the code.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Drift-Check Baseline
|
|
141
|
+
|
|
142
|
+
The drift sentinel records a content hash for `truth_sources` files. When either file changes, the skill's `drift_check.last_verified` becomes stale.
|
|
143
|
+
|
|
144
|
+
To record the current baseline (run from skill-graph repo root):
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
node scripts/skill-graph-drift.js \
|
|
148
|
+
--record \
|
|
149
|
+
--apply \
|
|
150
|
+
examples/projects/saas-stripe-postgres/skills/migrate-orders-to-canonical-schema
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The command reads the `truth_sources` paths from the skill frontmatter, hashes the file contents, and writes the hashes to `drift_check.truth_source_hashes`. Future runs of `npm run drift` compare the live hashes against the recorded baseline and report STALE when they diverge.
|
|
154
|
+
|
|
155
|
+
After recording, the skill frontmatter gains a `truth_source_hashes` block:
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
drift_check:
|
|
159
|
+
last_verified: "2026-05-18"
|
|
160
|
+
truth_source_hashes:
|
|
161
|
+
examples/projects/saas-stripe-postgres/db/migrations/0004_canonicalize_orders.sql: "sha256:<hash>"
|
|
162
|
+
examples/projects/saas-stripe-postgres/db/schema.sql: "sha256:<hash>"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Skills Referenced vs. Skills in This Project
|
|
168
|
+
|
|
169
|
+
The 5 skills cross-reference each other via `relations`. They also reference skills from the main Skill Graph library (e.g., `documentation`, `refactor`) via the `boundary` predicate — those skills must exist in the configured skill root (`../skills/skills/`) for the lint check to pass.
|
|
170
|
+
|
|
171
|
+
**Skills referenced from the library root** (must exist in `../skills/skills/`):
|
|
172
|
+
|
|
173
|
+
| Referenced by | Skill referenced | Via predicate |
|
|
174
|
+
|---|---|---|
|
|
175
|
+
| (all skills) | Standard library skills | (none in this example — intra-project only) |
|
|
176
|
+
|
|
177
|
+
These 5 specimens only cross-reference each other. They are self-contained within the example project.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## File Structure
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
examples/projects/saas-stripe-postgres/
|
|
185
|
+
├── README.md ← this file
|
|
186
|
+
├── db/
|
|
187
|
+
│ ├── schema.sql ← canonical table + RLS policy definitions
|
|
188
|
+
│ └── migrations/
|
|
189
|
+
│ └── 0004_canonicalize_orders.sql ← Phase 1+2 of orders canonicalization
|
|
190
|
+
└── skills/
|
|
191
|
+
├── stripe-webhook-signature-verification/SKILL.md
|
|
192
|
+
├── postgres-rls-pattern/SKILL.md
|
|
193
|
+
├── nextjs-server-action-validation/SKILL.md
|
|
194
|
+
├── payment-provider-router/SKILL.md
|
|
195
|
+
└── migrate-orders-to-canonical-schema/SKILL.md
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Why These 5 Skills?
|
|
201
|
+
|
|
202
|
+
These specimens were chosen by the IMPROVEMENT_PLAN 2026-05-06 board meeting (U19 edit) to demonstrate Skill Graph's contract on a realistic stack:
|
|
203
|
+
|
|
204
|
+
- **Stripe webhook + RLS + Server Action** covers the three most common "how do I do this securely?" questions in a SaaS codebase
|
|
205
|
+
- **Payment router** demonstrates the `type: router` archetype, distinct from `capability` and `workflow`
|
|
206
|
+
- **Migration** demonstrates `scope: codebase` grounding and the four-phase procedure pattern — the hardest migration category to get right
|
|
207
|
+
|
|
208
|
+
Each skill is a specimen for learning, not a production recommendation. The patterns are generic; adopt them and adapt them to your own codebase.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
-- Migration 0004: Canonicalize orders table
|
|
2
|
+
-- Changes: Stripe-specific column names → provider-agnostic names
|
|
3
|
+
-- stripe_session_id → provider_order_id
|
|
4
|
+
-- stripe_customer_id → provider_customer_id
|
|
5
|
+
-- (new) provider column set to 'stripe' for all existing rows
|
|
6
|
+
--
|
|
7
|
+
-- SAFE MIGRATION — four-phase procedure:
|
|
8
|
+
-- Phase 1: Add nullable columns (this file, deploy first)
|
|
9
|
+
-- Phase 2: Backfill data (this file, run after Phase 1 deploys)
|
|
10
|
+
-- Phase 3: Update application code to read new columns (manual, 24h observation)
|
|
11
|
+
-- Phase 4: Drop legacy columns (separate migration file 0004b)
|
|
12
|
+
--
|
|
13
|
+
-- Do NOT run Phase 4 (0004b) until 0 reads of stripe_session_id appear in logs
|
|
14
|
+
-- for at least 24 hours after Phase 3 application deployment.
|
|
15
|
+
|
|
16
|
+
-- ─── Phase 1: Add nullable canonical columns ─────────────────────────────────
|
|
17
|
+
ALTER TABLE orders
|
|
18
|
+
ADD COLUMN IF NOT EXISTS provider TEXT,
|
|
19
|
+
ADD COLUMN IF NOT EXISTS provider_order_id TEXT,
|
|
20
|
+
ADD COLUMN IF NOT EXISTS provider_customer_id TEXT;
|
|
21
|
+
|
|
22
|
+
-- ─── Phase 2: Backfill from Stripe-specific columns ──────────────────────────
|
|
23
|
+
-- Run: psql $DATABASE_URL -f 0004_canonicalize_orders.sql
|
|
24
|
+
-- Or: node scripts/migrate-orders.ts --apply (dry-run by default)
|
|
25
|
+
|
|
26
|
+
UPDATE orders
|
|
27
|
+
SET
|
|
28
|
+
provider = 'stripe',
|
|
29
|
+
provider_order_id = stripe_session_id,
|
|
30
|
+
provider_customer_id = stripe_customer_id
|
|
31
|
+
WHERE provider IS NULL;
|
|
32
|
+
|
|
33
|
+
-- Verify: SELECT COUNT(*) FROM orders WHERE provider IS NULL;
|
|
34
|
+
-- Expected: 0 rows
|
|
35
|
+
|
|
36
|
+
-- ─── Phase 4 is in 0004b_drop_legacy_columns.sql ────────────────────────────
|
|
37
|
+
-- Only run 0004b after Phase 3 observation period (24h, zero old-column reads).
|