bigpowers 2.58.0 → 2.58.2

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/.pi/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigpowers",
3
- "version": "2.58.0",
3
+ "version": "2.58.2",
4
4
  "description": "73 skills — 72 agent skills synthesizing 17 years of software engineering discipline into a prescriptive methodology for solo developers",
5
5
  "keywords": [
6
6
  "pi-package"
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [2.58.2](https://github.com/danielvm-git/bigpowers/compare/v2.58.1...v2.58.2) (2026-07-03)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **gates:** restore lost gap-closure fixes — e13s02 tag, validate-okf.sh, waivers, version ([3ddc000](https://github.com/danielvm-git/bigpowers/commit/3ddc0003288f65a5a7c3f681588d6281a6f83a05))
7
+
8
+ ## [2.58.1](https://github.com/danielvm-git/bigpowers/compare/v2.58.0...v2.58.1) (2026-07-03)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **specs:** sync epic capsule release labels to release trains ([15b18f4](https://github.com/danielvm-git/bigpowers/commit/15b18f4a45f43cade81e19250458e404eea1b24f))
14
+
1
15
  # [2.58.0](https://github.com/danielvm-git/bigpowers/compare/v2.57.0...v2.58.0) (2026-07-03)
2
16
 
3
17
 
package/CONVENTIONS.md CHANGED
@@ -231,3 +231,15 @@ name must return < 5 results across the repo.
231
231
  | `grill-with-docs` | three-word verb-prep-noun | Variant of `grill-me`; the `-with-docs` suffix is the distinguishing feature — collapsing it would hide the doc-grounded contract |
232
232
 
233
233
  Any new exception requires an entry in this table before the skill is published.
234
+
235
+ ## File-Size Exceptions
236
+
237
+ The 300-line file cap exists to ensure files fit in a single agent context
238
+ window. The following files are documented exceptions:
239
+
240
+ | File | Lines | Rationale | Review date |
241
+ |------|-------|-----------|-------------|
242
+ | `scripts/trace-stories.sh` | 613 | Parse-match-report phases are tightly coupled; splitting introduces grep-fragile inter-script state and breaks `set -e` error propagation. Tracked as P3 technical debt (BUG-2026-07-03-trace-stories-613-line). | 2026-10-01 |
243
+ | `scripts/audit-compliance.sh` | ~280 | Gherkin harness with embedded judge logic and waiver subsystem; splitting the judge loop from the reporting layer would require fragile state-passing. Approaching the 300-line cap; monitor. | 2026-10-01 |
244
+
245
+ Any new exception requires an entry in this table with rationale and a review date.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigpowers",
3
- "version": "2.58.0",
3
+ "version": "2.58.2",
4
4
  "description": "72 agent skills synthesizing 17 years of software engineering discipline into a prescriptive methodology for solo developers",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # story: e13s02
2
3
  # generate-skill-index.sh — Auto-generate SKILL-INDEX.md from skills-lock.json + SKILL.md frontmatter
3
4
  # This file is called by sync-skills.sh. Output is SKILL-INDEX.md at repo root.
4
5
  # DO NOT edit SKILL-INDEX.md manually — it is auto-generated.
@@ -1,27 +1,35 @@
1
1
  #!/usr/bin/env bash
2
+ # story: e38s09
2
3
  #
3
- # validate-okf.sh — provenance gate for OKF story-metrics bundles (e40/e31 style).
4
+ # validate-okf.sh — provenance gate for OKF bundles (e40/e31/e44 style).
4
5
  #
5
- # A bundle is valid iff:
6
+ # Kind-aware: validates story-metrics, spec-migration, and migration-registry
7
+ # bundles against their respective schemas. Fail-closed: unknown flags exit 2,
8
+ # missing directories exit 1. Multi-dir default scans specs/metrics/ AND
9
+ # specs/migrations/.
10
+ #
11
+ # A story-metrics bundle is valid iff:
6
12
  # 1. The generator ran (generator field matches scripts/record-cycle-time.sh).
7
13
  # 2. commit_range resolves to real commits in the repo.
8
14
  # 3. Source enum is valid (measured|estimated|backfilled).
9
- # 4. Required keys are present with correct aggregation tags.
15
+ # 4. Required keys are present with non-null values.
16
+ #
17
+ # A spec-migration bundle is valid iff:
18
+ # 1. id, title, since_version, order, actions_needed are present.
19
+ # 2. fingerprint.any has at least one file/exists check.
20
+ #
21
+ # A migration-registry bundle is valid iff:
22
+ # 1. migrations list has at least one entry with id + file + status.
10
23
  #
11
24
  # This script gates on PROVENANCE, NEVER on a specific metric value.
12
- # Gate on freshness (did the right generator run?) not on outcomes.
13
25
  #
14
26
  # Usage:
15
- # scripts/validate-okf.sh [--dir <path>] [--help]
16
- # scripts/validate-okf.sh --bundle <file> # validate a single bundle
27
+ # scripts/validate-okf.sh [--dir <path>] [--bundle <file>] [--help]
17
28
  #
18
29
  set -euo pipefail
19
30
 
20
31
  ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || { echo "validate-okf: not inside a git repo"; exit 1; }
21
- METRICS_DIR="$ROOT/specs/metrics"
22
32
  EXIT_CODE=0
23
- REQUIRED_KEYS="id epic bcps commit_range source generated_at generator"
24
- VALID_SOURCES="measured estimated backfilled"
25
33
 
26
34
  RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; NC='\033[0m'
27
35
 
@@ -30,30 +38,36 @@ usage() {
30
38
  Usage: scripts/validate-okf.sh [flags]
31
39
 
32
40
  Flags:
33
- --dir <path> Validate all OKF bundles in directory (default: specs/metrics/)
41
+ --dir <path> Validate all OKF bundles in directory
34
42
  --bundle <file> Validate a single OKF bundle
35
43
  --help Show this message
36
44
 
37
45
  Description:
38
- Provenance gate for OKF story-metrics bundles. Validates that:
39
- - Required keys are present (id, epic, bcps, commit_range, source, generated_at, generator)
40
- - Source enum is valid (measured|estimated|backfilled)
41
- - Generator matches scripts/record-cycle-time.sh
42
- - commit_range resolves to real commits
43
- - Aggregation tags are present (Σ, ⌀, %, •)
44
-
45
- NEVER gates on a specific metric value — only on provenance and freshness.
46
+ Kind-aware provenance gate for OKF bundles. Without flags, validates all
47
+ bundles in specs/metrics/ AND specs/migrations/. NEVER gates on a specific
48
+ metric value — only on provenance and schema conformance.
49
+
50
+ OKF kinds validated:
51
+ story-metrics — effort/lead-time provenance (e40)
52
+ spec-migration — migration bundle schema (e44)
53
+ migration-registry — registry index integrity (e44)
46
54
  EOF
47
55
  exit 0
48
56
  }
49
57
 
50
- # Parse a single YAML frontmatter block from an OKF bundle .md file.
51
- # Returns the frontmatter as JSON via Python (which handles YAML safely).
58
+ # ---- YAML frontmatter parser (datetime-safe) ---------------------------
52
59
  parse_frontmatter() {
53
60
  local file="$1"
54
- # Extract YAML frontmatter between --- markers
55
61
  python3 -c "
56
- import yaml, sys
62
+ import yaml, sys, json
63
+
64
+ class SafeEncoder(json.JSONEncoder):
65
+ def default(self, obj):
66
+ try:
67
+ return super().default(obj)
68
+ except TypeError:
69
+ return str(obj)
70
+
57
71
  content = open('$file').read()
58
72
  parts = content.split('---')
59
73
  if len(parts) < 3:
@@ -62,137 +76,226 @@ try:
62
76
  fm = yaml.safe_load(parts[1])
63
77
  if fm is None:
64
78
  sys.exit(1)
65
- # Emit as JSON for bash
66
- import json
67
- print(json.dumps(fm))
79
+ print(json.dumps(fm, cls=SafeEncoder))
68
80
  except Exception as e:
69
- print(f'validate-okf: YAML parse error in $file: {e}', file=sys.stderr)
81
+ print(f'YAML parse error: {e}', file=sys.stderr)
70
82
  sys.exit(1)
71
83
  " 2>/dev/null
72
84
  }
73
85
 
74
- validate_bundle() {
75
- local file="$1"
76
- local bundle_name; bundle_name="$(basename "$file")"
77
-
78
- # Parse frontmatter
79
- local fm
80
- fm="$(parse_frontmatter "$file")" || {
81
- printf "${RED}FAIL${NC} %s: cannot parse YAML frontmatter\n" "$bundle_name"
82
- EXIT_CODE=1
83
- return
84
- }
86
+ # ---- Kind-specific validators ------------------------------------------
85
87
 
86
- # Check okf_kind
87
- local kind
88
- kind="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('okf_kind',''))" 2>/dev/null)"
89
- if [ "$kind" != "story-metrics" ]; then
90
- printf "${YELLOW}SKIP${NC} %s: not a story-metrics bundle (kind=%s)\n" "$bundle_name" "${kind:-none}"
91
- return
92
- fi
88
+ validate_story_metrics() {
89
+ local file="$1" fm="$2" name="$3"
90
+ local errs=0
93
91
 
94
- # Check required keys
95
- for key in $REQUIRED_KEYS; do
92
+ # Required keys
93
+ for key in id epic bcps commit_range source generated_at generator; do
96
94
  local val
97
95
  val="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('$key',''))" 2>/dev/null)"
98
96
  if [ -z "$val" ] || [ "$val" = "null" ] || [ "$val" = "None" ]; then
99
- printf "${RED}FAIL${NC} %s: missing required key '%s'\n" "$bundle_name" "$key"
100
- EXIT_CODE=1
101
- return
97
+ printf "${RED}FAIL${NC} %s: missing required key '%s'\n" "$name" "$key"
98
+ errs=$((errs + 1))
102
99
  fi
103
100
  done
101
+ [ "$errs" -gt 0 ] && { EXIT_CODE=1; return; }
104
102
 
105
- # Check source enum
103
+ # Source enum
106
104
  local source
107
- source="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['source'])" 2>/dev/null)"
108
- if ! echo "$VALID_SOURCES" | grep -qw "$source"; then
109
- printf "${RED}FAIL${NC} %s: invalid source '%s' — must be one of: %s\n" "$bundle_name" "$source" "$VALID_SOURCES"
110
- EXIT_CODE=1
111
- return
105
+ source="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('source',''))" 2>/dev/null)"
106
+ if ! echo "measured estimated backfilled" | grep -qw "$source"; then
107
+ printf "${RED}FAIL${NC} %s: invalid source '%s' — must be measured|estimated|backfilled\n" "$name" "$source"
108
+ EXIT_CODE=1; return
112
109
  fi
113
110
 
114
- # Check generator
111
+ # Generator
115
112
  local generator
116
- generator="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['generator'])" 2>/dev/null)"
113
+ generator="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('generator',''))" 2>/dev/null)"
117
114
  if [ "$generator" != "scripts/record-cycle-time.sh" ]; then
118
- printf "${RED}FAIL${NC} %s: wrong generator '%s' — expected scripts/record-cycle-time.sh\n" "$bundle_name" "$generator"
119
- EXIT_CODE=1
120
- return
115
+ printf "${RED}FAIL${NC} %s: wrong generator '%s' — expected scripts/record-cycle-time.sh\n" "$name" "$generator"
116
+ EXIT_CODE=1; return
121
117
  fi
122
118
 
123
- # Check commit_range resolves
119
+ # commit_range resolves
124
120
  local commit_range
125
- commit_range="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['commit_range'])" 2>/dev/null)"
121
+ commit_range="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('commit_range',''))" 2>/dev/null)"
126
122
  if ! git -C "$ROOT" log --oneline -1 "$commit_range" >/dev/null 2>&1; then
127
- printf "${RED}FAIL${NC} %s: commit_range '%s' does not resolve\n" "$bundle_name" "$commit_range"
128
- EXIT_CODE=1
129
- return
123
+ printf "${RED}FAIL${NC} %s: commit_range '%s' does not resolve\n" "$name" "$commit_range"
124
+ EXIT_CODE=1; return
130
125
  fi
131
126
 
132
- # Check aggregation tags exist (not empty, but don't validate correctness)
133
- local effort_hours
134
- effort_hours="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); e=d.get('effort',{}); print(e.get('effort_hours',''))" 2>/dev/null)"
135
- if [ -z "$effort_hours" ] || [ "$effort_hours" = "null" ]; then
136
- printf "${RED}FAIL${NC} %s: effort.effort_hours missing or null\n" "$bundle_name"
137
- EXIT_CODE=1
138
- return
127
+ # effort.effort_hours present and non-negative
128
+ local eff
129
+ eff="$(echo "$fm" | python3 -c "
130
+ import json,sys
131
+ d=json.load(sys.stdin)
132
+ e=d.get('effort',{}).get('effort_hours')
133
+ if e is None: sys.exit(1)
134
+ if e < 0: sys.exit(2)
135
+ print(e)
136
+ " 2>/dev/null)" || {
137
+ local rc=$?
138
+ if [ "$rc" -eq 1 ]; then
139
+ printf "${RED}FAIL${NC} %s: effort.effort_hours missing or null\n" "$name"
140
+ else
141
+ printf "${RED}FAIL${NC} %s: effort_hours out of bounds\n" "$name"
142
+ fi
143
+ EXIT_CODE=1; return
144
+ }
145
+
146
+ printf "${GREEN}PASS${NC} %s (source=%s, generator=%s, commit_range resolves)\n" "$name" "$source" "$generator"
147
+ }
148
+
149
+ validate_spec_migration() {
150
+ local file="$1" fm="$2" name="$3"
151
+ local errs=0
152
+
153
+ # Required keys
154
+ for key in id title since_version order actions_needed; do
155
+ local val
156
+ val="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('$key',''))" 2>/dev/null)"
157
+ if [ -z "$val" ] || [ "$val" = "null" ] || [ "$val" = "None" ] || [ "$val" = "[]" ]; then
158
+ printf "${RED}FAIL${NC} %s: missing required key '%s'\n" "$name" "$key"
159
+ errs=$((errs + 1))
160
+ fi
161
+ done
162
+ [ "$errs" -gt 0 ] && { EXIT_CODE=1; return; }
163
+
164
+ # fingerprint.any has at least one check
165
+ local fp_count
166
+ fp_count="$(echo "$fm" | python3 -c "
167
+ import json,sys
168
+ d=json.load(sys.stdin)
169
+ fp=d.get('fingerprint',{}).get('any',[])
170
+ print(len(fp))
171
+ " 2>/dev/null)"
172
+ if [ "${fp_count:-0}" -eq 0 ]; then
173
+ printf "${RED}FAIL${NC} %s: fingerprint.any is empty — no detection criteria\n" "$name"
174
+ EXIT_CODE=1; return
139
175
  fi
140
176
 
141
- # Bounds sanity (effort can't be negative)
142
- python3 -c "
143
- import json, sys
144
- d = json.load(sys.stdin)
145
- eff = d.get('effort', {}).get('effort_hours')
146
- if eff is not None and eff < 0:
147
- sys.exit(1)
148
- " <<< "$fm" 2>/dev/null || {
149
- printf "${RED}FAIL${NC} %s: effort_hours out of bounds\n" "$bundle_name"
177
+ printf "${GREEN}PASS${NC} %s (actions=%s, fingerprint has %s check(s))\n" \
178
+ "$name" \
179
+ "$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(len(d.get('actions_needed',[])))" 2>/dev/null)" \
180
+ "$fp_count"
181
+ }
182
+
183
+ validate_migration_registry() {
184
+ local file="$1" fm="$2" name="$3"
185
+
186
+ local count
187
+ count="$(echo "$fm" | python3 -c "
188
+ import json,sys
189
+ d=json.load(sys.stdin)
190
+ migrations=d.get('migrations',[])
191
+ print(len(migrations))
192
+ " 2>/dev/null)"
193
+ if [ "${count:-0}" -eq 0 ]; then
194
+ printf "${RED}FAIL${NC} %s: migrations list is empty\n" "$name"
195
+ EXIT_CODE=1; return
196
+ fi
197
+
198
+ # Check each migration has id + file + status
199
+ local bad
200
+ bad="$(echo "$fm" | python3 -c "
201
+ import json,sys
202
+ d=json.load(sys.stdin)
203
+ for m in d.get('migrations',[]):
204
+ if not all(k in m for k in ('id','file','status')):
205
+ print(m.get('id','?')); sys.exit(1)
206
+ " 2>/dev/null)" || {
207
+ printf "${RED}FAIL${NC} %s: migration '%s' missing id/file/status\n" "$name" "${bad:-?}"
208
+ EXIT_CODE=1; return
209
+ }
210
+
211
+ printf "${GREEN}PASS${NC} %s (%s migrations indexed)\n" "$name" "$count"
212
+ }
213
+
214
+ # ---- Main validation dispatcher ----------------------------------------
215
+ validate_bundle() {
216
+ local file="$1"
217
+ local name; name="$(basename "$file")"
218
+
219
+ local fm
220
+ fm="$(parse_frontmatter "$file")" || {
221
+ printf "${RED}FAIL${NC} %s: cannot parse YAML frontmatter\n" "$name"
150
222
  EXIT_CODE=1
151
223
  return
152
224
  }
153
225
 
154
- printf "${GREEN}PASS${NC} %s (source=%s, generator=%s, commit_range resolves)\n" "$bundle_name" "$source" "$generator"
226
+ local kind
227
+ kind="$(echo "$fm" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('okf_kind',''))" 2>/dev/null)"
228
+
229
+ case "$kind" in
230
+ story-metrics) validate_story_metrics "$file" "$fm" "$name" ;;
231
+ spec-migration) validate_spec_migration "$file" "$fm" "$name" ;;
232
+ migration-registry) validate_migration_registry "$file" "$fm" "$name" ;;
233
+ "")
234
+ printf "${YELLOW}SKIP${NC} %s: no okf_kind — not an OKF bundle\n" "$name"
235
+ ;;
236
+ *)
237
+ printf "${YELLOW}SKIP${NC} %s: unknown okf_kind '%s'\n" "$name" "$kind"
238
+ ;;
239
+ esac
240
+ }
241
+
242
+ # ---- Scan directory ----------------------------------------------------
243
+ scan_dir() {
244
+ local dir="$1"
245
+ if [ ! -d "$dir" ]; then
246
+ printf "${RED}FAIL${NC} directory not found: %s\n" "$dir"
247
+ EXIT_CODE=1
248
+ return
249
+ fi
250
+ local count=0
251
+ while IFS= read -r -d '' f; do
252
+ if head -1 "$f" 2>/dev/null | grep -q '^---$'; then
253
+ validate_bundle "$f"
254
+ count=$((count + 1))
255
+ fi
256
+ done < <(find "$dir" -maxdepth 1 -name '*.md' -print0 2>/dev/null || true)
257
+ if [ "$count" -eq 0 ]; then
258
+ printf "${YELLOW}SKIP${NC} no OKF bundles found in %s\n" "$dir"
259
+ fi
155
260
  }
156
261
 
157
262
  # ---- main ----------------------------------------------------------------
158
- DIR=""
263
+ DIRS=()
159
264
  BUNDLE=""
265
+ DEFAULT_DIRS=("$ROOT/specs/metrics" "$ROOT/specs/migrations")
160
266
 
161
- [ $# -ge 1 ] || set -- "--dir" "$METRICS_DIR" # default: validate specs/metrics/
267
+ if [ $# -eq 0 ]; then
268
+ DIRS=("$ROOT/specs/metrics" "$ROOT/specs/migrations")
269
+ fi
162
270
 
163
271
  while [ $# -gt 0 ]; do
164
272
  case "$1" in
165
- --dir) DIR="$2"; shift 2 ;;
166
- --bundle) BUNDLE="$2"; shift 2 ;;
273
+ --dir) DIRS+=("$2"); shift 2 ;;
274
+ --bundle) BUNDLE="$2"; shift 2 ;;
167
275
  --help|-h) usage ;;
168
- *) echo "validate-okf: unknown flag: $1" >&2; usage ;;
276
+ *)
277
+ echo "validate-okf: unknown flag: $1" >&2
278
+ echo "Run 'scripts/validate-okf.sh --help' for usage." >&2
279
+ exit 2
280
+ ;;
169
281
  esac
170
282
  done
171
283
 
172
284
  echo "validate-okf: scanning for OKF bundles..."
173
285
 
174
286
  if [ -n "$BUNDLE" ]; then
175
- validate_bundle "$BUNDLE"
176
- elif [ -n "$DIR" ]; then
177
- if [ ! -d "$DIR" ]; then
178
- printf "${YELLOW}SKIP${NC} directory not found: %s\n" "$DIR"
179
- exit 0
180
- fi
181
- count=0
182
- while IFS= read -r -d '' f; do
183
- # Only process .md files with YAML frontmatter
184
- if head -1 "$f" 2>/dev/null | grep -q '^---$'; then
185
- validate_bundle "$f"
186
- count=$((count + 1))
187
- fi
188
- done < <(find "$DIR" -maxdepth 1 -name '*.md' -print0 2>/dev/null || true)
189
- if [ "$count" -eq 0 ]; then
190
- printf "${YELLOW}SKIP${NC} no OKF bundles found in %s\n" "$DIR"
191
- else
192
- echo "validate-okf: scanned $count bundle(s)"
287
+ if [ ! -f "$BUNDLE" ]; then
288
+ printf "${RED}FAIL${NC} bundle not found: %s\n" "$BUNDLE"
289
+ exit 1
193
290
  fi
291
+ validate_bundle "$BUNDLE"
292
+ elif [ ${#DIRS[@]} -gt 0 ]; then
293
+ for d in "${DIRS[@]}"; do
294
+ scan_dir "$d"
295
+ done
194
296
  else
195
- echo "validate-okf: nothing to validate" >&2
297
+ echo "validate-okf: nothing to validate (no --dir or --bundle)" >&2
298
+ exit 1
196
299
  fi
197
300
 
198
301
  exit "$EXIT_CODE"