@jairodri/huckleberry-cli 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -0
- package/agents/cos.json +2 -5
- package/agents/hermes/AGENTS.md +25 -49
- package/agents/hermes/fix-kimaki/SKILL.md +19 -92
- package/agents/hermes/hermes-fixer.md +44 -74
- package/agents/hermes.json +6 -18
- package/kanban/SKILL.md +18 -18
- package/kanban/package.json +1 -1
- package/kanban/src/dispatcher.mjs +1 -1
- package/kanban/templates/blog-social-campaign.yaml +6 -2
- package/kanban/templates/social-campaign.yaml +9 -4
- package/mcp/jev-calibration.mjs +335 -0
- package/mcp/jev-client.mjs +119 -0
- package/mcp/jev-thresholds.json +27 -0
- package/package.json +13 -9
- package/scripts/doctor-watchdog.sh +73 -0
- package/scripts/install-services.sh +34 -27
- package/scripts/self-improve-weekly.sh +34 -0
- package/scripts/sync-skills.mjs +121 -0
- package/skills/ab-test-setup/SKILL.md +266 -0
- package/skills/ab-test-setup/evals/evals.json +105 -0
- package/skills/ab-test-setup/references/sample-size-guide.md +263 -0
- package/skills/ab-test-setup/references/test-templates.md +277 -0
- package/skills/agent-reach/SKILL.md +132 -0
- package/skills/agent-reach/references/career.md +29 -0
- package/skills/agent-reach/references/dev.md +62 -0
- package/skills/agent-reach/references/search.md +33 -0
- package/skills/agent-reach/references/social.md +232 -0
- package/skills/agent-reach/references/video.md +130 -0
- package/skills/agent-reach/references/web.md +50 -0
- package/skills/ai-agent-seo/SKILL.md +450 -0
- package/skills/ai-cold-email-intelligence/SKILL.md +54 -0
- package/skills/ai-cold-email-intelligence/references/prompts.md +21 -0
- package/skills/ai-consensus-builder/SKILL.md +324 -0
- package/skills/ai-seo/SKILL.md +399 -0
- package/skills/ai-seo/evals/evals.json +90 -0
- package/skills/ai-seo/references/content-patterns.md +284 -0
- package/skills/ai-seo/references/platform-ranking-factors.md +152 -0
- package/skills/ai-visibility-audit/SKILL.md +322 -0
- package/skills/analytics-tracking/SKILL.md +309 -0
- package/skills/analytics-tracking/evals/evals.json +90 -0
- package/skills/analytics-tracking/references/event-library.md +260 -0
- package/skills/analytics-tracking/references/ga4-implementation.md +300 -0
- package/skills/analytics-tracking/references/gtm-implementation.md +390 -0
- package/skills/article-generator/SKILL.md +216 -0
- package/skills/auto-indexing/SKILL.md +179 -0
- package/skills/auto-indexing/scripts/auto-indexing.js +257 -0
- package/skills/auto-skill/SKILL.md +151 -0
- package/skills/auto-skill/correction-queue.js +102 -0
- package/skills/auto-skill/dedup.js +97 -0
- package/skills/auto-skill/skill-router.js +224 -0
- package/skills/autoresearch/SKILL.md +334 -0
- package/skills/autoresearch/autoresearch-autoresearch/SKILL.md.baseline +329 -0
- package/skills/autoresearch/autoresearch-autoresearch/changelog.md +34 -0
- package/skills/autoresearch/autoresearch-autoresearch/dashboard.html +116 -0
- package/skills/autoresearch/autoresearch-autoresearch/evals.md +39 -0
- package/skills/autoresearch/autoresearch-autoresearch/results.json +44 -0
- package/skills/autoresearch/autoresearch-autoresearch/results.tsv +3 -0
- package/skills/autoresearch/eval-guide.md +121 -0
- package/skills/b2b-cold-outreach/SKILL.md +322 -0
- package/skills/birdclaw/SKILL.md +82 -0
- package/skills/brainstorm/SKILL.md +168 -0
- package/skills/brand-kit-playground/SKILL.md +312 -0
- package/skills/brand-kit-playground/references/html-architecture.md +316 -0
- package/skills/brand-kit-playground/references/steal-patterns.md +88 -0
- package/skills/brand-voice/SKILL.md +223 -0
- package/skills/brand-voice/references/honesty-as-positioning.md +60 -0
- package/skills/brand-voice/references/voice-modes.md +1158 -0
- package/skills/business-advisory-council/README.md +136 -0
- package/skills/business-advisory-council/SKILL.md +94 -0
- package/skills/business-advisory-council/business-advisory-council.py +492 -0
- package/skills/business-advisory-council/discord-components-decision.json +8 -0
- package/skills/business-advisory-council/examples/steve-conley-partnership.json +6 -0
- package/skills/business-advisory-council/steve-conley-call-brief.json +6 -0
- package/skills/churn-prevention/SKILL.md +305 -0
- package/skills/churn-prevention/evals/evals.json +93 -0
- package/skills/churn-prevention/references/cancel-flow-patterns.md +316 -0
- package/skills/churn-prevention/references/dunning-playbook.md +408 -0
- package/skills/claw-compactor/LICENSE +21 -0
- package/skills/claw-compactor/README.md +459 -0
- package/skills/claw-compactor/SKILL.md +329 -0
- package/skills/claw-compactor/benchmark/RESULTS.md +104 -0
- package/skills/claw-compactor/benchmark/__init__.py +1 -0
- package/skills/claw-compactor/benchmark/compressors.py +520 -0
- package/skills/claw-compactor/benchmark/data/sample_01_devops.json +82 -0
- package/skills/claw-compactor/benchmark/data/sample_02_trading.json +54 -0
- package/skills/claw-compactor/benchmark/data/sample_03_ml_short.json +38 -0
- package/skills/claw-compactor/benchmark/data/sample_04_mixed_long.json +318 -0
- package/skills/claw-compactor/benchmark/data/sample_05_sysadmin.json +56 -0
- package/skills/claw-compactor/benchmark/evaluate.py +278 -0
- package/skills/claw-compactor/benchmark/report.py +241 -0
- package/skills/claw-compactor/benchmark/results/benchmark_results.json +405 -0
- package/skills/claw-compactor/benchmark/run_benchmark.py +238 -0
- package/skills/claw-compactor/engram.yaml +49 -0
- package/skills/claw-compactor/proxy/README.md +87 -0
- package/skills/claw-compactor/proxy/dashboard.html +804 -0
- package/skills/claw-compactor/proxy/event-log.mjs +213 -0
- package/skills/claw-compactor/proxy/fair-queue.mjs +288 -0
- package/skills/claw-compactor/proxy/metrics-store.mjs +425 -0
- package/skills/claw-compactor/proxy/package-lock.json +125 -0
- package/skills/claw-compactor/proxy/package.json +15 -0
- package/skills/claw-compactor/proxy/portal.html +360 -0
- package/skills/claw-compactor/proxy/process-registry.mjs +447 -0
- package/skills/claw-compactor/proxy/rate-limiter.mjs +117 -0
- package/skills/claw-compactor/proxy/redis-client.mjs +75 -0
- package/skills/claw-compactor/proxy/retry.mjs +182 -0
- package/skills/claw-compactor/proxy/server.mjs +2100 -0
- package/skills/claw-compactor/proxy/session-affinity.mjs +177 -0
- package/skills/claw-compactor/proxy/start.sh +23 -0
- package/skills/claw-compactor/proxy/test/event-log.test.mjs +237 -0
- package/skills/claw-compactor/proxy/test/helpers.mjs +103 -0
- package/skills/claw-compactor/proxy/test/integration.test.mjs +297 -0
- package/skills/claw-compactor/proxy/test/metrics-store.test.mjs +243 -0
- package/skills/claw-compactor/proxy/test/process-registry.test.mjs +390 -0
- package/skills/claw-compactor/proxy/test/rate-limiter.test.mjs +121 -0
- package/skills/claw-compactor/proxy/test/redis-client.test.mjs +62 -0
- package/skills/claw-compactor/proxy/test/token-tracker.test.mjs +200 -0
- package/skills/claw-compactor/proxy/token-tracker.mjs +482 -0
- package/skills/claw-compactor/pyproject.toml +26 -0
- package/skills/claw-compactor/references/README.md +44 -0
- package/skills/claw-compactor/references/architecture.md +197 -0
- package/skills/claw-compactor/references/benchmarks.md +94 -0
- package/skills/claw-compactor/references/compression-prompts.md +39 -0
- package/skills/claw-compactor/references/compression-techniques.md +219 -0
- package/skills/claw-compactor/references/testing.md +160 -0
- package/skills/claw-compactor/scripts/audit_memory.py +216 -0
- package/skills/claw-compactor/scripts/compress_memory.py +236 -0
- package/skills/claw-compactor/scripts/compressed_context.py +280 -0
- package/skills/claw-compactor/scripts/dedup_memory.py +147 -0
- package/skills/claw-compactor/scripts/dictionary_compress.py +170 -0
- package/skills/claw-compactor/scripts/engram-auto.sh +152 -0
- package/skills/claw-compactor/scripts/engram_auto.py +695 -0
- package/skills/claw-compactor/scripts/engram_cli.py +474 -0
- package/skills/claw-compactor/scripts/estimate_tokens.py +131 -0
- package/skills/claw-compactor/scripts/generate_summary_tiers.py +292 -0
- package/skills/claw-compactor/scripts/lib/__init__.py +34 -0
- package/skills/claw-compactor/scripts/lib/config.py +289 -0
- package/skills/claw-compactor/scripts/lib/dedup.py +119 -0
- package/skills/claw-compactor/scripts/lib/dictionary.py +281 -0
- package/skills/claw-compactor/scripts/lib/engram.py +793 -0
- package/skills/claw-compactor/scripts/lib/engram_prompts.py +175 -0
- package/skills/claw-compactor/scripts/lib/engram_storage.py +254 -0
- package/skills/claw-compactor/scripts/lib/exceptions.py +24 -0
- package/skills/claw-compactor/scripts/lib/markdown.py +312 -0
- package/skills/claw-compactor/scripts/lib/rle.py +165 -0
- package/skills/claw-compactor/scripts/lib/tokenizer_optimizer.py +188 -0
- package/skills/claw-compactor/scripts/lib/tokens.py +68 -0
- package/skills/claw-compactor/scripts/mem_compress.py +788 -0
- package/skills/claw-compactor/scripts/observation_compressor.py +346 -0
- package/skills/claw-compactor/tests/__init__.py +0 -0
- package/skills/claw-compactor/tests/conftest.py +94 -0
- package/skills/claw-compactor/tests/test_audit_comprehensive.py +123 -0
- package/skills/claw-compactor/tests/test_audit_memory.py +67 -0
- package/skills/claw-compactor/tests/test_benchmark.py +122 -0
- package/skills/claw-compactor/tests/test_cli_commands.py +228 -0
- package/skills/claw-compactor/tests/test_compress_memory.py +109 -0
- package/skills/claw-compactor/tests/test_compress_memory_comprehensive.py +191 -0
- package/skills/claw-compactor/tests/test_compressed_context.py +145 -0
- package/skills/claw-compactor/tests/test_config.py +54 -0
- package/skills/claw-compactor/tests/test_dedup_memory.py +124 -0
- package/skills/claw-compactor/tests/test_dictionary.py +327 -0
- package/skills/claw-compactor/tests/test_dictionary_comprehensive.py +241 -0
- package/skills/claw-compactor/tests/test_engram.py +1091 -0
- package/skills/claw-compactor/tests/test_engram_auto.py +529 -0
- package/skills/claw-compactor/tests/test_error_handling.py +194 -0
- package/skills/claw-compactor/tests/test_estimate_tokens.py +99 -0
- package/skills/claw-compactor/tests/test_generate_summary_tiers.py +105 -0
- package/skills/claw-compactor/tests/test_integration.py +249 -0
- package/skills/claw-compactor/tests/test_lib_dedup.py +135 -0
- package/skills/claw-compactor/tests/test_lib_markdown.py +388 -0
- package/skills/claw-compactor/tests/test_lib_tokens.py +82 -0
- package/skills/claw-compactor/tests/test_main_entry.py +176 -0
- package/skills/claw-compactor/tests/test_markdown_advanced.py +284 -0
- package/skills/claw-compactor/tests/test_new_features.py +77 -0
- package/skills/claw-compactor/tests/test_observation_comprehensive.py +261 -0
- package/skills/claw-compactor/tests/test_observation_compressor.py +128 -0
- package/skills/claw-compactor/tests/test_performance.py +172 -0
- package/skills/claw-compactor/tests/test_pipeline.py +109 -0
- package/skills/claw-compactor/tests/test_real_workspace.py +161 -0
- package/skills/claw-compactor/tests/test_rle.py +114 -0
- package/skills/claw-compactor/tests/test_rle_comprehensive.py +151 -0
- package/skills/claw-compactor/tests/test_roundtrip.py +253 -0
- package/skills/claw-compactor/tests/test_roundtrip_comprehensive.py +192 -0
- package/skills/claw-compactor/tests/test_tiers_comprehensive.py +171 -0
- package/skills/claw-compactor/tests/test_token_economics.py +237 -0
- package/skills/claw-compactor/tests/test_tokenizer_optimizer.py +175 -0
- package/skills/claw-compactor/tests/test_tokenizer_optimizer_comprehensive.py +241 -0
- package/skills/claw-compactor/tests/test_tokens.py +27 -0
- package/skills/cmo/CHANGELOG.md +61 -0
- package/skills/cmo/SKILL.md +500 -0
- package/skills/cmo/references/ai-slop-patterns.md +56 -0
- package/skills/cmo/references/analytics-guide.md +152 -0
- package/skills/cmo/references/ideas-library.md +197 -0
- package/skills/cmo/rules/brand-file-map.md +198 -0
- package/skills/cmo/rules/brand-memory.md +158 -0
- package/skills/cmo/rules/cli-runtime-index.md +95 -0
- package/skills/cmo/rules/command-reference.md +167 -0
- package/skills/cmo/rules/communication.md +15 -0
- package/skills/cmo/rules/context-switch.md +101 -0
- package/skills/cmo/rules/ecosystem.md +125 -0
- package/skills/cmo/rules/error-recovery.md +98 -0
- package/skills/cmo/rules/learning-loop.md +170 -0
- package/skills/cmo/rules/monorepo.md +78 -0
- package/skills/cmo/rules/output-format.md +124 -0
- package/skills/cmo/rules/persona.md +15 -0
- package/skills/cmo/rules/playbooks.md +327 -0
- package/skills/cmo/rules/progressive-enhancement.md +231 -0
- package/skills/cmo/rules/publish-index.md +106 -0
- package/skills/cmo/rules/quality-gate.md +90 -0
- package/skills/cmo/rules/recency-grounding.md +124 -0
- package/skills/cmo/rules/safety.md +80 -0
- package/skills/cmo/rules/studio-api-index.md +138 -0
- package/skills/cmo/rules/studio-integration.md +147 -0
- package/skills/cmo/rules/sub-agents.md +167 -0
- package/skills/cold-email/SKILL.md +240 -0
- package/skills/cold-email/evals/evals.json +94 -0
- package/skills/cold-email/references/benchmarks.md +83 -0
- package/skills/cold-email/references/follow-up-sequences.md +81 -0
- package/skills/cold-email/references/frameworks.md +90 -0
- package/skills/cold-email/references/personalization.md +79 -0
- package/skills/cold-email/references/subject-lines.md +53 -0
- package/skills/competitive-intel/SKILL.md +433 -0
- package/skills/competitive-intel/references/competitive-frameworks.md +145 -0
- package/skills/competitor-alternatives/SKILL.md +362 -0
- package/skills/competitor-alternatives/evals/evals.json +93 -0
- package/skills/competitor-alternatives/references/content-architecture.md +271 -0
- package/skills/competitor-alternatives/references/templates.md +223 -0
- package/skills/concreteness-fixer/SKILL.md +483 -0
- package/skills/concreteness-fixer/scripts/validation/concreteness-validator.js +221 -0
- package/skills/concreteness-fixer/utils/execFileNoThrow.js +16 -0
- package/skills/content-atomizer/SKILL.md +424 -0
- package/skills/content-atomizer/references/hook-strategies.md +56 -0
- package/skills/content-atomizer/references/platform-specs.md +118 -0
- package/skills/content-atomizer/references/platforms/bluesky.md +64 -0
- package/skills/content-atomizer/references/platforms/instagram.md +77 -0
- package/skills/content-atomizer/references/platforms/linkedin.md +120 -0
- package/skills/content-atomizer/references/platforms/reddit.md +73 -0
- package/skills/content-atomizer/references/platforms/threads.md +64 -0
- package/skills/content-atomizer/references/platforms/tiktok.md +55 -0
- package/skills/content-atomizer/references/platforms/twitter.md +123 -0
- package/skills/content-atomizer/references/platforms/youtube.md +56 -0
- package/skills/content-atomizer/references/tweet-patterns.md +40 -0
- package/skills/content-repost-manager/SKILL.md +245 -0
- package/skills/content-repost-manager/scripts/content-repost-scan.py +133 -0
- package/skills/context-recovery/.clawdhub/origin.json +7 -0
- package/skills/context-recovery/SKILL.md +198 -0
- package/skills/context-recovery/_meta.json +6 -0
- package/skills/conversion-flow-cro/SKILL.md +248 -0
- package/skills/conversion-flow-cro/references/flow-benchmarks.md +158 -0
- package/skills/copy-editing/SKILL.md +474 -0
- package/skills/copy-editing/evals/evals.json +89 -0
- package/skills/copy-editing/references/plain-english-alternatives.md +394 -0
- package/skills/copywriting/SKILL.md +349 -0
- package/skills/copywriting/evals/evals.json +111 -0
- package/skills/copywriting/references/awareness-level-guide.md +227 -0
- package/skills/copywriting/references/copy-frameworks.md +389 -0
- package/skills/copywriting/references/natural-transitions.md +272 -0
- package/skills/creative/SKILL.md +365 -0
- package/skills/creative/modes/ad-creative.md +1748 -0
- package/skills/creative/modes/product-photo.md +1520 -0
- package/skills/creative/modes/product-video.md +1657 -0
- package/skills/creative/modes/social-graphics.md +1511 -0
- package/skills/creative/modes/talking-head.md +2208 -0
- package/skills/creative/references/VISUAL_INTELLIGENCE.md +1233 -0
- package/skills/deep-serp-article/SKILL.md +677 -0
- package/skills/deep-serp-article/SKILL.md.bak +530 -0
- package/skills/earned-media/SKILL.md +260 -0
- package/skills/email-sequences/SKILL.md +446 -0
- package/skills/email-sequences/references/sequence-templates.md +1217 -0
- package/skills/firecrawl/.skill-meta.json +13 -0
- package/skills/firecrawl/SKILL.md +154 -0
- package/skills/firecrawl/rules/install.md +63 -0
- package/skills/firecrawl/rules/security.md +26 -0
- package/skills/form-cro/SKILL.md +429 -0
- package/skills/form-cro/evals/evals.json +90 -0
- package/skills/free-tool-strategy/SKILL.md +325 -0
- package/skills/free-tool-strategy/evals/evals.json +90 -0
- package/skills/free-tool-strategy/references/tool-types.md +253 -0
- package/skills/frontend-slides/SKILL.md +248 -0
- package/skills/frontend-slides/STYLE_PRESETS.md +347 -0
- package/skills/frontend-slides/animation-patterns.md +110 -0
- package/skills/frontend-slides/html-template.md +347 -0
- package/skills/frontend-slides/scripts/extract-pptx.py +96 -0
- package/skills/frontend-slides/viewport-base.css +153 -0
- package/skills/guardrail-framework/SKILL.md +319 -0
- package/skills/hook-generator/SKILL.md +438 -0
- package/skills/hook-generator/database/2026-PLATFORM-RESEARCH.md +211 -0
- package/skills/hook-generator/database/instagram-hooks.json +591 -0
- package/skills/hook-generator/database/linkedin-hooks.json +502 -0
- package/skills/hook-generator/database/medium-hooks.json +181 -0
- package/skills/hook-generator/database/tiktok-hooks.json +337 -0
- package/skills/hook-generator/database/twitter-hooks.json +567 -0
- package/skills/hook-generator/database/youtube-hooks.json +275 -0
- package/skills/hook-generator/package-lock.json +24 -0
- package/skills/hook-generator/package.json +5 -0
- package/skills/hook-generator/references/hook-generation-system.md +257 -0
- package/skills/hook-generator/references/hook-performance-analysis.json +153 -0
- package/skills/hook-generator/references/hooks-library.md +128 -0
- package/skills/hook-generator/references/platform-hook-frameworks.md +275 -0
- package/skills/hook-generator/scripts/generate-hooks-unified.js +722 -0
- package/skills/hook-generator/scripts/generate-hooks.js +225 -0
- package/skills/hook-generator/scripts/generate.sh +36 -0
- package/skills/hook-generator/scripts/ralph-hook-enhancer.js +864 -0
- package/skills/hook-generator/scripts/test-gemini-output.js +51 -0
- package/skills/humanizer/README.md +120 -0
- package/skills/humanizer/SKILL.md +699 -0
- package/skills/image-gen/SKILL.md +277 -0
- package/skills/image-gen/references/prompt-patterns.md +114 -0
- package/skills/image-gen/references/visual-metaphors.md +51 -0
- package/skills/impeccable/SKILL.md +86 -0
- package/skills/impeccable/reference/adapt.md +312 -0
- package/skills/impeccable/reference/adapt.native.md +58 -0
- package/skills/impeccable/reference/android.md +40 -0
- package/skills/impeccable/reference/animate.md +86 -0
- package/skills/impeccable/reference/audit.md +136 -0
- package/skills/impeccable/reference/audit.native.md +139 -0
- package/skills/impeccable/reference/bolder.md +31 -0
- package/skills/impeccable/reference/clarify.md +94 -0
- package/skills/impeccable/reference/colorize.md +86 -0
- package/skills/impeccable/reference/craft-floor.md +42 -0
- package/skills/impeccable/reference/craft.md +5 -0
- package/skills/impeccable/reference/critique.md +788 -0
- package/skills/impeccable/reference/degraded/asset-producer.md +90 -0
- package/skills/impeccable/reference/degraded/documenter.md +24 -0
- package/skills/impeccable/reference/degraded/finish-reviewer.md +37 -0
- package/skills/impeccable/reference/degraded/manual-edit-applier.md +92 -0
- package/skills/impeccable/reference/delight.md +70 -0
- package/skills/impeccable/reference/distill.md +111 -0
- package/skills/impeccable/reference/doctor.md +53 -0
- package/skills/impeccable/reference/document.md +416 -0
- package/skills/impeccable/reference/extract.md +69 -0
- package/skills/impeccable/reference/harden.md +336 -0
- package/skills/impeccable/reference/hooks.md +105 -0
- package/skills/impeccable/reference/init.md +125 -0
- package/skills/impeccable/reference/ios.md +45 -0
- package/skills/impeccable/reference/layout.md +84 -0
- package/skills/impeccable/reference/live-setup.md +102 -0
- package/skills/impeccable/reference/live.md +323 -0
- package/skills/impeccable/reference/new-work.md +110 -0
- package/skills/impeccable/reference/onboard.md +234 -0
- package/skills/impeccable/reference/operate.md +61 -0
- package/skills/impeccable/reference/optimize.md +258 -0
- package/skills/impeccable/reference/overdrive.md +127 -0
- package/skills/impeccable/reference/polish.md +97 -0
- package/skills/impeccable/reference/quieter.md +99 -0
- package/skills/impeccable/reference/routing.md +18 -0
- package/skills/impeccable/reference/shape.md +59 -0
- package/skills/impeccable/reference/typeset.md +80 -0
- package/skills/impeccable/reference/visualize.md +49 -0
- package/skills/impeccable/scripts/command-metadata.json +94 -0
- package/skills/impeccable/scripts/concept-seed.mjs +558 -0
- package/skills/impeccable/scripts/context-signals.mjs +334 -0
- package/skills/impeccable/scripts/context.mjs +1467 -0
- package/skills/impeccable/scripts/critique-storage.mjs +213 -0
- package/skills/impeccable/scripts/detect-csp.mjs +198 -0
- package/skills/impeccable/scripts/detect.mjs +21 -0
- package/skills/impeccable/scripts/detector/browser/injected/index.mjs +2023 -0
- package/skills/impeccable/scripts/detector/cli/main.mjs +438 -0
- package/skills/impeccable/scripts/detector/design-system.mjs +1046 -0
- package/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +8283 -0
- package/skills/impeccable/scripts/detector/detect-antipatterns.mjs +50 -0
- package/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +372 -0
- package/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +1168 -0
- package/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +1186 -0
- package/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +264 -0
- package/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +189 -0
- package/skills/impeccable/scripts/detector/findings.mjs +18 -0
- package/skills/impeccable/scripts/detector/node/file-system.mjs +203 -0
- package/skills/impeccable/scripts/detector/profile/profiler.mjs +166 -0
- package/skills/impeccable/scripts/detector/registry/antipatterns.mjs +617 -0
- package/skills/impeccable/scripts/detector/rules/checks.mjs +5580 -0
- package/skills/impeccable/scripts/detector/shared/color.mjs +124 -0
- package/skills/impeccable/scripts/detector/shared/constants.mjs +112 -0
- package/skills/impeccable/scripts/detector/shared/fonts.mjs +30 -0
- package/skills/impeccable/scripts/detector/shared/inline-ignores.mjs +148 -0
- package/skills/impeccable/scripts/detector/shared/page.mjs +7 -0
- package/skills/impeccable/scripts/doctor.mjs +336 -0
- package/skills/impeccable/scripts/embed-prompt.mjs +133 -0
- package/skills/impeccable/scripts/generate-image.mjs +240 -0
- package/skills/impeccable/scripts/hook-admin.mjs +801 -0
- package/skills/impeccable/scripts/hook-before-edit.mjs +508 -0
- package/skills/impeccable/scripts/hook-lib.mjs +2153 -0
- package/skills/impeccable/scripts/hook.mjs +78 -0
- package/skills/impeccable/scripts/lib/artifact-schema.mjs +93 -0
- package/skills/impeccable/scripts/lib/composition-catalog.mjs +200 -0
- package/skills/impeccable/scripts/lib/concept-catalog.mjs +384 -0
- package/skills/impeccable/scripts/lib/design-parser.mjs +925 -0
- package/skills/impeccable/scripts/lib/impeccable-config.mjs +658 -0
- package/skills/impeccable/scripts/lib/impeccable-paths.mjs +137 -0
- package/skills/impeccable/scripts/lib/is-generated.mjs +69 -0
- package/skills/impeccable/scripts/lib/provider.mjs +5 -0
- package/skills/impeccable/scripts/lib/roll-selection.mjs +362 -0
- package/skills/impeccable/scripts/lib/staleness-deep.mjs +478 -0
- package/skills/impeccable/scripts/lib/staleness-notice.mjs +169 -0
- package/skills/impeccable/scripts/lib/staleness.mjs +457 -0
- package/skills/impeccable/scripts/lib/surface-briefs.mjs +151 -0
- package/skills/impeccable/scripts/lib/target-args.mjs +42 -0
- package/skills/impeccable/scripts/lib/target-slug.mjs +33 -0
- package/skills/impeccable/scripts/lib/template-extensions.mjs +146 -0
- package/skills/impeccable/scripts/live/accept-css.mjs +617 -0
- package/skills/impeccable/scripts/live/accept-verify.mjs +60 -0
- package/skills/impeccable/scripts/live/browser-script-parts.mjs +55 -0
- package/skills/impeccable/scripts/live/completion.mjs +28 -0
- package/skills/impeccable/scripts/live/event-validation.mjs +199 -0
- package/skills/impeccable/scripts/live/frameworks/astro.mjs +47 -0
- package/skills/impeccable/scripts/live/frameworks/detect-utils.mjs +73 -0
- package/skills/impeccable/scripts/live/frameworks/index.mjs +143 -0
- package/skills/impeccable/scripts/live/frameworks/journal.mjs +197 -0
- package/skills/impeccable/scripts/live/frameworks/nextjs.mjs +49 -0
- package/skills/impeccable/scripts/live/frameworks/nuxt.mjs +161 -0
- package/skills/impeccable/scripts/live/frameworks/script-src.mjs +17 -0
- package/skills/impeccable/scripts/live/frameworks/static-html.mjs +26 -0
- package/skills/impeccable/scripts/live/frameworks/sveltekit.mjs +71 -0
- package/skills/impeccable/scripts/live/frameworks/tag-strategy.mjs +247 -0
- package/skills/impeccable/scripts/live/frameworks/tanstack-start.mjs +70 -0
- package/skills/impeccable/scripts/live/frameworks/vite-generic.mjs +42 -0
- package/skills/impeccable/scripts/live/generation-preflight.mjs +149 -0
- package/skills/impeccable/scripts/live/insert-ui.mjs +458 -0
- package/skills/impeccable/scripts/live/instructions.mjs +142 -0
- package/skills/impeccable/scripts/live/manual-apply.mjs +939 -0
- package/skills/impeccable/scripts/live/manual-edit-routes.mjs +357 -0
- package/skills/impeccable/scripts/live/manual-edits-buffer.mjs +152 -0
- package/skills/impeccable/scripts/live/poll-lanes.mjs +14 -0
- package/skills/impeccable/scripts/live/roots.mjs +508 -0
- package/skills/impeccable/scripts/live/session-store.mjs +563 -0
- package/skills/impeccable/scripts/live/source-lock.mjs +105 -0
- package/skills/impeccable/scripts/live/source-search.mjs +105 -0
- package/skills/impeccable/scripts/live/svelte-ast.mjs +961 -0
- package/skills/impeccable/scripts/live/svelte-component.mjs +1342 -0
- package/skills/impeccable/scripts/live/sveltekit-adapter.mjs +316 -0
- package/skills/impeccable/scripts/live/tanstack-adapter.mjs +280 -0
- package/skills/impeccable/scripts/live/ui-core.mjs +180 -0
- package/skills/impeccable/scripts/live/vocabulary.mjs +171 -0
- package/skills/impeccable/scripts/live-accept.mjs +954 -0
- package/skills/impeccable/scripts/live-browser-dom.js +146 -0
- package/skills/impeccable/scripts/live-browser-session.js +123 -0
- package/skills/impeccable/scripts/live-browser.js +12520 -0
- package/skills/impeccable/scripts/live-commit-manual-edits.mjs +1244 -0
- package/skills/impeccable/scripts/live-complete.mjs +107 -0
- package/skills/impeccable/scripts/live-copy-edit-agent.mjs +683 -0
- package/skills/impeccable/scripts/live-discard-manual-edits.mjs +51 -0
- package/skills/impeccable/scripts/live-inject.mjs +503 -0
- package/skills/impeccable/scripts/live-insert.mjs +292 -0
- package/skills/impeccable/scripts/live-manual-edit-evidence.mjs +368 -0
- package/skills/impeccable/scripts/live-poll.mjs +429 -0
- package/skills/impeccable/scripts/live-resume.mjs +123 -0
- package/skills/impeccable/scripts/live-server.mjs +1669 -0
- package/skills/impeccable/scripts/live-status.mjs +71 -0
- package/skills/impeccable/scripts/live-target.mjs +30 -0
- package/skills/impeccable/scripts/live-wrap.mjs +927 -0
- package/skills/impeccable/scripts/live.mjs +359 -0
- package/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
- package/skills/impeccable/scripts/palette.mjs +628 -0
- package/skills/impeccable/scripts/pin.mjs +221 -0
- package/skills/impeccable/scripts/serve-question.mjs +932 -0
- package/skills/impeccable/scripts/surface-brief.mjs +74 -0
- package/skills/inkstone-admin/SKILL.md +66 -0
- package/skills/jev-hook-gate/SKILL.md +111 -0
- package/skills/keyword-research/SKILL.md +503 -0
- package/skills/keyword-research/references/dr-cap-and-confidence.md +62 -0
- package/skills/keyword-research/references/keyword-examples.md +769 -0
- package/skills/landing-page-architect/SKILL.md +585 -0
- package/skills/landing-page-architect/references/architecture-reference.md +32 -0
- package/skills/launch-strategy/SKILL.md +384 -0
- package/skills/launch-strategy/evals/evals.json +91 -0
- package/skills/launch-strategy/references/launch-checklist.md +209 -0
- package/skills/launch-strategy/references/launch-timeline.md +159 -0
- package/skills/lead-email-craft/SKILL.md +522 -0
- package/skills/lead-magnets/SKILL.md +310 -0
- package/skills/lead-magnets/references/benchmarks.md +129 -0
- package/skills/lead-magnets/references/format-guide.md +196 -0
- package/skills/link-building-seo/SKILL.md +210 -0
- package/skills/lint-report.txt +1 -0
- package/skills/manifest.json +129 -0
- package/skills/marketing-demo/SKILL.md +249 -0
- package/skills/marketing-demo/references/remotion-examples.md +281 -0
- package/skills/marketing-ideas/SKILL.md +167 -0
- package/skills/marketing-ideas/evals/evals.json +90 -0
- package/skills/marketing-ideas/references/ideas-by-category.md +366 -0
- package/skills/marketing-psychology/SKILL.md +374 -0
- package/skills/marketing-psychology/evals/evals.json +88 -0
- package/skills/marketing-psychology/references/case-studies.md +148 -0
- package/skills/narrative-research-article/SKILL.md +469 -0
- package/skills/narrative-research-article/references/lanusse-patterns.md +166 -0
- package/skills/notebooklm/SKILL.md +674 -0
- package/skills/off-page-seo/SKILL.md +219 -0
- package/skills/onboarding-cro/SKILL.md +220 -0
- package/skills/onboarding-cro/evals/evals.json +92 -0
- package/skills/onboarding-cro/references/experiments.md +258 -0
- package/skills/original-research/SKILL.md +388 -0
- package/skills/page-cro/SKILL.md +269 -0
- package/skills/page-cro/references/cro-benchmarks.md +140 -0
- package/skills/paper-marketing/SKILL.md +448 -0
- package/skills/paper-marketing/references/agent-quality-rubric.md +68 -0
- package/skills/paper-marketing/references/brand-system-template.md +120 -0
- package/skills/paper-marketing/references/paper-mcp-rules.md +71 -0
- package/skills/paper-marketing/references/platform-conventions.md +43 -0
- package/skills/paywall-upgrade-cro/SKILL.md +227 -0
- package/skills/paywall-upgrade-cro/evals/evals.json +93 -0
- package/skills/paywall-upgrade-cro/references/experiments.md +164 -0
- package/skills/platform-formatting/SKILL.md +51 -0
- package/skills/popup-cro/SKILL.md +454 -0
- package/skills/popup-cro/evals/evals.json +94 -0
- package/skills/positioning-angles/SKILL.md +524 -0
- package/skills/positioning-angles/references/ad-matrix-and-examples.md +176 -0
- package/skills/positioning-angles/references/angle-frameworks.md +187 -0
- package/skills/positioning-angles/references/dunford-positioning.md +135 -0
- package/skills/positioning-angles/references/hormozi-offer.md +247 -0
- package/skills/positioning-angles/references/schwartz-sophistication.md +166 -0
- package/skills/positioning-angles/references/unique-mechanism.md +162 -0
- package/skills/pricing-strategy/SKILL.md +346 -0
- package/skills/pricing-strategy/evals/evals.json +90 -0
- package/skills/pricing-strategy/references/research-methods.md +152 -0
- package/skills/pricing-strategy/references/tier-structure.md +307 -0
- package/skills/programmatic-seo/SKILL.md +238 -0
- package/skills/programmatic-seo/evals/evals.json +94 -0
- package/skills/programmatic-seo/references/playbooks.md +308 -0
- package/skills/project-rag/SKILL.md +127 -0
- package/skills/quality-gate/SKILL.md +519 -0
- package/skills/quality-gate/judge-personas/buyer.md +47 -0
- package/skills/quality-gate/judge-personas/expert.md +47 -0
- package/skills/quality-gate/judge-personas/outsider.md +47 -0
- package/skills/quality-gate/judge-personas/scanner.md +41 -0
- package/skills/quality-gate/judge-personas/skeptic.md +40 -0
- package/skills/referral-program/SKILL.md +290 -0
- package/skills/referral-program/evals/evals.json +89 -0
- package/skills/referral-program/references/affiliate-programs.md +163 -0
- package/skills/referral-program/references/program-examples.md +143 -0
- package/skills/review-sites/SKILL.md +279 -0
- package/skills/revops/SKILL.md +343 -0
- package/skills/revops/evals/evals.json +91 -0
- package/skills/revops/references/automation-playbooks.md +290 -0
- package/skills/revops/references/lifecycle-definitions.md +278 -0
- package/skills/revops/references/routing-rules.md +203 -0
- package/skills/revops/references/scoring-models.md +247 -0
- package/skills/saas-product-seo/SKILL.md +324 -0
- package/skills/sales-enablement/SKILL.md +349 -0
- package/skills/sales-enablement/evals/evals.json +91 -0
- package/skills/sales-enablement/references/deck-frameworks.md +263 -0
- package/skills/sales-enablement/references/demo-scripts.md +355 -0
- package/skills/sales-enablement/references/objection-library.md +270 -0
- package/skills/sales-enablement/references/one-pager-templates.md +208 -0
- package/skills/schema-markup/SKILL.md +179 -0
- package/skills/schema-markup/evals/evals.json +87 -0
- package/skills/schema-markup/references/schema-examples.md +398 -0
- package/skills/self-improve/SKILL.md +166 -0
- package/skills/self-improving-agent/README.md +243 -0
- package/skills/self-improving-agent/SKILL.md +437 -0
- package/skills/self-improving-agent/scripts/__init__.py +16 -0
- package/skills/self-improving-agent/scripts/__pycache__/auto_detect.cpython-314.pyc +0 -0
- package/skills/self-improving-agent/scripts/__pycache__/nlm_curation.cpython-314.pyc +0 -0
- package/skills/self-improving-agent/scripts/__pycache__/self_improving_agent.cpython-314.pyc +0 -0
- package/skills/self-improving-agent/scripts/auto_detect.py +270 -0
- package/skills/self-improving-agent/scripts/init_expertise_registry.py +89 -0
- package/skills/self-improving-agent/scripts/nlm_curation.py +259 -0
- package/skills/self-improving-agent/scripts/self-improving-agent +113 -0
- package/skills/self-improving-agent/scripts/self_improving_agent.py +603 -0
- package/skills/self-improving-agent/scripts/test_curation_scorer.py +20 -0
- package/skills/self-improving-agent/scripts/test_self_improving.py +184 -0
- package/skills/send-email/SKILL.md +426 -0
- package/skills/send-email/references/batch-email-examples.md +807 -0
- package/skills/send-email/references/best-practices.md +453 -0
- package/skills/send-email/references/installation.md +123 -0
- package/skills/send-email/references/single-email-examples.md +470 -0
- package/skills/send-email/references/webhooks.md +221 -0
- package/skills/seo-audit/SKILL.md +362 -0
- package/skills/seo-audit/references/ai-writing-detection.md +200 -0
- package/skills/seo-audit/references/architecture-patterns.md +271 -0
- package/skills/seo-audit/references/schema-templates.md +427 -0
- package/skills/seo-content/SKILL.md +510 -0
- package/skills/seo-content/references/anti-ai-detection.md +184 -0
- package/skills/seo-content/references/content-structures.md +148 -0
- package/skills/seo-content/references/eeat-examples.md +235 -0
- package/skills/seo-content/references/on-page-seo.md +261 -0
- package/skills/seo-content/references/pseo-playbooks.md +226 -0
- package/skills/seo-content/references/schema-templates.md +104 -0
- package/skills/seo-content/references/serp-analysis-format.md +151 -0
- package/skills/seo-machine/SKILL.md +331 -0
- package/skills/seo-machine/assets/brand-template.md +73 -0
- package/skills/seo-machine/assets/link-inventory-template.md +74 -0
- package/skills/seo-machine/assets/roadmap-template.md +184 -0
- package/skills/seo-machine/references/api-stack-recipes.md +230 -0
- package/skills/seo-machine/references/exa-recipes.md +260 -0
- package/skills/seo-machine/references/manual-research.md +73 -0
- package/skills/seo-machine/references/methodology.md +87 -0
- package/skills/seo-machine/references/off-page.md +123 -0
- package/skills/seo-machine/references/patterns/alternatives.md +176 -0
- package/skills/seo-machine/references/patterns/compare.md +105 -0
- package/skills/seo-machine/references/patterns/playbooks.md +106 -0
- package/skills/seo-machine/references/patterns/use-case.md +109 -0
- package/skills/seo-machine/references/quality-bars.md +99 -0
- package/skills/seo-machine/references/stacks/astro.md +156 -0
- package/skills/seo-machine/references/stacks/detection.md +61 -0
- package/skills/seo-machine/references/stacks/markdown-fallback.md +181 -0
- package/skills/seo-machine/references/stacks/nextjs.md +108 -0
- package/skills/seo-machine/references/stacks/rails-inertia.md +99 -0
- package/skills/seo-machine/references/striking-distance.md +116 -0
- package/skills/seo-machine/references/technical-audit.md +153 -0
- package/skills/seo-machine/scripts/link_audit.py +265 -0
- package/skills/seo-machine/scripts/tech_audit.py +221 -0
- package/skills/seo-machine/scripts/word_count.py +154 -0
- package/skills/sharp-thesis-validator/SKILL.md +393 -0
- package/skills/sharp-thesis-validator/examples.md +186 -0
- package/skills/signup-flow-cro/SKILL.md +359 -0
- package/skills/signup-flow-cro/evals/evals.json +88 -0
- package/skills/site-architecture/SKILL.md +357 -0
- package/skills/site-architecture/evals/evals.json +88 -0
- package/skills/site-architecture/references/mermaid-templates.md +216 -0
- package/skills/site-architecture/references/navigation-patterns.md +305 -0
- package/skills/site-architecture/references/site-type-templates.md +293 -0
- package/skills/skill-self-improvement/SKILL.md +151 -0
- package/skills/slideshow-script/SKILL.md +274 -0
- package/skills/slideshow-script/references/content-spec-schema.md +77 -0
- package/skills/slideshow-script/references/frameworks.md +84 -0
- package/skills/slideshow-script/references/paips-framework.md +37 -0
- package/skills/social-campaign/SKILL.md +419 -0
- package/skills/social-campaign/references/paper-mcp-workflow.md +48 -0
- package/skills/social-content/SKILL.md +359 -0
- package/skills/social-content/evals/evals.json +92 -0
- package/skills/social-content/references/platforms.md +170 -0
- package/skills/social-content/references/post-templates.md +177 -0
- package/skills/social-content/references/reverse-engineering.md +195 -0
- package/skills/social-worker/SKILL.md +204 -0
- package/skills/startup-launcher/SKILL.md +252 -0
- package/skills/startup-launcher/references/file-router.md +64 -0
- package/skills/startup-launcher/references/platform-matrix.md +65 -0
- package/skills/startup-launcher/references/platforms/alternativeto.md +283 -0
- package/skills/startup-launcher/references/platforms/appsumo.md +495 -0
- package/skills/startup-launcher/references/platforms/auraplusplus.md +736 -0
- package/skills/startup-launcher/references/platforms/betalist.md +98 -0
- package/skills/startup-launcher/references/platforms/capterra.md +276 -0
- package/skills/startup-launcher/references/platforms/crunchbase.md +514 -0
- package/skills/startup-launcher/references/platforms/dealify.md +291 -0
- package/skills/startup-launcher/references/platforms/dealmirror.md +313 -0
- package/skills/startup-launcher/references/platforms/desifounder.md +490 -0
- package/skills/startup-launcher/references/platforms/devhunt.md +210 -0
- package/skills/startup-launcher/references/platforms/devpost.md +448 -0
- package/skills/startup-launcher/references/platforms/fazier.md +56 -0
- package/skills/startup-launcher/references/platforms/firsto.md +489 -0
- package/skills/startup-launcher/references/platforms/g2.md +226 -0
- package/skills/startup-launcher/references/platforms/hackernews.md +99 -0
- package/skills/startup-launcher/references/platforms/hackernoon.md +385 -0
- package/skills/startup-launcher/references/platforms/indiedeals.md +367 -0
- package/skills/startup-launcher/references/platforms/indiehackers.md +80 -0
- package/skills/startup-launcher/references/platforms/kenmoo.md +231 -0
- package/skills/startup-launcher/references/platforms/labstartups.md +618 -0
- package/skills/startup-launcher/references/platforms/launchboard.md +307 -0
- package/skills/startup-launcher/references/platforms/launchfast.md +560 -0
- package/skills/startup-launcher/references/platforms/launchigniter.md +56 -0
- package/skills/startup-launcher/references/platforms/launchingnext.md +674 -0
- package/skills/startup-launcher/references/platforms/launchit.md +574 -0
- package/skills/startup-launcher/references/platforms/launchyourapp.md +677 -0
- package/skills/startup-launcher/references/platforms/libhunt.md +220 -0
- package/skills/startup-launcher/references/platforms/ltdhunt.md +221 -0
- package/skills/startup-launcher/references/platforms/microlaunch.md +45 -0
- package/skills/startup-launcher/references/platforms/openalternative.md +195 -0
- package/skills/startup-launcher/references/platforms/peerlist.md +56 -0
- package/skills/startup-launcher/references/platforms/peerpush.md +64 -0
- package/skills/startup-launcher/references/platforms/primeclub.md +282 -0
- package/skills/startup-launcher/references/platforms/productcanyon.md +190 -0
- package/skills/startup-launcher/references/platforms/producthunt.md +98 -0
- package/skills/startup-launcher/references/platforms/rankinpublic.md +315 -0
- package/skills/startup-launcher/references/platforms/rockethub.md +374 -0
- package/skills/startup-launcher/references/platforms/saasgenius.md +175 -0
- package/skills/startup-launcher/references/platforms/saashub.md +205 -0
- package/skills/startup-launcher/references/platforms/saasmantra.md +221 -0
- package/skills/startup-launcher/references/platforms/saaspirate.md +287 -0
- package/skills/startup-launcher/references/platforms/saaswarrior.md +190 -0
- package/skills/startup-launcher/references/platforms/saaszilla.md +194 -0
- package/skills/startup-launcher/references/platforms/selected.md +925 -0
- package/skills/startup-launcher/references/platforms/sideprojectors.md +86 -0
- package/skills/startup-launcher/references/platforms/softonic.md +240 -0
- package/skills/startup-launcher/references/platforms/sourceforge.md +251 -0
- package/skills/startup-launcher/references/platforms/stacksocial.md +244 -0
- package/skills/startup-launcher/references/platforms/startupstash.md +326 -0
- package/skills/startup-launcher/references/platforms/theresanaiforthat.md +253 -0
- package/skills/startup-launcher/references/platforms/tinylaunch.md +70 -0
- package/skills/startup-launcher/references/platforms/tinystartups.md +72 -0
- package/skills/startup-launcher/references/platforms/toolfolio.md +291 -0
- package/skills/startup-launcher/references/platforms/trustmrr.md +194 -0
- package/skills/startup-launcher/references/platforms/trylaunch.md +531 -0
- package/skills/startup-launcher/references/platforms/uneed.md +57 -0
- package/skills/startup-launcher/references/templates/asset-checklist.md +218 -0
- package/skills/startup-launcher/references/templates/launch-tracker.md +195 -0
- package/skills/startup-launcher/references/templates/product-brief.md +98 -0
- package/skills/summarize/.skill-meta.json +13 -0
- package/skills/summarize/SKILL.md +170 -0
- package/skills/summarize/rules/install.md +157 -0
- package/skills/summarize/rules/usage.md +207 -0
- package/skills/topical-authority/SKILL.md +307 -0
- package/skills/topical-authority/references/jake-ward-framework.md +201 -0
- package/skills/topical-authority/references/serp-clustering-algorithm.md +325 -0
- package/skills/topical-authority/scripts/orchestrator.js +367 -0
- package/skills/topical-authority/scripts/seo/analyze-competitor-coverage.js +3 -0
- package/skills/topical-authority/scripts/seo/audit-internal-links.js +3 -0
- package/skills/topical-authority/scripts/seo/build-clusters-from-serp.js +3 -0
- package/skills/topical-authority/scripts/seo/extract-keywords-from-forums.js +3 -0
- package/skills/topical-authority/scripts/seo/extract-paa-questions.js +3 -0
- package/skills/topical-authority/scripts/seo/fetch-serp-urls.js +3 -0
- package/skills/topical-authority/scripts/seo/gemini-serp-clustering.js +3 -0
- package/skills/topical-authority/scripts/seo/identify-content-gaps.js +3 -0
- package/skills/topical-authority/scripts/seo/identify-research-gaps.js +3 -0
- package/skills/topical-authority/scripts/seo/scrape-quora-questions.js +3 -0
- package/skills/topical-authority/scripts/seo/scrape-reddit-pain-points.js +3 -0
- package/skills/topical-authority/scripts/seo/weave-internal-links.js +3 -0
- package/skills/visual-style/SKILL.md +199 -0
- package/skills/voice-brand-alignment/SKILL.md +70 -0
- package/skills/voice-brand-alignment/references/ai-slop-patterns.md +405 -0
- package/skills/voice-brand-alignment/scripts/validation/gemini-voice-validator.js +96 -0
- package/skills/voice-extraction/SKILL.md +234 -0
- package/skills/voice-extraction/references/extraction-prompt.md +155 -0
- package/skills/voice-extraction/references/voice-dna-template.md +168 -0
- package/skills/voice-extraction/references/voice-elements.md +259 -0
- package/skills/voice-extraction/scripts/build-corpus.js +120 -0
- package/skills/voice-extraction/scripts/collect-sources.sh +168 -0
- package/skills/warm-outbound/SKILL.md +299 -0
- package/skills/warm-outbound/templates/warm-message.md +39 -0
- package/skills/weekly-newsletter-digest/SKILL.md +78 -0
- package/skills/x-playwriter/SKILL.md +428 -0
- package/skills/x-playwriter/scripts/x-browser.js +185 -0
- package/skills/x-post-generator-openclaw/SKILL.md +138 -0
- package/skills/x-post-generator-openclaw/scripts/generate-x-post.js +537 -0
- package/skills/x-posting-playwriter/SKILL.md +203 -0
- package/skills/x-research/SKILL.md +129 -0
- package/skills/x-research/x-research.sh +85 -0
- package/skills/youtube-summarize/SKILL.md +90 -0
- package/skills/youtube-summarize/scripts/youtube-summarize.sh +143 -0
- package/src/cli.js +347 -172
- package/src/harness/deepseek-adapter.js +102 -0
- package/src/harness/deepseek.js +225 -0
- package/src/harness/opencode-adapter.js +174 -0
- package/src/harness/pi-adapter.js +172 -0
- package/src/harness/registry.js +121 -0
- package/src/harness/telemetry.js +102 -0
- package/src/harness/types.js +165 -0
- package/src/interview.js +36 -4
- package/src/postinstall.js +10 -12
- package/templates/AGENTS.md +17 -17
- package/templates/ORG.md +1 -1
- package/templates/TOOLS.md +7 -2
- package/templates/opencode.json +26 -29
- package/wiki/doctor.md +54 -0
- package/wiki/inkstone.md +4 -4
- package/wiki/opencode.md +3 -3
- package/skills/curated.txt +0 -68
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Stack adapter — Rails + Inertia + React
|
|
2
|
+
|
|
3
|
+
This adapter mirrors the reference implementation from the repo this skill was built against. It's the most opinionated adapter because it's been pressure-tested over 49 phases.
|
|
4
|
+
|
|
5
|
+
## Conventions to use
|
|
6
|
+
|
|
7
|
+
- **Routes:** dispatch-by-slug. `get 'alternatives/:slug', to: 'marketing#alternatives_show'` — one controller action serves many pages from a single hash.
|
|
8
|
+
- **Data lives on the controller** as a frozen Ruby hash constant (e.g. `MarketingController::ALTERNATIVES`). Slug → payload. **No database tables for marketing copy** unless the user already has a CMS pattern.
|
|
9
|
+
- **Components in `app/frontend/components/`**, named `[Pattern]Layout.tsx`. One layout per pattern.
|
|
10
|
+
- **Page wrappers in `app/frontend/pages/[Pattern]/Show.tsx`** — thin wrappers that hydrate the layout from props.
|
|
11
|
+
- **Sitemap** in `app/views/tools/sitemap.xml.erb` (or wherever the sitemap lives) — loop over each pattern's hash and emit `<url>` entries.
|
|
12
|
+
- **SSR enabled** for marketing controllers via `inertia_config ssr_enabled: true` if the app's main controller has SSR disabled. **Marketing pages MUST be SSR or full-HTML so search and AI crawlers see content.**
|
|
13
|
+
|
|
14
|
+
## Adding a new alternative (Pattern A) — concrete steps
|
|
15
|
+
|
|
16
|
+
1. **Append to `MarketingController::ALTERNATIVES`** — add an entry with the slug as the key. Reference the existing `'hootsuite'` entry as the gold-standard structure.
|
|
17
|
+
2. **Append to one cluster in `MarketingController::ALTERNATIVES_CLUSTERS`** — without this, the new alt won't appear on `/alternatives` directory page.
|
|
18
|
+
3. **Internal-link updates:**
|
|
19
|
+
- In ≥2 sibling alt entries' copy, add a reference to the new alt
|
|
20
|
+
- In `MarketingLayout.tsx`'s "Compare" footer block, swap in the new alt if it's high-priority (replace a lower-volume entry)
|
|
21
|
+
4. **Smoke test:** `bin/rails test test/controllers/alternatives_smoke_test.rb` enforces 1:1 coverage between `ALTERNATIVES` and `ALTERNATIVES_CLUSTERS`.
|
|
22
|
+
5. **Sitemap auto-updates** — `app/views/tools/sitemap.xml.erb` loops `ALTERNATIVES.each_key`.
|
|
23
|
+
6. **Bump `ToolsController::SITEMAP_LASTMOD`** to today's date.
|
|
24
|
+
|
|
25
|
+
## Adding a new use-case/audience (Pattern B/C) — concrete steps
|
|
26
|
+
|
|
27
|
+
1. **Append to `MarketingController::USE_CASES`** — slug → `ForData` hash
|
|
28
|
+
2. **Internal-link updates:**
|
|
29
|
+
- In ≥1 sibling `/for/*` entry's `related.siblings`, add the new slug
|
|
30
|
+
- In ≥2 `/features/*` entries' related-links, add the new `/for/*`
|
|
31
|
+
3. **Sitemap auto-updates**
|
|
32
|
+
|
|
33
|
+
## Adding a new comparison (Pattern D) — concrete steps
|
|
34
|
+
|
|
35
|
+
1. **Append to `MarketingController::COMPARISONS`** with alphabetical slug
|
|
36
|
+
2. **Internal-link updates:**
|
|
37
|
+
- In `MarketingController::ALTERNATIVES['a']` and `['b']` entries, add a "compare to [b]" link
|
|
38
|
+
- In one relevant `/for/*` entry (the use-case both compete in), add a related-link to the new compare
|
|
39
|
+
3. **Sitemap auto-updates**
|
|
40
|
+
|
|
41
|
+
## Adding a new playbook (Pattern E) — concrete steps
|
|
42
|
+
|
|
43
|
+
1. **Append to `MarketingController::PLAYBOOKS`** with metadata
|
|
44
|
+
2. **Create `app/frontend/pages/Playbooks/[PascalCaseSlug].tsx`** — clone `B2bSocialMediaStrategy.tsx` and rewrite the body
|
|
45
|
+
3. **Internal-link updates:**
|
|
46
|
+
- In ≥2 sibling playbooks' `related` arrays, add the new one
|
|
47
|
+
- In `/playbooks` index, ensure auto-discovery works (it should via the hash)
|
|
48
|
+
4. **Sitemap auto-updates**
|
|
49
|
+
|
|
50
|
+
## Meta tags + schema
|
|
51
|
+
|
|
52
|
+
Use the existing helper pattern. If `meta_tags_helper.rb` exists:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
set_meta_tags(
|
|
56
|
+
title: data[:meta_title],
|
|
57
|
+
description: data[:meta_description],
|
|
58
|
+
canonical: alternatives_show_url(slug: slug),
|
|
59
|
+
open_graph: { type: 'website', image: og_image_for(slug) }
|
|
60
|
+
)
|
|
61
|
+
add_software_application_schema # before_action sets this for marketing controllers
|
|
62
|
+
faqpage_jsonld(data[:faqs]) if data[:faqs].present?
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If the helper doesn't exist yet, this is **Phase 0** work — build the helper before any pattern phase.
|
|
66
|
+
|
|
67
|
+
## File-write checklist for any phase
|
|
68
|
+
|
|
69
|
+
Before declaring a phase complete:
|
|
70
|
+
|
|
71
|
+
- [ ] Hash entry added (`ALTERNATIVES`, `USE_CASES`, `COMPARISONS`, or `PLAYBOOKS`)
|
|
72
|
+
- [ ] Cluster appended (alternatives only)
|
|
73
|
+
- [ ] Sibling page references added (≥2 spots)
|
|
74
|
+
- [ ] `SITEMAP_LASTMOD` bumped to today
|
|
75
|
+
- [ ] `test/controllers/*_smoke_test.rb` passes if present
|
|
76
|
+
- [ ] `bundle exec rubocop -a` clean
|
|
77
|
+
- [ ] Local server check: visit the URL, view-source confirms full SSR HTML (not just a React shell)
|
|
78
|
+
- [ ] `docs/seo-machine.md` tracker row updated in the same commit
|
|
79
|
+
|
|
80
|
+
## SSR sanity check (every phase)
|
|
81
|
+
|
|
82
|
+
After adding a page, visit it locally and run `curl -s http://localhost:3000/<url> | grep -c "<h1"`. If the result is 0, SSR is broken for that route — check:
|
|
83
|
+
|
|
84
|
+
1. Controller has `inertia_config ssr_enabled: true`
|
|
85
|
+
2. `puma.rb` includes `plugin :inertia_ssr`
|
|
86
|
+
3. `public/vite-ssr/ssr.js` was built (`bundle exec rails assets:precompile` in dev creates this)
|
|
87
|
+
4. Browser-only code (`window`, `document`) at module-init is wrapped in `if (!import.meta.env.SSR)`
|
|
88
|
+
|
|
89
|
+
A page that renders client-side but blanks in `curl` won't be indexed correctly.
|
|
90
|
+
|
|
91
|
+
## When this adapter doesn't fit perfectly
|
|
92
|
+
|
|
93
|
+
If the project is Rails but NOT Inertia (e.g. Rails + Hotwire/Turbo + ERB), most of this still applies — the difference is:
|
|
94
|
+
|
|
95
|
+
- Skip the React component step
|
|
96
|
+
- Build ERB partials in `app/views/marketing/alternatives/show.html.erb` instead
|
|
97
|
+
- Use `content_tag` helpers or partials for the comparison table
|
|
98
|
+
|
|
99
|
+
Switch to `rails-erb.md` for that flow.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Striking-Distance Audit
|
|
2
|
+
|
|
3
|
+
The fastest win on any existing site. Pages currently ranking position 5-20 in GSC are one push from page 1. Boosting a position-14 page to position-3 typically **triples its traffic** without writing a new page.
|
|
4
|
+
|
|
5
|
+
## Eligibility
|
|
6
|
+
|
|
7
|
+
This audit only applies to sites with existing GSC data. For greenfield (≤14 days old, no rankings yet), skip — there's no striking-distance to find.
|
|
8
|
+
|
|
9
|
+
## Recipe
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
mcp__ahrefs__gsc-keywords
|
|
13
|
+
project_id: <project_id>
|
|
14
|
+
date_from: <90-days-ago>
|
|
15
|
+
date_to: <today>
|
|
16
|
+
where: position >= 5 AND position <= 20 AND impressions >= 50
|
|
17
|
+
order_by: impressions:desc
|
|
18
|
+
limit: 100
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Then for each high-value keyword, find the page that owns it:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
mcp__ahrefs__gsc-pages
|
|
25
|
+
project_id: <project_id>
|
|
26
|
+
date_from: <90-days-ago>
|
|
27
|
+
date_to: <today>
|
|
28
|
+
where: position >= 5 AND position <= 20
|
|
29
|
+
order_by: clicks:desc
|
|
30
|
+
limit: 50
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Cross-reference. Each (page, keyword) pair is a candidate boost phase.
|
|
34
|
+
|
|
35
|
+
## Prioritization
|
|
36
|
+
|
|
37
|
+
Rank candidates by **estimated traffic-at-position-3 minus current-traffic**, using rough CTR-by-position:
|
|
38
|
+
|
|
39
|
+
| Position | CTR |
|
|
40
|
+
|---|---|
|
|
41
|
+
| 1 | 28-32% |
|
|
42
|
+
| 2 | 14-17% |
|
|
43
|
+
| 3 | 9-11% |
|
|
44
|
+
| 4 | 6-8% |
|
|
45
|
+
| 5 | 5-6% |
|
|
46
|
+
| 6-10 | 2-4% |
|
|
47
|
+
| 11-15 | 1-2% |
|
|
48
|
+
| 16-20 | <1% |
|
|
49
|
+
|
|
50
|
+
So a keyword at position 14 with 1,000 monthly impressions currently gets ~10 clicks/month. At position 3 it would get ~100/month — a 10x bump on a single phase of work.
|
|
51
|
+
|
|
52
|
+
Skip candidates where:
|
|
53
|
+
- Impressions < 50/month (not enough signal)
|
|
54
|
+
- Top 3 results are all DR > 60 with deep, well-optimized content (you won't displace them)
|
|
55
|
+
- The page already has 1,500+ words on the topic (out of easy depth-adds)
|
|
56
|
+
|
|
57
|
+
## Boost-phase scope
|
|
58
|
+
|
|
59
|
+
A striking-distance boost phase is **NOT writing a new page**. It's amplifying an existing one. Specifically:
|
|
60
|
+
|
|
61
|
+
1. **Add 200-400 words of depth** to the section where the target keyword appears. Common amplifiers:
|
|
62
|
+
- Add an FAQ if missing (FAQPage schema is a featured-snippet magnet)
|
|
63
|
+
- Expand a thin section with a worked example
|
|
64
|
+
- Add a counter-argument paragraph if the existing content is one-sided
|
|
65
|
+
- Add a how-to subsection if the keyword is procedural
|
|
66
|
+
2. **Add 3-5 new internal links to this page** from related pages. The pages most likely to send useful link equity:
|
|
67
|
+
- Other pages already ranking for related queries (find via GSC)
|
|
68
|
+
- Sibling pattern pages (other `/for/*`, other `/alternatives/*`)
|
|
69
|
+
- Recent playbooks or blog posts on the same topic
|
|
70
|
+
3. **Update meta title/description** if it doesn't include the target keyword prominently. Bump the title's keyword towards the front.
|
|
71
|
+
4. **Update `lastmod` in sitemap** to today. The freshness signal helps the recrawl pick up the changes.
|
|
72
|
+
|
|
73
|
+
## Phase template for striking distance
|
|
74
|
+
|
|
75
|
+
```markdown
|
|
76
|
+
### Phase N — Boost /<existing-url> for "<target keyword>"
|
|
77
|
+
|
|
78
|
+
**Why:** currently ranks position 14 for "<target keyword>" (vol 500, KD 18). Position 3 captures an estimated +40 clicks/month with content depth + 3 new internal links from related pages.
|
|
79
|
+
|
|
80
|
+
**Scope:**
|
|
81
|
+
|
|
82
|
+
1. Add a 250-word FAQ section to /<existing-url> answering "<related question>"
|
|
83
|
+
2. Add `FAQPage` JSON-LD with the new FAQ
|
|
84
|
+
3. Add internal links from:
|
|
85
|
+
- `/<related-page-1>` (anchor: "<anchor text>")
|
|
86
|
+
- `/<related-page-2>` (anchor: "<anchor text>")
|
|
87
|
+
- `/<related-page-3>` (anchor: "<anchor text>")
|
|
88
|
+
4. Bump meta title to lead with "<target keyword>"
|
|
89
|
+
5. Bump sitemap lastmod to today
|
|
90
|
+
|
|
91
|
+
**Files modified:**
|
|
92
|
+
- (stack-specific)
|
|
93
|
+
|
|
94
|
+
**Verification:**
|
|
95
|
+
- [ ] Page has the new FAQ section (200+ words)
|
|
96
|
+
- [ ] `FAQPage` JSON-LD validates
|
|
97
|
+
- [ ] 3 new inbound links from named pages
|
|
98
|
+
- [ ] Meta title leads with target keyword and is ≤60 chars
|
|
99
|
+
- [ ] After 14 days, GSC shows position improvement (track manually)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## When to schedule striking-distance phases
|
|
103
|
+
|
|
104
|
+
Front-load them in the tracker. They're faster than new-page phases (a boost typically takes 1-3 hours vs 4-8 for a new page), use existing link equity, and produce measurable traffic gains within 7-21 days.
|
|
105
|
+
|
|
106
|
+
Suggested ordering on existing sites:
|
|
107
|
+
|
|
108
|
+
1. Phase 0 — Technical foundations
|
|
109
|
+
2. Phases 1-5 — Striking-distance boosts (the top 5 by estimated traffic gain)
|
|
110
|
+
3. Phases 6+ — New pattern pages, ordered by traffic potential
|
|
111
|
+
|
|
112
|
+
## Re-running the audit
|
|
113
|
+
|
|
114
|
+
GSC data is a lagging indicator. Re-run striking-distance every 30 days during the sprint — new keywords enter position 5-20 every cycle as you ship content, and old ones either graduate to page 1 (success!) or fall off (worth investigating).
|
|
115
|
+
|
|
116
|
+
If a keyword was at position 8 last month and is now position 12, that's regression. Investigate before boosting — usually means a competitor shipped fresh content on the same query.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Technical Foundations Audit (Phase 0)
|
|
2
|
+
|
|
3
|
+
Always Phase 0. Always. Day-0 crawl shapes how Google understands the site for months — fixing technical foundations later is harder than getting them right the first time.
|
|
4
|
+
|
|
5
|
+
Four checks: **sitemap**, **robots.txt**, **meta tag uniqueness**, **schema markup**. Run them in order.
|
|
6
|
+
|
|
7
|
+
Use `scripts/tech_audit.py` for the deterministic parts. The script outputs a JSON report you can read and translate into Phase 0 tasks for the roadmap.
|
|
8
|
+
|
|
9
|
+
## Check 1 — sitemap.xml
|
|
10
|
+
|
|
11
|
+
**Goal:** every indexable URL appears in a valid sitemap, with reasonable lastmod, submitted to GSC.
|
|
12
|
+
|
|
13
|
+
Run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Local sitemap exists?
|
|
17
|
+
find . -name 'sitemap*.xml*' -not -path './node_modules/*' -not -path './.git/*' | head
|
|
18
|
+
|
|
19
|
+
# Production sitemap reachable?
|
|
20
|
+
curl -sI https://<domain>/sitemap.xml | head -1
|
|
21
|
+
curl -s https://<domain>/sitemap.xml | xmllint --noout - && echo "Valid XML"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
If using Ahrefs MCP:
|
|
25
|
+
```
|
|
26
|
+
mcp__ahrefs__site-audit-issues
|
|
27
|
+
filter: category=indexing AND severity=high
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Findings to convert into Phase 0 tasks:
|
|
31
|
+
|
|
32
|
+
| Finding | Phase 0 task |
|
|
33
|
+
|---|---|
|
|
34
|
+
| No sitemap at all | Generate sitemap (stack-specific path: `app/views/tools/sitemap.xml.erb` for Rails, `app/sitemap.ts` for Next.js, `@astrojs/sitemap` for Astro) |
|
|
35
|
+
| Sitemap exists but missing key URLs | Patch the sitemap generator to include them |
|
|
36
|
+
| `lastmod` dates in the future | Bump to today — future dates are a crawler red flag |
|
|
37
|
+
| `lastmod` dates stale (>180 days) on actively-updated pages | Tie `lastmod` to a build constant that bumps per deploy |
|
|
38
|
+
| Sitemap not referenced in `robots.txt` | Add `Sitemap: https://<domain>/sitemap.xml` to robots.txt |
|
|
39
|
+
| Sitemap not submitted to GSC | Add a checklist item in the off-page section |
|
|
40
|
+
|
|
41
|
+
## Check 2 — robots.txt + canonicals
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# robots.txt exists and allows /?
|
|
45
|
+
curl -s https://<domain>/robots.txt
|
|
46
|
+
|
|
47
|
+
# Spot-check canonical tags on existing marketing pages
|
|
48
|
+
curl -s https://<domain>/ | grep -E 'rel="canonical"' | head
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If using Ahrefs MCP:
|
|
52
|
+
```
|
|
53
|
+
mcp__ahrefs__site-audit-issues
|
|
54
|
+
filter: category=crawlability OR category=canonical
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Common failures:
|
|
58
|
+
|
|
59
|
+
- **`User-agent: * Disallow: /`** in robots.txt (often from production-template defaults). Fix immediately.
|
|
60
|
+
- **Marketing routes blocked by accident.** Things like `/marketing/*` being in robots disallow because of a templating leftover.
|
|
61
|
+
- **Missing canonical tags** on pages that have query-param variants (sort, filter, pagination). Add canonical to the param-stripped URL.
|
|
62
|
+
- **Conflicting canonicals** — page points its canonical to a different URL, but that other URL doesn't canonical-point back consistently. Fix one direction.
|
|
63
|
+
- **Trailing-slash inconsistency.** `/alternatives/hootsuite` vs `/alternatives/hootsuite/` — pick one, redirect the other, canonical to the chosen one.
|
|
64
|
+
|
|
65
|
+
## Check 3 — meta tag uniqueness + length
|
|
66
|
+
|
|
67
|
+
For each page in the existing sitemap, fetch and extract `<title>` + `<meta name="description">`. Cross-reference.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Get all URLs from sitemap
|
|
71
|
+
curl -s https://<domain>/sitemap.xml | grep -oE '<loc>[^<]+' | sed 's/<loc>//' > /tmp/urls.txt
|
|
72
|
+
|
|
73
|
+
# Fetch each and capture title + meta description
|
|
74
|
+
while read url; do
|
|
75
|
+
echo "=== $url ==="
|
|
76
|
+
curl -s "$url" | grep -E '<title>|name="description"' | head -2
|
|
77
|
+
done < /tmp/urls.txt > /tmp/meta-audit.txt
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If using Ahrefs MCP:
|
|
81
|
+
```
|
|
82
|
+
mcp__ahrefs__site-audit-issues
|
|
83
|
+
filter: category=content AND (issue=duplicate_title OR issue=duplicate_description OR issue=title_too_long OR issue=description_too_long)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Failures to fix in Phase 0:
|
|
87
|
+
|
|
88
|
+
- **Duplicate titles across pages.** Each indexable URL needs a unique title.
|
|
89
|
+
- **Duplicate descriptions.** Same rule. CMS-default descriptions are a common offender.
|
|
90
|
+
- **Title >60 chars.** Get truncated in SERPs.
|
|
91
|
+
- **Description >155 chars.** Same.
|
|
92
|
+
- **Missing description.** Google auto-generates one; usually worse than what you'd write.
|
|
93
|
+
- **Multiple H1 tags on a single page.** Should be exactly 1.
|
|
94
|
+
|
|
95
|
+
## Check 4 — schema markup
|
|
96
|
+
|
|
97
|
+
Spot-check what JSON-LD currently exists on existing marketing pages:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
curl -s https://<domain>/ | grep -oE 'application/ld\+json"[^<]*</script' | head
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Common findings:
|
|
104
|
+
- No JSON-LD anywhere → add `SoftwareApplication` to the homepage as table-stakes
|
|
105
|
+
- Only `BreadcrumbList` → fine for nav but missing the page-type schemas
|
|
106
|
+
- Schemas exist but invalid (wrong `@type`, missing required fields) — validate via https://validator.schema.org/
|
|
107
|
+
|
|
108
|
+
Per-page-type schema requirements this skill enforces from Phase 1 onward:
|
|
109
|
+
|
|
110
|
+
| Page type | Required schemas |
|
|
111
|
+
|---|---|
|
|
112
|
+
| Homepage | `SoftwareApplication` (or `Product`), `Organization` |
|
|
113
|
+
| `/alternatives/[slug]` | `SoftwareApplication`, `BreadcrumbList`, `FAQPage` |
|
|
114
|
+
| `/for/[slug]` | `SoftwareApplication`, `BreadcrumbList`, `FAQPage` |
|
|
115
|
+
| `/compare/[slug]` | `BreadcrumbList`, `FAQPage` |
|
|
116
|
+
| `/playbooks/[slug]` | `Article`, `BreadcrumbList` |
|
|
117
|
+
| `/blog/[slug]` | `Article`, `BreadcrumbList` |
|
|
118
|
+
| `/tools/[slug]` | `SoftwareApplication` or `WebApplication`, `BreadcrumbList` |
|
|
119
|
+
|
|
120
|
+
If the user's stack doesn't already have a schema helper, Phase 0 builds one before any pattern phase runs. A helper saves rewriting the same JSON-LD boilerplate 30 times.
|
|
121
|
+
|
|
122
|
+
## Reporting findings
|
|
123
|
+
|
|
124
|
+
After running all four checks, write a Phase 0 entry to the roadmap that looks like:
|
|
125
|
+
|
|
126
|
+
```markdown
|
|
127
|
+
### Phase 0 — Technical foundations
|
|
128
|
+
|
|
129
|
+
**Why:** the day-0 crawl shapes Google's understanding of the site for months. Fix these before shipping content.
|
|
130
|
+
|
|
131
|
+
**Scope:**
|
|
132
|
+
|
|
133
|
+
1. Generate sitemap.xml at `<stack-appropriate-path>` (currently missing)
|
|
134
|
+
2. Add `Sitemap: https://<domain>/sitemap.xml` to robots.txt
|
|
135
|
+
3. Fix 3 duplicate `<title>` tags on `/`, `/pricing`, `/about`
|
|
136
|
+
4. Build `meta_tags_helper` with `add_software_application_schema` and `faqpage_jsonld` (or stack-equivalent)
|
|
137
|
+
5. Add `SoftwareApplication` JSON-LD to homepage
|
|
138
|
+
6. Submit sitemap to Google Search Console + Bing Webmaster Tools
|
|
139
|
+
|
|
140
|
+
**Files modified:**
|
|
141
|
+
- (auto-populate based on stack)
|
|
142
|
+
|
|
143
|
+
**Verification:**
|
|
144
|
+
- [ ] curl sitemap.xml returns 200 + valid XML
|
|
145
|
+
- [ ] robots.txt does not disallow marketing routes
|
|
146
|
+
- [ ] No duplicate titles in sitemap-listed URLs
|
|
147
|
+
- [ ] Schema validator returns 0 errors on homepage
|
|
148
|
+
- [ ] Sitemap submitted in GSC (manual; check off when done)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## What NOT to include in Phase 0
|
|
152
|
+
|
|
153
|
+
Don't try to fix Core Web Vitals or page speed in Phase 0. Those are real issues but they're not foundational; they're optimization. Run a Lighthouse audit in a separate phase after the foundations are right. Otherwise Phase 0 sprawls into a month-long performance pass.
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Internal-link audit for SEO-sprint pages.
|
|
4
|
+
|
|
5
|
+
Counts internal links pointing TO a given slug AND FROM a given slug,
|
|
6
|
+
and asserts they meet per-pattern minimums.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python link_audit.py --slug hootsuite --pattern A --root .
|
|
10
|
+
python link_audit.py --pattern A --root . --slug-list slug1,slug2
|
|
11
|
+
python link_audit.py --orphan-check --root .
|
|
12
|
+
|
|
13
|
+
The script scans common file extensions for links matching:
|
|
14
|
+
/alternatives/<slug>
|
|
15
|
+
/for/<slug>
|
|
16
|
+
/compare/<slug>
|
|
17
|
+
/playbooks/<slug>
|
|
18
|
+
/features/<slug>
|
|
19
|
+
/tools/<slug>
|
|
20
|
+
|
|
21
|
+
It does not try to understand framework-specific link helpers. Direct URL
|
|
22
|
+
strings or href= attributes are what it counts. If your code uses a helper
|
|
23
|
+
like `alternatives_show_url(slug)`, this script will undercount — bias
|
|
24
|
+
towards URL strings or augment the script's regex to your helper's pattern.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import argparse
|
|
28
|
+
import re
|
|
29
|
+
import sys
|
|
30
|
+
from collections import defaultdict
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
# Patterns: how many links are required FROM each page-type, broken down by link-target-type
|
|
34
|
+
OUTBOUND_REQUIREMENTS = {
|
|
35
|
+
"A": { # /alternatives/[slug]
|
|
36
|
+
"alternatives": 2,
|
|
37
|
+
"features": 1,
|
|
38
|
+
"tools": 1,
|
|
39
|
+
},
|
|
40
|
+
"B": { # /for/[slug] (use-case)
|
|
41
|
+
"features": 2,
|
|
42
|
+
"tools": 2,
|
|
43
|
+
"for": 1,
|
|
44
|
+
},
|
|
45
|
+
"C": { # /for/[slug] (audience) — same as B
|
|
46
|
+
"features": 2,
|
|
47
|
+
"tools": 2,
|
|
48
|
+
"for": 1,
|
|
49
|
+
},
|
|
50
|
+
"D": { # /compare/[slug]
|
|
51
|
+
"alternatives": 2, # both /alternatives/[a] and /alternatives/[b]
|
|
52
|
+
"for": 1,
|
|
53
|
+
"pricing": 1,
|
|
54
|
+
},
|
|
55
|
+
"E": { # /playbooks/[slug]
|
|
56
|
+
"features": 3,
|
|
57
|
+
"tools": 2,
|
|
58
|
+
"for": 2,
|
|
59
|
+
"alternatives": 1,
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
INBOUND_MINIMUM = 2 # every page must be linked to from at least 2 other pages
|
|
64
|
+
|
|
65
|
+
LINK_REGEXES = {
|
|
66
|
+
"alternatives": re.compile(r"/alternatives/([a-z0-9][a-z0-9-]*)"),
|
|
67
|
+
"for": re.compile(r"/for/([a-z0-9][a-z0-9-]*)"),
|
|
68
|
+
"compare": re.compile(r"/compare/([a-z0-9][a-z0-9-]*)"),
|
|
69
|
+
"playbooks": re.compile(r"/playbooks/([a-z0-9][a-z0-9-]*)"),
|
|
70
|
+
"features": re.compile(r"/features/([a-z0-9][a-z0-9-]*)"),
|
|
71
|
+
"tools": re.compile(r"/tools/([a-z0-9][a-z0-9-]*)"),
|
|
72
|
+
"pricing": re.compile(r"/pricing(?:[/'\"\s>?])"),
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
DEFAULT_EXTENSIONS = {".tsx", ".ts", ".jsx", ".js", ".astro", ".mdx", ".md", ".erb", ".rb", ".html", ".vue", ".svelte"}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def scan_links(root: Path, exclude: list = None):
|
|
79
|
+
"""Return {file_path: {target_type: [slugs]}} for every link found."""
|
|
80
|
+
found = defaultdict(lambda: defaultdict(list))
|
|
81
|
+
excludes = exclude or []
|
|
82
|
+
for path in root.rglob("*"):
|
|
83
|
+
if not path.is_file():
|
|
84
|
+
continue
|
|
85
|
+
if path.suffix not in DEFAULT_EXTENSIONS:
|
|
86
|
+
continue
|
|
87
|
+
if any(part in path.parts for part in (".git", "node_modules", "dist", "build", ".next", "tmp", "public")):
|
|
88
|
+
continue
|
|
89
|
+
if any(str(path).endswith(ex) for ex in excludes):
|
|
90
|
+
continue
|
|
91
|
+
try:
|
|
92
|
+
text = path.read_text(encoding="utf-8")
|
|
93
|
+
except (OSError, UnicodeDecodeError):
|
|
94
|
+
continue
|
|
95
|
+
for target_type, rx in LINK_REGEXES.items():
|
|
96
|
+
for m in rx.finditer(text):
|
|
97
|
+
slug = m.group(1) if rx.groups else "_pricing"
|
|
98
|
+
found[str(path)][target_type].append(slug)
|
|
99
|
+
return found
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def assert_outbound(slug: str, pattern: str, root: Path):
|
|
103
|
+
"""For a given (slug, pattern), check that the page file linking from it meets requirements."""
|
|
104
|
+
if pattern not in OUTBOUND_REQUIREMENTS:
|
|
105
|
+
print(f"unknown pattern: {pattern}", file=sys.stderr)
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
pattern_dir_map = {"A": "alternatives", "B": "for", "C": "for", "D": "compare", "E": "playbooks"}
|
|
109
|
+
page_kind = pattern_dir_map[pattern]
|
|
110
|
+
# Heuristic: page-defining file is one whose path contains the slug AND the pattern dir
|
|
111
|
+
candidates = []
|
|
112
|
+
for path in root.rglob("*"):
|
|
113
|
+
if not path.is_file() or path.suffix not in DEFAULT_EXTENSIONS:
|
|
114
|
+
continue
|
|
115
|
+
if slug in path.stem or slug in str(path):
|
|
116
|
+
if page_kind in str(path).lower() or pattern == "E":
|
|
117
|
+
candidates.append(path)
|
|
118
|
+
# For data-driven files (single hash with all slugs), also check the file that *defines* this slug
|
|
119
|
+
for path in root.rglob("*"):
|
|
120
|
+
if not path.is_file() or path.suffix not in {".rb", ".ts", ".tsx", ".js"}:
|
|
121
|
+
continue
|
|
122
|
+
try:
|
|
123
|
+
text = path.read_text(encoding="utf-8")
|
|
124
|
+
except (OSError, UnicodeDecodeError):
|
|
125
|
+
continue
|
|
126
|
+
if f"'{slug}'" in text or f'"{slug}"' in text:
|
|
127
|
+
if page_kind in text.lower() or slug in text:
|
|
128
|
+
if path not in candidates:
|
|
129
|
+
candidates.append(path)
|
|
130
|
+
|
|
131
|
+
if not candidates:
|
|
132
|
+
print(f"✗ Could not locate the page definition file for slug={slug} pattern={pattern}", file=sys.stderr)
|
|
133
|
+
return False
|
|
134
|
+
|
|
135
|
+
# Aggregate outbound links across all candidate files
|
|
136
|
+
aggregated = defaultdict(set)
|
|
137
|
+
for path in candidates:
|
|
138
|
+
try:
|
|
139
|
+
text = path.read_text(encoding="utf-8")
|
|
140
|
+
except (OSError, UnicodeDecodeError):
|
|
141
|
+
continue
|
|
142
|
+
# Only count text near this slug (rough proximity heuristic: nearest 4000 chars)
|
|
143
|
+
i = text.find(slug)
|
|
144
|
+
snippet = text[max(0, i - 200):i + 4000] if i >= 0 else text
|
|
145
|
+
for target_type, rx in LINK_REGEXES.items():
|
|
146
|
+
for m in rx.finditer(snippet):
|
|
147
|
+
target_slug = m.group(1) if rx.groups else "_pricing"
|
|
148
|
+
if target_type == page_kind and target_slug == slug:
|
|
149
|
+
continue # self-link doesn't count
|
|
150
|
+
aggregated[target_type].add(target_slug)
|
|
151
|
+
|
|
152
|
+
required = OUTBOUND_REQUIREMENTS[pattern]
|
|
153
|
+
all_pass = True
|
|
154
|
+
print(f"\nOutbound link audit — pattern {pattern}, slug={slug}")
|
|
155
|
+
for target_type, min_count in required.items():
|
|
156
|
+
found = len(aggregated.get(target_type, set()))
|
|
157
|
+
ok = found >= min_count
|
|
158
|
+
mark = "✓" if ok else "✗"
|
|
159
|
+
print(f" {mark} {target_type}: {found} / {min_count} required")
|
|
160
|
+
if not ok:
|
|
161
|
+
all_pass = False
|
|
162
|
+
return all_pass
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def assert_inbound(slug: str, pattern: str, root: Path):
|
|
166
|
+
"""Check that ≥2 other files link to this slug."""
|
|
167
|
+
pattern_dir_map = {"A": "alternatives", "B": "for", "C": "for", "D": "compare", "E": "playbooks"}
|
|
168
|
+
target_type = pattern_dir_map[pattern]
|
|
169
|
+
rx = LINK_REGEXES[target_type]
|
|
170
|
+
|
|
171
|
+
inbound_files = set()
|
|
172
|
+
for path in root.rglob("*"):
|
|
173
|
+
if not path.is_file() or path.suffix not in DEFAULT_EXTENSIONS:
|
|
174
|
+
continue
|
|
175
|
+
if any(p in path.parts for p in (".git", "node_modules", "dist", "build", ".next", "tmp")):
|
|
176
|
+
continue
|
|
177
|
+
try:
|
|
178
|
+
text = path.read_text(encoding="utf-8")
|
|
179
|
+
except (OSError, UnicodeDecodeError):
|
|
180
|
+
continue
|
|
181
|
+
for m in rx.finditer(text):
|
|
182
|
+
if m.group(1) == slug:
|
|
183
|
+
inbound_files.add(str(path))
|
|
184
|
+
|
|
185
|
+
n = len(inbound_files)
|
|
186
|
+
ok = n >= INBOUND_MINIMUM
|
|
187
|
+
mark = "✓" if ok else "✗"
|
|
188
|
+
print(f"\nInbound link audit — slug={slug}")
|
|
189
|
+
print(f" {mark} {n} / {INBOUND_MINIMUM} required files link to this page")
|
|
190
|
+
if n < INBOUND_MINIMUM and inbound_files:
|
|
191
|
+
for f in sorted(inbound_files):
|
|
192
|
+
print(f" → {f}")
|
|
193
|
+
return ok
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def orphan_check(root: Path):
|
|
197
|
+
"""Find pattern slugs that have <2 inbound links anywhere in the repo."""
|
|
198
|
+
print("\nOrphan check — slugs with <2 inbound links")
|
|
199
|
+
all_slugs_by_type = defaultdict(set)
|
|
200
|
+
# Discover all slugs from file naming conventions (rough)
|
|
201
|
+
for path in root.rglob("*"):
|
|
202
|
+
if not path.is_file() or path.suffix not in DEFAULT_EXTENSIONS:
|
|
203
|
+
continue
|
|
204
|
+
try:
|
|
205
|
+
text = path.read_text(encoding="utf-8")
|
|
206
|
+
except (OSError, UnicodeDecodeError):
|
|
207
|
+
continue
|
|
208
|
+
for target_type, rx in LINK_REGEXES.items():
|
|
209
|
+
for m in rx.finditer(text):
|
|
210
|
+
if rx.groups:
|
|
211
|
+
all_slugs_by_type[target_type].add(m.group(1))
|
|
212
|
+
|
|
213
|
+
any_orphans = False
|
|
214
|
+
for target_type, slugs in all_slugs_by_type.items():
|
|
215
|
+
rx = LINK_REGEXES[target_type]
|
|
216
|
+
for slug in sorted(slugs):
|
|
217
|
+
inbound_files = set()
|
|
218
|
+
for path in root.rglob("*"):
|
|
219
|
+
if not path.is_file() or path.suffix not in DEFAULT_EXTENSIONS:
|
|
220
|
+
continue
|
|
221
|
+
try:
|
|
222
|
+
text = path.read_text(encoding="utf-8")
|
|
223
|
+
except (OSError, UnicodeDecodeError):
|
|
224
|
+
continue
|
|
225
|
+
for m in rx.finditer(text):
|
|
226
|
+
if m.group(1) == slug:
|
|
227
|
+
inbound_files.add(str(path))
|
|
228
|
+
# subtract files that ARE the page-definition file (we want inbound from elsewhere)
|
|
229
|
+
external_inbound = [f for f in inbound_files if not slug in Path(f).stem]
|
|
230
|
+
if len(external_inbound) < INBOUND_MINIMUM:
|
|
231
|
+
print(f" ✗ /{target_type}/{slug} — only {len(external_inbound)} inbound link(s)")
|
|
232
|
+
any_orphans = True
|
|
233
|
+
|
|
234
|
+
if not any_orphans:
|
|
235
|
+
print(" ✓ No orphans")
|
|
236
|
+
return not any_orphans
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def main():
|
|
240
|
+
parser = argparse.ArgumentParser()
|
|
241
|
+
parser.add_argument("--slug", help="Slug to audit")
|
|
242
|
+
parser.add_argument("--pattern", choices=["A", "B", "C", "D", "E"])
|
|
243
|
+
parser.add_argument("--root", default=".", help="Repo root to scan")
|
|
244
|
+
parser.add_argument("--orphan-check", action="store_true", help="List all orphan pages")
|
|
245
|
+
args = parser.parse_args()
|
|
246
|
+
|
|
247
|
+
root = Path(args.root).resolve()
|
|
248
|
+
if not root.is_dir():
|
|
249
|
+
print(f"not a directory: {root}", file=sys.stderr)
|
|
250
|
+
sys.exit(2)
|
|
251
|
+
|
|
252
|
+
if args.orphan_check:
|
|
253
|
+
ok = orphan_check(root)
|
|
254
|
+
sys.exit(0 if ok else 1)
|
|
255
|
+
|
|
256
|
+
if not args.slug or not args.pattern:
|
|
257
|
+
parser.error("--slug and --pattern are required unless --orphan-check is used")
|
|
258
|
+
|
|
259
|
+
a = assert_outbound(args.slug, args.pattern, root)
|
|
260
|
+
b = assert_inbound(args.slug, args.pattern, root)
|
|
261
|
+
sys.exit(0 if (a and b) else 1)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
if __name__ == "__main__":
|
|
265
|
+
main()
|