bigpowers 2.90.2 → 2.91.1
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/.agents/skills/build-epic/SKILL.md +1 -1
- package/.agents/skills/commit-message/SKILL.md +1 -0
- package/.agents/skills/guard-git/SKILL.md +7 -2
- package/.agents/skills/release-branch/SKILL.md +4 -5
- package/.agents/skills/run-planning/SKILL.md +6 -1
- package/.agents/skills/verify-work/SKILL.md +2 -1
- package/.cline/skills/build-epic/SKILL.md +1 -1
- package/.cline/skills/commit-message/SKILL.md +1 -0
- package/.cline/skills/guard-git/SKILL.md +7 -2
- package/.cline/skills/release-branch/SKILL.md +4 -5
- package/.cline/skills/run-planning/SKILL.md +6 -1
- package/.cline/skills/verify-work/SKILL.md +2 -1
- package/.codebuddy/skills/build-epic/SKILL.md +1 -1
- package/.codebuddy/skills/commit-message/SKILL.md +1 -0
- package/.codebuddy/skills/guard-git/SKILL.md +7 -2
- package/.codebuddy/skills/release-branch/SKILL.md +4 -5
- package/.codebuddy/skills/run-planning/SKILL.md +6 -1
- package/.codebuddy/skills/verify-work/SKILL.md +2 -1
- package/.codex/skills/build-epic/SKILL.md +1 -1
- package/.codex/skills/commit-message/SKILL.md +1 -0
- package/.codex/skills/guard-git/SKILL.md +7 -2
- package/.codex/skills/release-branch/SKILL.md +4 -5
- package/.codex/skills/run-planning/SKILL.md +6 -1
- package/.codex/skills/verify-work/SKILL.md +2 -1
- package/.copilot/skills/build-epic/SKILL.md +1 -1
- package/.copilot/skills/commit-message/SKILL.md +1 -0
- package/.copilot/skills/guard-git/SKILL.md +7 -2
- package/.copilot/skills/release-branch/SKILL.md +4 -5
- package/.copilot/skills/run-planning/SKILL.md +6 -1
- package/.copilot/skills/verify-work/SKILL.md +2 -1
- package/.cursor/rules/build-epic.mdc +1 -1
- package/.cursor/rules/commit-message.mdc +1 -0
- package/.cursor/rules/guard-git.mdc +7 -2
- package/.cursor/rules/release-branch.mdc +4 -5
- package/.cursor/rules/run-planning.mdc +6 -1
- package/.cursor/rules/verify-work.mdc +2 -1
- package/.gemini/extensions/bigpowers/commands/prompts/build-epic.md +1 -1
- package/.gemini/extensions/bigpowers/commands/prompts/commit-message.md +1 -0
- package/.gemini/extensions/bigpowers/commands/prompts/guard-git.md +7 -2
- package/.gemini/extensions/bigpowers/commands/prompts/release-branch.md +4 -5
- package/.gemini/extensions/bigpowers/commands/prompts/run-planning.md +6 -1
- package/.gemini/extensions/bigpowers/commands/prompts/verify-work.md +2 -1
- package/.gemini/extensions/bigpowers/gemini-extension.json +1 -1
- package/.gemini/extensions/bigpowers/skills/build-epic/SKILL.md +1 -1
- package/.gemini/extensions/bigpowers/skills/commit-message/SKILL.md +1 -0
- package/.gemini/extensions/bigpowers/skills/guard-git/SKILL.md +7 -2
- package/.gemini/extensions/bigpowers/skills/release-branch/SKILL.md +4 -5
- package/.gemini/extensions/bigpowers/skills/run-planning/SKILL.md +6 -1
- package/.gemini/extensions/bigpowers/skills/verify-work/SKILL.md +2 -1
- package/.hermes/skills/build-epic/SKILL.md +1 -1
- package/.hermes/skills/commit-message/SKILL.md +1 -0
- package/.hermes/skills/guard-git/SKILL.md +7 -2
- package/.hermes/skills/release-branch/SKILL.md +4 -5
- package/.hermes/skills/run-planning/SKILL.md +6 -1
- package/.hermes/skills/verify-work/SKILL.md +2 -1
- package/.kilocode/rules/build-epic.md +1 -1
- package/.kilocode/rules/commit-message.md +1 -0
- package/.kilocode/rules/guard-git.md +7 -2
- package/.kilocode/rules/release-branch.md +4 -5
- package/.kilocode/rules/run-planning.md +6 -1
- package/.kilocode/rules/verify-work.md +2 -1
- package/.mimocode/skills/build-epic/SKILL.md +1 -1
- package/.mimocode/skills/commit-message/SKILL.md +1 -0
- package/.mimocode/skills/guard-git/SKILL.md +7 -2
- package/.mimocode/skills/release-branch/SKILL.md +4 -5
- package/.mimocode/skills/run-planning/SKILL.md +6 -1
- package/.mimocode/skills/verify-work/SKILL.md +2 -1
- package/.opencode/skills/build-epic/SKILL.md +1 -1
- package/.opencode/skills/commit-message/SKILL.md +1 -0
- package/.opencode/skills/guard-git/SKILL.md +7 -2
- package/.opencode/skills/release-branch/SKILL.md +4 -5
- package/.opencode/skills/run-planning/SKILL.md +6 -1
- package/.opencode/skills/verify-work/SKILL.md +2 -1
- package/.pi/package.json +1 -1
- package/.pi/prompts/build-epic.md +1 -1
- package/.pi/prompts/commit-message.md +1 -0
- package/.pi/prompts/guard-git.md +7 -2
- package/.pi/prompts/release-branch.md +4 -5
- package/.pi/prompts/run-planning.md +6 -1
- package/.pi/prompts/verify-work.md +2 -1
- package/.pi/skills/build-epic/SKILL.md +1 -1
- package/.pi/skills/commit-message/SKILL.md +1 -0
- package/.pi/skills/guard-git/SKILL.md +7 -2
- package/.pi/skills/release-branch/SKILL.md +4 -5
- package/.pi/skills/run-planning/SKILL.md +6 -1
- package/.pi/skills/verify-work/SKILL.md +2 -1
- package/.qwen/skills/build-epic/SKILL.md +1 -1
- package/.qwen/skills/commit-message/SKILL.md +1 -0
- package/.qwen/skills/guard-git/SKILL.md +7 -2
- package/.qwen/skills/release-branch/SKILL.md +4 -5
- package/.qwen/skills/run-planning/SKILL.md +6 -1
- package/.qwen/skills/verify-work/SKILL.md +2 -1
- package/.trae/skills/build-epic/SKILL.md +1 -1
- package/.trae/skills/commit-message/SKILL.md +1 -0
- package/.trae/skills/guard-git/SKILL.md +7 -2
- package/.trae/skills/release-branch/SKILL.md +4 -5
- package/.trae/skills/run-planning/SKILL.md +6 -1
- package/.trae/skills/verify-work/SKILL.md +2 -1
- package/.windsurf/rules/build-epic.md +1 -1
- package/.windsurf/rules/commit-message.md +1 -0
- package/.windsurf/rules/guard-git.md +7 -2
- package/.windsurf/rules/release-branch.md +4 -5
- package/.windsurf/rules/run-planning.md +6 -1
- package/.windsurf/rules/verify-work.md +2 -1
- package/.zcode/skills/build-epic/SKILL.md +1 -1
- package/.zcode/skills/commit-message/SKILL.md +1 -0
- package/.zcode/skills/guard-git/SKILL.md +7 -2
- package/.zcode/skills/release-branch/SKILL.md +4 -5
- package/.zcode/skills/run-planning/SKILL.md +6 -1
- package/.zcode/skills/verify-work/SKILL.md +2 -1
- package/CHANGELOG.md +15 -0
- package/extensions/omp-hooks.ts +197 -58
- package/hooks/pre/bash.sh +54 -7
- package/hooks/pre-tool-use.sh +72 -12
- package/package.json +2 -1
- package/scripts/convert-legado.sh +1 -0
- package/scripts/lib/__pycache__/atomic_write.cpython-310.pyc +0 -0
- package/scripts/lib/__pycache__/link_utils.cpython-310.pyc +0 -0
- package/scripts/lib/__pycache__/srp_engine_links.cpython-310.pyc +0 -0
- package/scripts/lib/__pycache__/srp_engine_okf.cpython-310.pyc +0 -0
- package/scripts/lib/assert-epic-gate.sh +32 -0
- package/scripts/lib/assert-planning-artifacts.sh +65 -0
- package/scripts/lib/git-argv.py +168 -0
- package/scripts/lib/golden-suite-gates.sh +2 -0
- package/scripts/omp-guard-probe.ts +46 -0
- package/scripts/test-generated-path-hook.sh +57 -0
- package/scripts/test-guard-git-normalize.sh +189 -0
- package/scripts/test-test-lock-hook.sh +100 -0
- package/scripts/validate-doctrine.sh +4 -4
- package/scripts/verify-adversarial.sh +146 -0
- package/scripts/verify-tdd-red-commit.sh +39 -1
- package/skills/build-epic/SKILL.md +1 -1
- package/skills/commit-message/SKILL.md +1 -0
- package/skills/guard-git/SKILL.md +7 -2
- package/skills/release-branch/SKILL.md +4 -5
- package/skills/run-planning/SKILL.md +6 -1
- package/skills/verify-work/SKILL.md +2 -1
- package/skills-lock.json +6 -6
- package/tests/test-artifact-assertions.sh +86 -0
- package/tests/test-verify-adversarial.sh +27 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# story: e86
|
|
3
|
+
# Adversarial Defect Mutation & Boundary Fuzzing Gate.
|
|
4
|
+
# Evaluates code changes against null/undefined, empty collections, extreme bounds,
|
|
5
|
+
# and unexpected types before UAT sign-off.
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
REPO_ROOT="$(git -C "$PWD" rev-parse --show-toplevel 2>/dev/null)" || {
|
|
9
|
+
echo "verify-adversarial: not in a git repository" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
}
|
|
12
|
+
cd "$REPO_ROOT"
|
|
13
|
+
|
|
14
|
+
self_test() {
|
|
15
|
+
local tmp
|
|
16
|
+
tmp=$(mktemp -d)
|
|
17
|
+
trap 'rm -rf "$tmp"' RETURN
|
|
18
|
+
|
|
19
|
+
cd "$tmp"
|
|
20
|
+
git init -q
|
|
21
|
+
git config user.email "adversarial@bigpowers.local"
|
|
22
|
+
git config user.name "adversarial"
|
|
23
|
+
|
|
24
|
+
mkdir -p src test
|
|
25
|
+
cat > package.json <<'JSON'
|
|
26
|
+
{"name":"adversarial-fixture","scripts":{"test":"node test/calc.test.js"}}
|
|
27
|
+
JSON
|
|
28
|
+
|
|
29
|
+
# Vulnerable implementation (crashes on undefined brand or null line item, like ab-20)
|
|
30
|
+
cat > src/calc.js <<'JS'
|
|
31
|
+
function applyDiscount(item) {
|
|
32
|
+
// Bug: crashes if item.brand is undefined or item is null
|
|
33
|
+
return item.brand.toUpperCase() === "ACME" ? 0.9 : 1.0;
|
|
34
|
+
}
|
|
35
|
+
module.exports = { applyDiscount };
|
|
36
|
+
JS
|
|
37
|
+
|
|
38
|
+
cat > test/calc.test.js <<'JS'
|
|
39
|
+
const assert = require('assert');
|
|
40
|
+
const { applyDiscount } = require('../src/calc');
|
|
41
|
+
assert.strictEqual(applyDiscount({ brand: 'Acme' }), 0.9);
|
|
42
|
+
assert.strictEqual(applyDiscount({ brand: 'Other' }), 1.0);
|
|
43
|
+
console.log("Acceptance tests PASS");
|
|
44
|
+
JS
|
|
45
|
+
|
|
46
|
+
git add .
|
|
47
|
+
git commit -q -m "feat: initial feature with hidden boundary flaw"
|
|
48
|
+
|
|
49
|
+
# Run self-test probe: probe with { brand: undefined } and {}
|
|
50
|
+
local probe_fail=false
|
|
51
|
+
node -e "
|
|
52
|
+
const { applyDiscount } = require('./src/calc');
|
|
53
|
+
try {
|
|
54
|
+
applyDiscount({});
|
|
55
|
+
} catch (e) {
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
" 2>/dev/null || probe_fail=true
|
|
59
|
+
|
|
60
|
+
if [ "$probe_fail" = false ]; then
|
|
61
|
+
echo "FAIL: Expected vulnerable fixture to crash on missing brand"
|
|
62
|
+
return 1
|
|
63
|
+
fi
|
|
64
|
+
echo "PASS: Vulnerable fixture correctly triggered defect on boundary probe"
|
|
65
|
+
|
|
66
|
+
# Now harden the fixture
|
|
67
|
+
cat > src/calc.js <<'JS'
|
|
68
|
+
function applyDiscount(item) {
|
|
69
|
+
if (!item || !item.brand) return 1.0;
|
|
70
|
+
return item.brand.toUpperCase() === "ACME" ? 0.9 : 1.0;
|
|
71
|
+
}
|
|
72
|
+
module.exports = { applyDiscount };
|
|
73
|
+
JS
|
|
74
|
+
|
|
75
|
+
local probe_pass=true
|
|
76
|
+
node -e "
|
|
77
|
+
const { applyDiscount } = require('./src/calc');
|
|
78
|
+
try {
|
|
79
|
+
applyDiscount({});
|
|
80
|
+
applyDiscount(null);
|
|
81
|
+
applyDiscount({ brand: undefined });
|
|
82
|
+
} catch (e) {
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
" 2>/dev/null || probe_pass=false
|
|
86
|
+
|
|
87
|
+
if [ "$probe_pass" = false ]; then
|
|
88
|
+
echo "FAIL: Hardened fixture should survive boundary probe"
|
|
89
|
+
return 1
|
|
90
|
+
fi
|
|
91
|
+
echo "PASS: Hardened fixture survived boundary probes"
|
|
92
|
+
echo "verify-adversarial: self-test OK"
|
|
93
|
+
return 0
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if [[ "${1:-}" == "--self-test" ]]; then
|
|
97
|
+
self_test
|
|
98
|
+
exit $?
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
echo "=== Adversarial Defect Mutation Gate ==="
|
|
102
|
+
|
|
103
|
+
# 1. Identify changed source files
|
|
104
|
+
CHANGED_FILES=$(git diff --name-only HEAD 2>/dev/null || git status --porcelain | awk '{print $2}')
|
|
105
|
+
if [[ -z "$CHANGED_FILES" ]] && git rev-parse HEAD~1 >/dev/null 2>&1; then
|
|
106
|
+
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || true)
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
DEFECTS_FOUND=0
|
|
110
|
+
mkdir -p specs/verifications
|
|
111
|
+
|
|
112
|
+
# 2. Check for common unsafe property access patterns on JS/TS files
|
|
113
|
+
for file in $CHANGED_FILES; do
|
|
114
|
+
if [[ "$file" =~ \.(js|ts|mjs)$ ]] && [[ -f "$file" ]] && [[ ! "$file" =~ (^|/)test/ ]] && [[ ! "$file" =~ \.test\. ]]; then
|
|
115
|
+
# Look for unsafe chained property access like item.brand.toLowerCase() or item.prop.subprop
|
|
116
|
+
if grep -nE '\.[a-zA-Z0-9_]+\.(toLowerCase|toUpperCase|trim|length|slice)\(' "$file" | grep -v '\?\.' >/dev/null 2>&1; then
|
|
117
|
+
echo "WARNING [boundary-mutation]: Potential unhandled undefined access without optional chaining in $file:"
|
|
118
|
+
grep -nE '\.[a-zA-Z0-9_]+\.(toLowerCase|toUpperCase|trim|length|slice)\(' "$file" | grep -v '\?\.' | head -n 5
|
|
119
|
+
fi
|
|
120
|
+
fi
|
|
121
|
+
done
|
|
122
|
+
|
|
123
|
+
# 3. If the repository defines an adversarial test script, execute it
|
|
124
|
+
if [[ -f package.json ]] && grep -q '"test:adversarial"' package.json 2>/dev/null; then
|
|
125
|
+
echo "Running project-defined adversarial test suite (npm run test:adversarial)..."
|
|
126
|
+
if ! npm run test:adversarial; then
|
|
127
|
+
DEFECTS_FOUND=$((DEFECTS_FOUND + 1))
|
|
128
|
+
fi
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
# 4. Write evidence artifact
|
|
132
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
133
|
+
cat > specs/verifications/ADVERSARIAL_LATEST.yaml <<YAML
|
|
134
|
+
verified_at: "$TIMESTAMP"
|
|
135
|
+
gate: verify-adversarial
|
|
136
|
+
defects_found: $DEFECTS_FOUND
|
|
137
|
+
passed: $( [ "$DEFECTS_FOUND" -eq 0 ] && echo "true" || echo "false" )
|
|
138
|
+
YAML
|
|
139
|
+
|
|
140
|
+
if [ "$DEFECTS_FOUND" -gt 0 ]; then
|
|
141
|
+
echo "FAIL: Adversarial mutation gate found $DEFECTS_FOUND defects. Harden edge cases before declaring UAT green." >&2
|
|
142
|
+
exit 1
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
echo "PASS: Adversarial defect mutation gate passed."
|
|
146
|
+
exit 0
|
|
@@ -78,7 +78,45 @@ if [[ -z "$VERIFY_CMD" ]]; then
|
|
|
78
78
|
fi
|
|
79
79
|
fi
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
LATEST_MSG=$(git log -1 --format=%s 2>/dev/null || echo "")
|
|
82
|
+
|
|
83
|
+
# Enforce during fix_bug flow, bug-fix commits, or when explicitly requested
|
|
84
|
+
IS_FIX_FLOW=false
|
|
85
|
+
if [ -f specs/state.yaml ] && grep -qE "active_flow:[[:space:]]*fix_bug" specs/state.yaml 2>/dev/null; then
|
|
86
|
+
IS_FIX_FLOW=true
|
|
87
|
+
elif [[ -n "${TDD_ENFORCE_RED:-}" ]]; then
|
|
88
|
+
IS_FIX_FLOW=true
|
|
89
|
+
elif [[ "$LATEST_MSG" =~ ^fix\(bug ]] || [[ "$LATEST_MSG" =~ BUG-[0-9] ]]; then
|
|
90
|
+
IS_FIX_FLOW=true
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
if [ "$IS_FIX_FLOW" = false ] && [[ "${CHECK_PENDING_FIX:-0}" != "1" ]]; then
|
|
94
|
+
echo "SKIP: verify-tdd-red-commit only enforces during fix_bug flow or bug-fix commits"
|
|
95
|
+
exit 0
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
if [[ "$LATEST_MSG" =~ ^fix ]]; then
|
|
99
|
+
RED_SHA=$(git rev-parse HEAD~1 2>/dev/null || echo "")
|
|
100
|
+
RED_MSG=$(git log -1 --format=%s "$RED_SHA" 2>/dev/null || echo "")
|
|
101
|
+
if [[ ! "$RED_MSG" =~ ^test ]]; then
|
|
102
|
+
echo "FAIL: preceding commit $RED_SHA is not a test-only commit (found: '$RED_MSG') — RED gate violated"
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
elif [[ "$LATEST_MSG" =~ ^test ]]; then
|
|
106
|
+
RED_SHA=$(git rev-parse HEAD 2>/dev/null || echo "")
|
|
107
|
+
else
|
|
108
|
+
if [[ "${CHECK_PENDING_FIX:-0}" == "1" ]]; then
|
|
109
|
+
echo "FAIL: latest commit '$LATEST_MSG' is not a test-only (RED) commit — RED gate violated"
|
|
110
|
+
exit 1
|
|
111
|
+
fi
|
|
112
|
+
RED_SHA=$(git rev-parse HEAD~1 2>/dev/null || echo "")
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
if [[ -z "$RED_SHA" ]]; then
|
|
116
|
+
echo "FAIL: could not identify RED commit"
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
|
|
82
120
|
WORKTREE=$(mktemp -d)
|
|
83
121
|
trap 'git worktree remove -f "$WORKTREE" 2>/dev/null || rm -rf "$WORKTREE"' EXIT
|
|
84
122
|
|
|
@@ -68,7 +68,7 @@ Orchestrates the **build** flow for a single epic: survey → plan tasks → kic
|
|
|
68
68
|
After step 5 (verify-work) completes successfully, step 6 runs `audit-code` automatically in `--gate` mode:
|
|
69
69
|
|
|
70
70
|
1. **Run audit:** Invoke `audit-code --gate` on the complete diff for this story.
|
|
71
|
-
2. **Pass (exit 0):** All checklist sections pass → advance to step 7 (commit-message). Record `epic_cycle.audit_result: pass` in `state.yaml`.
|
|
71
|
+
2. **Pass (exit 0):** All checklist sections pass → run `bash scripts/lib/assert-epic-gate.sh advance` to mechanically confirm the audit pass, then advance to step 7 (commit-message). Record `epic_cycle.audit_result: pass` in `state.yaml`.
|
|
72
72
|
3. **Fail (exit 1):** One or more checklist sections fail → **reset `epic_cycle.current_step` to `4`** (develop-tdd) and add the failing section IDs to `completed_steps` as `"1,2,3,4,5,6(fail: ...)"`. Record `epic_cycle.audit_result: fail` in `state.yaml`. Do NOT advance past step 6 until audit passes.
|
|
73
73
|
4. **Audit artifact:** Full audit report saved to `specs/verifications/AUDIT-<epic>-<story>.md` regardless of pass/fail, for reviewer traceability.
|
|
74
74
|
5. **Enforce F.I.R.S.T:** After audit-code passes, run `enforce-first --quick` on new/modified tests. Append F.I.R.S.T violations (if any) to the audit report. Failing F.I.R.S.T criteria trigger the same loop-back to step 4.
|
|
@@ -37,6 +37,7 @@ description: Reviews working-tree changes, then drafts a Conventional Commits ti
|
|
|
37
37
|
|
|
38
38
|
## Checklist before finalizing
|
|
39
39
|
|
|
40
|
+
- [ ] **Audit pass confirmed (HARD GATE — Issue #182):** In active epic flow, `bash scripts/lib/assert-epic-gate.sh commit` passes.
|
|
40
41
|
- [ ] Type matches the **dominant** user-visible outcome (`feat` vs `fix` vs `perf`, etc.).
|
|
41
42
|
- [ ] **Scope** is a short noun in parentheses if it helps (e.g. `fix(api): …`).
|
|
42
43
|
- [ ] Breaking changes are explicit (`!` and/or `BREAKING CHANGE:` in the body/footer).
|
|
@@ -13,7 +13,8 @@ Installs a shared hook that blocks destructive git operations and enforces workf
|
|
|
13
13
|
|
|
14
14
|
## What gets blocked/enforced
|
|
15
15
|
|
|
16
|
-
- **Safety**:
|
|
16
|
+
- **Safety**: force push (`-f`, `--force`, `+refspec`), `reset` with `--hard`, `clean` with any `-f*`, `branch -D` / `--delete --force`, `checkout`/`restore` that discard work (`-f`, `.` pathspec).
|
|
17
|
+
- **Argv, not substrings**: the hook tokenizes each command, strips git's global options (`-C <path>`, `-c k=v`, `--no-pager`, `--git-dir=…`) and judges the `(subcommand, arguments)` pair — so `git -C repo reset -q --hard` is blocked, while `git push --force-with-lease` is allowed. Rules live in `scripts/lib/git-argv.py`, mirrored in `extensions/omp-hooks.ts`; `scripts/test-guard-git-normalize.sh` fails if the two disagree.
|
|
17
18
|
- **Discipline**: Blocks direct commits or pushes to protected branches (`main`, `master`) unless `GIT_BIGPOWERS_LAND=1` (set only by `scripts/land-branch.sh`).
|
|
18
19
|
- **Allows**: `git push origin <feature-branch>` for backup/CI; solo land push to `main` only inside `land-branch.sh`.
|
|
19
20
|
- **Standardization**: Enforces [Conventional Commits](https://www.conventionalcommits.org/) for all `git commit` commands.
|
|
@@ -38,7 +39,11 @@ Installs a shared hook that blocks destructive git operations and enforces workf
|
|
|
38
39
|
|
|
39
40
|
## Customization
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
The rule table lives in `scripts/lib/git-argv.py` (shell hooks) and is mirrored in `extensions/omp-hooks.ts`. Add a rule to both and a row to `specs/verifications/fixtures/guard-git-normalize.yaml`.
|
|
43
|
+
|
|
44
|
+
The TS side is judged through `evaluateBashCall()` — the single pure function the `tool_call` handler calls — so the fixture covers **every** rule (destructive argv, protected-branch push, Conventional Commits), not just the argv table. The gate (`bash scripts/test-guard-git-normalize.sh`) runs both implementations with `GIT_BIGPOWERS_LAND` unset and fails if they disagree, so a verdict can never depend on the developer's shell.
|
|
45
|
+
|
|
46
|
+
Protected-branch rules answer differently on `main` than on a feature branch, so a row that touches commit/push semantics states its `branch:` and both sides are run in it (the shell hook in a throwaway repo checked out on that branch). A row without `branch:` is judged on a feature branch. Do not pin the branch inside either implementation — that is what made the gate pass on PRs and fail on `main`.
|
|
42
47
|
|
|
43
48
|
## Advanced
|
|
44
49
|
|
|
@@ -58,13 +58,12 @@ git log main...HEAD --format="%B" | grep -qiE 'co[- ]authored[- ]by' && echo "
|
|
|
58
58
|
### 2a. Security gate
|
|
59
59
|
|
|
60
60
|
- [ ] `specs/security/REVIEW.md` exists and is fresh (matches current branch diff)
|
|
61
|
-
- [ ] No unresolved HIGH findings with confidence ≥ 8 (or all documented in `specs/security/EXCEPTIONS.md` with sign-off rationale)
|
|
62
61
|
|
|
63
|
-
|
|
62
|
+
### 2b. Audit-code & Traceability gates (HARD GATES — Issue #182)
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Run `gate-trace
|
|
64
|
+
- [ ] Run `bash scripts/lib/assert-epic-gate.sh release` (asserts `specs/AUDIT_LATEST.md` passed; blocks release on failure).
|
|
65
|
+
- [ ] No unresolved HIGH security findings with confidence ≥ 8 (or documented in `specs/security/EXCEPTIONS.md`).
|
|
66
|
+
- [ ] Run `gate-trace`. FAIL blocks merge; CONCERNS requires explicit override in `specs/state.yaml`. WAIVED if no matrix available.
|
|
68
67
|
|
|
69
68
|
> **Adversarial refute framing (e45s32):** The final pre-merge check is **refute, not rubber-stamp**. Before declaring ready, actively try to disprove traceability completeness — missing story tags, absent verify evidence, stale security review. Only proceed when refutation fails.
|
|
70
69
|
|
|
@@ -62,7 +62,12 @@ if written:
|
|
|
62
62
|
- `plan-release` — sequence epics by WSJF
|
|
63
63
|
- `slice-tasks` — cut vertical slices
|
|
64
64
|
|
|
65
|
-
4. **
|
|
65
|
+
4. **Mechanical artifact assertion before status update (HARD GATE — Issue #183):**
|
|
66
|
+
Before marking any workflow key `status: done`, run:
|
|
67
|
+
```bash
|
|
68
|
+
bash scripts/lib/assert-planning-artifacts.sh <workflow-key>
|
|
69
|
+
```
|
|
70
|
+
If the artifact assertion fails, do NOT advance status. Remediate missing output files before continuing. On success, set `status: done` for that workflow key in `planning-status.yaml`.
|
|
66
71
|
|
|
67
72
|
5. **Advance** — Set `state.yaml` `active_flow: planning` while in this chain. When all required keys are done, set `handoff.next_skill` to `plan-work`.
|
|
68
73
|
|
|
@@ -63,7 +63,8 @@ Review answers "is the code good?"; Verify answers "does the built thing do what
|
|
|
63
63
|
5a. **Blind-spot check** — run `bash scripts/check-blind-spots.sh`. This detects structural quality gaps (verify-gap, test-gap, stale-tag, etc.) beyond percentage coverage. If any HIGH-severity findings exist → **block the verify-work PASS gate**. Findings are written to `specs/blind-spots.json`. MEDIUM/LOW findings warn but don't block.
|
|
64
64
|
5a2. **Completeness critic (e45s05)** — `bash scripts/lib/completeness-critic.sh`. **BLOCKER** aborts merge gate; WARNING → gaps loop; FILLED = evidence only.
|
|
65
65
|
|
|
66
|
-
5b. **NFR Evidence Gate** (P0 only) —
|
|
66
|
+
5b. **NFR Evidence Gate** (P0 only) — Go/no-go on Performance, Reliability, Operability against `specs/tech-architecture/eNN-TEST_PLAN_LATEST.md`. Evidence written to `specs/verifications/NFR-eNNsYY.json`. FAIL blocks gate.
|
|
67
|
+
5c. **Adversarial Defect Mutation Gate (HARD GATE — e86 / ab-20)** — `bash scripts/verify-adversarial.sh`. Boundary fuzzing & parameter injection against modified interfaces. Crashes or failures block PASS gate; evidence in `specs/verifications/ADVERSARIAL_LATEST.yaml`.
|
|
67
68
|
6. **Step-by-step UAT** (skip if P2/P3) — one user-observable action at a time.
|
|
68
69
|
7. **Gaps loop** — failures → log → `plan-work` → re-verify. Unaddressed HIGH findings from step 5 feed into this loop alongside other quality gaps.
|
|
69
70
|
|
package/skills-lock.json
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"build-epic": {
|
|
25
25
|
"description": "Eight-step epic build cycle — reads state.yaml, execution-status.yaml, and one epic capsule; updates status via bp-yaml-set or direct edit. Resume mode runs one step per invocation. Use instead of ad-hoc execute-plan for release work.",
|
|
26
|
-
"sha256": "
|
|
26
|
+
"sha256": "c1687698f60f5df1",
|
|
27
27
|
"path": "skills/build-epic/SKILL.md"
|
|
28
28
|
},
|
|
29
29
|
"change-request": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"commit-message": {
|
|
35
35
|
"description": "Reviews working-tree changes, then drafts a Conventional Commits title/body and states the semantic-release version bump a single such commit would imply. Also notes which defensive-code categories were touched. Use when the user wants to commit recent work, prepare a Conventional Commits message, or asks for semantic-release / semver-consistent messaging before git commit.",
|
|
36
|
-
"sha256": "
|
|
36
|
+
"sha256": "58bc72a02aa4ce00",
|
|
37
37
|
"path": "skills/commit-message/SKILL.md"
|
|
38
38
|
},
|
|
39
39
|
"compose-workflow": {
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
},
|
|
159
159
|
"guard-git": {
|
|
160
160
|
"description": "Block dangerous git commands (push, force push, reset --hard, clean, branch -D, checkout/restore .) and enforce Conventional Commits & Branch Protection before an AI agent runs them. Installs hook scripts for Claude Code, Cursor, Cursor CLI, and Gemini CLI; documents Google Antigravity Terminal deny lists. Use when the user wants git safety hooks, to block git push or destructive git in agents, or to mirror the same policy across AI coding tools.",
|
|
161
|
-
"sha256": "
|
|
161
|
+
"sha256": "08b4b14a1134032e",
|
|
162
162
|
"path": "skills/guard-git/SKILL.md"
|
|
163
163
|
},
|
|
164
164
|
"harden-vps": {
|
|
@@ -248,7 +248,7 @@
|
|
|
248
248
|
},
|
|
249
249
|
"release-branch": {
|
|
250
250
|
"description": "Make the merge/PR/keep/discard decision for a feature branch, verify coverage gates, create the PR with gh, and clean up the worktree. Use when a feature is done and ready to ship, or when user says \"release\", \"merge\", or \"open a PR\".",
|
|
251
|
-
"sha256": "
|
|
251
|
+
"sha256": "41b42f5d409de4cb",
|
|
252
252
|
"path": "skills/release-branch/SKILL.md"
|
|
253
253
|
},
|
|
254
254
|
"request-review": {
|
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
},
|
|
284
284
|
"run-planning": {
|
|
285
285
|
"description": "\"DISCOVER-PHASE ADVANCER — Drive the discover-phase checklist (specs/planning-status.yaml) through survey-context → scope-work → research-first → elaborate-spec → plan-release → slice-tasks. NOT a duplicate of plan-work or the planning spine; it orchestrates the pre-coding discover phase only.\"",
|
|
286
|
-
"sha256": "
|
|
286
|
+
"sha256": "5cdd1e03360f0f6c",
|
|
287
287
|
"path": "skills/run-planning/SKILL.md"
|
|
288
288
|
},
|
|
289
289
|
"scope-work": {
|
|
@@ -378,7 +378,7 @@
|
|
|
378
378
|
},
|
|
379
379
|
"verify-work": {
|
|
380
380
|
"description": "Multi-phase UAT gate — cold-start smoke, build, typecheck, lint, tests, step-by-step manual verification, gaps-closure loop. Use after execute-plan or develop-tdd, before audit-code.",
|
|
381
|
-
"sha256": "
|
|
381
|
+
"sha256": "b395c44051f4ac3c",
|
|
382
382
|
"path": "skills/verify-work/SKILL.md"
|
|
383
383
|
},
|
|
384
384
|
"visual-dashboard": {
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# story: e86 / GH #182 / GH #183
|
|
3
|
+
# Tests for mechanical artifact assertions and epic audit gate.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
8
|
+
|
|
9
|
+
pass_count=0
|
|
10
|
+
fail_count=0
|
|
11
|
+
|
|
12
|
+
assert_true() {
|
|
13
|
+
local label="$1"
|
|
14
|
+
shift
|
|
15
|
+
if "$@"; then
|
|
16
|
+
echo " PASS $label"
|
|
17
|
+
pass_count=$((pass_count + 1))
|
|
18
|
+
else
|
|
19
|
+
echo " FAIL $label"
|
|
20
|
+
fail_count=$((fail_count + 1))
|
|
21
|
+
fi
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
assert_false() {
|
|
25
|
+
local label="$1"
|
|
26
|
+
shift
|
|
27
|
+
if ! "$@"; then
|
|
28
|
+
echo " PASS $label"
|
|
29
|
+
pass_count=$((pass_count + 1))
|
|
30
|
+
else
|
|
31
|
+
echo " FAIL $label"
|
|
32
|
+
fail_count=$((fail_count + 1))
|
|
33
|
+
fi
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
echo "=== Artifact & Gate Assertion Tests (GH #182, GH #183) ==="
|
|
37
|
+
|
|
38
|
+
TMP_DIR=$(mktemp -d)
|
|
39
|
+
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
40
|
+
|
|
41
|
+
cd "$TMP_DIR"
|
|
42
|
+
mkdir -p specs/product specs/epics/e01-test
|
|
43
|
+
|
|
44
|
+
# 1. Test assert-planning-artifacts.sh for scope-work (missing -> fail, present -> pass)
|
|
45
|
+
assert_false "scope-work fails when SCOPE_LATEST.yaml missing" \
|
|
46
|
+
bash "$REPO_ROOT/scripts/lib/assert-planning-artifacts.sh" scope-work
|
|
47
|
+
|
|
48
|
+
echo "scope: test" > specs/product/SCOPE_LATEST.yaml
|
|
49
|
+
assert_true "scope-work passes when SCOPE_LATEST.yaml exists and non-empty" \
|
|
50
|
+
bash "$REPO_ROOT/scripts/lib/assert-planning-artifacts.sh" scope-work
|
|
51
|
+
|
|
52
|
+
# 2. Test assert-planning-artifacts.sh for slice-tasks
|
|
53
|
+
assert_false "slice-tasks fails when no *-tasks.yaml exists" \
|
|
54
|
+
bash "$REPO_ROOT/scripts/lib/assert-planning-artifacts.sh" slice-tasks
|
|
55
|
+
|
|
56
|
+
cat > specs/epics/e01-test/e01s01-tasks.yaml <<'YAML'
|
|
57
|
+
story_id: e01s01
|
|
58
|
+
tasks: []
|
|
59
|
+
YAML
|
|
60
|
+
assert_true "slice-tasks passes when *-tasks.yaml exists" \
|
|
61
|
+
bash "$REPO_ROOT/scripts/lib/assert-planning-artifacts.sh" slice-tasks
|
|
62
|
+
|
|
63
|
+
# 3. Test assert-epic-gate.sh (Issue #182)
|
|
64
|
+
assert_false "assert-epic-gate fails when no audit report exists" \
|
|
65
|
+
bash "$REPO_ROOT/scripts/lib/assert-epic-gate.sh" commit
|
|
66
|
+
|
|
67
|
+
cat > specs/AUDIT_LATEST.md <<'MD'
|
|
68
|
+
# Audit Report
|
|
69
|
+
VERDICT: FAIL
|
|
70
|
+
MD
|
|
71
|
+
assert_false "assert-epic-gate fails when audit report is FAIL" \
|
|
72
|
+
bash "$REPO_ROOT/scripts/lib/assert-epic-gate.sh" commit
|
|
73
|
+
|
|
74
|
+
cat > specs/AUDIT_LATEST.md <<'MD'
|
|
75
|
+
# Audit Report
|
|
76
|
+
VERDICT: PASS
|
|
77
|
+
MD
|
|
78
|
+
assert_true "assert-epic-gate passes when audit report is PASS" \
|
|
79
|
+
bash "$REPO_ROOT/scripts/lib/assert-epic-gate.sh" commit
|
|
80
|
+
|
|
81
|
+
echo ""
|
|
82
|
+
echo "=== Summary: $pass_count passed, $fail_count failed ==="
|
|
83
|
+
if [ "$fail_count" -gt 0 ]; then
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
exit 0
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# story: e86 / verify-work adversarial mutation
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
7
|
+
|
|
8
|
+
echo "=== Testing verify-adversarial.sh ==="
|
|
9
|
+
|
|
10
|
+
# 1. Run self-test
|
|
11
|
+
bash "$REPO_ROOT/scripts/verify-adversarial.sh" --self-test
|
|
12
|
+
echo " PASS verify-adversarial self-test"
|
|
13
|
+
|
|
14
|
+
# 2. Run normal invocation in repo root
|
|
15
|
+
bash "$REPO_ROOT/scripts/verify-adversarial.sh"
|
|
16
|
+
echo " PASS verify-adversarial repo root run"
|
|
17
|
+
|
|
18
|
+
# 3. Assert artifact was created
|
|
19
|
+
if [[ -f "$REPO_ROOT/specs/verifications/ADVERSARIAL_LATEST.yaml" ]]; then
|
|
20
|
+
echo " PASS ADVERSARIAL_LATEST.yaml created"
|
|
21
|
+
else
|
|
22
|
+
echo " FAIL ADVERSARIAL_LATEST.yaml missing"
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
echo "=== All verify-adversarial tests passed ==="
|
|
27
|
+
exit 0
|