Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{
"name": "autodev",
"description": "Autonomous development workflow skills for coding agents",
"version": "6.1.0",
"version": "6.1.1",
"source": "./",
"author": {
"name": "Jon Langevin",
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "autodev",
"description": "Autonomous development workflow skills for coding agents: design, review, planning, execution, monitoring, and retrospectives",
"version": "6.1.0",
"version": "6.1.1",
"author": {
"name": "Jon Langevin",
"email": "jon@gocodealone.com"
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "autodev",
"displayName": "Autonomous Dev Kit",
"description": "Autonomous development workflow skills for coding agents",
"version": "6.1.0",
"version": "6.1.1",
"author": {
"name": "Jon Langevin",
"email": "jon@gocodealone.com"
Expand Down
21 changes: 21 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Autonomous Dev Kit Release Notes

## v6.1.1 — 2026-05-27

Cascade retro plugin-level follow-ups bundle.

- **adversarial-design-review**: added "plugin-loader runtime layout" + "config-validation schema rules" plan-phase bug classes
- **writing-plans / verification-before-completion**: added `golangci-lint run` pre-push verification for Go-repo PRs
- **scope-lock**: new `hooks/scope-lock-publish` sibling helper publishes a Locked plan + `.scope-lock` sidecar via a chore PR on the default branch (sidesteps the case where design+plan branch never merges)
- **scope-lock**: new `tests/cascade-preflight.sh` verifies each plugin repo's last Release workflow was green before cascade launch (catches ManifestProvider-class gaps cheap)
- **subagent-driven-development**: spec-reviewer for IaC-test-scenario PRs must now execute ≥1 scenario end-to-end before approving (`bash -n` insufficient)
- **RELEASE-NOTES**: backfilled missing v6.1.0 entry

All 5 follow-ups originate from `workflow-plugin-infra/docs/retros/2026-05-27-dns-provider-cascade-retro.md`.

## v6.1.0 — 2026-05-26

Session-scoped lock nag + claim/abandon helpers (PR #42 + #43).

- Anchor-match `Status: Locked` substring (eliminates substring-bug demoed live during PR review)
- Workspace-fallback removed when session has no attribution
- New helpers: `scope-lock-claim` (resume after restart), `scope-lock-abandon` (close never-completed lock)

## v6.0.5 (2026-05-26)

### Scope-lock completion cleanup
Expand Down
87 changes: 87 additions & 0 deletions hooks/scope-lock-publish
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/env bash
# hooks/scope-lock-publish
# Publishes a Locked plan + its .scope-lock sidecar to the default branch
# via a chore PR so the lock survives even when the design+plan feature
# branch never merges to main/master.
#
# Usage:
# hooks/scope-lock-publish docs/plans/example.md [--base main]
#
# Preconditions:
# - plan exists at given path AND is committed on the current branch
# (along with its .scope-lock sidecar)
# - plan Status: line shows "Locked YYYY-MM-DD..."
# - working tree clean (no staged/unstaged changes)
# - gh CLI authenticated
set -euo pipefail
[ "${SUPERPOWERS_HOOKS_DISABLE:-}" = "1" ] && exit 0

plan=""
base="main"
while [ "$#" -gt 0 ]; do
case "$1" in
--base) base="$2"; shift 2;;
--base=*) base="${1#--base=}"; shift;;
-h|--help) printf 'Usage: %s <plan-path> [--base <branch>]\n' "$0"; exit 0;;
*) if [ -z "$plan" ]; then plan="$1"; shift; else printf 'unexpected arg: %s\n' "$1" >&2; exit 2; fi;;
esac
done

[ -n "$plan" ] || { printf 'scope-lock-publish: missing plan path\n' >&2; exit 2; }
[ -f "$plan" ] || { printf 'scope-lock-publish: plan not found: %s\n' "$plan" >&2; exit 2; }
[ -f "${plan}.scope-lock" ] || { printf 'scope-lock-publish: lock file not found: %s.scope-lock — run scope-lock-apply first\n' "$plan" >&2; exit 2; }
grep -q '^\*\*Status:\*\* Locked ' "$plan" || { printf 'scope-lock-publish: plan Status: is not Locked — refuse\n' >&2; exit 2; }

# Committed-file guard (files must be tracked; clean-tree guard ensures
# they're also committed — staged-only files would fail the cached diff check).
git ls-files --error-unmatch "$plan" "${plan}.scope-lock" >/dev/null 2>&1 || {
printf 'scope-lock-publish: plan+lock must be committed on current branch before publishing\n' >&2
exit 2
}

git diff --quiet && git diff --cached --quiet || {
printf 'scope-lock-publish: working tree has uncommitted changes; stash or commit first\n' >&2
exit 2
}

orig_branch=$(git symbolic-ref --short HEAD 2>/dev/null) || {
printf 'scope-lock-publish: HEAD is detached; check out a branch first\n' >&2
exit 2
}

slug=$(basename "$plan" .md)
branch="chore/scope-lock-init-${slug}"

if git rev-parse --verify -q "refs/heads/$branch" >/dev/null 2>&1; then
printf 'scope-lock-publish: branch %s already exists locally; aborting\n' "$branch" >&2
exit 2
fi
if git ls-remote --exit-code origin "refs/heads/$branch" >/dev/null 2>&1; then
printf 'scope-lock-publish: branch %s already exists on origin; aborting\n' "$branch" >&2
exit 2
fi

src_ref=$(git rev-parse HEAD)

git fetch origin "$base" --quiet
git checkout -b "$branch" "origin/$base" --quiet

git checkout "$src_ref" -- "$plan" "${plan}.scope-lock"
git add "$plan" "${plan}.scope-lock"
git commit -m "chore: publish scope-lock for $slug" --quiet

git push -u origin "$branch" --quiet
pr_url=$(gh pr create --title "chore: publish scope-lock for $slug" \
--body "Auto-published by scope-lock-publish so the locked plan + sidecar land on $base before execution dispatches." \
--base "$base")
pr_num=$(printf '%s' "$pr_url" | grep -oE '[0-9]+$')

gh pr checks "$pr_num" --watch --fail-fast >/dev/null 2>&1 || true

# Switch back BEFORE delete-branch fires (cycle-4 fix: gh pr merge --delete-branch
# deletes local copy too; Git blocks deleting currently-checked-out branch).
git checkout "$orig_branch" --quiet
gh pr merge "$pr_num" --squash --admin --delete-branch
git branch -D "$branch" 2>/dev/null || true

printf 'scope-lock-publish: PR %s merged; plan + sidecar now on %s\n' "$pr_url" "$base"
2 changes: 2 additions & 0 deletions skills/adversarial-design-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ inherits the design's blast radius) and adds:
| **Missing rollback wiring** | The design specifies a rollback story (per the design-phase class above). Is it actually implemented in the plan as a task or step? Or is it a paragraph nobody is going to write code for? |
| **Missing integration proof** | For multi-component changes, does the plan include an end-to-end or integration verification that exercises the real boundary? If it only tests each component with mocks, flag it unless the design explicitly justified that as sufficient. |
| **Infrastructure verification mismatch** | For infrastructure-affecting changes, does the plan verify render/plan/apply/dry-run, secret wiring, migration order, rollback, and post-deploy health as appropriate? If not, flag it. |
| **Plugin-loader runtime layout** | Plans that spawn or load an external plugin process must build the binary in a layout the host's discovery code accepts. For wfctl: `$WFCTL_PLUGIN_DIR/<plugin-name>/<plugin-name>` + sibling `plugin.json`. Plans that `go build -o /tmp/single-binary` without the subdir + manifest sidecar will fail at runtime. |
| **Config-validation schema rules** | Plans that create new config files validated by a schema or CLI tool must satisfy that tool's invariants (e.g., for wfctl: `checkEntryPoints` requires ≥1 entry-point module like `http.server`/`scheduler.modular`/`messaging.broker`, OR a trigger/route/subscription/job/pipeline). Plans omitting required entry-point modules pass `bash -n` but fail schema validation at CI. |

## Process

Expand Down
2 changes: 2 additions & 0 deletions skills/scope-lock/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Manual invocation:
- **At execution checkpoints** (between tasks): verify reality still matches the lock.
- **At completion time** (before PR creation): assert manifest is fully satisfied.
- **At amendment time** (user-approved scope change, or bug/assumption backport that changes the manifest): record the amendment as an ADR, update the design/plan/manifest, re-stamp.
- **At cascade launch time** (before scope-lock-apply when the plan's PR Grouping table touches multiple plugin repos that will be re-tagged): run `tests/cascade-preflight.sh` to verify each repo's most-recent Release workflow on main was SUCCESS.

## The Scope Manifest

Expand Down Expand Up @@ -271,6 +272,7 @@ status line back to `Locked YYYY-MM-DDTHH:MM:SSZ` by hand and re-run
- `scope-lock-claim <plan>` — attribute an existing lock to the current session (resume after restart).
- `scope-lock-complete <plan> --evidence "<verification>"` — close the lock as Complete.
- `scope-lock-abandon <plan> --reason "<reason>"` — close the lock as Abandoned (no completion verification).
- `scope-lock-publish <plan> [--base <branch>]` — publish a Locked plan + its `.scope-lock` sidecar to the default branch via a chore PR. Use when the design+plan branch will not merge to main (e.g., separate per-PR feature branches consume the plan markdown but not the lock file).

The set of helper names that update `session-locks.jsonl` is centralized in
`hooks/pre-tool-scope-guard`'s `SESSION_LOCK_RECOGNIZED` variable; helpers and
Expand Down
6 changes: 6 additions & 0 deletions skills/subagent-driven-development/spec-reviewer-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ Task tool (general-purpose):

If any acceptance bullet has no corresponding change: **MISSING**.

### Pre-approval gate (for IaC-test-scenario PRs)

For PRs whose changes include `scenarios/`, `tests/integration/`, or files matching `*/test/run.sh`: run AT LEAST ONE scenario end-to-end before approving. `bash -n` (syntax check) is insufficient — past cascade reviews have caught Critical bugs (state-backend mismatch, plugin-loader layout) only when the reviewer actually executed the script.

Heuristic scope: file path contains `scenarios/`, `tests/integration/`, OR matches `*/test/run.sh`.

3. **For TDD tasks, run the test yourself**. Do not trust "I ran it":
- "RED" task (failing test): `go test ./...` (or equivalent) MUST FAIL
when you run it. If it passes, the test isn't asserting what the
Expand Down
1 change: 1 addition & 0 deletions skills/verification-before-completion/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Skip step = unverified claim.
| regression test works | red → green proof | green only |
| agent completed | inspect diff + verify | agent report |
| requirements met | checklist vs plan/design | tests alone |
| lint clean (Go-repo PR) | `golangci-lint run` exit 0 | tests green alone |

## Red Flags

Expand Down
1 change: 1 addition & 0 deletions skills/writing-plans/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ When writing a plan task, the verification step must match the change class. A g
| Hook / trigger / event handler | fire the event; observe handler runs | logged side effect confirmed; assertion passes |
| Multi-component boundary | run an integration/E2E path with real adjacent components where feasible | request/event crosses boundary; downstream side effect observed |
| Infrastructure change | render/validate/plan/dry-run plus targeted apply in safe env when available | expected resource diff; no destructive prod action without approval |
| Go-repo code change | `golangci-lint run --new-from-rev=origin/<base>` before push | exit 0 |

These examples are illustrative minimums; per-task `Expected:` fields must be literal values the check can assert against.

Expand Down
40 changes: 40 additions & 0 deletions tests/cascade-preflight.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# tests/cascade-preflight.sh
# Pre-cascade gate: verify each plugin repo's most-recent Release
# workflow run was SUCCESS. Catches release-pipeline-class gaps
# (e.g., ManifestProvider missing) before scope-lock + dispatch.
#
# Usage:
# tests/cascade-preflight.sh <repo1> <repo2> ...
# tests/cascade-preflight.sh GoCodeAlone/workflow-plugin-cloudflare GoCodeAlone/workflow-plugin-namecheap
#
# Note: Release workflows typically trigger on tag-push (push: tags: 'v*'),
# not branch-push. headBranch for tag-triggered runs is the tag name (e.g.,
# 'v1.0.0'), not 'main'. Don't filter --branch.
set -euo pipefail

[ "$#" -ge 1 ] || { printf 'Usage: %s <owner/repo> [...]\n' "$0" >&2; exit 2; }

failed=0
for repo in "$@"; do
conclusion=""
for wf in release.yml Release.yml; do
result=$(gh run list --repo "$repo" --workflow "$wf" --limit 1 \
--json conclusion --jq '.[0].conclusion // ""' 2>/dev/null || echo "")
if [ -n "$result" ]; then
conclusion="$result"
break
fi
done
conclusion="${conclusion:-not-found}"

if [ "$conclusion" = "success" ]; then
printf ' ✓ %s: Release workflow last run = success\n' "$repo"
else
printf ' ✗ %s: Release workflow last run = %s — FIX BEFORE CASCADE\n' "$repo" "$conclusion" >&2
failed=$((failed+1))
fi
done

[ "$failed" -eq 0 ] || { printf '\nPreflight FAIL: %d repo(s) have broken Release pipelines\n' "$failed" >&2; exit 1; }
printf '\nPreflight PASS: all %d repo(s) have green Release workflows\n' "$#"
Loading