diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index 40a1c62..1550c5a 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -12,7 +12,7 @@ { "name": "srepowers-core", "description": "SRE workflow spine, mandatory gates, and incident response", - "version": "5.4.0", + "version": "5.5.0", "source": { "source": "local", "path": "./plugins/srepowers-core" @@ -30,7 +30,7 @@ { "name": "srepowers-domain", "description": "Software engineering domain expertise for infrastructure engineers", - "version": "5.4.0", + "version": "5.5.0", "source": { "source": "local", "path": "./plugins/srepowers-domain" @@ -48,7 +48,7 @@ { "name": "srepowers-infra", "description": "Portable Proxmox, Puppet analysis, DNS, TLS, backup, and GitLab CI/CD administration", - "version": "5.4.0", + "version": "5.5.0", "source": { "source": "local", "path": "./plugins/srepowers-infra" @@ -66,7 +66,7 @@ { "name": "srepowers-private", "description": "Site-specific Puppet, Hiera, and Ansible operational workflow skills (sanitized templates)", - "version": "5.4.0", + "version": "5.5.0", "source": { "source": "local", "path": "./plugins/srepowers-private" diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 529295d..fcf3692 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,13 +5,13 @@ "email": "yg-codes@users.noreply.github.com" }, "metadata": { - "version": "5.4.0", + "version": "5.5.0", "description": "SRE infrastructure skills marketplace — workflow, domain expertise, and infrastructure administration plugins" }, "plugins": [ { "name": "srepowers-core", - "version": "5.4.0", + "version": "5.5.0", "description": "SRE workflow spine, mandatory gates, and incident response — verification-first operations with TDO and SDO", "source": "./plugins/srepowers-core", "author": { @@ -23,7 +23,7 @@ }, { "name": "srepowers-domain", - "version": "5.4.0", + "version": "5.5.0", "description": "Software engineering domain expertise — Go, Python, Rust, Kubernetes, Terraform, containers, networking, security, testing, and more", "source": "./plugins/srepowers-domain", "author": { @@ -35,7 +35,7 @@ }, { "name": "srepowers-infra", - "version": "5.4.0", + "version": "5.5.0", "description": "Portable infrastructure administration — Proxmox VE, Puppet code analysis, DNS, TLS/PKI, backup, change management, and GitLab CI/CD pipelines", "source": "./plugins/srepowers-infra", "author": { @@ -47,7 +47,7 @@ }, { "name": "srepowers-private", - "version": "5.4.0", + "version": "5.5.0", "description": "Site-specific operational workflows (sanitized templates) — Puppet deploy/release/MR lifecycle, Hiera debugging, and Ansible operations", "source": "./plugins/srepowers-private", "author": { diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index d686ea3..3526cfd 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "srepowers", "description": "SRE infrastructure skills marketplace with 3 plugins: core (workflow + gates + incident), domain (Go, Python, Rust, K8s, Terraform, security, etc.), infra (Proxmox, Puppet, GitLab CI/CD)", - "version": "5.4.0", + "version": "5.5.0", "author": { "name": "yg-codes", "email": "yg-codes@users.noreply.github.com" diff --git a/README.md b/README.md index 5e1fda3..e8f5fe4 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ SREPowers uses Superpowers as a methodology reference, not as a strict downstrea It intentionally diverges for infrastructure operations: routing is risk-based, production/destructive actions require safety gates, incident response has its own workflow, and TDO means verification-first rather than always failing-first. Baseline capture, blast radius, rollback, evidence, and change-control context are first-class requirements. +The `subagent-driven-operation` skill ships its SDD file-handoff scripts (`task-brief`, `review-package`, `sdd-workspace`) under a srepowers-namespaced `.srepowers/sdd/` workspace in the working tree — never under `.git/`, which Claude Code treats as a protected path. `tests/claude-code/test-sdd-workspace.sh` locks in that the workspace is self-ignoring, that the handoff scripts write into it, and that a linked git worktree resolves its own distinct workspace. + ## Minimum Sufficient Workflow SREPowers now routes tasks through the minimum sufficient workflow instead of forcing the heaviest process every time. diff --git a/plugins/srepowers-core/.claude-plugin/plugin.json b/plugins/srepowers-core/.claude-plugin/plugin.json index 2524df9..9ffadaa 100644 --- a/plugins/srepowers-core/.claude-plugin/plugin.json +++ b/plugins/srepowers-core/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "srepowers-core", - "version": "5.4.0", + "version": "5.5.0", "description": "SRE workflow spine, mandatory gates, and incident response — verification-first operations with Test-Driven Operation and Subagent-Driven Operation", "author": { "name": "yg-codes", diff --git a/plugins/srepowers-core/.codex-plugin/plugin.json b/plugins/srepowers-core/.codex-plugin/plugin.json index 2524df9..9ffadaa 100644 --- a/plugins/srepowers-core/.codex-plugin/plugin.json +++ b/plugins/srepowers-core/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "srepowers-core", - "version": "5.4.0", + "version": "5.5.0", "description": "SRE workflow spine, mandatory gates, and incident response — verification-first operations with Test-Driven Operation and Subagent-Driven Operation", "author": { "name": "yg-codes", diff --git a/plugins/srepowers-domain/.claude-plugin/plugin.json b/plugins/srepowers-domain/.claude-plugin/plugin.json index 908e90b..f3f649a 100644 --- a/plugins/srepowers-domain/.claude-plugin/plugin.json +++ b/plugins/srepowers-domain/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "srepowers-domain", - "version": "5.4.0", + "version": "5.5.0", "description": "Software engineering domain expertise — Go, Python, Rust, Kubernetes, Terraform, containers, networking, security, testing, and more", "author": { "name": "yg-codes", diff --git a/plugins/srepowers-domain/.codex-plugin/plugin.json b/plugins/srepowers-domain/.codex-plugin/plugin.json index 908e90b..f3f649a 100644 --- a/plugins/srepowers-domain/.codex-plugin/plugin.json +++ b/plugins/srepowers-domain/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "srepowers-domain", - "version": "5.4.0", + "version": "5.5.0", "description": "Software engineering domain expertise — Go, Python, Rust, Kubernetes, Terraform, containers, networking, security, testing, and more", "author": { "name": "yg-codes", diff --git a/plugins/srepowers-infra/.claude-plugin/plugin.json b/plugins/srepowers-infra/.claude-plugin/plugin.json index ddd0613..ae08c87 100644 --- a/plugins/srepowers-infra/.claude-plugin/plugin.json +++ b/plugins/srepowers-infra/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "srepowers-infra", - "version": "5.4.0", + "version": "5.5.0", "description": "Portable infrastructure administration — Proxmox VE, Puppet code analysis, PuppetDB queries, DNS, TLS/PKI, backup, change management, and GitLab CI/CD pipelines", "author": { "name": "yg-codes", diff --git a/plugins/srepowers-infra/.codex-plugin/plugin.json b/plugins/srepowers-infra/.codex-plugin/plugin.json index 957c378..29dd3a8 100644 --- a/plugins/srepowers-infra/.codex-plugin/plugin.json +++ b/plugins/srepowers-infra/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "srepowers-infra", - "version": "5.4.0", + "version": "5.5.0", "description": "Portable infrastructure administration — Proxmox VE, Puppet code analysis, DNS, TLS/PKI, backup, change management, and GitLab CI/CD pipelines", "author": { "name": "yg-codes", diff --git a/plugins/srepowers-private/.claude-plugin/plugin.json b/plugins/srepowers-private/.claude-plugin/plugin.json index 551e9d9..22da4f2 100644 --- a/plugins/srepowers-private/.claude-plugin/plugin.json +++ b/plugins/srepowers-private/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "srepowers-private", - "version": "5.4.0", + "version": "5.5.0", "description": "Site-specific operational workflows — Puppet deploy/release/MR lifecycle, Hiera debugging, and Ansible operations. Sanitized templates: replace placeholders with your environment's values.", "author": { "name": "yg-codes", diff --git a/plugins/srepowers-private/.codex-plugin/plugin.json b/plugins/srepowers-private/.codex-plugin/plugin.json index 551e9d9..22da4f2 100644 --- a/plugins/srepowers-private/.codex-plugin/plugin.json +++ b/plugins/srepowers-private/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "srepowers-private", - "version": "5.4.0", + "version": "5.5.0", "description": "Site-specific operational workflows — Puppet deploy/release/MR lifecycle, Hiera debugging, and Ansible operations. Sanitized templates: replace placeholders with your environment's values.", "author": { "name": "yg-codes", diff --git a/tests/claude-code/run-skill-tests.sh b/tests/claude-code/run-skill-tests.sh index 101ca3b..c2deca7 100755 --- a/tests/claude-code/run-skill-tests.sh +++ b/tests/claude-code/run-skill-tests.sh @@ -60,6 +60,7 @@ while [[ $# -gt 0 ]]; do echo " Core workflow:" echo " test-test-driven-operation.sh TDO skill loading and requirements" echo " test-subagent-driven-operation.sh SDO skill loading and requirements" + echo " test-sdd-workspace.sh SDD workspace path and worktree isolation" echo " test-brainstorming-operations.sh Brainstorming skill workflow" echo " test-writing-operation-plans.sh Planning skill TDO discipline" echo " test-executing-operation-plans.sh Batch execution with checkpoints" @@ -112,6 +113,7 @@ done tests=( "test-test-driven-operation.sh" "test-subagent-driven-operation.sh" + "test-sdd-workspace.sh" "test-brainstorming-operations.sh" "test-writing-operation-plans.sh" "test-executing-operation-plans.sh" diff --git a/tests/claude-code/test-sdd-workspace.sh b/tests/claude-code/test-sdd-workspace.sh new file mode 100755 index 0000000..076957d --- /dev/null +++ b/tests/claude-code/test-sdd-workspace.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env bash +# Tests for the SDD workspace: the sdd-workspace helper resolves a self-ignoring +# working-tree directory (.srepowers/sdd) for SDD artifacts, and the task-brief +# and review-package scripts write into it. A linked worktree resolves its own +# distinct workspace (parity with superpowers v6.0.3 per-worktree isolation). +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +SDD_SCRIPTS="$REPO_ROOT/plugins/srepowers-core/skills/subagent-driven-operation/scripts" +NS=".srepowers/sdd" + +FAILURES=0 +TEST_ROOT="" + +pass() { echo " [PASS] $1"; } +fail() { + echo " [FAIL] $1" + FAILURES=$((FAILURES + 1)) +} + +cleanup() { + if [[ -n "$TEST_ROOT" && -d "$TEST_ROOT" ]]; then + rm -rf "$TEST_ROOT" + fi +} + +main() { + echo "=== Test: sdd-workspace ===" + + TEST_ROOT="$(mktemp -d)" + trap cleanup EXIT + + # Resolve repo to its physical path so string comparisons match the + # helper's output (git rev-parse --show-toplevel resolves symlinks). + git init -q -b main "$TEST_ROOT/repo" + local repo + repo="$(cd "$TEST_ROOT/repo" && git rev-parse --show-toplevel)" + + local dir + dir="$(cd "$repo" && "$SDD_SCRIPTS/sdd-workspace")" + + if [[ "$dir" == "$repo/$NS" ]]; then + pass "prints /$NS" + else + fail "prints /$NS" + echo " got: $dir" + fi + + if [[ -f "$repo/$NS/.gitignore" && "$(cat "$repo/$NS/.gitignore")" == "*" ]]; then + pass "self-ignoring .gitignore created with '*'" + else + fail "self-ignoring .gitignore created with '*'" + fi + + printf 'x\n' > "$repo/$NS/artifact.md" + local status + status="$(cd "$repo" && git status --porcelain)" + if [[ -z "$status" ]]; then + pass "workspace invisible to git status" + else + fail "workspace invisible to git status" + echo " status: $status" + fi + + ( cd "$repo" && git add -A ) + local staged + staged="$(cd "$repo" && git diff --cached --name-only)" + if [[ -z "$staged" ]]; then + pass "git add -A does not stage the workspace" + else + fail "git add -A does not stage the workspace" + echo " staged: $staged" + fi + + cat > "$repo/plan.md" <<'PLAN' +# Plan + +## Task 1: First thing + +Do the first thing. +PLAN + + local brief_out brief_path + brief_out="$(cd "$repo" && "$SDD_SCRIPTS/task-brief" plan.md 1)" + brief_path="$(printf '%s\n' "$brief_out" | sed -n 's/^wrote \(.*\): [0-9][0-9]* lines$/\1/p')" + case "$brief_path" in + "$repo/$NS/"*) pass "task-brief writes its brief under the workspace" ;; + *) + fail "task-brief writes its brief under the workspace" + echo " got: $brief_path" + ;; + esac + + local git_id=(-c user.email=t@example.com -c user.name=t -c commit.gpgsign=false) + ( cd "$repo" \ + && git add plan.md \ + && git "${git_id[@]}" commit -qm c1 \ + && printf 'y\n' > f && git add f \ + && git "${git_id[@]}" commit -qm c2 ) + local rp_out rp_path + rp_out="$(cd "$repo" && "$SDD_SCRIPTS/review-package" HEAD~1 HEAD)" + rp_path="$(printf '%s\n' "$rp_out" | sed -n 's/^wrote \(.*\): [0-9].*$/\1/p')" + case "$rp_path" in + "$repo/$NS/"*) pass "review-package writes its diff under the workspace" ;; + *) + fail "review-package writes its diff under the workspace" + echo " got: $rp_path" + ;; + esac + + # --- Worktree isolation: a linked worktree resolves its own workspace --- + local wt="$TEST_ROOT/wt" + ( cd "$repo" && git worktree add -q "$wt" -b wt-feature ) + local wt_root wt_dir + wt_root="$(cd "$wt" && git rev-parse --show-toplevel)" + wt_dir="$(cd "$wt" && "$SDD_SCRIPTS/sdd-workspace")" + if [[ "$wt_dir" == "$wt_root/$NS" && "$wt_dir" != "$dir" ]]; then + pass "linked worktree resolves its own distinct workspace" + else + fail "linked worktree resolves its own distinct workspace" + echo " main: $dir" + echo " wt: $wt_dir" + fi + + printf 'y\n' > "$wt/$NS/artifact.md" + local wt_status + wt_status="$(cd "$wt" && git status --porcelain)" + if [[ -z "$wt_status" ]]; then + pass "worktree workspace invisible to git status" + else + fail "worktree workspace invisible to git status" + echo " status: $wt_status" + fi + + echo "" + if [[ "$FAILURES" -ne 0 ]]; then + echo "FAILED: $FAILURES assertion(s)." + exit 1 + fi + echo "PASS" +} + +main "$@"