@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.
Files changed (745) hide show
  1. package/README.md +85 -0
  2. package/agents/cos.json +2 -5
  3. package/agents/hermes/AGENTS.md +25 -49
  4. package/agents/hermes/fix-kimaki/SKILL.md +19 -92
  5. package/agents/hermes/hermes-fixer.md +44 -74
  6. package/agents/hermes.json +6 -18
  7. package/kanban/SKILL.md +18 -18
  8. package/kanban/package.json +1 -1
  9. package/kanban/src/dispatcher.mjs +1 -1
  10. package/kanban/templates/blog-social-campaign.yaml +6 -2
  11. package/kanban/templates/social-campaign.yaml +9 -4
  12. package/mcp/jev-calibration.mjs +335 -0
  13. package/mcp/jev-client.mjs +119 -0
  14. package/mcp/jev-thresholds.json +27 -0
  15. package/package.json +13 -9
  16. package/scripts/doctor-watchdog.sh +73 -0
  17. package/scripts/install-services.sh +34 -27
  18. package/scripts/self-improve-weekly.sh +34 -0
  19. package/scripts/sync-skills.mjs +121 -0
  20. package/skills/ab-test-setup/SKILL.md +266 -0
  21. package/skills/ab-test-setup/evals/evals.json +105 -0
  22. package/skills/ab-test-setup/references/sample-size-guide.md +263 -0
  23. package/skills/ab-test-setup/references/test-templates.md +277 -0
  24. package/skills/agent-reach/SKILL.md +132 -0
  25. package/skills/agent-reach/references/career.md +29 -0
  26. package/skills/agent-reach/references/dev.md +62 -0
  27. package/skills/agent-reach/references/search.md +33 -0
  28. package/skills/agent-reach/references/social.md +232 -0
  29. package/skills/agent-reach/references/video.md +130 -0
  30. package/skills/agent-reach/references/web.md +50 -0
  31. package/skills/ai-agent-seo/SKILL.md +450 -0
  32. package/skills/ai-cold-email-intelligence/SKILL.md +54 -0
  33. package/skills/ai-cold-email-intelligence/references/prompts.md +21 -0
  34. package/skills/ai-consensus-builder/SKILL.md +324 -0
  35. package/skills/ai-seo/SKILL.md +399 -0
  36. package/skills/ai-seo/evals/evals.json +90 -0
  37. package/skills/ai-seo/references/content-patterns.md +284 -0
  38. package/skills/ai-seo/references/platform-ranking-factors.md +152 -0
  39. package/skills/ai-visibility-audit/SKILL.md +322 -0
  40. package/skills/analytics-tracking/SKILL.md +309 -0
  41. package/skills/analytics-tracking/evals/evals.json +90 -0
  42. package/skills/analytics-tracking/references/event-library.md +260 -0
  43. package/skills/analytics-tracking/references/ga4-implementation.md +300 -0
  44. package/skills/analytics-tracking/references/gtm-implementation.md +390 -0
  45. package/skills/article-generator/SKILL.md +216 -0
  46. package/skills/auto-indexing/SKILL.md +179 -0
  47. package/skills/auto-indexing/scripts/auto-indexing.js +257 -0
  48. package/skills/auto-skill/SKILL.md +151 -0
  49. package/skills/auto-skill/correction-queue.js +102 -0
  50. package/skills/auto-skill/dedup.js +97 -0
  51. package/skills/auto-skill/skill-router.js +224 -0
  52. package/skills/autoresearch/SKILL.md +334 -0
  53. package/skills/autoresearch/autoresearch-autoresearch/SKILL.md.baseline +329 -0
  54. package/skills/autoresearch/autoresearch-autoresearch/changelog.md +34 -0
  55. package/skills/autoresearch/autoresearch-autoresearch/dashboard.html +116 -0
  56. package/skills/autoresearch/autoresearch-autoresearch/evals.md +39 -0
  57. package/skills/autoresearch/autoresearch-autoresearch/results.json +44 -0
  58. package/skills/autoresearch/autoresearch-autoresearch/results.tsv +3 -0
  59. package/skills/autoresearch/eval-guide.md +121 -0
  60. package/skills/b2b-cold-outreach/SKILL.md +322 -0
  61. package/skills/birdclaw/SKILL.md +82 -0
  62. package/skills/brainstorm/SKILL.md +168 -0
  63. package/skills/brand-kit-playground/SKILL.md +312 -0
  64. package/skills/brand-kit-playground/references/html-architecture.md +316 -0
  65. package/skills/brand-kit-playground/references/steal-patterns.md +88 -0
  66. package/skills/brand-voice/SKILL.md +223 -0
  67. package/skills/brand-voice/references/honesty-as-positioning.md +60 -0
  68. package/skills/brand-voice/references/voice-modes.md +1158 -0
  69. package/skills/business-advisory-council/README.md +136 -0
  70. package/skills/business-advisory-council/SKILL.md +94 -0
  71. package/skills/business-advisory-council/business-advisory-council.py +492 -0
  72. package/skills/business-advisory-council/discord-components-decision.json +8 -0
  73. package/skills/business-advisory-council/examples/steve-conley-partnership.json +6 -0
  74. package/skills/business-advisory-council/steve-conley-call-brief.json +6 -0
  75. package/skills/churn-prevention/SKILL.md +305 -0
  76. package/skills/churn-prevention/evals/evals.json +93 -0
  77. package/skills/churn-prevention/references/cancel-flow-patterns.md +316 -0
  78. package/skills/churn-prevention/references/dunning-playbook.md +408 -0
  79. package/skills/claw-compactor/LICENSE +21 -0
  80. package/skills/claw-compactor/README.md +459 -0
  81. package/skills/claw-compactor/SKILL.md +329 -0
  82. package/skills/claw-compactor/benchmark/RESULTS.md +104 -0
  83. package/skills/claw-compactor/benchmark/__init__.py +1 -0
  84. package/skills/claw-compactor/benchmark/compressors.py +520 -0
  85. package/skills/claw-compactor/benchmark/data/sample_01_devops.json +82 -0
  86. package/skills/claw-compactor/benchmark/data/sample_02_trading.json +54 -0
  87. package/skills/claw-compactor/benchmark/data/sample_03_ml_short.json +38 -0
  88. package/skills/claw-compactor/benchmark/data/sample_04_mixed_long.json +318 -0
  89. package/skills/claw-compactor/benchmark/data/sample_05_sysadmin.json +56 -0
  90. package/skills/claw-compactor/benchmark/evaluate.py +278 -0
  91. package/skills/claw-compactor/benchmark/report.py +241 -0
  92. package/skills/claw-compactor/benchmark/results/benchmark_results.json +405 -0
  93. package/skills/claw-compactor/benchmark/run_benchmark.py +238 -0
  94. package/skills/claw-compactor/engram.yaml +49 -0
  95. package/skills/claw-compactor/proxy/README.md +87 -0
  96. package/skills/claw-compactor/proxy/dashboard.html +804 -0
  97. package/skills/claw-compactor/proxy/event-log.mjs +213 -0
  98. package/skills/claw-compactor/proxy/fair-queue.mjs +288 -0
  99. package/skills/claw-compactor/proxy/metrics-store.mjs +425 -0
  100. package/skills/claw-compactor/proxy/package-lock.json +125 -0
  101. package/skills/claw-compactor/proxy/package.json +15 -0
  102. package/skills/claw-compactor/proxy/portal.html +360 -0
  103. package/skills/claw-compactor/proxy/process-registry.mjs +447 -0
  104. package/skills/claw-compactor/proxy/rate-limiter.mjs +117 -0
  105. package/skills/claw-compactor/proxy/redis-client.mjs +75 -0
  106. package/skills/claw-compactor/proxy/retry.mjs +182 -0
  107. package/skills/claw-compactor/proxy/server.mjs +2100 -0
  108. package/skills/claw-compactor/proxy/session-affinity.mjs +177 -0
  109. package/skills/claw-compactor/proxy/start.sh +23 -0
  110. package/skills/claw-compactor/proxy/test/event-log.test.mjs +237 -0
  111. package/skills/claw-compactor/proxy/test/helpers.mjs +103 -0
  112. package/skills/claw-compactor/proxy/test/integration.test.mjs +297 -0
  113. package/skills/claw-compactor/proxy/test/metrics-store.test.mjs +243 -0
  114. package/skills/claw-compactor/proxy/test/process-registry.test.mjs +390 -0
  115. package/skills/claw-compactor/proxy/test/rate-limiter.test.mjs +121 -0
  116. package/skills/claw-compactor/proxy/test/redis-client.test.mjs +62 -0
  117. package/skills/claw-compactor/proxy/test/token-tracker.test.mjs +200 -0
  118. package/skills/claw-compactor/proxy/token-tracker.mjs +482 -0
  119. package/skills/claw-compactor/pyproject.toml +26 -0
  120. package/skills/claw-compactor/references/README.md +44 -0
  121. package/skills/claw-compactor/references/architecture.md +197 -0
  122. package/skills/claw-compactor/references/benchmarks.md +94 -0
  123. package/skills/claw-compactor/references/compression-prompts.md +39 -0
  124. package/skills/claw-compactor/references/compression-techniques.md +219 -0
  125. package/skills/claw-compactor/references/testing.md +160 -0
  126. package/skills/claw-compactor/scripts/audit_memory.py +216 -0
  127. package/skills/claw-compactor/scripts/compress_memory.py +236 -0
  128. package/skills/claw-compactor/scripts/compressed_context.py +280 -0
  129. package/skills/claw-compactor/scripts/dedup_memory.py +147 -0
  130. package/skills/claw-compactor/scripts/dictionary_compress.py +170 -0
  131. package/skills/claw-compactor/scripts/engram-auto.sh +152 -0
  132. package/skills/claw-compactor/scripts/engram_auto.py +695 -0
  133. package/skills/claw-compactor/scripts/engram_cli.py +474 -0
  134. package/skills/claw-compactor/scripts/estimate_tokens.py +131 -0
  135. package/skills/claw-compactor/scripts/generate_summary_tiers.py +292 -0
  136. package/skills/claw-compactor/scripts/lib/__init__.py +34 -0
  137. package/skills/claw-compactor/scripts/lib/config.py +289 -0
  138. package/skills/claw-compactor/scripts/lib/dedup.py +119 -0
  139. package/skills/claw-compactor/scripts/lib/dictionary.py +281 -0
  140. package/skills/claw-compactor/scripts/lib/engram.py +793 -0
  141. package/skills/claw-compactor/scripts/lib/engram_prompts.py +175 -0
  142. package/skills/claw-compactor/scripts/lib/engram_storage.py +254 -0
  143. package/skills/claw-compactor/scripts/lib/exceptions.py +24 -0
  144. package/skills/claw-compactor/scripts/lib/markdown.py +312 -0
  145. package/skills/claw-compactor/scripts/lib/rle.py +165 -0
  146. package/skills/claw-compactor/scripts/lib/tokenizer_optimizer.py +188 -0
  147. package/skills/claw-compactor/scripts/lib/tokens.py +68 -0
  148. package/skills/claw-compactor/scripts/mem_compress.py +788 -0
  149. package/skills/claw-compactor/scripts/observation_compressor.py +346 -0
  150. package/skills/claw-compactor/tests/__init__.py +0 -0
  151. package/skills/claw-compactor/tests/conftest.py +94 -0
  152. package/skills/claw-compactor/tests/test_audit_comprehensive.py +123 -0
  153. package/skills/claw-compactor/tests/test_audit_memory.py +67 -0
  154. package/skills/claw-compactor/tests/test_benchmark.py +122 -0
  155. package/skills/claw-compactor/tests/test_cli_commands.py +228 -0
  156. package/skills/claw-compactor/tests/test_compress_memory.py +109 -0
  157. package/skills/claw-compactor/tests/test_compress_memory_comprehensive.py +191 -0
  158. package/skills/claw-compactor/tests/test_compressed_context.py +145 -0
  159. package/skills/claw-compactor/tests/test_config.py +54 -0
  160. package/skills/claw-compactor/tests/test_dedup_memory.py +124 -0
  161. package/skills/claw-compactor/tests/test_dictionary.py +327 -0
  162. package/skills/claw-compactor/tests/test_dictionary_comprehensive.py +241 -0
  163. package/skills/claw-compactor/tests/test_engram.py +1091 -0
  164. package/skills/claw-compactor/tests/test_engram_auto.py +529 -0
  165. package/skills/claw-compactor/tests/test_error_handling.py +194 -0
  166. package/skills/claw-compactor/tests/test_estimate_tokens.py +99 -0
  167. package/skills/claw-compactor/tests/test_generate_summary_tiers.py +105 -0
  168. package/skills/claw-compactor/tests/test_integration.py +249 -0
  169. package/skills/claw-compactor/tests/test_lib_dedup.py +135 -0
  170. package/skills/claw-compactor/tests/test_lib_markdown.py +388 -0
  171. package/skills/claw-compactor/tests/test_lib_tokens.py +82 -0
  172. package/skills/claw-compactor/tests/test_main_entry.py +176 -0
  173. package/skills/claw-compactor/tests/test_markdown_advanced.py +284 -0
  174. package/skills/claw-compactor/tests/test_new_features.py +77 -0
  175. package/skills/claw-compactor/tests/test_observation_comprehensive.py +261 -0
  176. package/skills/claw-compactor/tests/test_observation_compressor.py +128 -0
  177. package/skills/claw-compactor/tests/test_performance.py +172 -0
  178. package/skills/claw-compactor/tests/test_pipeline.py +109 -0
  179. package/skills/claw-compactor/tests/test_real_workspace.py +161 -0
  180. package/skills/claw-compactor/tests/test_rle.py +114 -0
  181. package/skills/claw-compactor/tests/test_rle_comprehensive.py +151 -0
  182. package/skills/claw-compactor/tests/test_roundtrip.py +253 -0
  183. package/skills/claw-compactor/tests/test_roundtrip_comprehensive.py +192 -0
  184. package/skills/claw-compactor/tests/test_tiers_comprehensive.py +171 -0
  185. package/skills/claw-compactor/tests/test_token_economics.py +237 -0
  186. package/skills/claw-compactor/tests/test_tokenizer_optimizer.py +175 -0
  187. package/skills/claw-compactor/tests/test_tokenizer_optimizer_comprehensive.py +241 -0
  188. package/skills/claw-compactor/tests/test_tokens.py +27 -0
  189. package/skills/cmo/CHANGELOG.md +61 -0
  190. package/skills/cmo/SKILL.md +500 -0
  191. package/skills/cmo/references/ai-slop-patterns.md +56 -0
  192. package/skills/cmo/references/analytics-guide.md +152 -0
  193. package/skills/cmo/references/ideas-library.md +197 -0
  194. package/skills/cmo/rules/brand-file-map.md +198 -0
  195. package/skills/cmo/rules/brand-memory.md +158 -0
  196. package/skills/cmo/rules/cli-runtime-index.md +95 -0
  197. package/skills/cmo/rules/command-reference.md +167 -0
  198. package/skills/cmo/rules/communication.md +15 -0
  199. package/skills/cmo/rules/context-switch.md +101 -0
  200. package/skills/cmo/rules/ecosystem.md +125 -0
  201. package/skills/cmo/rules/error-recovery.md +98 -0
  202. package/skills/cmo/rules/learning-loop.md +170 -0
  203. package/skills/cmo/rules/monorepo.md +78 -0
  204. package/skills/cmo/rules/output-format.md +124 -0
  205. package/skills/cmo/rules/persona.md +15 -0
  206. package/skills/cmo/rules/playbooks.md +327 -0
  207. package/skills/cmo/rules/progressive-enhancement.md +231 -0
  208. package/skills/cmo/rules/publish-index.md +106 -0
  209. package/skills/cmo/rules/quality-gate.md +90 -0
  210. package/skills/cmo/rules/recency-grounding.md +124 -0
  211. package/skills/cmo/rules/safety.md +80 -0
  212. package/skills/cmo/rules/studio-api-index.md +138 -0
  213. package/skills/cmo/rules/studio-integration.md +147 -0
  214. package/skills/cmo/rules/sub-agents.md +167 -0
  215. package/skills/cold-email/SKILL.md +240 -0
  216. package/skills/cold-email/evals/evals.json +94 -0
  217. package/skills/cold-email/references/benchmarks.md +83 -0
  218. package/skills/cold-email/references/follow-up-sequences.md +81 -0
  219. package/skills/cold-email/references/frameworks.md +90 -0
  220. package/skills/cold-email/references/personalization.md +79 -0
  221. package/skills/cold-email/references/subject-lines.md +53 -0
  222. package/skills/competitive-intel/SKILL.md +433 -0
  223. package/skills/competitive-intel/references/competitive-frameworks.md +145 -0
  224. package/skills/competitor-alternatives/SKILL.md +362 -0
  225. package/skills/competitor-alternatives/evals/evals.json +93 -0
  226. package/skills/competitor-alternatives/references/content-architecture.md +271 -0
  227. package/skills/competitor-alternatives/references/templates.md +223 -0
  228. package/skills/concreteness-fixer/SKILL.md +483 -0
  229. package/skills/concreteness-fixer/scripts/validation/concreteness-validator.js +221 -0
  230. package/skills/concreteness-fixer/utils/execFileNoThrow.js +16 -0
  231. package/skills/content-atomizer/SKILL.md +424 -0
  232. package/skills/content-atomizer/references/hook-strategies.md +56 -0
  233. package/skills/content-atomizer/references/platform-specs.md +118 -0
  234. package/skills/content-atomizer/references/platforms/bluesky.md +64 -0
  235. package/skills/content-atomizer/references/platforms/instagram.md +77 -0
  236. package/skills/content-atomizer/references/platforms/linkedin.md +120 -0
  237. package/skills/content-atomizer/references/platforms/reddit.md +73 -0
  238. package/skills/content-atomizer/references/platforms/threads.md +64 -0
  239. package/skills/content-atomizer/references/platforms/tiktok.md +55 -0
  240. package/skills/content-atomizer/references/platforms/twitter.md +123 -0
  241. package/skills/content-atomizer/references/platforms/youtube.md +56 -0
  242. package/skills/content-atomizer/references/tweet-patterns.md +40 -0
  243. package/skills/content-repost-manager/SKILL.md +245 -0
  244. package/skills/content-repost-manager/scripts/content-repost-scan.py +133 -0
  245. package/skills/context-recovery/.clawdhub/origin.json +7 -0
  246. package/skills/context-recovery/SKILL.md +198 -0
  247. package/skills/context-recovery/_meta.json +6 -0
  248. package/skills/conversion-flow-cro/SKILL.md +248 -0
  249. package/skills/conversion-flow-cro/references/flow-benchmarks.md +158 -0
  250. package/skills/copy-editing/SKILL.md +474 -0
  251. package/skills/copy-editing/evals/evals.json +89 -0
  252. package/skills/copy-editing/references/plain-english-alternatives.md +394 -0
  253. package/skills/copywriting/SKILL.md +349 -0
  254. package/skills/copywriting/evals/evals.json +111 -0
  255. package/skills/copywriting/references/awareness-level-guide.md +227 -0
  256. package/skills/copywriting/references/copy-frameworks.md +389 -0
  257. package/skills/copywriting/references/natural-transitions.md +272 -0
  258. package/skills/creative/SKILL.md +365 -0
  259. package/skills/creative/modes/ad-creative.md +1748 -0
  260. package/skills/creative/modes/product-photo.md +1520 -0
  261. package/skills/creative/modes/product-video.md +1657 -0
  262. package/skills/creative/modes/social-graphics.md +1511 -0
  263. package/skills/creative/modes/talking-head.md +2208 -0
  264. package/skills/creative/references/VISUAL_INTELLIGENCE.md +1233 -0
  265. package/skills/deep-serp-article/SKILL.md +677 -0
  266. package/skills/deep-serp-article/SKILL.md.bak +530 -0
  267. package/skills/earned-media/SKILL.md +260 -0
  268. package/skills/email-sequences/SKILL.md +446 -0
  269. package/skills/email-sequences/references/sequence-templates.md +1217 -0
  270. package/skills/firecrawl/.skill-meta.json +13 -0
  271. package/skills/firecrawl/SKILL.md +154 -0
  272. package/skills/firecrawl/rules/install.md +63 -0
  273. package/skills/firecrawl/rules/security.md +26 -0
  274. package/skills/form-cro/SKILL.md +429 -0
  275. package/skills/form-cro/evals/evals.json +90 -0
  276. package/skills/free-tool-strategy/SKILL.md +325 -0
  277. package/skills/free-tool-strategy/evals/evals.json +90 -0
  278. package/skills/free-tool-strategy/references/tool-types.md +253 -0
  279. package/skills/frontend-slides/SKILL.md +248 -0
  280. package/skills/frontend-slides/STYLE_PRESETS.md +347 -0
  281. package/skills/frontend-slides/animation-patterns.md +110 -0
  282. package/skills/frontend-slides/html-template.md +347 -0
  283. package/skills/frontend-slides/scripts/extract-pptx.py +96 -0
  284. package/skills/frontend-slides/viewport-base.css +153 -0
  285. package/skills/guardrail-framework/SKILL.md +319 -0
  286. package/skills/hook-generator/SKILL.md +438 -0
  287. package/skills/hook-generator/database/2026-PLATFORM-RESEARCH.md +211 -0
  288. package/skills/hook-generator/database/instagram-hooks.json +591 -0
  289. package/skills/hook-generator/database/linkedin-hooks.json +502 -0
  290. package/skills/hook-generator/database/medium-hooks.json +181 -0
  291. package/skills/hook-generator/database/tiktok-hooks.json +337 -0
  292. package/skills/hook-generator/database/twitter-hooks.json +567 -0
  293. package/skills/hook-generator/database/youtube-hooks.json +275 -0
  294. package/skills/hook-generator/package-lock.json +24 -0
  295. package/skills/hook-generator/package.json +5 -0
  296. package/skills/hook-generator/references/hook-generation-system.md +257 -0
  297. package/skills/hook-generator/references/hook-performance-analysis.json +153 -0
  298. package/skills/hook-generator/references/hooks-library.md +128 -0
  299. package/skills/hook-generator/references/platform-hook-frameworks.md +275 -0
  300. package/skills/hook-generator/scripts/generate-hooks-unified.js +722 -0
  301. package/skills/hook-generator/scripts/generate-hooks.js +225 -0
  302. package/skills/hook-generator/scripts/generate.sh +36 -0
  303. package/skills/hook-generator/scripts/ralph-hook-enhancer.js +864 -0
  304. package/skills/hook-generator/scripts/test-gemini-output.js +51 -0
  305. package/skills/humanizer/README.md +120 -0
  306. package/skills/humanizer/SKILL.md +699 -0
  307. package/skills/image-gen/SKILL.md +277 -0
  308. package/skills/image-gen/references/prompt-patterns.md +114 -0
  309. package/skills/image-gen/references/visual-metaphors.md +51 -0
  310. package/skills/impeccable/SKILL.md +86 -0
  311. package/skills/impeccable/reference/adapt.md +312 -0
  312. package/skills/impeccable/reference/adapt.native.md +58 -0
  313. package/skills/impeccable/reference/android.md +40 -0
  314. package/skills/impeccable/reference/animate.md +86 -0
  315. package/skills/impeccable/reference/audit.md +136 -0
  316. package/skills/impeccable/reference/audit.native.md +139 -0
  317. package/skills/impeccable/reference/bolder.md +31 -0
  318. package/skills/impeccable/reference/clarify.md +94 -0
  319. package/skills/impeccable/reference/colorize.md +86 -0
  320. package/skills/impeccable/reference/craft-floor.md +42 -0
  321. package/skills/impeccable/reference/craft.md +5 -0
  322. package/skills/impeccable/reference/critique.md +788 -0
  323. package/skills/impeccable/reference/degraded/asset-producer.md +90 -0
  324. package/skills/impeccable/reference/degraded/documenter.md +24 -0
  325. package/skills/impeccable/reference/degraded/finish-reviewer.md +37 -0
  326. package/skills/impeccable/reference/degraded/manual-edit-applier.md +92 -0
  327. package/skills/impeccable/reference/delight.md +70 -0
  328. package/skills/impeccable/reference/distill.md +111 -0
  329. package/skills/impeccable/reference/doctor.md +53 -0
  330. package/skills/impeccable/reference/document.md +416 -0
  331. package/skills/impeccable/reference/extract.md +69 -0
  332. package/skills/impeccable/reference/harden.md +336 -0
  333. package/skills/impeccable/reference/hooks.md +105 -0
  334. package/skills/impeccable/reference/init.md +125 -0
  335. package/skills/impeccable/reference/ios.md +45 -0
  336. package/skills/impeccable/reference/layout.md +84 -0
  337. package/skills/impeccable/reference/live-setup.md +102 -0
  338. package/skills/impeccable/reference/live.md +323 -0
  339. package/skills/impeccable/reference/new-work.md +110 -0
  340. package/skills/impeccable/reference/onboard.md +234 -0
  341. package/skills/impeccable/reference/operate.md +61 -0
  342. package/skills/impeccable/reference/optimize.md +258 -0
  343. package/skills/impeccable/reference/overdrive.md +127 -0
  344. package/skills/impeccable/reference/polish.md +97 -0
  345. package/skills/impeccable/reference/quieter.md +99 -0
  346. package/skills/impeccable/reference/routing.md +18 -0
  347. package/skills/impeccable/reference/shape.md +59 -0
  348. package/skills/impeccable/reference/typeset.md +80 -0
  349. package/skills/impeccable/reference/visualize.md +49 -0
  350. package/skills/impeccable/scripts/command-metadata.json +94 -0
  351. package/skills/impeccable/scripts/concept-seed.mjs +558 -0
  352. package/skills/impeccable/scripts/context-signals.mjs +334 -0
  353. package/skills/impeccable/scripts/context.mjs +1467 -0
  354. package/skills/impeccable/scripts/critique-storage.mjs +213 -0
  355. package/skills/impeccable/scripts/detect-csp.mjs +198 -0
  356. package/skills/impeccable/scripts/detect.mjs +21 -0
  357. package/skills/impeccable/scripts/detector/browser/injected/index.mjs +2023 -0
  358. package/skills/impeccable/scripts/detector/cli/main.mjs +438 -0
  359. package/skills/impeccable/scripts/detector/design-system.mjs +1046 -0
  360. package/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +8283 -0
  361. package/skills/impeccable/scripts/detector/detect-antipatterns.mjs +50 -0
  362. package/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +372 -0
  363. package/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +1168 -0
  364. package/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +1186 -0
  365. package/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +264 -0
  366. package/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +189 -0
  367. package/skills/impeccable/scripts/detector/findings.mjs +18 -0
  368. package/skills/impeccable/scripts/detector/node/file-system.mjs +203 -0
  369. package/skills/impeccable/scripts/detector/profile/profiler.mjs +166 -0
  370. package/skills/impeccable/scripts/detector/registry/antipatterns.mjs +617 -0
  371. package/skills/impeccable/scripts/detector/rules/checks.mjs +5580 -0
  372. package/skills/impeccable/scripts/detector/shared/color.mjs +124 -0
  373. package/skills/impeccable/scripts/detector/shared/constants.mjs +112 -0
  374. package/skills/impeccable/scripts/detector/shared/fonts.mjs +30 -0
  375. package/skills/impeccable/scripts/detector/shared/inline-ignores.mjs +148 -0
  376. package/skills/impeccable/scripts/detector/shared/page.mjs +7 -0
  377. package/skills/impeccable/scripts/doctor.mjs +336 -0
  378. package/skills/impeccable/scripts/embed-prompt.mjs +133 -0
  379. package/skills/impeccable/scripts/generate-image.mjs +240 -0
  380. package/skills/impeccable/scripts/hook-admin.mjs +801 -0
  381. package/skills/impeccable/scripts/hook-before-edit.mjs +508 -0
  382. package/skills/impeccable/scripts/hook-lib.mjs +2153 -0
  383. package/skills/impeccable/scripts/hook.mjs +78 -0
  384. package/skills/impeccable/scripts/lib/artifact-schema.mjs +93 -0
  385. package/skills/impeccable/scripts/lib/composition-catalog.mjs +200 -0
  386. package/skills/impeccable/scripts/lib/concept-catalog.mjs +384 -0
  387. package/skills/impeccable/scripts/lib/design-parser.mjs +925 -0
  388. package/skills/impeccable/scripts/lib/impeccable-config.mjs +658 -0
  389. package/skills/impeccable/scripts/lib/impeccable-paths.mjs +137 -0
  390. package/skills/impeccable/scripts/lib/is-generated.mjs +69 -0
  391. package/skills/impeccable/scripts/lib/provider.mjs +5 -0
  392. package/skills/impeccable/scripts/lib/roll-selection.mjs +362 -0
  393. package/skills/impeccable/scripts/lib/staleness-deep.mjs +478 -0
  394. package/skills/impeccable/scripts/lib/staleness-notice.mjs +169 -0
  395. package/skills/impeccable/scripts/lib/staleness.mjs +457 -0
  396. package/skills/impeccable/scripts/lib/surface-briefs.mjs +151 -0
  397. package/skills/impeccable/scripts/lib/target-args.mjs +42 -0
  398. package/skills/impeccable/scripts/lib/target-slug.mjs +33 -0
  399. package/skills/impeccable/scripts/lib/template-extensions.mjs +146 -0
  400. package/skills/impeccable/scripts/live/accept-css.mjs +617 -0
  401. package/skills/impeccable/scripts/live/accept-verify.mjs +60 -0
  402. package/skills/impeccable/scripts/live/browser-script-parts.mjs +55 -0
  403. package/skills/impeccable/scripts/live/completion.mjs +28 -0
  404. package/skills/impeccable/scripts/live/event-validation.mjs +199 -0
  405. package/skills/impeccable/scripts/live/frameworks/astro.mjs +47 -0
  406. package/skills/impeccable/scripts/live/frameworks/detect-utils.mjs +73 -0
  407. package/skills/impeccable/scripts/live/frameworks/index.mjs +143 -0
  408. package/skills/impeccable/scripts/live/frameworks/journal.mjs +197 -0
  409. package/skills/impeccable/scripts/live/frameworks/nextjs.mjs +49 -0
  410. package/skills/impeccable/scripts/live/frameworks/nuxt.mjs +161 -0
  411. package/skills/impeccable/scripts/live/frameworks/script-src.mjs +17 -0
  412. package/skills/impeccable/scripts/live/frameworks/static-html.mjs +26 -0
  413. package/skills/impeccable/scripts/live/frameworks/sveltekit.mjs +71 -0
  414. package/skills/impeccable/scripts/live/frameworks/tag-strategy.mjs +247 -0
  415. package/skills/impeccable/scripts/live/frameworks/tanstack-start.mjs +70 -0
  416. package/skills/impeccable/scripts/live/frameworks/vite-generic.mjs +42 -0
  417. package/skills/impeccable/scripts/live/generation-preflight.mjs +149 -0
  418. package/skills/impeccable/scripts/live/insert-ui.mjs +458 -0
  419. package/skills/impeccable/scripts/live/instructions.mjs +142 -0
  420. package/skills/impeccable/scripts/live/manual-apply.mjs +939 -0
  421. package/skills/impeccable/scripts/live/manual-edit-routes.mjs +357 -0
  422. package/skills/impeccable/scripts/live/manual-edits-buffer.mjs +152 -0
  423. package/skills/impeccable/scripts/live/poll-lanes.mjs +14 -0
  424. package/skills/impeccable/scripts/live/roots.mjs +508 -0
  425. package/skills/impeccable/scripts/live/session-store.mjs +563 -0
  426. package/skills/impeccable/scripts/live/source-lock.mjs +105 -0
  427. package/skills/impeccable/scripts/live/source-search.mjs +105 -0
  428. package/skills/impeccable/scripts/live/svelte-ast.mjs +961 -0
  429. package/skills/impeccable/scripts/live/svelte-component.mjs +1342 -0
  430. package/skills/impeccable/scripts/live/sveltekit-adapter.mjs +316 -0
  431. package/skills/impeccable/scripts/live/tanstack-adapter.mjs +280 -0
  432. package/skills/impeccable/scripts/live/ui-core.mjs +180 -0
  433. package/skills/impeccable/scripts/live/vocabulary.mjs +171 -0
  434. package/skills/impeccable/scripts/live-accept.mjs +954 -0
  435. package/skills/impeccable/scripts/live-browser-dom.js +146 -0
  436. package/skills/impeccable/scripts/live-browser-session.js +123 -0
  437. package/skills/impeccable/scripts/live-browser.js +12520 -0
  438. package/skills/impeccable/scripts/live-commit-manual-edits.mjs +1244 -0
  439. package/skills/impeccable/scripts/live-complete.mjs +107 -0
  440. package/skills/impeccable/scripts/live-copy-edit-agent.mjs +683 -0
  441. package/skills/impeccable/scripts/live-discard-manual-edits.mjs +51 -0
  442. package/skills/impeccable/scripts/live-inject.mjs +503 -0
  443. package/skills/impeccable/scripts/live-insert.mjs +292 -0
  444. package/skills/impeccable/scripts/live-manual-edit-evidence.mjs +368 -0
  445. package/skills/impeccable/scripts/live-poll.mjs +429 -0
  446. package/skills/impeccable/scripts/live-resume.mjs +123 -0
  447. package/skills/impeccable/scripts/live-server.mjs +1669 -0
  448. package/skills/impeccable/scripts/live-status.mjs +71 -0
  449. package/skills/impeccable/scripts/live-target.mjs +30 -0
  450. package/skills/impeccable/scripts/live-wrap.mjs +927 -0
  451. package/skills/impeccable/scripts/live.mjs +359 -0
  452. package/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  453. package/skills/impeccable/scripts/palette.mjs +628 -0
  454. package/skills/impeccable/scripts/pin.mjs +221 -0
  455. package/skills/impeccable/scripts/serve-question.mjs +932 -0
  456. package/skills/impeccable/scripts/surface-brief.mjs +74 -0
  457. package/skills/inkstone-admin/SKILL.md +66 -0
  458. package/skills/jev-hook-gate/SKILL.md +111 -0
  459. package/skills/keyword-research/SKILL.md +503 -0
  460. package/skills/keyword-research/references/dr-cap-and-confidence.md +62 -0
  461. package/skills/keyword-research/references/keyword-examples.md +769 -0
  462. package/skills/landing-page-architect/SKILL.md +585 -0
  463. package/skills/landing-page-architect/references/architecture-reference.md +32 -0
  464. package/skills/launch-strategy/SKILL.md +384 -0
  465. package/skills/launch-strategy/evals/evals.json +91 -0
  466. package/skills/launch-strategy/references/launch-checklist.md +209 -0
  467. package/skills/launch-strategy/references/launch-timeline.md +159 -0
  468. package/skills/lead-email-craft/SKILL.md +522 -0
  469. package/skills/lead-magnets/SKILL.md +310 -0
  470. package/skills/lead-magnets/references/benchmarks.md +129 -0
  471. package/skills/lead-magnets/references/format-guide.md +196 -0
  472. package/skills/link-building-seo/SKILL.md +210 -0
  473. package/skills/lint-report.txt +1 -0
  474. package/skills/manifest.json +129 -0
  475. package/skills/marketing-demo/SKILL.md +249 -0
  476. package/skills/marketing-demo/references/remotion-examples.md +281 -0
  477. package/skills/marketing-ideas/SKILL.md +167 -0
  478. package/skills/marketing-ideas/evals/evals.json +90 -0
  479. package/skills/marketing-ideas/references/ideas-by-category.md +366 -0
  480. package/skills/marketing-psychology/SKILL.md +374 -0
  481. package/skills/marketing-psychology/evals/evals.json +88 -0
  482. package/skills/marketing-psychology/references/case-studies.md +148 -0
  483. package/skills/narrative-research-article/SKILL.md +469 -0
  484. package/skills/narrative-research-article/references/lanusse-patterns.md +166 -0
  485. package/skills/notebooklm/SKILL.md +674 -0
  486. package/skills/off-page-seo/SKILL.md +219 -0
  487. package/skills/onboarding-cro/SKILL.md +220 -0
  488. package/skills/onboarding-cro/evals/evals.json +92 -0
  489. package/skills/onboarding-cro/references/experiments.md +258 -0
  490. package/skills/original-research/SKILL.md +388 -0
  491. package/skills/page-cro/SKILL.md +269 -0
  492. package/skills/page-cro/references/cro-benchmarks.md +140 -0
  493. package/skills/paper-marketing/SKILL.md +448 -0
  494. package/skills/paper-marketing/references/agent-quality-rubric.md +68 -0
  495. package/skills/paper-marketing/references/brand-system-template.md +120 -0
  496. package/skills/paper-marketing/references/paper-mcp-rules.md +71 -0
  497. package/skills/paper-marketing/references/platform-conventions.md +43 -0
  498. package/skills/paywall-upgrade-cro/SKILL.md +227 -0
  499. package/skills/paywall-upgrade-cro/evals/evals.json +93 -0
  500. package/skills/paywall-upgrade-cro/references/experiments.md +164 -0
  501. package/skills/platform-formatting/SKILL.md +51 -0
  502. package/skills/popup-cro/SKILL.md +454 -0
  503. package/skills/popup-cro/evals/evals.json +94 -0
  504. package/skills/positioning-angles/SKILL.md +524 -0
  505. package/skills/positioning-angles/references/ad-matrix-and-examples.md +176 -0
  506. package/skills/positioning-angles/references/angle-frameworks.md +187 -0
  507. package/skills/positioning-angles/references/dunford-positioning.md +135 -0
  508. package/skills/positioning-angles/references/hormozi-offer.md +247 -0
  509. package/skills/positioning-angles/references/schwartz-sophistication.md +166 -0
  510. package/skills/positioning-angles/references/unique-mechanism.md +162 -0
  511. package/skills/pricing-strategy/SKILL.md +346 -0
  512. package/skills/pricing-strategy/evals/evals.json +90 -0
  513. package/skills/pricing-strategy/references/research-methods.md +152 -0
  514. package/skills/pricing-strategy/references/tier-structure.md +307 -0
  515. package/skills/programmatic-seo/SKILL.md +238 -0
  516. package/skills/programmatic-seo/evals/evals.json +94 -0
  517. package/skills/programmatic-seo/references/playbooks.md +308 -0
  518. package/skills/project-rag/SKILL.md +127 -0
  519. package/skills/quality-gate/SKILL.md +519 -0
  520. package/skills/quality-gate/judge-personas/buyer.md +47 -0
  521. package/skills/quality-gate/judge-personas/expert.md +47 -0
  522. package/skills/quality-gate/judge-personas/outsider.md +47 -0
  523. package/skills/quality-gate/judge-personas/scanner.md +41 -0
  524. package/skills/quality-gate/judge-personas/skeptic.md +40 -0
  525. package/skills/referral-program/SKILL.md +290 -0
  526. package/skills/referral-program/evals/evals.json +89 -0
  527. package/skills/referral-program/references/affiliate-programs.md +163 -0
  528. package/skills/referral-program/references/program-examples.md +143 -0
  529. package/skills/review-sites/SKILL.md +279 -0
  530. package/skills/revops/SKILL.md +343 -0
  531. package/skills/revops/evals/evals.json +91 -0
  532. package/skills/revops/references/automation-playbooks.md +290 -0
  533. package/skills/revops/references/lifecycle-definitions.md +278 -0
  534. package/skills/revops/references/routing-rules.md +203 -0
  535. package/skills/revops/references/scoring-models.md +247 -0
  536. package/skills/saas-product-seo/SKILL.md +324 -0
  537. package/skills/sales-enablement/SKILL.md +349 -0
  538. package/skills/sales-enablement/evals/evals.json +91 -0
  539. package/skills/sales-enablement/references/deck-frameworks.md +263 -0
  540. package/skills/sales-enablement/references/demo-scripts.md +355 -0
  541. package/skills/sales-enablement/references/objection-library.md +270 -0
  542. package/skills/sales-enablement/references/one-pager-templates.md +208 -0
  543. package/skills/schema-markup/SKILL.md +179 -0
  544. package/skills/schema-markup/evals/evals.json +87 -0
  545. package/skills/schema-markup/references/schema-examples.md +398 -0
  546. package/skills/self-improve/SKILL.md +166 -0
  547. package/skills/self-improving-agent/README.md +243 -0
  548. package/skills/self-improving-agent/SKILL.md +437 -0
  549. package/skills/self-improving-agent/scripts/__init__.py +16 -0
  550. package/skills/self-improving-agent/scripts/__pycache__/auto_detect.cpython-314.pyc +0 -0
  551. package/skills/self-improving-agent/scripts/__pycache__/nlm_curation.cpython-314.pyc +0 -0
  552. package/skills/self-improving-agent/scripts/__pycache__/self_improving_agent.cpython-314.pyc +0 -0
  553. package/skills/self-improving-agent/scripts/auto_detect.py +270 -0
  554. package/skills/self-improving-agent/scripts/init_expertise_registry.py +89 -0
  555. package/skills/self-improving-agent/scripts/nlm_curation.py +259 -0
  556. package/skills/self-improving-agent/scripts/self-improving-agent +113 -0
  557. package/skills/self-improving-agent/scripts/self_improving_agent.py +603 -0
  558. package/skills/self-improving-agent/scripts/test_curation_scorer.py +20 -0
  559. package/skills/self-improving-agent/scripts/test_self_improving.py +184 -0
  560. package/skills/send-email/SKILL.md +426 -0
  561. package/skills/send-email/references/batch-email-examples.md +807 -0
  562. package/skills/send-email/references/best-practices.md +453 -0
  563. package/skills/send-email/references/installation.md +123 -0
  564. package/skills/send-email/references/single-email-examples.md +470 -0
  565. package/skills/send-email/references/webhooks.md +221 -0
  566. package/skills/seo-audit/SKILL.md +362 -0
  567. package/skills/seo-audit/references/ai-writing-detection.md +200 -0
  568. package/skills/seo-audit/references/architecture-patterns.md +271 -0
  569. package/skills/seo-audit/references/schema-templates.md +427 -0
  570. package/skills/seo-content/SKILL.md +510 -0
  571. package/skills/seo-content/references/anti-ai-detection.md +184 -0
  572. package/skills/seo-content/references/content-structures.md +148 -0
  573. package/skills/seo-content/references/eeat-examples.md +235 -0
  574. package/skills/seo-content/references/on-page-seo.md +261 -0
  575. package/skills/seo-content/references/pseo-playbooks.md +226 -0
  576. package/skills/seo-content/references/schema-templates.md +104 -0
  577. package/skills/seo-content/references/serp-analysis-format.md +151 -0
  578. package/skills/seo-machine/SKILL.md +331 -0
  579. package/skills/seo-machine/assets/brand-template.md +73 -0
  580. package/skills/seo-machine/assets/link-inventory-template.md +74 -0
  581. package/skills/seo-machine/assets/roadmap-template.md +184 -0
  582. package/skills/seo-machine/references/api-stack-recipes.md +230 -0
  583. package/skills/seo-machine/references/exa-recipes.md +260 -0
  584. package/skills/seo-machine/references/manual-research.md +73 -0
  585. package/skills/seo-machine/references/methodology.md +87 -0
  586. package/skills/seo-machine/references/off-page.md +123 -0
  587. package/skills/seo-machine/references/patterns/alternatives.md +176 -0
  588. package/skills/seo-machine/references/patterns/compare.md +105 -0
  589. package/skills/seo-machine/references/patterns/playbooks.md +106 -0
  590. package/skills/seo-machine/references/patterns/use-case.md +109 -0
  591. package/skills/seo-machine/references/quality-bars.md +99 -0
  592. package/skills/seo-machine/references/stacks/astro.md +156 -0
  593. package/skills/seo-machine/references/stacks/detection.md +61 -0
  594. package/skills/seo-machine/references/stacks/markdown-fallback.md +181 -0
  595. package/skills/seo-machine/references/stacks/nextjs.md +108 -0
  596. package/skills/seo-machine/references/stacks/rails-inertia.md +99 -0
  597. package/skills/seo-machine/references/striking-distance.md +116 -0
  598. package/skills/seo-machine/references/technical-audit.md +153 -0
  599. package/skills/seo-machine/scripts/link_audit.py +265 -0
  600. package/skills/seo-machine/scripts/tech_audit.py +221 -0
  601. package/skills/seo-machine/scripts/word_count.py +154 -0
  602. package/skills/sharp-thesis-validator/SKILL.md +393 -0
  603. package/skills/sharp-thesis-validator/examples.md +186 -0
  604. package/skills/signup-flow-cro/SKILL.md +359 -0
  605. package/skills/signup-flow-cro/evals/evals.json +88 -0
  606. package/skills/site-architecture/SKILL.md +357 -0
  607. package/skills/site-architecture/evals/evals.json +88 -0
  608. package/skills/site-architecture/references/mermaid-templates.md +216 -0
  609. package/skills/site-architecture/references/navigation-patterns.md +305 -0
  610. package/skills/site-architecture/references/site-type-templates.md +293 -0
  611. package/skills/skill-self-improvement/SKILL.md +151 -0
  612. package/skills/slideshow-script/SKILL.md +274 -0
  613. package/skills/slideshow-script/references/content-spec-schema.md +77 -0
  614. package/skills/slideshow-script/references/frameworks.md +84 -0
  615. package/skills/slideshow-script/references/paips-framework.md +37 -0
  616. package/skills/social-campaign/SKILL.md +419 -0
  617. package/skills/social-campaign/references/paper-mcp-workflow.md +48 -0
  618. package/skills/social-content/SKILL.md +359 -0
  619. package/skills/social-content/evals/evals.json +92 -0
  620. package/skills/social-content/references/platforms.md +170 -0
  621. package/skills/social-content/references/post-templates.md +177 -0
  622. package/skills/social-content/references/reverse-engineering.md +195 -0
  623. package/skills/social-worker/SKILL.md +204 -0
  624. package/skills/startup-launcher/SKILL.md +252 -0
  625. package/skills/startup-launcher/references/file-router.md +64 -0
  626. package/skills/startup-launcher/references/platform-matrix.md +65 -0
  627. package/skills/startup-launcher/references/platforms/alternativeto.md +283 -0
  628. package/skills/startup-launcher/references/platforms/appsumo.md +495 -0
  629. package/skills/startup-launcher/references/platforms/auraplusplus.md +736 -0
  630. package/skills/startup-launcher/references/platforms/betalist.md +98 -0
  631. package/skills/startup-launcher/references/platforms/capterra.md +276 -0
  632. package/skills/startup-launcher/references/platforms/crunchbase.md +514 -0
  633. package/skills/startup-launcher/references/platforms/dealify.md +291 -0
  634. package/skills/startup-launcher/references/platforms/dealmirror.md +313 -0
  635. package/skills/startup-launcher/references/platforms/desifounder.md +490 -0
  636. package/skills/startup-launcher/references/platforms/devhunt.md +210 -0
  637. package/skills/startup-launcher/references/platforms/devpost.md +448 -0
  638. package/skills/startup-launcher/references/platforms/fazier.md +56 -0
  639. package/skills/startup-launcher/references/platforms/firsto.md +489 -0
  640. package/skills/startup-launcher/references/platforms/g2.md +226 -0
  641. package/skills/startup-launcher/references/platforms/hackernews.md +99 -0
  642. package/skills/startup-launcher/references/platforms/hackernoon.md +385 -0
  643. package/skills/startup-launcher/references/platforms/indiedeals.md +367 -0
  644. package/skills/startup-launcher/references/platforms/indiehackers.md +80 -0
  645. package/skills/startup-launcher/references/platforms/kenmoo.md +231 -0
  646. package/skills/startup-launcher/references/platforms/labstartups.md +618 -0
  647. package/skills/startup-launcher/references/platforms/launchboard.md +307 -0
  648. package/skills/startup-launcher/references/platforms/launchfast.md +560 -0
  649. package/skills/startup-launcher/references/platforms/launchigniter.md +56 -0
  650. package/skills/startup-launcher/references/platforms/launchingnext.md +674 -0
  651. package/skills/startup-launcher/references/platforms/launchit.md +574 -0
  652. package/skills/startup-launcher/references/platforms/launchyourapp.md +677 -0
  653. package/skills/startup-launcher/references/platforms/libhunt.md +220 -0
  654. package/skills/startup-launcher/references/platforms/ltdhunt.md +221 -0
  655. package/skills/startup-launcher/references/platforms/microlaunch.md +45 -0
  656. package/skills/startup-launcher/references/platforms/openalternative.md +195 -0
  657. package/skills/startup-launcher/references/platforms/peerlist.md +56 -0
  658. package/skills/startup-launcher/references/platforms/peerpush.md +64 -0
  659. package/skills/startup-launcher/references/platforms/primeclub.md +282 -0
  660. package/skills/startup-launcher/references/platforms/productcanyon.md +190 -0
  661. package/skills/startup-launcher/references/platforms/producthunt.md +98 -0
  662. package/skills/startup-launcher/references/platforms/rankinpublic.md +315 -0
  663. package/skills/startup-launcher/references/platforms/rockethub.md +374 -0
  664. package/skills/startup-launcher/references/platforms/saasgenius.md +175 -0
  665. package/skills/startup-launcher/references/platforms/saashub.md +205 -0
  666. package/skills/startup-launcher/references/platforms/saasmantra.md +221 -0
  667. package/skills/startup-launcher/references/platforms/saaspirate.md +287 -0
  668. package/skills/startup-launcher/references/platforms/saaswarrior.md +190 -0
  669. package/skills/startup-launcher/references/platforms/saaszilla.md +194 -0
  670. package/skills/startup-launcher/references/platforms/selected.md +925 -0
  671. package/skills/startup-launcher/references/platforms/sideprojectors.md +86 -0
  672. package/skills/startup-launcher/references/platforms/softonic.md +240 -0
  673. package/skills/startup-launcher/references/platforms/sourceforge.md +251 -0
  674. package/skills/startup-launcher/references/platforms/stacksocial.md +244 -0
  675. package/skills/startup-launcher/references/platforms/startupstash.md +326 -0
  676. package/skills/startup-launcher/references/platforms/theresanaiforthat.md +253 -0
  677. package/skills/startup-launcher/references/platforms/tinylaunch.md +70 -0
  678. package/skills/startup-launcher/references/platforms/tinystartups.md +72 -0
  679. package/skills/startup-launcher/references/platforms/toolfolio.md +291 -0
  680. package/skills/startup-launcher/references/platforms/trustmrr.md +194 -0
  681. package/skills/startup-launcher/references/platforms/trylaunch.md +531 -0
  682. package/skills/startup-launcher/references/platforms/uneed.md +57 -0
  683. package/skills/startup-launcher/references/templates/asset-checklist.md +218 -0
  684. package/skills/startup-launcher/references/templates/launch-tracker.md +195 -0
  685. package/skills/startup-launcher/references/templates/product-brief.md +98 -0
  686. package/skills/summarize/.skill-meta.json +13 -0
  687. package/skills/summarize/SKILL.md +170 -0
  688. package/skills/summarize/rules/install.md +157 -0
  689. package/skills/summarize/rules/usage.md +207 -0
  690. package/skills/topical-authority/SKILL.md +307 -0
  691. package/skills/topical-authority/references/jake-ward-framework.md +201 -0
  692. package/skills/topical-authority/references/serp-clustering-algorithm.md +325 -0
  693. package/skills/topical-authority/scripts/orchestrator.js +367 -0
  694. package/skills/topical-authority/scripts/seo/analyze-competitor-coverage.js +3 -0
  695. package/skills/topical-authority/scripts/seo/audit-internal-links.js +3 -0
  696. package/skills/topical-authority/scripts/seo/build-clusters-from-serp.js +3 -0
  697. package/skills/topical-authority/scripts/seo/extract-keywords-from-forums.js +3 -0
  698. package/skills/topical-authority/scripts/seo/extract-paa-questions.js +3 -0
  699. package/skills/topical-authority/scripts/seo/fetch-serp-urls.js +3 -0
  700. package/skills/topical-authority/scripts/seo/gemini-serp-clustering.js +3 -0
  701. package/skills/topical-authority/scripts/seo/identify-content-gaps.js +3 -0
  702. package/skills/topical-authority/scripts/seo/identify-research-gaps.js +3 -0
  703. package/skills/topical-authority/scripts/seo/scrape-quora-questions.js +3 -0
  704. package/skills/topical-authority/scripts/seo/scrape-reddit-pain-points.js +3 -0
  705. package/skills/topical-authority/scripts/seo/weave-internal-links.js +3 -0
  706. package/skills/visual-style/SKILL.md +199 -0
  707. package/skills/voice-brand-alignment/SKILL.md +70 -0
  708. package/skills/voice-brand-alignment/references/ai-slop-patterns.md +405 -0
  709. package/skills/voice-brand-alignment/scripts/validation/gemini-voice-validator.js +96 -0
  710. package/skills/voice-extraction/SKILL.md +234 -0
  711. package/skills/voice-extraction/references/extraction-prompt.md +155 -0
  712. package/skills/voice-extraction/references/voice-dna-template.md +168 -0
  713. package/skills/voice-extraction/references/voice-elements.md +259 -0
  714. package/skills/voice-extraction/scripts/build-corpus.js +120 -0
  715. package/skills/voice-extraction/scripts/collect-sources.sh +168 -0
  716. package/skills/warm-outbound/SKILL.md +299 -0
  717. package/skills/warm-outbound/templates/warm-message.md +39 -0
  718. package/skills/weekly-newsletter-digest/SKILL.md +78 -0
  719. package/skills/x-playwriter/SKILL.md +428 -0
  720. package/skills/x-playwriter/scripts/x-browser.js +185 -0
  721. package/skills/x-post-generator-openclaw/SKILL.md +138 -0
  722. package/skills/x-post-generator-openclaw/scripts/generate-x-post.js +537 -0
  723. package/skills/x-posting-playwriter/SKILL.md +203 -0
  724. package/skills/x-research/SKILL.md +129 -0
  725. package/skills/x-research/x-research.sh +85 -0
  726. package/skills/youtube-summarize/SKILL.md +90 -0
  727. package/skills/youtube-summarize/scripts/youtube-summarize.sh +143 -0
  728. package/src/cli.js +349 -172
  729. package/src/harness/deepseek-adapter.js +102 -0
  730. package/src/harness/deepseek.js +225 -0
  731. package/src/harness/opencode-adapter.js +174 -0
  732. package/src/harness/pi-adapter.js +172 -0
  733. package/src/harness/registry.js +121 -0
  734. package/src/harness/telemetry.js +102 -0
  735. package/src/harness/types.js +165 -0
  736. package/src/interview.js +36 -4
  737. package/src/postinstall.js +10 -12
  738. package/templates/AGENTS.md +17 -17
  739. package/templates/ORG.md +1 -1
  740. package/templates/TOOLS.md +7 -2
  741. package/templates/opencode.json +26 -29
  742. package/wiki/doctor.md +54 -0
  743. package/wiki/inkstone.md +4 -4
  744. package/wiki/opencode.md +3 -3
  745. package/skills/curated.txt +0 -68
@@ -0,0 +1,939 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { getLiveDir } from '../lib/impeccable-paths.mjs';
5
+ import { readBuffer as readManualEditsBuffer } from './manual-edits-buffer.mjs';
6
+
7
+ const APPLY_EVENT_HARD_TIMEOUT_MS = Number(process.env.IMPECCABLE_LIVE_APPLY_EVENT_HARD_TIMEOUT_MS || 150_000);
8
+ const APPLY_EVENT_SOFT_DEADLINE_MS = Number(process.env.IMPECCABLE_LIVE_APPLY_EVENT_SOFT_DEADLINE_MS || 120_000);
9
+ const DEFAULT_MANUAL_EDIT_APPLY_CHUNK_SIZE = 3;
10
+ const MIN_MANUAL_EDIT_APPLY_CHUNK_SIZE = 1;
11
+ const MAX_MANUAL_EDIT_APPLY_CHUNK_SIZE = 20;
12
+ const MANUAL_APPLY_COMPACT_TEXT_LIMIT = 240;
13
+ const MANUAL_APPLY_COMPACT_NEARBY_LIMIT = 4;
14
+
15
+ export function createManualApplyController({
16
+ pendingEvents,
17
+ pendingApplyDeferreds,
18
+ timedOutApplyIds,
19
+ enqueueEvent,
20
+ acknowledgePendingEvent,
21
+ flushPendingPolls,
22
+ recordManualEditActivity,
23
+ cwd = () => process.cwd(),
24
+ } = {}) {
25
+ const projectCwd = () => typeof cwd === 'function' ? cwd() : cwd || process.cwd();
26
+
27
+ function tombstoneTimedOutApplyId(eventId, details = {}) {
28
+ if (!eventId) return;
29
+ timedOutApplyIds.set(eventId, details);
30
+ if (timedOutApplyIds.size <= 200) return;
31
+ const oldest = timedOutApplyIds.keys().next().value;
32
+ timedOutApplyIds.delete(oldest);
33
+ }
34
+
35
+ function pushApplyEventAndWait(batch, pageUrl, chunk = null, repair = null) {
36
+ const cwdValue = projectCwd();
37
+ const eventId = randomUUID().replace(/-/g, '').slice(0, 8);
38
+ const evidencePath = writeManualApplyEvidence(eventId, batch, cwdValue);
39
+ const event = {
40
+ type: 'manual_edit_apply',
41
+ id: eventId,
42
+ pageUrl,
43
+ batch: compactManualApplyBatch(batch, cwdValue),
44
+ evidencePath,
45
+ agentAction: buildManualApplyAgentAction(eventId),
46
+ schemaVersion: 1,
47
+ deadlineMs: APPLY_EVENT_SOFT_DEADLINE_MS,
48
+ };
49
+ if (chunk) event.chunk = chunk;
50
+ if (repair) event.repair = repair;
51
+ const rollbackSnapshot = snapshotApplyEventFiles(batch, cwdValue);
52
+ recordManualEditActivity('manual_edit_apply_dispatched', {
53
+ id: eventId,
54
+ pageUrl,
55
+ chunk,
56
+ repair,
57
+ entryCount: Array.isArray(batch.entries) ? batch.entries.length : 0,
58
+ opCount: countManualApplyOps(batch),
59
+ fileCount: collectManualApplyFiles(batch, [], cwdValue).length,
60
+ });
61
+ return new Promise((resolve, reject) => {
62
+ const timer = setTimeout(() => {
63
+ pendingApplyDeferreds.delete(eventId);
64
+ tombstoneTimedOutApplyId(eventId, { batch, rollbackSnapshot, cwd: cwdValue });
65
+ acknowledgePendingEvent(eventId);
66
+ removeManualApplyEvidence(evidencePath, cwdValue);
67
+ recordManualEditActivity('manual_edit_apply_timeout', {
68
+ id: eventId,
69
+ pageUrl,
70
+ chunk,
71
+ entryCount: Array.isArray(batch.entries) ? batch.entries.length : 0,
72
+ opCount: countManualApplyOps(batch),
73
+ });
74
+ reject(new Error('chat_agent_timeout'));
75
+ }, APPLY_EVENT_HARD_TIMEOUT_MS);
76
+ pendingApplyDeferreds.set(eventId, { resolve, reject, timer, event, batch, pageUrl, rollbackSnapshot, cwd: cwdValue });
77
+ enqueueEvent(event);
78
+ });
79
+ }
80
+
81
+ async function pushBatchInChunksAndWait(batch, pageUrl, context = {}) {
82
+ const repair = context?.repair || batch?.repair || null;
83
+ if (repair) return pushApplyEventAndWait(batch, pageUrl, null, repair);
84
+ const chunks = splitManualApplyBatch(batch, manualEditApplyChunkSize());
85
+ if (chunks.length <= 1) return pushApplyEventAndWait(batch, pageUrl);
86
+
87
+ const expectedOpsByEntry = new Map();
88
+ for (const entry of batch?.entries || []) {
89
+ expectedOpsByEntry.set(entry.id, Array.isArray(entry.ops) ? entry.ops.length : 0);
90
+ }
91
+
92
+ const appliedOpsByEntry = new Map();
93
+ const failedByEntry = new Map();
94
+ const files = new Set();
95
+ const notes = [];
96
+ let aborted = false;
97
+
98
+ for (const chunk of chunks) {
99
+ if (aborted) {
100
+ markChunkEntriesFailed(failedByEntry, chunk, 'manual_edit_chunk_aborted');
101
+ continue;
102
+ }
103
+
104
+ let result;
105
+ try {
106
+ result = normalizeApplyChunkResult(await pushApplyEventAndWait(chunk.batch, pageUrl, chunk.meta));
107
+ } catch (err) {
108
+ markChunkEntriesFailed(failedByEntry, chunk, err.message || 'chat_agent_error');
109
+ aborted = true;
110
+ continue;
111
+ }
112
+
113
+ for (const file of result.files) files.add(file);
114
+ notes.push(...result.notes);
115
+
116
+ const chunkFailedIds = new Set();
117
+ for (const item of result.failed) {
118
+ const entryId = item.entryId || item.id;
119
+ if (!entryId) continue;
120
+ chunkFailedIds.add(entryId);
121
+ if (!failedByEntry.has(entryId)) {
122
+ failedByEntry.set(entryId, {
123
+ entryId,
124
+ reason: item.reason || item.message || 'failed',
125
+ candidates: Array.isArray(item.candidates) ? item.candidates : [],
126
+ });
127
+ }
128
+ }
129
+
130
+ if (result.status === 'error') {
131
+ markChunkEntriesFailed(failedByEntry, chunk, result.message || firstFailureReason(result) || 'chat_agent_error');
132
+ aborted = true;
133
+ continue;
134
+ }
135
+
136
+ const reportedAppliedIds = new Set(result.appliedEntryIds);
137
+ for (const entryId of reportedAppliedIds) {
138
+ if (!chunk.entryIds.has(entryId) || chunkFailedIds.has(entryId)) continue;
139
+ appliedOpsByEntry.set(entryId, (appliedOpsByEntry.get(entryId) || 0) + (chunk.opCountsByEntry.get(entryId) || 0));
140
+ }
141
+
142
+ for (const entryId of chunk.entryIds) {
143
+ if (reportedAppliedIds.has(entryId) || chunkFailedIds.has(entryId)) continue;
144
+ if (!failedByEntry.has(entryId)) {
145
+ failedByEntry.set(entryId, { entryId, reason: 'not_reported_applied', candidates: [] });
146
+ }
147
+ }
148
+ }
149
+
150
+ const appliedEntryIds = [];
151
+ for (const [entryId, expectedOps] of expectedOpsByEntry.entries()) {
152
+ if (failedByEntry.has(entryId)) continue;
153
+ if ((appliedOpsByEntry.get(entryId) || 0) === expectedOps && expectedOps > 0) {
154
+ appliedEntryIds.push(entryId);
155
+ } else if (!failedByEntry.has(entryId)) {
156
+ failedByEntry.set(entryId, { entryId, reason: 'not_reported_applied', candidates: [] });
157
+ }
158
+ }
159
+
160
+ const failed = [...failedByEntry.values()];
161
+ return {
162
+ status: failed.length === 0 ? 'done' : appliedEntryIds.length > 0 ? 'partial' : 'error',
163
+ appliedEntryIds,
164
+ failed,
165
+ files: [...files],
166
+ notes,
167
+ };
168
+ }
169
+
170
+ function getDeferred(eventId) {
171
+ return pendingApplyDeferreds.get(eventId) || null;
172
+ }
173
+
174
+ function hasTimedOutId(eventId) {
175
+ return timedOutApplyIds.has(eventId);
176
+ }
177
+
178
+ function resolveDeferred(eventId, body) {
179
+ const deferred = pendingApplyDeferreds.get(eventId);
180
+ if (!deferred) return false;
181
+ pendingApplyDeferreds.delete(eventId);
182
+ clearTimeout(deferred.timer);
183
+ removeManualApplyEvidence(deferred.event?.evidencePath, deferred.cwd || projectCwd());
184
+ deferred.resolve(body);
185
+ return true;
186
+ }
187
+
188
+ function rejectDeferred(eventId, reason) {
189
+ const deferred = pendingApplyDeferreds.get(eventId);
190
+ if (!deferred) return false;
191
+ pendingApplyDeferreds.delete(eventId);
192
+ clearTimeout(deferred.timer);
193
+ removeManualApplyEvidence(deferred.event?.evidencePath, deferred.cwd || projectCwd());
194
+ deferred.reject(new Error(reason || 'chat_agent_error'));
195
+ return true;
196
+ }
197
+
198
+ function referencedManualApplyEvidencePaths(cwdValue = projectCwd()) {
199
+ const referenced = new Set();
200
+ const add = (event) => {
201
+ const fullPath = normalizeManualApplyEvidencePath(event?.evidencePath, cwdValue);
202
+ if (fullPath) referenced.add(fullPath);
203
+ };
204
+ for (const entry of pendingEvents) add(entry.event);
205
+ for (const deferred of pendingApplyDeferreds.values()) add(deferred.event);
206
+ return referenced;
207
+ }
208
+
209
+ function pruneStaleEvidence(cwdValue = projectCwd()) {
210
+ const dir = manualApplyEvidenceDir(cwdValue);
211
+ if (!fs.existsSync(dir)) return [];
212
+ const referenced = referencedManualApplyEvidencePaths(cwdValue);
213
+ const removed = [];
214
+ for (const name of fs.readdirSync(dir)) {
215
+ if (!name.endsWith('.json')) continue;
216
+ const fullPath = path.join(dir, name);
217
+ if (referenced.has(fullPath)) continue;
218
+ try {
219
+ fs.unlinkSync(fullPath);
220
+ removed.push(fullPath);
221
+ } catch {
222
+ // Stale evidence cleanup is best-effort; Apply verification never relies
223
+ // on deleting these files.
224
+ }
225
+ }
226
+ return removed;
227
+ }
228
+
229
+ function rollbackTimedOutReply(msg) {
230
+ const details = timedOutApplyIds.get(msg.id);
231
+ if (!details) return { rolledBackFiles: [], rollbackFailures: [] };
232
+ timedOutApplyIds.delete(msg.id);
233
+ return rollbackApplySnapshot(
234
+ details.batch,
235
+ details.rollbackSnapshot,
236
+ msg.data?.files || [],
237
+ 'stale_manual_edit_apply_reply',
238
+ details.cwd || projectCwd(),
239
+ );
240
+ }
241
+
242
+ function cancelPendingEvents(pageUrl, reason = 'manual_edit_discarded') {
243
+ const canceledById = new Map();
244
+ const shouldCancel = (event) => event?.type === 'manual_edit_apply' && (!pageUrl || event.pageUrl === pageUrl);
245
+
246
+ for (let i = pendingEvents.length - 1; i >= 0; i -= 1) {
247
+ const event = pendingEvents[i]?.event;
248
+ if (!shouldCancel(event)) continue;
249
+ pendingEvents.splice(i, 1);
250
+ removeManualApplyEvidence(event.evidencePath, projectCwd());
251
+ canceledById.set(event.id, {
252
+ id: event.id,
253
+ pageUrl: event.pageUrl,
254
+ entryCount: event.batch?.entries?.length || 0,
255
+ });
256
+ }
257
+
258
+ for (const [eventId, deferred] of [...pendingApplyDeferreds.entries()]) {
259
+ if (!shouldCancel(deferred.event)) continue;
260
+ pendingApplyDeferreds.delete(eventId);
261
+ clearTimeout(deferred.timer);
262
+ const cwdValue = deferred.cwd || projectCwd();
263
+ const rollback = rollbackApplySnapshot(deferred.batch, deferred.rollbackSnapshot, [], reason, cwdValue);
264
+ tombstoneTimedOutApplyId(eventId, {
265
+ batch: deferred.batch,
266
+ rollbackSnapshot: deferred.rollbackSnapshot,
267
+ reason,
268
+ cwd: cwdValue,
269
+ });
270
+ removeManualApplyEvidence(deferred.event?.evidencePath, cwdValue);
271
+ canceledById.set(eventId, {
272
+ id: eventId,
273
+ pageUrl: deferred.pageUrl,
274
+ entryCount: deferred.batch?.entries?.length || 0,
275
+ rolledBackFiles: rollback.rolledBackFiles,
276
+ rollbackFailures: rollback.rollbackFailures,
277
+ });
278
+ deferred.reject(new Error(reason));
279
+ }
280
+
281
+ if (canceledById.size > 0) flushPendingPolls();
282
+ return [...canceledById.values()];
283
+ }
284
+
285
+ return {
286
+ buildAgentAction: buildManualApplyAgentAction,
287
+ cancelPendingEvents,
288
+ clearTransaction: (transactionId = null) => clearManualApplyTransaction(projectCwd(), transactionId),
289
+ countOps: countManualApplyOps,
290
+ getDeferred,
291
+ hasTimedOutId,
292
+ pruneStaleEvidence,
293
+ pushBatchInChunksAndWait,
294
+ readTransaction: () => readManualApplyTransaction(projectCwd()),
295
+ rejectDeferred,
296
+ resolveDeferred,
297
+ rollbackTimedOutReply,
298
+ rollbackTransaction: (opts = {}) => rollbackManualApplyTransaction({
299
+ cwd: projectCwd(),
300
+ recordManualEditActivity,
301
+ ...opts,
302
+ }),
303
+ summarizeEvent: (event = {}, batch = event.batch) => summarizeManualApplyEvent(event, batch, projectCwd()),
304
+ validateResultMessage: validateManualApplyResultMessage,
305
+ writeTransaction: (opts = {}) => writeManualApplyTransaction({ cwd: projectCwd(), ...opts }),
306
+ };
307
+ }
308
+
309
+ export function manualEditApplyChunkSize(env = process.env) {
310
+ const raw = Number(env.IMPECCABLE_LIVE_MANUAL_EDIT_CHUNK_SIZE);
311
+ if (!Number.isFinite(raw)) return DEFAULT_MANUAL_EDIT_APPLY_CHUNK_SIZE;
312
+ const size = Math.trunc(raw);
313
+ return Math.max(MIN_MANUAL_EDIT_APPLY_CHUNK_SIZE, Math.min(MAX_MANUAL_EDIT_APPLY_CHUNK_SIZE, size));
314
+ }
315
+
316
+ export function countManualApplyOps(entriesOrBatch) {
317
+ const entries = Array.isArray(entriesOrBatch)
318
+ ? entriesOrBatch
319
+ : Array.isArray(entriesOrBatch?.entries) ? entriesOrBatch.entries : [];
320
+ let count = 0;
321
+ for (const entry of entries) count += Array.isArray(entry.ops) ? entry.ops.length : 0;
322
+ return count;
323
+ }
324
+
325
+ export function writeManualApplyEvidence(eventId, batch, cwd = process.cwd()) {
326
+ const dir = manualApplyEvidenceDir(cwd);
327
+ fs.mkdirSync(dir, { recursive: true });
328
+ const evidencePath = path.join(dir, `${eventId}.json`);
329
+ fs.writeFileSync(evidencePath, JSON.stringify(batch, null, 2) + '\n', 'utf-8');
330
+ return evidencePath;
331
+ }
332
+
333
+ export function manualApplyEvidenceDir(cwd = process.cwd()) {
334
+ return path.join(getLiveDir(cwd), 'manual-edit-evidence');
335
+ }
336
+
337
+ export function normalizeManualApplyEvidencePath(evidencePath, cwd = process.cwd()) {
338
+ if (!evidencePath || typeof evidencePath !== 'string') return null;
339
+ const fullPath = path.isAbsolute(evidencePath) ? evidencePath : path.resolve(cwd, evidencePath);
340
+ const evidenceDir = manualApplyEvidenceDir(cwd);
341
+ const relative = path.relative(evidenceDir, fullPath);
342
+ if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) return null;
343
+ if (path.extname(relative) !== '.json') return null;
344
+ return fullPath;
345
+ }
346
+
347
+ export function removeManualApplyEvidence(evidencePath, cwd = process.cwd()) {
348
+ const fullPath = normalizeManualApplyEvidencePath(evidencePath, cwd);
349
+ if (!fullPath) return false;
350
+ try {
351
+ fs.unlinkSync(fullPath);
352
+ return true;
353
+ } catch {
354
+ return false;
355
+ }
356
+ }
357
+
358
+ export function compactManualApplyBatch(batch = {}, cwd = process.cwd()) {
359
+ const entries = (batch.entries || []).map(compactManualApplyEntry);
360
+ const candidates = compactManualApplyCandidates(batch.candidates || [], cwd);
361
+ return {
362
+ version: batch.version,
363
+ pageUrl: batch.pageUrl || null,
364
+ count: batch.count,
365
+ entries,
366
+ ops: entries.flatMap((entry) => entry.ops.map((op) => ({ ...op, entryId: entry.id }))),
367
+ candidates: candidates.length > 0 ? candidates : undefined,
368
+ context: batch.context ? {
369
+ bufferPath: batch.context.bufferPath,
370
+ totalEntries: batch.context.totalEntries,
371
+ totalOps: batch.context.totalOps,
372
+ chunkIndex: batch.context.chunkIndex,
373
+ chunkTotal: batch.context.chunkTotal,
374
+ totalApplyOps: batch.context.totalApplyOps,
375
+ } : undefined,
376
+ };
377
+ }
378
+
379
+ export function compactManualApplyCandidates(candidates, cwd = process.cwd()) {
380
+ return (Array.isArray(candidates) ? candidates : [])
381
+ .slice(0, 24)
382
+ .map((candidate) => ({
383
+ entryId: candidate.entryId,
384
+ ref: candidate.ref,
385
+ sourceHint: compactManualApplySourceMatch(candidate.sourceHint, cwd),
386
+ textMatches: compactManualApplySourceMatches(candidate.textMatches, 8, cwd),
387
+ objectKeyMatches: compactManualApplySourceMatches(candidate.objectKeyMatches, 8, cwd),
388
+ contextTextMatches: compactManualApplySourceMatches(candidate.contextTextMatches, 8, cwd),
389
+ locatorMatches: compactManualApplySourceMatches(candidate.locatorMatches, 6, cwd),
390
+ }));
391
+ }
392
+
393
+ function compactManualApplySourceMatches(matches, limit, cwd) {
394
+ return (Array.isArray(matches) ? matches : [])
395
+ .slice(0, limit)
396
+ .map((match) => compactManualApplySourceMatch(match, cwd))
397
+ .filter(Boolean);
398
+ }
399
+
400
+ function compactManualApplySourceMatch(match, cwd) {
401
+ if (!match || typeof match !== 'object') return null;
402
+ const file = match.relativeFile || match.file;
403
+ if (!file && !match.line) return null;
404
+ return {
405
+ file: summarizeManualLogFile(file, cwd),
406
+ line: match.line || null,
407
+ column: match.column || null,
408
+ reason: match.reason || match.kind || undefined,
409
+ status: match.status || undefined,
410
+ };
411
+ }
412
+
413
+ function compactManualApplyEntry(entry = {}) {
414
+ return {
415
+ id: entry.id,
416
+ pageUrl: entry.pageUrl,
417
+ stagedAt: entry.stagedAt || null,
418
+ element: compactManualApplyContext(entry.element),
419
+ ops: (entry.ops || []).map(compactManualApplyOp),
420
+ };
421
+ }
422
+
423
+ function compactManualApplyOp(op = {}) {
424
+ return {
425
+ entryId: op.entryId,
426
+ ref: op.ref,
427
+ contextRef: op.contextRef,
428
+ tag: op.tag,
429
+ elementId: op.elementId,
430
+ classes: Array.isArray(op.classes) ? op.classes : [],
431
+ originalText: op.originalText,
432
+ newText: op.newText,
433
+ deleted: op.deleted === true || undefined,
434
+ sourceHint: op.sourceHint || null,
435
+ leaf: compactManualApplyContext(op.leaf),
436
+ nearbyEditableTexts: compactNearbyManualEditTexts(op.nearbyEditableTexts),
437
+ container: compactManualApplyContext(op.container),
438
+ contextHints: Array.isArray(op.contextHints) ? op.contextHints.slice(0, 8) : undefined,
439
+ };
440
+ }
441
+
442
+ function compactManualApplyContext(value) {
443
+ if (!value || typeof value !== 'object') return null;
444
+ return {
445
+ ref: value.ref,
446
+ tagName: value.tagName || value.tag || null,
447
+ id: value.id || null,
448
+ classes: Array.isArray(value.classes) ? value.classes : [],
449
+ textContent: truncateManualApplyText(value.textContent, MANUAL_APPLY_COMPACT_TEXT_LIMIT),
450
+ };
451
+ }
452
+
453
+ function compactNearbyManualEditTexts(items) {
454
+ return (Array.isArray(items) ? items : [])
455
+ .slice(0, MANUAL_APPLY_COMPACT_NEARBY_LIMIT)
456
+ .map((item) => typeof item === 'string' ? { text: truncateManualApplyText(item, MANUAL_APPLY_COMPACT_TEXT_LIMIT) } : {
457
+ ref: item?.ref,
458
+ tag: item?.tag,
459
+ classes: Array.isArray(item?.classes) ? item.classes : [],
460
+ text: truncateManualApplyText(item?.text, MANUAL_APPLY_COMPACT_TEXT_LIMIT),
461
+ });
462
+ }
463
+
464
+ function truncateManualApplyText(value, max) {
465
+ if (typeof value !== 'string') return value || null;
466
+ return value.length > max ? value.slice(0, max) : value;
467
+ }
468
+
469
+ function normalizeApplyChunkResult(result) {
470
+ const status = result?.status === 'partial' ? 'partial' : result?.status === 'error' ? 'error' : 'done';
471
+ return {
472
+ status,
473
+ message: typeof result?.message === 'string' ? result.message : null,
474
+ appliedEntryIds: Array.isArray(result?.appliedEntryIds) ? result.appliedEntryIds.filter((id) => typeof id === 'string') : [],
475
+ failed: Array.isArray(result?.failed) ? result.failed.filter(Boolean) : [],
476
+ files: Array.isArray(result?.files) ? result.files.filter((file) => typeof file === 'string') : [],
477
+ notes: Array.isArray(result?.notes) ? result.notes.filter((note) => typeof note === 'string') : [],
478
+ };
479
+ }
480
+
481
+ function manualApplyResultShapeHint(eventId = 'EVENT_ID') {
482
+ return `Use live-poll.mjs --reply ${eventId} done --data '{"status":"done","appliedEntryIds":["ENTRY_ID"],"failed":[],"files":["src/page.html"],"notes":[]}'`;
483
+ }
484
+
485
+ function invalidManualApplyResult(reason, eventId, extra = {}) {
486
+ return {
487
+ ok: false,
488
+ body: {
489
+ error: 'invalid_manual_apply_result',
490
+ reason,
491
+ hint: manualApplyResultShapeHint(eventId),
492
+ ...extra,
493
+ },
494
+ };
495
+ }
496
+
497
+ export function validateManualApplyResultMessage(msg, deferred) {
498
+ let data = msg?.data;
499
+ const eventId = msg?.id || deferred?.event?.id || 'EVENT_ID';
500
+ if (!data || typeof data !== 'object' || Array.isArray(data)) {
501
+ return invalidManualApplyResult('missing_result_data', eventId);
502
+ }
503
+ if ('entries' in data || 'ops' in data) {
504
+ return invalidManualApplyResult('summary_result_not_allowed', eventId);
505
+ }
506
+ if (!['done', 'partial', 'error'].includes(data.status)) {
507
+ return invalidManualApplyResult('invalid_status', eventId, { status: data.status ?? null });
508
+ }
509
+
510
+ for (const key of ['appliedEntryIds', 'failed', 'files', 'notes']) {
511
+ if (!Array.isArray(data[key])) {
512
+ return invalidManualApplyResult(`${key}_must_be_array`, eventId);
513
+ }
514
+ }
515
+
516
+ for (const [index, value] of data.appliedEntryIds.entries()) {
517
+ if (typeof value !== 'string' || !value) {
518
+ return invalidManualApplyResult('appliedEntryIds_must_contain_strings', eventId, { index });
519
+ }
520
+ }
521
+ for (const [index, value] of data.files.entries()) {
522
+ if (typeof value !== 'string' || !value) {
523
+ return invalidManualApplyResult('files_must_contain_strings', eventId, { index });
524
+ }
525
+ }
526
+ for (const [index, value] of data.notes.entries()) {
527
+ if (typeof value !== 'string') {
528
+ return invalidManualApplyResult('notes_must_contain_strings', eventId, { index });
529
+ }
530
+ }
531
+ for (const [index, item] of data.failed.entries()) {
532
+ if (!item || typeof item !== 'object' || Array.isArray(item)) {
533
+ return invalidManualApplyResult('failed_must_contain_objects', eventId, { index });
534
+ }
535
+ if (typeof item.entryId !== 'string' || !item.entryId) {
536
+ return invalidManualApplyResult('failed_entryId_required', eventId, { index });
537
+ }
538
+ if (typeof item.reason !== 'string' || !item.reason) {
539
+ return invalidManualApplyResult('failed_reason_required', eventId, { index });
540
+ }
541
+ }
542
+
543
+ const eventEntryIds = new Set((deferred?.batch?.entries || []).map((entry) => entry.id).filter(Boolean));
544
+ for (const entryId of data.appliedEntryIds) {
545
+ if (eventEntryIds.size > 0 && !eventEntryIds.has(entryId)) {
546
+ return invalidManualApplyResult('applied_entry_id_not_in_event', eventId, { entryId });
547
+ }
548
+ }
549
+ for (const item of data.failed) {
550
+ if (eventEntryIds.size > 0 && !eventEntryIds.has(item.entryId)) {
551
+ return invalidManualApplyResult('failed_entry_id_not_in_event', eventId, { entryId: item.entryId });
552
+ }
553
+ }
554
+
555
+ if (data.status === 'done') {
556
+ if (data.failed.length > 0) {
557
+ return invalidManualApplyResult('done_result_has_failed_entries', eventId);
558
+ }
559
+ if (countManualApplyOps(deferred?.batch) > 0 && data.appliedEntryIds.length === 0) {
560
+ return invalidManualApplyResult('done_result_missing_applied_entry_ids', eventId);
561
+ }
562
+ }
563
+ if (data.status === 'partial' && data.appliedEntryIds.length === 0 && data.failed.length === 0) {
564
+ return invalidManualApplyResult('partial_result_has_no_entries', eventId);
565
+ }
566
+ if (data.status === 'error' && data.appliedEntryIds.length > 0) {
567
+ return invalidManualApplyResult('error_result_has_applied_entries', eventId);
568
+ }
569
+
570
+ return {
571
+ ok: true,
572
+ result: {
573
+ status: data.status,
574
+ message: typeof data.message === 'string' ? data.message : undefined,
575
+ appliedEntryIds: data.appliedEntryIds,
576
+ failed: data.failed,
577
+ files: data.files,
578
+ notes: data.notes,
579
+ },
580
+ };
581
+ }
582
+
583
+ function firstFailureReason(result) {
584
+ const first = Array.isArray(result?.failed) ? result.failed.find(Boolean) : null;
585
+ return first?.reason || first?.message || null;
586
+ }
587
+
588
+ function markChunkEntriesFailed(failedByEntry, chunk, reason) {
589
+ for (const entryId of chunk.entryIds) {
590
+ if (failedByEntry.has(entryId)) continue;
591
+ failedByEntry.set(entryId, { entryId, reason, candidates: [] });
592
+ }
593
+ }
594
+
595
+ export function splitManualApplyBatch(batch, maxOps) {
596
+ const totalOpCount = countManualApplyOps(batch);
597
+ if (totalOpCount <= maxOps) {
598
+ return [{
599
+ batch,
600
+ meta: null,
601
+ entryIds: new Set((batch?.entries || []).map((entry) => entry.id).filter(Boolean)),
602
+ opCountsByEntry: new Map((batch?.entries || []).map((entry) => [entry.id, Array.isArray(entry.ops) ? entry.ops.length : 0])),
603
+ }];
604
+ }
605
+
606
+ const rawChunks = [];
607
+ let current = createManualApplyChunkBuilder();
608
+ for (const entry of batch?.entries || []) {
609
+ const ops = entry.ops || [];
610
+ if (ops.length <= maxOps) {
611
+ if (current.opCount > 0 && current.opCount + ops.length > maxOps) {
612
+ rawChunks.push(current);
613
+ current = createManualApplyChunkBuilder();
614
+ }
615
+ for (const op of ops) addOpToManualApplyChunk(current, entry, op);
616
+ continue;
617
+ }
618
+ if (current.opCount > 0) {
619
+ rawChunks.push(current);
620
+ current = createManualApplyChunkBuilder();
621
+ }
622
+ for (const op of ops) {
623
+ if (current.opCount >= maxOps) {
624
+ rawChunks.push(current);
625
+ current = createManualApplyChunkBuilder();
626
+ }
627
+ addOpToManualApplyChunk(current, entry, op);
628
+ }
629
+ }
630
+ if (current.opCount > 0) rawChunks.push(current);
631
+
632
+ return rawChunks.map((chunk, index) => ({
633
+ batch: {
634
+ ...batch,
635
+ count: chunk.opCount,
636
+ entries: chunk.entries,
637
+ ops: chunk.ops,
638
+ candidates: filterManualApplyChunkCandidates(batch, chunk.refsByEntry),
639
+ context: {
640
+ ...(batch?.context || {}),
641
+ totalEntries: chunk.entries.length,
642
+ totalOps: chunk.opCount,
643
+ chunkIndex: index + 1,
644
+ chunkTotal: rawChunks.length,
645
+ totalApplyOps: totalOpCount,
646
+ },
647
+ },
648
+ meta: {
649
+ index: index + 1,
650
+ total: rawChunks.length,
651
+ opCount: chunk.opCount,
652
+ totalOpCount,
653
+ },
654
+ entryIds: new Set(chunk.entries.map((entry) => entry.id).filter(Boolean)),
655
+ opCountsByEntry: chunk.opCountsByEntry,
656
+ }));
657
+ }
658
+
659
+ function createManualApplyChunkBuilder() {
660
+ return {
661
+ entries: [],
662
+ entryById: new Map(),
663
+ entryIds: new Set(),
664
+ ops: [],
665
+ refsByEntry: new Map(),
666
+ opCountsByEntry: new Map(),
667
+ opCount: 0,
668
+ };
669
+ }
670
+
671
+ function addOpToManualApplyChunk(chunk, entry, op) {
672
+ let chunkEntry = chunk.entryById.get(entry.id);
673
+ if (!chunkEntry) {
674
+ chunkEntry = { ...entry, ops: [] };
675
+ chunk.entryById.set(entry.id, chunkEntry);
676
+ chunk.entryIds.add(entry.id);
677
+ chunk.entries.push(chunkEntry);
678
+ }
679
+ chunkEntry.ops.push(op);
680
+ chunk.ops.push({ ...op, entryId: op.entryId || entry.id });
681
+ if (!chunk.refsByEntry.has(entry.id)) chunk.refsByEntry.set(entry.id, new Set());
682
+ if (op.ref) chunk.refsByEntry.get(entry.id).add(op.ref);
683
+ chunk.opCountsByEntry.set(entry.id, (chunk.opCountsByEntry.get(entry.id) || 0) + 1);
684
+ chunk.opCount += 1;
685
+ }
686
+
687
+ function filterManualApplyChunkCandidates(batch, refsByEntry) {
688
+ return (batch?.candidates || []).filter((candidate) => {
689
+ const refs = refsByEntry.get(candidate.entryId);
690
+ if (!refs) return false;
691
+ if (!candidate.ref) return true;
692
+ return refs.has(candidate.ref);
693
+ });
694
+ }
695
+
696
+ export function snapshotApplyEventFiles(batch, cwd = process.cwd()) {
697
+ const snapshot = new Map();
698
+ for (const relativeFile of collectManualApplyFiles(batch, [], cwd)) {
699
+ const absolute = path.resolve(cwd, relativeFile);
700
+ try {
701
+ snapshot.set(relativeFile, {
702
+ exists: fs.existsSync(absolute),
703
+ content: fs.existsSync(absolute) ? fs.readFileSync(absolute, 'utf-8') : '',
704
+ });
705
+ } catch {
706
+ // If a file cannot be read before dispatch, do not attempt late rollback.
707
+ }
708
+ }
709
+ return snapshot;
710
+ }
711
+
712
+ export function manualApplyTransactionPath(cwd = process.cwd()) {
713
+ return path.join(getLiveDir(cwd), 'manual-edit-apply-transaction.json');
714
+ }
715
+
716
+ export function readManualApplyTransaction(cwd = process.cwd()) {
717
+ const file = manualApplyTransactionPath(cwd);
718
+ if (!fs.existsSync(file)) return null;
719
+ try {
720
+ return JSON.parse(fs.readFileSync(file, 'utf-8'));
721
+ } catch {
722
+ return null;
723
+ }
724
+ }
725
+
726
+ export function writeManualApplyTransaction({ cwd = process.cwd(), pageUrl = null, batch }) {
727
+ const file = manualApplyTransactionPath(cwd);
728
+ const files = collectManualApplyFiles(batch, [], cwd);
729
+ const transaction = {
730
+ version: 1,
731
+ id: randomUUID().replace(/-/g, '').slice(0, 8),
732
+ createdAt: new Date().toISOString(),
733
+ pageUrl,
734
+ entryIds: (batch?.entries || []).map((entry) => entry.id).filter(Boolean),
735
+ files: files.map((relativeFile) => {
736
+ const absolute = path.resolve(cwd, relativeFile);
737
+ const exists = fs.existsSync(absolute);
738
+ return {
739
+ file: relativeFile,
740
+ exists,
741
+ content: exists ? fs.readFileSync(absolute, 'utf-8') : '',
742
+ };
743
+ }),
744
+ };
745
+ fs.mkdirSync(path.dirname(file), { recursive: true });
746
+ fs.writeFileSync(`${file}.tmp`, JSON.stringify(transaction, null, 2) + '\n', 'utf-8');
747
+ fs.renameSync(`${file}.tmp`, file);
748
+ return transaction;
749
+ }
750
+
751
+ export function clearManualApplyTransaction(cwd = process.cwd(), transactionId = null) {
752
+ const file = manualApplyTransactionPath(cwd);
753
+ if (!fs.existsSync(file)) return false;
754
+ if (transactionId) {
755
+ const existing = readManualApplyTransaction(cwd);
756
+ if (existing?.id && existing.id !== transactionId) return false;
757
+ }
758
+ try {
759
+ fs.unlinkSync(file);
760
+ return true;
761
+ } catch {
762
+ return false;
763
+ }
764
+ }
765
+
766
+ export function rollbackManualApplyTransaction({
767
+ cwd = process.cwd(),
768
+ pageUrl = null,
769
+ reason = 'manual_edit_transaction_rollback',
770
+ recordManualEditActivity = null,
771
+ } = {}) {
772
+ const transaction = readManualApplyTransaction(cwd);
773
+ if (!transaction) return null;
774
+ if (pageUrl && transaction.pageUrl && transaction.pageUrl !== pageUrl) return null;
775
+
776
+ let pendingIds = new Set();
777
+ try {
778
+ const buffer = readManualEditsBuffer(cwd);
779
+ pendingIds = new Set((buffer.entries || []).map((entry) => entry.id).filter(Boolean));
780
+ } catch {
781
+ pendingIds = new Set(transaction.entryIds || []);
782
+ }
783
+ const shouldRollback = (transaction.entryIds || []).some((id) => pendingIds.has(id));
784
+ if (!shouldRollback) {
785
+ clearManualApplyTransaction(cwd, transaction.id);
786
+ return { id: transaction.id, reason, rolledBackFiles: [], rollbackFailures: [], skipped: 'entries_not_pending' };
787
+ }
788
+
789
+ const rolledBackFiles = [];
790
+ const rollbackFailures = [];
791
+ for (const item of transaction.files || []) {
792
+ const relativeFile = normalizeProjectFile(item.file, cwd);
793
+ if (!relativeFile) continue;
794
+ const absolute = path.resolve(cwd, relativeFile);
795
+ try {
796
+ if (item.exists) {
797
+ fs.mkdirSync(path.dirname(absolute), { recursive: true });
798
+ fs.writeFileSync(absolute, item.content || '', 'utf-8');
799
+ } else if (fs.existsSync(absolute)) {
800
+ fs.rmSync(absolute);
801
+ }
802
+ rolledBackFiles.push(relativeFile);
803
+ } catch (err) {
804
+ rollbackFailures.push({ file: relativeFile, reason: 'restore_failed', message: err.message || String(err) });
805
+ }
806
+ }
807
+ clearManualApplyTransaction(cwd, transaction.id);
808
+ recordManualEditActivity?.('manual_edit_transaction_rolled_back', {
809
+ id: transaction.id,
810
+ pageUrl: transaction.pageUrl || null,
811
+ reason,
812
+ entryIds: transaction.entryIds || [],
813
+ rolledBackFiles: rolledBackFiles.map((file) => summarizeManualLogFile(file, cwd)).filter(Boolean),
814
+ rollbackFailures: summarizeManualDiagnostics(rollbackFailures, cwd),
815
+ });
816
+ return { id: transaction.id, reason, rolledBackFiles, rollbackFailures };
817
+ }
818
+
819
+ export function collectManualApplyFiles(batch, extraFiles = [], cwd = process.cwd()) {
820
+ const files = [];
821
+ for (const entry of batch?.entries || []) {
822
+ for (const op of entry.ops || []) files.push(op.sourceHint?.file);
823
+ }
824
+ for (const candidate of batch?.candidates || []) {
825
+ files.push(candidate.sourceHint?.relativeFile, candidate.sourceHint?.file);
826
+ for (const item of candidate.textMatches || []) files.push(item.file);
827
+ for (const item of candidate.objectKeyMatches || []) files.push(item.file);
828
+ for (const item of candidate.locatorMatches || []) files.push(item.file);
829
+ for (const item of candidate.contextTextMatches || []) files.push(item.file);
830
+ }
831
+ files.push(...(extraFiles || []));
832
+ return [...new Set(files)]
833
+ .map((file) => normalizeProjectFile(file, cwd))
834
+ .filter(Boolean);
835
+ }
836
+
837
+ function normalizeProjectFile(file, cwd = process.cwd()) {
838
+ if (!file || typeof file !== 'string') return null;
839
+ const absolute = path.isAbsolute(file) ? file : path.resolve(cwd, file);
840
+ const relative = path.relative(cwd, absolute);
841
+ if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) return null;
842
+ return relative;
843
+ }
844
+
845
+ export function rollbackApplySnapshot(
846
+ batch,
847
+ rollbackSnapshot,
848
+ extraFiles = [],
849
+ _reason = 'manual_edit_apply_snapshot_rollback',
850
+ cwd = process.cwd(),
851
+ ) {
852
+ const scope = collectManualApplyFiles(batch, extraFiles, cwd);
853
+ const rolledBackFiles = [];
854
+ const rollbackFailures = [];
855
+ for (const relativeFile of scope) {
856
+ const before = rollbackSnapshot?.get(relativeFile);
857
+ if (!before) continue;
858
+ const absolute = path.resolve(cwd, relativeFile);
859
+ try {
860
+ if (before.exists) {
861
+ fs.mkdirSync(path.dirname(absolute), { recursive: true });
862
+ fs.writeFileSync(absolute, before.content, 'utf-8');
863
+ } else if (fs.existsSync(absolute)) {
864
+ fs.rmSync(absolute);
865
+ }
866
+ rolledBackFiles.push(relativeFile);
867
+ } catch (err) {
868
+ rollbackFailures.push({ file: relativeFile, reason: 'restore_failed', message: err.message || String(err) });
869
+ }
870
+ }
871
+ return { rolledBackFiles, rollbackFailures };
872
+ }
873
+
874
+ function manualApplyReplyCommand(eventOrId = 'EVENT_ID') {
875
+ const id = typeof eventOrId === 'string' ? eventOrId : eventOrId?.id || 'EVENT_ID';
876
+ return `live-poll.mjs --reply ${id} done --data '<json>'`;
877
+ }
878
+
879
+ export function buildManualApplyAgentAction(eventOrId = 'EVENT_ID') {
880
+ return {
881
+ kind: 'manual_edit_apply',
882
+ required: 'apply_source_edits_then_reply',
883
+ replyCommand: manualApplyReplyCommand(eventOrId),
884
+ warning: 'Polling only leases this work item; it does not commit source edits.',
885
+ };
886
+ }
887
+
888
+ export function summarizeManualApplyEvent(event = {}, batch = event.batch, cwd = process.cwd()) {
889
+ const entries = Array.isArray(batch?.entries) ? batch.entries : [];
890
+ const opCount = entries.reduce((sum, entry) => sum + (Array.isArray(entry.ops) ? entry.ops.length : 0), 0);
891
+ return {
892
+ pageUrl: event.pageUrl || null,
893
+ chunk: event.chunk || null,
894
+ entryCount: entries.length,
895
+ opCount,
896
+ files: collectManualApplyFiles(batch, [], cwd),
897
+ };
898
+ }
899
+
900
+ export function summarizeManualApplyFailures(failed, cwd = process.cwd()) {
901
+ if (!Array.isArray(failed)) return [];
902
+ return failed.slice(0, 20).map((item) => ({
903
+ id: item.id || item.entryId || null,
904
+ reason: item.reason || item.message || 'failed',
905
+ message: compactManualLogText(item.message, 300),
906
+ files: Array.isArray(item.files) ? item.files.slice(0, 12).map((file) => summarizeManualLogFile(file, cwd)).filter(Boolean) : undefined,
907
+ checks: summarizeManualDiagnostics(item.checks, cwd),
908
+ failures: summarizeManualDiagnostics(item.failures, cwd),
909
+ candidates: summarizeManualDiagnostics(item.candidates, cwd),
910
+ }));
911
+ }
912
+
913
+ export function summarizeManualDiagnostics(items, cwd = process.cwd()) {
914
+ if (!Array.isArray(items) || items.length === 0) return undefined;
915
+ return items.slice(0, 12).map((item) => ({
916
+ reason: item.reason || item.kind || undefined,
917
+ detail: compactManualLogText(item.detail, 220),
918
+ message: compactManualLogText(item.message, 300),
919
+ file: summarizeManualLogFile(item.file || item.relativeFile, cwd),
920
+ line: item.line || undefined,
921
+ ref: compactManualLogText(item.ref, 180),
922
+ marker: compactManualLogText(item.marker, 120),
923
+ files: Array.isArray(item.files) ? item.files.slice(0, 8).map((file) => summarizeManualLogFile(file, cwd)).filter(Boolean) : undefined,
924
+ }));
925
+ }
926
+
927
+ export function summarizeManualLogFile(file, cwd = process.cwd()) {
928
+ if (!file || typeof file !== 'string') return undefined;
929
+ if (!path.isAbsolute(file)) return file;
930
+ const relative = path.relative(cwd, file);
931
+ return relative && !relative.startsWith('..') && !path.isAbsolute(relative) ? relative : file;
932
+ }
933
+
934
+ export function compactManualLogText(value, max = 200) {
935
+ if (typeof value !== 'string') return undefined;
936
+ const normalized = value.replace(/\s+/g, ' ').trim();
937
+ if (normalized.length <= max) return normalized;
938
+ return normalized.slice(0, max) + `... [truncated ${normalized.length - max} chars]`;
939
+ }