bigpowers 2.65.1 → 2.67.0
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/.fix_regex.sh +16 -0
- package/.hermes-verify-sed-fix.py +53 -0
- package/.pi/package.json +2 -2
- package/.pi/prompts/build-epic.md +8 -0
- package/.pi/prompts/gate-trace.md +2 -1
- package/.pi/prompts/kickoff-branch.md +19 -0
- package/.pi/prompts/maintain-wiki.md +63 -0
- package/.pi/prompts/plan-tests.md +1 -1
- package/.pi/prompts/release-branch.md +17 -13
- package/.pi/prompts/verify-work.md +9 -5
- package/.pi/skills/build-epic/SKILL.md +8 -0
- package/.pi/skills/gate-trace/SKILL.md +2 -1
- package/.pi/skills/kickoff-branch/SKILL.md +19 -0
- package/.pi/skills/maintain-wiki/SKILL.md +65 -0
- package/.pi/skills/plan-tests/SKILL.md +1 -1
- package/.pi/skills/release-branch/SKILL.md +17 -13
- package/.pi/skills/verify-work/SKILL.md +9 -5
- package/CHANGELOG.md +20 -0
- package/README.md +1 -1
- package/SKILL-INDEX.md +1 -1
- package/_test_e28s01.sh +2 -0
- package/hermes-verify-sed-fix.py +30 -0
- package/package.json +1 -1
- package/scripts/build-skill-graph.sh +151 -183
- package/scripts/check-spec-drift.sh +121 -0
- package/scripts/check-spec-version-gap.sh +143 -0
- package/scripts/decompose-conventions.sh +147 -0
- package/scripts/generate-agent-guide.sh +89 -0
- package/scripts/hermes-verify-e39s02.sh +28 -0
- package/scripts/migrate-version.sh +721 -0
- package/scripts/okf-post-sync.sh +163 -0
- package/scripts/run-golden-suite.sh +235 -27
- package/scripts/validate-okf.sh +18 -0
- package/skills/build-epic/SKILL.md +8 -0
- package/skills/gate-trace/SKILL.md +2 -1
- package/skills/kickoff-branch/SKILL.md +19 -0
- package/skills/maintain-wiki/SKILL.md +66 -0
- package/skills/plan-tests/SKILL.md +1 -1
- package/skills/release-branch/SKILL.md +17 -13
- package/skills/verify-work/SKILL.md +9 -5
- package/skills-lock.json +11 -6
- package/tests/fixtures/v1.x-project/CLAUDE.md +4 -0
- package/tests/fixtures/v1.x-project/CONVENTIONS.md +4 -0
- package/tests/fixtures/v2.0.0-project/CLAUDE.md +4 -0
- package/tests/fixtures/v2.0.0-project/CONVENTIONS.md +3 -0
- package/tests/fixtures/v2.20-project/CLAUDE.md +4 -0
- package/tests/fixtures/v2.20-project/CONVENTIONS.md +4 -0
- package/tests/run-golden-migrate-version.sh +155 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# story: e39s05
|
|
3
|
+
# Decompose CONVENTIONS.md into specs/conventions-wiki/ OKF concept bundle
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
8
|
+
CONVENTIONS="$REPO_ROOT/CONVENTIONS.md"
|
|
9
|
+
CONVENTIONS_WIKI="$REPO_ROOT/specs/conventions-wiki"
|
|
10
|
+
CONVENTIONS_INDEX="$CONVENTIONS_WIKI/index.md"
|
|
11
|
+
SKILL_GRAPH="$REPO_ROOT/specs/skill-graph.json"
|
|
12
|
+
|
|
13
|
+
show_help() {
|
|
14
|
+
cat <<EOF
|
|
15
|
+
Usage: $(basename "$0") [OPTION]
|
|
16
|
+
|
|
17
|
+
Decompose CONVENTIONS.md into specs/conventions-wiki/ OKF concept bundle.
|
|
18
|
+
Each major heading becomes a concept page with cross-references to enforcing skills.
|
|
19
|
+
|
|
20
|
+
Options:
|
|
21
|
+
--help Show this help and exit
|
|
22
|
+
EOF
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if [ "$#" -eq 1 ] && [ "$1" = "--help" ]; then
|
|
26
|
+
show_help
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
if [ ! -f "$CONVENTIONS" ]; then
|
|
31
|
+
echo "[ERROR] CONVENTIONS.md not found at $CONVENTIONS" >&2
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
mkdir -p "$CONVENTIONS_WIKI"
|
|
36
|
+
|
|
37
|
+
# Generate index page
|
|
38
|
+
cat > "$CONVENTIONS_INDEX" << 'IDXEOF'
|
|
39
|
+
---
|
|
40
|
+
type: Index
|
|
41
|
+
title: Conventions Wiki
|
|
42
|
+
context: conventions
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
# Conventions Wiki — OKF Bundle
|
|
46
|
+
|
|
47
|
+
**Generated by:** scripts/decompose-conventions.sh (e39s05)
|
|
48
|
+
|
|
49
|
+
## Convention Sections
|
|
50
|
+
|
|
51
|
+
IDXEOF
|
|
52
|
+
|
|
53
|
+
# Parse CONVENTIONS.md headings into sections
|
|
54
|
+
python3 -c "
|
|
55
|
+
import re, os, json
|
|
56
|
+
|
|
57
|
+
with open('$CONVENTIONS') as f:
|
|
58
|
+
content = f.read()
|
|
59
|
+
|
|
60
|
+
# Split on markdown headings (## or ###)
|
|
61
|
+
sections = re.split(r'^(#{2,3})\s+(.+)$', content, flags=re.MULTILINE)
|
|
62
|
+
|
|
63
|
+
# Load skill graph for cross-references
|
|
64
|
+
graph_data = {}
|
|
65
|
+
if os.path.exists('$SKILL_GRAPH'):
|
|
66
|
+
with open('$SKILL_GRAPH') as gf:
|
|
67
|
+
graph_data = json.load(gf)
|
|
68
|
+
|
|
69
|
+
convention_skills = {} # convention_name -> [skill_names]
|
|
70
|
+
|
|
71
|
+
# Build mapping from edges (skill -> convention)
|
|
72
|
+
for edge in graph_data.get('edges', []):
|
|
73
|
+
src = edge.get('source', '')
|
|
74
|
+
tgt = edge.get('target', '')
|
|
75
|
+
rel = edge.get('relation', '')
|
|
76
|
+
if rel == 'enforces' and tgt:
|
|
77
|
+
# tgt is something like 'CONVENTIONS.md §Tests;'
|
|
78
|
+
convention_name = tgt.replace('CONVENTIONS.md', '').replace('§', '').replace(';', '').strip()
|
|
79
|
+
if convention_name:
|
|
80
|
+
if convention_name not in convention_skills:
|
|
81
|
+
convention_skills[convention_name] = []
|
|
82
|
+
convention_skills[convention_name].append(src)
|
|
83
|
+
|
|
84
|
+
# Process sections
|
|
85
|
+
current_level = ''
|
|
86
|
+
current_title = ''
|
|
87
|
+
current_body = []
|
|
88
|
+
section_count = 0
|
|
89
|
+
|
|
90
|
+
for part in sections:
|
|
91
|
+
if part in ('##', '###'):
|
|
92
|
+
current_level = part
|
|
93
|
+
elif current_level and (current_title == ''):
|
|
94
|
+
current_title = part.strip()
|
|
95
|
+
elif current_level and current_title:
|
|
96
|
+
current_body.append(part)
|
|
97
|
+
elif current_level and current_title and not part.startswith('#'):
|
|
98
|
+
current_body.append(part)
|
|
99
|
+
|
|
100
|
+
# Actually let me rebuild this properly
|
|
101
|
+
lines = content.split('\n')
|
|
102
|
+
i = 0
|
|
103
|
+
sections_data = []
|
|
104
|
+
current = None
|
|
105
|
+
|
|
106
|
+
while i < len(lines):
|
|
107
|
+
line = lines[i]
|
|
108
|
+
m = re.match(r'^(###?)\s+(.+)$', line)
|
|
109
|
+
if m:
|
|
110
|
+
if current:
|
|
111
|
+
sections_data.append(current)
|
|
112
|
+
current = {
|
|
113
|
+
'level': len(m.group(1)),
|
|
114
|
+
'title': m.group(2).strip(),
|
|
115
|
+
'body': []
|
|
116
|
+
}
|
|
117
|
+
elif current:
|
|
118
|
+
current['body'].append(line)
|
|
119
|
+
i += 1
|
|
120
|
+
|
|
121
|
+
if current:
|
|
122
|
+
sections_data.append(current)
|
|
123
|
+
|
|
124
|
+
with open('$CONVENTIONS_INDEX', 'a') as idx:
|
|
125
|
+
for sec in sections_data:
|
|
126
|
+
slug = re.sub(r'[^a-z0-9]+', '-', sec['title'].lower()).strip('-')
|
|
127
|
+
sec_file = os.path.join('$CONVENTIONS_WIKI', f'{slug}.md')
|
|
128
|
+
|
|
129
|
+
# Check for enforcing skills
|
|
130
|
+
enforcing = convention_skills.get(sec['title'], [])
|
|
131
|
+
|
|
132
|
+
body_text = '\n'.join(sec['body']).strip()
|
|
133
|
+
|
|
134
|
+
with open(sec_file, 'w') as sf:
|
|
135
|
+
sf.write(f'---\ntype: Convention\ntitle: {sec[\"title\"]}\ncontext: conventions\n')
|
|
136
|
+
if enforcing:
|
|
137
|
+
sf.write(f'enforced_by:\n')
|
|
138
|
+
for sk in enforcing:
|
|
139
|
+
sf.write(f' - {sk}\n')
|
|
140
|
+
sf.write(f'---\n\n# {sec[\"title\"]}\n\n')
|
|
141
|
+
sf.write(f'{body_text}\n\n---\n*Auto-generated by scripts/decompose-conventions.sh (e39s05)*\n')
|
|
142
|
+
|
|
143
|
+
idx.write(f'- [{sec[\"title\"]}]({slug}.md)\\n')
|
|
144
|
+
section_count += 1
|
|
145
|
+
|
|
146
|
+
print(f'OK: {section_count} convention sections written to specs/conventions-wiki/')
|
|
147
|
+
"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# story: e39s06
|
|
3
|
+
# Decompose CLAUDE.md into specs/agent-guide/ for progressive disclosure
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
8
|
+
CLAUDE_MD="$REPO_ROOT/CLAUDE.md"
|
|
9
|
+
AGENT_GUIDE="$REPO_ROOT/specs/agent-guide"
|
|
10
|
+
|
|
11
|
+
show_help() {
|
|
12
|
+
cat <<EOF
|
|
13
|
+
Usage: $(basename "$0") [OPTION]
|
|
14
|
+
|
|
15
|
+
Decompose CLAUDE.md into specs/agent-guide/ OKF concept pages.
|
|
16
|
+
Each section becomes a Guide concept with thin pointers.
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--help Show this help and exit
|
|
20
|
+
EOF
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if [ "$#" -eq 1 ] && [ "$1" = "--help" ]; then
|
|
24
|
+
show_help
|
|
25
|
+
exit 0
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
if [ ! -f "$CLAUDE_MD" ]; then
|
|
29
|
+
echo "[WARN] CLAUDE.md not found — trying GEMINI.md" >&2
|
|
30
|
+
CLAUDE_MD="$REPO_ROOT/GEMINI.md"
|
|
31
|
+
if [ ! -f "$CLAUDE_MD" ]; then
|
|
32
|
+
echo "[ERROR] Neither CLAUDE.md nor GEMINI.md found" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
mkdir -p "$AGENT_GUIDE"
|
|
38
|
+
|
|
39
|
+
python3 -c "
|
|
40
|
+
import re, os
|
|
41
|
+
|
|
42
|
+
with open('$CLAUDE_MD') as f:
|
|
43
|
+
content = f.read()
|
|
44
|
+
|
|
45
|
+
lines = content.split('\n')
|
|
46
|
+
sections = []
|
|
47
|
+
current_title = ''
|
|
48
|
+
current_body = []
|
|
49
|
+
|
|
50
|
+
for line in lines:
|
|
51
|
+
m = re.match(r'^(#{2,3})\s+(.+)$', line)
|
|
52
|
+
if m:
|
|
53
|
+
if current_title:
|
|
54
|
+
sections.append((current_title, '\n'.join(current_body)))
|
|
55
|
+
current_title = m.group(2).strip()
|
|
56
|
+
current_body = []
|
|
57
|
+
elif current_title:
|
|
58
|
+
current_body.append(line)
|
|
59
|
+
|
|
60
|
+
if current_title:
|
|
61
|
+
sections.append((current_title, '\n'.join(current_body)))
|
|
62
|
+
|
|
63
|
+
guide_dir = '$AGENT_GUIDE'
|
|
64
|
+
|
|
65
|
+
with open(os.path.join(guide_dir, 'index.md'), 'w') as idx:
|
|
66
|
+
idx.write('---\ntype: Index\ntitle: Agent Guide\ncontext: guide\n---\n\n')
|
|
67
|
+
idx.write('# Agent Guide — OKF Bundle\n\n')
|
|
68
|
+
idx.write(f'**Generated by:** scripts/generate-agent-guide.sh (e39s06)\n')
|
|
69
|
+
idx.write(f'**Source:** CLAUDE.md\n\n')
|
|
70
|
+
idx.write('## Guide Sections\n\n')
|
|
71
|
+
|
|
72
|
+
for title, body in sections:
|
|
73
|
+
slug = re.sub(r'[^a-z0-9]+', '-', title.lower()).strip('-')
|
|
74
|
+
sec_file = os.path.join(guide_dir, f'{slug}.md')
|
|
75
|
+
|
|
76
|
+
with open(sec_file, 'w') as sf:
|
|
77
|
+
sf.write(f'---\ntype: Guide\ntitle: {title}\ncontext: guide\n')
|
|
78
|
+
sf.write(f'source: CLAUDE.md#{slug}\n---\n\n')
|
|
79
|
+
sf.write(f'# {title}\n\n')
|
|
80
|
+
# Thin pointer — first 200 chars
|
|
81
|
+
preview = body.strip()[:200]
|
|
82
|
+
sf.write(f'{preview}\n\n')
|
|
83
|
+
sf.write(f'> Full content: $CLAUDE_MD section \"{title}\"\n')
|
|
84
|
+
sf.write('---\n*Auto-generated by scripts/generate-agent-guide.sh*\n')
|
|
85
|
+
|
|
86
|
+
idx.write(f'- [{title}]({slug}.md)\n')
|
|
87
|
+
|
|
88
|
+
print(f'OK: {len(sections)} guide sections written to specs/agent-guide/')
|
|
89
|
+
"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Ad-hoc verification: e39s02 agent-locks protocol
|
|
3
|
+
REPO="/Users/danielvm/Developer/bigpowers"
|
|
4
|
+
ERR=0
|
|
5
|
+
echo "=== e39s02 agent-locks verification ==="
|
|
6
|
+
|
|
7
|
+
echo -n "1. agent-locks.yaml: "
|
|
8
|
+
test -f "$REPO/specs/agent-locks.yaml" || { echo "MISSING"; ERR=1; }
|
|
9
|
+
LOCKS=$(yq '.locks | length' "$REPO/specs/agent-locks.yaml" 2>/dev/null)
|
|
10
|
+
[ "$LOCKS" = "0" ] && echo "OK (0 locks)" || { echo "FAIL ($LOCKS)"; ERR=1; }
|
|
11
|
+
|
|
12
|
+
echo -n "2. kickoff-branch: "
|
|
13
|
+
grep -q 'agent-locks' "$REPO/skills/kickoff-branch/SKILL.md" && echo "OK" || { echo "FAIL"; ERR=1; }
|
|
14
|
+
|
|
15
|
+
echo -n "3. release-branch: "
|
|
16
|
+
grep -q 'agent-locks' "$REPO/skills/release-branch/SKILL.md" && echo "OK" || { echo "FAIL"; ERR=1; }
|
|
17
|
+
|
|
18
|
+
echo -n "4. CI workflow: "
|
|
19
|
+
grep -rq 'agent-locks' "$REPO/.github/workflows/" && echo "OK" || { echo "FAIL"; ERR=1; }
|
|
20
|
+
echo -n " 24h threshold: "
|
|
21
|
+
grep -q 'timedelta(hours=24)' "$REPO/.github/workflows/agent-locks.yml" && echo "OK" || { echo "FAIL"; ERR=1; }
|
|
22
|
+
echo -n " exit(1): "
|
|
23
|
+
grep -q 'sys.exit(1)' "$REPO/.github/workflows/agent-locks.yml" && echo "OK" || { echo "FAIL"; ERR=1; }
|
|
24
|
+
echo -n " hourly cron: "
|
|
25
|
+
grep -q 'cron: "0 \* \* \* \*"' "$REPO/.github/workflows/agent-locks.yml" && echo "OK" || { echo "FAIL"; ERR=1; }
|
|
26
|
+
|
|
27
|
+
[ $ERR -eq 0 ] && echo "ALL CHECKS PASSED" || echo "SOME FAILED"
|
|
28
|
+
exit $ERR
|