autonomous-coding-toolkit 1.0.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 (324) hide show
  1. package/.claude-plugin/marketplace.json +22 -0
  2. package/.claude-plugin/plugin.json +13 -0
  3. package/LICENSE +21 -0
  4. package/Makefile +21 -0
  5. package/README.md +140 -0
  6. package/SECURITY.md +28 -0
  7. package/agents/bash-expert.md +113 -0
  8. package/agents/dependency-auditor.md +138 -0
  9. package/agents/integration-tester.md +120 -0
  10. package/agents/lesson-scanner.md +149 -0
  11. package/agents/python-expert.md +179 -0
  12. package/agents/service-monitor.md +141 -0
  13. package/agents/shell-expert.md +147 -0
  14. package/benchmarks/runner.sh +147 -0
  15. package/benchmarks/tasks/01-rest-endpoint/rubric.sh +29 -0
  16. package/benchmarks/tasks/01-rest-endpoint/task.md +17 -0
  17. package/benchmarks/tasks/02-refactor-module/task.md +8 -0
  18. package/benchmarks/tasks/03-fix-integration-bug/task.md +8 -0
  19. package/benchmarks/tasks/04-add-test-coverage/task.md +8 -0
  20. package/benchmarks/tasks/05-multi-file-feature/task.md +8 -0
  21. package/bin/act.js +238 -0
  22. package/commands/autocode.md +6 -0
  23. package/commands/cancel-ralph.md +18 -0
  24. package/commands/code-factory.md +53 -0
  25. package/commands/create-prd.md +55 -0
  26. package/commands/ralph-loop.md +18 -0
  27. package/commands/run-plan.md +117 -0
  28. package/commands/submit-lesson.md +122 -0
  29. package/docs/ARCHITECTURE.md +630 -0
  30. package/docs/CONTRIBUTING.md +125 -0
  31. package/docs/lessons/0001-bare-exception-swallowing.md +34 -0
  32. package/docs/lessons/0002-async-def-without-await.md +28 -0
  33. package/docs/lessons/0003-create-task-without-callback.md +28 -0
  34. package/docs/lessons/0004-hardcoded-test-counts.md +28 -0
  35. package/docs/lessons/0005-sqlite-without-closing.md +33 -0
  36. package/docs/lessons/0006-venv-pip-path.md +27 -0
  37. package/docs/lessons/0007-runner-state-self-rejection.md +35 -0
  38. package/docs/lessons/0008-quality-gate-blind-spot.md +33 -0
  39. package/docs/lessons/0009-parser-overcount-empty-batches.md +36 -0
  40. package/docs/lessons/0010-local-outside-function-bash.md +33 -0
  41. package/docs/lessons/0011-batch-tests-for-unimplemented-code.md +36 -0
  42. package/docs/lessons/0012-api-markdown-unescaped-chars.md +33 -0
  43. package/docs/lessons/0013-export-prefix-env-parsing.md +33 -0
  44. package/docs/lessons/0014-decorator-registry-import-side-effect.md +43 -0
  45. package/docs/lessons/0015-frontend-backend-schema-drift.md +43 -0
  46. package/docs/lessons/0016-event-driven-cold-start-seeding.md +44 -0
  47. package/docs/lessons/0017-copy-paste-logic-diverges.md +43 -0
  48. package/docs/lessons/0018-layer-passes-pipeline-broken.md +45 -0
  49. package/docs/lessons/0019-systemd-envfile-ignores-export.md +41 -0
  50. package/docs/lessons/0020-persist-state-incrementally.md +44 -0
  51. package/docs/lessons/0021-dual-axis-testing.md +48 -0
  52. package/docs/lessons/0022-jsx-factory-shadowing.md +43 -0
  53. package/docs/lessons/0023-static-analysis-spiral.md +51 -0
  54. package/docs/lessons/0024-shared-pipeline-implementation.md +55 -0
  55. package/docs/lessons/0025-defense-in-depth-all-entry-points.md +65 -0
  56. package/docs/lessons/0026-linter-no-rules-false-enforcement.md +54 -0
  57. package/docs/lessons/0027-jsx-silent-prop-drop.md +64 -0
  58. package/docs/lessons/0028-no-infrastructure-in-client-code.md +49 -0
  59. package/docs/lessons/0029-never-write-secrets-to-files.md +61 -0
  60. package/docs/lessons/0030-cache-merge-not-replace.md +62 -0
  61. package/docs/lessons/0031-verify-units-at-boundaries.md +66 -0
  62. package/docs/lessons/0032-module-lifecycle-subscribe-unsubscribe.md +89 -0
  63. package/docs/lessons/0033-async-iteration-mutable-snapshot.md +72 -0
  64. package/docs/lessons/0034-caller-missing-await-silent-discard.md +65 -0
  65. package/docs/lessons/0035-duplicate-registration-silent-overwrite.md +85 -0
  66. package/docs/lessons/0036-websocket-dirty-disconnect.md +33 -0
  67. package/docs/lessons/0037-parallel-agents-worktree-corruption.md +31 -0
  68. package/docs/lessons/0038-subscribe-no-stored-ref.md +36 -0
  69. package/docs/lessons/0039-fallback-or-default-hides-bugs.md +34 -0
  70. package/docs/lessons/0040-event-firehose-filter-first.md +36 -0
  71. package/docs/lessons/0041-ambiguous-base-dir-path-nesting.md +32 -0
  72. package/docs/lessons/0042-spec-compliance-insufficient.md +36 -0
  73. package/docs/lessons/0043-exact-count-extensible-collections.md +32 -0
  74. package/docs/lessons/0044-relative-file-deps-worktree.md +39 -0
  75. package/docs/lessons/0045-iterative-design-improvement.md +33 -0
  76. package/docs/lessons/0046-plan-assertion-math-bugs.md +38 -0
  77. package/docs/lessons/0047-pytest-single-threaded-default.md +37 -0
  78. package/docs/lessons/0048-integration-wiring-batch.md +40 -0
  79. package/docs/lessons/0049-ab-verification.md +41 -0
  80. package/docs/lessons/0050-editing-sourced-files-during-execution.md +33 -0
  81. package/docs/lessons/0051-infrastructure-fixes-cant-self-heal.md +30 -0
  82. package/docs/lessons/0052-uncommitted-changes-poison-quality-gates.md +31 -0
  83. package/docs/lessons/0053-jq-compact-flag-inconsistency.md +31 -0
  84. package/docs/lessons/0054-parser-matches-inside-code-blocks.md +30 -0
  85. package/docs/lessons/0055-agents-compensate-for-garbled-prompts.md +31 -0
  86. package/docs/lessons/0056-grep-count-exit-code-on-zero.md +42 -0
  87. package/docs/lessons/0057-new-artifacts-break-git-clean-gates.md +42 -0
  88. package/docs/lessons/0058-dead-config-keys-never-consumed.md +49 -0
  89. package/docs/lessons/0059-contract-test-shared-structures.md +53 -0
  90. package/docs/lessons/0060-set-e-silent-death-in-runners.md +53 -0
  91. package/docs/lessons/0061-context-injection-dirty-state.md +50 -0
  92. package/docs/lessons/0062-sibling-bug-neighborhood-scan.md +29 -0
  93. package/docs/lessons/0063-one-flag-two-lifetimes.md +31 -0
  94. package/docs/lessons/0064-test-passes-wrong-reason.md +31 -0
  95. package/docs/lessons/0065-pipefail-grep-count-double-output.md +39 -0
  96. package/docs/lessons/0066-local-keyword-outside-function.md +37 -0
  97. package/docs/lessons/0067-stdin-hang-non-interactive-shell.md +36 -0
  98. package/docs/lessons/0068-agent-builds-wrong-thing-correctly.md +31 -0
  99. package/docs/lessons/0069-plan-quality-dominates-execution.md +30 -0
  100. package/docs/lessons/0070-spec-echo-back-prevents-drift.md +31 -0
  101. package/docs/lessons/0071-positive-instructions-outperform-negative.md +30 -0
  102. package/docs/lessons/0072-lost-in-the-middle-context-placement.md +30 -0
  103. package/docs/lessons/0073-unscoped-lessons-cause-false-positives.md +30 -0
  104. package/docs/lessons/0074-stale-context-injection-wrong-batch.md +32 -0
  105. package/docs/lessons/0075-research-artifacts-must-persist.md +32 -0
  106. package/docs/lessons/0076-wrong-decomposition-contaminates-downstream.md +30 -0
  107. package/docs/lessons/0077-cherry-pick-merges-need-manual-resolution.md +30 -0
  108. package/docs/lessons/0078-static-review-without-live-test.md +30 -0
  109. package/docs/lessons/0079-integration-wiring-batch-required.md +32 -0
  110. package/docs/lessons/FRAMEWORK.md +161 -0
  111. package/docs/lessons/SUMMARY.md +201 -0
  112. package/docs/lessons/TEMPLATE.md +85 -0
  113. package/docs/plans/2026-02-21-code-factory-v2-design.md +204 -0
  114. package/docs/plans/2026-02-21-code-factory-v2-implementation-plan.md +2189 -0
  115. package/docs/plans/2026-02-21-code-factory-v2-phase4-design.md +537 -0
  116. package/docs/plans/2026-02-21-code-factory-v2-phase4-implementation-plan.md +2012 -0
  117. package/docs/plans/2026-02-21-hardening-pass-design.md +108 -0
  118. package/docs/plans/2026-02-21-hardening-pass-plan.md +1378 -0
  119. package/docs/plans/2026-02-21-mab-research-report.md +406 -0
  120. package/docs/plans/2026-02-21-marketplace-restructure-design.md +240 -0
  121. package/docs/plans/2026-02-21-marketplace-restructure-plan.md +832 -0
  122. package/docs/plans/2026-02-21-phase4-completion-plan.md +697 -0
  123. package/docs/plans/2026-02-21-validator-suite-design.md +148 -0
  124. package/docs/plans/2026-02-21-validator-suite-plan.md +540 -0
  125. package/docs/plans/2026-02-22-mab-research-round2.md +556 -0
  126. package/docs/plans/2026-02-22-mab-run-design.md +462 -0
  127. package/docs/plans/2026-02-22-mab-run-plan.md +2046 -0
  128. package/docs/plans/2026-02-22-operations-design-methodology-research.md +681 -0
  129. package/docs/plans/2026-02-22-research-agent-failure-taxonomy.md +532 -0
  130. package/docs/plans/2026-02-22-research-code-guideline-policies.md +886 -0
  131. package/docs/plans/2026-02-22-research-codebase-audit-refactoring.md +908 -0
  132. package/docs/plans/2026-02-22-research-coding-standards-documentation.md +541 -0
  133. package/docs/plans/2026-02-22-research-competitive-landscape.md +687 -0
  134. package/docs/plans/2026-02-22-research-comprehensive-testing.md +1076 -0
  135. package/docs/plans/2026-02-22-research-context-utilization.md +459 -0
  136. package/docs/plans/2026-02-22-research-cost-quality-tradeoff.md +548 -0
  137. package/docs/plans/2026-02-22-research-lesson-transferability.md +508 -0
  138. package/docs/plans/2026-02-22-research-multi-agent-coordination.md +312 -0
  139. package/docs/plans/2026-02-22-research-phase-integration.md +602 -0
  140. package/docs/plans/2026-02-22-research-plan-quality.md +428 -0
  141. package/docs/plans/2026-02-22-research-prompt-engineering.md +558 -0
  142. package/docs/plans/2026-02-22-research-unconventional-perspectives.md +528 -0
  143. package/docs/plans/2026-02-22-research-user-adoption.md +638 -0
  144. package/docs/plans/2026-02-22-research-verification-effectiveness.md +433 -0
  145. package/docs/plans/2026-02-23-agent-suite-design.md +299 -0
  146. package/docs/plans/2026-02-23-agent-suite-plan.md +578 -0
  147. package/docs/plans/2026-02-23-phase3-cost-infrastructure-design.md +148 -0
  148. package/docs/plans/2026-02-23-phase3-cost-infrastructure-plan.md +1062 -0
  149. package/docs/plans/2026-02-23-research-bash-expert-agent.md +543 -0
  150. package/docs/plans/2026-02-23-research-dependency-auditor-agent.md +564 -0
  151. package/docs/plans/2026-02-23-research-improving-existing-agents.md +503 -0
  152. package/docs/plans/2026-02-23-research-integration-tester-agent.md +454 -0
  153. package/docs/plans/2026-02-23-research-python-expert-agent.md +429 -0
  154. package/docs/plans/2026-02-23-research-service-monitor-agent.md +425 -0
  155. package/docs/plans/2026-02-23-research-shell-expert-agent.md +533 -0
  156. package/docs/plans/2026-02-23-roadmap-to-completion.md +530 -0
  157. package/docs/plans/2026-02-24-headless-module-split-design.md +98 -0
  158. package/docs/plans/2026-02-24-headless-module-split.md +443 -0
  159. package/docs/plans/2026-02-24-lesson-scope-metadata-design.md +228 -0
  160. package/docs/plans/2026-02-24-lesson-scope-metadata-plan.md +968 -0
  161. package/docs/plans/2026-02-24-npm-packaging-design.md +841 -0
  162. package/docs/plans/2026-02-24-npm-packaging-plan.md +1965 -0
  163. package/docs/plans/audit-findings.md +186 -0
  164. package/docs/telegram-notification-format.md +98 -0
  165. package/examples/example-plan.md +51 -0
  166. package/examples/example-prd.json +72 -0
  167. package/examples/example-roadmap.md +33 -0
  168. package/examples/quickstart-plan.md +63 -0
  169. package/hooks/hooks.json +26 -0
  170. package/hooks/setup-symlinks.sh +48 -0
  171. package/hooks/stop-hook.sh +135 -0
  172. package/package.json +47 -0
  173. package/policies/bash.md +71 -0
  174. package/policies/python.md +71 -0
  175. package/policies/testing.md +61 -0
  176. package/policies/universal.md +60 -0
  177. package/scripts/analyze-report.sh +97 -0
  178. package/scripts/architecture-map.sh +145 -0
  179. package/scripts/auto-compound.sh +273 -0
  180. package/scripts/batch-audit.sh +42 -0
  181. package/scripts/batch-test.sh +101 -0
  182. package/scripts/entropy-audit.sh +221 -0
  183. package/scripts/failure-digest.sh +51 -0
  184. package/scripts/generate-ast-rules.sh +96 -0
  185. package/scripts/init.sh +112 -0
  186. package/scripts/lesson-check.sh +428 -0
  187. package/scripts/lib/common.sh +61 -0
  188. package/scripts/lib/cost-tracking.sh +153 -0
  189. package/scripts/lib/ollama.sh +60 -0
  190. package/scripts/lib/progress-writer.sh +128 -0
  191. package/scripts/lib/run-plan-context.sh +215 -0
  192. package/scripts/lib/run-plan-echo-back.sh +231 -0
  193. package/scripts/lib/run-plan-headless.sh +396 -0
  194. package/scripts/lib/run-plan-notify.sh +57 -0
  195. package/scripts/lib/run-plan-parser.sh +81 -0
  196. package/scripts/lib/run-plan-prompt.sh +215 -0
  197. package/scripts/lib/run-plan-quality-gate.sh +132 -0
  198. package/scripts/lib/run-plan-routing.sh +315 -0
  199. package/scripts/lib/run-plan-sampling.sh +170 -0
  200. package/scripts/lib/run-plan-scoring.sh +146 -0
  201. package/scripts/lib/run-plan-state.sh +142 -0
  202. package/scripts/lib/run-plan-team.sh +199 -0
  203. package/scripts/lib/telegram.sh +54 -0
  204. package/scripts/lib/thompson-sampling.sh +176 -0
  205. package/scripts/license-check.sh +74 -0
  206. package/scripts/mab-run.sh +575 -0
  207. package/scripts/module-size-check.sh +146 -0
  208. package/scripts/patterns/async-no-await.yml +5 -0
  209. package/scripts/patterns/bare-except.yml +6 -0
  210. package/scripts/patterns/empty-catch.yml +6 -0
  211. package/scripts/patterns/hardcoded-localhost.yml +9 -0
  212. package/scripts/patterns/retry-loop-no-backoff.yml +12 -0
  213. package/scripts/pipeline-status.sh +197 -0
  214. package/scripts/policy-check.sh +226 -0
  215. package/scripts/prior-art-search.sh +133 -0
  216. package/scripts/promote-mab-lessons.sh +126 -0
  217. package/scripts/prompts/agent-a-superpowers.md +29 -0
  218. package/scripts/prompts/agent-b-ralph.md +29 -0
  219. package/scripts/prompts/judge-agent.md +61 -0
  220. package/scripts/prompts/planner-agent.md +44 -0
  221. package/scripts/pull-community-lessons.sh +90 -0
  222. package/scripts/quality-gate.sh +266 -0
  223. package/scripts/research-gate.sh +90 -0
  224. package/scripts/run-plan.sh +329 -0
  225. package/scripts/scope-infer.sh +159 -0
  226. package/scripts/setup-ralph-loop.sh +155 -0
  227. package/scripts/telemetry.sh +230 -0
  228. package/scripts/tests/run-all-tests.sh +52 -0
  229. package/scripts/tests/test-act-cli.sh +46 -0
  230. package/scripts/tests/test-agents-md.sh +87 -0
  231. package/scripts/tests/test-analyze-report.sh +114 -0
  232. package/scripts/tests/test-architecture-map.sh +89 -0
  233. package/scripts/tests/test-auto-compound.sh +169 -0
  234. package/scripts/tests/test-batch-test.sh +65 -0
  235. package/scripts/tests/test-benchmark-runner.sh +25 -0
  236. package/scripts/tests/test-common.sh +168 -0
  237. package/scripts/tests/test-cost-tracking.sh +158 -0
  238. package/scripts/tests/test-echo-back.sh +180 -0
  239. package/scripts/tests/test-entropy-audit.sh +146 -0
  240. package/scripts/tests/test-failure-digest.sh +66 -0
  241. package/scripts/tests/test-generate-ast-rules.sh +145 -0
  242. package/scripts/tests/test-helpers.sh +82 -0
  243. package/scripts/tests/test-init.sh +47 -0
  244. package/scripts/tests/test-lesson-check.sh +278 -0
  245. package/scripts/tests/test-lesson-local.sh +55 -0
  246. package/scripts/tests/test-license-check.sh +109 -0
  247. package/scripts/tests/test-mab-run.sh +182 -0
  248. package/scripts/tests/test-ollama-lib.sh +49 -0
  249. package/scripts/tests/test-ollama.sh +60 -0
  250. package/scripts/tests/test-pipeline-status.sh +198 -0
  251. package/scripts/tests/test-policy-check.sh +124 -0
  252. package/scripts/tests/test-prior-art-search.sh +96 -0
  253. package/scripts/tests/test-progress-writer.sh +140 -0
  254. package/scripts/tests/test-promote-mab-lessons.sh +110 -0
  255. package/scripts/tests/test-pull-community-lessons.sh +149 -0
  256. package/scripts/tests/test-quality-gate.sh +241 -0
  257. package/scripts/tests/test-research-gate.sh +132 -0
  258. package/scripts/tests/test-run-plan-cli.sh +86 -0
  259. package/scripts/tests/test-run-plan-context.sh +305 -0
  260. package/scripts/tests/test-run-plan-e2e.sh +153 -0
  261. package/scripts/tests/test-run-plan-headless.sh +424 -0
  262. package/scripts/tests/test-run-plan-notify.sh +124 -0
  263. package/scripts/tests/test-run-plan-parser.sh +217 -0
  264. package/scripts/tests/test-run-plan-prompt.sh +254 -0
  265. package/scripts/tests/test-run-plan-quality-gate.sh +222 -0
  266. package/scripts/tests/test-run-plan-routing.sh +178 -0
  267. package/scripts/tests/test-run-plan-scoring.sh +148 -0
  268. package/scripts/tests/test-run-plan-state.sh +261 -0
  269. package/scripts/tests/test-run-plan-team.sh +157 -0
  270. package/scripts/tests/test-scope-infer.sh +150 -0
  271. package/scripts/tests/test-setup-ralph-loop.sh +63 -0
  272. package/scripts/tests/test-telegram-env.sh +38 -0
  273. package/scripts/tests/test-telegram.sh +121 -0
  274. package/scripts/tests/test-telemetry.sh +46 -0
  275. package/scripts/tests/test-thompson-sampling.sh +139 -0
  276. package/scripts/tests/test-validate-all.sh +60 -0
  277. package/scripts/tests/test-validate-commands.sh +89 -0
  278. package/scripts/tests/test-validate-hooks.sh +98 -0
  279. package/scripts/tests/test-validate-lessons.sh +150 -0
  280. package/scripts/tests/test-validate-plan-quality.sh +235 -0
  281. package/scripts/tests/test-validate-plans.sh +187 -0
  282. package/scripts/tests/test-validate-plugin.sh +106 -0
  283. package/scripts/tests/test-validate-prd.sh +184 -0
  284. package/scripts/tests/test-validate-skills.sh +134 -0
  285. package/scripts/validate-all.sh +57 -0
  286. package/scripts/validate-commands.sh +67 -0
  287. package/scripts/validate-hooks.sh +89 -0
  288. package/scripts/validate-lessons.sh +98 -0
  289. package/scripts/validate-plan-quality.sh +369 -0
  290. package/scripts/validate-plans.sh +120 -0
  291. package/scripts/validate-plugin.sh +86 -0
  292. package/scripts/validate-policies.sh +42 -0
  293. package/scripts/validate-prd.sh +118 -0
  294. package/scripts/validate-skills.sh +96 -0
  295. package/skills/autocode/SKILL.md +285 -0
  296. package/skills/autocode/ab-verification.md +51 -0
  297. package/skills/autocode/code-quality-standards.md +37 -0
  298. package/skills/autocode/competitive-mode.md +364 -0
  299. package/skills/brainstorming/SKILL.md +97 -0
  300. package/skills/capture-lesson/SKILL.md +187 -0
  301. package/skills/check-lessons/SKILL.md +116 -0
  302. package/skills/dispatching-parallel-agents/SKILL.md +110 -0
  303. package/skills/executing-plans/SKILL.md +85 -0
  304. package/skills/finishing-a-development-branch/SKILL.md +201 -0
  305. package/skills/receiving-code-review/SKILL.md +72 -0
  306. package/skills/requesting-code-review/SKILL.md +59 -0
  307. package/skills/requesting-code-review/code-reviewer.md +82 -0
  308. package/skills/research/SKILL.md +145 -0
  309. package/skills/roadmap/SKILL.md +115 -0
  310. package/skills/subagent-driven-development/SKILL.md +98 -0
  311. package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +18 -0
  312. package/skills/subagent-driven-development/implementer-prompt.md +73 -0
  313. package/skills/subagent-driven-development/spec-reviewer-prompt.md +57 -0
  314. package/skills/systematic-debugging/SKILL.md +134 -0
  315. package/skills/systematic-debugging/condition-based-waiting.md +64 -0
  316. package/skills/systematic-debugging/defense-in-depth.md +32 -0
  317. package/skills/systematic-debugging/root-cause-tracing.md +55 -0
  318. package/skills/test-driven-development/SKILL.md +167 -0
  319. package/skills/using-git-worktrees/SKILL.md +219 -0
  320. package/skills/using-superpowers/SKILL.md +54 -0
  321. package/skills/verification-before-completion/SKILL.md +140 -0
  322. package/skills/verify/SKILL.md +82 -0
  323. package/skills/writing-plans/SKILL.md +128 -0
  324. package/skills/writing-skills/SKILL.md +93 -0
@@ -0,0 +1,235 @@
1
+ #!/usr/bin/env bash
2
+ # Test plan quality scorecard
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ VALIDATE="$SCRIPT_DIR/../validate-plan-quality.sh"
7
+
8
+ FAILURES=0
9
+ TESTS=0
10
+
11
+ assert_eq() {
12
+ local desc="$1" expected="$2" actual="$3"
13
+ TESTS=$((TESTS + 1))
14
+ if [[ "$expected" != "$actual" ]]; then
15
+ echo "FAIL: $desc (expected: $expected, got: $actual)"
16
+ FAILURES=$((FAILURES + 1))
17
+ else
18
+ echo "PASS: $desc"
19
+ fi
20
+ }
21
+
22
+ assert_contains() {
23
+ local desc="$1" needle="$2" haystack="$3"
24
+ TESTS=$((TESTS + 1))
25
+ if [[ "$haystack" != *"$needle"* ]]; then
26
+ echo "FAIL: $desc"
27
+ echo " expected to contain: $needle"
28
+ FAILURES=$((FAILURES + 1))
29
+ else
30
+ echo "PASS: $desc"
31
+ fi
32
+ }
33
+
34
+ TMPDIR_ROOT=$(mktemp -d)
35
+ trap 'rm -rf "$TMPDIR_ROOT"' EXIT
36
+
37
+ # =============================================================================
38
+ # High-quality plan (should score >= 60)
39
+ # =============================================================================
40
+
41
+ HIGH_QUALITY="$TMPDIR_ROOT/high-quality.md"
42
+ cat > "$HIGH_QUALITY" << 'EOF'
43
+ # High Quality Plan
44
+
45
+ ## Batch 1: Setup (Tasks 1-2)
46
+
47
+ ### Task 1: Create Data Model
48
+
49
+ **Files:**
50
+ - Create: `src/models.py`
51
+ - Test: `tests/test_models.py`
52
+
53
+ **Step 1: Write the failing test**
54
+
55
+ Write `tests/test_models.py` with assertions that verify Model class works.
56
+
57
+ **Step 2: Implement**
58
+
59
+ Create `src/models.py` with the Model class.
60
+
61
+ ### Task 2: Add Validation
62
+
63
+ **Files:**
64
+ - Modify: `src/models.py`
65
+
66
+ Add validation. Write test first, then implement. Should reject invalid input.
67
+
68
+ ## Batch 2: Integration (Tasks 3-4)
69
+
70
+ ### Task 3: Wire Components
71
+
72
+ **Files:**
73
+ - Create: `src/pipeline.py`
74
+ - Test: `tests/test_pipeline.py`
75
+
76
+ Connect parser to transformer. Verify end-to-end with test that checks output format.
77
+
78
+ ### Task 4: CLI Entry Point
79
+
80
+ **Files:**
81
+ - Create: `src/cli.py`
82
+ - Test: `tests/test_cli.py`
83
+
84
+ Add CLI. Test argument parsing. Should handle missing file gracefully.
85
+ EOF
86
+
87
+ output=$(bash "$VALIDATE" "$HIGH_QUALITY" 2>&1)
88
+ exit_code=$?
89
+
90
+ assert_eq "high quality plan passes" "0" "$exit_code"
91
+ assert_contains "high quality shows PASSED" "PASSED" "$output"
92
+
93
+ # =============================================================================
94
+ # Low-quality plan (should score < 60 with low min-score threshold)
95
+ # =============================================================================
96
+
97
+ LOW_QUALITY="$TMPDIR_ROOT/low-quality.md"
98
+ cat > "$LOW_QUALITY" << 'EOF'
99
+ # Low Quality Plan
100
+
101
+ ## Batch 1: Do Everything
102
+
103
+ Build the whole thing. Make it work. Deploy it.
104
+
105
+ ## Batch 2: More Stuff
106
+
107
+ Do more stuff. Fix what broke in batch 1.
108
+ Depends on batch 3 being done first.
109
+
110
+ ## Batch 3: Final Things
111
+
112
+ Finish everything. Clean up.
113
+ EOF
114
+
115
+ output=$(bash "$VALIDATE" "$LOW_QUALITY" 2>&1 || true)
116
+ # Low quality: no tasks, no files, no tests, forward ref in batch 2 → batch 3
117
+ assert_contains "low quality shows scores" "Scorecard" "$output"
118
+
119
+ # With min-score=90 this should definitely fail
120
+ exit_code=0
121
+ bash "$VALIDATE" "$LOW_QUALITY" --min-score 90 >/dev/null 2>&1 || exit_code=$?
122
+ assert_eq "low quality fails at min-score 90" "1" "$exit_code"
123
+
124
+ # =============================================================================
125
+ # JSON output mode
126
+ # =============================================================================
127
+
128
+ json_output=$(bash "$VALIDATE" "$HIGH_QUALITY" --json 2>&1)
129
+ assert_contains "json has score field" '"score"' "$json_output"
130
+ assert_contains "json has dimensions" '"dimensions"' "$json_output"
131
+ assert_contains "json has passed field" '"passed"' "$json_output"
132
+ assert_contains "json has task_granularity" '"task_granularity"' "$json_output"
133
+ assert_contains "json has weight" '"weight"' "$json_output"
134
+
135
+ # =============================================================================
136
+ # Error cases
137
+ # =============================================================================
138
+
139
+ # No file
140
+ exit_code=0
141
+ bash "$VALIDATE" 2>/dev/null || exit_code=$?
142
+ assert_eq "no file arg exits 1" "1" "$exit_code"
143
+
144
+ # Missing file
145
+ exit_code=0
146
+ bash "$VALIDATE" "$TMPDIR_ROOT/nonexistent.md" 2>/dev/null || exit_code=$?
147
+ assert_eq "missing file exits 1" "1" "$exit_code"
148
+
149
+ # File with no batches
150
+ NO_BATCHES="$TMPDIR_ROOT/no-batches.md"
151
+ echo "# Just a title" > "$NO_BATCHES"
152
+ exit_code=0
153
+ bash "$VALIDATE" "$NO_BATCHES" 2>/dev/null || exit_code=$?
154
+ assert_eq "no batches exits 1" "1" "$exit_code"
155
+
156
+ # =============================================================================
157
+ # Custom min-score
158
+ # =============================================================================
159
+
160
+ # High quality with min-score=101 should fail (max score is 100)
161
+ exit_code=0
162
+ bash "$VALIDATE" "$HIGH_QUALITY" --min-score 101 >/dev/null 2>&1 || exit_code=$?
163
+ assert_eq "min-score 101 is impossible to pass" "1" "$exit_code"
164
+
165
+ # High quality with min-score=1 should pass
166
+ exit_code=0
167
+ bash "$VALIDATE" "$HIGH_QUALITY" --min-score 1 >/dev/null 2>&1 || exit_code=$?
168
+ assert_eq "min-score 1 is easy to pass" "0" "$exit_code"
169
+
170
+ # =============================================================================
171
+ # Dimension-specific tests
172
+ # =============================================================================
173
+
174
+ # Forward dependency reference
175
+ FORWARD_REF="$TMPDIR_ROOT/forward-ref.md"
176
+ cat > "$FORWARD_REF" << 'EOF'
177
+ # Forward Reference Plan
178
+
179
+ ## Batch 1: First
180
+
181
+ ### Task 1: Setup
182
+
183
+ **Files:**
184
+ - Create: `src/setup.py`
185
+
186
+ This task needs batch 2 to be done first. Check tests pass.
187
+
188
+ ## Batch 2: Second
189
+
190
+ ### Task 2: Build
191
+
192
+ **Files:**
193
+ - Create: `src/build.py`
194
+
195
+ Build the thing. Verify it works.
196
+ EOF
197
+
198
+ json=$(bash "$VALIDATE" "$FORWARD_REF" --json 2>&1)
199
+ dep_score=$(echo "$json" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['dimensions']['dependency_ordering']['score'])")
200
+ assert_eq "forward ref lowers dependency score" "50" "$dep_score"
201
+
202
+ # Oversized batch (> 5 tasks)
203
+ BIG_BATCH="$TMPDIR_ROOT/big-batch.md"
204
+ cat > "$BIG_BATCH" << 'EOF'
205
+ # Big Batch Plan
206
+
207
+ ## Batch 1: Everything
208
+
209
+ ### Task 1: A
210
+ Do A. Check it works.
211
+ ### Task 2: B
212
+ Do B. Verify output.
213
+ ### Task 3: C
214
+ Do C. Test the result.
215
+ ### Task 4: D
216
+ Do D. Assert correctness.
217
+ ### Task 5: E
218
+ Do E. Should pass all tests.
219
+ ### Task 6: F
220
+ Do F. Confirm it works.
221
+ ### Task 7: G
222
+ Do G. Must be correct.
223
+ EOF
224
+
225
+ json=$(bash "$VALIDATE" "$BIG_BATCH" --json 2>&1)
226
+ size_score=$(echo "$json" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['dimensions']['batch_size']['score'])")
227
+ assert_eq "oversized batch gets 0 on batch_size" "0" "$size_score"
228
+
229
+ echo ""
230
+ echo "Results: $((TESTS - FAILURES))/$TESTS passed"
231
+ if [[ $FAILURES -gt 0 ]]; then
232
+ echo "FAILURES: $FAILURES"
233
+ exit 1
234
+ fi
235
+ echo "ALL PASSED"
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env bash
2
+ # Test validate-plans.sh
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ source "$SCRIPT_DIR/test-helpers.sh"
7
+
8
+ VALIDATOR="$SCRIPT_DIR/../validate-plans.sh"
9
+ WORK=$(mktemp -d)
10
+ trap 'rm -rf "$WORK"' EXIT
11
+
12
+ # Helper: create a plan file
13
+ create_plan() {
14
+ local name="$1" content="$2"
15
+ mkdir -p "$WORK/plans"
16
+ printf '%s\n' "$content" > "$WORK/plans/$name"
17
+ }
18
+
19
+ # Helper: run validator against temp plans dir
20
+ run_validator() {
21
+ local exit_code=0
22
+ PLANS_DIR="$WORK/plans" bash "$VALIDATOR" "$@" 2>&1 || exit_code=$?
23
+ echo "EXIT:$exit_code"
24
+ }
25
+
26
+ # === Test: Valid plan passes ===
27
+ rm -rf "$WORK/plans"
28
+ create_plan "2026-01-01-test-plan.md" '# Test Plan
29
+
30
+ ## Batch 1: Setup
31
+
32
+ ### Task 1: Do thing one
33
+
34
+ Some content.
35
+
36
+ ### Task 2: Do thing two
37
+
38
+ More content.
39
+
40
+ ## Batch 2: Implementation
41
+
42
+ ### Task 3: Do thing three
43
+
44
+ Final content.'
45
+
46
+ output=$(run_validator)
47
+ assert_contains "valid plan: PASS" "validate-plans: PASS" "$output"
48
+ assert_contains "valid plan: exit 0" "EXIT:0" "$output"
49
+
50
+ # === Test: No batches fails (explicit file) ===
51
+ rm -rf "$WORK/plans"
52
+ create_plan "2026-01-01-no-batches.md" '# A Plan
53
+
54
+ This plan has no batch headers at all.
55
+
56
+ Just some text.'
57
+
58
+ exit_code=0
59
+ output=$(bash "$VALIDATOR" "$WORK/plans/2026-01-01-no-batches.md" 2>&1) || exit_code=$?
60
+ output="${output}
61
+ EXIT:${exit_code}"
62
+ assert_contains "no batches: reports violation" "No batches found" "$output"
63
+ assert_contains "no batches: exit 1" "EXIT:1" "$output"
64
+
65
+ # === Test: Empty batch (no tasks) fails ===
66
+ rm -rf "$WORK/plans"
67
+ create_plan "2026-01-01-empty-batch.md" '# Plan
68
+
69
+ ## Batch 1: Setup
70
+
71
+ ### Task 1: Do something
72
+
73
+ Content.
74
+
75
+ ## Batch 2: Empty
76
+
77
+ No tasks here.
78
+
79
+ ## Batch 3: More
80
+
81
+ ### Task 2: Do another thing
82
+
83
+ Content.'
84
+
85
+ output=$(run_validator)
86
+ assert_contains "empty batch: reports violation" "has no tasks" "$output"
87
+ assert_contains "empty batch: exit 1" "EXIT:1" "$output"
88
+
89
+ # === Test: Non-sequential batch numbers fails ===
90
+ rm -rf "$WORK/plans"
91
+ create_plan "2026-01-01-nonseq.md" '# Plan
92
+
93
+ ## Batch 1: First
94
+
95
+ ### Task 1: Do thing
96
+
97
+ Content.
98
+
99
+ ## Batch 3: Skipped Two
100
+
101
+ ### Task 2: Do another
102
+
103
+ Content.'
104
+
105
+ output=$(run_validator)
106
+ assert_contains "non-sequential: reports violation" "expected Batch 2" "$output"
107
+ assert_contains "non-sequential: exit 1" "EXIT:1" "$output"
108
+
109
+ # === Test: Design docs (no Batch headers) are skipped ===
110
+ rm -rf "$WORK/plans"
111
+ create_plan "2026-01-01-design.md" '# Design Doc
112
+
113
+ This is a design document, not a plan. No Batch headers.'
114
+ create_plan "2026-01-01-plan.md" '# Plan
115
+
116
+ ## Batch 1: Setup
117
+
118
+ ### Task 1: Do thing
119
+
120
+ Content.'
121
+
122
+ output=$(run_validator)
123
+ assert_contains "design doc skipped: PASS" "validate-plans: PASS" "$output"
124
+ assert_contains "design doc skipped: exit 0" "EXIT:0" "$output"
125
+
126
+ # === Test: Single file argument validates just that file ===
127
+ rm -rf "$WORK/plans"
128
+ create_plan "2026-01-01-good.md" '# Plan
129
+
130
+ ## Batch 1: Setup
131
+
132
+ ### Task 1: Do thing
133
+
134
+ Content.'
135
+
136
+ exit_code=0
137
+ output=$(bash "$VALIDATOR" "$WORK/plans/2026-01-01-good.md" 2>&1) || exit_code=$?
138
+ output="${output}
139
+ EXIT:${exit_code}"
140
+ assert_contains "single file arg: PASS" "validate-plans: PASS" "$output"
141
+ assert_contains "single file arg: exit 0" "EXIT:0" "$output"
142
+
143
+ # === Test: --warn exits 0 even with violations ===
144
+ rm -rf "$WORK/plans"
145
+ create_plan "2026-01-01-bad.md" '# Plan
146
+
147
+ ## Batch 1: Setup
148
+
149
+ No tasks here.'
150
+
151
+ output=$(run_validator --warn)
152
+ assert_contains "--warn: still reports violation" "has no tasks" "$output"
153
+ assert_contains "--warn: exits 0" "EXIT:0" "$output"
154
+
155
+ # === Test: --help exits 0 ===
156
+ output=$(run_validator --help)
157
+ assert_contains "--help: shows usage" "Usage:" "$output"
158
+ assert_contains "--help: exits 0" "EXIT:0" "$output"
159
+
160
+ # === Test: Task on next batch header line not counted for previous batch (#26) ===
161
+ # This tests the sed range fix — when a "### Task" line is the first line of
162
+ # the next batch (immediately after "## Batch N"), it must not be counted for
163
+ # the previous batch.
164
+ rm -rf "$WORK/plans"
165
+ create_plan "2026-01-01-adjacent.md" '# Plan
166
+
167
+ ## Batch 1: Setup
168
+
169
+ Some content but no tasks here.
170
+
171
+ ## Batch 2: Implementation
172
+
173
+ ### Task 1: The only task
174
+
175
+ Content.'
176
+
177
+ output=$(run_validator)
178
+ assert_contains "adjacent batch: batch 1 has no tasks" "Batch 1 has no tasks" "$output"
179
+ assert_contains "adjacent batch: FAIL" "FAIL" "$output"
180
+
181
+ # === Test: Missing plans directory fails ===
182
+ rm -rf "$WORK/plans"
183
+ output=$(PLANS_DIR="$WORK/nonexistent" bash "$VALIDATOR" 2>&1 || echo "EXIT:$?")
184
+ assert_contains "missing dir: error message" "plans directory not found" "$output"
185
+ assert_contains "missing dir: exit 1" "EXIT:1" "$output"
186
+
187
+ report_results
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bash
2
+ # Test validate-plugin.sh
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ source "$SCRIPT_DIR/test-helpers.sh"
7
+
8
+ VALIDATOR="$SCRIPT_DIR/../validate-plugin.sh"
9
+ WORK=$(mktemp -d)
10
+ trap 'rm -rf "$WORK"' EXIT
11
+
12
+ # Helper: create plugin files
13
+ create_plugin() {
14
+ local plugin_json="$1" marketplace_json="$2"
15
+ mkdir -p "$WORK/.claude-plugin"
16
+ echo "$plugin_json" > "$WORK/.claude-plugin/plugin.json"
17
+ echo "$marketplace_json" > "$WORK/.claude-plugin/marketplace.json"
18
+ }
19
+
20
+ # Helper: run validator against temp dir
21
+ run_validator() {
22
+ local exit_code=0
23
+ PLUGIN_DIR="$WORK/.claude-plugin" bash "$VALIDATOR" "$@" 2>&1 || exit_code=$?
24
+ echo "EXIT:$exit_code"
25
+ }
26
+
27
+ # === Test: Matching name and version passes ===
28
+ create_plugin \
29
+ '{"name":"my-toolkit","version":"1.0.0","description":"Test"}' \
30
+ '{"name":"my-toolkit","plugins":[{"name":"my-toolkit","version":"1.0.0"}]}'
31
+
32
+ output=$(run_validator)
33
+ assert_contains "matching: PASS" "validate-plugin: PASS" "$output"
34
+ assert_contains "matching: exit 0" "EXIT:0" "$output"
35
+
36
+ # === Test: Mismatched name fails ===
37
+ create_plugin \
38
+ '{"name":"toolkit-a","version":"1.0.0","description":"Test"}' \
39
+ '{"name":"toolkit-b","plugins":[{"name":"toolkit-b","version":"1.0.0"}]}'
40
+
41
+ output=$(run_validator)
42
+ assert_contains "name mismatch: reports violation" "name mismatch" "$output"
43
+ assert_contains "name mismatch: exit 1" "EXIT:1" "$output"
44
+
45
+ # === Test: Mismatched version fails ===
46
+ create_plugin \
47
+ '{"name":"my-toolkit","version":"1.0.0","description":"Test"}' \
48
+ '{"name":"my-toolkit","plugins":[{"name":"my-toolkit","version":"2.0.0"}]}'
49
+
50
+ output=$(run_validator)
51
+ assert_contains "version mismatch: reports violation" "version mismatch" "$output"
52
+ assert_contains "version mismatch: exit 1" "EXIT:1" "$output"
53
+
54
+ # === Test: Missing plugin.json fails ===
55
+ rm -rf "$WORK/.claude-plugin"
56
+ mkdir -p "$WORK/.claude-plugin"
57
+ echo '{"name":"x","plugins":[{"name":"x","version":"1.0.0"}]}' > "$WORK/.claude-plugin/marketplace.json"
58
+
59
+ output=$(run_validator)
60
+ assert_contains "missing plugin.json: error" "plugin.json not found" "$output"
61
+ assert_contains "missing plugin.json: exit 1" "EXIT:1" "$output"
62
+
63
+ # === Test: Missing marketplace.json fails ===
64
+ rm -rf "$WORK/.claude-plugin"
65
+ mkdir -p "$WORK/.claude-plugin"
66
+ echo '{"name":"x","version":"1.0.0"}' > "$WORK/.claude-plugin/plugin.json"
67
+
68
+ output=$(run_validator)
69
+ assert_contains "missing marketplace.json: error" "marketplace.json not found" "$output"
70
+ assert_contains "missing marketplace.json: exit 1" "EXIT:1" "$output"
71
+
72
+ # === Test: Invalid JSON in plugin.json fails ===
73
+ create_plugin '{invalid json' '{"name":"x","plugins":[{"name":"x","version":"1.0.0"}]}'
74
+
75
+ output=$(run_validator)
76
+ assert_contains "invalid plugin.json: error" "plugin.json is not valid JSON" "$output"
77
+ assert_contains "invalid plugin.json: exit 1" "EXIT:1" "$output"
78
+
79
+ # === Test: Invalid JSON in marketplace.json fails ===
80
+ create_plugin '{"name":"x","version":"1.0.0"}' '{invalid json'
81
+
82
+ output=$(run_validator)
83
+ assert_contains "invalid marketplace.json: error" "marketplace.json is not valid JSON" "$output"
84
+ assert_contains "invalid marketplace.json: exit 1" "EXIT:1" "$output"
85
+
86
+ # === Test: --warn exits 0 even with violations ===
87
+ create_plugin \
88
+ '{"name":"a","version":"1.0.0"}' \
89
+ '{"name":"b","plugins":[{"name":"b","version":"1.0.0"}]}'
90
+
91
+ output=$(run_validator --warn)
92
+ assert_contains "--warn: still reports violation" "name mismatch" "$output"
93
+ assert_contains "--warn: exits 0" "EXIT:0" "$output"
94
+
95
+ # === Test: --help exits 0 ===
96
+ output=$(run_validator --help)
97
+ assert_contains "--help: shows usage" "Usage:" "$output"
98
+ assert_contains "--help: exits 0" "EXIT:0" "$output"
99
+
100
+ # === Test: Missing plugin directory fails ===
101
+ rm -rf "$WORK/.claude-plugin"
102
+ output=$(PLUGIN_DIR="$WORK/nonexistent" bash "$VALIDATOR" 2>&1 || echo "EXIT:$?")
103
+ assert_contains "missing dir: error message" "plugin directory not found" "$output"
104
+ assert_contains "missing dir: exit 1" "EXIT:1" "$output"
105
+
106
+ report_results