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,241 @@
1
+ #!/usr/bin/env bash
2
+ # Test quality-gate.sh — verifies refactored behavior using common.sh
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ QG="$SCRIPT_DIR/../quality-gate.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"
16
+ echo " expected: $expected"
17
+ echo " actual: $actual"
18
+ FAILURES=$((FAILURES + 1))
19
+ else
20
+ echo "PASS: $desc"
21
+ fi
22
+ }
23
+
24
+ assert_exit() {
25
+ local desc="$1" expected_exit="$2"
26
+ shift 2
27
+ local actual_exit=0
28
+ "$@" >/dev/null 2>&1 || actual_exit=$?
29
+ TESTS=$((TESTS + 1))
30
+ if [[ "$expected_exit" != "$actual_exit" ]]; then
31
+ echo "FAIL: $desc"
32
+ echo " expected exit: $expected_exit"
33
+ echo " actual exit: $actual_exit"
34
+ FAILURES=$((FAILURES + 1))
35
+ else
36
+ echo "PASS: $desc"
37
+ fi
38
+ }
39
+
40
+ assert_contains() {
41
+ local desc="$1" needle="$2" haystack="$3"
42
+ TESTS=$((TESTS + 1))
43
+ if echo "$haystack" | grep -qF "$needle"; then
44
+ echo "PASS: $desc"
45
+ else
46
+ echo "FAIL: $desc"
47
+ echo " expected to contain: $needle"
48
+ echo " in: $(echo "$haystack" | head -5)"
49
+ FAILURES=$((FAILURES + 1))
50
+ fi
51
+ }
52
+
53
+ WORK=$(mktemp -d)
54
+ trap 'rm -rf "$WORK"' EXIT
55
+
56
+ # === CLI tests ===
57
+
58
+ assert_exit "no args exits 1" 1 bash "$QG"
59
+ assert_exit "--help exits 0" 0 bash "$QG" --help
60
+ assert_exit "nonexistent dir exits 1" 1 bash "$QG" --project-root /nonexistent/path
61
+
62
+ # === Sources common.sh ===
63
+
64
+ # Check that the script sources common.sh (grep for the source line)
65
+ TESTS=$((TESTS + 1))
66
+ if grep -q 'source.*lib/common.sh' "$QG"; then
67
+ echo "PASS: quality-gate.sh sources lib/common.sh"
68
+ else
69
+ echo "FAIL: quality-gate.sh sources lib/common.sh"
70
+ echo " expected: source line for lib/common.sh"
71
+ FAILURES=$((FAILURES + 1))
72
+ fi
73
+
74
+ # === Python project detection via detect_project_type ===
75
+
76
+ # Create a minimal Python project with no actual test suite
77
+ # (so the test suite step will run but fail — we just care about detection)
78
+ mkdir -p "$WORK/py-proj"
79
+ touch "$WORK/py-proj/pyproject.toml"
80
+ # Create a fake .venv/bin/python that exits 0
81
+ mkdir -p "$WORK/py-proj/.venv/bin"
82
+ cat > "$WORK/py-proj/.venv/bin/python" <<'FAKE'
83
+ #!/bin/bash
84
+ echo "1 passed"
85
+ exit 0
86
+ FAKE
87
+ chmod +x "$WORK/py-proj/.venv/bin/python"
88
+
89
+ # Run quality-gate on the python project — lesson-check will be skipped (no git)
90
+ output=$(bash "$QG" --project-root "$WORK/py-proj" 2>&1) || true
91
+ assert_contains "detects pytest project" "Detected: pytest project" "$output"
92
+
93
+ # === Node project detection ===
94
+
95
+ mkdir -p "$WORK/node-proj"
96
+ echo '{"name":"test","scripts":{"test":"echo ok"}}' > "$WORK/node-proj/package.json"
97
+ output=$(bash "$QG" --project-root "$WORK/node-proj" 2>&1) || true
98
+ assert_contains "detects npm project" "Detected: npm project" "$output"
99
+
100
+ # === Lint check output (Python project with ruff) ===
101
+
102
+ output=$(bash "$QG" --project-root "$WORK/py-proj" 2>&1) || true
103
+ assert_contains "lint check section present" "Lint Check" "$output"
104
+
105
+ # === Lint check output (Node project — no eslint config → skipped) ===
106
+
107
+ output=$(bash "$QG" --project-root "$WORK/node-proj" 2>&1) || true
108
+ assert_contains "node lint skipped without config" "No eslint config found" "$output"
109
+
110
+ # === --quick flag skips lint ===
111
+
112
+ output=$(bash "$QG" --project-root "$WORK/py-proj" --quick 2>&1) || true
113
+ TESTS=$((TESTS + 1))
114
+ if echo "$output" | grep -qF "Lint Check"; then
115
+ echo "FAIL: --quick skips lint check"
116
+ echo " Lint Check header should not appear with --quick"
117
+ FAILURES=$((FAILURES + 1))
118
+ else
119
+ echo "PASS: --quick skips lint check"
120
+ fi
121
+ assert_contains "--quick still runs tests" "Test Suite" "$output"
122
+ assert_contains "--quick still runs memory" "Memory Check" "$output"
123
+
124
+ # === --with-license flag adds license check ===
125
+
126
+ output=$(bash "$QG" --project-root "$WORK/py-proj" --with-license 2>&1) || true
127
+ assert_contains "--with-license runs license check" "License Check" "$output"
128
+
129
+ # === without --with-license, no license check ===
130
+
131
+ output=$(bash "$QG" --project-root "$WORK/py-proj" 2>&1) || true
132
+ TESTS=$((TESTS + 1))
133
+ # License Check should NOT appear in the quality-gate section headers
134
+ # (it may appear in lesson check output, so check for the specific gate header)
135
+ if echo "$output" | grep -qF "Quality Gate: License Check"; then
136
+ echo "FAIL: no license check without --with-license"
137
+ FAILURES=$((FAILURES + 1))
138
+ else
139
+ echo "PASS: no license check without --with-license"
140
+ fi
141
+
142
+ # === --quick and --with-license combined ===
143
+
144
+ output=$(bash "$QG" --project-root "$WORK/py-proj" --quick --with-license 2>&1) || true
145
+ TESTS=$((TESTS + 1))
146
+ if echo "$output" | grep -qF "Lint Check"; then
147
+ echo "FAIL: --quick --with-license skips lint"
148
+ FAILURES=$((FAILURES + 1))
149
+ else
150
+ echo "PASS: --quick --with-license skips lint"
151
+ fi
152
+ assert_contains "--quick --with-license keeps license" "License Check" "$output"
153
+
154
+ # === Memory check output ===
155
+
156
+ output=$(bash "$QG" --project-root "$WORK/py-proj" 2>&1) || true
157
+ # Should contain either "Memory OK" or "WARNING: Low memory" or "skipped"
158
+ TESTS=$((TESTS + 1))
159
+ if echo "$output" | grep -qE "(Memory OK|WARNING.*memory|WARNING.*Consider|Memory check skipped)"; then
160
+ echo "PASS: memory check runs"
161
+ else
162
+ echo "FAIL: memory check runs"
163
+ echo " expected memory check output"
164
+ echo " got: $output"
165
+ FAILURES=$((FAILURES + 1))
166
+ fi
167
+
168
+ # Memory display should use decimal GB (e.g., "3.9G") not truncated integer
169
+ TESTS=$((TESTS + 1))
170
+ if echo "$output" | grep -qE 'Memory OK \([0-9]+\.[0-9]+G'; then
171
+ echo "PASS: memory display uses decimal GB (MB-based, not truncated)"
172
+ else
173
+ # On systems where free is unavailable, this is expected to skip
174
+ if echo "$output" | grep -qF "Memory check skipped"; then
175
+ echo "PASS: memory display skipped (free unavailable — acceptable)"
176
+ else
177
+ echo "FAIL: memory display should show decimal GB (e.g., 3.9G)"
178
+ echo " got: $(echo "$output" | grep -i memory)"
179
+ FAILURES=$((FAILURES + 1))
180
+ fi
181
+ fi
182
+
183
+ # quality-gate.sh should not use free -g (only free -m via common.sh)
184
+ TESTS=$((TESTS + 1))
185
+ if grep -q 'free -g' "$QG"; then
186
+ echo "FAIL: quality-gate.sh should not use free -g (use free -m)"
187
+ FAILURES=$((FAILURES + 1))
188
+ else
189
+ echo "PASS: quality-gate.sh does not use free -g"
190
+ fi
191
+
192
+ # === Word-splitting fix (#5): changed_files passed to lesson-check via array ===
193
+
194
+ TESTS=$((TESTS + 1))
195
+ # Should use readarray and "${changed_array[@]}" — not bare $changed_files
196
+ if grep -q 'readarray.*changed_array' "$QG" && grep -q '"${changed_array\[@\]}"' "$QG"; then
197
+ echo "PASS: quality-gate passes files to lesson-check via array (no word-splitting, bug #5)"
198
+ else
199
+ echo "FAIL: quality-gate should use readarray + \${changed_array[@]} for lesson-check args (bug #5)"
200
+ FAILURES=$((FAILURES + 1))
201
+ fi
202
+
203
+ # The old unquoted $changed_files pattern must not be present
204
+ TESTS=$((TESTS + 1))
205
+ # Strip comment lines and look for the old unquoted expansion used as args
206
+ if grep -v '^\s*#' "$QG" | grep -q 'lesson-check.sh \$changed_files\b'; then
207
+ echo "FAIL: quality-gate still passes unquoted \$changed_files to lesson-check (bug #5)"
208
+ FAILURES=$((FAILURES + 1))
209
+ else
210
+ echo "PASS: quality-gate does not pass unquoted \$changed_files to lesson-check"
211
+ fi
212
+
213
+ # === ast-grep section present in full mode (advisory, doesn't fail gate) ===
214
+
215
+ output=$(bash "$QG" --project-root "$WORK/py-proj" 2>&1) || true
216
+ TESTS=$((TESTS + 1))
217
+ if echo "$output" | grep -qiE "structural|ast-grep"; then
218
+ echo "PASS: ast-grep section present in full mode"
219
+ else
220
+ echo "FAIL: ast-grep section should be present in full mode"
221
+ FAILURES=$((FAILURES + 1))
222
+ fi
223
+
224
+ # ast-grep section should be skipped in --quick mode
225
+ output=$(bash "$QG" --project-root "$WORK/py-proj" --quick 2>&1) || true
226
+ TESTS=$((TESTS + 1))
227
+ if echo "$output" | grep -qF "Structural Analysis"; then
228
+ echo "FAIL: --quick should skip ast-grep structural analysis"
229
+ FAILURES=$((FAILURES + 1))
230
+ else
231
+ echo "PASS: --quick skips ast-grep structural analysis"
232
+ fi
233
+
234
+ # === Summary ===
235
+ echo ""
236
+ echo "Results: $((TESTS - FAILURES))/$TESTS passed"
237
+ if [[ $FAILURES -gt 0 ]]; then
238
+ echo "FAILURES: $FAILURES"
239
+ exit 1
240
+ fi
241
+ echo "ALL PASSED"
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env bash
2
+ # Tests for research-gate.sh
3
+
4
+ set -euo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ GATE="$SCRIPT_DIR/../research-gate.sh"
8
+ PASS=0 FAIL=0 TOTAL=0
9
+
10
+ assert() {
11
+ local desc="$1" expected="$2" actual="$3"
12
+ TOTAL=$((TOTAL + 1))
13
+ if [[ "$expected" == "$actual" ]]; then
14
+ echo "PASS: $desc"
15
+ PASS=$((PASS + 1))
16
+ else
17
+ echo "FAIL: $desc (expected=$expected, actual=$actual)"
18
+ FAIL=$((FAIL + 1))
19
+ fi
20
+ }
21
+
22
+ tmpdir=$(mktemp -d)
23
+ trap 'rm -rf "$tmpdir"' EXIT
24
+
25
+ # Test 1: No blocking issues → exit 0
26
+ cat > "$tmpdir/clear.json" <<'EOF'
27
+ {
28
+ "feature": "test-feature",
29
+ "blocking_issues": [],
30
+ "warnings": [],
31
+ "confidence_ratings": {"approach": "high"}
32
+ }
33
+ EOF
34
+ output=$("$GATE" "$tmpdir/clear.json" 2>&1) || true
35
+ exit_code=$?
36
+ assert "no blockers: exit 0" "0" "$exit_code"
37
+ echo "$output" | grep -q "clear"
38
+ assert "no blockers: says clear" "0" "$?"
39
+
40
+ # Test 2: All resolved blocking issues → exit 0
41
+ cat > "$tmpdir/resolved.json" <<'EOF'
42
+ {
43
+ "feature": "test-feature",
44
+ "blocking_issues": [
45
+ {"issue": "missing dep", "resolved": true, "resolution": "installed"}
46
+ ],
47
+ "warnings": []
48
+ }
49
+ EOF
50
+ exit_code=0
51
+ "$GATE" "$tmpdir/resolved.json" > /dev/null 2>&1 || exit_code=$?
52
+ assert "resolved blockers: exit 0" "0" "$exit_code"
53
+
54
+ # Test 3: Unresolved blocking issues → exit 1
55
+ cat > "$tmpdir/blocked.json" <<'EOF'
56
+ {
57
+ "feature": "test-feature",
58
+ "blocking_issues": [
59
+ {"issue": "no viable auth library", "resolved": false, "resolution": "evaluate alternatives"}
60
+ ],
61
+ "warnings": []
62
+ }
63
+ EOF
64
+ exit_code=0
65
+ "$GATE" "$tmpdir/blocked.json" > /dev/null 2>&1 || exit_code=$?
66
+ assert "unresolved blockers: exit 1" "1" "$exit_code"
67
+
68
+ # Test 4: --force overrides blockers → exit 0
69
+ exit_code=0
70
+ output=$("$GATE" "$tmpdir/blocked.json" --force 2>&1) || exit_code=$?
71
+ assert "--force: exit 0" "0" "$exit_code"
72
+ assert "--force: shows warning" "1" "$(echo "$output" | grep -c "WARNING.*force")"
73
+
74
+ # Test 5: Missing file → exit 1
75
+ exit_code=0
76
+ "$GATE" "$tmpdir/nonexistent.json" > /dev/null 2>&1 || exit_code=$?
77
+ assert "missing file: exit 1" "1" "$exit_code"
78
+
79
+ # Test 6: Invalid JSON → exit 1
80
+ echo "not json" > "$tmpdir/invalid.json"
81
+ exit_code=0
82
+ "$GATE" "$tmpdir/invalid.json" > /dev/null 2>&1 || exit_code=$?
83
+ assert "invalid JSON: exit 1" "1" "$exit_code"
84
+
85
+ # Test 7: --help → exit 0
86
+ exit_code=0
87
+ output=$("$GATE" --help 2>&1) || exit_code=$?
88
+ assert "--help: exit 0" "0" "$exit_code"
89
+ assert "--help: shows usage" "1" "$(echo "$output" | grep -c "USAGE")"
90
+
91
+ # Test 8: Warnings present but no blockers → exit 0
92
+ cat > "$tmpdir/warnings.json" <<'EOF'
93
+ {
94
+ "feature": "test-feature",
95
+ "blocking_issues": [],
96
+ "warnings": ["deprecated API", "performance concern"]
97
+ }
98
+ EOF
99
+ exit_code=0
100
+ output=$("$GATE" "$tmpdir/warnings.json" 2>&1) || exit_code=$?
101
+ assert "warnings only: exit 0" "0" "$exit_code"
102
+ assert "warnings only: shows warning count" "1" "$(echo "$output" | grep -c "2 warning")"
103
+
104
+ # Test 9: No args → exit 1
105
+ exit_code=0
106
+ "$GATE" > /dev/null 2>&1 || exit_code=$?
107
+ assert "no args: exit 1" "1" "$exit_code"
108
+
109
+ # Test 10: Multiple unresolved + some resolved → exit 1
110
+ cat > "$tmpdir/mixed.json" <<'EOF'
111
+ {
112
+ "feature": "test-feature",
113
+ "blocking_issues": [
114
+ {"issue": "resolved one", "resolved": true},
115
+ {"issue": "still blocked", "resolved": false},
116
+ {"issue": "also blocked", "resolved": false}
117
+ ],
118
+ "warnings": []
119
+ }
120
+ EOF
121
+ exit_code=0
122
+ output=$("$GATE" "$tmpdir/mixed.json" 2>&1) || exit_code=$?
123
+ assert "mixed blockers: exit 1" "1" "$exit_code"
124
+ assert "mixed blockers: shows count 2" "1" "$(echo "$output" | grep -c "2 unresolved")"
125
+
126
+ echo ""
127
+ echo "Results: $PASS/$TOTAL passed"
128
+ if [[ $FAIL -gt 0 ]]; then
129
+ echo "FAILURES: $FAIL"
130
+ exit 1
131
+ fi
132
+ echo "ALL PASSED"
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env bash
2
+ # Test run-plan.sh CLI argument parsing and validation
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ RUN_PLAN="$SCRIPT_DIR/../run-plan.sh"
7
+
8
+ FAILURES=0
9
+ TESTS=0
10
+
11
+ assert_exit() {
12
+ local desc="$1" expected_exit="$2"
13
+ shift 2
14
+ local actual_exit=0
15
+ local output
16
+ output=$("$@" 2>&1) || actual_exit=$?
17
+ TESTS=$((TESTS + 1))
18
+ if [[ "$actual_exit" -ne "$expected_exit" ]]; then
19
+ echo "FAIL: $desc"
20
+ echo " expected exit: $expected_exit"
21
+ echo " actual exit: $actual_exit"
22
+ echo " output: ${output:0:300}"
23
+ FAILURES=$((FAILURES + 1))
24
+ else
25
+ echo "PASS: $desc"
26
+ fi
27
+ }
28
+
29
+ assert_output_contains() {
30
+ local desc="$1" needle="$2"
31
+ shift 2
32
+ local output
33
+ output=$("$@" 2>&1) || true
34
+ TESTS=$((TESTS + 1))
35
+ if [[ "$output" != *"$needle"* ]]; then
36
+ echo "FAIL: $desc"
37
+ echo " expected to contain: $needle"
38
+ echo " in: ${output:0:300}"
39
+ FAILURES=$((FAILURES + 1))
40
+ else
41
+ echo "PASS: $desc"
42
+ fi
43
+ }
44
+
45
+ # --- Test: --help exits 0 ---
46
+ assert_exit "--help exits 0" 0 "$RUN_PLAN" --help
47
+
48
+ # --- Test: -h exits 0 ---
49
+ assert_exit "-h exits 0" 0 "$RUN_PLAN" -h
50
+
51
+ # --- Test: no args exits 1 ---
52
+ assert_exit "no args exits 1" 1 "$RUN_PLAN"
53
+
54
+ # --- Test: nonexistent plan file exits 1 ---
55
+ assert_exit "nonexistent plan exits 1" 1 "$RUN_PLAN" /tmp/nonexistent-plan-file-abc123.md
56
+
57
+ # --- Test: help output mentions run-plan ---
58
+ assert_output_contains "help mentions run-plan" "run-plan" "$RUN_PLAN" --help
59
+
60
+ # --- Test: help output mentions --mode ---
61
+ assert_output_contains "help mentions --mode" "--mode" "$RUN_PLAN" --help
62
+
63
+ # --- Test: help output mentions headless ---
64
+ assert_output_contains "help mentions headless" "headless" "$RUN_PLAN" --help
65
+
66
+ # --- Test: help output mentions --resume ---
67
+ assert_output_contains "help mentions --resume" "--resume" "$RUN_PLAN" --help
68
+
69
+ # --- Test: help output mentions --on-failure ---
70
+ assert_output_contains "help mentions --on-failure" "--on-failure" "$RUN_PLAN" --help
71
+
72
+ # --- Test: help output mentions --mab ---
73
+ assert_output_contains "help mentions --mab" "--mab" "$RUN_PLAN" --help
74
+
75
+ # --- Test: --resume without state file exits 1 ---
76
+ TMPDIR_RESUME=$(mktemp -d)
77
+ trap 'rm -rf "$TMPDIR_RESUME"' EXIT
78
+ assert_exit "--resume without state file exits 1" 1 "$RUN_PLAN" --resume --worktree "$TMPDIR_RESUME"
79
+
80
+ echo ""
81
+ echo "Results: $((TESTS - FAILURES))/$TESTS passed"
82
+ if [[ $FAILURES -gt 0 ]]; then
83
+ echo "FAILURES: $FAILURES"
84
+ exit 1
85
+ fi
86
+ echo "ALL PASSED"