bigpowers 2.34.1 → 2.35.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/.pi/package.json +2 -2
- package/.pi/prompts/deploy.md +53 -28
- package/.pi/prompts/develop-tdd.md +5 -80
- package/.pi/prompts/migrate-spec.md +273 -197
- package/.pi/prompts/publish-package.md +125 -67
- package/.pi/prompts/release-branch.md +85 -69
- package/.pi/prompts/security-review.md +323 -0
- package/.pi/prompts/smoke-test.md +98 -58
- package/.pi/prompts/using-bigpowers.md +2 -2
- package/.pi/prompts/validate-contracts.md +169 -54
- package/.pi/prompts/wire-ci.md +147 -89
- package/.pi/skills/deploy/SKILL.md +53 -28
- package/.pi/skills/develop-tdd/SKILL.md +5 -80
- package/.pi/skills/migrate-spec/SKILL.md +273 -197
- package/.pi/skills/publish-package/SKILL.md +125 -67
- package/.pi/skills/release-branch/SKILL.md +85 -69
- package/.pi/skills/security-review/SKILL.md +324 -0
- package/.pi/skills/smoke-test/SKILL.md +98 -58
- package/.pi/skills/using-bigpowers/SKILL.md +2 -2
- package/.pi/skills/validate-contracts/SKILL.md +169 -54
- package/.pi/skills/wire-ci/SKILL.md +147 -89
- package/CHANGELOG.md +14 -0
- package/README.md +4 -4
- package/SKILL-INDEX.md +2 -2
- package/deploy/REFERENCE.md +82 -0
- package/deploy/SKILL.md +3 -63
- package/develop-tdd/SKILL.md +5 -80
- package/migrate-spec/REFERENCE.md +268 -0
- package/migrate-spec/SKILL.md +5 -199
- package/package.json +2 -2
- package/publish-package/REFERENCE.md +239 -0
- package/publish-package/SKILL.md +8 -192
- package/release-branch/REFERENCE.md +83 -0
- package/release-branch/SKILL.md +2 -69
- package/scripts/generate-reference-tables.sh +1 -0
- package/scripts/sync-skills.sh +4 -1
- package/security-review/REFERENCE-confidence-rubric.md +85 -0
- package/security-review/REFERENCE-false-positives.md +68 -0
- package/security-review/REFERENCE-vuln-categories.md +103 -0
- package/security-review/SKILL.md +63 -0
- package/skills-lock.json +14 -9
- package/smoke-test/REFERENCE.md +162 -0
- package/smoke-test/SKILL.md +5 -130
- package/using-bigpowers/SKILL.md +2 -2
- package/validate-contracts/REFERENCE.md +183 -0
- package/validate-contracts/SKILL.md +6 -77
- package/wire-ci/REFERENCE.md +257 -0
- package/wire-ci/SKILL.md +8 -210
package/publish-package/SKILL.md
CHANGED
|
@@ -33,225 +33,41 @@ If no manifest is found, prompt the user to specify the type or pass `--type <np
|
|
|
33
33
|
Before attempting any publish, run all applicable checks:
|
|
34
34
|
|
|
35
35
|
**npm (`package.json`):**
|
|
36
|
-
|
|
37
|
-
# Check auth token exists
|
|
38
|
-
if [ -z "${NPM_TOKEN:-}" ]; then
|
|
39
|
-
if [ ! -f ~/.npmrc ] || ! grep -q "_authToken" ~/.npmrc; then
|
|
40
|
-
echo "FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add //registry.npmjs.org/:_authToken=<token> to .npmrc"
|
|
41
|
-
exit 1
|
|
42
|
-
fi
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
# Check version not already published
|
|
46
|
-
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
47
|
-
CURRENT_VER=$(node -p "require('./package.json').version")
|
|
48
|
-
if npm view "$PACKAGE_NAME@$CURRENT_VER" version 2>/dev/null; then
|
|
49
|
-
echo "FAIL: Version $CURRENT_VER already published for $PACKAGE_NAME. Bump version first."
|
|
50
|
-
exit 1
|
|
51
|
-
fi
|
|
52
|
-
|
|
53
|
-
# Check build artifacts are fresh
|
|
54
|
-
if [ -d dist ] || [ -d lib ]; then
|
|
55
|
-
LATEST_BUILD=$(find dist lib 2>/dev/null -name "*.js" -o -name "*.cjs" -o -name "*.mjs" | xargs ls -t 2>/dev/null | head -1)
|
|
56
|
-
PACKAGE_MODIFIED=$(stat -f %m package.json 2>/dev/null || stat -c %Y package.json 2>/dev/null)
|
|
57
|
-
if [ -n "$LATEST_BUILD" ] && [ -n "$PACKAGE_MODIFIED" ]; then
|
|
58
|
-
BUILD_TIME=$(stat -f %m "$LATEST_BUILD" 2>/dev/null || stat -c %Y "$LATEST_BUILD" 2>/dev/null)
|
|
59
|
-
if [ "$BUILD_TIME" -lt "$PACKAGE_MODIFIED" ]; then
|
|
60
|
-
echo "WARNING: Build artifacts may be stale (package.json modified after last build). Run npm run build first."
|
|
61
|
-
fi
|
|
62
|
-
fi
|
|
63
|
-
fi
|
|
64
|
-
|
|
65
|
-
# Check CHANGELOG is updated
|
|
66
|
-
if [ -f CHANGELOG.md ]; then
|
|
67
|
-
if ! grep -q "$CURRENT_VER" CHANGELOG.md 2>/dev/null; then
|
|
68
|
-
echo "WARNING: Version $CURRENT_VER not found in CHANGELOG.md. Update changelog before publish."
|
|
69
|
-
fi
|
|
70
|
-
fi
|
|
71
|
-
```
|
|
36
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
72
37
|
|
|
73
38
|
**crates.io (`Cargo.toml`):**
|
|
74
|
-
|
|
75
|
-
# Check auth token exists
|
|
76
|
-
if [ -z "${CARGO_REGISTRY_TOKEN:-}" ]; then
|
|
77
|
-
if [ ! -f ~/.cargo/config.toml ] || ! grep -q "token" ~/.cargo/config.toml; then
|
|
78
|
-
echo "FAIL: CARGO_REGISTRY_TOKEN not set. Set via: export CARGO_REGISTRY_TOKEN=<token> or add to ~/.cargo/config.toml"
|
|
79
|
-
exit 1
|
|
80
|
-
fi
|
|
81
|
-
fi
|
|
82
|
-
|
|
83
|
-
# Check version not already published
|
|
84
|
-
CRATE_NAME=$(grep '^name' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
|
|
85
|
-
CURRENT_VER=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
|
|
86
|
-
if cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\""; then
|
|
87
|
-
echo "FAIL: Version $CURRENT_VER already published for $CRATE_NAME. Bump version in Cargo.toml first."
|
|
88
|
-
exit 1
|
|
89
|
-
fi
|
|
90
|
-
```
|
|
39
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
91
40
|
|
|
92
41
|
**PyPI (`setup.py` / `pyproject.toml`):**
|
|
93
|
-
|
|
94
|
-
# Check auth token exists
|
|
95
|
-
if [ -z "${TWINE_PASSWORD:-}" ] && [ -z "${POETRY_PYPI_TOKEN_PYPI:-}" ]; then
|
|
96
|
-
if [ ! -f ~/.pypirc ]; then
|
|
97
|
-
echo "FAIL: PyPI token not configured. Set TWINE_PASSWORD or create ~/.pypirc"
|
|
98
|
-
exit 1
|
|
99
|
-
fi
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
# Check for build artifacts
|
|
103
|
-
if [ ! -d dist ] || [ -z "$(ls dist/*.whl 2>/dev/null)" ]; then
|
|
104
|
-
echo "WARNING: No .whl files found in dist/. Run: python -m build"
|
|
105
|
-
fi
|
|
106
|
-
```
|
|
42
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
107
43
|
|
|
108
44
|
### 3. Run publish
|
|
109
45
|
|
|
110
46
|
After all prerequisite checks pass, run the registry-specific command:
|
|
111
47
|
|
|
112
|
-
|
|
113
|
-
# npm
|
|
114
|
-
npm publish --access public
|
|
115
|
-
|
|
116
|
-
# crates.io
|
|
117
|
-
cargo publish
|
|
118
|
-
|
|
119
|
-
# PyPI
|
|
120
|
-
python -m twine upload dist/* # or: poetry publish
|
|
121
|
-
|
|
122
|
-
# Homebrew (opens PR, does not publish directly)
|
|
123
|
-
brew bump-formula-pr --url=<tarball-url> <formula-name>
|
|
124
|
-
```
|
|
48
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
125
49
|
|
|
126
50
|
### 4. Verify publish success
|
|
127
51
|
|
|
128
52
|
After publish, confirm the version appears on the registry:
|
|
129
53
|
|
|
130
|
-
|
|
131
|
-
# npm
|
|
132
|
-
npm view "$PACKAGE_NAME" versions --json 2>/dev/null | grep -q "\"$CURRENT_VER\"" && echo "OK: npm publish confirmed"
|
|
133
|
-
|
|
134
|
-
# crates.io
|
|
135
|
-
cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\"" && echo "OK: crates.io publish confirmed"
|
|
136
|
-
|
|
137
|
-
# PyPI
|
|
138
|
-
pip index versions "$PACKAGE_NAME" 2>/dev/null | grep -q "$CURRENT_VER" && echo "OK: PyPI publish confirmed"
|
|
139
|
-
```
|
|
54
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
140
55
|
|
|
141
56
|
### 5. Error handling
|
|
142
57
|
|
|
143
58
|
On failure, surface actionable hints:
|
|
144
59
|
|
|
145
|
-
|
|
146
|
-
# Generic failure handler
|
|
147
|
-
if [ $? -ne 0 ]; then
|
|
148
|
-
case "$REGISTRY" in
|
|
149
|
-
npm)
|
|
150
|
-
echo "FAIL: npm publish failed."
|
|
151
|
-
echo " Common causes:"
|
|
152
|
-
echo " - NPM_TOKEN not set in secrets: add to GitHub repo secrets"
|
|
153
|
-
echo " - Version already published: bump version in package.json"
|
|
154
|
-
echo " - Two-factor auth required: use --otp=<code> flag"
|
|
155
|
-
echo " - Package scoped but not public: add --access public"
|
|
156
|
-
;;
|
|
157
|
-
crates.io)
|
|
158
|
-
echo "FAIL: cargo publish failed."
|
|
159
|
-
echo " Common causes:"
|
|
160
|
-
echo " - CARGO_REGISTRY_TOKEN not configured: see ~/.cargo/config.toml"
|
|
161
|
-
echo " - Version already published: bump version in Cargo.toml"
|
|
162
|
-
echo " - Local changes not committed: cargo publish requires clean working tree"
|
|
163
|
-
;;
|
|
164
|
-
pypi)
|
|
165
|
-
echo "FAIL: PyPI publish failed."
|
|
166
|
-
echo " Common causes:"
|
|
167
|
-
echo " - TWINE_PASSWORD not configured: set env var or ~/.pypirc"
|
|
168
|
-
echo " - Build artifacts missing: run python -m build first"
|
|
169
|
-
echo " - Version conflict: version already exists on PyPI"
|
|
170
|
-
;;
|
|
171
|
-
esac
|
|
172
|
-
exit 1
|
|
173
|
-
fi
|
|
174
|
-
```
|
|
60
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
175
61
|
|
|
176
62
|
### 6. Dry-run mode (`--dry-run`)
|
|
177
63
|
|
|
178
64
|
Run `--dry-run` to verify all prerequisites without actually publishing:
|
|
179
65
|
|
|
180
|
-
|
|
181
|
-
# Example output
|
|
182
|
-
$ publish-package --dry-run
|
|
183
|
-
|
|
184
|
-
[DRY-RUN] Detected package type: npm
|
|
185
|
-
[DRY-RUN] Package: my-package v0.4.0
|
|
186
|
-
[DRY-RUN] Checking NPM_TOKEN... OK
|
|
187
|
-
[DRY-RUN] Checking version 0.4.0 not already published... OK
|
|
188
|
-
[DRY-RUN] Checking build artifacts... WARNING: package.json modified after build
|
|
189
|
-
[DRY-RUN] Checking CHANGELOG... OK
|
|
190
|
-
[DRY-RUN] Would run: npm publish --access public
|
|
191
|
-
[DRY-RUN] Exiting without publishing.
|
|
192
|
-
```
|
|
66
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
193
67
|
|
|
194
68
|
### 7. Dry-run mode per registry
|
|
195
69
|
|
|
196
|
-
|
|
197
|
-
# npm dry-run
|
|
198
|
-
npm publish --access public --dry-run
|
|
199
|
-
|
|
200
|
-
# crates.io dry-run (cargo does not have a publish dry-run; use --dry-run flag for validation only)
|
|
201
|
-
cargo package --list 2>/dev/null
|
|
202
|
-
|
|
203
|
-
# PyPI dry-run
|
|
204
|
-
python -m twine upload --repository testpypi dist/* # test.pypi.org
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## Options
|
|
208
|
-
|
|
209
|
-
| Flag | Description |
|
|
210
|
-
|------|-------------|
|
|
211
|
-
| `--dry-run` | Verify prerequisites and show publish command without executing |
|
|
212
|
-
| `--registry <type>` | Force registry type (skip auto-detection) |
|
|
213
|
-
| `--otp <code>` | One-time password for npm 2FA |
|
|
214
|
-
| `--no-verify` | Skip prerequisite checks (use with caution) |
|
|
215
|
-
|
|
216
|
-
## Examples
|
|
217
|
-
|
|
218
|
-
### Publish an npm package
|
|
219
|
-
|
|
220
|
-
```bash
|
|
221
|
-
# Verify first
|
|
222
|
-
publish-package --dry-run
|
|
223
|
-
|
|
224
|
-
# Publish
|
|
225
|
-
publish-package
|
|
226
|
-
|
|
227
|
-
# Output:
|
|
228
|
-
# [npm] Publishing my-package v0.4.0...
|
|
229
|
-
# OK: npm publish confirmed (my-package@0.4.0 on registry)
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Publish a Rust crate
|
|
233
|
-
|
|
234
|
-
```bash
|
|
235
|
-
export CARGO_REGISTRY_TOKEN=<token>
|
|
236
|
-
publish-package --dry-run
|
|
237
|
-
publish-package
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Missing token scenario
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
$ publish-package
|
|
244
|
-
FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add to .npmrc
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## Integration with release-branch
|
|
248
|
-
|
|
249
|
-
When wired into `release-branch`, add a step after git push:
|
|
250
|
-
|
|
251
|
-
```
|
|
252
|
-
6a. Run publish-package to publish to package registries
|
|
253
|
-
→ verify: publish-package --dry-run && publish-package
|
|
254
|
-
```
|
|
70
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
255
71
|
|
|
256
72
|
## Verify
|
|
257
73
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Release Branch — Reference
|
|
2
2
|
|
|
3
|
+
# Release Branch — Reference
|
|
4
|
+
|
|
3
5
|
## PR body template (team-pr mode)
|
|
4
6
|
|
|
5
7
|
```bash
|
|
@@ -53,3 +55,84 @@ After landing the branch, record delivery metrics for this story:
|
|
|
53
55
|
cycle_minutes: 90
|
|
54
56
|
bcp_per_hour: 2.0
|
|
55
57
|
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Solo-local fallback detail
|
|
62
|
+
|
|
63
|
+
The fallback sequence (Path B above) handles the "remote has moved" case with `git pull --rebase`. Use when `scripts/land-branch.sh` is absent.
|
|
64
|
+
|
|
65
|
+
**Acceptance:** When fallback runs, main is updated, feature branch is deleted locally, and output states `"used fallback merge (land-branch.sh not found)"`.
|
|
66
|
+
|
|
67
|
+
## Handoff
|
|
68
|
+
|
|
69
|
+
Gate: READY -> next: survey-context
|
|
70
|
+
Writes: state.yaml handoff.next_skill = survey-context
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Reference block 1
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Fallback: manual squash-merge when land-branch.sh is absent
|
|
78
|
+
FEATURE_BRANCH=<task-slug>
|
|
79
|
+
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo main)
|
|
80
|
+
|
|
81
|
+
# Ensure we're on the feature branch
|
|
82
|
+
if [ "$(git branch --show-current)" != "$FEATURE_BRANCH" ]; then
|
|
83
|
+
git checkout "$FEATURE_BRANCH"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# Checkout default branch and update
|
|
87
|
+
git checkout "$DEFAULT_BRANCH"
|
|
88
|
+
git pull --rebase origin "$DEFAULT_BRANCH" 2>/dev/null || git pull origin "$DEFAULT_BRANCH"
|
|
89
|
+
|
|
90
|
+
# Squash-merge the feature branch
|
|
91
|
+
git merge --no-ff "$FEATURE_BRANCH" -m "<conventional-commit-message>"
|
|
92
|
+
|
|
93
|
+
# Push
|
|
94
|
+
git push origin "$DEFAULT_BRANCH"
|
|
95
|
+
|
|
96
|
+
# Clean up local feature branch
|
|
97
|
+
git branch -d "$FEATURE_BRANCH"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Reference block 2
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
echo "==> Polling CI for main branch..."
|
|
106
|
+
TIMEOUT=600 # 10 minutes
|
|
107
|
+
INTERVAL=30 # poll every 30 seconds
|
|
108
|
+
ELAPSED=0
|
|
109
|
+
|
|
110
|
+
while [ $ELAPSED -lt $TIMEOUT ]; do
|
|
111
|
+
CI_JSON=$(gh run list --limit 1 --branch main --workflow CI --json status,conclusion,headSha,databaseId 2>/dev/null)
|
|
112
|
+
CI_STATUS=$(echo "$CI_JSON" | jq -r '.[0].status // "unknown"')
|
|
113
|
+
CI_CONCLUSION=$(echo "$CI_JSON" | jq -r '.[0].conclusion // ""')
|
|
114
|
+
CI_SHA=$(echo "$CI_JSON" | jq -r '.[0].headSha // ""')
|
|
115
|
+
CI_ID=$(echo "$CI_JSON" | jq -r '.[0].databaseId // ""')
|
|
116
|
+
|
|
117
|
+
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "success" ]; then
|
|
118
|
+
echo "OK: CI passed for $(git rev-parse --short HEAD)"
|
|
119
|
+
bp-yaml-set.sh specs/state.yaml release.ci_verified true 2>/dev/null || \
|
|
120
|
+
echo " (bp-yaml-set not available — manually set release.ci_verified: true in state.yaml)"
|
|
121
|
+
break
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "failure" ]; then
|
|
125
|
+
echo "FAIL: CI failed for $(git rev-parse --short HEAD)"
|
|
126
|
+
echo " Run URL: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/actions/runs/$CI_ID"
|
|
127
|
+
echo " Handoff to fix-bug with the failure URL above."
|
|
128
|
+
return 1
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
sleep $INTERVAL
|
|
132
|
+
ELAPSED=$((ELAPSED + INTERVAL))
|
|
133
|
+
echo " Waiting... (${ELAPSED}s / ${TIMEOUT}s)"
|
|
134
|
+
done
|
|
135
|
+
|
|
136
|
+
echo "FAIL: CI did not complete within ${TIMEOUT}s timeout"
|
|
137
|
+
return 1
|
|
138
|
+
```
|
package/release-branch/SKILL.md
CHANGED
|
@@ -63,29 +63,7 @@ bash scripts/land-branch.sh <task-slug> "feat(scope): description"
|
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
**Path B — `scripts/land-branch.sh` missing (fallback):**
|
|
66
|
-
|
|
67
|
-
# Fallback: manual squash-merge when land-branch.sh is absent
|
|
68
|
-
FEATURE_BRANCH=<task-slug>
|
|
69
|
-
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo main)
|
|
70
|
-
|
|
71
|
-
# Ensure we're on the feature branch
|
|
72
|
-
if [ "$(git branch --show-current)" != "$FEATURE_BRANCH" ]; then
|
|
73
|
-
git checkout "$FEATURE_BRANCH"
|
|
74
|
-
fi
|
|
75
|
-
|
|
76
|
-
# Checkout default branch and update
|
|
77
|
-
git checkout "$DEFAULT_BRANCH"
|
|
78
|
-
git pull --rebase origin "$DEFAULT_BRANCH" 2>/dev/null || git pull origin "$DEFAULT_BRANCH"
|
|
79
|
-
|
|
80
|
-
# Squash-merge the feature branch
|
|
81
|
-
git merge --no-ff "$FEATURE_BRANCH" -m "<conventional-commit-message>"
|
|
82
|
-
|
|
83
|
-
# Push
|
|
84
|
-
git push origin "$DEFAULT_BRANCH"
|
|
85
|
-
|
|
86
|
-
# Clean up local feature branch
|
|
87
|
-
git branch -d "$FEATURE_BRANCH"
|
|
88
|
-
```
|
|
66
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
89
67
|
|
|
90
68
|
**Report which path was taken.** Print exactly:
|
|
91
69
|
- `"used land-branch.sh"` if Path A
|
|
@@ -117,41 +95,7 @@ mv specs/epics/eNN-slug specs/epics/archive/
|
|
|
117
95
|
|
|
118
96
|
After push (solo-local step 5 or team-pr step 7), verify the CI workflow completes successfully:
|
|
119
97
|
|
|
120
|
-
|
|
121
|
-
echo "==> Polling CI for main branch..."
|
|
122
|
-
TIMEOUT=600 # 10 minutes
|
|
123
|
-
INTERVAL=30 # poll every 30 seconds
|
|
124
|
-
ELAPSED=0
|
|
125
|
-
|
|
126
|
-
while [ $ELAPSED -lt $TIMEOUT ]; do
|
|
127
|
-
CI_JSON=$(gh run list --limit 1 --branch main --workflow CI --json status,conclusion,headSha,databaseId 2>/dev/null)
|
|
128
|
-
CI_STATUS=$(echo "$CI_JSON" | jq -r '.[0].status // "unknown"')
|
|
129
|
-
CI_CONCLUSION=$(echo "$CI_JSON" | jq -r '.[0].conclusion // ""')
|
|
130
|
-
CI_SHA=$(echo "$CI_JSON" | jq -r '.[0].headSha // ""')
|
|
131
|
-
CI_ID=$(echo "$CI_JSON" | jq -r '.[0].databaseId // ""')
|
|
132
|
-
|
|
133
|
-
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "success" ]; then
|
|
134
|
-
echo "OK: CI passed for $(git rev-parse --short HEAD)"
|
|
135
|
-
bp-yaml-set.sh specs/state.yaml release.ci_verified true 2>/dev/null || \
|
|
136
|
-
echo " (bp-yaml-set not available — manually set release.ci_verified: true in state.yaml)"
|
|
137
|
-
break
|
|
138
|
-
fi
|
|
139
|
-
|
|
140
|
-
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "failure" ]; then
|
|
141
|
-
echo "FAIL: CI failed for $(git rev-parse --short HEAD)"
|
|
142
|
-
echo " Run URL: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/actions/runs/$CI_ID"
|
|
143
|
-
echo " Handoff to fix-bug with the failure URL above."
|
|
144
|
-
return 1
|
|
145
|
-
fi
|
|
146
|
-
|
|
147
|
-
sleep $INTERVAL
|
|
148
|
-
ELAPSED=$((ELAPSED + INTERVAL))
|
|
149
|
-
echo " Waiting... (${ELAPSED}s / ${TIMEOUT}s)"
|
|
150
|
-
done
|
|
151
|
-
|
|
152
|
-
echo "FAIL: CI did not complete within ${TIMEOUT}s timeout"
|
|
153
|
-
return 1
|
|
154
|
-
```
|
|
98
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
155
99
|
|
|
156
100
|
- [ ] CI workflow passes after push
|
|
157
101
|
- [ ] `release.ci_verified: true` documented in state.yaml
|
|
@@ -176,14 +120,3 @@ git checkout main && git status && pwd
|
|
|
176
120
|
```
|
|
177
121
|
|
|
178
122
|
Report: "Branch released. Integrate mode: <solo-local|team-pr>. cwd: $(pwd) on $(git branch --show-current)."
|
|
179
|
-
|
|
180
|
-
## Solo-local fallback detail
|
|
181
|
-
|
|
182
|
-
The fallback sequence (Path B above) handles the "remote has moved" case with `git pull --rebase`. Use when `scripts/land-branch.sh` is absent.
|
|
183
|
-
|
|
184
|
-
**Acceptance:** When fallback runs, main is updated, feature branch is deleted locally, and output states `"used fallback merge (land-branch.sh not found)"`.
|
|
185
|
-
|
|
186
|
-
## Handoff
|
|
187
|
-
|
|
188
|
-
Gate: READY -> next: survey-context
|
|
189
|
-
Writes: state.yaml handoff.next_skill = survey-context
|
package/scripts/sync-skills.sh
CHANGED
|
@@ -231,6 +231,9 @@ if [[ -f "$validate_script" ]] && command -v python3 &>/dev/null; then
|
|
|
231
231
|
fi
|
|
232
232
|
|
|
233
233
|
# Regenerate derived reference tables from live SKILL.md frontmatter
|
|
234
|
-
|
|
234
|
+
# Only in dev context (with .git) — not during consumer npm install where docs/ is excluded
|
|
235
|
+
if [[ -d "$REPO_ROOT/.git" ]]; then
|
|
236
|
+
bash "$REPO_ROOT/scripts/generate-reference-tables.sh"
|
|
237
|
+
fi
|
|
235
238
|
|
|
236
239
|
exit 0
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Confidence Scoring Rubric
|
|
2
|
+
|
|
3
|
+
Every finding that survives Phase 4 false-positive filtering receives a confidence
|
|
4
|
+
score from 1 (speculative) to 10 (certain). Only findings ≥ 8 are reported.
|
|
5
|
+
|
|
6
|
+
## Score 9–10: Certain Exploit Path
|
|
7
|
+
|
|
8
|
+
**Criteria:**
|
|
9
|
+
- Concrete, testable exploit with clear reproduction steps
|
|
10
|
+
- No assumptions about uncommon configurations
|
|
11
|
+
- No chain of multiple unlikely conditions
|
|
12
|
+
- Attacker has full control over the input vector
|
|
13
|
+
|
|
14
|
+
**Examples:**
|
|
15
|
+
- User-supplied SQL in a `SELECT` statement with no parameterization
|
|
16
|
+
- `os.system(f"rm {user_path}")` where user controls the path
|
|
17
|
+
- Pickle deserialization of user-supplied data without any wrapping
|
|
18
|
+
|
|
19
|
+
**Severity:** HIGH
|
|
20
|
+
|
|
21
|
+
## Score 8: Clear Vulnerability Pattern
|
|
22
|
+
|
|
23
|
+
**Criteria:**
|
|
24
|
+
- Well-known vulnerability pattern with standard exploitation method
|
|
25
|
+
- Requires specific conditions but conditions are commonly met
|
|
26
|
+
- Exploitability is well-documented in OWASP / CVE databases
|
|
27
|
+
|
|
28
|
+
**Examples:**
|
|
29
|
+
- JWT without signature verification in authentication middleware
|
|
30
|
+
- SSRF where attacker controls the full URL including host
|
|
31
|
+
- Hardcoded AWS secret key in source code
|
|
32
|
+
|
|
33
|
+
**Severity:** HIGH or MEDIUM
|
|
34
|
+
|
|
35
|
+
## Score 7: Suspicious Pattern
|
|
36
|
+
|
|
37
|
+
**Criteria:**
|
|
38
|
+
- Unusual code that may indicate a vulnerability
|
|
39
|
+
- Requires specific conditions that may not be present
|
|
40
|
+
- Alternative secure interpretation is equally likely
|
|
41
|
+
- Defense-in-depth concern rather than direct exploit
|
|
42
|
+
|
|
43
|
+
**Examples:**
|
|
44
|
+
- A function accepting user input that passes through multiple layers before reaching a sink (unclear if sanitized)
|
|
45
|
+
- Custom encryption implementation (likely weak, but may not process sensitive data)
|
|
46
|
+
- Path construction that looks safe but has a subtle bypass
|
|
47
|
+
|
|
48
|
+
**Severity:** LOW or suppress
|
|
49
|
+
|
|
50
|
+
## Score < 7: Do Not Report
|
|
51
|
+
|
|
52
|
+
**Criteria:**
|
|
53
|
+
- Theoretical concern without exploit path
|
|
54
|
+
- Requires unrealistic attacker capabilities
|
|
55
|
+
- Violates one or more hard exclusion rules
|
|
56
|
+
- Better handled by separate tooling (dependency scanner, SAST, secret scanner)
|
|
57
|
+
- Purely stylistic or best-practice concern without security impact
|
|
58
|
+
|
|
59
|
+
**Examples:**
|
|
60
|
+
- "This function doesn't validate all inputs" without proving the validated input is the attack surface
|
|
61
|
+
- "This uses MD5" where the hash is not used for security (e.g., cache key)
|
|
62
|
+
- "This function could consume too much memory" (DOS exclusion)
|
|
63
|
+
|
|
64
|
+
**Action:** Suppress entirely. Do not include in report.
|
|
65
|
+
|
|
66
|
+
## Severity Mapping
|
|
67
|
+
|
|
68
|
+
Once confidence ≥ 8 is confirmed, map to severity:
|
|
69
|
+
|
|
70
|
+
| Severity | Impact | Examples |
|
|
71
|
+
|----------|--------|---------|
|
|
72
|
+
| **CRITICAL** | Remote compromise, full data breach | RCE, auth bypass with admin escalation, SQLi with data exfiltration |
|
|
73
|
+
| **HIGH** | Significant security boundary crossed | SSRF to internal services, hardcoded cloud credentials, insecure deserialization |
|
|
74
|
+
| **MEDIUM** | Limited impact or requires conditions | Stored XSS behind auth, IDOR on non-sensitive data, weak but not broken crypto |
|
|
75
|
+
| **LOW** | Defense-in-depth, minimal blast radius | Missing security header, verbose error messages in non-production |
|
|
76
|
+
|
|
77
|
+
## Quality Gate
|
|
78
|
+
|
|
79
|
+
The confidence rubric double-checks each finding against three lenses:
|
|
80
|
+
|
|
81
|
+
| Lens | Question |
|
|
82
|
+
|------|----------|
|
|
83
|
+
| **Exploitability** | Can a real attacker trigger this from a trust boundary? |
|
|
84
|
+
| **Actionability** | Would a security engineer accept a fix recommendation for this? |
|
|
85
|
+
| **Precedent** | Has this type of finding passed/failed human review before? |
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# False-Positive Exclusion Rules
|
|
2
|
+
|
|
3
|
+
Applied during Phase 4 of the scan. Findings matching any hard exclusion are
|
|
4
|
+
automatically suppressed. Precedents from prior reviews guide borderline cases.
|
|
5
|
+
|
|
6
|
+
## Hard Exclusions
|
|
7
|
+
|
|
8
|
+
Automatically exclude findings matching these patterns:
|
|
9
|
+
|
|
10
|
+
| # | Rule | Rationale |
|
|
11
|
+
|---|------|-----------|
|
|
12
|
+
| 1 | **Denial of Service (DOS)** — resource exhaustion, CPU/memory attacks | Handled separately; not actionable in code review |
|
|
13
|
+
| 2 | **Secrets on disk** if otherwise secured | Secrets management is a separate concern |
|
|
14
|
+
| 3 | **Rate limiting** concerns | Operational, not a code vulnerability |
|
|
15
|
+
| 4 | **Memory consumption / CPU exhaustion** | Not actionable in diff review |
|
|
16
|
+
| 5 | **Input validation on non-security-critical fields** without proven exploit path | Theoretical, not concrete |
|
|
17
|
+
| 6 | **GitHub Actions input sanitization** unless clearly triggerable via untrusted input | Most workflow vulns are not exploitable |
|
|
18
|
+
| 7 | **Lack of hardening measures** | Code is not expected to implement all best practices |
|
|
19
|
+
| 8 | **Race conditions / timing attacks** that are theoretical | Only report if concretely problematic |
|
|
20
|
+
| 9 | **Outdated third-party libraries** | Managed separately by dependency scanners |
|
|
21
|
+
| 10 | **Memory safety** in Rust or other memory-safe languages | Impossible by language guarantees |
|
|
22
|
+
| 11 | **Unit test files only** | Not production risk |
|
|
23
|
+
| 12 | **Log spoofing** | Outputting unsanitized input to logs is not a vuln |
|
|
24
|
+
| 13 | **SSRF that only controls path** | Only host/protocol control is exploitable |
|
|
25
|
+
| 14 | **User-controlled content in AI system prompts** | Not a security vulnerability |
|
|
26
|
+
| 15 | **Regex injection** | Injecting untrusted content into regex is not a vuln |
|
|
27
|
+
| 16 | **Regex DOS** | Excluded alongside general DOS |
|
|
28
|
+
| 17 | **Documentation files** (.md, .txt) | Insecure docs are not code vulnerabilities |
|
|
29
|
+
| 18 | **Lack of audit logs** | Not a vulnerability |
|
|
30
|
+
|
|
31
|
+
## Precedent Rules
|
|
32
|
+
|
|
33
|
+
These guide borderline cases based on prior human review decisions:
|
|
34
|
+
|
|
35
|
+
| # | Precedent | Reasoning |
|
|
36
|
+
|---|-----------|-----------|
|
|
37
|
+
| 1 | **Logging high-value secrets in plaintext IS a vuln.** Logging URLs is safe. | Secrets in logs = credential exposure; URLs are not secrets |
|
|
38
|
+
| 2 | **UUIDs are unguessable** — no validation needed | Cryptographic property of UUID v4/v7 |
|
|
39
|
+
| 3 | **Environment variables and CLI flags are trusted values** | Attackers cannot modify these in secure environments |
|
|
40
|
+
| 4 | **Resource management issues** (memory leaks, fd leaks) are NOT valid | Operational, not security |
|
|
41
|
+
| 5 | **Tabnabbing, XS-Leaks, prototype pollution, open redirects** — do NOT report unless extremely high confidence | Subtle, low-impact, high false-positive rate |
|
|
42
|
+
| 6 | **React/Angular XSS** — safe unless `dangerouslySetInnerHTML`, `bypassSecurityTrustHtml`, etc. | Framework auto-escapes |
|
|
43
|
+
| 7 | **GitHub Action workflow vulns** — verify concrete attack path before reporting | Most are theoretical |
|
|
44
|
+
| 8 | **Client-side JS/TS auth checks** — not a vuln; server is authoritative | Client code is untrusted |
|
|
45
|
+
| 9 | **IPython notebook vulns** — only report if concrete untrusted-input trigger | Most are not exploitable |
|
|
46
|
+
| 10 | **Logging non-PII data** — not a vuln even if sensitive. Only PII/secrets/passwords. | Intent: operational logging vs credential exposure |
|
|
47
|
+
| 11 | **Shell script command injection** — only report if concrete untrusted-input path | Most shell scripts don't process untrusted input |
|
|
48
|
+
|
|
49
|
+
## Confidence Scoring
|
|
50
|
+
|
|
51
|
+
Findings that survive exclusions get a confidence score (1–10):
|
|
52
|
+
|
|
53
|
+
| Range | Meaning | Action |
|
|
54
|
+
|-------|---------|--------|
|
|
55
|
+
| 9–10 | Certain exploit path, testable | Report as HIGH |
|
|
56
|
+
| 8 | Clear vulnerability pattern | Report as HIGH/MEDIUM |
|
|
57
|
+
| 7 | Suspicious, needs conditions | Report as LOW or suppress |
|
|
58
|
+
| <7 | Too speculative | **Do not report** |
|
|
59
|
+
|
|
60
|
+
**Hard threshold:** Only report findings with confidence ≥ 8.
|
|
61
|
+
|
|
62
|
+
## Signal Quality Criteria
|
|
63
|
+
|
|
64
|
+
For remaining findings, assess:
|
|
65
|
+
1. Is there a concrete, exploitable vulnerability with a clear attack path?
|
|
66
|
+
2. Does this represent a real security risk (vs theoretical best practice)?
|
|
67
|
+
3. Are there specific code locations and reproduction steps?
|
|
68
|
+
4. Would this finding be actionable for a security team?
|