bigpowers 2.77.0 → 2.77.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.
Files changed (76) hide show
  1. package/.pi/package.json +1 -1
  2. package/.pi/prompts/audit-code.md +1 -1
  3. package/.pi/prompts/craft-skill.md +2 -2
  4. package/.pi/prompts/elaborate-spec.md +1 -1
  5. package/.pi/prompts/evolve-skill.md +1 -1
  6. package/.pi/prompts/grill-me.md +1 -1
  7. package/.pi/prompts/guard-git.md +1 -1
  8. package/.pi/prompts/investigate-bug.md +2 -2
  9. package/.pi/prompts/model-domain.md +3 -3
  10. package/.pi/prompts/plan-refactor.md +2 -2
  11. package/.pi/prompts/plan-release.md +2 -2
  12. package/.pi/prompts/using-bigpowers.md +1 -1
  13. package/.pi/prompts/write-document.md +2 -2
  14. package/.pi/skills/audit-code/SKILL.md +1 -1
  15. package/.pi/skills/change-request/SKILL.md +1 -1
  16. package/.pi/skills/commit-message/SKILL.md +3 -3
  17. package/.pi/skills/compose-workflow/SKILL.md +1 -1
  18. package/.pi/skills/craft-skill/SKILL.md +4 -4
  19. package/.pi/skills/deepen-architecture/SKILL.md +13 -13
  20. package/.pi/skills/deploy/SKILL.md +4 -4
  21. package/.pi/skills/develop-tdd/SKILL.md +5 -5
  22. package/.pi/skills/elaborate-spec/SKILL.md +1 -1
  23. package/.pi/skills/evolve-skill/SKILL.md +2 -2
  24. package/.pi/skills/extract-design/SKILL.md +1 -1
  25. package/.pi/skills/generate-allure-report/SKILL.md +1 -1
  26. package/.pi/skills/grill-me/SKILL.md +2 -2
  27. package/.pi/skills/grill-with-docs/SKILL.md +1 -1
  28. package/.pi/skills/guard-git/SKILL.md +5 -5
  29. package/.pi/skills/harden-vps/SKILL.md +1 -1
  30. package/.pi/skills/investigate-bug/SKILL.md +2 -2
  31. package/.pi/skills/migrate-spec/SKILL.md +13 -13
  32. package/.pi/skills/model-domain/SKILL.md +5 -5
  33. package/.pi/skills/orchestrate-project/SKILL.md +2 -2
  34. package/.pi/skills/organize-workspace/SKILL.md +1 -1
  35. package/.pi/skills/plan-refactor/SKILL.md +2 -2
  36. package/.pi/skills/plan-release/SKILL.md +2 -2
  37. package/.pi/skills/plan-work/SKILL.md +2 -2
  38. package/.pi/skills/publish-package/SKILL.md +8 -8
  39. package/.pi/skills/release-branch/SKILL.md +2 -2
  40. package/.pi/skills/research-first/SKILL.md +1 -1
  41. package/.pi/skills/run-evals/SKILL.md +1 -1
  42. package/.pi/skills/security-review/SKILL.md +3 -3
  43. package/.pi/skills/seed-conventions/SKILL.md +3 -3
  44. package/.pi/skills/smoke-test/SKILL.md +5 -5
  45. package/.pi/skills/stocktake-skills/SKILL.md +1 -1
  46. package/.pi/skills/using-bigpowers/SKILL.md +1 -1
  47. package/.pi/skills/validate-contracts/SKILL.md +6 -6
  48. package/.pi/skills/verify-work/SKILL.md +1 -1
  49. package/.pi/skills/wire-ci/SKILL.md +8 -8
  50. package/.pi/skills/write-document/SKILL.md +3 -3
  51. package/CHANGELOG.md +14 -0
  52. package/package.json +4 -3
  53. package/scripts/adapters/pi.sh +4 -1
  54. package/scripts/check-skill-links.py +78 -0
  55. package/scripts/generate-reference-tables.sh +2 -1
  56. package/scripts/lib/__pycache__/link_utils.cpython-312.pyc +0 -0
  57. package/scripts/lib/link_utils.py +49 -0
  58. package/scripts/lib/simple_yaml.py +64 -13
  59. package/scripts/lib/srp-engine.py +100 -4
  60. package/scripts/sync-skills.sh +1 -1
  61. package/scripts/test-setup-no-pyyaml.sh +83 -0
  62. package/scripts/validate-skill-yaml.py +12 -5
  63. package/skills/audit-code/SKILL.md +1 -1
  64. package/skills/craft-skill/SKILL.md +2 -2
  65. package/skills/elaborate-spec/SKILL.md +1 -1
  66. package/skills/evolve-skill/REFERENCE.md +1 -1
  67. package/skills/grill-me/REFERENCE.md +1 -1
  68. package/skills/guard-git/SKILL.md +1 -1
  69. package/skills/investigate-bug/SKILL.md +2 -2
  70. package/skills/model-domain/CONTEXT-FORMAT.md +3 -3
  71. package/skills/plan-refactor/SKILL.md +2 -2
  72. package/skills/plan-release/SKILL.md +2 -2
  73. package/skills/using-bigpowers/SKILL.md +1 -1
  74. package/skills/write-document/REFERENCE.md +2 -2
  75. package/skills-lock.json +8 -8
  76. package/tests/test_srp_engine.py +148 -0
@@ -78,7 +78,7 @@ UTILITY terse-mode / craft-skill / edit-document (any phase)
78
78
 
79
79
  If you work alone and do not want PR ceremony every task:
80
80
 
81
- 1. Read [profiles/solo-git.md](../profiles/solo-git.md).
81
+ 1. Read [profiles/solo-git.md](../../profiles/solo-git.md).
82
82
  2. Register with `compose-workflow` → `specs/WORKFLOW-solo-git.md`.
83
83
  3. Ship with `release-branch` in **solo-local** mode (`land-branch.sh`), not `gh pr create`.
84
84
 
@@ -141,7 +141,7 @@ Auto-fill from CLAUDE.md `Test` and `Lint` commands.
141
141
  ```markdown
142
142
  ## Changelog
143
143
 
144
- See [CHANGELOG.md](CHANGELOG.md) or [Releases](https://github.com/user/repo/releases).
144
+ See [CHANGELOG.md](../../CHANGELOG.md) or [Releases](https://github.com/user/repo/releases).
145
145
  ```
146
146
 
147
147
  ### 13. Links
@@ -158,7 +158,7 @@ See [CHANGELOG.md](CHANGELOG.md) or [Releases](https://github.com/user/repo/rele
158
158
  ```markdown
159
159
  ## License
160
160
 
161
- MIT — see [LICENSE](LICENSE) for details.
161
+ MIT — see [LICENSE](../../LICENSE) for details.
162
162
  ```
163
163
 
164
164
  Detect from CLAUDE.md or project LICENSE file.
package/skills-lock.json CHANGED
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "audit-code": {
15
15
  "description": "Self-review checklist for the coding agent to run before dispatching a reviewer. Checks CONVENTIONS.md compliance, Boy Scout Rule, test coverage, types, and SOLID. Produces a pass/fail checklist. Use before request-review, before committing, or when user asks for a code quality check.",
16
- "sha256": "bbb128254464f8f4",
16
+ "sha256": "0636f1d9d6c591a3",
17
17
  "path": "skills/audit-codeSKILL.md"
18
18
  },
19
19
  "audit-plan": {
@@ -48,7 +48,7 @@
48
48
  },
49
49
  "craft-skill": {
50
50
  "description": "Create new bigpowers skills with proper structure, progressive disclosure, and bundled resources. Use when user wants to create, write, or build a new skill for the bigpowers lifecycle.",
51
- "sha256": "cbf8ab939cfbab87",
51
+ "sha256": "2caa9d8ae9298b4b",
52
52
  "path": "skills/craft-skillSKILL.md"
53
53
  },
54
54
  "deepen-architecture": {
@@ -108,7 +108,7 @@
108
108
  },
109
109
  "elaborate-spec": {
110
110
  "description": "Refine a rough idea into a clear, detailed specification through dialogue. Does not produce code. Use when user has a vague idea, wants to think through a feature before planning, or needs to turn \"I want X\" into a concrete spec.",
111
- "sha256": "62ebfca87e6d0162",
111
+ "sha256": "9307ab61c789a0a0",
112
112
  "path": "skills/elaborate-specSKILL.md"
113
113
  },
114
114
  "enforce-first": {
@@ -158,7 +158,7 @@
158
158
  },
159
159
  "guard-git": {
160
160
  "description": "Block dangerous git commands (push, force push, reset --hard, clean, branch -D, checkout/restore .) and enforce Conventional Commits & Branch Protection before an AI agent runs them. Installs hook scripts for Claude Code, Cursor, Cursor CLI, and Gemini CLI; documents Google Antigravity Terminal deny lists. Use when the user wants git safety hooks, to block git push or destructive git in agents, or to mirror the same policy across AI coding tools.",
161
- "sha256": "9ee881df89273b00",
161
+ "sha256": "e7083cba6d95a15f",
162
162
  "path": "skills/guard-gitSKILL.md"
163
163
  },
164
164
  "harden-vps": {
@@ -178,7 +178,7 @@
178
178
  },
179
179
  "investigate-bug": {
180
180
  "description": "Investigate a bug or issue by exploring the codebase to find root cause, then write a TDD-based fix plan to specs/bugs/BUG-*.md. Use when user reports a bug, wants to investigate a problem, mentions \"triage\", or wants to plan a fix.",
181
- "sha256": "b842fd329d1f7741",
181
+ "sha256": "54f8c5417be34ef0",
182
182
  "path": "skills/investigate-bugSKILL.md"
183
183
  },
184
184
  "kickoff-branch": {
@@ -218,12 +218,12 @@
218
218
  },
219
219
  "plan-refactor": {
220
220
  "description": "Create a detailed refactor plan with tiny commits via user interview, then save it as specs/REFACTOR_LATEST.md. Use when user wants to plan a refactor, create a refactoring RFC, or break a refactor into safe incremental steps.",
221
- "sha256": "c418c850806e2f16",
221
+ "sha256": "2d18809da7cc9de8",
222
222
  "path": "skills/plan-refactorSKILL.md"
223
223
  },
224
224
  "plan-release": {
225
225
  "description": "\"RELEASE-INDEX BUILDER — Sequence elaborated epics into specs/release-plan.yaml with WSJF ordering and BCP baselines. NOT a planning-spine substitute: it does not scope work (scope-work) or write story tasks (plan-work). Use after elaborate-spec when the user wants a versioned release index of epics.\"",
226
- "sha256": "b56b800817cd383e",
226
+ "sha256": "9334ff48e5b1fab3",
227
227
  "path": "skills/plan-releaseSKILL.md"
228
228
  },
229
229
  "plan-tests": {
@@ -358,7 +358,7 @@
358
358
  },
359
359
  "using-bigpowers": {
360
360
  "description": "One-time bootstrap that introduces the bigpowers skills system, the PMBOK lifecycle arc, and tells you which skill to call first for your situation. Use when starting with bigpowers for the first time, when user asks \"where do I start?\", or when the skills system needs to be explained.",
361
- "sha256": "332d6468868b759b",
361
+ "sha256": "bad9ebe9bf303b36",
362
362
  "path": "skills/using-bigpowersSKILL.md"
363
363
  },
364
364
  "validate-contracts": {
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env python3
2
+ """tests/test_srp_engine.py — unit tests for rewrite_links_for_pi and link_utils.
3
+
4
+ Run: python3 -m pytest tests/test_srp_engine.py -v
5
+ or: python3 tests/test_srp_engine.py
6
+ """
7
+ import os
8
+ import sys
9
+ import unittest
10
+
11
+ # Make scripts/lib importable without installation.
12
+ _REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
13
+ _LIB = os.path.join(_REPO_ROOT, "scripts", "lib")
14
+ sys.path.insert(0, _LIB)
15
+ sys.path.insert(0, os.path.join(_REPO_ROOT, "scripts"))
16
+
17
+ # srp-engine.py has a hyphen so we load it via importlib.
18
+ import importlib.util as _ilu
19
+ _spec = _ilu.spec_from_file_location("srp_engine", os.path.join(_LIB, "srp-engine.py"))
20
+ _srp = _ilu.module_from_spec(_spec)
21
+ sys.modules["srp_engine"] = _srp
22
+ _spec.loader.exec_module(_srp)
23
+
24
+ from srp_engine import rewrite_links_for_pi # type: ignore[import]
25
+ from link_utils import strip_code_spans, LINK_RE, MACHINE_PATH_RE
26
+
27
+
28
+ class TestStripCodeSpans(unittest.TestCase):
29
+ def test_fenced_block_blanked(self):
30
+ md = "Before.\n```\n[fake](fake.md)\n```\nAfter."
31
+ shadow = strip_code_spans(md)
32
+ self.assertNotIn("[fake](fake.md)", shadow)
33
+ self.assertEqual(len(shadow), len(md)) # positions preserved
34
+
35
+ def test_inline_code_blanked(self):
36
+ md = "Use `[x](y.md)` as an example."
37
+ shadow = strip_code_spans(md)
38
+ self.assertNotIn("[x](y.md)", shadow)
39
+ self.assertEqual(len(shadow), len(md))
40
+
41
+ def test_real_link_survives(self):
42
+ md = "See [docs](guide.md) for details."
43
+ shadow = strip_code_spans(md)
44
+ self.assertIn("[docs](guide.md)", shadow)
45
+
46
+
47
+ class TestLinkRE(unittest.TestCase):
48
+ def test_plain_link(self):
49
+ m = LINK_RE.search("[text](target.md)")
50
+ self.assertIsNotNone(m)
51
+ self.assertEqual(m.group(2), "target.md")
52
+
53
+ def test_link_with_title(self):
54
+ m = LINK_RE.search('[text](target.md "My Title")')
55
+ self.assertIsNotNone(m)
56
+ self.assertEqual(m.group(2), "target.md")
57
+
58
+ def test_link_with_fragment(self):
59
+ m = LINK_RE.search("[text](doc.md#section)")
60
+ self.assertIsNotNone(m)
61
+ self.assertEqual(m.group(2), "doc.md#section")
62
+
63
+ def test_no_match_on_image(self):
64
+ # Image links (![...](url)) contain the same syntax — LINK_RE will match
65
+ # the inner part; they should be treated as pass-through by callers.
66
+ m = LINK_RE.search("![alt](image.png)")
67
+ # The regex matches the inner ](url) portion — callers must handle images.
68
+ self.assertIsNotNone(m)
69
+
70
+
71
+ class TestMachinePathRE(unittest.TestCase):
72
+ def test_file_uri(self):
73
+ self.assertTrue(MACHINE_PATH_RE.search("file:///Users/alice/project"))
74
+
75
+ def test_macos_path(self):
76
+ self.assertTrue(MACHINE_PATH_RE.search("/Users/alice/project"))
77
+
78
+ def test_linux_path(self):
79
+ self.assertTrue(MACHINE_PATH_RE.search("/home/alice/project"))
80
+
81
+ def test_windows_path_single_backslash(self):
82
+ self.assertTrue(MACHINE_PATH_RE.search("C:\\Users\\alice"))
83
+
84
+ def test_github_url_not_flagged(self):
85
+ self.assertFalse(
86
+ MACHINE_PATH_RE.search("https://github.com/danielvm-git/bigpowers")
87
+ )
88
+
89
+
90
+ class TestRewriteLinksForPi(unittest.TestCase):
91
+ """Tests run without a real repo tree — path existence is irrelevant here;
92
+ we only verify that the URL construction logic is correct."""
93
+
94
+ NAME = "my-skill"
95
+
96
+ def _rw(self, body):
97
+ return rewrite_links_for_pi(body, self.NAME)
98
+
99
+ def test_external_link_untouched(self):
100
+ body = "[docs](https://example.com)"
101
+ self.assertEqual(self._rw(body), body)
102
+
103
+ def test_anchor_only_untouched(self):
104
+ body = "[section](#heading)"
105
+ self.assertEqual(self._rw(body), body)
106
+
107
+ def test_absolute_path_untouched(self):
108
+ body = "[root](/absolute/path.md)"
109
+ self.assertEqual(self._rw(body), body)
110
+
111
+ def test_relative_link_repointed(self):
112
+ body = "[ref](REFERENCE.md)"
113
+ result = self._rw(body)
114
+ # Must not contain the original bare target
115
+ self.assertNotIn("](REFERENCE.md)", result)
116
+ # Must be a relative path targeting the skills source tree
117
+ self.assertIn("REFERENCE.md", result)
118
+
119
+ def test_fragment_preserved(self):
120
+ body = "[section](REFERENCE.md#anchor)"
121
+ result = self._rw(body)
122
+ self.assertIn("#anchor", result)
123
+ # Fragment must not be mangled into a path component
124
+ self.assertNotIn("anchor" + os.sep, result)
125
+
126
+ def test_link_with_title_attribute(self):
127
+ body = '[ref](REFERENCE.md "My Title")'
128
+ result = self._rw(body)
129
+ # Must not be left unrewritten
130
+ self.assertNotIn("](REFERENCE.md", result)
131
+
132
+ def test_code_block_links_not_rewritten(self):
133
+ body = "Real: [ref](REFERENCE.md)\n\n```\n[fake](nowhere.md)\n```\n"
134
+ result = self._rw(body)
135
+ # The real link should be rewritten
136
+ self.assertNotIn("](REFERENCE.md)", result)
137
+ # The code-block link must be untouched
138
+ self.assertIn("[fake](nowhere.md)", result)
139
+
140
+ def test_inline_code_link_not_rewritten(self):
141
+ body = "Example: `[x](bad.md)` — real [ref](REFERENCE.md)."
142
+ result = self._rw(body)
143
+ self.assertIn("[x](bad.md)", result) # inline code preserved
144
+ self.assertNotIn("](REFERENCE.md)", result) # real link rewritten
145
+
146
+
147
+ if __name__ == "__main__":
148
+ unittest.main()