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.
- package/.claude-plugin/marketplace.json +22 -0
- package/.claude-plugin/plugin.json +13 -0
- package/LICENSE +21 -0
- package/Makefile +21 -0
- package/README.md +140 -0
- package/SECURITY.md +28 -0
- package/agents/bash-expert.md +113 -0
- package/agents/dependency-auditor.md +138 -0
- package/agents/integration-tester.md +120 -0
- package/agents/lesson-scanner.md +149 -0
- package/agents/python-expert.md +179 -0
- package/agents/service-monitor.md +141 -0
- package/agents/shell-expert.md +147 -0
- package/benchmarks/runner.sh +147 -0
- package/benchmarks/tasks/01-rest-endpoint/rubric.sh +29 -0
- package/benchmarks/tasks/01-rest-endpoint/task.md +17 -0
- package/benchmarks/tasks/02-refactor-module/task.md +8 -0
- package/benchmarks/tasks/03-fix-integration-bug/task.md +8 -0
- package/benchmarks/tasks/04-add-test-coverage/task.md +8 -0
- package/benchmarks/tasks/05-multi-file-feature/task.md +8 -0
- package/bin/act.js +238 -0
- package/commands/autocode.md +6 -0
- package/commands/cancel-ralph.md +18 -0
- package/commands/code-factory.md +53 -0
- package/commands/create-prd.md +55 -0
- package/commands/ralph-loop.md +18 -0
- package/commands/run-plan.md +117 -0
- package/commands/submit-lesson.md +122 -0
- package/docs/ARCHITECTURE.md +630 -0
- package/docs/CONTRIBUTING.md +125 -0
- package/docs/lessons/0001-bare-exception-swallowing.md +34 -0
- package/docs/lessons/0002-async-def-without-await.md +28 -0
- package/docs/lessons/0003-create-task-without-callback.md +28 -0
- package/docs/lessons/0004-hardcoded-test-counts.md +28 -0
- package/docs/lessons/0005-sqlite-without-closing.md +33 -0
- package/docs/lessons/0006-venv-pip-path.md +27 -0
- package/docs/lessons/0007-runner-state-self-rejection.md +35 -0
- package/docs/lessons/0008-quality-gate-blind-spot.md +33 -0
- package/docs/lessons/0009-parser-overcount-empty-batches.md +36 -0
- package/docs/lessons/0010-local-outside-function-bash.md +33 -0
- package/docs/lessons/0011-batch-tests-for-unimplemented-code.md +36 -0
- package/docs/lessons/0012-api-markdown-unescaped-chars.md +33 -0
- package/docs/lessons/0013-export-prefix-env-parsing.md +33 -0
- package/docs/lessons/0014-decorator-registry-import-side-effect.md +43 -0
- package/docs/lessons/0015-frontend-backend-schema-drift.md +43 -0
- package/docs/lessons/0016-event-driven-cold-start-seeding.md +44 -0
- package/docs/lessons/0017-copy-paste-logic-diverges.md +43 -0
- package/docs/lessons/0018-layer-passes-pipeline-broken.md +45 -0
- package/docs/lessons/0019-systemd-envfile-ignores-export.md +41 -0
- package/docs/lessons/0020-persist-state-incrementally.md +44 -0
- package/docs/lessons/0021-dual-axis-testing.md +48 -0
- package/docs/lessons/0022-jsx-factory-shadowing.md +43 -0
- package/docs/lessons/0023-static-analysis-spiral.md +51 -0
- package/docs/lessons/0024-shared-pipeline-implementation.md +55 -0
- package/docs/lessons/0025-defense-in-depth-all-entry-points.md +65 -0
- package/docs/lessons/0026-linter-no-rules-false-enforcement.md +54 -0
- package/docs/lessons/0027-jsx-silent-prop-drop.md +64 -0
- package/docs/lessons/0028-no-infrastructure-in-client-code.md +49 -0
- package/docs/lessons/0029-never-write-secrets-to-files.md +61 -0
- package/docs/lessons/0030-cache-merge-not-replace.md +62 -0
- package/docs/lessons/0031-verify-units-at-boundaries.md +66 -0
- package/docs/lessons/0032-module-lifecycle-subscribe-unsubscribe.md +89 -0
- package/docs/lessons/0033-async-iteration-mutable-snapshot.md +72 -0
- package/docs/lessons/0034-caller-missing-await-silent-discard.md +65 -0
- package/docs/lessons/0035-duplicate-registration-silent-overwrite.md +85 -0
- package/docs/lessons/0036-websocket-dirty-disconnect.md +33 -0
- package/docs/lessons/0037-parallel-agents-worktree-corruption.md +31 -0
- package/docs/lessons/0038-subscribe-no-stored-ref.md +36 -0
- package/docs/lessons/0039-fallback-or-default-hides-bugs.md +34 -0
- package/docs/lessons/0040-event-firehose-filter-first.md +36 -0
- package/docs/lessons/0041-ambiguous-base-dir-path-nesting.md +32 -0
- package/docs/lessons/0042-spec-compliance-insufficient.md +36 -0
- package/docs/lessons/0043-exact-count-extensible-collections.md +32 -0
- package/docs/lessons/0044-relative-file-deps-worktree.md +39 -0
- package/docs/lessons/0045-iterative-design-improvement.md +33 -0
- package/docs/lessons/0046-plan-assertion-math-bugs.md +38 -0
- package/docs/lessons/0047-pytest-single-threaded-default.md +37 -0
- package/docs/lessons/0048-integration-wiring-batch.md +40 -0
- package/docs/lessons/0049-ab-verification.md +41 -0
- package/docs/lessons/0050-editing-sourced-files-during-execution.md +33 -0
- package/docs/lessons/0051-infrastructure-fixes-cant-self-heal.md +30 -0
- package/docs/lessons/0052-uncommitted-changes-poison-quality-gates.md +31 -0
- package/docs/lessons/0053-jq-compact-flag-inconsistency.md +31 -0
- package/docs/lessons/0054-parser-matches-inside-code-blocks.md +30 -0
- package/docs/lessons/0055-agents-compensate-for-garbled-prompts.md +31 -0
- package/docs/lessons/0056-grep-count-exit-code-on-zero.md +42 -0
- package/docs/lessons/0057-new-artifacts-break-git-clean-gates.md +42 -0
- package/docs/lessons/0058-dead-config-keys-never-consumed.md +49 -0
- package/docs/lessons/0059-contract-test-shared-structures.md +53 -0
- package/docs/lessons/0060-set-e-silent-death-in-runners.md +53 -0
- package/docs/lessons/0061-context-injection-dirty-state.md +50 -0
- package/docs/lessons/0062-sibling-bug-neighborhood-scan.md +29 -0
- package/docs/lessons/0063-one-flag-two-lifetimes.md +31 -0
- package/docs/lessons/0064-test-passes-wrong-reason.md +31 -0
- package/docs/lessons/0065-pipefail-grep-count-double-output.md +39 -0
- package/docs/lessons/0066-local-keyword-outside-function.md +37 -0
- package/docs/lessons/0067-stdin-hang-non-interactive-shell.md +36 -0
- package/docs/lessons/0068-agent-builds-wrong-thing-correctly.md +31 -0
- package/docs/lessons/0069-plan-quality-dominates-execution.md +30 -0
- package/docs/lessons/0070-spec-echo-back-prevents-drift.md +31 -0
- package/docs/lessons/0071-positive-instructions-outperform-negative.md +30 -0
- package/docs/lessons/0072-lost-in-the-middle-context-placement.md +30 -0
- package/docs/lessons/0073-unscoped-lessons-cause-false-positives.md +30 -0
- package/docs/lessons/0074-stale-context-injection-wrong-batch.md +32 -0
- package/docs/lessons/0075-research-artifacts-must-persist.md +32 -0
- package/docs/lessons/0076-wrong-decomposition-contaminates-downstream.md +30 -0
- package/docs/lessons/0077-cherry-pick-merges-need-manual-resolution.md +30 -0
- package/docs/lessons/0078-static-review-without-live-test.md +30 -0
- package/docs/lessons/0079-integration-wiring-batch-required.md +32 -0
- package/docs/lessons/FRAMEWORK.md +161 -0
- package/docs/lessons/SUMMARY.md +201 -0
- package/docs/lessons/TEMPLATE.md +85 -0
- package/docs/plans/2026-02-21-code-factory-v2-design.md +204 -0
- package/docs/plans/2026-02-21-code-factory-v2-implementation-plan.md +2189 -0
- package/docs/plans/2026-02-21-code-factory-v2-phase4-design.md +537 -0
- package/docs/plans/2026-02-21-code-factory-v2-phase4-implementation-plan.md +2012 -0
- package/docs/plans/2026-02-21-hardening-pass-design.md +108 -0
- package/docs/plans/2026-02-21-hardening-pass-plan.md +1378 -0
- package/docs/plans/2026-02-21-mab-research-report.md +406 -0
- package/docs/plans/2026-02-21-marketplace-restructure-design.md +240 -0
- package/docs/plans/2026-02-21-marketplace-restructure-plan.md +832 -0
- package/docs/plans/2026-02-21-phase4-completion-plan.md +697 -0
- package/docs/plans/2026-02-21-validator-suite-design.md +148 -0
- package/docs/plans/2026-02-21-validator-suite-plan.md +540 -0
- package/docs/plans/2026-02-22-mab-research-round2.md +556 -0
- package/docs/plans/2026-02-22-mab-run-design.md +462 -0
- package/docs/plans/2026-02-22-mab-run-plan.md +2046 -0
- package/docs/plans/2026-02-22-operations-design-methodology-research.md +681 -0
- package/docs/plans/2026-02-22-research-agent-failure-taxonomy.md +532 -0
- package/docs/plans/2026-02-22-research-code-guideline-policies.md +886 -0
- package/docs/plans/2026-02-22-research-codebase-audit-refactoring.md +908 -0
- package/docs/plans/2026-02-22-research-coding-standards-documentation.md +541 -0
- package/docs/plans/2026-02-22-research-competitive-landscape.md +687 -0
- package/docs/plans/2026-02-22-research-comprehensive-testing.md +1076 -0
- package/docs/plans/2026-02-22-research-context-utilization.md +459 -0
- package/docs/plans/2026-02-22-research-cost-quality-tradeoff.md +548 -0
- package/docs/plans/2026-02-22-research-lesson-transferability.md +508 -0
- package/docs/plans/2026-02-22-research-multi-agent-coordination.md +312 -0
- package/docs/plans/2026-02-22-research-phase-integration.md +602 -0
- package/docs/plans/2026-02-22-research-plan-quality.md +428 -0
- package/docs/plans/2026-02-22-research-prompt-engineering.md +558 -0
- package/docs/plans/2026-02-22-research-unconventional-perspectives.md +528 -0
- package/docs/plans/2026-02-22-research-user-adoption.md +638 -0
- package/docs/plans/2026-02-22-research-verification-effectiveness.md +433 -0
- package/docs/plans/2026-02-23-agent-suite-design.md +299 -0
- package/docs/plans/2026-02-23-agent-suite-plan.md +578 -0
- package/docs/plans/2026-02-23-phase3-cost-infrastructure-design.md +148 -0
- package/docs/plans/2026-02-23-phase3-cost-infrastructure-plan.md +1062 -0
- package/docs/plans/2026-02-23-research-bash-expert-agent.md +543 -0
- package/docs/plans/2026-02-23-research-dependency-auditor-agent.md +564 -0
- package/docs/plans/2026-02-23-research-improving-existing-agents.md +503 -0
- package/docs/plans/2026-02-23-research-integration-tester-agent.md +454 -0
- package/docs/plans/2026-02-23-research-python-expert-agent.md +429 -0
- package/docs/plans/2026-02-23-research-service-monitor-agent.md +425 -0
- package/docs/plans/2026-02-23-research-shell-expert-agent.md +533 -0
- package/docs/plans/2026-02-23-roadmap-to-completion.md +530 -0
- package/docs/plans/2026-02-24-headless-module-split-design.md +98 -0
- package/docs/plans/2026-02-24-headless-module-split.md +443 -0
- package/docs/plans/2026-02-24-lesson-scope-metadata-design.md +228 -0
- package/docs/plans/2026-02-24-lesson-scope-metadata-plan.md +968 -0
- package/docs/plans/2026-02-24-npm-packaging-design.md +841 -0
- package/docs/plans/2026-02-24-npm-packaging-plan.md +1965 -0
- package/docs/plans/audit-findings.md +186 -0
- package/docs/telegram-notification-format.md +98 -0
- package/examples/example-plan.md +51 -0
- package/examples/example-prd.json +72 -0
- package/examples/example-roadmap.md +33 -0
- package/examples/quickstart-plan.md +63 -0
- package/hooks/hooks.json +26 -0
- package/hooks/setup-symlinks.sh +48 -0
- package/hooks/stop-hook.sh +135 -0
- package/package.json +47 -0
- package/policies/bash.md +71 -0
- package/policies/python.md +71 -0
- package/policies/testing.md +61 -0
- package/policies/universal.md +60 -0
- package/scripts/analyze-report.sh +97 -0
- package/scripts/architecture-map.sh +145 -0
- package/scripts/auto-compound.sh +273 -0
- package/scripts/batch-audit.sh +42 -0
- package/scripts/batch-test.sh +101 -0
- package/scripts/entropy-audit.sh +221 -0
- package/scripts/failure-digest.sh +51 -0
- package/scripts/generate-ast-rules.sh +96 -0
- package/scripts/init.sh +112 -0
- package/scripts/lesson-check.sh +428 -0
- package/scripts/lib/common.sh +61 -0
- package/scripts/lib/cost-tracking.sh +153 -0
- package/scripts/lib/ollama.sh +60 -0
- package/scripts/lib/progress-writer.sh +128 -0
- package/scripts/lib/run-plan-context.sh +215 -0
- package/scripts/lib/run-plan-echo-back.sh +231 -0
- package/scripts/lib/run-plan-headless.sh +396 -0
- package/scripts/lib/run-plan-notify.sh +57 -0
- package/scripts/lib/run-plan-parser.sh +81 -0
- package/scripts/lib/run-plan-prompt.sh +215 -0
- package/scripts/lib/run-plan-quality-gate.sh +132 -0
- package/scripts/lib/run-plan-routing.sh +315 -0
- package/scripts/lib/run-plan-sampling.sh +170 -0
- package/scripts/lib/run-plan-scoring.sh +146 -0
- package/scripts/lib/run-plan-state.sh +142 -0
- package/scripts/lib/run-plan-team.sh +199 -0
- package/scripts/lib/telegram.sh +54 -0
- package/scripts/lib/thompson-sampling.sh +176 -0
- package/scripts/license-check.sh +74 -0
- package/scripts/mab-run.sh +575 -0
- package/scripts/module-size-check.sh +146 -0
- package/scripts/patterns/async-no-await.yml +5 -0
- package/scripts/patterns/bare-except.yml +6 -0
- package/scripts/patterns/empty-catch.yml +6 -0
- package/scripts/patterns/hardcoded-localhost.yml +9 -0
- package/scripts/patterns/retry-loop-no-backoff.yml +12 -0
- package/scripts/pipeline-status.sh +197 -0
- package/scripts/policy-check.sh +226 -0
- package/scripts/prior-art-search.sh +133 -0
- package/scripts/promote-mab-lessons.sh +126 -0
- package/scripts/prompts/agent-a-superpowers.md +29 -0
- package/scripts/prompts/agent-b-ralph.md +29 -0
- package/scripts/prompts/judge-agent.md +61 -0
- package/scripts/prompts/planner-agent.md +44 -0
- package/scripts/pull-community-lessons.sh +90 -0
- package/scripts/quality-gate.sh +266 -0
- package/scripts/research-gate.sh +90 -0
- package/scripts/run-plan.sh +329 -0
- package/scripts/scope-infer.sh +159 -0
- package/scripts/setup-ralph-loop.sh +155 -0
- package/scripts/telemetry.sh +230 -0
- package/scripts/tests/run-all-tests.sh +52 -0
- package/scripts/tests/test-act-cli.sh +46 -0
- package/scripts/tests/test-agents-md.sh +87 -0
- package/scripts/tests/test-analyze-report.sh +114 -0
- package/scripts/tests/test-architecture-map.sh +89 -0
- package/scripts/tests/test-auto-compound.sh +169 -0
- package/scripts/tests/test-batch-test.sh +65 -0
- package/scripts/tests/test-benchmark-runner.sh +25 -0
- package/scripts/tests/test-common.sh +168 -0
- package/scripts/tests/test-cost-tracking.sh +158 -0
- package/scripts/tests/test-echo-back.sh +180 -0
- package/scripts/tests/test-entropy-audit.sh +146 -0
- package/scripts/tests/test-failure-digest.sh +66 -0
- package/scripts/tests/test-generate-ast-rules.sh +145 -0
- package/scripts/tests/test-helpers.sh +82 -0
- package/scripts/tests/test-init.sh +47 -0
- package/scripts/tests/test-lesson-check.sh +278 -0
- package/scripts/tests/test-lesson-local.sh +55 -0
- package/scripts/tests/test-license-check.sh +109 -0
- package/scripts/tests/test-mab-run.sh +182 -0
- package/scripts/tests/test-ollama-lib.sh +49 -0
- package/scripts/tests/test-ollama.sh +60 -0
- package/scripts/tests/test-pipeline-status.sh +198 -0
- package/scripts/tests/test-policy-check.sh +124 -0
- package/scripts/tests/test-prior-art-search.sh +96 -0
- package/scripts/tests/test-progress-writer.sh +140 -0
- package/scripts/tests/test-promote-mab-lessons.sh +110 -0
- package/scripts/tests/test-pull-community-lessons.sh +149 -0
- package/scripts/tests/test-quality-gate.sh +241 -0
- package/scripts/tests/test-research-gate.sh +132 -0
- package/scripts/tests/test-run-plan-cli.sh +86 -0
- package/scripts/tests/test-run-plan-context.sh +305 -0
- package/scripts/tests/test-run-plan-e2e.sh +153 -0
- package/scripts/tests/test-run-plan-headless.sh +424 -0
- package/scripts/tests/test-run-plan-notify.sh +124 -0
- package/scripts/tests/test-run-plan-parser.sh +217 -0
- package/scripts/tests/test-run-plan-prompt.sh +254 -0
- package/scripts/tests/test-run-plan-quality-gate.sh +222 -0
- package/scripts/tests/test-run-plan-routing.sh +178 -0
- package/scripts/tests/test-run-plan-scoring.sh +148 -0
- package/scripts/tests/test-run-plan-state.sh +261 -0
- package/scripts/tests/test-run-plan-team.sh +157 -0
- package/scripts/tests/test-scope-infer.sh +150 -0
- package/scripts/tests/test-setup-ralph-loop.sh +63 -0
- package/scripts/tests/test-telegram-env.sh +38 -0
- package/scripts/tests/test-telegram.sh +121 -0
- package/scripts/tests/test-telemetry.sh +46 -0
- package/scripts/tests/test-thompson-sampling.sh +139 -0
- package/scripts/tests/test-validate-all.sh +60 -0
- package/scripts/tests/test-validate-commands.sh +89 -0
- package/scripts/tests/test-validate-hooks.sh +98 -0
- package/scripts/tests/test-validate-lessons.sh +150 -0
- package/scripts/tests/test-validate-plan-quality.sh +235 -0
- package/scripts/tests/test-validate-plans.sh +187 -0
- package/scripts/tests/test-validate-plugin.sh +106 -0
- package/scripts/tests/test-validate-prd.sh +184 -0
- package/scripts/tests/test-validate-skills.sh +134 -0
- package/scripts/validate-all.sh +57 -0
- package/scripts/validate-commands.sh +67 -0
- package/scripts/validate-hooks.sh +89 -0
- package/scripts/validate-lessons.sh +98 -0
- package/scripts/validate-plan-quality.sh +369 -0
- package/scripts/validate-plans.sh +120 -0
- package/scripts/validate-plugin.sh +86 -0
- package/scripts/validate-policies.sh +42 -0
- package/scripts/validate-prd.sh +118 -0
- package/scripts/validate-skills.sh +96 -0
- package/skills/autocode/SKILL.md +285 -0
- package/skills/autocode/ab-verification.md +51 -0
- package/skills/autocode/code-quality-standards.md +37 -0
- package/skills/autocode/competitive-mode.md +364 -0
- package/skills/brainstorming/SKILL.md +97 -0
- package/skills/capture-lesson/SKILL.md +187 -0
- package/skills/check-lessons/SKILL.md +116 -0
- package/skills/dispatching-parallel-agents/SKILL.md +110 -0
- package/skills/executing-plans/SKILL.md +85 -0
- package/skills/finishing-a-development-branch/SKILL.md +201 -0
- package/skills/receiving-code-review/SKILL.md +72 -0
- package/skills/requesting-code-review/SKILL.md +59 -0
- package/skills/requesting-code-review/code-reviewer.md +82 -0
- package/skills/research/SKILL.md +145 -0
- package/skills/roadmap/SKILL.md +115 -0
- package/skills/subagent-driven-development/SKILL.md +98 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +18 -0
- package/skills/subagent-driven-development/implementer-prompt.md +73 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +57 -0
- package/skills/systematic-debugging/SKILL.md +134 -0
- package/skills/systematic-debugging/condition-based-waiting.md +64 -0
- package/skills/systematic-debugging/defense-in-depth.md +32 -0
- package/skills/systematic-debugging/root-cause-tracing.md +55 -0
- package/skills/test-driven-development/SKILL.md +167 -0
- package/skills/using-git-worktrees/SKILL.md +219 -0
- package/skills/using-superpowers/SKILL.md +54 -0
- package/skills/verification-before-completion/SKILL.md +140 -0
- package/skills/verify/SKILL.md +82 -0
- package/skills/writing-plans/SKILL.md +128 -0
- 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
|