forgedock 1.0.16 → 1.0.18

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 (190) hide show
  1. package/README.md +54 -3
  2. package/bin/cross-publish.mjs +344 -0
  3. package/bin/forgedock.mjs +2205 -541
  4. package/bin/github-app-manifest.json.license +2 -0
  5. package/bin/hooks/session-start.mjs +4 -5
  6. package/bin/registry.mjs +20 -0
  7. package/bin/tui.mjs +172 -96
  8. package/commands/adopt.md +433 -0
  9. package/commands/analytics.md +2 -0
  10. package/commands/audit-agents.md +2 -0
  11. package/commands/audit.md +2 -0
  12. package/commands/autopilot.md +77 -0
  13. package/commands/changelog.md +354 -0
  14. package/commands/cleanup.md +2 -0
  15. package/commands/compat-audit.md +330 -0
  16. package/commands/deploy-info.md +6 -5
  17. package/commands/design-bench.md +176 -0
  18. package/commands/design-render-critique-loop.md +103 -0
  19. package/commands/design.md +259 -0
  20. package/commands/diagnose.md +483 -0
  21. package/commands/explain.md +349 -0
  22. package/commands/forge-stats.md +2 -0
  23. package/commands/forgedock-init.md +2 -0
  24. package/commands/geo-audit.md +2 -0
  25. package/commands/incident-response.md +2 -0
  26. package/commands/issue.md +9 -3
  27. package/commands/milestone.md +2 -0
  28. package/commands/optimize.md +411 -0
  29. package/commands/orchestrate.md +239 -0
  30. package/commands/pipeline-health.md +60 -1
  31. package/commands/qa-sweep.md +39 -2
  32. package/commands/quality-gate.md +67 -0
  33. package/commands/replay.md +263 -0
  34. package/commands/resume.md +264 -0
  35. package/commands/review-pr-agents.md +5 -1
  36. package/commands/review-pr-staging.md +160 -2
  37. package/commands/review-pr.md +85 -3
  38. package/commands/rollback.md +2 -0
  39. package/commands/scope.md +280 -0
  40. package/commands/security-audit.md +2 -0
  41. package/commands/status.md +262 -0
  42. package/commands/sync-ecosystem.md +2 -0
  43. package/commands/test-gate.md +929 -0
  44. package/commands/validate.md +2 -0
  45. package/commands/work-on/build/architect.md +128 -18
  46. package/commands/work-on/build/context.md +130 -17
  47. package/commands/work-on/build/implement.md +7 -3
  48. package/commands/work-on/build/validate.md +2 -0
  49. package/commands/work-on/build.md +32 -7
  50. package/commands/work-on/close.md +85 -0
  51. package/commands/work-on/decompose.md +2 -0
  52. package/commands/work-on/investigate.md +30 -3
  53. package/commands/work-on/review.md +13 -1
  54. package/commands/work-on-monolithic.md +2 -0
  55. package/commands/work-on.md +676 -38
  56. package/docs/BRAND.md +51 -0
  57. package/docs/CI.md +177 -0
  58. package/docs/CONFIG.md +94 -0
  59. package/docs/FORGE-PROTOCOL.md +324 -0
  60. package/docs/articles/b-vs-c-baseline.md +210 -0
  61. package/docs/articles/full-abc-benchmark.md +205 -0
  62. package/docs/articles/per-repo-adaptive-scripts-token-savings.md +174 -0
  63. package/docs/articles/selective-spec-loading-token-savings.md +140 -0
  64. package/docs/claude-breakpoints.json +47 -0
  65. package/docs/design/abc-benchmark.md +195 -0
  66. package/docs/design/design-architect-rationale.md +123 -0
  67. package/docs/design/design-memory.md +61 -0
  68. package/docs/design/design-spec-schema.md +248 -0
  69. package/docs/design/design-system-lint.md +150 -0
  70. package/docs/design/divergent-generation.md +106 -0
  71. package/docs/design/effects-appropriateness.md +133 -0
  72. package/docs/design/fixtures/briefs/README.md +47 -0
  73. package/docs/design/fixtures/briefs/cadence.md +39 -0
  74. package/docs/design/fixtures/briefs/plume.md +39 -0
  75. package/docs/design/fixtures/briefs/slipstream.md +39 -0
  76. package/docs/design/fixtures/briefs/tender.md +39 -0
  77. package/docs/design/fixtures/briefs/voltage.md +39 -0
  78. package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-1.html +364 -0
  79. package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-2.html +420 -0
  80. package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-3.html +506 -0
  81. package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-1.html +611 -0
  82. package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-2.html +594 -0
  83. package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-3.html +817 -0
  84. package/docs/design/fixtures/runs/b-vs-c-baseline/runs.json +175 -0
  85. package/docs/design/fixtures/runs/b-vs-c-baseline/scorecard.json +138 -0
  86. package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-1.html +373 -0
  87. package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-2.html +398 -0
  88. package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-3.html +595 -0
  89. package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-1.html +531 -0
  90. package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-2.html +565 -0
  91. package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-3.html +674 -0
  92. package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-1.html +388 -0
  93. package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-2.html +463 -0
  94. package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-3.html +568 -0
  95. package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-1.html +562 -0
  96. package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-2.html +618 -0
  97. package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-3.html +618 -0
  98. package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-1.html +364 -0
  99. package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-2.html +420 -0
  100. package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-3.html +506 -0
  101. package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-1.html +527 -0
  102. package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-2.html +445 -0
  103. package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-3.html +483 -0
  104. package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-1.html +611 -0
  105. package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-2.html +594 -0
  106. package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-3.html +817 -0
  107. package/docs/design/fixtures/runs/full-abc/runs.json +190 -0
  108. package/docs/design/fixtures/runs/full-abc/scorecard.json +144 -0
  109. package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-1.html +496 -0
  110. package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-2.html +447 -0
  111. package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-3.html +564 -0
  112. package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-1.html +373 -0
  113. package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-2.html +398 -0
  114. package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-3.html +595 -0
  115. package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-1.html +622 -0
  116. package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-2.html +475 -0
  117. package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-3.html +660 -0
  118. package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-1.html +531 -0
  119. package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-2.html +565 -0
  120. package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-3.html +674 -0
  121. package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-1.html +525 -0
  122. package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-2.html +446 -0
  123. package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-3.html +463 -0
  124. package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-1.html +388 -0
  125. package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-2.html +463 -0
  126. package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-3.html +568 -0
  127. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-1.html +1068 -0
  128. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-2.html +1423 -0
  129. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-3.html +1245 -0
  130. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-1.html +305 -0
  131. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-2.html +327 -0
  132. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-3.html +428 -0
  133. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-1.html +1270 -0
  134. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-2.html +1172 -0
  135. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-3.html +1532 -0
  136. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-1.html +315 -0
  137. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-2.html +342 -0
  138. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-3.html +353 -0
  139. package/docs/design/fixtures/runs/full-abc-opus/runs.json +190 -0
  140. package/docs/design/fixtures/runs/full-abc-opus/scorecard.json +144 -0
  141. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-1.html +345 -0
  142. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-2.html +396 -0
  143. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-3.html +502 -0
  144. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-1.html +408 -0
  145. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-2.html +446 -0
  146. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-3.html +496 -0
  147. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-1.html +813 -0
  148. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-2.html +711 -0
  149. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-3.html +721 -0
  150. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-1.html +280 -0
  151. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-2.html +291 -0
  152. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-3.html +366 -0
  153. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-1.html +1010 -0
  154. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-2.html +836 -0
  155. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-3.html +930 -0
  156. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-1.html +407 -0
  157. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-2.html +396 -0
  158. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-3.html +529 -0
  159. package/docs/design/foundations/brutalist.css +294 -0
  160. package/docs/design/foundations/editorial.css +300 -0
  161. package/docs/design/foundations/minimal-luxury.css +295 -0
  162. package/docs/design/foundations/technical.css +293 -0
  163. package/docs/design/foundations/warm-photo.css +299 -0
  164. package/docs/design/reference-corpus.md +1726 -0
  165. package/docs/design/render-critique-loop.md +57 -0
  166. package/docs/site/getting-started.md +21 -0
  167. package/docs/spec-graph-schema.md +397 -0
  168. package/package.json +3 -3
  169. package/scripts/bench-scorecard.mjs +239 -0
  170. package/scripts/build-spec-graph.mjs +509 -0
  171. package/scripts/classify-lane.sh +138 -0
  172. package/scripts/design-system-lint.mjs +993 -0
  173. package/scripts/graph-query.sh +486 -0
  174. package/scripts/transition-label.sh +169 -0
  175. package/scripts/validate-pr-target.sh +30 -0
  176. package/scripts/validate-spec-graph.sh +423 -0
  177. package/templates/devdocs/README.md +72 -0
  178. package/templates/devdocs/agent/using-forgedock.md +3 -0
  179. package/templates/devdocs/agent/using-github.md +3 -0
  180. package/templates/devdocs/index.yaml +162 -0
  181. package/templates/devdocs/project/architecture.md +3 -0
  182. package/templates/devdocs/project/conventions.md +3 -0
  183. package/templates/devdocs/project/custom-instructions.md +3 -0
  184. package/templates/devdocs/project/glossary.md +3 -0
  185. package/templates/devdocs/project/stack.md +3 -0
  186. package/templates/devdocs/templates/commit-convention.md +3 -0
  187. package/templates/devdocs/templates/issue.md +3 -0
  188. package/templates/devdocs/templates/pull-request.md +3 -0
  189. package/templates/devdocs/templates/review-finding.md +3 -0
  190. package/templates/workflows/forgedock-review.yml +96 -0
@@ -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
 
@@ -0,0 +1,262 @@
1
+ ---
2
+ description: Pipeline-wide situational awareness — groups open issues by workflow state, shows active PRs, flags stale items, and reports milestone progress
3
+ argument-hint: [--repo <owner/repo> | --stale-days <N>]
4
+ ---
5
+
6
+ # /status — Pipeline Status
7
+
8
+ **Input**: $ARGUMENTS (optional: `--repo <owner/repo>`, `--stale-days <N>`)
9
+
10
+ Read-only snapshot of the ForgeDock pipeline. Shows open issues grouped by workflow label, active PRs with age, stale items, and milestone progress.
11
+
12
+ **This command is fully read-only.** It makes no label changes, posts no comments, and creates no issues.
13
+
14
+ **NEVER use plan mode (EnterPlanMode)** — it breaks execution context.
15
+
16
+ ---
17
+
18
+ ## Config Resolution
19
+
20
+ ```bash
21
+ CONFIG_FILE="${FORGE_CONFIG:-forge.yaml}"
22
+ GH_REPO=$(yq '.project.owner + "/" + .project.repo' "$CONFIG_FILE")
23
+ GH_FLAG="-R $GH_REPO"
24
+ STAGING_BRANCH=$(yq '.branches.staging' "$CONFIG_FILE")
25
+
26
+ # Optional: --repo flag overrides the default repo
27
+ if echo "$ARGUMENTS" | grep -q -- "--repo"; then
28
+ GH_REPO=$(echo "$ARGUMENTS" | sed 's/.*--repo[[:space:]]\([^[:space:]]*\).*/\1/')
29
+ GH_FLAG="-R $GH_REPO"
30
+ fi
31
+
32
+ # Optional: --stale-days flag (default: 7)
33
+ STALE_DAYS=7
34
+ if echo "$ARGUMENTS" | grep -q -- "--stale-days"; then
35
+ STALE_DAYS=$(echo "$ARGUMENTS" | sed 's/.*--stale-days[[:space:]]\([^[:space:]]*\).*/\1/')
36
+ fi
37
+
38
+ STALE_THRESHOLD=$(date -d "${STALE_DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
39
+ || date -v-${STALE_DAYS}d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
40
+ || echo "")
41
+
42
+ echo "Repo: $GH_REPO"
43
+ echo "Staging branch: $STAGING_BRANCH"
44
+ echo "Stale threshold: ${STALE_DAYS} days"
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Phase 1: Issues by Workflow State
50
+
51
+ Fetch all open issues with `workflow:*` labels. Group and count by state.
52
+
53
+ ```bash
54
+ echo ""
55
+ echo "=== Pipeline Issues — $(date +%Y-%m-%d) ==="
56
+ echo ""
57
+
58
+ # Workflow states to display (in pipeline order)
59
+ STATES="workflow:investigating workflow:building workflow:in-review workflow:ready-to-build needs-human"
60
+
61
+ for LABEL in $STATES; do
62
+ ISSUES=$(gh issue list $GH_FLAG \
63
+ --state open \
64
+ --label "$LABEL" \
65
+ --limit 50 \
66
+ --json number,title,updatedAt,assignees \
67
+ --jq '.[] | "#\(.number) \(.title[:60]) [updated: \(.updatedAt[:10])]"' \
68
+ 2>/dev/null || echo "")
69
+
70
+ COUNT=$(echo "$ISSUES" | grep -c '#' 2>/dev/null || echo 0)
71
+ [ "$COUNT" = "0" ] && [ -z "$ISSUES" ] && COUNT=0
72
+
73
+ if [ -n "$ISSUES" ] && [ "$COUNT" -gt 0 ]; then
74
+ echo "[$LABEL] ($COUNT open)"
75
+ echo "$ISSUES" | while IFS= read -r line; do
76
+ echo " $line"
77
+ done
78
+ echo ""
79
+ else
80
+ echo "[$LABEL] — none"
81
+ fi
82
+ done
83
+
84
+ # Issues with no workflow label (untracked / not yet entered pipeline)
85
+ UNTRACKED=$(gh issue list $GH_FLAG \
86
+ --state open \
87
+ --limit 20 \
88
+ --json number,title,labels,createdAt \
89
+ --jq '.[] | select(
90
+ (.labels | map(.name) | any(startswith("workflow:"))) | not
91
+ ) | "#\(.number) \(.title[:60]) [created: \(.createdAt[:10])]"' \
92
+ 2>/dev/null || echo "")
93
+
94
+ UNTRACKED_COUNT=$(echo "$UNTRACKED" | grep -c '#' 2>/dev/null || echo 0)
95
+ if [ -n "$UNTRACKED" ] && [ "$UNTRACKED_COUNT" -gt 0 ]; then
96
+ echo "[untracked] ($UNTRACKED_COUNT — not yet in pipeline)"
97
+ echo "$UNTRACKED" | while IFS= read -r line; do
98
+ echo " $line"
99
+ done
100
+ echo ""
101
+ fi
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Phase 2: Active PRs
107
+
108
+ Show open PRs targeting `staging` or any `milestone/*` branch, with age and review status.
109
+
110
+ ```bash
111
+ echo "=== Active PRs ==="
112
+ echo ""
113
+
114
+ gh pr list $GH_FLAG \
115
+ --state open \
116
+ --limit 30 \
117
+ --json number,title,headRefName,baseRefName,createdAt,reviews,isDraft \
118
+ --jq '.[] | {
119
+ number: .number,
120
+ title: .title[:55],
121
+ head: .headRefName,
122
+ base: .baseRefName,
123
+ age_days: (((now - (.createdAt | fromdateiso8601)) / 86400) | floor),
124
+ draft: .isDraft,
125
+ review_state: (
126
+ if (.reviews | length) == 0 then "no review"
127
+ elif (.reviews | map(select(.state == "APPROVED")) | length) > 0 then "APPROVED"
128
+ elif (.reviews | map(select(.state == "CHANGES_REQUESTED")) | length) > 0 then "CHANGES REQUESTED"
129
+ else "COMMENTED"
130
+ end
131
+ )
132
+ } | " PR #\(.number) \(.title) [\(.age_days)d old] [\(.review_state)]\(if .draft then " [DRAFT]" else "" end)\n → \(.head) → \(.base)"' \
133
+ 2>/dev/null || echo " (none)"
134
+
135
+ echo ""
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Phase 3: Stale Items
141
+
142
+ Flag issues and PRs with no activity in the last `$STALE_DAYS` days.
143
+
144
+ ```bash
145
+ echo "=== Stale Items (no activity > ${STALE_DAYS} days) ==="
146
+ echo ""
147
+
148
+ if [ -z "$STALE_THRESHOLD" ]; then
149
+ echo " (skipped — could not compute stale threshold on this platform)"
150
+ else
151
+ # Stale open issues with workflow labels
152
+ STALE_ISSUES=$(gh issue list $GH_FLAG \
153
+ --state open \
154
+ --limit 100 \
155
+ --json number,title,updatedAt,labels \
156
+ --jq --arg threshold "$STALE_THRESHOLD" \
157
+ '[.[] |
158
+ select(
159
+ (.updatedAt < $threshold) and
160
+ (.labels | map(.name) | any(startswith("workflow:")))
161
+ )
162
+ ] | .[] | " ISSUE #\(.number) \(.title[:55]) [last updated: \(.updatedAt[:10])] [\(.labels | map(select(.name | startswith("workflow:"))) | .[0].name // "no-workflow")]"' \
163
+ 2>/dev/null || echo "")
164
+
165
+ STALE_PRS=$(gh pr list $GH_FLAG \
166
+ --state open \
167
+ --limit 50 \
168
+ --json number,title,updatedAt \
169
+ --jq --arg threshold "$STALE_THRESHOLD" \
170
+ '[.[] | select(.updatedAt < $threshold)] |
171
+ .[] | " PR #\(.number) \(.title[:55]) [last updated: \(.updatedAt[:10])]"' \
172
+ 2>/dev/null || echo "")
173
+
174
+ if [ -z "$STALE_ISSUES" ] && [ -z "$STALE_PRS" ]; then
175
+ echo " None — pipeline is moving."
176
+ else
177
+ [ -n "$STALE_ISSUES" ] && echo "$STALE_ISSUES"
178
+ [ -n "$STALE_PRS" ] && echo "$STALE_PRS"
179
+ fi
180
+ fi
181
+
182
+ echo ""
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Phase 4: Milestone Progress
188
+
189
+ Show open milestones with open/closed issue counts and percentage complete.
190
+
191
+ ```bash
192
+ echo "=== Milestone Progress ==="
193
+ echo ""
194
+
195
+ MILESTONES=$(gh api repos/$GH_REPO/milestones \
196
+ --jq '.[] | select(.state == "open") | {
197
+ title: .title,
198
+ number: .number,
199
+ open: .open_issues,
200
+ closed: .closed_issues,
201
+ total: (.open_issues + .closed_issues),
202
+ due: (.due_on // "no due date")[:10],
203
+ pct: (if (.open_issues + .closed_issues) > 0 then
204
+ ((.closed_issues / (.open_issues + .closed_issues)) * 100) | floor
205
+ else 0 end)
206
+ } | "\(.title) [\(.pct)% done — \(.closed)/\(.total) issues] [due: \(.due)]"' \
207
+ 2>/dev/null || echo "")
208
+
209
+ if [ -z "$MILESTONES" ]; then
210
+ echo " No active milestones."
211
+ else
212
+ echo "$MILESTONES" | while IFS= read -r line; do
213
+ echo " $line"
214
+ done
215
+ fi
216
+
217
+ echo ""
218
+ ```
219
+
220
+ ---
221
+
222
+ ## Phase 5: Bottleneck Summary
223
+
224
+ Highlight states where issues are piling up or stuck.
225
+
226
+ ```bash
227
+ echo "=== Bottleneck Summary ==="
228
+ echo ""
229
+
230
+ INVESTIGATING=$(gh issue list $GH_FLAG --state open --label "workflow:investigating" --limit 100 --json number --jq '. | length' 2>/dev/null || echo 0)
231
+ BUILDING=$(gh issue list $GH_FLAG --state open --label "workflow:building" --limit 100 --json number --jq '. | length' 2>/dev/null || echo 0)
232
+ IN_REVIEW=$(gh issue list $GH_FLAG --state open --label "workflow:in-review" --limit 100 --json number --jq '. | length' 2>/dev/null || echo 0)
233
+ BLOCKED=$(gh issue list $GH_FLAG --state open --label "needs-human" --limit 100 --json number --jq '. | length' 2>/dev/null || echo 0)
234
+ READY=$(gh issue list $GH_FLAG --state open --label "workflow:ready-to-build" --limit 100 --json number --jq '. | length' 2>/dev/null || echo 0)
235
+
236
+ TOTAL_INFLIGHT=$((INVESTIGATING + BUILDING + IN_REVIEW + READY))
237
+
238
+ echo " investigating : $INVESTIGATING"
239
+ echo " ready-to-build : $READY"
240
+ echo " building : $BUILDING"
241
+ echo " in-review : $IN_REVIEW"
242
+ echo " needs-human : $BLOCKED $([ "$BLOCKED" -gt 0 ] && echo '← ACTION REQUIRED' || true)"
243
+ echo ""
244
+ echo " Total in-flight: $TOTAL_INFLIGHT"
245
+
246
+ if [ "$BLOCKED" -gt 0 ]; then
247
+ echo ""
248
+ echo " ⚠ $BLOCKED issue(s) need human attention:"
249
+ gh issue list $GH_FLAG --state open --label "needs-human" --limit 20 \
250
+ --json number,title \
251
+ --jq '.[] | " #\(.number) \(.title[:70])"' \
252
+ 2>/dev/null || true
253
+ fi
254
+
255
+ if [ "$IN_REVIEW" -gt 3 ]; then
256
+ echo ""
257
+ echo " ⚠ Review queue depth is $IN_REVIEW — consider running /review-pr or /orchestrate fast-lane"
258
+ fi
259
+
260
+ echo ""
261
+ echo "=== Status complete — $(date +%Y-%m-%d\ %H:%M:%S) ==="
262
+ ```
@@ -2,6 +2,8 @@
2
2
  description: Detect API changes, sync satellite repos, and publish releases
3
3
  argument-hint: [check | auto | status | publish | PR-number]
4
4
  ---
5
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
5
7
 
6
8
  # /sync-ecosystem — Cross-Project Sync & Publish
7
9