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.
- package/README.md +54 -3
- package/bin/cross-publish.mjs +344 -0
- package/bin/forgedock.mjs +2205 -541
- package/bin/github-app-manifest.json.license +2 -0
- package/bin/hooks/session-start.mjs +4 -5
- package/bin/registry.mjs +20 -0
- package/bin/tui.mjs +172 -96
- package/commands/adopt.md +433 -0
- package/commands/analytics.md +2 -0
- package/commands/audit-agents.md +2 -0
- package/commands/audit.md +2 -0
- package/commands/autopilot.md +77 -0
- package/commands/changelog.md +354 -0
- package/commands/cleanup.md +2 -0
- package/commands/compat-audit.md +330 -0
- package/commands/deploy-info.md +6 -5
- package/commands/design-bench.md +176 -0
- package/commands/design-render-critique-loop.md +103 -0
- package/commands/design.md +259 -0
- package/commands/diagnose.md +483 -0
- package/commands/explain.md +349 -0
- package/commands/forge-stats.md +2 -0
- package/commands/forgedock-init.md +2 -0
- package/commands/geo-audit.md +2 -0
- package/commands/incident-response.md +2 -0
- package/commands/issue.md +9 -3
- package/commands/milestone.md +2 -0
- package/commands/optimize.md +411 -0
- package/commands/orchestrate.md +239 -0
- package/commands/pipeline-health.md +60 -1
- package/commands/qa-sweep.md +39 -2
- package/commands/quality-gate.md +67 -0
- package/commands/replay.md +263 -0
- package/commands/resume.md +264 -0
- package/commands/review-pr-agents.md +5 -1
- package/commands/review-pr-staging.md +160 -2
- package/commands/review-pr.md +85 -3
- package/commands/rollback.md +2 -0
- package/commands/scope.md +280 -0
- package/commands/security-audit.md +2 -0
- package/commands/status.md +262 -0
- package/commands/sync-ecosystem.md +2 -0
- package/commands/test-gate.md +929 -0
- package/commands/validate.md +2 -0
- package/commands/work-on/build/architect.md +128 -18
- package/commands/work-on/build/context.md +130 -17
- package/commands/work-on/build/implement.md +7 -3
- package/commands/work-on/build/validate.md +2 -0
- package/commands/work-on/build.md +32 -7
- package/commands/work-on/close.md +85 -0
- package/commands/work-on/decompose.md +2 -0
- package/commands/work-on/investigate.md +30 -3
- package/commands/work-on/review.md +13 -1
- package/commands/work-on-monolithic.md +2 -0
- package/commands/work-on.md +676 -38
- package/docs/BRAND.md +51 -0
- package/docs/CI.md +177 -0
- package/docs/CONFIG.md +94 -0
- package/docs/FORGE-PROTOCOL.md +324 -0
- package/docs/articles/b-vs-c-baseline.md +210 -0
- package/docs/articles/full-abc-benchmark.md +205 -0
- package/docs/articles/per-repo-adaptive-scripts-token-savings.md +174 -0
- package/docs/articles/selective-spec-loading-token-savings.md +140 -0
- package/docs/claude-breakpoints.json +47 -0
- package/docs/design/abc-benchmark.md +195 -0
- package/docs/design/design-architect-rationale.md +123 -0
- package/docs/design/design-memory.md +61 -0
- package/docs/design/design-spec-schema.md +248 -0
- package/docs/design/design-system-lint.md +150 -0
- package/docs/design/divergent-generation.md +106 -0
- package/docs/design/effects-appropriateness.md +133 -0
- package/docs/design/fixtures/briefs/README.md +47 -0
- package/docs/design/fixtures/briefs/cadence.md +39 -0
- package/docs/design/fixtures/briefs/plume.md +39 -0
- package/docs/design/fixtures/briefs/slipstream.md +39 -0
- package/docs/design/fixtures/briefs/tender.md +39 -0
- package/docs/design/fixtures/briefs/voltage.md +39 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-1.html +364 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-2.html +420 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-3.html +506 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-1.html +611 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-2.html +594 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-3.html +817 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/runs.json +175 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/scorecard.json +138 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-1.html +373 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-2.html +398 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-3.html +595 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-1.html +531 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-2.html +565 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-3.html +674 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-1.html +388 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-2.html +463 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-3.html +568 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-1.html +562 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-2.html +618 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-3.html +618 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-1.html +364 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-2.html +420 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-3.html +506 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-1.html +527 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-2.html +445 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-3.html +483 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-1.html +611 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-2.html +594 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-3.html +817 -0
- package/docs/design/fixtures/runs/full-abc/runs.json +190 -0
- package/docs/design/fixtures/runs/full-abc/scorecard.json +144 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-1.html +496 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-2.html +447 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-3.html +564 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-1.html +373 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-2.html +398 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-3.html +595 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-1.html +622 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-2.html +475 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-3.html +660 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-1.html +531 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-2.html +565 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-3.html +674 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-1.html +525 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-2.html +446 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-3.html +463 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-1.html +388 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-2.html +463 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-3.html +568 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-1.html +1068 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-2.html +1423 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-3.html +1245 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-1.html +305 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-2.html +327 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-3.html +428 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-1.html +1270 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-2.html +1172 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-3.html +1532 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-1.html +315 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-2.html +342 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-3.html +353 -0
- package/docs/design/fixtures/runs/full-abc-opus/runs.json +190 -0
- package/docs/design/fixtures/runs/full-abc-opus/scorecard.json +144 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-1.html +345 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-2.html +396 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-3.html +502 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-1.html +408 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-2.html +446 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-3.html +496 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-1.html +813 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-2.html +711 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-3.html +721 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-1.html +280 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-2.html +291 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-3.html +366 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-1.html +1010 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-2.html +836 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-3.html +930 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-1.html +407 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-2.html +396 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-3.html +529 -0
- package/docs/design/foundations/brutalist.css +294 -0
- package/docs/design/foundations/editorial.css +300 -0
- package/docs/design/foundations/minimal-luxury.css +295 -0
- package/docs/design/foundations/technical.css +293 -0
- package/docs/design/foundations/warm-photo.css +299 -0
- package/docs/design/reference-corpus.md +1726 -0
- package/docs/design/render-critique-loop.md +57 -0
- package/docs/site/getting-started.md +21 -0
- package/docs/spec-graph-schema.md +397 -0
- package/package.json +3 -3
- package/scripts/bench-scorecard.mjs +239 -0
- package/scripts/build-spec-graph.mjs +509 -0
- package/scripts/classify-lane.sh +138 -0
- package/scripts/design-system-lint.mjs +993 -0
- package/scripts/graph-query.sh +486 -0
- package/scripts/transition-label.sh +169 -0
- package/scripts/validate-pr-target.sh +30 -0
- package/scripts/validate-spec-graph.sh +423 -0
- package/templates/devdocs/README.md +72 -0
- package/templates/devdocs/agent/using-forgedock.md +3 -0
- package/templates/devdocs/agent/using-github.md +3 -0
- package/templates/devdocs/index.yaml +162 -0
- package/templates/devdocs/project/architecture.md +3 -0
- package/templates/devdocs/project/conventions.md +3 -0
- package/templates/devdocs/project/custom-instructions.md +3 -0
- package/templates/devdocs/project/glossary.md +3 -0
- package/templates/devdocs/project/stack.md +3 -0
- package/templates/devdocs/templates/commit-convention.md +3 -0
- package/templates/devdocs/templates/issue.md +3 -0
- package/templates/devdocs/templates/pull-request.md +3 -0
- package/templates/devdocs/templates/review-finding.md +3 -0
- 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
|
|