bigpowers 2.86.3 → 2.86.5

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 (170) hide show
  1. package/.agents/skills/craft-skill/SKILL.md +2 -2
  2. package/.agents/skills/define-success/SKILL.md +6 -59
  3. package/.agents/skills/deploy/SKILL.md +1 -1
  4. package/.agents/skills/elaborate-spec/SKILL.md +1 -1
  5. package/.agents/skills/harden-vps/SKILL.md +63 -60
  6. package/.agents/skills/investigate-bug/SKILL.md +2 -2
  7. package/.agents/skills/orchestrate-project/SKILL.md +1 -1
  8. package/.agents/skills/plan-refactor/SKILL.md +2 -2
  9. package/.agents/skills/plan-release/SKILL.md +2 -2
  10. package/.agents/skills/plan-work/SKILL.md +1 -1
  11. package/.agents/skills/using-bigpowers/SKILL.md +2 -2
  12. package/.agents/skills/wire-ci/SKILL.md +11 -14
  13. package/.codebuddy/skills/craft-skill/SKILL.md +2 -2
  14. package/.codebuddy/skills/define-success/SKILL.md +6 -59
  15. package/.codebuddy/skills/deploy/SKILL.md +1 -1
  16. package/.codebuddy/skills/elaborate-spec/SKILL.md +1 -1
  17. package/.codebuddy/skills/harden-vps/SKILL.md +63 -60
  18. package/.codebuddy/skills/investigate-bug/SKILL.md +2 -2
  19. package/.codebuddy/skills/orchestrate-project/SKILL.md +1 -1
  20. package/.codebuddy/skills/plan-refactor/SKILL.md +2 -2
  21. package/.codebuddy/skills/plan-release/SKILL.md +2 -2
  22. package/.codebuddy/skills/plan-work/SKILL.md +1 -1
  23. package/.codebuddy/skills/using-bigpowers/SKILL.md +2 -2
  24. package/.codebuddy/skills/wire-ci/SKILL.md +11 -14
  25. package/.codex/skills/craft-skill/SKILL.md +2 -2
  26. package/.codex/skills/define-success/SKILL.md +6 -59
  27. package/.codex/skills/deploy/SKILL.md +1 -1
  28. package/.codex/skills/elaborate-spec/SKILL.md +1 -1
  29. package/.codex/skills/harden-vps/SKILL.md +63 -60
  30. package/.codex/skills/investigate-bug/SKILL.md +2 -2
  31. package/.codex/skills/orchestrate-project/SKILL.md +1 -1
  32. package/.codex/skills/plan-refactor/SKILL.md +2 -2
  33. package/.codex/skills/plan-release/SKILL.md +2 -2
  34. package/.codex/skills/plan-work/SKILL.md +1 -1
  35. package/.codex/skills/using-bigpowers/SKILL.md +2 -2
  36. package/.codex/skills/wire-ci/SKILL.md +11 -14
  37. package/.hermes/skills/craft-skill/SKILL.md +2 -2
  38. package/.hermes/skills/define-success/SKILL.md +6 -59
  39. package/.hermes/skills/deploy/SKILL.md +1 -1
  40. package/.hermes/skills/elaborate-spec/SKILL.md +1 -1
  41. package/.hermes/skills/harden-vps/SKILL.md +63 -60
  42. package/.hermes/skills/investigate-bug/SKILL.md +2 -2
  43. package/.hermes/skills/orchestrate-project/SKILL.md +1 -1
  44. package/.hermes/skills/plan-refactor/SKILL.md +2 -2
  45. package/.hermes/skills/plan-release/SKILL.md +2 -2
  46. package/.hermes/skills/plan-work/SKILL.md +1 -1
  47. package/.hermes/skills/using-bigpowers/SKILL.md +2 -2
  48. package/.hermes/skills/wire-ci/SKILL.md +11 -14
  49. package/.kilocode/rules/craft-skill.md +2 -2
  50. package/.kilocode/rules/define-success.md +6 -59
  51. package/.kilocode/rules/deploy.md +1 -1
  52. package/.kilocode/rules/elaborate-spec.md +1 -1
  53. package/.kilocode/rules/harden-vps.md +63 -60
  54. package/.kilocode/rules/investigate-bug.md +2 -2
  55. package/.kilocode/rules/orchestrate-project.md +1 -1
  56. package/.kilocode/rules/plan-refactor.md +2 -2
  57. package/.kilocode/rules/plan-release.md +2 -2
  58. package/.kilocode/rules/plan-work.md +1 -1
  59. package/.kilocode/rules/using-bigpowers.md +2 -2
  60. package/.kilocode/rules/wire-ci.md +11 -14
  61. package/.mimocode/skills/craft-skill/SKILL.md +2 -2
  62. package/.mimocode/skills/define-success/SKILL.md +6 -59
  63. package/.mimocode/skills/deploy/SKILL.md +1 -1
  64. package/.mimocode/skills/elaborate-spec/SKILL.md +1 -1
  65. package/.mimocode/skills/harden-vps/SKILL.md +63 -60
  66. package/.mimocode/skills/investigate-bug/SKILL.md +2 -2
  67. package/.mimocode/skills/orchestrate-project/SKILL.md +1 -1
  68. package/.mimocode/skills/plan-refactor/SKILL.md +2 -2
  69. package/.mimocode/skills/plan-release/SKILL.md +2 -2
  70. package/.mimocode/skills/plan-work/SKILL.md +1 -1
  71. package/.mimocode/skills/using-bigpowers/SKILL.md +2 -2
  72. package/.mimocode/skills/wire-ci/SKILL.md +11 -14
  73. package/.pi/package.json +1 -1
  74. package/.pi/prompts/craft-skill.md +2 -2
  75. package/.pi/prompts/define-success.md +5 -58
  76. package/.pi/prompts/deploy.md +1 -1
  77. package/.pi/prompts/elaborate-spec.md +1 -1
  78. package/.pi/prompts/harden-vps.md +63 -60
  79. package/.pi/prompts/investigate-bug.md +2 -2
  80. package/.pi/prompts/orchestrate-project.md +1 -1
  81. package/.pi/prompts/plan-refactor.md +2 -2
  82. package/.pi/prompts/plan-release.md +2 -2
  83. package/.pi/prompts/plan-work.md +1 -1
  84. package/.pi/prompts/using-bigpowers.md +2 -2
  85. package/.pi/prompts/wire-ci.md +11 -14
  86. package/.pi/skills/craft-skill/SKILL.md +2 -2
  87. package/.pi/skills/define-success/SKILL.md +6 -59
  88. package/.pi/skills/deploy/SKILL.md +1 -1
  89. package/.pi/skills/elaborate-spec/SKILL.md +1 -1
  90. package/.pi/skills/harden-vps/SKILL.md +63 -60
  91. package/.pi/skills/investigate-bug/SKILL.md +2 -2
  92. package/.pi/skills/orchestrate-project/SKILL.md +1 -1
  93. package/.pi/skills/plan-refactor/SKILL.md +2 -2
  94. package/.pi/skills/plan-release/SKILL.md +2 -2
  95. package/.pi/skills/plan-work/SKILL.md +1 -1
  96. package/.pi/skills/using-bigpowers/SKILL.md +2 -2
  97. package/.pi/skills/wire-ci/SKILL.md +11 -14
  98. package/.trae/skills/craft-skill/SKILL.md +2 -2
  99. package/.trae/skills/define-success/SKILL.md +6 -59
  100. package/.trae/skills/deploy/SKILL.md +1 -1
  101. package/.trae/skills/elaborate-spec/SKILL.md +1 -1
  102. package/.trae/skills/harden-vps/SKILL.md +63 -60
  103. package/.trae/skills/investigate-bug/SKILL.md +2 -2
  104. package/.trae/skills/orchestrate-project/SKILL.md +1 -1
  105. package/.trae/skills/plan-refactor/SKILL.md +2 -2
  106. package/.trae/skills/plan-release/SKILL.md +2 -2
  107. package/.trae/skills/plan-work/SKILL.md +1 -1
  108. package/.trae/skills/using-bigpowers/SKILL.md +2 -2
  109. package/.trae/skills/wire-ci/SKILL.md +11 -14
  110. package/.windsurf/rules/craft-skill.md +2 -2
  111. package/.windsurf/rules/define-success.md +6 -59
  112. package/.windsurf/rules/deploy.md +1 -1
  113. package/.windsurf/rules/elaborate-spec.md +1 -1
  114. package/.windsurf/rules/harden-vps.md +63 -60
  115. package/.windsurf/rules/investigate-bug.md +2 -2
  116. package/.windsurf/rules/orchestrate-project.md +1 -1
  117. package/.windsurf/rules/plan-refactor.md +2 -2
  118. package/.windsurf/rules/plan-release.md +2 -2
  119. package/.windsurf/rules/plan-work.md +1 -1
  120. package/.windsurf/rules/using-bigpowers.md +2 -2
  121. package/.windsurf/rules/wire-ci.md +11 -14
  122. package/.zcode/skills/craft-skill/SKILL.md +2 -2
  123. package/.zcode/skills/define-success/SKILL.md +6 -59
  124. package/.zcode/skills/deploy/SKILL.md +1 -1
  125. package/.zcode/skills/elaborate-spec/SKILL.md +1 -1
  126. package/.zcode/skills/harden-vps/SKILL.md +63 -60
  127. package/.zcode/skills/investigate-bug/SKILL.md +2 -2
  128. package/.zcode/skills/orchestrate-project/SKILL.md +1 -1
  129. package/.zcode/skills/plan-refactor/SKILL.md +2 -2
  130. package/.zcode/skills/plan-release/SKILL.md +2 -2
  131. package/.zcode/skills/plan-work/SKILL.md +1 -1
  132. package/.zcode/skills/using-bigpowers/SKILL.md +2 -2
  133. package/.zcode/skills/wire-ci/SKILL.md +11 -14
  134. package/CHANGELOG.md +14 -0
  135. package/SKILL-INDEX.md +2 -2
  136. package/package.json +1 -1
  137. package/scripts/check-skill-links.py +35 -0
  138. package/scripts/golden-g12-status-consistency.sh +232 -0
  139. package/scripts/land-branch.sh +9 -3
  140. package/scripts/lib/__pycache__/link_utils.cpython-312.pyc +0 -0
  141. package/scripts/lib/__pycache__/srp_engine_links.cpython-312.pyc +0 -0
  142. package/scripts/lib/golden-suite-gates.sh +9 -0
  143. package/scripts/lib/target-contracts.sh +37 -1
  144. package/scripts/sync-status-from-epics.sh +8 -0
  145. package/scripts/test-target-contracts.sh +73 -0
  146. package/scripts/tombstone-skill.sh +6 -0
  147. package/skills/craft-skill/SKILL.md +2 -2
  148. package/skills/define-success/SKILL.md +7 -61
  149. package/skills/deploy/SKILL.md +1 -1
  150. package/skills/elaborate-spec/SKILL.md +1 -1
  151. package/skills/harden-vps/REFERENCE.md +39 -36
  152. package/skills/harden-vps/SKILL.md +24 -24
  153. package/skills/investigate-bug/SKILL.md +2 -2
  154. package/skills/orchestrate-project/REFERENCE.md +1 -1
  155. package/skills/plan-refactor/SKILL.md +2 -2
  156. package/skills/plan-release/SKILL.md +2 -2
  157. package/skills/plan-work/SKILL.md +1 -1
  158. package/skills/security-review/fixtures/CWE-639-idor-negative.go +1 -1
  159. package/skills/security-review/fixtures/CWE-639-idor-positive.go +1 -1
  160. package/skills/using-bigpowers/SKILL.md +2 -2
  161. package/skills/wire-ci/REFERENCE.md +11 -14
  162. package/skills-lock.json +12 -12
  163. package/.fix_regex.sh +0 -16
  164. package/.hermes-verify-sed-fix.py +0 -53
  165. package/_test_e28s01.sh +0 -2
  166. package/audit-independent-unwaived-2026-07-06.md +0 -49
  167. package/hermes-verify-sed-fix.py +0 -30
  168. package/instructions +0 -1
  169. package/scripts/hermes-verify-e39s02.sh +0 -28
  170. package/test_figlet.py +0 -17
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env bash
2
+ # story: e51s04
3
+ # golden-g12-status-consistency.sh — Planning SoT Consistency Gate (G-12)
4
+ #
5
+ # CONVENTIONS.md § specs/ declares specs/execution-status.yaml the sole SoT for
6
+ # story state. Nothing enforced that. sync-status-from-epics.sh is a *seeder*:
7
+ # it preloads keys from execution-status.yaml itself and uses setdefault(), so
8
+ # an existing key keeps its old value and epic.yaml's stories[].status is never
9
+ # read. Story status written by build-epic step 8 into a capsule could therefore
10
+ # disagree with the SoT forever, undetected
11
+ # (BUG-2026-07-26-planning-sot-drift).
12
+ #
13
+ # This gate makes the two agree or fails.
14
+ #
15
+ # Authority model (CONVENTIONS.md § specs/): execution-status.yaml is the sole
16
+ # SoT for story state; a capsule's stories[].status is derived. Capsules under
17
+ # specs/epics/archive/ are frozen historical records — an archived shard that
18
+ # still reads 'todo' while the SoT reads 'done' is normal history, not drift, so
19
+ # archive/ is excluded. Status vocabulary is normalised before comparison
20
+ # ('passing' == 'done'; 'todo'/'planned'/'not-started' == 'backlog').
21
+ #
22
+ # Checks:
23
+ # 1. A LIVE capsule must not disagree with execution-status.yaml (both the
24
+ # stories: and development_status: sections). In practice this catches a
25
+ # capsule marked done by build-epic step 8 whose SoT was never updated.
26
+ # 2. Every capsule_dir in release-plan.yaml must resolve to a real directory.
27
+ # 3. A live capsule must not also exist under archive/ — two shards for one
28
+ # epic makes "which status is authoritative" undecidable.
29
+ #
30
+ # Usage: bash scripts/golden-g12-status-consistency.sh [--self-test]
31
+ # Exit 0: SoT is consistent
32
+ # Exit 1: drift detected (or, under --self-test, the gate failed to detect
33
+ # deliberately injected drift — a vacuous gate, G-08 bug class)
34
+
35
+ set -euo pipefail
36
+ source "$(dirname "${BASH_SOURCE[0]}")/lib/python-env.sh"
37
+ source "$(dirname "${BASH_SOURCE[0]}")/lib/skill-common.sh"
38
+ resolve_repo_root
39
+
40
+ RED='\033[0;31m'
41
+ GREEN='\033[0;32m'
42
+ NC='\033[0m'
43
+
44
+ SELF_TEST=0
45
+ [[ "${1:-}" == "--self-test" ]] && SELF_TEST=1
46
+
47
+ check_tree() {
48
+ # $1 = specs dir to check
49
+ $PYTHON - "$1" <<'PY'
50
+ import sys, re
51
+ from pathlib import Path
52
+ import yaml
53
+
54
+ specs = Path(sys.argv[1])
55
+ epics_dir = specs / "epics"
56
+ exec_path = specs / "execution-status.yaml"
57
+ rp_path = specs / "release-plan.yaml"
58
+
59
+ problems = []
60
+ archived_skipped = 0
61
+
62
+ # Status vocabulary normalisation — different skills have written different
63
+ # words for the same state over the repo's history.
64
+ ALIASES = {
65
+ "passing": "done",
66
+ "complete": "done",
67
+ "completed": "done",
68
+ "todo": "backlog",
69
+ "planned": "backlog",
70
+ "not-started": "backlog",
71
+ }
72
+
73
+
74
+ def norm(v):
75
+ return ALIASES.get(str(v).strip().lower(), str(v).strip().lower())
76
+
77
+
78
+ exec_data = yaml.safe_load(exec_path.read_text(encoding="utf-8")) or {}
79
+ dev = exec_data.get("development_status") or {}
80
+ stories = exec_data.get("stories") or {}
81
+
82
+ # --- Check 1: LIVE epic.yaml story status vs execution-status.yaml ---
83
+ for epic_file in sorted(epics_dir.rglob("epic.yaml")):
84
+ rel = epic_file.relative_to(specs)
85
+ if "archive" in epic_file.relative_to(epics_dir).parts:
86
+ archived_skipped += 1
87
+ continue
88
+
89
+ try:
90
+ ed = yaml.safe_load(epic_file.read_text(encoding="utf-8")) or {}
91
+ except Exception as exc:
92
+ problems.append(f"unparseable epic shard {rel}: {exc}")
93
+ continue
94
+
95
+ for story in ed.get("stories") or []:
96
+ if not isinstance(story, dict):
97
+ continue
98
+ sid = story.get("id")
99
+ declared = story.get("status")
100
+ if not sid or not declared:
101
+ continue
102
+ if not re.match(r"^e\d+s\d+$", str(sid)):
103
+ continue
104
+
105
+ sot_detail = stories.get(sid, {})
106
+ sot_detail = sot_detail.get("status") if isinstance(sot_detail, dict) else None
107
+ sot_summary = dev.get(sid)
108
+
109
+ if sot_detail is not None and norm(sot_detail) != norm(declared):
110
+ problems.append(
111
+ f"{sid}: {rel} says '{declared}' but execution-status.yaml "
112
+ f"stories.{sid}.status says '{sot_detail}'"
113
+ )
114
+ if sot_summary is not None and norm(sot_summary) != norm(declared):
115
+ problems.append(
116
+ f"{sid}: {rel} says '{declared}' but execution-status.yaml "
117
+ f"development_status.{sid} says '{sot_summary}'"
118
+ )
119
+
120
+ # --- Check 2: release-plan.yaml capsule_dir resolves ---
121
+ if rp_path.exists():
122
+ rp = yaml.safe_load(rp_path.read_text(encoding="utf-8")) or {}
123
+ for ep in rp.get("epics") or []:
124
+ if not isinstance(ep, dict):
125
+ continue
126
+ cd = ep.get("capsule_dir")
127
+ if cd and not (specs / cd).is_dir():
128
+ problems.append(
129
+ f"{ep.get('id')}: release-plan.yaml capsule_dir '{cd}' does not exist"
130
+ )
131
+
132
+ # --- Check 3: no epic has both a live and an archived capsule ---
133
+ archive_dir = epics_dir / "archive"
134
+ if archive_dir.is_dir():
135
+ live = {p.name for p in epics_dir.iterdir() if p.is_dir() and p.name != "archive"}
136
+ for p in archive_dir.iterdir():
137
+ if p.is_dir() and p.name in live:
138
+ problems.append(
139
+ f"{p.name}: capsule exists both live and under archive/ — "
140
+ f"authoritative status is undecidable"
141
+ )
142
+
143
+ if archived_skipped:
144
+ print(f" info: {archived_skipped} archived capsule(s) skipped (frozen history)")
145
+
146
+ if problems:
147
+ for p in problems:
148
+ print(f" DRIFT {p}")
149
+ print(f"\n{len(problems)} inconsistencies")
150
+ sys.exit(1)
151
+
152
+ print(" ok : epic shards, execution-status.yaml and release-plan.yaml agree")
153
+ sys.exit(0)
154
+ PY
155
+ }
156
+
157
+ if [[ "$SELF_TEST" -eq 1 ]]; then
158
+ echo "=== G-12 self-test: prove the gate can fail ==="
159
+ TMP=$(mktemp -d)
160
+ trap 'rm -rf "$TMP"' EXIT
161
+ # Copy only what check_tree reads — specs/ as a whole is ~28MB and the copy
162
+ # would dominate the gate's runtime.
163
+ mkdir -p "$TMP/specs"
164
+ cp -R "$REPO_ROOT/specs/epics" "$TMP/specs/epics"
165
+ cp "$REPO_ROOT/specs/execution-status.yaml" "$TMP/specs/"
166
+ cp "$REPO_ROOT/specs/release-plan.yaml" "$TMP/specs/"
167
+
168
+ # Inject drift into a LIVE capsule. Archived shards are excluded from the
169
+ # check, so mutating one would prove nothing — the gate would rightly stay
170
+ # silent and the self-test would report a false vacuity failure.
171
+ $PYTHON - "$TMP/specs" <<'PY'
172
+ import sys, re
173
+ from pathlib import Path
174
+ import yaml
175
+
176
+ specs = Path(sys.argv[1])
177
+ epics_dir = specs / "epics"
178
+ exec_path = specs / "execution-status.yaml"
179
+ data = yaml.safe_load(exec_path.read_text(encoding="utf-8")) or {}
180
+
181
+ for epic_file in sorted(epics_dir.rglob("epic.yaml")):
182
+ if "archive" in epic_file.relative_to(epics_dir).parts:
183
+ continue
184
+ ed = yaml.safe_load(epic_file.read_text(encoding="utf-8")) or {}
185
+ for story in ed.get("stories") or []:
186
+ if not isinstance(story, dict):
187
+ continue
188
+ sid, st = story.get("id"), story.get("status")
189
+ if sid and st and re.match(r"^e\d+s\d+$", str(sid)):
190
+ flipped = "backlog" if st != "backlog" else "done"
191
+ data.setdefault("stories", {}).setdefault(sid, {})["status"] = flipped
192
+ data.setdefault("development_status", {})[sid] = flipped
193
+ exec_path.write_text(
194
+ yaml.dump(data, default_flow_style=False, sort_keys=False),
195
+ encoding="utf-8",
196
+ )
197
+ print(f"injected: {sid} {st} -> {flipped} (live capsule)")
198
+ sys.exit(0)
199
+ print("ERROR: no live story with a status found to mutate", file=sys.stderr)
200
+ sys.exit(2)
201
+ PY
202
+
203
+ set +e
204
+ check_tree "$TMP/specs" >/dev/null 2>&1
205
+ injected_exit=$?
206
+ set -e
207
+
208
+ if [[ $injected_exit -ne 0 ]]; then
209
+ echo -e "${GREEN}PASS${NC} G-12 detected injected drift (exit $injected_exit)"
210
+ echo "G-12 self-test: PASS"
211
+ exit 0
212
+ fi
213
+ echo -e "${RED}FAIL${NC} G-12 passed on deliberately drifted specs — vacuous gate"
214
+ echo "G-12 self-test: FAIL — same bug class as G-08 / BUG-2026-07-26-planning-sot-drift"
215
+ exit 1
216
+ fi
217
+
218
+ echo "=== G-12: Planning SoT Consistency ==="
219
+ set +e
220
+ output=$(check_tree "$REPO_ROOT/specs" 2>&1)
221
+ actual_exit=$?
222
+ set -e
223
+ echo "$output"
224
+
225
+ if [[ $actual_exit -eq 0 ]]; then
226
+ echo -e "${GREEN}PASS${NC} planning SoT is consistent"
227
+ echo "G-12: PASS"
228
+ exit 0
229
+ fi
230
+ echo -e "${RED}FAIL${NC} planning SoT has drifted"
231
+ echo "G-12: FAIL — see BUG-2026-07-26-planning-sot-drift"
232
+ exit 1
@@ -36,12 +36,18 @@ COMMIT_MSG="${ARGS[1]:-}"
36
36
 
37
37
  [ -n "$FEATURE_BRANCH" ] && [ -n "$COMMIT_MSG" ] || usage_land
38
38
 
39
- if [[ ! "$COMMIT_MSG" =~ $CONVENTIONAL_REGEX ]]; then
39
+ # Both checks below judge the subject line, not the whole message. The length
40
+ # test used to read ${#COMMIT_MSG}, so any Conventional Commit carrying a body
41
+ # was rejected no matter how short its subject — the error text said "subject
42
+ # line" while the check measured the entire string.
43
+ COMMIT_SUBJECT="${COMMIT_MSG%%$'\n'*}"
44
+
45
+ if [[ ! "$COMMIT_SUBJECT" =~ $CONVENTIONAL_REGEX ]]; then
40
46
  land_branch_deny "Commit message must follow Conventional Commits: <type>(<scope>): <subject>"
41
47
  fi
42
48
 
43
- if [ ${#COMMIT_MSG} -gt 72 ]; then
44
- land_branch_deny "Commit subject line must be 72 characters or less"
49
+ if [ ${#COMMIT_SUBJECT} -gt 72 ]; then
50
+ land_branch_deny "Commit subject line must be 72 characters or less (got ${#COMMIT_SUBJECT})"
45
51
  fi
46
52
 
47
53
  # Block AI agent attribution (P1 — CONVENTIONS.md § Git Attribution)
@@ -14,6 +14,15 @@ 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
+ # Planning SoT consistency (BUG-2026-07-26-planning-sot-drift): live epic
18
+ # shards, execution-status.yaml and release-plan.yaml must agree. Self-test
19
+ # first so a vacuous gate is caught before its verdict is trusted.
20
+ "g12-status-selftest:bash scripts/golden-g12-status-consistency.sh --self-test:false"
21
+ "g12-status-consistency:bash scripts/golden-g12-status-consistency.sh:false"
22
+ # Anti-vacuity for the target-contract seam: every contract declared in
23
+ # targets.yaml must have a real assertion, and an unknown contract must FAIL
24
+ # rather than SKIP+exit 0 (seven contracts were fail-open before this).
25
+ "target-contracts:bash scripts/test-target-contracts.sh:false"
17
26
  "install-helpers:bash scripts/test-install-helpers.sh:false"
18
27
  "import-boundaries:bash scripts/check-import-boundaries.sh:false"
19
28
  "skill-catalog:bash scripts/validate-skill-catalog.sh:false"
@@ -82,6 +82,33 @@ assert_agy_skills_nonempty() {
82
82
  return 1
83
83
  }
84
84
 
85
+ # Generic hooks-manifest assertion for every target that ships one under
86
+ # scripts/hooks/<target>/. Before this existed, cline/codebuddy/codex/kilocode/
87
+ # qwen/trae/windsurf all declared <target>_hooks_manifest in targets.yaml and
88
+ # every one of them fell through run_contract's default branch to SKIP + exit 0
89
+ # — seven declared contracts that could never fail.
90
+ assert_hooks_manifest() {
91
+ local id="$1"
92
+ local contract="$2"
93
+ local target="${contract%_hooks_manifest}"
94
+ local manifest="scripts/hooks/${target}/hooks-manifest.json"
95
+
96
+ if [[ ! -f "$manifest" ]]; then
97
+ echo "FAIL $id:$contract — $manifest missing"
98
+ return 1
99
+ fi
100
+ # verify-install.sh sources this file without lib/python-env.sh, so resolve an
101
+ # interpreter locally rather than relying on $PYTHON being set.
102
+ local py="${PYTHON:-}"
103
+ [[ -n "$py" ]] || py="$(command -v python3 || command -v python || true)"
104
+ if [[ -n "$py" ]] && ! "$py" -c "import json; json.load(open('$manifest'))" 2>/dev/null; then
105
+ echo "FAIL $id:$contract — $manifest is not valid JSON"
106
+ return 1
107
+ fi
108
+ echo "PASS $id:$contract"
109
+ return 0
110
+ }
111
+
85
112
  run_contract() {
86
113
  local id="$1"
87
114
  local contract="$2"
@@ -90,10 +117,19 @@ run_contract() {
90
117
  symlink_claude_md) assert_symlink_claude_md "$id" ;;
91
118
  cursor_rules_nonempty) assert_cursor_rules_nonempty "$id" ;;
92
119
  gemini_ext_exists) assert_gemini_ext_exists "$id" ;;
120
+ # gemini has its own adapter-level validator; keep it ahead of the generic
121
+ # pattern below so the more specific check wins.
93
122
  gemini_hooks_manifest) assert_gemini_hooks_manifest "$id" ;;
123
+ *_hooks_manifest) assert_hooks_manifest "$id" "$contract" ;;
94
124
  pi_skills_nonempty) assert_pi_skills_nonempty "$id" ;;
95
125
  agy_skills_nonempty) assert_agy_skills_nonempty "$id" ;;
96
126
  aider_bridge) assert_aider_bridge "$id" ;;
97
- *) echo "SKIP $id:$contract — unknown contract"; return 0 ;;
127
+ # A contract declared in targets.yaml with no assertion behind it is a
128
+ # broken contract, not a no-op. Failing here is what makes the registry an
129
+ # enforced interface rather than documentation.
130
+ *)
131
+ echo "FAIL $id:$contract — unknown contract (no assertion implemented)"
132
+ return 1
133
+ ;;
98
134
  esac
99
135
  }
@@ -1,5 +1,13 @@
1
1
  #!/usr/bin/env bash
2
2
  # sync-status-from-epics.sh — seed execution-status.yaml keys from epic shards
3
+ #
4
+ # SEEDER, NOT A RECONCILER. `keys` is preloaded from execution-status.yaml
5
+ # itself and applied with setdefault(), so an already-present key keeps its
6
+ # existing value; epic.yaml's stories[].status is never read. Running this does
7
+ # NOT pull a capsule's status into the SoT — it only adds missing keys and
8
+ # refreshes task counters. Drift between a capsule and the SoT is detected by
9
+ # scripts/golden-g12-status-consistency.sh (G-12), not corrected here.
10
+ # See specs/bugs/BUG-2026-07-26-planning-sot-drift.md.
3
11
  set -euo pipefail
4
12
  source "$(dirname "${BASH_SOURCE[0]}")/lib/python-env.sh"
5
13
  source "$(dirname "${BASH_SOURCE[0]}")/lib/skill-common.sh"
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env bash
2
+ # story: e37s08
3
+ # test-target-contracts.sh — anti-vacuity guard for run_contract.
4
+ #
5
+ # Every contract named in scripts/targets.yaml must have a real assertion behind
6
+ # it. run_contract used to end in `*) echo "SKIP ..."; return 0`, so seven
7
+ # declared contracts (cline/codebuddy/codex/kilocode/qwen/trae/windsurf
8
+ # _hooks_manifest) silently passed forever. This test fails if that default ever
9
+ # returns to being permissive, or if targets.yaml declares a contract nothing
10
+ # implements.
11
+ #
12
+ # Usage: bash scripts/test-target-contracts.sh
13
+ set -euo pipefail
14
+ source "$(dirname "${BASH_SOURCE[0]}")/lib/skill-common.sh"
15
+ resolve_repo_root
16
+ cd "$REPO_ROOT"
17
+
18
+ PASS=0
19
+ FAIL=0
20
+ pass() { echo "PASS: $1"; PASS=$((PASS + 1)); }
21
+ fail() { echo "FAIL: $1" >&2; FAIL=$((FAIL + 1)); }
22
+
23
+ echo "=== test-target-contracts.sh ==="
24
+
25
+ # shellcheck source=lib/target-contracts.sh
26
+ source "$REPO_ROOT/scripts/lib/target-contracts.sh"
27
+
28
+ # 1. An unknown contract MUST fail. This is the anti-vacuity assertion.
29
+ set +e
30
+ out=$(run_contract "faketarget" "definitely_not_a_real_contract" 2>&1)
31
+ rc=$?
32
+ set -e
33
+ if [[ $rc -ne 0 ]]; then
34
+ pass "unknown contract fails (exit $rc)"
35
+ else
36
+ fail "unknown contract returned 0 — run_contract is fail-open again: $out"
37
+ fi
38
+
39
+ # 2. Every contract declared in targets.yaml must resolve to an assertion.
40
+ # Probing with a nonexistent target id means a real assertion returns 1 with
41
+ # a FAIL line, while a missing implementation hits the default branch and
42
+ # reports "unknown contract".
43
+ declared=$(grep -E "^ - [a-z0-9_]+$" scripts/targets.yaml | sed 's/^ - //' | sort -u)
44
+ [[ -n "$declared" ]] || fail "no contracts parsed from targets.yaml"
45
+
46
+ for c in $declared; do
47
+ set +e
48
+ out=$(run_contract "__probe__" "$c" 2>&1)
49
+ set -e
50
+ if grep -q "unknown contract" <<<"$out"; then
51
+ fail "$c declared in targets.yaml but no assertion implements it"
52
+ else
53
+ pass "$c has an implementation"
54
+ fi
55
+ done
56
+
57
+ # 3. Every *_hooks_manifest target must actually ship a parseable manifest.
58
+ for c in $declared; do
59
+ case "$c" in
60
+ gemini_hooks_manifest) continue ;; # adapter-level validator, not a file check
61
+ *_hooks_manifest)
62
+ t="${c%_hooks_manifest}"
63
+ if [[ -f "scripts/hooks/${t}/hooks-manifest.json" ]]; then
64
+ pass "$t ships hooks-manifest.json"
65
+ else
66
+ fail "$t declares $c but scripts/hooks/${t}/hooks-manifest.json is missing"
67
+ fi
68
+ ;;
69
+ esac
70
+ done
71
+
72
+ echo "test-target-contracts: $PASS passed, $FAIL failed"
73
+ [[ "$FAIL" -eq 0 ]] || exit 1
@@ -54,9 +54,15 @@ STORY_TAGS=$(grep -E '^#\s*story:' "$OLD_SKILL_MD" || true)
54
54
  CURRENT_VERSION=$(jq -r '.version' package.json 2>/dev/null)
55
55
  CREATED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
56
56
 
57
+ # A tombstone is still a live SKILL.md for its transition window, so it must
58
+ # carry the same required frontmatter as any other skill. Omitting `model:`
59
+ # made docs/references/model-profiles.md count one fewer skill than there are
60
+ # skill directories, which fails validate-doctrine's skill-count check.
57
61
  cat > "$OLD_SKILL_MD" <<STUBEOF
58
62
  ---
59
63
  name: ${OLD_NAME}
64
+ model: haiku
65
+ effort: light
60
66
  description: "TOMBSTONE — renamed/merged to ${NEW_NAME}. This stub resolves for one release then is removed."
61
67
  ---
62
68
 
@@ -48,7 +48,7 @@ Skill-body instructional prose MUST follow [AGENTIC-STE.md](../../docs/AGENTIC-S
48
48
  - Any reference materials to include?
49
49
  - What specs/ output does it produce (if any)?
50
50
 
51
- 2. **Verify Principles** — Ensure the skill aligns with [PRINCIPLES.md](https://github.com/danielvm-git/bigpowers/blob/main/docs/PRINCIPLES.md):
51
+ 2. **Verify Principles** — Ensure the skill aligns with [PRINCIPLES.md](../../docs/PRINCIPLES.md):
52
52
  - Is it atomic (verb-noun)?
53
53
  - Is it "deep" (simple interface, complex internal logic)?
54
54
  - Does it include Hard Gates?
@@ -62,7 +62,7 @@ Skill-body instructional prose MUST follow [AGENTIC-STE.md](../../docs/AGENTIC-S
62
62
  **Auto-skill from library README:** When user provides a library README or API docs URL, extract triggers and HARD GATEs.
63
63
  Draft verify commands and specs/ output into SKILL.md. Do NOT invent APIs not in the source.
64
64
 
65
- 4. Add `model:` frontmatter (`haiku` | `sonnet` | `opus`) per [model-profiles.md](https://github.com/danielvm-git/bigpowers/blob/main/docs/references/model-profiles.md).
65
+ 4. Add `model:` frontmatter (`haiku` | `sonnet` | `opus`) per [model-profiles.md](../../docs/references/model-profiles.md).
66
66
 
67
67
  > **STREAM CONTINUITY** — When writing file content, output in continuous chunks of ~200 lines. Do not pause. Continue immediately until complete. If you need time, emit a placeholder comment rather than going silent.
68
68
 
@@ -1,69 +1,15 @@
1
- ARCHIVED: content absorbed into plan-work
2
-
3
1
  ---
4
2
  name: define-success
5
- model: sonnet
6
- effort: standard
7
- description: 'Convert an imperative task statement into explicit "step → verify: <cmd>" pairs before implementation begins. Use before plan-work when success criteria are unclear, when a task lacks verifiable checkpoints, or when user says "how will we know this is done?".'
3
+ model: haiku
4
+ effort: light
5
+ description: "TOMBSTONE — renamed/merged to plan-work. This stub resolves for one release then is removed."
8
6
  ---
9
7
 
10
- # Define Success
11
-
12
- Transform "do X" into "step → verify: <cmd>" pairs. This is the pre-flight check before `plan-work` or `develop-tdd` — it makes success observable and removes ambiguity about when you're done.
13
-
14
- > **HARD GATE** — Success criteria must be testable and user-observable. "Code should be fast" is not testable. "Pageload latency < 2s" is testable.
15
-
16
- ## Why this matters
17
-
18
- "Implement user authentication" is not a plan. It has no checkpoints, no evidence requirement, and no way to know if you're done. The Karpathy principle: every step must be independently verifiable with a runnable command. If you can't verify it, you can't prove it works.
19
-
20
- ## Process
21
-
22
- ### 1. Read the task statement
23
-
24
- Take the task as stated (from conversation, or from `specs/epics/ (see slice-tasks)`, or from `specs/product/SCOPE_LATEST.yaml`).
25
-
26
- ### 2. Break into observable outcomes
27
-
28
- For each thing the task requires, identify:
29
- - The smallest unit of observable behavior that proves something works
30
- - The command that proves it
31
-
32
- Work at the level of behaviors (what the system does) not implementation steps (how you'll write the code).
33
-
34
- ### 3. Write the pairs
35
-
36
- Format each pair as:
37
- ```
38
- N. [What must be true] → verify: <runnable command>
39
- ```
40
-
41
- Examples:
42
-
43
- ```
44
- Task: "Add user registration to the API"
45
-
46
- 1. POST /users accepts {email, name} and returns {id, email, name} → verify: curl -s -X POST http://localhost:3000/users -H 'Content-Type: application/json' -d '{"email":"test@test.com","name":"Test"}' | jq .id
47
- 2. Duplicate email is rejected with 409 → verify: npm test -- user-registration.test.ts
48
- 3. Missing email is rejected with 400 and descriptive error → verify: npm test -- user-validation.test.ts
49
- 4. Password is hashed (never stored in plaintext) → verify: npm test -- user-security.test.ts
50
- 5. All existing tests still pass → verify: npm test
51
- ```
52
-
53
- ### 4. Challenge completeness
54
-
55
- Ask yourself:
56
- - Is there any behavior the task requires that isn't covered by a verify step?
57
- - Is every verify step runnable right now without additional setup?
58
- - Does the final step verify the whole thing end-to-end?
59
-
60
- Add any missing pairs.
61
-
62
- ### 5. Output
8
+ # define-success (tombstoned)
63
9
 
64
- Present the pairs to the user and ask: "Does this capture everything the task requires? Anything missing?"
10
+ This skill has been renamed or merged into `plan-work`. Use `plan-work` instead.
65
11
 
66
- Once confirmed, these pairs become the skeleton for `plan-work`'s steps. Pass them along when calling `plan-work`.
12
+ This stub exists for one release as a transition aid, then is removed once
13
+ `scripts/validate-tombstones.sh` flags it as expired.
67
14
 
68
- ## Verify
69
15
 
@@ -74,7 +74,7 @@ Platform-agnostic — supports multiple deployment targets via environment varia
74
74
  |----------|---------|---------|
75
75
  | Vercel | `VERCEL_TOKEN`, `VERCEL_PROJECT_ID` | `vercel deploy --prod --token $VERCEL_TOKEN` |
76
76
  | Netlify | `NETLIFY_AUTH_TOKEN`, `NETLIFY_SITE_ID` | `netlify deploy --prod --auth $NETLIFY_AUTH_TOKEN --dir $ARTIFACT_DIR` |
77
- | BigBase MCP | MCP tool call | `mcp deploy` via BigBase server |
77
+ | Platform MCP | MCP tool call | `mcp deploy` via your platform MCP server |
78
78
  | rsync/SSH | `DEPLOY_SSH_USER`, `DEPLOY_SSH_HOST`, `DEPLOY_SSH_PATH` | `rsync -avz $ARTIFACT_DIR/ $DEPLOY_SSH_USER@$DEPLOY_SSH_HOST:$DEPLOY_SSH_PATH` |
79
79
  | Custom | `DEPLOY_COMMAND` | Run any deploy command string |
80
80
 
@@ -65,7 +65,7 @@ Once the user has answered the main questions, probe for assumptions:
65
65
 
66
66
  ### 4. Synthesize and confirm
67
67
 
68
- Summarize your understanding in 3–5 bullet points aligned with [countable-story-format.md](https://github.com/danielvm-git/bigpowers/blob/main/docs/countable-story-format.md):
68
+ Summarize your understanding in 3–5 bullet points aligned with [countable-story-format.md](../../docs/countable-story-format.md):
69
69
  - The problem (feeds into §1 Business narrative)
70
70
  - The solution and main flow (feeds into §5)
71
71
  - The key constraints and alternative flows (feeds into §6)