forgedock 1.0.16 → 1.0.17

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 (71) hide show
  1. package/README.md +21 -3
  2. package/bin/forgedock.mjs +1992 -540
  3. package/bin/github-app-manifest.json.license +2 -0
  4. package/bin/hooks/session-start.mjs +4 -5
  5. package/bin/registry.mjs +20 -0
  6. package/bin/tui.mjs +172 -96
  7. package/commands/adopt.md +433 -0
  8. package/commands/analytics.md +2 -0
  9. package/commands/audit-agents.md +2 -0
  10. package/commands/audit.md +2 -0
  11. package/commands/changelog.md +354 -0
  12. package/commands/cleanup.md +2 -0
  13. package/commands/compat-audit.md +330 -0
  14. package/commands/deploy-info.md +6 -5
  15. package/commands/diagnose.md +483 -0
  16. package/commands/explain.md +349 -0
  17. package/commands/forge-stats.md +2 -0
  18. package/commands/forgedock-init.md +2 -0
  19. package/commands/geo-audit.md +2 -0
  20. package/commands/incident-response.md +2 -0
  21. package/commands/issue.md +2 -0
  22. package/commands/milestone.md +2 -0
  23. package/commands/optimize.md +411 -0
  24. package/commands/orchestrate.md +118 -0
  25. package/commands/pipeline-health.md +60 -1
  26. package/commands/qa-sweep.md +2 -0
  27. package/commands/quality-gate.md +37 -0
  28. package/commands/replay.md +263 -0
  29. package/commands/resume.md +264 -0
  30. package/commands/review-pr-agents.md +5 -1
  31. package/commands/review-pr-staging.md +2 -0
  32. package/commands/review-pr.md +85 -3
  33. package/commands/rollback.md +2 -0
  34. package/commands/scope.md +280 -0
  35. package/commands/security-audit.md +2 -0
  36. package/commands/status.md +262 -0
  37. package/commands/sync-ecosystem.md +2 -0
  38. package/commands/validate.md +2 -0
  39. package/commands/work-on/build/architect.md +128 -18
  40. package/commands/work-on/build/context.md +130 -17
  41. package/commands/work-on/build/implement.md +2 -0
  42. package/commands/work-on/build/validate.md +2 -0
  43. package/commands/work-on/build.md +32 -7
  44. package/commands/work-on/close.md +85 -0
  45. package/commands/work-on/decompose.md +2 -0
  46. package/commands/work-on/investigate.md +30 -3
  47. package/commands/work-on/review.md +13 -1
  48. package/commands/work-on-monolithic.md +2 -0
  49. package/commands/work-on.md +624 -36
  50. package/docs/BRAND.md +51 -0
  51. package/docs/CONFIG.md +94 -0
  52. package/docs/articles/per-repo-adaptive-scripts-token-savings.md +174 -0
  53. package/docs/claude-breakpoints.json +47 -0
  54. package/docs/site/getting-started.md +21 -0
  55. package/package.json +3 -3
  56. package/scripts/classify-lane.sh +145 -0
  57. package/scripts/transition-label.sh +161 -0
  58. package/scripts/validate-pr-target.sh +30 -0
  59. package/templates/devdocs/README.md +72 -0
  60. package/templates/devdocs/agent/using-forgedock.md +3 -0
  61. package/templates/devdocs/agent/using-github.md +3 -0
  62. package/templates/devdocs/index.yaml +162 -0
  63. package/templates/devdocs/project/architecture.md +3 -0
  64. package/templates/devdocs/project/conventions.md +3 -0
  65. package/templates/devdocs/project/custom-instructions.md +3 -0
  66. package/templates/devdocs/project/glossary.md +3 -0
  67. package/templates/devdocs/project/stack.md +3 -0
  68. package/templates/devdocs/templates/commit-convention.md +3 -0
  69. package/templates/devdocs/templates/issue.md +3 -0
  70. package/templates/devdocs/templates/pull-request.md +3 -0
  71. package/templates/devdocs/templates/review-finding.md +3 -0
@@ -3,6 +3,8 @@ description: Context-aware PR review — analyzes what the PR touches, spawns do
3
3
  argument-hint: [PR number, URL, "open", or "staging" for feature→main review]
4
4
  allowed-tools: Task, Bash, Read, Grep, Glob, WebFetch, Skill
5
5
  ---
6
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
7
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
6
8
 
7
9
  # PR Review — Orchestrator
8
10
 
@@ -124,6 +126,9 @@ while [ "$MERGE_HEALTH" = "UNKNOWN" ] && [ "$MERGE_RETRY" -lt 3 ]; do
124
126
  done
125
127
  # MERGE_HEALTH: MERGEABLE | CONFLICTING | UNKNOWN (still async after retries)
126
128
  # MERGE_HEALTH_STATE: CLEAN | DIRTY | BLOCKED | UNSTABLE | UNKNOWN
129
+
130
+ # Resolve repo name early — used in Phases 5, 6, 8B, 9A (clean-review skip path bypasses Phase 6A) <!-- Added: forge#820 -->
131
+ REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
127
132
  ```
128
133
 
129
134
  ### 1B: Classify
@@ -731,7 +736,6 @@ If synthesis needed, launch a `general-purpose` Task (model: resolved per policy
731
736
  ### 6A: Extract Findings
732
737
 
733
738
  ```bash
734
- REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
735
739
  HAS_SYNTHESIS=$(gh api "repos/${REPO}/issues/${PR_NUMBER}/comments" --jq '.[].body' | grep -c 'REVIEW-FINDINGS-SYNTHESIZED-START' || echo 0)
736
740
 
737
741
  if [ "$HAS_SYNTHESIS" -gt 0 ]; then
@@ -786,8 +790,8 @@ fi
786
790
 
787
791
  if [ -n "$MILESTONE_BRANCH" ]; then
788
792
  BRANCH_SLUG=$(echo "$MILESTONE_BRANCH" | sed 's|^milestone/||')
789
- MILESTONE_NUMBER=$(gh api repos/${REPO}/milestones --jq --arg slug "$BRANCH_SLUG" '.[] | select((.title | ascii_downcase | gsub("[^a-z0-9]+"; "-")) == $slug) | .number' 2>/dev/null | head -1)
790
- [ -z "$MILESTONE_NUMBER" ] && MILESTONE_NUMBER=$(gh api repos/${REPO}/milestones --jq --arg slug "$BRANCH_SLUG" '.[] | select((.title | ascii_downcase | gsub("[^a-z0-9]+"; "-")) | test($slug)) | .number' 2>/dev/null | head -1)
793
+ MILESTONE_NUMBER=$(gh api repos/${REPO}/milestones 2>/dev/null | jq --arg slug "$BRANCH_SLUG" '.[] | select((.title | ascii_downcase | gsub("[^a-z0-9]+"; "-")) == $slug) | .number' 2>/dev/null | head -1)
794
+ [ -z "$MILESTONE_NUMBER" ] && MILESTONE_NUMBER=$(gh api repos/${REPO}/milestones 2>/dev/null | jq --arg slug "$BRANCH_SLUG" '.[] | select((.title | ascii_downcase | gsub("[^a-z0-9]+"; "-")) | test($slug)) | .number' 2>/dev/null | head -1)
791
795
  [ -n "$MILESTONE_NUMBER" ] && MILESTONE_FLAG="--milestone $(gh api repos/${REPO}/milestones/${MILESTONE_NUMBER} --jq '.title')"
792
796
  fi
793
797
  ```
@@ -1060,12 +1064,89 @@ fi
1060
1064
 
1061
1065
  **Important**: Phase 8 ONLY merges the PR. It does NOT close the issue, update labels, or clean up worktrees. When invoked via `/work-on`, those responsibilities belong to `work-on/close.md` — which runs after the router detects state 4 (MERGE_COMPLETE: PR merged + issue open). Doing them here would cause the router to hit TERMINAL_MERGED (state 1) and skip the close phase entirely.
1062
1066
 
1067
+ ### 8B: Post-Merge Review Finding Demilestoning (Milestone PRs Only)
1068
+
1069
+ **Skip if**: `IS_MILESTONE_TO_STAGING` is false or `MERGE_STATE != "MERGED"`. Runs only when a milestone→staging PR was just successfully merged.
1070
+
1071
+ **Purpose**: Review-finding issues created during a milestone PR review (Phase 6C) inherit the milestone. Once the milestone PR merges, those findings should flow through the fast lane independently — not remain stranded on a closed milestone. This step clears their milestone assignment automatically.
1072
+
1073
+ ```bash
1074
+ if [ "${IS_MILESTONE_TO_STAGING:-false}" = "true" ] && [ "${MERGE_STATE:-}" = "MERGED" ]; then
1075
+ echo "Phase 8B: Clearing milestone from open review-finding issues referencing PR #${PR_NUMBER}..."
1076
+
1077
+ # Find open review-finding issues whose body references this PR number
1078
+ # The title template in Phase 6C always includes: "review finding — PR #${PR_NUMBER}"
1079
+ FINDINGS_TO_DEMILESTONE=$(gh issue list -R "${REPO}" \
1080
+ --state open \
1081
+ --label "review-finding" \
1082
+ --limit 200 \
1083
+ --json number,title,milestone \
1084
+ --jq ".[] | select(.milestone != null) | select(.title | test(\"PR #${PR_NUMBER}\")) | .number" \
1085
+ 2>/dev/null || echo "")
1086
+
1087
+ if [ -z "$FINDINGS_TO_DEMILESTONE" ]; then
1088
+ echo "Phase 8B: No open review-finding issues with milestones found referencing PR #${PR_NUMBER}."
1089
+ else
1090
+ MOVED_COUNT=0
1091
+ echo "$FINDINGS_TO_DEMILESTONE" | while IFS= read -r FINDING_NUM; do
1092
+ [ -z "$FINDING_NUM" ] && continue
1093
+ FINDING_TITLE=$(gh issue view "$FINDING_NUM" -R "${REPO}" --json title --jq '.title' 2>/dev/null || echo "#${FINDING_NUM}")
1094
+ gh issue edit "$FINDING_NUM" -R "${REPO}" --milestone "" 2>/dev/null && \
1095
+ echo " Moved to fast lane: #${FINDING_NUM} — ${FINDING_TITLE}" || \
1096
+ echo " WARNING: Failed to clear milestone for #${FINDING_NUM}"
1097
+ MOVED_COUNT=$((MOVED_COUNT + 1))
1098
+ done
1099
+ echo "Phase 8B: Review finding demilestoning complete."
1100
+ fi
1101
+ fi
1102
+ ```
1103
+
1104
+ <!-- Added: forge#815 -->
1105
+
1063
1106
  ---
1064
1107
 
1065
1108
  ## Phase 9: Integrity Check & Summary (LAST)
1066
1109
 
1067
1110
  **Run AFTER Phase 6 (issues created), Phase 7 (verdict posted), Phase 8 (merge if applicable).**
1068
1111
 
1112
+ ### 9A: Post-Merge Review Finding Demilestoning Fallback (Milestone PRs Only)
1113
+
1114
+ **Skip if**: `IS_MILESTONE_TO_STAGING` is false. Runs when `AUTO_MERGE=false` but the PR was merged manually — Phase 8B did not run in this case, so Phase 9 handles cleanup.
1115
+
1116
+ **Detection**: Check if the PR is now MERGED. If so and `IS_MILESTONE_TO_STAGING=true`, run the same demilestoning logic as Phase 8B.
1117
+
1118
+ ```bash
1119
+ if [ "${IS_MILESTONE_TO_STAGING:-false}" = "true" ]; then
1120
+ PR_MERGE_STATE=$(gh pr view $ARGUMENTS --json state --jq '.state' 2>/dev/null || echo "")
1121
+ if [ "$PR_MERGE_STATE" = "MERGED" ]; then
1122
+ echo "Phase 9A: Checking for open review-finding issues to demilestone (fallback — manual merge path)..."
1123
+
1124
+ FINDINGS_TO_DEMILESTONE=$(gh issue list -R "${REPO}" \
1125
+ --state open \
1126
+ --label "review-finding" \
1127
+ --limit 200 \
1128
+ --json number,title,milestone \
1129
+ --jq ".[] | select(.milestone != null) | select(.title | test(\"PR #${PR_NUMBER}\")) | .number" \
1130
+ 2>/dev/null || echo "")
1131
+
1132
+ if [ -z "$FINDINGS_TO_DEMILESTONE" ]; then
1133
+ echo "Phase 9A: No open review-finding issues with milestones found referencing PR #${PR_NUMBER} (already cleared or none created)."
1134
+ else
1135
+ echo "$FINDINGS_TO_DEMILESTONE" | while IFS= read -r FINDING_NUM; do
1136
+ [ -z "$FINDING_NUM" ] && continue
1137
+ FINDING_TITLE=$(gh issue view "$FINDING_NUM" -R "${REPO}" --json title --jq '.title' 2>/dev/null || echo "#${FINDING_NUM}")
1138
+ gh issue edit "$FINDING_NUM" -R "${REPO}" --milestone "" 2>/dev/null && \
1139
+ echo " Moved to fast lane: #${FINDING_NUM} — ${FINDING_TITLE}" || \
1140
+ echo " WARNING: Failed to clear milestone for #${FINDING_NUM}"
1141
+ done
1142
+ echo "Phase 9A: Fallback demilestoning complete."
1143
+ fi
1144
+ fi
1145
+ fi
1146
+ ```
1147
+
1148
+ <!-- Added: forge#815 -->
1149
+
1069
1150
  ```bash
1070
1151
  CURRENT_SHA=$(gh pr view $ARGUMENTS --json headRefOid --jq '.headRefOid')
1071
1152
  REVIEW_IS_STALE="false"
@@ -1118,4 +1199,5 @@ Review complete for PR #X. Verdict: [VERDICT].
1118
1199
  - Integration checks: [pass/N broken paths found]
1119
1200
  - Issues created: [M]
1120
1201
  {IF AUTO_MERGE: "PR merged and issue closed." / "Merge FAILED — see issue."}
1202
+ {IF IS_MILESTONE_TO_STAGING: "Review findings demilestoned: [N] issues moved to fast lane." / ""}
1121
1203
  ```
@@ -2,6 +2,8 @@
2
2
  description: Create a revert PR to roll back a shipped feature or fix that caused a production incident
3
3
  argument-hint: [PR number to revert, or "last" for most recent deploy]
4
4
  ---
5
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
5
7
 
6
8
  # /rollback — Automated Revert PR Creation
7
9
 
@@ -0,0 +1,280 @@
1
+ ---
2
+ description: Estimate issue complexity before running /work-on — affected files, blast radius, risk flags, and decomposition recommendation
3
+ argument-hint: <issue number> [--repo {owner}/{repo}]
4
+ ---
5
+
6
+ # /scope — Pre-Flight Complexity Estimator
7
+
8
+ **Input**: $ARGUMENTS
9
+
10
+ You are a read-only pre-flight analyst. Given a GitHub issue number, you estimate how complex it is BEFORE the user commits to running `/work-on`. You surface affected files, blast radius, dependency risks, estimated pipeline phases, and a decomposition recommendation.
11
+
12
+ **This command is strictly READ-ONLY.** No labels are written, no comments are posted, no worktrees are created.
13
+
14
+ **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
15
+ **NEVER use plan mode (EnterPlanMode).**
16
+
17
+ ---
18
+
19
+ ## Config Preamble
20
+
21
+ Read `forge.yaml` before running any phase:
22
+
23
+ ```bash
24
+ CONFIG_FILE="${FORGE_CONFIG:-forge.yaml}"
25
+ if [ -f "$CONFIG_FILE" ]; then
26
+ GH_OWNER=$(yq '.project.owner' "$CONFIG_FILE")
27
+ GH_REPO_NAME=$(yq '.project.repo' "$CONFIG_FILE")
28
+ GH_REPO="${GH_OWNER}/${GH_REPO_NAME}"
29
+ GH_FLAG="-R $GH_REPO"
30
+ REPO_PATH=$(yq '.paths.root' "$CONFIG_FILE")
31
+ else
32
+ echo "WARNING: forge.yaml not found."
33
+ echo "Run: npx forgedock init"
34
+ exit 1
35
+ fi
36
+ ```
37
+
38
+ Parse `$ARGUMENTS`:
39
+ - `{NUMBER}` — issue number (required)
40
+ - `--repo {owner}/{repo}` — override GH_REPO (optional; useful for satellite repos)
41
+
42
+ If `--repo` is provided: set `GH_REPO` and `GH_FLAG` to the override value.
43
+
44
+ ---
45
+
46
+ ## Phase 1: Load Issue
47
+
48
+ ```bash
49
+ gh issue view {NUMBER} {GH_FLAG} \
50
+ --json number,title,body,labels,milestone,state
51
+ ```
52
+
53
+ If the issue is CLOSED: print `Issue #{NUMBER} is already closed — scope analysis may not be actionable.` and continue anyway (the user may be scoping a re-open or reference).
54
+
55
+ Extract:
56
+ - `TITLE` — issue title (strip conventional commit prefix: `fix:`, `feat:`, `refactor:`, `chore:`)
57
+ - `BODY` — full body text
58
+ - `LABELS` — label names (used for domain detection)
59
+ - `MILESTONE` — milestone title if set (indicates feature lane)
60
+ - `TASK_TYPE` — infer from title prefix: `fix:` → Bug Fix, `feat:` → Feature, `refactor:` → Refactor, `chore:` → Maintenance, other → Unknown
61
+
62
+ ---
63
+
64
+ ## Phase 2: Extract Keywords
65
+
66
+ From `TITLE` and `BODY`, extract:
67
+ 1. **Explicit file references** — anything matching `*.py`, `*.ts`, `*.tsx`, `*.md`, `*.yml`, `*.yaml`, `*.json`, `*.sh`, `docker-compose*`, `Dockerfile*` — collect as `EXPLICIT_FILES`
68
+ 2. **Domain terms** — nouns and compound terms (e.g. function names, service names, component names, CLI command names) — collect as `DOMAIN_TERMS`
69
+ 3. **Affected section files** — lines under `## Affected Files` section in the body (if present)
70
+
71
+ Merge `EXPLICIT_FILES` + `AFFECTED_SECTION_FILES` into `TARGET_FILES` (deduplicated).
72
+
73
+ Limit `DOMAIN_TERMS` to the 10 most specific (skip generic words: "fix", "bug", "issue", "add", "the", "and", "for", "with", "use", "get", "set").
74
+
75
+ ---
76
+
77
+ ## Phase 3: Affected-File Discovery
78
+
79
+ Search `REPO_PATH` for each keyword to find candidate files:
80
+
81
+ ```bash
82
+ # For each file explicitly named in the issue
83
+ for file in {TARGET_FILES}; do
84
+ find "$REPO_PATH" -name "$file" -not -path "*/.git/*" -not -path "*/node_modules/*" 2>/dev/null
85
+ done
86
+
87
+ # For each domain term: grep for references
88
+ for term in {DOMAIN_TERMS}; do
89
+ grep -rl "$term" "$REPO_PATH" \
90
+ --include="*.py" --include="*.ts" --include="*.tsx" \
91
+ --include="*.md" --include="*.yml" --include="*.yaml" \
92
+ --include="*.json" --include="*.sh" \
93
+ --exclude-dir=".git" --exclude-dir="node_modules" \
94
+ --exclude-dir=".claude" 2>/dev/null | head -5
95
+ done
96
+
97
+ # Git log — files recently changed alongside the named files
98
+ if [ -n "{TARGET_FILES}" ]; then
99
+ for file in {TARGET_FILES}; do
100
+ git -C "$REPO_PATH" log --oneline -20 -- "$file" \
101
+ --name-only --format="" 2>/dev/null | grep -v "^$" | sort -u | head -10
102
+ done
103
+ fi
104
+ ```
105
+
106
+ Collect all results into `CANDIDATE_FILES` (deduplicated, sorted, absolute paths stripped to relative).
107
+
108
+ **Relevance filter**: Keep only files where the keyword match is in the file's primary logic — not in test fixtures, lock files, or generated output. Exclude: `*.lock`, `package-lock.json`, `yarn.lock`, `*.min.js`, `dist/`, `build/`, `.next/`, `__pycache__/`.
109
+
110
+ Final list: `AFFECTED_FILES` — at most 25 files.
111
+
112
+ ---
113
+
114
+ ## Phase 4: Blast Radius
115
+
116
+ From `AFFECTED_FILES`, compute:
117
+
118
+ ```bash
119
+ # Count unique top-level directories
120
+ DIRS=$(echo "{AFFECTED_FILES}" | xargs -I{} dirname {} | sort -u)
121
+ DIR_COUNT=$(echo "$DIRS" | grep -c .)
122
+
123
+ # Count unique service groups (second-level directories under known roots)
124
+ # Adapt to project structure — common roots: services/, apps/, packages/, web/, commands/
125
+ SERVICE_GROUPS=$(echo "{AFFECTED_FILES}" | sed 's|/[^/]*$||' | sort -u)
126
+ SERVICE_COUNT=$(echo "$SERVICE_GROUPS" | grep -c .)
127
+
128
+ # Classify affected modules
129
+ MODULES=""
130
+ echo "{AFFECTED_FILES}" | grep -q "^commands/" && MODULES="$MODULES pipeline-commands"
131
+ echo "{AFFECTED_FILES}" | grep -q "^bin/" && MODULES="$MODULES installer"
132
+ echo "{AFFECTED_FILES}" | grep -q "^\.github/" && MODULES="$MODULES CI/CD"
133
+ echo "{AFFECTED_FILES}" | grep -q "^docs/" && MODULES="$MODULES docs"
134
+ echo "{AFFECTED_FILES}" | grep -q "services/" && MODULES="$MODULES backend-services"
135
+ echo "{AFFECTED_FILES}" | grep -q "web/" && MODULES="$MODULES frontend"
136
+ echo "{AFFECTED_FILES}" | grep -q "infra/\|docker-compose" && MODULES="$MODULES infrastructure"
137
+ echo "{AFFECTED_FILES}" | grep -q "migrations/" && MODULES="$MODULES database"
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Phase 5: Risk Flag Detection
143
+
144
+ Scan `AFFECTED_FILES` and the issue body for high-risk signals:
145
+
146
+ ```bash
147
+ RISK_FLAGS=""
148
+
149
+ # Auth risk
150
+ (echo "{AFFECTED_FILES}" | grep -qiE "auth|login|session|token|jwt|oauth|permission|role" || \
151
+ echo "$BODY" | grep -qiE "auth|login|session|token|jwt|oauth|permission|role") && \
152
+ RISK_FLAGS="$RISK_FLAGS AUTH"
153
+
154
+ # Billing risk
155
+ (echo "{AFFECTED_FILES}" | grep -qiE "billing|payment|stripe|subscription|credit|invoice" || \
156
+ echo "$BODY" | grep -qiE "billing|payment|stripe|subscription|credit|invoice") && \
157
+ RISK_FLAGS="$RISK_FLAGS BILLING"
158
+
159
+ # Database migration risk
160
+ (echo "{AFFECTED_FILES}" | grep -qiE "migration|alembic|schema|model" || \
161
+ echo "$BODY" | grep -qiE "migration|schema change|db migration|database") && \
162
+ RISK_FLAGS="$RISK_FLAGS DB-MIGRATION"
163
+
164
+ # API schema / contract risk
165
+ (echo "{AFFECTED_FILES}" | grep -qiE "openapi|schema|serializer|types\.ts|api\.ts|client\.py" || \
166
+ echo "$BODY" | grep -qiE "api.contract|breaking.change|response.shape|openapi") && \
167
+ RISK_FLAGS="$RISK_FLAGS API-CONTRACT"
168
+
169
+ # CI/CD risk
170
+ (echo "{AFFECTED_FILES}" | grep -qiE "\.github/workflows|Dockerfile|docker-compose|deploy|infra/" || \
171
+ echo "$BODY" | grep -qiE "deploy|CI|CD|workflow|dockerfile|container") && \
172
+ RISK_FLAGS="$RISK_FLAGS CI-CD"
173
+
174
+ # Pipeline-phase risk (for ForgeDock itself)
175
+ echo "{AFFECTED_FILES}" | grep -qE "^commands/(work-on|review-pr|quality-gate|orchestrate)" && \
176
+ RISK_FLAGS="$RISK_FLAGS PIPELINE-CORE"
177
+
178
+ # New env vars
179
+ echo "$BODY" | grep -qiE "env var|environment variable|\.env|getenv|process\.env" && \
180
+ RISK_FLAGS="$RISK_FLAGS ENV-VARS"
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Phase 6: Complexity Scoring
186
+
187
+ Compute a complexity score from the signals collected:
188
+
189
+ | Signal | Points |
190
+ |--------|--------|
191
+ | Each affected file | +1 |
192
+ | Each unique directory | +2 |
193
+ | AUTH risk flag | +5 |
194
+ | BILLING risk flag | +5 |
195
+ | DB-MIGRATION risk flag | +4 |
196
+ | API-CONTRACT risk flag | +3 |
197
+ | CI-CD risk flag | +3 |
198
+ | PIPELINE-CORE risk flag | +4 |
199
+ | ENV-VARS risk flag | +2 |
200
+ | Milestone set (feature lane) | +3 |
201
+ | 2+ task type signals in body | +3 |
202
+
203
+ **Score bands**:
204
+ | Score | Band | Typical pipeline time |
205
+ |-------|------|-----------------------|
206
+ | 0–10 | TRIVIAL | 5–15 min (1-file fix, 1–2 pipeline phases) |
207
+ | 11–20 | SIMPLE | 20–40 min (2–5 files, all phases) |
208
+ | 21–35 | MODERATE | 45–90 min (5–10 files, possible review findings) |
209
+ | 36–55 | COMPLEX | 90–150 min (10+ files, multiple domains) |
210
+ | 56+ | DECOMPOSE | 2h+ (multiple task types, 3+ service groups) |
211
+
212
+ ---
213
+
214
+ ## Phase 7: Decomposition Recommendation
215
+
216
+ Apply the same signals `/work-on` uses to trigger decomposition. Recommend **decompose: YES** if 2+ of these signals match (at least 1 Strong):
217
+
218
+ **Strong signals**:
219
+ - [ ] 2+ distinct task types (Bug Fix + Feature, Refactor + Feature, etc.)
220
+ - [ ] 3+ service groups affected
221
+ - [ ] 6+ files across 3+ directories
222
+
223
+ **Supporting signals**:
224
+ - [ ] Phased requirements ("first do X, then Y, then Z")
225
+ - [ ] Score band is DECOMPOSE (56+)
226
+ - [ ] Both frontend and backend affected
227
+ - [ ] DB migration + API contract change in same issue
228
+
229
+ If decompose: YES — suggest 2–4 sub-issue titles based on the natural fault lines visible in the affected-file analysis.
230
+
231
+ ---
232
+
233
+ ## Phase 8: Output Scope Report
234
+
235
+ Print a structured scope report. Do NOT post it as a GitHub comment — print to stdout only.
236
+
237
+ ```
238
+ ╔══════════════════════════════════════════════════════════════╗
239
+ ║ /scope — Issue #{NUMBER}: {TITLE}
240
+ ╠══════════════════════════════════════════════════════════════╣
241
+ ║ Task type : {TASK_TYPE}
242
+ ║ Lane : {Fast lane (no milestone) | Feature lane — milestone: {MILESTONE}}
243
+ ║ Complexity: {SCORE} → {BAND}
244
+ ║ Est. time : {TYPICAL_PIPELINE_TIME}
245
+ ╠══════════════════════════════════════════════════════════════╣
246
+ ║ AFFECTED FILES ({COUNT})
247
+ ╠══════════════════════════════════════════════════════════════╣
248
+ {list each file — one per line, relative to REPO_PATH}
249
+ ╠══════════════════════════════════════════════════════════════╣
250
+ ║ BLAST RADIUS
251
+ ║ Directories : {DIR_COUNT}
252
+ ║ Modules : {MODULES}
253
+ ╠══════════════════════════════════════════════════════════════╣
254
+ ║ RISK FLAGS
255
+ {if no flags: " None detected"}
256
+ {for each flag: " ⚠ {FLAG} — {brief note on what to watch for}"}
257
+ ╠══════════════════════════════════════════════════════════════╣
258
+ ║ DECOMPOSITION
259
+ ║ Recommendation: {decompose: YES | decompose: NO}
260
+ {if YES:
261
+ "║ Signals met: {list matched signals}
262
+ ║ Suggested sub-issues:
263
+ ║ 1. {sub-issue title}
264
+ ║ 2. {sub-issue title}
265
+ ║ → Run /work-on {NUMBER} — it will auto-decompose based on investigation."
266
+ }
267
+ {if NO:
268
+ "║ → Safe to run /work-on {NUMBER} directly."
269
+ }
270
+ ╚══════════════════════════════════════════════════════════════╝
271
+ ```
272
+
273
+ Risk flag annotations:
274
+ - AUTH — review auth middleware, permission checks, and session handling carefully
275
+ - BILLING — get explicit sign-off before merging; test with real payment fixtures
276
+ - DB-MIGRATION — verify migration is reversible and tested on a copy of prod data
277
+ - API-CONTRACT — grep all consumers of the changed endpoint before shipping
278
+ - CI-CD — test workflow changes in a fork or staging environment first
279
+ - PIPELINE-CORE — changes to work-on/review-pr/quality-gate affect the entire AI dev loop; review-pr will run extra scrutiny
280
+ - ENV-VARS — ensure new vars are added to .env.example and all required config locations
@@ -2,6 +2,8 @@
2
2
  description: Periodic security posture audit — runs a scripted 4-phase checklist against repo files (not diffs), creates GitHub issues for confirmed findings
3
3
  argument-hint: [--repo <prefix>] [--phase 1|2|3|4|all] [--dry-run]
4
4
  ---
5
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
5
7
 
6
8
  # /security-audit — Periodic Security Posture Audit
7
9