@jairodri/huckleberry-cli 1.0.1 → 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 +349 -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,160 @@
|
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
## Philosophy
|
|
4
|
+
claw-compactor follows a **trust-through-testing** approach. Every compression technique must prove:
|
|
5
|
+
|
|
6
|
+
1. **Correctness** — lossless techniques roundtrip perfectly; lossy techniques preserve all facts
|
|
7
|
+
2. **Safety** — edge cases (empty files, Unicode, malformed markdown) never crash
|
|
8
|
+
3. **Non-inflation** — compressed output is never larger than input
|
|
9
|
+
4. **Idempotency** — running compression twice produces the same result
|
|
10
|
+
|
|
11
|
+
## Test Suite Overview
|
|
12
|
+
**810+ tests** across 30 test files, covering unit tests, integration tests, and real-workspace validation.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
tests/
|
|
16
|
+
├── conftest.py # Shared fixtures
|
|
17
|
+
│
|
|
18
|
+
├── # Core module tests
|
|
19
|
+
├── test_compress_memory.py # Rule engine compression
|
|
20
|
+
├── test_compress_memory_comprehensive.py # Extended rule engine tests
|
|
21
|
+
├── test_dictionary.py # Dictionary encoding basics
|
|
22
|
+
├── test_dictionary_comprehensive.py # Codebook edge cases, roundtrip
|
|
23
|
+
├── test_observation_compressor.py # Observation pipeline
|
|
24
|
+
├── test_observation_comprehensive.py # Extended observation tests
|
|
25
|
+
├── test_compressed_context.py # CCP levels
|
|
26
|
+
├── test_dedup_memory.py # Shingle dedup
|
|
27
|
+
├── test_generate_summary_tiers.py # Tier generation
|
|
28
|
+
├── test_estimate_tokens.py # Token estimation
|
|
29
|
+
├── test_audit_memory.py # Audit checks
|
|
30
|
+
├── test_audit_comprehensive.py # Extended audit tests
|
|
31
|
+
├── # Library tests
|
|
32
|
+
├── test_lib_tokens.py # tiktoken + fallback
|
|
33
|
+
├── test_lib_dedup.py # Shingle hashing, Jaccard
|
|
34
|
+
├── test_lib_markdown.py # MD parsing, normalization
|
|
35
|
+
├── test_rle.py # RLE basics
|
|
36
|
+
├── test_rle_comprehensive.py # Path/IP/enum edge cases
|
|
37
|
+
├── test_tokenizer_optimizer.py # Format optimization
|
|
38
|
+
├── test_tokenizer_optimizer_comprehensive.py # Extended optimizer tests
|
|
39
|
+
├── test_config.py # Config loading
|
|
40
|
+
├── test_tokens.py # Token utilities
|
|
41
|
+
├── # Integration & validation
|
|
42
|
+
├── test_main_entry.py # mem_compress.py CLI routing
|
|
43
|
+
├── test_cli_commands.py # Subprocess CLI invocation
|
|
44
|
+
├── test_pipeline.py # Full pipeline integration
|
|
45
|
+
├── test_integration.py # End-to-end scenarios
|
|
46
|
+
├── test_roundtrip.py # Roundtrip guarantees
|
|
47
|
+
├── test_roundtrip_comprehensive.py # Extended roundtrip tests
|
|
48
|
+
├── test_performance.py # Performance regression
|
|
49
|
+
├── test_benchmark.py # Benchmark command
|
|
50
|
+
├── test_tiers_comprehensive.py # Tier edge cases
|
|
51
|
+
├── test_error_handling.py # Error paths
|
|
52
|
+
├── test_new_features.py # Recent feature tests
|
|
53
|
+
├── test_real_workspace.py # Real workspace validation
|
|
54
|
+
├── test_token_economics.py # Cost calculations
|
|
55
|
+
└── test_markdown_advanced.py # Advanced MD scenarios
|
|
56
|
+
|
|
57
|
+
## Coverage Matrix
|
|
58
|
+
| compress_memory | | | | |
|
|
59
|
+
| dictionary_compress | | | | (50+ cases) |
|
|
60
|
+
| observation_compressor | | | | N/A (lossy) |
|
|
61
|
+
| dedup_memory | | | | N/A |
|
|
62
|
+
| generate_summary_tiers | | | | N/A |
|
|
63
|
+
| estimate_tokens | | | | N/A |
|
|
64
|
+
| audit_memory | | | | N/A |
|
|
65
|
+
| compressed_context | | | | N/A (lossy) |
|
|
66
|
+
| lib/tokens | | — | | N/A |
|
|
67
|
+
| lib/markdown | | — | | N/A |
|
|
68
|
+
| lib/dedup | | — | | N/A |
|
|
69
|
+
| lib/dictionary | | — | | |
|
|
70
|
+
| lib/rle | | — | | |
|
|
71
|
+
| lib/tokenizer_optimizer | | — | | N/A |
|
|
72
|
+
| lib/config | | — | | N/A |
|
|
73
|
+
| mem_compress (CLI) | | | | N/A |
|
|
74
|
+
|
|
75
|
+
### Edge Cases Tested
|
|
76
|
+
- **Empty files** — all modules handle gracefully
|
|
77
|
+
- **Unicode/CJK** — Chinese headers, mixed en/zh, emoji, accented characters
|
|
78
|
+
- **Large files** — 100K+ characters, 2000+ sections
|
|
79
|
+
- **Malformed markdown** — unclosed code blocks, broken headers, missing spaces
|
|
80
|
+
- **Headers-only files** — no body content
|
|
81
|
+
- **Single-line files** — minimal content
|
|
82
|
+
- **Nonexistent paths** — proper errors and exit codes
|
|
83
|
+
- **Overlapping dictionary codes** — no collisions
|
|
84
|
+
- **Adjacent `$XX` codes** — correct boundary detection
|
|
85
|
+
- **Empty codebooks** — graceful no-op
|
|
86
|
+
|
|
87
|
+
## Running Tests
|
|
88
|
+
```bash
|
|
89
|
+
cd skills/claw-compactor
|
|
90
|
+
|
|
91
|
+
# Run all tests
|
|
92
|
+
PYTHONPATH=scripts python3 -m pytest tests/ -v
|
|
93
|
+
|
|
94
|
+
# Run a specific test file
|
|
95
|
+
PYTHONPATH=scripts python3 -m pytest tests/test_dictionary.py -v
|
|
96
|
+
|
|
97
|
+
# Run a specific test class
|
|
98
|
+
PYTHONPATH=scripts python3 -m pytest tests/test_roundtrip.py::TestDictionaryRoundtrip -v
|
|
99
|
+
|
|
100
|
+
# Run with coverage (requires pytest-cov)
|
|
101
|
+
PYTHONPATH=scripts python3 -m pytest tests/ --cov=lib --cov-report=term-missing
|
|
102
|
+
|
|
103
|
+
# Quick check (no verbose)
|
|
104
|
+
PYTHONPATH=scripts python3 -m pytest tests/ -q
|
|
105
|
+
|
|
106
|
+
**Expected output:**
|
|
107
|
+
810 passed in 31s
|
|
108
|
+
|
|
109
|
+
## Fixtures (conftest.py)
|
|
110
|
+
Shared test fixtures provide consistent test environments:
|
|
111
|
+
|
|
112
|
+
- `tmp_workspace`: Workspace with MEMORY.md + `memory/` containing 2 daily files
|
|
113
|
+
- `empty_file`: Empty `.md` file
|
|
114
|
+
- `unicode_file`: Chinese + Japanese + emoji + accented characters
|
|
115
|
+
- `large_file`: 2000 sections, 100K+ characters
|
|
116
|
+
- `broken_markdown`: Malformed headers, unclosed code blocks
|
|
117
|
+
- `headers_only`: Only header lines, no body text
|
|
118
|
+
- `single_line`: Single line of text
|
|
119
|
+
- `duplicate_content`: Two files with known overlapping sections
|
|
120
|
+
|
|
121
|
+
## Adding New Tests
|
|
122
|
+
|
|
123
|
+
### For a new compression technique
|
|
124
|
+
1. Create `tests/test_<technique>.py`
|
|
125
|
+
2. Include at minimum:
|
|
126
|
+
- **Basic functionality** — happy path
|
|
127
|
+
- **Empty input** — should return empty/no-op
|
|
128
|
+
- **Unicode input** — CJK, emoji, mixed scripts
|
|
129
|
+
- **Roundtrip** (if lossless) — `decompress(compress(x)) == x`
|
|
130
|
+
- **Non-inflation** — `len(compress(x)) <= len(x)` in tokens
|
|
131
|
+
- **Idempotency** — `compress(compress(x)) == compress(x)`
|
|
132
|
+
|
|
133
|
+
3. Add fixture if needed in `conftest.py`
|
|
134
|
+
|
|
135
|
+
### For a new edge case
|
|
136
|
+
1. Add to the most relevant existing test file
|
|
137
|
+
2. Use the `@pytest.mark.parametrize` decorator for variants
|
|
138
|
+
3. Document what the edge case covers in the test docstring
|
|
139
|
+
|
|
140
|
+
### Test naming convention
|
|
141
|
+
```python
|
|
142
|
+
class TestModuleName:
|
|
143
|
+
def test_basic_functionality(self):
|
|
144
|
+
"""Module handles the standard case."""
|
|
145
|
+
|
|
146
|
+
def test_empty_input(self):
|
|
147
|
+
"""Module handles empty input gracefully."""
|
|
148
|
+
|
|
149
|
+
def test_unicode_content(self):
|
|
150
|
+
"""Module handles CJK and emoji content."""
|
|
151
|
+
|
|
152
|
+
def test_roundtrip_guarantee(self):
|
|
153
|
+
"""Compress then decompress returns original."""
|
|
154
|
+
|
|
155
|
+
## Continuous Validation
|
|
156
|
+
Tests should be run:
|
|
157
|
+
- Before any code change is committed
|
|
158
|
+
- After modifying any `lib/` module (shared dependencies)
|
|
159
|
+
- After updating compression rules or codebook logic
|
|
160
|
+
- As part of the `full` pipeline verification (post-packaging)
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Audit workspace memory files for token usage, staleness, and compression opportunities.
|
|
3
|
+
|
|
4
|
+
Scans all markdown files in a workspace and reports:
|
|
5
|
+
- Total token budget usage
|
|
6
|
+
- File age distribution
|
|
7
|
+
- Stale entries (not updated in N days)
|
|
8
|
+
- Compression suggestions
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
python3 audit_memory.py <workspace_path> [--stale-days 14] [--json]
|
|
12
|
+
|
|
13
|
+
Part of claw-compactor. License: MIT.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import argparse
|
|
17
|
+
import json
|
|
18
|
+
import logging
|
|
19
|
+
import os
|
|
20
|
+
import sys
|
|
21
|
+
import time
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Dict, List, Any, Optional
|
|
25
|
+
|
|
26
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
27
|
+
from lib.tokens import estimate_tokens
|
|
28
|
+
from lib.markdown import parse_sections, compress_markdown_table, strip_emoji
|
|
29
|
+
from lib.exceptions import FileNotFoundError_
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
# Default memory token budgets
|
|
34
|
+
DEFAULT_BUDGETS = {
|
|
35
|
+
"MEMORY.md": 2000,
|
|
36
|
+
"TOOLS.md": 1500,
|
|
37
|
+
"AGENTS.md": 2000,
|
|
38
|
+
"daily_total": 5000,
|
|
39
|
+
"workspace_total": 15000,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _has_tables(text: str) -> bool:
|
|
44
|
+
"""Check if text contains markdown tables."""
|
|
45
|
+
return '|' in text and '---' in text
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _has_emoji(text: str) -> bool:
|
|
49
|
+
"""Check if text contains emoji characters."""
|
|
50
|
+
from lib.markdown import _EMOJI_RE
|
|
51
|
+
return bool(_EMOJI_RE.search(text))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _count_empty_sections(text: str) -> int:
|
|
55
|
+
"""Count sections with no meaningful body content."""
|
|
56
|
+
from lib.markdown import parse_sections
|
|
57
|
+
sections = parse_sections(text)
|
|
58
|
+
return sum(1 for h, b, _ in sections if h and not b.strip())
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _file_age_days(path: Path) -> float:
|
|
62
|
+
"""Return the age of *path* in days since last modification."""
|
|
63
|
+
mtime = path.stat().st_mtime
|
|
64
|
+
return (time.time() - mtime) / 86400
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def audit_file(
|
|
68
|
+
path: Path,
|
|
69
|
+
stale_days: int = 14,
|
|
70
|
+
) -> Dict[str, Any]:
|
|
71
|
+
"""Audit a single markdown file.
|
|
72
|
+
|
|
73
|
+
Returns dict with name, tokens, is_stale, suggestions, etc.
|
|
74
|
+
"""
|
|
75
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
76
|
+
tokens = estimate_tokens(text)
|
|
77
|
+
age = _file_age_days(path)
|
|
78
|
+
is_stale = age > stale_days
|
|
79
|
+
|
|
80
|
+
suggestions: List[str] = []
|
|
81
|
+
|
|
82
|
+
# Check for tables that could be compressed
|
|
83
|
+
if '|' in text and '---' in text:
|
|
84
|
+
compressed = compress_markdown_table(text)
|
|
85
|
+
if len(compressed) < len(text) * 0.9:
|
|
86
|
+
suggestions.append("Table detected — compress_markdown_table could save tokens")
|
|
87
|
+
|
|
88
|
+
# Check for emoji
|
|
89
|
+
stripped = strip_emoji(text)
|
|
90
|
+
if len(stripped) < len(text):
|
|
91
|
+
suggestions.append("Contains emoji — strip_emoji could save tokens")
|
|
92
|
+
|
|
93
|
+
# Check for empty sections
|
|
94
|
+
sections = parse_sections(text)
|
|
95
|
+
empty_count = sum(1 for h, b, _ in sections if h and not b.strip())
|
|
96
|
+
if empty_count > 0:
|
|
97
|
+
suggestions.append(f"{empty_count} empty section(s) — remove_empty_sections")
|
|
98
|
+
|
|
99
|
+
# Check token budget
|
|
100
|
+
budget = DEFAULT_BUDGETS.get(path.name, DEFAULT_BUDGETS["workspace_total"])
|
|
101
|
+
if tokens > budget:
|
|
102
|
+
suggestions.append(f"Over budget: {tokens:,} tokens (budget: {budget:,})")
|
|
103
|
+
|
|
104
|
+
if is_stale:
|
|
105
|
+
suggestions.append(f"Stale: not modified in {age:.0f} days")
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
"path": str(path),
|
|
109
|
+
"file": str(path),
|
|
110
|
+
"name": path.name,
|
|
111
|
+
"tokens": tokens,
|
|
112
|
+
"age_days": round(age, 1),
|
|
113
|
+
"is_stale": is_stale,
|
|
114
|
+
"suggestions": suggestions,
|
|
115
|
+
"sections": len(sections),
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def audit_workspace(
|
|
120
|
+
workspace: str,
|
|
121
|
+
stale_days: int = 14,
|
|
122
|
+
) -> Dict[str, Any]:
|
|
123
|
+
"""Audit all memory files in *workspace*.
|
|
124
|
+
|
|
125
|
+
Raises FileNotFoundError_ if workspace doesn't exist.
|
|
126
|
+
"""
|
|
127
|
+
p = Path(workspace)
|
|
128
|
+
if not p.exists():
|
|
129
|
+
raise FileNotFoundError_(f"Workspace not found: {workspace}")
|
|
130
|
+
|
|
131
|
+
files: List[Path] = []
|
|
132
|
+
for f in sorted(p.glob("*.md")):
|
|
133
|
+
files.append(f)
|
|
134
|
+
mem_dir = p / "memory"
|
|
135
|
+
if mem_dir.is_dir():
|
|
136
|
+
for f in sorted(mem_dir.glob("*.md")):
|
|
137
|
+
files.append(f)
|
|
138
|
+
|
|
139
|
+
if not files:
|
|
140
|
+
return {
|
|
141
|
+
"total_files": 0,
|
|
142
|
+
"total_tokens": 0,
|
|
143
|
+
"files": [],
|
|
144
|
+
"age_distribution": {},
|
|
145
|
+
"suggestions": [],
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
file_results = [audit_file(f, stale_days=stale_days) for f in files]
|
|
149
|
+
total_tokens = sum(r["tokens"] for r in file_results)
|
|
150
|
+
|
|
151
|
+
# Age distribution
|
|
152
|
+
age_bins = {"<7d": 0, "7-30d": 0, "30-90d": 0, ">90d": 0}
|
|
153
|
+
for r in file_results:
|
|
154
|
+
age = r["age_days"]
|
|
155
|
+
if age < 7:
|
|
156
|
+
age_bins["<7d"] += 1
|
|
157
|
+
elif age < 30:
|
|
158
|
+
age_bins["7-30d"] += 1
|
|
159
|
+
elif age < 90:
|
|
160
|
+
age_bins["30-90d"] += 1
|
|
161
|
+
else:
|
|
162
|
+
age_bins[">90d"] += 1
|
|
163
|
+
|
|
164
|
+
# Aggregate suggestions
|
|
165
|
+
all_suggestions = []
|
|
166
|
+
for r in file_results:
|
|
167
|
+
for s in r["suggestions"]:
|
|
168
|
+
all_suggestions.append(f"[{r['name']}] {s}")
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
"total_files": len(file_results),
|
|
172
|
+
"total_tokens": total_tokens,
|
|
173
|
+
"files": file_results,
|
|
174
|
+
"age_distribution": age_bins,
|
|
175
|
+
"suggestions": all_suggestions,
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def format_report(result: Dict[str, Any]) -> str:
|
|
180
|
+
"""Format audit result as a human-readable report."""
|
|
181
|
+
lines = [
|
|
182
|
+
"=== Memory Audit Report ===",
|
|
183
|
+
f"Files: {result['total_files']}",
|
|
184
|
+
f"Total tokens: {result['total_tokens']:,}",
|
|
185
|
+
"",
|
|
186
|
+
"Age distribution:",
|
|
187
|
+
]
|
|
188
|
+
for bucket, count in result.get("age_distribution", {}).items():
|
|
189
|
+
lines.append(f" {bucket}: {count} files")
|
|
190
|
+
|
|
191
|
+
if result.get("suggestions"):
|
|
192
|
+
lines.append("\nSuggestions:")
|
|
193
|
+
for s in result["suggestions"]:
|
|
194
|
+
lines.append(f" - {s}")
|
|
195
|
+
else:
|
|
196
|
+
lines.append("\nNo suggestions — workspace looks healthy.")
|
|
197
|
+
|
|
198
|
+
return '\n'.join(lines)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def main():
|
|
202
|
+
parser = argparse.ArgumentParser(description="Audit workspace memory files")
|
|
203
|
+
parser.add_argument("workspace", help="Workspace directory")
|
|
204
|
+
parser.add_argument("--stale-days", type=int, default=14, help="Days before stale")
|
|
205
|
+
parser.add_argument("--json", action="store_true", help="JSON output")
|
|
206
|
+
args = parser.parse_args()
|
|
207
|
+
|
|
208
|
+
result = audit_workspace(args.workspace, stale_days=args.stale_days)
|
|
209
|
+
if args.json:
|
|
210
|
+
print(json.dumps(result, indent=2))
|
|
211
|
+
else:
|
|
212
|
+
print(format_report(result))
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
if __name__ == "__main__":
|
|
216
|
+
main()
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Compress memory files using rule-based preprocessing + LLM semantic compression.
|
|
3
|
+
|
|
4
|
+
Two-phase approach:
|
|
5
|
+
1. Rule engine: dedup lines, strip markdown redundancy, merge similar entries
|
|
6
|
+
2. LLM prompt: generate a prompt for semantic compression of remaining content
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 compress_memory.py <path> [--dry-run] [--output FILE] [--older-than DAYS] [--no-llm]
|
|
10
|
+
|
|
11
|
+
Part of claw-compactor. License: MIT.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import json
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
import time
|
|
20
|
+
from datetime import datetime, timedelta
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import List, Dict, Any, Optional
|
|
23
|
+
|
|
24
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
25
|
+
from lib.tokens import estimate_tokens, using_tiktoken
|
|
26
|
+
from lib.markdown import (
|
|
27
|
+
strip_markdown_redundancy, remove_duplicate_lines, parse_sections,
|
|
28
|
+
normalize_chinese_punctuation, strip_emoji, remove_empty_sections,
|
|
29
|
+
compress_markdown_table, merge_similar_bullets, merge_short_bullets,
|
|
30
|
+
)
|
|
31
|
+
from lib.dedup import find_duplicates, merge_duplicates
|
|
32
|
+
from lib.exceptions import FileNotFoundError_, MemCompressError
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
# LLM prompt template for semantic compression
|
|
37
|
+
COMPRESS_PROMPT = """You are a memory compression assistant. Compress the following text to approximately {target_pct}% of its current size while preserving ALL factual information, decisions, configurations, and actionable items.
|
|
38
|
+
|
|
39
|
+
Rules:
|
|
40
|
+
- Keep all names, IPs, paths, tokens, dates, and technical details EXACTLY
|
|
41
|
+
- Remove filler words, redundant explanations, and verbose phrasing
|
|
42
|
+
- Merge related items
|
|
43
|
+
- Use concise notation (key:value, abbreviations)
|
|
44
|
+
- Preserve markdown structure (headers, bullets)
|
|
45
|
+
- Output ONLY the compressed text, no commentary
|
|
46
|
+
|
|
47
|
+
Text to compress:
|
|
48
|
+
---
|
|
49
|
+
{content}
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
Compressed version:"""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _file_age_days(path: Path) -> float:
|
|
56
|
+
"""Return file age in days based on mtime."""
|
|
57
|
+
return (time.time() - path.stat().st_mtime) / 86400
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def rule_compress(
|
|
61
|
+
text: str,
|
|
62
|
+
enable_emoji_strip: bool = True,
|
|
63
|
+
) -> str:
|
|
64
|
+
"""Apply all rule-based compression passes to *text*.
|
|
65
|
+
|
|
66
|
+
Returns the compressed text. Never increases token count.
|
|
67
|
+
"""
|
|
68
|
+
if not text:
|
|
69
|
+
return ""
|
|
70
|
+
|
|
71
|
+
result = text
|
|
72
|
+
|
|
73
|
+
# 1. Normalize Chinese punctuation
|
|
74
|
+
result = normalize_chinese_punctuation(result)
|
|
75
|
+
|
|
76
|
+
# 2. Strip markdown redundancy (excess blanks, trailing whitespace)
|
|
77
|
+
result = strip_markdown_redundancy(result)
|
|
78
|
+
|
|
79
|
+
# 3. Remove duplicate lines
|
|
80
|
+
result = remove_duplicate_lines(result)
|
|
81
|
+
|
|
82
|
+
# 4. Remove empty sections
|
|
83
|
+
result = remove_empty_sections(result)
|
|
84
|
+
|
|
85
|
+
# 5. Compress markdown tables to key:value
|
|
86
|
+
result = compress_markdown_table(result)
|
|
87
|
+
|
|
88
|
+
# 6. Strip emoji if enabled
|
|
89
|
+
if enable_emoji_strip:
|
|
90
|
+
result = strip_emoji(result)
|
|
91
|
+
|
|
92
|
+
# 7. Merge similar bullets
|
|
93
|
+
result = merge_similar_bullets(result)
|
|
94
|
+
|
|
95
|
+
# 8. Merge short bullets
|
|
96
|
+
result = merge_short_bullets(result)
|
|
97
|
+
|
|
98
|
+
# 9. Final cleanup
|
|
99
|
+
result = strip_markdown_redundancy(result)
|
|
100
|
+
|
|
101
|
+
return result
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def generate_llm_prompt(content: str, target_pct: int = 50) -> str:
|
|
105
|
+
"""Generate an LLM prompt for semantic compression of *content*."""
|
|
106
|
+
return COMPRESS_PROMPT.format(content=content, target_pct=target_pct)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _collect_files(
|
|
110
|
+
target: str,
|
|
111
|
+
older_than: Optional[int] = None,
|
|
112
|
+
) -> List[Path]:
|
|
113
|
+
"""Collect markdown files from *target* (file or directory).
|
|
114
|
+
|
|
115
|
+
If *older_than* is set, only include files older than N days.
|
|
116
|
+
"""
|
|
117
|
+
path = Path(target)
|
|
118
|
+
if not path.exists():
|
|
119
|
+
raise FileNotFoundError_(f"Path not found: {target}")
|
|
120
|
+
|
|
121
|
+
if path.is_file():
|
|
122
|
+
if older_than is not None and _file_age_days(path) < older_than:
|
|
123
|
+
return []
|
|
124
|
+
return [path]
|
|
125
|
+
|
|
126
|
+
# Directory: collect all .md files recursively, excluding junk dirs
|
|
127
|
+
_EXCLUDE_DIRS = {"node_modules", ".git", "__pycache__", ".venv", "venv",
|
|
128
|
+
"target", "dist", "build", ".tox", ".mypy_cache", ".pytest_cache"}
|
|
129
|
+
files = []
|
|
130
|
+
for f in sorted(path.rglob("*.md")):
|
|
131
|
+
if _EXCLUDE_DIRS.intersection(f.relative_to(path).parts):
|
|
132
|
+
continue
|
|
133
|
+
files.append(f)
|
|
134
|
+
if older_than is not None:
|
|
135
|
+
files = [f for f in files if _file_age_days(f) >= older_than]
|
|
136
|
+
return files
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def compress_file(
|
|
140
|
+
path: Path,
|
|
141
|
+
dry_run: bool = False,
|
|
142
|
+
output: Optional[str] = None,
|
|
143
|
+
no_llm: bool = False,
|
|
144
|
+
) -> Dict[str, Any]:
|
|
145
|
+
"""Compress a single file using rule-based compression.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
path: File to compress.
|
|
149
|
+
dry_run: If True, don't write changes.
|
|
150
|
+
output: Optional output file path.
|
|
151
|
+
no_llm: If True, skip LLM prompt generation.
|
|
152
|
+
|
|
153
|
+
Returns a dict with compression statistics.
|
|
154
|
+
"""
|
|
155
|
+
path = Path(path)
|
|
156
|
+
original = path.read_text(encoding="utf-8")
|
|
157
|
+
original_tokens = estimate_tokens(original)
|
|
158
|
+
|
|
159
|
+
compressed = rule_compress(original)
|
|
160
|
+
compressed_tokens = estimate_tokens(compressed)
|
|
161
|
+
|
|
162
|
+
reduction_pct = ((original_tokens - compressed_tokens) / original_tokens * 100) if original_tokens else 0.0
|
|
163
|
+
result: Dict[str, Any] = {
|
|
164
|
+
"file": str(path),
|
|
165
|
+
"original_tokens": original_tokens,
|
|
166
|
+
"rule_compressed_tokens": compressed_tokens,
|
|
167
|
+
"rule_reduction_pct": round(reduction_pct, 2),
|
|
168
|
+
"dry_run": dry_run,
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if not no_llm and compressed.strip():
|
|
172
|
+
result["llm_prompt"] = generate_llm_prompt(compressed)
|
|
173
|
+
|
|
174
|
+
if not dry_run:
|
|
175
|
+
target = Path(output) if output else path
|
|
176
|
+
target.write_text(compressed, encoding="utf-8")
|
|
177
|
+
result["written_to"] = str(target)
|
|
178
|
+
|
|
179
|
+
return result
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def llm_compress_file(
|
|
183
|
+
path: Path,
|
|
184
|
+
target_pct: int = 40,
|
|
185
|
+
) -> Dict[str, Any]:
|
|
186
|
+
"""Generate an LLM compression prompt for a file and write it to a .prompt file.
|
|
187
|
+
|
|
188
|
+
Returns stats dict with original_tokens, rule_compressed_tokens, prompt_file, etc.
|
|
189
|
+
"""
|
|
190
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
191
|
+
original_tokens = estimate_tokens(text)
|
|
192
|
+
compressed = rule_compress(text)
|
|
193
|
+
rule_tokens = estimate_tokens(compressed)
|
|
194
|
+
prompt = generate_llm_prompt(compressed, target_pct)
|
|
195
|
+
prompt_tokens = estimate_tokens(prompt)
|
|
196
|
+
|
|
197
|
+
prompt_path = path.with_suffix(".prompt.md")
|
|
198
|
+
prompt_path.write_text(prompt, encoding="utf-8")
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
"file": str(path),
|
|
202
|
+
"original_tokens": original_tokens,
|
|
203
|
+
"rule_compressed_tokens": rule_tokens,
|
|
204
|
+
"prompt_tokens": prompt_tokens,
|
|
205
|
+
"prompt_file": str(prompt_path),
|
|
206
|
+
"target_pct": target_pct,
|
|
207
|
+
"instruction": f"Feed this prompt to an LLM for further {target_pct}% compression.",
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def main():
|
|
212
|
+
parser = argparse.ArgumentParser(description="Compress memory files")
|
|
213
|
+
parser.add_argument("path", help="File or directory to compress")
|
|
214
|
+
parser.add_argument("--dry-run", action="store_true")
|
|
215
|
+
parser.add_argument("--output", help="Output file")
|
|
216
|
+
parser.add_argument("--older-than", type=int, help="Only files older than N days")
|
|
217
|
+
parser.add_argument("--no-llm", action="store_true", help="Skip LLM prompt")
|
|
218
|
+
parser.add_argument("--json", action="store_true")
|
|
219
|
+
args = parser.parse_args()
|
|
220
|
+
|
|
221
|
+
files = _collect_files(args.path, older_than=args.older_than)
|
|
222
|
+
results = []
|
|
223
|
+
for f in files:
|
|
224
|
+
r = compress_file(f, dry_run=args.dry_run, output=args.output, no_llm=args.no_llm)
|
|
225
|
+
results.append(r)
|
|
226
|
+
|
|
227
|
+
if args.json:
|
|
228
|
+
print(json.dumps(results, indent=2, ensure_ascii=False))
|
|
229
|
+
else:
|
|
230
|
+
for r in results:
|
|
231
|
+
saved = r["original_tokens"] - r["rule_compressed_tokens"]
|
|
232
|
+
print(f"{r['file']}: {r['original_tokens']} → {r['rule_compressed_tokens']} tokens (saved {saved})")
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
if __name__ == "__main__":
|
|
236
|
+
main()
|