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.
- package/.continue/rules/context7-mcp.md +0 -0
- package/.continue/rules/diagnose-stall.md +0 -0
- package/.kilocode/rules/context7-mcp.md +0 -0
- package/.kilocode/rules/diagnose-stall.md +0 -0
- package/.pi/package.json +2 -2
- package/.pi/prompts/audit-code.md +17 -13
- package/.pi/prompts/build-epic.md +5 -0
- package/.pi/prompts/change-request.md +4 -1
- package/.pi/prompts/compose-workflow.md +17 -0
- package/.pi/prompts/context7-mcp.md +54 -0
- package/.pi/prompts/craft-skill.md +28 -0
- package/.pi/prompts/deepen-architecture.md +20 -0
- package/.pi/prompts/delegate-task.md +14 -0
- package/.pi/prompts/deploy.md +8 -0
- package/.pi/prompts/develop-tdd.md +15 -4
- package/.pi/prompts/diagnose-stall.md +53 -0
- package/.pi/prompts/dispatch-agents.md +53 -19
- package/.pi/prompts/evolve-skill.md +7 -0
- package/.pi/prompts/gate-trace.md +9 -1
- package/.pi/prompts/guard-git.md +14 -0
- package/.pi/prompts/kickoff-branch.md +4 -0
- package/.pi/prompts/migrate-spec.md +18 -0
- package/.pi/prompts/plan-work.md +62 -2
- package/.pi/prompts/publish-package.md +11 -0
- package/.pi/prompts/release-branch.md +46 -43
- package/.pi/prompts/request-review.md +57 -17
- package/.pi/prompts/research-first.md +3 -0
- package/.pi/prompts/run-benchmark.md +3 -3
- package/.pi/prompts/run-evals.md +26 -6
- package/.pi/prompts/run-planning.md +1 -0
- package/.pi/prompts/scope-work.md +3 -0
- package/.pi/prompts/search-skills.md +3 -0
- package/.pi/prompts/security-review.md +66 -12
- package/.pi/prompts/seed-conventions.md +68 -0
- package/.pi/prompts/session-state.md +5 -10
- package/.pi/prompts/slice-tasks.md +3 -0
- package/.pi/prompts/smoke-test.md +11 -0
- package/.pi/prompts/stocktake-skills.md +6 -1
- package/.pi/prompts/validate-contracts.md +12 -0
- package/.pi/prompts/validate-fix.md +2 -0
- package/.pi/prompts/verify-work.md +42 -20
- package/.pi/prompts/wire-ci.md +11 -0
- package/.pi/prompts/write-document.md +10 -0
- package/.pi/skills/audit-code/SKILL.md +17 -13
- package/.pi/skills/build-epic/SKILL.md +5 -0
- package/.pi/skills/change-request/SKILL.md +4 -1
- package/.pi/skills/compose-workflow/SKILL.md +17 -0
- package/.pi/skills/context7-mcp/SKILL.md +56 -0
- package/.pi/skills/craft-skill/SKILL.md +28 -0
- package/.pi/skills/deepen-architecture/SKILL.md +20 -0
- package/.pi/skills/delegate-task/SKILL.md +14 -0
- package/.pi/skills/deploy/SKILL.md +8 -0
- package/.pi/skills/develop-tdd/SKILL.md +15 -4
- package/.pi/skills/diagnose-stall/SKILL.md +55 -0
- package/.pi/skills/dispatch-agents/SKILL.md +53 -19
- package/.pi/skills/evolve-skill/SKILL.md +7 -0
- package/.pi/skills/gate-trace/SKILL.md +9 -1
- package/.pi/skills/guard-git/SKILL.md +14 -0
- package/.pi/skills/kickoff-branch/SKILL.md +4 -0
- package/.pi/skills/migrate-spec/SKILL.md +18 -0
- package/.pi/skills/plan-work/SKILL.md +62 -2
- package/.pi/skills/publish-package/SKILL.md +11 -0
- package/.pi/skills/release-branch/SKILL.md +46 -43
- package/.pi/skills/request-review/SKILL.md +57 -17
- package/.pi/skills/research-first/SKILL.md +3 -0
- package/.pi/skills/run-benchmark/SKILL.md +3 -3
- package/.pi/skills/run-evals/SKILL.md +26 -6
- package/.pi/skills/run-planning/SKILL.md +1 -0
- package/.pi/skills/scope-work/SKILL.md +3 -0
- package/.pi/skills/search-skills/SKILL.md +3 -0
- package/.pi/skills/security-review/SKILL.md +66 -12
- package/.pi/skills/seed-conventions/SKILL.md +68 -0
- package/.pi/skills/session-state/SKILL.md +5 -10
- package/.pi/skills/slice-tasks/SKILL.md +3 -0
- package/.pi/skills/smoke-test/SKILL.md +11 -0
- package/.pi/skills/stocktake-skills/SKILL.md +6 -1
- package/.pi/skills/validate-contracts/SKILL.md +12 -0
- package/.pi/skills/validate-fix/SKILL.md +2 -0
- package/.pi/skills/verify-work/SKILL.md +42 -20
- package/.pi/skills/wire-ci/SKILL.md +11 -0
- package/.pi/skills/write-document/SKILL.md +10 -0
- package/CHANGELOG.md +15 -0
- package/CLAUDE.md +59 -1
- package/CONVENTIONS.md +81 -0
- package/README.md +1 -1
- package/SKILL-INDEX.md +1 -1
- package/package.json +1 -1
- package/scripts/bp-churn-rank.sh +49 -0
- package/scripts/bp-read-agents.sh +1 -0
- package/scripts/check-import-boundaries.sh +64 -0
- package/scripts/compile-rule-matrix.sh +114 -0
- package/scripts/hooks/rtk-rewrite.sh +11 -0
- package/scripts/hooks/token-mgmt-pre-tool-use.sh +53 -0
- package/scripts/install.sh +6 -0
- package/scripts/lib/completeness-critic.sh +62 -0
- package/scripts/lib/doc-fetch-cache.sh +71 -0
- package/scripts/lib/golden-suite-gates.sh +3 -1
- package/scripts/lib/parallel-review-worktrees.sh +34 -0
- package/scripts/lib/plan-consistency-check.sh +88 -0
- package/scripts/lib/run-benchmark.py +210 -0
- package/scripts/lib/sync-context-engineering-ref.sh +19 -0
- package/scripts/references-manifest.yaml +19 -0
- package/scripts/run-benchmark.sh +6 -0
- package/scripts/run-skill-verify.sh +1 -0
- package/scripts/sync-references.sh +25 -0
- package/scripts/sync-skills.sh +12 -1
- package/scripts/validate-skill-catalog.sh +147 -0
- package/scripts/validate-skill-description.sh +70 -0
- package/skills/audit-code/SKILL.md +19 -13
- package/skills/build-epic/SKILL.md +6 -1
- package/skills/change-request/SKILL.md +4 -1
- package/skills/compose-workflow/SKILL.md +17 -0
- package/skills/context7-mcp/SKILL.md +57 -0
- package/skills/craft-skill/SKILL.md +29 -0
- package/skills/deepen-architecture/SKILL.md +22 -0
- package/skills/delegate-task/SKILL.md +14 -0
- package/skills/deploy/SKILL.md +9 -0
- package/skills/develop-tdd/SKILL.md +18 -4
- package/skills/diagnose-stall/SKILL.md +56 -0
- package/skills/dispatch-agents/SKILL.md +53 -19
- package/skills/elaborate-spec/SKILL.md +1 -0
- package/skills/evolve-skill/SKILL.md +7 -0
- package/skills/gate-trace/SKILL.md +11 -1
- package/skills/guard-git/REFERENCE.md +14 -0
- package/skills/kickoff-branch/SKILL.md +4 -1
- package/skills/migrate-spec/REFERENCE.md +12 -0
- package/skills/migrate-spec/SKILL.md +6 -0
- package/skills/plan-work/REFERENCE.md +29 -2
- package/skills/plan-work/SKILL.md +38 -0
- package/skills/publish-package/REFERENCE.md +11 -0
- package/skills/release-branch/REFERENCE.md +14 -0
- package/skills/release-branch/SKILL.md +33 -44
- package/skills/request-review/SKILL.md +59 -17
- package/skills/research-first/SKILL.md +3 -0
- package/skills/run-benchmark/SKILL.md +5 -4
- package/skills/run-evals/REFERENCE.md +14 -4
- package/skills/run-evals/SKILL.md +13 -2
- package/skills/run-planning/SKILL.md +1 -0
- package/skills/scope-work/SKILL.md +3 -0
- package/skills/search-skills/SKILL.md +3 -0
- package/skills/security-review/REFERENCE-false-positives.md +9 -8
- package/skills/security-review/REFERENCE-vuln-categories.md +4 -0
- package/skills/security-review/SKILL.md +53 -4
- package/skills/security-review/fixtures/CWE-79-xss-negative.js +6 -0
- package/skills/security-review/fixtures/CWE-79-xss-positive.js +6 -0
- package/skills/security-review/fixtures/CWE-89-sqli-negative.py +8 -0
- package/skills/security-review/fixtures/CWE-89-sqli-positive.py +9 -0
- package/skills/seed-conventions/REFERENCE.md +40 -0
- package/skills/seed-conventions/SKILL.md +28 -1
- package/skills/session-state/SKILL.md +5 -10
- package/skills/slice-tasks/SKILL.md +3 -0
- package/skills/smoke-test/REFERENCE.md +11 -0
- package/skills/stocktake-skills/SKILL.md +8 -1
- package/skills/validate-contracts/REFERENCE.md +12 -0
- package/skills/validate-fix/SKILL.md +3 -0
- package/skills/verify-work/REFERENCE.md +17 -0
- package/skills/verify-work/SKILL.md +25 -22
- package/skills/wire-ci/REFERENCE.md +11 -0
- package/skills/write-document/REFERENCE.md +10 -0
- 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
|
package/scripts/install.sh
CHANGED
|
@@ -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" "$@"
|
|
@@ -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"))"
|
package/scripts/sync-skills.sh
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# story:
|
|
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.
|