bigpowers 2.73.9 → 2.74.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.
Files changed (160) hide show
  1. package/.continue/rules/context7-mcp.md +0 -0
  2. package/.continue/rules/diagnose-stall.md +0 -0
  3. package/.kilocode/rules/context7-mcp.md +0 -0
  4. package/.kilocode/rules/diagnose-stall.md +0 -0
  5. package/.pi/package.json +2 -2
  6. package/.pi/prompts/audit-code.md +17 -13
  7. package/.pi/prompts/build-epic.md +5 -0
  8. package/.pi/prompts/change-request.md +4 -1
  9. package/.pi/prompts/compose-workflow.md +17 -0
  10. package/.pi/prompts/context7-mcp.md +54 -0
  11. package/.pi/prompts/craft-skill.md +28 -0
  12. package/.pi/prompts/deepen-architecture.md +20 -0
  13. package/.pi/prompts/delegate-task.md +14 -0
  14. package/.pi/prompts/deploy.md +8 -0
  15. package/.pi/prompts/develop-tdd.md +15 -4
  16. package/.pi/prompts/diagnose-stall.md +53 -0
  17. package/.pi/prompts/dispatch-agents.md +53 -19
  18. package/.pi/prompts/evolve-skill.md +7 -0
  19. package/.pi/prompts/gate-trace.md +9 -1
  20. package/.pi/prompts/guard-git.md +14 -0
  21. package/.pi/prompts/kickoff-branch.md +4 -0
  22. package/.pi/prompts/migrate-spec.md +18 -0
  23. package/.pi/prompts/plan-work.md +62 -2
  24. package/.pi/prompts/publish-package.md +11 -0
  25. package/.pi/prompts/release-branch.md +46 -43
  26. package/.pi/prompts/request-review.md +57 -17
  27. package/.pi/prompts/research-first.md +3 -0
  28. package/.pi/prompts/run-benchmark.md +3 -3
  29. package/.pi/prompts/run-evals.md +26 -6
  30. package/.pi/prompts/run-planning.md +1 -0
  31. package/.pi/prompts/scope-work.md +3 -0
  32. package/.pi/prompts/search-skills.md +3 -0
  33. package/.pi/prompts/security-review.md +66 -12
  34. package/.pi/prompts/seed-conventions.md +68 -0
  35. package/.pi/prompts/session-state.md +5 -10
  36. package/.pi/prompts/slice-tasks.md +3 -0
  37. package/.pi/prompts/smoke-test.md +11 -0
  38. package/.pi/prompts/stocktake-skills.md +6 -1
  39. package/.pi/prompts/validate-contracts.md +12 -0
  40. package/.pi/prompts/validate-fix.md +2 -0
  41. package/.pi/prompts/verify-work.md +42 -20
  42. package/.pi/prompts/wire-ci.md +11 -0
  43. package/.pi/prompts/write-document.md +10 -0
  44. package/.pi/skills/audit-code/SKILL.md +17 -13
  45. package/.pi/skills/build-epic/SKILL.md +5 -0
  46. package/.pi/skills/change-request/SKILL.md +4 -1
  47. package/.pi/skills/compose-workflow/SKILL.md +17 -0
  48. package/.pi/skills/context7-mcp/SKILL.md +56 -0
  49. package/.pi/skills/craft-skill/SKILL.md +28 -0
  50. package/.pi/skills/deepen-architecture/SKILL.md +20 -0
  51. package/.pi/skills/delegate-task/SKILL.md +14 -0
  52. package/.pi/skills/deploy/SKILL.md +8 -0
  53. package/.pi/skills/develop-tdd/SKILL.md +15 -4
  54. package/.pi/skills/diagnose-stall/SKILL.md +55 -0
  55. package/.pi/skills/dispatch-agents/SKILL.md +53 -19
  56. package/.pi/skills/evolve-skill/SKILL.md +7 -0
  57. package/.pi/skills/gate-trace/SKILL.md +9 -1
  58. package/.pi/skills/guard-git/SKILL.md +14 -0
  59. package/.pi/skills/kickoff-branch/SKILL.md +4 -0
  60. package/.pi/skills/migrate-spec/SKILL.md +18 -0
  61. package/.pi/skills/plan-work/SKILL.md +62 -2
  62. package/.pi/skills/publish-package/SKILL.md +11 -0
  63. package/.pi/skills/release-branch/SKILL.md +46 -43
  64. package/.pi/skills/request-review/SKILL.md +57 -17
  65. package/.pi/skills/research-first/SKILL.md +3 -0
  66. package/.pi/skills/run-benchmark/SKILL.md +3 -3
  67. package/.pi/skills/run-evals/SKILL.md +26 -6
  68. package/.pi/skills/run-planning/SKILL.md +1 -0
  69. package/.pi/skills/scope-work/SKILL.md +3 -0
  70. package/.pi/skills/search-skills/SKILL.md +3 -0
  71. package/.pi/skills/security-review/SKILL.md +66 -12
  72. package/.pi/skills/seed-conventions/SKILL.md +68 -0
  73. package/.pi/skills/session-state/SKILL.md +5 -10
  74. package/.pi/skills/slice-tasks/SKILL.md +3 -0
  75. package/.pi/skills/smoke-test/SKILL.md +11 -0
  76. package/.pi/skills/stocktake-skills/SKILL.md +6 -1
  77. package/.pi/skills/validate-contracts/SKILL.md +12 -0
  78. package/.pi/skills/validate-fix/SKILL.md +2 -0
  79. package/.pi/skills/verify-work/SKILL.md +42 -20
  80. package/.pi/skills/wire-ci/SKILL.md +11 -0
  81. package/.pi/skills/write-document/SKILL.md +10 -0
  82. package/CHANGELOG.md +15 -0
  83. package/CLAUDE.md +59 -1
  84. package/CONVENTIONS.md +81 -0
  85. package/README.md +1 -1
  86. package/SKILL-INDEX.md +1 -1
  87. package/package.json +1 -1
  88. package/scripts/bp-churn-rank.sh +49 -0
  89. package/scripts/bp-read-agents.sh +1 -0
  90. package/scripts/check-import-boundaries.sh +64 -0
  91. package/scripts/compile-rule-matrix.sh +114 -0
  92. package/scripts/hooks/rtk-rewrite.sh +11 -0
  93. package/scripts/hooks/token-mgmt-pre-tool-use.sh +53 -0
  94. package/scripts/install.sh +6 -0
  95. package/scripts/lib/completeness-critic.sh +62 -0
  96. package/scripts/lib/doc-fetch-cache.sh +71 -0
  97. package/scripts/lib/golden-suite-gates.sh +3 -1
  98. package/scripts/lib/parallel-review-worktrees.sh +34 -0
  99. package/scripts/lib/plan-consistency-check.sh +88 -0
  100. package/scripts/lib/run-benchmark.py +210 -0
  101. package/scripts/lib/sync-context-engineering-ref.sh +19 -0
  102. package/scripts/references-manifest.yaml +19 -0
  103. package/scripts/run-benchmark.sh +6 -0
  104. package/scripts/run-skill-verify.sh +1 -0
  105. package/scripts/sync-references.sh +25 -0
  106. package/scripts/sync-skills.sh +12 -1
  107. package/scripts/validate-skill-catalog.sh +147 -0
  108. package/scripts/validate-skill-description.sh +70 -0
  109. package/skills/audit-code/SKILL.md +19 -13
  110. package/skills/build-epic/SKILL.md +6 -1
  111. package/skills/change-request/SKILL.md +4 -1
  112. package/skills/compose-workflow/SKILL.md +17 -0
  113. package/skills/context7-mcp/SKILL.md +57 -0
  114. package/skills/craft-skill/SKILL.md +29 -0
  115. package/skills/deepen-architecture/SKILL.md +22 -0
  116. package/skills/delegate-task/SKILL.md +14 -0
  117. package/skills/deploy/SKILL.md +9 -0
  118. package/skills/develop-tdd/SKILL.md +18 -4
  119. package/skills/diagnose-stall/SKILL.md +56 -0
  120. package/skills/dispatch-agents/SKILL.md +53 -19
  121. package/skills/elaborate-spec/SKILL.md +1 -0
  122. package/skills/evolve-skill/SKILL.md +7 -0
  123. package/skills/gate-trace/SKILL.md +11 -1
  124. package/skills/guard-git/REFERENCE.md +14 -0
  125. package/skills/kickoff-branch/SKILL.md +4 -1
  126. package/skills/migrate-spec/REFERENCE.md +12 -0
  127. package/skills/migrate-spec/SKILL.md +6 -0
  128. package/skills/plan-work/REFERENCE.md +29 -2
  129. package/skills/plan-work/SKILL.md +38 -0
  130. package/skills/publish-package/REFERENCE.md +11 -0
  131. package/skills/release-branch/REFERENCE.md +14 -0
  132. package/skills/release-branch/SKILL.md +33 -44
  133. package/skills/request-review/SKILL.md +59 -17
  134. package/skills/research-first/SKILL.md +3 -0
  135. package/skills/run-benchmark/SKILL.md +5 -4
  136. package/skills/run-evals/REFERENCE.md +14 -4
  137. package/skills/run-evals/SKILL.md +13 -2
  138. package/skills/run-planning/SKILL.md +1 -0
  139. package/skills/scope-work/SKILL.md +3 -0
  140. package/skills/search-skills/SKILL.md +3 -0
  141. package/skills/security-review/REFERENCE-false-positives.md +9 -8
  142. package/skills/security-review/REFERENCE-vuln-categories.md +4 -0
  143. package/skills/security-review/SKILL.md +53 -4
  144. package/skills/security-review/fixtures/CWE-79-xss-negative.js +6 -0
  145. package/skills/security-review/fixtures/CWE-79-xss-positive.js +6 -0
  146. package/skills/security-review/fixtures/CWE-89-sqli-negative.py +8 -0
  147. package/skills/security-review/fixtures/CWE-89-sqli-positive.py +9 -0
  148. package/skills/seed-conventions/REFERENCE.md +40 -0
  149. package/skills/seed-conventions/SKILL.md +28 -1
  150. package/skills/session-state/SKILL.md +5 -10
  151. package/skills/slice-tasks/SKILL.md +3 -0
  152. package/skills/smoke-test/REFERENCE.md +11 -0
  153. package/skills/stocktake-skills/SKILL.md +8 -1
  154. package/skills/validate-contracts/REFERENCE.md +12 -0
  155. package/skills/validate-fix/SKILL.md +3 -0
  156. package/skills/verify-work/REFERENCE.md +17 -0
  157. package/skills/verify-work/SKILL.md +25 -22
  158. package/skills/wire-ci/REFERENCE.md +11 -0
  159. package/skills/write-document/REFERENCE.md +10 -0
  160. package/skills-lock.json +41 -31
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bash
2
+ # story: e45s03
3
+ # Mechanical PreToolUse backstop — block oversized Read/Grep/Bash before context bloat.
4
+ set -euo pipefail
5
+
6
+ READ_MAX_BYTES=102400 # 100KB
7
+ GREP_MAX_MATCHES=200
8
+ BASH_WARN_PATTERNS='^(npm test|pnpm test|yarn test|cargo test|go test|jest|vitest|pytest|rake test|rspec|git log|git diff|docker logs|kubectl logs|find |rg |grep )'
9
+
10
+ deny() {
11
+ echo "TOKEN-MGMT BLOCK: $1" >&2
12
+ echo "Use sqz_read_file / sqz_grep / rtk / bts compress per CLAUDE.md § Token Management." >&2
13
+ exit 2
14
+ }
15
+
16
+ INPUT="$(cat)"
17
+ TOOL="$(echo "$INPUT" | jq -r '.tool_name // .tool // empty')"
18
+ TOOL_INPUT="$(echo "$INPUT" | jq -c '.tool_input // .input // {}')"
19
+
20
+ case "$TOOL" in
21
+ Read|read)
22
+ PATH_ARG="$(echo "$TOOL_INPUT" | jq -r '.path // .file_path // .file // empty')"
23
+ [[ -n "$PATH_ARG" && -f "$PATH_ARG" ]] || exit 0
24
+ SIZE="$(wc -c < "$PATH_ARG" | tr -d ' ')"
25
+ if (( SIZE > READ_MAX_BYTES )); then
26
+ deny "Read $PATH_ARG is ${SIZE} bytes (max ${READ_MAX_BYTES}). Use sqz_read_file or bts compress."
27
+ fi
28
+ ;;
29
+ Grep|grep)
30
+ LIMIT="$(echo "$TOOL_INPUT" | jq -r '.head_limit // .max_matches // empty')"
31
+ if [[ -z "$LIMIT" || "$LIMIT" == "null" ]]; then
32
+ deny "Grep without head_limit (max ${GREP_MAX_MATCHES}). Set head_limit<=${GREP_MAX_MATCHES} or use sqz_grep."
33
+ fi
34
+ if [[ "$LIMIT" =~ ^[0-9]+$ ]] && (( LIMIT > GREP_MAX_MATCHES )); then
35
+ deny "Grep head_limit=${LIMIT} exceeds ${GREP_MAX_MATCHES}. Lower limit or use sqz_grep."
36
+ fi
37
+ ;;
38
+ Bash|bash|Shell|shell)
39
+ CMD="$(echo "$TOOL_INPUT" | jq -r '.command // empty')"
40
+ [[ -n "$CMD" ]] || exit 0
41
+ if echo "$CMD" | grep -qE 'sqz compress|bts compress|rtk |SQZ_NO_DEDUP'; then
42
+ exit 0
43
+ fi
44
+ if echo "$CMD" | grep -qE "$BASH_WARN_PATTERNS"; then
45
+ deny "Bash may exceed 500 lines of output. Prefix with rtk or pipe through sqz compress."
46
+ fi
47
+ ;;
48
+ *)
49
+ exit 0
50
+ ;;
51
+ esac
52
+
53
+ exit 0
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # story: e45s16
2
3
  # install.sh — global symlink install for bigpowers skills
3
4
  #
4
5
  # Supported tools:
@@ -83,6 +84,9 @@ install_claude() {
83
84
  link "$REPO_ROOT/.gemini/extensions/bigpowers/hooks/run-hook.cmd" "$CLAUDE_HOOKS_DIR/run-hook.cmd"
84
85
  link "$REPO_ROOT/guard-git/scripts/block-dangerous-git.sh" "$CLAUDE_HOOKS_DIR/block-dangerous-git.sh"
85
86
  link "$REPO_ROOT/guard-git/scripts/lib" "$CLAUDE_HOOKS_DIR/lib"
87
+ link "$REPO_ROOT/scripts/hooks/rtk-rewrite.sh" "$CLAUDE_HOOKS_DIR/rtk-rewrite.sh"
88
+ # story: e45s16
89
+ chmod +x "$REPO_ROOT/scripts/hooks/rtk-rewrite.sh" 2>/dev/null || true
86
90
 
87
91
  if [[ -f "$CLAUDE_SETTINGS" ]]; then
88
92
  echo " Configuring global hooks in $CLAUDE_SETTINGS..."
@@ -92,6 +96,7 @@ install_claude() {
92
96
  cat "$CLAUDE_SETTINGS" | jq '
93
97
  .hooks.SessionStart += [{"matcher":"startup|clear|compact","hooks":[{"type":"command","command":"\"'"$CLAUDE_HOOKS_DIR/run-hook.cmd"'\" session-start","async":false}]}] |
94
98
  .hooks.PreToolUse += [{"matcher":"Bash","hooks":[{"type":"command","command":"\"'"$CLAUDE_HOOKS_DIR/block-dangerous-git.sh"'\""}]}] |
99
+ .hooks.PreToolUse += [{"matcher":"Bash","hooks":[{"type":"command","command":"\"'"$CLAUDE_HOOKS_DIR/rtk-rewrite.sh"'\""}]}] |
95
100
  # deduplicate
96
101
  .hooks.SessionStart |= unique |
97
102
  .hooks.PreToolUse |= unique
@@ -115,6 +120,7 @@ uninstall_claude() {
115
120
  unlink_if_managed "$CLAUDE_HOOKS_DIR/session-start" "$REPO_ROOT/"
116
121
  unlink_if_managed "$CLAUDE_HOOKS_DIR/run-hook.cmd" "$REPO_ROOT/"
117
122
  unlink_if_managed "$CLAUDE_HOOKS_DIR/block-dangerous-git.sh" "$REPO_ROOT/"
123
+ unlink_if_managed "$CLAUDE_HOOKS_DIR/rtk-rewrite.sh" "$REPO_ROOT/"
118
124
  unlink_if_managed "$CLAUDE_HOOKS_DIR/lib" "$REPO_ROOT/"
119
125
  fi
120
126
  }
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env bash
2
+ # story: e45s05
3
+ # Adversarial gap-finding completeness critic — post gate-trace.
4
+ # Classifications: BLOCKER | WARNING | FILLED
5
+ set -euo pipefail
6
+
7
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
8
+ cd "$REPO_ROOT"
9
+
10
+ BLOCKERS=0
11
+ WARNINGS=0
12
+ FILLED=0
13
+
14
+ classify() {
15
+ local kind="$1" msg="$2"
16
+ echo "[$kind] $msg"
17
+ case "$kind" in
18
+ BLOCKER) BLOCKERS=$((BLOCKERS + 1)) ;;
19
+ WARNING) WARNINGS=$((WARNINGS + 1)) ;;
20
+ FILLED) FILLED=$((FILLED + 1)) ;;
21
+ esac
22
+ }
23
+
24
+ # Ensure upstream artifacts exist
25
+ [[ -f specs/traceability-matrix.json ]] \
26
+ || classify BLOCKER "Missing specs/traceability-matrix.json — run trace-stories.sh --json"
27
+ [[ -f specs/blind-spots.json ]] \
28
+ || classify BLOCKER "Missing specs/blind-spots.json — run check-blind-spots.sh"
29
+
30
+ if [[ -f specs/traceability-matrix.json ]]; then
31
+ UNDONE="$(jq '[.stories[]? | select(.status != "done" and (.code_tags // 0) == 0)] | length' specs/traceability-matrix.json 2>/dev/null || echo 0)"
32
+ (( UNDONE > 0 )) && classify BLOCKER "$UNDONE active story(ies) with zero code tags"
33
+ COVERAGE="$(jq -r '.summary.coverage_percent // .coverage_percent // empty' specs/traceability-matrix.json 2>/dev/null)"
34
+ if [[ -n "$COVERAGE" && "$COVERAGE" != "null" ]]; then
35
+ awk -v c="$COVERAGE" 'BEGIN{if(c+0 < 60) exit 1}' || classify WARNING "Trace coverage ${COVERAGE}% below 60% target"
36
+ awk -v c="$COVERAGE" 'BEGIN{if(c+0 >= 80) exit 0; exit 1}' && classify FILLED "Trace coverage ${COVERAGE}% meets 80% PASS bar"
37
+ fi
38
+ fi
39
+
40
+ if [[ -f specs/blind-spots.json ]]; then
41
+ HIGH="$(jq '[.findings[]? | select(.severity == "HIGH")] | length' specs/blind-spots.json 2>/dev/null || echo 0)"
42
+ (( HIGH > 0 )) && classify BLOCKER "$HIGH HIGH-severity blind-spot finding(s) remain open"
43
+ fi
44
+
45
+ # Verify evidence for done stories
46
+ if [[ -d specs/verifications ]]; then
47
+ VC="$(find specs/verifications -maxdepth 1 -name '*-verify.yaml' 2>/dev/null | wc -l | tr -d ' ')"
48
+ (( VC == 0 )) && classify WARNING "No specs/verifications/*-verify.yaml evidence bundles"
49
+ (( VC > 0 )) && classify FILLED "$VC verification evidence bundle(s) on disk"
50
+ else
51
+ classify WARNING "specs/verifications/ directory missing"
52
+ fi
53
+
54
+ echo "---"
55
+ echo "completeness-critic: BLOCKER=$BLOCKERS WARNING=$WARNINGS FILLED=$FILLED"
56
+
57
+ if (( BLOCKERS > 0 )); then
58
+ echo "MERGE GATE ABORT: BLOCKER findings must be resolved" >&2
59
+ exit 1
60
+ fi
61
+
62
+ exit 0
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env bash
2
+ # story: e45s20
3
+ # doc-fetch-cache.sh — ETag-revalidated fetch cache for Context7 / bts docs queries.
4
+ # Usage:
5
+ # bash scripts/lib/doc-fetch-cache.sh get <cache-key> # print cached body or empty
6
+ # bash scripts/lib/doc-fetch-cache.sh put <key> <etag> <body-file>
7
+ # bash scripts/lib/doc-fetch-cache.sh stale <cache-key> # exit 0 if TTL expired
8
+ set -euo pipefail
9
+
10
+ CACHE_DIR="${DOC_CACHE_DIR:-.bigpowers/cache/docs}"
11
+ TTL_SEC="${DOC_CACHE_TTL:-300}"
12
+
13
+ mkdir -p "$CACHE_DIR"
14
+
15
+ _key_path() {
16
+ local key="$1"
17
+ local hash
18
+ hash=$(printf '%s' "$key" | shasum -a 256 | awk '{print $1}')
19
+ echo "$CACHE_DIR/${hash}"
20
+ }
21
+
22
+ cmd_get() {
23
+ local key="$1" base etag_file body_file meta_file
24
+ base="$(_key_path "$key")"
25
+ body_file="${base}.body"
26
+ etag_file="${base}.etag"
27
+ meta_file="${base}.meta"
28
+
29
+ [[ -f "$body_file" && -f "$meta_file" ]] || exit 1
30
+
31
+ local cached_at now
32
+ cached_at=$(grep '^cached_at=' "$meta_file" | cut -d= -f2)
33
+ now=$(date +%s)
34
+ if [[ -n "$cached_at" && $((now - cached_at)) -gt "$TTL_SEC" ]]; then
35
+ exit 1
36
+ fi
37
+
38
+ cat "$body_file"
39
+ [[ -f "$etag_file" ]] && printf 'ETAG:%s\n' "$(cat "$etag_file")" >&2
40
+ exit 0
41
+ }
42
+
43
+ cmd_put() {
44
+ local key="$1" etag="$2" body_file="$3" base
45
+ base="$(_key_path "$key")"
46
+ cp "$body_file" "${base}.body"
47
+ printf '%s' "$etag" > "${base}.etag"
48
+ printf 'cached_at=%s\nkey=%s\n' "$(date +%s)" "$key" > "${base}.meta"
49
+ }
50
+
51
+ cmd_stale() {
52
+ local key="$1" base meta_file
53
+ base="$(_key_path "$key")"
54
+ meta_file="${base}.meta"
55
+ [[ -f "$meta_file" ]] || exit 0
56
+ local cached_at now
57
+ cached_at=$(grep '^cached_at=' "$meta_file" | cut -d= -f2)
58
+ now=$(date +%s)
59
+ [[ $((now - cached_at)) -gt "$TTL_SEC" ]] && exit 0
60
+ exit 1
61
+ }
62
+
63
+ case "${1:-}" in
64
+ get) cmd_get "${2:?key}" ;;
65
+ put) cmd_put "${2:?key}" "${3:?etag}" "${4:?body}" ;;
66
+ stale) cmd_stale "${2:?key}" ;;
67
+ *)
68
+ echo "Usage: doc-fetch-cache.sh get|put|stale <key> [etag] [body-file]" >&2
69
+ exit 2
70
+ ;;
71
+ esac
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # story: e42s04 e45s02
2
+ # story: e42s04 e45s02 e45s14
3
3
  # Deterministic gate runner for golden suite — sourced by golden-suite-run.sh
4
4
 
5
5
  if [ -n "${GOLDEN_GATES_LOADED:-}" ]; then return 0; fi
@@ -14,6 +14,8 @@ GOLDEN_GATES=(
14
14
  "g09-yaml-roundtrip:bash scripts/golden-g09-yaml-roundtrip.sh:false"
15
15
  "g10-trace-anti-vacuity:bash scripts/golden-g10-trace-anti-vacuity.sh:false"
16
16
  "g11-gitignore-venv:bash scripts/golden-g11-gitignore-venv.sh:false"
17
+ "import-boundaries:bash scripts/check-import-boundaries.sh:false"
18
+ "skill-catalog:bash scripts/validate-skill-catalog.sh:false"
17
19
  "specs-parse:bash scripts/validate-specs-yaml.sh:false"
18
20
  )
19
21
 
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bash
2
+ # story: e45s18
3
+ # parallel-review-worktrees.sh — isolated git worktrees for parallel audit-code / security-review
4
+ # Usage: bash scripts/lib/parallel-review-worktrees.sh <audit-code|security-review>
5
+ set -euo pipefail
6
+
7
+ CHECK="${1:?usage: parallel-review-worktrees.sh <audit-code|security-review>}"
8
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
9
+ cd "$REPO_ROOT"
10
+
11
+ BASE=".bigpowers/worktrees/review-${CHECK}"
12
+ mkdir -p "$(dirname "$BASE")"
13
+
14
+ if git worktree list | grep -q "$BASE"; then
15
+ git worktree remove --force "$BASE" 2>/dev/null || true
16
+ fi
17
+
18
+ git worktree add --detach "$BASE" HEAD >/dev/null
19
+ echo "WORKTREE: $BASE (detached @ $(git -C "$BASE" rev-parse --short HEAD))"
20
+
21
+ case "$CHECK" in
22
+ audit-code)
23
+ echo "Run audit-code checklist inside worktree; reports → specs/verifications/"
24
+ ;;
25
+ security-review)
26
+ echo "Run security-review 5-phase scan inside worktree; reports → specs/security/"
27
+ ;;
28
+ *)
29
+ echo "Unknown check: $CHECK" >&2
30
+ exit 2
31
+ ;;
32
+ esac
33
+
34
+ echo "OK: isolated worktree ready — parallel checks cannot corrupt parent working tree"
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env bash
2
+ # story: e45s04
3
+ # Pre-build cross-artifact consistency — slice-tasks output vs epic capsule.
4
+ # Severity: CRITICAL | HIGH | MED | LOW (LOW is informational only).
5
+ set -euo pipefail
6
+
7
+ CAPSULE="${1:-}"
8
+ if [[ -z "$CAPSULE" || ! -d "$CAPSULE" ]]; then
9
+ echo "Usage: bash scripts/lib/plan-consistency-check.sh specs/epics/eNN-slug" >&2
10
+ exit 2
11
+ fi
12
+
13
+ EPIC_YAML="$CAPSULE/epic.yaml"
14
+ CRITICAL=0
15
+ HIGH=0
16
+ MED=0
17
+
18
+ report() {
19
+ local sev="$1" msg="$2"
20
+ echo "[$sev] $msg"
21
+ case "$sev" in
22
+ CRITICAL) CRITICAL=$((CRITICAL + 1)) ;;
23
+ HIGH) HIGH=$((HIGH + 1)) ;;
24
+ MED) MED=$((MED + 1)) ;;
25
+ esac
26
+ }
27
+
28
+ [[ -f "$EPIC_YAML" ]] || report CRITICAL "Missing epic.yaml in $CAPSULE"
29
+
30
+ # Story IDs declared in epic.yaml
31
+ declare -A EPIC_STORIES=()
32
+ if [[ -f "$EPIC_YAML" ]]; then
33
+ while IFS= read -r sid; do
34
+ [[ -n "$sid" ]] && EPIC_STORIES["$sid"]=1
35
+ done < <(grep -E '^[[:space:]]*- id: e[0-9]+s[0-9]+' "$EPIC_YAML" | awk '{print $3}')
36
+ fi
37
+
38
+ shopt -s nullglob
39
+ SPECS=("$CAPSULE"/e*s*.md)
40
+ TASKS=("$CAPSULE"/e*s*-tasks.yaml)
41
+ shopt -u nullglob
42
+
43
+ (( ${#SPECS[@]} > 0 )) || report CRITICAL "No story spec .md files in capsule (run slice-tasks first)"
44
+ (( ${#TASKS[@]} > 0 )) || report CRITICAL "No *-tasks.yaml files in capsule (run plan-work first)"
45
+
46
+ declare -A SPEC_IDS=()
47
+ for spec in "${SPECS[@]}"; do
48
+ base="$(basename "$spec" .md)"
49
+ sid="$(echo "$base" | grep -oE 'e[0-9]+s[0-9]+' | head -1)"
50
+ [[ -n "$sid" ]] || continue
51
+ SPEC_IDS["$sid"]=1
52
+ [[ -n "${EPIC_STORIES[$sid]+x}" ]] || report HIGH "Story $sid in spec file but missing from epic.yaml manifest"
53
+ grep -qE '^## (17\.|Acceptance|Verification Script)' "$spec" \
54
+ || report HIGH "Story $sid spec missing §17 acceptance criteria or Verification Script"
55
+ grep -qiE 'ambiguous|TBD|TODO|FIXME' "$spec" \
56
+ && report MED "Story $sid spec contains ambiguous/TBD markers"
57
+ done
58
+
59
+ for tasks in "${TASKS[@]}"; do
60
+ base="$(basename "$tasks" -tasks.yaml)"
61
+ sid="$(echo "$base" | grep -oE 'e[0-9]+s[0-9]+' | head -1)"
62
+ [[ -n "$sid" ]] || continue
63
+ [[ -n "${SPEC_IDS[$sid]+x}" ]] || report CRITICAL "tasks.yaml for $sid without matching story spec .md"
64
+ grep -qE '^[[:space:]]*verify:' "$tasks" \
65
+ || report CRITICAL "Story $sid tasks.yaml missing runnable verify: commands"
66
+ grep -qE '^status:[[:space:]]*(failing|todo|passing)' "$tasks" \
67
+ || report MED "Story $sid tasks.yaml should use status: failing|passing ledger (e45s06)"
68
+ done
69
+
70
+ for sid in "${!EPIC_STORIES[@]}"; do
71
+ [[ -n "${SPEC_IDS[$sid]+x}" ]] || report HIGH "epic.yaml lists $sid but no story spec .md exists"
72
+ done
73
+
74
+ echo "---"
75
+ echo "plan-consistency-check: CRITICAL=$CRITICAL HIGH=$HIGH MED=$MED"
76
+
77
+ if (( CRITICAL > 0 || HIGH > 0 )); then
78
+ echo "BLOCKED: resolve CRITICAL/HIGH before code generation" >&2
79
+ exit 1
80
+ fi
81
+
82
+ if (( MED > 0 )); then
83
+ echo "WARN: MED findings present — confirm with user before build"
84
+ exit 0
85
+ fi
86
+
87
+ echo "PASS: capsule artifacts consistent"
88
+ exit 0
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env python3
2
+ # story: e45s01
3
+ """Run skill benchmarks from specs/benchmarks/ with train/validation split and delta grading."""
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import subprocess
9
+ import sys
10
+ from datetime import date
11
+ from pathlib import Path
12
+
13
+ import yaml
14
+
15
+ REPO_ROOT = Path(__file__).resolve().parents[2]
16
+ BENCH_DIR = REPO_ROOT / "specs" / "benchmarks"
17
+ REPORTS_DIR = BENCH_DIR / "reports"
18
+ DEFAULT_RUNS = 3
19
+ GRADER_TIMEOUT = 15
20
+
21
+
22
+ def load_definition(skill: str) -> dict:
23
+ path = BENCH_DIR / f"{skill}.yaml"
24
+ if not path.exists():
25
+ print(f"ERROR: no benchmark definition at {path}", file=sys.stderr)
26
+ sys.exit(1)
27
+ with path.open() as f:
28
+ return yaml.safe_load(f)
29
+
30
+
31
+ def list_skills() -> list[str]:
32
+ return sorted(p.stem for p in BENCH_DIR.glob("*.yaml") if p.stem not in ("axes",))
33
+
34
+
35
+ def run_code_grader(command: str, cwd: Path) -> bool:
36
+ try:
37
+ result = subprocess.run(
38
+ ["bash", "-c", command],
39
+ cwd=cwd,
40
+ capture_output=True,
41
+ text=True,
42
+ timeout=GRADER_TIMEOUT,
43
+ )
44
+ out = (result.stdout + result.stderr).strip()
45
+ if "PASS" in out.upper() and "FAIL" not in out.upper():
46
+ return True
47
+ return result.returncode == 0
48
+ except (subprocess.TimeoutExpired, OSError):
49
+ return False
50
+
51
+
52
+ def scenario_pass_rate(scenario: dict, runs: int, with_skill: bool) -> tuple[float, str]:
53
+ grader = scenario.get("grader", {})
54
+ gtype = grader.get("type", "code")
55
+ if gtype == "rubric":
56
+ return (-1.0, "pending_agent_eval")
57
+ if gtype != "code":
58
+ return (-1.0, "unsupported_grader")
59
+ command = grader.get("command", "")
60
+ if not command:
61
+ return (-1.0, "missing_command")
62
+ if not with_skill:
63
+ command = f"test -f /dev/null" # bare agent: code graders cannot pass without skill context
64
+ passes = sum(1 for _ in range(runs) if run_code_grader(command, REPO_ROOT))
65
+ return (passes / runs, "code")
66
+
67
+
68
+ def pass_at_k(scenarios: list[dict], runs: int, with_skill: bool) -> float:
69
+ total_weight = 0.0
70
+ weighted = 0.0
71
+ for sc in scenarios:
72
+ rate, status = scenario_pass_rate(sc, runs, with_skill)
73
+ if status == "pending_agent_eval":
74
+ continue
75
+ weight = float(sc.get("weight", 1.0))
76
+ total_weight += weight
77
+ weighted += weight * max(rate, 0.0)
78
+ if total_weight == 0:
79
+ return 0.0
80
+ return round(weighted / total_weight, 2)
81
+
82
+
83
+ def partition_scenarios(scenarios: list[dict]) -> tuple[list[dict], list[dict]]:
84
+ train, validation = [], []
85
+ for sc in scenarios:
86
+ split = sc.get("split", "validation")
87
+ if split == "train":
88
+ train.append(sc)
89
+ else:
90
+ validation.append(sc)
91
+ return train, validation
92
+
93
+
94
+ def build_split_report(scenarios: list[dict], runs: int) -> dict:
95
+ if not scenarios:
96
+ return {"with_skill": 0.0, "without_skill": 0.0, "delta": 0.0, "scenarios": []}
97
+ with_score = pass_at_k(scenarios, runs, with_skill=True)
98
+ without_score = pass_at_k(scenarios, runs, with_skill=False)
99
+ return {
100
+ "with_skill": with_score,
101
+ "without_skill": without_score,
102
+ "delta": round(with_score - without_score, 2),
103
+ "scenarios": [sc["id"] for sc in scenarios],
104
+ }
105
+
106
+
107
+ def scenario_details(scenarios: list[dict], runs: int) -> list[dict]:
108
+ rows = []
109
+ for sc in scenarios:
110
+ with_rate, status = scenario_pass_rate(sc, runs, with_skill=True)
111
+ without_rate, _ = scenario_pass_rate(sc, runs, with_skill=False)
112
+ if status == "pending_agent_eval":
113
+ rows.append(
114
+ {
115
+ "id": sc["id"],
116
+ "split": sc.get("split", "validation"),
117
+ "status": "pending_agent_eval",
118
+ "weight": sc.get("weight", 1.0),
119
+ }
120
+ )
121
+ continue
122
+ rows.append(
123
+ {
124
+ "id": sc["id"],
125
+ "split": sc.get("split", "validation"),
126
+ "with_pass_rate": round(max(with_rate, 0.0), 2),
127
+ "without_pass_rate": round(max(without_rate, 0.0), 2),
128
+ "delta": round(max(with_rate, 0.0) - max(without_rate, 0.0), 2),
129
+ "weight": sc.get("weight", 1.0),
130
+ }
131
+ )
132
+ return rows
133
+
134
+
135
+ def run_benchmark(skill: str, baseline: bool = False) -> dict:
136
+ definition = load_definition(skill)
137
+ runs = int(definition.get("runs", DEFAULT_RUNS))
138
+ scenarios = definition.get("scenarios", [])
139
+ train_sc, val_sc = partition_scenarios(scenarios)
140
+ today = date.today().isoformat()
141
+ report = {
142
+ "skill": skill,
143
+ "run_date": today,
144
+ "runs_per_scenario": runs,
145
+ "train": build_split_report(train_sc, runs),
146
+ "validation": build_split_report(val_sc, runs),
147
+ "scenarios": scenario_details(scenarios, runs),
148
+ }
149
+ REPORTS_DIR.mkdir(parents=True, exist_ok=True)
150
+ yaml_path = REPORTS_DIR / f"BENCHMARK-{skill}-{today}.yaml"
151
+ json_path = REPORTS_DIR / f"benchmark-{skill}.json"
152
+ with yaml_path.open("w") as f:
153
+ yaml.dump(
154
+ {
155
+ "skill": skill,
156
+ "run_date": today,
157
+ "runs_per_scenario": runs,
158
+ "train": {
159
+ "pass_at_k_with": report["train"]["with_skill"],
160
+ "pass_at_k_without": report["train"]["without_skill"],
161
+ "delta": report["train"]["delta"],
162
+ },
163
+ "validation": {
164
+ "pass_at_k_with": report["validation"]["with_skill"],
165
+ "pass_at_k_without": report["validation"]["without_skill"],
166
+ "delta": report["validation"]["delta"],
167
+ },
168
+ "scenarios": report["scenarios"],
169
+ },
170
+ f,
171
+ default_flow_style=False,
172
+ )
173
+ with json_path.open("w") as f:
174
+ json.dump(report, f, separators=(",", ":"))
175
+ print(f"Wrote {yaml_path}")
176
+ print(f"Wrote {json_path}")
177
+ if baseline:
178
+ import shutil
179
+
180
+ shutil.copy(yaml_path, REPORTS_DIR / f"BASELINE-{skill}.yaml")
181
+ shutil.copy(json_path, REPORTS_DIR / f"baseline-{skill}.json")
182
+ print(f"Pinned baseline for {skill}")
183
+ val_delta = report["validation"]["delta"]
184
+ if val_delta < 0:
185
+ print(f"REGRESSION: validation Δ {val_delta} — do NOT ship")
186
+ elif val_delta < 0.05:
187
+ print(f"WARN: validation Δ {val_delta} — marginal contribution")
188
+ else:
189
+ print(f"OK: validation Δ {val_delta}")
190
+ return report
191
+
192
+
193
+ def main() -> None:
194
+ parser = argparse.ArgumentParser(description="Run skill quality benchmarks")
195
+ parser.add_argument("skill", nargs="?", help="Skill name to benchmark")
196
+ parser.add_argument("--all", action="store_true", help="Benchmark all skills with definitions")
197
+ parser.add_argument("--baseline", action="store_true", help="Pin results as baseline")
198
+ args = parser.parse_args()
199
+ if args.all:
200
+ for skill in list_skills():
201
+ run_benchmark(skill, baseline=args.baseline)
202
+ elif args.skill:
203
+ run_benchmark(args.skill, baseline=args.baseline)
204
+ else:
205
+ parser.print_help()
206
+ sys.exit(1)
207
+
208
+
209
+ if __name__ == "__main__":
210
+ main()
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bash
2
+ # story: e45s10
3
+ # Refresh context-engineering.md sync stamp from SSOT (CLAUDE.md + PRINCIPLES.md).
4
+ set -euo pipefail
5
+
6
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
7
+ TARGET="$REPO_ROOT/docs/references/context-engineering.md"
8
+ STAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
9
+
10
+ [[ -f "$TARGET" ]] || exit 0
11
+
12
+ if grep -q 'Last synced:' "$TARGET"; then
13
+ sed -i.bak "s/\*\*Last synced:\*\*.*/\*\*Last synced:\*\* ${STAMP} (from CLAUDE.md + PRINCIPLES.md)/" "$TARGET"
14
+ rm -f "${TARGET}.bak"
15
+ else
16
+ printf '\n**Last synced:** %s (from CLAUDE.md + PRINCIPLES.md)\n' "$STAMP" >> "$TARGET"
17
+ fi
18
+
19
+ echo "sync-context-engineering-ref: stamped $TARGET"
@@ -0,0 +1,19 @@
1
+ # story: e45s10
2
+ # SSOT → docs/references distillation manifest.
3
+ # Each entry: source globs/files regenerate target via generator script.
4
+ version: 1
5
+ generated_at_field: docs/references/.sync-stamp
6
+
7
+ entries:
8
+ - id: model-profiles-catalog
9
+ sources:
10
+ - skills/*/SKILL.md
11
+ target: docs/references/model-profiles.md
12
+ generator: scripts/generate-reference-tables.sh
13
+
14
+ - id: context-engineering
15
+ sources:
16
+ - CLAUDE.md
17
+ - docs/PRINCIPLES.md
18
+ target: docs/references/context-engineering.md
19
+ generator: scripts/lib/sync-context-engineering-ref.sh
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ # story: e45s01
3
+ # run-benchmark.sh — N-run with/without-skill delta grading + train/validation split.
4
+ set -euo pipefail
5
+ source "$(dirname "${BASH_SOURCE[0]}")/lib/python-env.sh"
6
+ exec "$PYTHON" "$(dirname "${BASH_SOURCE[0]}")/lib/run-benchmark.py" "$@"
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # story: e22s01
2
3
  # Run all SKILL.md → verify: commands and report PASS/FAIL/SKIP.
3
4
  # Exit 0 only when zero FAILs.
4
5
  # Usage: bash scripts/run-skill-verify.sh [skill-name]
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env bash
2
+ # story: e45s10
3
+ # Regenerate docs/references from SSOT sources (see scripts/references-manifest.yaml).
4
+ # Schedule: weekly via .github/workflows/sync-references.yml; also safe to run locally.
5
+ set -euo pipefail
6
+
7
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
8
+ MANIFEST="$REPO_ROOT/scripts/references-manifest.yaml"
9
+ STAMP_FILE="$REPO_ROOT/docs/references/.sync-stamp"
10
+
11
+ cd "$REPO_ROOT"
12
+ [[ -f "$MANIFEST" ]] || { echo "sync-references: missing manifest" >&2; exit 1; }
13
+
14
+ run_generator() {
15
+ local gen="$1"
16
+ [[ -x "$REPO_ROOT/$gen" || -f "$REPO_ROOT/$gen" ]] || { echo "sync-references: generator not found: $gen" >&2; exit 1; }
17
+ bash "$REPO_ROOT/$gen"
18
+ }
19
+
20
+ # model-profiles catalog
21
+ run_generator scripts/generate-reference-tables.sh
22
+ run_generator scripts/lib/sync-context-engineering-ref.sh
23
+
24
+ date -u +%Y-%m-%dT%H:%M:%SZ > "$STAMP_FILE"
25
+ echo "sync-references: OK (stamp $(cat "$STAMP_FILE"))"
@@ -1,5 +1,16 @@
1
1
  #!/usr/bin/env bash
2
- # story: e13s03 e28s03 e39s04
2
+ # story: e05s01
3
+ # story: e12s01
4
+ # story: e12s02
5
+ # story: e12s03
6
+ # story: e12s04
7
+ # story: e12s06
8
+ # story: e13s03
9
+ # story: e28s02
10
+ # story: e28s03
11
+ # story: e39s04
12
+ # story: e29s01
13
+ # story: e29s02
3
14
  # sync-skills.sh — generate Cursor, Gemini CLI, pi, and OKF artifacts from SKILL.md source files
4
15
  # Architecture: Parse→IR→Render. Each target is its own render_<target>() function.
5
16
  # Run this after adding or updating any skill. Symlinks carry changes through automatically.