forgedock 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +244 -0
- package/README.md +251 -0
- package/bin/forgedock.mjs +232 -0
- package/commands/analytics.md +777 -0
- package/commands/audit-agents.md +410 -0
- package/commands/audit.md +410 -0
- package/commands/autopilot.md +432 -0
- package/commands/cleanup.md +264 -0
- package/commands/deploy-info.md +292 -0
- package/commands/failure-recon.md +375 -0
- package/commands/forge-stats.md +183 -0
- package/commands/geo-audit.md +343 -0
- package/commands/incident-response.md +384 -0
- package/commands/issue.md +506 -0
- package/commands/milestone.md +599 -0
- package/commands/orchestrate.md +1044 -0
- package/commands/pipeline-health.md +2343 -0
- package/commands/qa-sweep.md +237 -0
- package/commands/quality-gate.md +777 -0
- package/commands/review-pr-agents.md +1711 -0
- package/commands/review-pr-staging.md +325 -0
- package/commands/review-pr.md +888 -0
- package/commands/rollback.md +253 -0
- package/commands/security-audit.md +529 -0
- package/commands/sync-ecosystem.md +527 -0
- package/commands/validate.md +131 -0
- package/commands/work-on/build/architect.md +291 -0
- package/commands/work-on/build/context.md +349 -0
- package/commands/work-on/build/implement.md +280 -0
- package/commands/work-on/build/validate.md +292 -0
- package/commands/work-on/build.md +262 -0
- package/commands/work-on/close.md +350 -0
- package/commands/work-on/decompose.md +254 -0
- package/commands/work-on/investigate.md +437 -0
- package/commands/work-on/review.md +245 -0
- package/commands/work-on-monolithic.md +298 -0
- package/commands/work-on.md +1089 -0
- package/docs/CODEX.md +92 -0
- package/docs/WORKFLOW.md +104 -0
- package/package.json +45 -0
- package/scripts/verify-env-vars.sh +201 -0
- package/scripts/verify-host-headers.sh +117 -0
- package/scripts/verify-route-registration.sh +118 -0
- package/scripts/verify-sops-chain.sh +163 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Implementation agent — writes code, makes commits, posts builder comment
|
|
3
|
+
argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--branch BRANCH]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# work-on/build/implement — Implementation Subcommand
|
|
7
|
+
|
|
8
|
+
**Input**: $ARGUMENTS
|
|
9
|
+
|
|
10
|
+
**Invoked by**: `work-on.md` Step 3F, after worktree is created and context is gathered.
|
|
11
|
+
**Output**: Write code, commit(s), post `<!-- FORGE:BUILDER -->` comment, return result to caller.
|
|
12
|
+
|
|
13
|
+
**Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
|
|
14
|
+
**NEVER use plan mode (EnterPlanMode).**
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Inputs
|
|
19
|
+
|
|
20
|
+
Parse from $ARGUMENTS:
|
|
21
|
+
- `{NUMBER}` — issue number (required)
|
|
22
|
+
- `--repo {GH_REPO}` — GitHub repo (e.g. `RapierCraft/AlterLab`)
|
|
23
|
+
- `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R RapierCraft/AlterLab`)
|
|
24
|
+
- `--worktree {WORKTREE_PATH}` — absolute path to the git worktree (set by caller)
|
|
25
|
+
- `--branch {BRANCH}` — feature branch name (e.g. `feat/my-feature`)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Phase I1: Load Context from GitHub
|
|
30
|
+
|
|
31
|
+
Read the full context chain before writing a single line of code:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Issue body and labels
|
|
35
|
+
gh issue view {NUMBER} {GH_FLAG} --json number,title,body,labels
|
|
36
|
+
|
|
37
|
+
# Architect plan (primary implementation guide — read BEFORE writing any code)
|
|
38
|
+
gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
|
|
39
|
+
--jq '.[] | select(.body | contains("FORGE:ARCHITECT")) | .body'
|
|
40
|
+
|
|
41
|
+
# Investigation report
|
|
42
|
+
gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
|
|
43
|
+
--jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body'
|
|
44
|
+
|
|
45
|
+
# Builder contract
|
|
46
|
+
gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
|
|
47
|
+
--jq '.[] | select(.body | contains("FORGE:CONTRACT")) | .body'
|
|
48
|
+
|
|
49
|
+
# Context briefing (if present)
|
|
50
|
+
gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
|
|
51
|
+
--jq '.[] | select(.body | contains("FORGE:CONTEXT")) | .body'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Resume check**: If `<!-- FORGE:BUILDER -->` comment already exists, the implementation is done — EXIT and return `IMPLEMENT_RESULT: status: ALREADY_DONE` to caller.
|
|
55
|
+
|
|
56
|
+
**Primary guide**: If `<!-- FORGE:ARCHITECT -->` is present, it is the **primary implementation input**. Follow its ordered implementation list exactly — it defines which files change, in what order, and what consistency checks must pass. The investigation report and contract are secondary context.
|
|
57
|
+
|
|
58
|
+
**Fallback**: If `<!-- FORGE:ARCHITECT -->` is absent (architect step was skipped), proceed with investigation report + contract as the sole implementation guide.
|
|
59
|
+
|
|
60
|
+
Extract from architect plan (when present):
|
|
61
|
+
- Ordered implementation list (sequence of file changes to make)
|
|
62
|
+
- All affected paths (every file that must change for consistency)
|
|
63
|
+
- Consistency checks (invariants the builder must verify before committing)
|
|
64
|
+
- Risk assessment (HIGH/MEDIUM/LOW risks to watch for)
|
|
65
|
+
|
|
66
|
+
Extract from investigation report:
|
|
67
|
+
- Affected files list
|
|
68
|
+
- Root cause
|
|
69
|
+
- Recommendation
|
|
70
|
+
|
|
71
|
+
Extract from contract:
|
|
72
|
+
- Task type (Bug Fix / Feature / Refactor / Maintenance / UI/UX / Full-Stack)
|
|
73
|
+
- Deliverables table (file, change, why)
|
|
74
|
+
- Acceptance criteria
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Phase I2: Route by Task Type
|
|
79
|
+
|
|
80
|
+
| Task Type | Approach |
|
|
81
|
+
|-----------|----------|
|
|
82
|
+
| Bug Fix | Implement fix directly in worktree |
|
|
83
|
+
| Feature (backend only) | Implement directly |
|
|
84
|
+
| Feature (UI/UX) | Invoke `frontend-design` skill + visual verification |
|
|
85
|
+
| Full-Stack | Backend first, then invoke `frontend-design` skill for UI |
|
|
86
|
+
| Refactor / Maintenance | Implement directly following contract deliverables |
|
|
87
|
+
| Investigation | Spawn research agents, create GitHub issues for findings, skip to I5 |
|
|
88
|
+
|
|
89
|
+
**Investigation task special case**: Research deeply, create GitHub issues for each finding using the Pipeline Issue Template (see `commands/issue.md` § "Pipeline Issue Template"). Each issue MUST include `## Problem`, `## Affected Files`, and `## Acceptance Criteria`. Use `gh issue create {GH_FLAG}` with a fully-structured body. Post a deliverables comment listing the created issues, close the original issue, return `IMPLEMENT_RESULT: status: INVESTIGATION_COMPLETE`.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Phase I3: Implement
|
|
94
|
+
|
|
95
|
+
Work in `{WORKTREE_PATH}`. Follow the contract deliverables table exactly — implement each file change listed, in the order that resolves dependencies first.
|
|
96
|
+
|
|
97
|
+
**Implementation rules**:
|
|
98
|
+
- Read the current file before modifying it — never assume its state
|
|
99
|
+
- Read related files identified in the context briefing before touching the changed code
|
|
100
|
+
- For each acceptance criterion in the contract: implement it, then mentally verify it's met
|
|
101
|
+
- Do NOT add unrequested scope — contract out-of-scope items stay out of scope
|
|
102
|
+
- **Library callback verification**: When writing a lambda or callable that will be passed to a library/framework parameter (e.g., `prepared_statement_name_func=lambda: ""`, `key=lambda x: ...`), you MUST verify the expected calling convention BEFORE writing it. Check the library's default value for that parameter, its documentation, or its source code. A lambda with wrong arity causes `TypeError` at runtime — this is invisible to static analysis and linting. The P0 incident from PR #14391 was caused by `lambda _: ""` (1 arg) passed where SQLAlchemy expects 0 args.
|
|
103
|
+
- **Worktree-aware path derivation**: When writing shell code that derives repository paths, ALWAYS use `git rev-parse --show-toplevel` for the repo root in regular checkouts, or `git rev-parse --git-common-dir` (then `dirname`) to get the shared `.git` directory when the context may be a linked worktree. For worktree cleanup code specifically, ALWAYS use `--git-common-dir` — `--show-toplevel` returns the worktree path itself, NOT the main repo root. NEVER use `pwd`, relative paths, or `dirname` chains on `--show-toplevel` output for repo root derivation. Test path logic for both regular checkouts and linked worktrees. (Ref: review-findings #104, #105 — 4 PATH_DERIVATION defects, 15% of all review findings)
|
|
104
|
+
- **State machine completeness verification**: When implementing routing logic, state transition tables, or phase dispatch code (e.g., adding a `Skill()` call in a routing loop, adding a new phase to a state machine, creating a new subcommand file), you MUST run three checks BEFORE staging: (1) **Routing target existence** — for each `Skill("subcommand", ...)` call or file reference in routing logic, verify the target file exists at `commands/{subcommand-path}.md`; (2) **State reachability** — for each declared state or phase, verify at least one prior state or entry condition in the router routes to it; (3) **Subcommand invocation wiring** — for each `commands/work-on/*.md` file that declares its invocation condition (e.g., `Invoked by work-on.md routing loop, when X`), verify that condition is actually handled in the router. A missing target file, an unreachable state, or a declared-but-unwired subcommand will not surface until review. (Ref: review-findings #85, #116, #137 — 4 ROUTING defects, 15% of all review findings)
|
|
105
|
+
- **Migration safety checklist** *(trigger: diff includes `*.sql` files or files under a `migrations/` path)*: When any migration file is in the diff, verify ALL of the following BEFORE staging. Fix each violation inline — do not defer to review or the quality gate: (a) **Rollback file**: a corresponding down/rollback migration file exists (e.g. `0042_down_*.sql`, `rollback_*.sql`) or the migration is explicitly self-reversing (DROP of a previously-added column); (b) **NOT NULL safety**: any `ADD COLUMN ... NOT NULL` either includes a `DEFAULT` clause or is preceded by a backfill step — a NOT NULL column without DEFAULT locks the table and fails on existing rows; (c) **Constraint name consistency**: constraint names in the migration match ORM model declarations — a mismatch causes `alembic stamp` and FK introspection to silently diverge; (d) **CREATE TRIGGER idempotency**: every `CREATE TRIGGER` uses `CREATE OR REPLACE TRIGGER` or is preceded by `DROP TRIGGER IF EXISTS` — a bare `CREATE TRIGGER` fails on re-run in test and CI environments; (e) **Migration prefix uniqueness**: confirm the new file's numeric prefix does not already exist in the `infra/migrations/` tree (`ls infra/migrations/*.sql | grep -oP '^\d+' | sort | uniq -d` prints duplicates) — a duplicate prefix hard-fails the deploy gate regardless of file content. <!-- Added: forge#373 -->
|
|
106
|
+
- If you discover the contract is wrong (e.g. a file doesn't exist, a function has a different signature): STOP, post a comment on the issue explaining the discrepancy, add label `needs-human`, and EXIT
|
|
107
|
+
|
|
108
|
+
**Worktree working directory**:
|
|
109
|
+
```bash
|
|
110
|
+
cd {WORKTREE_PATH}
|
|
111
|
+
# all file reads, writes, and git operations happen here
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Phase I3.5: Env/Config Completeness Check
|
|
117
|
+
|
|
118
|
+
**Run this BEFORE Phase I4.** This phase is read-only — it scans the working changes for INFRA-class gaps that would otherwise surface as review findings. Do NOT run `git add` or `git commit` here.
|
|
119
|
+
|
|
120
|
+
**Trigger**: Run this phase whenever the diff introduces env vars, touches infra/deploy configs, or adds literal IP addresses.
|
|
121
|
+
|
|
122
|
+
### Check 1 — New env var documentation sync
|
|
123
|
+
|
|
124
|
+
Scan changed files for newly introduced env var references:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
cd {WORKTREE_PATH}
|
|
128
|
+
# Collect all env var names referenced in changed files
|
|
129
|
+
NEW_ENV_VARS=$(grep -rnE "os\.getenv\(|process\.env\." {CHANGED_FILES} 2>/dev/null \
|
|
130
|
+
| grep -oP "(os\.getenv\(['\"]|process\.env\.)(\w+)" \
|
|
131
|
+
| sed "s/os\.getenv\(['\"]//; s/process\.env\.//" \
|
|
132
|
+
| sort -u)
|
|
133
|
+
|
|
134
|
+
if [ -n "$NEW_ENV_VARS" ]; then
|
|
135
|
+
for var in $NEW_ENV_VARS; do
|
|
136
|
+
grep -q "$var" .env.example 2>/dev/null \
|
|
137
|
+
|| echo "MISSING: $var not in .env.example — add it before staging"
|
|
138
|
+
[ -f ENV_VARS.md ] \
|
|
139
|
+
&& { grep -q "$var" ENV_VARS.md \
|
|
140
|
+
|| echo "MISSING: $var not in ENV_VARS.md — add it before staging"; }
|
|
141
|
+
[ -f env_validation.py ] \
|
|
142
|
+
&& { grep -q "$var" env_validation.py \
|
|
143
|
+
|| echo "MISSING: $var not in env_validation.py — add it before staging"; }
|
|
144
|
+
done
|
|
145
|
+
fi
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**If any MISSING line is printed**: add the var to the missing location before proceeding to Phase I4. If the file doesn't exist in this repo (e.g. `ENV_VARS.md` is an AlterLab file, not a Forge file), skip that check silently.
|
|
149
|
+
|
|
150
|
+
### Check 2 — Deploy/infra restart risk
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
cd {WORKTREE_PATH}
|
|
154
|
+
INFRA_FILES=$(echo "{CHANGED_FILES}" | tr ' ' '\n' \
|
|
155
|
+
| grep -E "docker-compose.*\.yml|deploy/|infra/")
|
|
156
|
+
|
|
157
|
+
if [ -n "$INFRA_FILES" ]; then
|
|
158
|
+
echo "INFRA CHANGE DETECTED in: $INFRA_FILES"
|
|
159
|
+
# Check for restart-inducing changes
|
|
160
|
+
RESTART_LINES=$(while IFS= read -r f; do grep -n "" "$f"; done <<< "$INFRA_FILES" \
|
|
161
|
+
| grep -E "^\+.*(image:|resources:|mem_limit|cpus:|restart:|depends_on:)" \
|
|
162
|
+
| grep -v "^---" || true)
|
|
163
|
+
if [ -n "$RESTART_LINES" ]; then
|
|
164
|
+
echo "RESTART RISK: the following lines may force container restarts on next deploy:"
|
|
165
|
+
echo "$RESTART_LINES"
|
|
166
|
+
echo "ACTION: annotate your commit message with [restart: <service_name>]"
|
|
167
|
+
fi
|
|
168
|
+
fi
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**If RESTART RISK is printed**: annotate the commit message (in Phase V5) with `[restart: <service>]` so operators know to plan downtime.
|
|
172
|
+
|
|
173
|
+
### Check 3 — Hardcoded IPs and credentials
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
cd {WORKTREE_PATH}
|
|
177
|
+
# Scan for bare IPv4 literals not inside env var lookups
|
|
178
|
+
grep -rnE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" {CHANGED_FILES} 2>/dev/null \
|
|
179
|
+
| grep -vE "os\.getenv|process\.env|\.env\.example|example|placeholder|test|mock|localhost|127\.0\.0\.1|0\.0\.0\.0" \
|
|
180
|
+
&& echo "HARDCODED IP: replace with a config reference (env var or config file) before staging"
|
|
181
|
+
|
|
182
|
+
# Scan for credential-like assignments with literal values
|
|
183
|
+
grep -rnE "(api_key|secret|password|token|credential)\s*=\s*(f?['\"]|\`)[^{'\"\`]" {CHANGED_FILES} 2>/dev/null \
|
|
184
|
+
| grep -vE "os\.getenv|process\.env|example|placeholder|test|mock" \
|
|
185
|
+
&& echo "HARDCODED CREDENTIAL: replace with env var before staging"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**If HARDCODED IP or HARDCODED CREDENTIAL is printed**: replace the literal value with a config reference before proceeding to Phase I4. This is a hard blocker — do not stage hardcoded secrets or IPs.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Phase I4: Stage Changes
|
|
193
|
+
|
|
194
|
+
**Precondition**: Do NOT commit yet — the validate subcommand (validate.md) runs AFTER implement and will make the commit in Phase V5 after the gate passes. Commit will happen in validate.md Phase V5 after the gate passes.
|
|
195
|
+
|
|
196
|
+
Migration collision check (if applicable):
|
|
197
|
+
```bash
|
|
198
|
+
git fetch origin
|
|
199
|
+
git log --oneline origin/{PR_BASE}..HEAD -- {MIGRATION_PATHS}
|
|
200
|
+
```
|
|
201
|
+
If a collision is detected, post a comment and add `needs-human` label before staging.
|
|
202
|
+
|
|
203
|
+
Stage the changed files:
|
|
204
|
+
```bash
|
|
205
|
+
cd {WORKTREE_PATH}
|
|
206
|
+
git add {CHANGED_FILES}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Do NOT run `git commit` here. The commit (with conventional commit message and issue reference) is made by validate.md Phase V5 after `GATE_PASSED=true`.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Phase I5: Update Issue Body
|
|
214
|
+
|
|
215
|
+
Check off each acceptance criterion that has been implemented:
|
|
216
|
+
```bash
|
|
217
|
+
gh issue view {NUMBER} {GH_FLAG} --json body --jq '.body'
|
|
218
|
+
# Edit the body: check off completed items, add PR reference if known
|
|
219
|
+
gh issue edit {NUMBER} {GH_FLAG} --body "{UPDATED_BODY}"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Phase I6: Post FORGE:BUILDER Comment
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:BUILDER -->
|
|
228
|
+
## Implementation Complete
|
|
229
|
+
|
|
230
|
+
**Branch**: \`{BRANCH}\`
|
|
231
|
+
**Commits**: {COMMIT_SHA(S)}
|
|
232
|
+
**Files changed**: {COUNT}
|
|
233
|
+
|
|
234
|
+
### Approach
|
|
235
|
+
{One paragraph: what was built, key decisions, why this approach over alternatives}
|
|
236
|
+
|
|
237
|
+
### Changes
|
|
238
|
+
{Bulleted list of each file changed and what was done}
|
|
239
|
+
|
|
240
|
+
### Acceptance Criteria Status
|
|
241
|
+
{Checklist of each criterion from the contract, marked ✅ or ❌}
|
|
242
|
+
|
|
243
|
+
### Testing Checklist
|
|
244
|
+
- [ ] {Test scenario 1}
|
|
245
|
+
- [ ] {Test scenario 2}
|
|
246
|
+
- [ ] {Test scenario 3}
|
|
247
|
+
|
|
248
|
+
<!-- FORGE:BUILDER:COMPLETE -->"
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Output
|
|
254
|
+
|
|
255
|
+
The subcommand writes its results to GitHub (FORGE:BUILDER comment). Return structured output to the caller:
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
IMPLEMENT_RESULT:
|
|
259
|
+
status: COMPLETE | ALREADY_DONE | INVESTIGATION_COMPLETE | BLOCKED
|
|
260
|
+
branch: {BRANCH}
|
|
261
|
+
commits: [{SHA}, ...]
|
|
262
|
+
files_changed: [{file}, ...]
|
|
263
|
+
comment_url: {url of FORGE:BUILDER comment}
|
|
264
|
+
blocker: {description if status=BLOCKED}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Integration Point in work-on.md
|
|
270
|
+
|
|
271
|
+
This module runs at **Step 3F** — after worktree creation and context gathering, before validate:
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
3E → Worktree created (by router)
|
|
275
|
+
3C.5 → Context gathered (by context.md)
|
|
276
|
+
3F → [THIS MODULE] Implement — code written, staged (not committed)
|
|
277
|
+
3F.5 → Validate (by validate.md) — gate loop runs; V5 commit happens here after GATE_PASSED=true
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The validate subcommand reads the staged diff produced by this module, runs the gate, and commits only after the gate passes.
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Validation agent — quality gate loop, format/verify, proxy check, deploy check
|
|
3
|
+
argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--files FILE1 FILE2...]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# work-on/build/validate — Validation Subcommand
|
|
7
|
+
|
|
8
|
+
**Input**: $ARGUMENTS
|
|
9
|
+
|
|
10
|
+
**Invoked by**: `work-on.md` Step 3F.5, after `implement.md` has written and staged code (not committed).
|
|
11
|
+
**Output**: Return `GATE_PASSED: true/false` to caller. On failure after max iterations, post comment and set `needs-human`.
|
|
12
|
+
|
|
13
|
+
**Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
|
|
14
|
+
**NEVER use plan mode (EnterPlanMode).**
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Inputs
|
|
19
|
+
|
|
20
|
+
Parse from $ARGUMENTS:
|
|
21
|
+
- `{NUMBER}` — issue number (required)
|
|
22
|
+
- `--repo {GH_REPO}` — GitHub repo (e.g. `RapierCraft/AlterLab`)
|
|
23
|
+
- `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R RapierCraft/AlterLab`)
|
|
24
|
+
- `--worktree {WORKTREE_PATH}` — absolute path to the git worktree
|
|
25
|
+
- `--files {CHANGED_FILES}` — space-separated list of changed files (from implement result)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Skip Conditions
|
|
30
|
+
|
|
31
|
+
Skip all phases (return `GATE_PASSED: true` immediately) if:
|
|
32
|
+
- Only 1 file was changed AND it is a config or docs file with no code logic (e.g. `.md`, `.yml` with no scripts, `.env.example`)
|
|
33
|
+
|
|
34
|
+
In all other cases, the gate MUST run.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Phase V1: Quality Gate Loop
|
|
39
|
+
|
|
40
|
+
**Loop protocol** — the gate MUST pass or exhaust iterations before returning:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
iteration = 0
|
|
44
|
+
max_iterations = 3
|
|
45
|
+
|
|
46
|
+
while iteration < max_iterations:
|
|
47
|
+
iteration += 1
|
|
48
|
+
Run quality-gate agent on CHANGED_FILES
|
|
49
|
+
if result == "QUALITY GATE: PASS":
|
|
50
|
+
GATE_PASSED = true
|
|
51
|
+
break
|
|
52
|
+
else:
|
|
53
|
+
Fix each HIGH and MEDIUM finding in the code at {WORKTREE_PATH}
|
|
54
|
+
(Do NOT commit yet — fixes are staged for the next gate run)
|
|
55
|
+
|
|
56
|
+
if iteration == max_iterations AND result != PASS:
|
|
57
|
+
GATE_PASSED = false
|
|
58
|
+
→ post comment (see V1-FAIL below)
|
|
59
|
+
→ add label needs-human
|
|
60
|
+
→ return GATE_PASSED: false to caller, STOP
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Quality gate invocation**:
|
|
64
|
+
```
|
|
65
|
+
Skill("quality-gate", args="{CHANGED_FILES} --worktree {WORKTREE_PATH}")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Rules**:
|
|
69
|
+
- Re-run after EVERY fix pass — never trust that fixes resolved findings without verification
|
|
70
|
+
- Each iteration re-scans ALL changed files — fixes can introduce new issues
|
|
71
|
+
- Only HIGH and MEDIUM findings must be fixed; LOW findings are advisory only
|
|
72
|
+
|
|
73
|
+
**V1-FAIL comment** (post when gate never passes):
|
|
74
|
+
```bash
|
|
75
|
+
gh issue comment {NUMBER} {GH_FLAG} --body "## Quality Gate Failed After 3 Iterations
|
|
76
|
+
|
|
77
|
+
Quality gate findings persist after 3 fix passes. Flagging for human review.
|
|
78
|
+
|
|
79
|
+
**Files**: {CHANGED_FILES}
|
|
80
|
+
**Final findings**: {SUMMARY_OF_REMAINING_FINDINGS}
|
|
81
|
+
|
|
82
|
+
Needs human review before proceeding to commit.
|
|
83
|
+
|
|
84
|
+
<!-- FORGE:GATE_FAILED -->"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Phase V2: Format and Verify
|
|
90
|
+
|
|
91
|
+
Run after quality gate passes. Format checks are per-language:
|
|
92
|
+
|
|
93
|
+
**Python**:
|
|
94
|
+
```bash
|
|
95
|
+
cd {WORKTREE_PATH}
|
|
96
|
+
black {PYTHON_FILES}
|
|
97
|
+
isort {PYTHON_FILES}
|
|
98
|
+
python -m py_compile {PYTHON_FILES}
|
|
99
|
+
```
|
|
100
|
+
Failures in `py_compile` are BLOCKING — fix before continuing.
|
|
101
|
+
|
|
102
|
+
**TypeScript (AlterLab)**:
|
|
103
|
+
```bash
|
|
104
|
+
cd {WORKTREE_PATH}
|
|
105
|
+
prettier --write {TS_FILES}
|
|
106
|
+
tsc --noEmit
|
|
107
|
+
```
|
|
108
|
+
`tsc --noEmit` failures are BLOCKING — fix type errors before continuing.
|
|
109
|
+
|
|
110
|
+
**TypeScript (satellite repos — MCP, n8n)**:
|
|
111
|
+
```bash
|
|
112
|
+
cd {WORKTREE_PATH}
|
|
113
|
+
npm run build
|
|
114
|
+
prettier --write {TS_FILES}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Shell scripts**: Verify service interactions — read target middleware files, document what was verified in V4 summary.
|
|
118
|
+
|
|
119
|
+
**Markdown / config files**: No format step required.
|
|
120
|
+
|
|
121
|
+
If no files match a language category, skip that language's step.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Phase V3: Frontend Proxy Wiring Check
|
|
126
|
+
|
|
127
|
+
**Skip if**: No TypeScript/TSX files were changed.
|
|
128
|
+
|
|
129
|
+
Scan all changed client-side files for direct backend calls that bypass the Next.js proxy:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
grep -n "api/v1" {CHANGED_TS_FILES}
|
|
133
|
+
grep -n "localhost:" {CHANGED_TS_FILES}
|
|
134
|
+
grep -n "127.0.0.1" {CHANGED_TS_FILES}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Rule**: All client-side `fetch`, `useSWR`, `apiFetch`, and `axios` calls MUST use `/api/...` proxy routes. Direct calls to `/api/v1/...` or hardcoded host:port are BLOCKING.
|
|
138
|
+
|
|
139
|
+
If violations found:
|
|
140
|
+
1. Fix them in `{WORKTREE_PATH}`
|
|
141
|
+
2. Document fixes in V4 summary
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Phase V3.5: Database Configuration Change Advisory
|
|
146
|
+
|
|
147
|
+
**Skip if**: No changed Python files contain database engine/session/pool configuration patterns.
|
|
148
|
+
|
|
149
|
+
When changed files touch database engine configuration, flag for manual connectivity verification. Configuration bugs in `create_async_engine`, `connect_args`, or session factories are invisible to static analysis but cause immediate runtime failures.
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
cd {WORKTREE_PATH}
|
|
153
|
+
DB_CONFIG_FILES=""
|
|
154
|
+
for f in $(echo {CHANGED_FILES} | tr ' ' '\n' | grep -E '\.py$'); do
|
|
155
|
+
grep -qE "create_async_engine|AsyncSession|connect_args|pool_size|prepared_statement|engine_from_config|sessionmaker" "$f" 2>/dev/null && \
|
|
156
|
+
DB_CONFIG_FILES="$DB_CONFIG_FILES $f"
|
|
157
|
+
done
|
|
158
|
+
|
|
159
|
+
if [ -n "$DB_CONFIG_FILES" ]; then
|
|
160
|
+
echo "DB CONFIG CHANGE DETECTED in:$DB_CONFIG_FILES"
|
|
161
|
+
echo "ACTION: Verify database connectivity after deploy — changes to engine config, connect_args, or session factories can cause silent runtime failures."
|
|
162
|
+
echo "RECOMMENDED: Run a minimal connectivity test (e.g., SELECT 1) through the modified session/engine path."
|
|
163
|
+
|
|
164
|
+
# Check for lambda/callable in connect_args — the exact bug class from PR #14391
|
|
165
|
+
for f in $DB_CONFIG_FILES; do
|
|
166
|
+
grep -nE "lambda.*:.*['\"]|=lambda" "$f" 2>/dev/null | grep -iE "connect_args|prepared_statement|pool|engine" && \
|
|
167
|
+
echo "WARNING: Lambda/callable in database configuration in $f — verify callback signature matches library's expected calling convention"
|
|
168
|
+
done
|
|
169
|
+
fi
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**This is advisory only** — it does not block the build. The output is included in the V5 summary to alert reviewers and deployers. This check exists because PR #14391 passed `lambda _: ""` to `prepared_statement_name_func` (which expects 0 args), breaking all worker billing. Static analysis cannot catch arity mismatches in library callbacks — the flag ensures a human verifies connectivity.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Phase V4: Deployment Completeness Check
|
|
177
|
+
|
|
178
|
+
**Skip if**: No new environment variables were introduced in the changed files.
|
|
179
|
+
|
|
180
|
+
Detect new env vars:
|
|
181
|
+
```bash
|
|
182
|
+
cd {WORKTREE_PATH}
|
|
183
|
+
git diff HEAD~1 -- {CHANGED_FILES} | grep -oP '(?<=os\.environ\[")[^"]+|(?<=os\.getenv\()["\']?[A-Z_]+' | sort -u
|
|
184
|
+
# Also check TypeScript:
|
|
185
|
+
git diff HEAD~1 -- {CHANGED_FILES} | grep -oP 'process\.env\.\K[A-Z_]+' | sort -u
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
For each new env var found, verify it is present in ALL required locations:
|
|
189
|
+
|
|
190
|
+
| Location | Required for |
|
|
191
|
+
|----------|-------------|
|
|
192
|
+
| `.env.example` | All new vars |
|
|
193
|
+
| `infra/secrets/prod.enc.yaml` (SOPS) | Production secrets |
|
|
194
|
+
| `infra/decrypt-secrets.sh` ENV_MAPPING | All vars in deploy chain |
|
|
195
|
+
| `app/env_validation.py` | API service vars |
|
|
196
|
+
| `docker-compose.prod.yml` | Vars needing explicit injection |
|
|
197
|
+
|
|
198
|
+
**Deploy chain**: SOPS → `decrypt-secrets.sh` (ENV_MAPPING) → `.env.secrets` → `merge-env-secrets.sh` → `.env.production` → docker-compose `env_file`.
|
|
199
|
+
|
|
200
|
+
If any required location is missing the var:
|
|
201
|
+
1. Add it to the missing location in `{WORKTREE_PATH}`
|
|
202
|
+
2. Document the addition in V4 summary
|
|
203
|
+
3. These additions are NOT new commits — they should be staged and committed together with any other pending fixes, or as a separate commit if clean
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Phase V5: Commit (always — after GATE_PASSED=true)
|
|
208
|
+
|
|
209
|
+
After the gate passes, commit all staged changes in a single commit. This includes:
|
|
210
|
+
- The implementation changes staged by `implement.md` Phase I4
|
|
211
|
+
- Any format, proxy, or deploy fixes applied by phases V2–V4
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cd {WORKTREE_PATH}
|
|
215
|
+
git add -u
|
|
216
|
+
git commit -m "fix({SCOPE}): {description} (#NUMBER)"
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Where `{SCOPE}` is the command or module scope from the contract (e.g. `work-on`, `quality-gate`), and `{description}` summarises the implementation. Use the commit convention from the contract:
|
|
220
|
+
- Bug Fix → `fix(`
|
|
221
|
+
- Feature → `feat(`
|
|
222
|
+
- Refactor → `refactor(`
|
|
223
|
+
|
|
224
|
+
This is the **only** commit for this build cycle. It replaces the old `git commit` that was previously in `implement.md` Phase I4. Do NOT create a separate commit for validation fixes — they are absorbed into this single commit.
|
|
225
|
+
|
|
226
|
+
### V5 Post-Commit Ancestry Audit (MANDATORY)
|
|
227
|
+
|
|
228
|
+
After committing, run the ancestry audit to detect merge commits from unrelated branches before the branch is pushed:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
cd {WORKTREE_PATH}
|
|
232
|
+
MERGE_COMMITS=$(git log --merges HEAD ^origin/{PR_BASE} 2>/dev/null)
|
|
233
|
+
if [ -n "$MERGE_COMMITS" ]; then
|
|
234
|
+
echo "ANCESTRY AUDIT FAILED: merge commits from unrelated branches detected on this branch:"
|
|
235
|
+
echo "$MERGE_COMMITS"
|
|
236
|
+
# Block push — do NOT proceed to review.md R1
|
|
237
|
+
gh issue comment {NUMBER} {GH_FLAG} --body "## Ancestry Audit Failed
|
|
238
|
+
|
|
239
|
+
Branch \`{BRANCH}\` contains merge commits from branches outside the PR base (\`{PR_BASE}\`). This is a staging contamination risk — these commits may carry code from milestone branches that has not been approved for \`{PR_BASE}\`.
|
|
240
|
+
|
|
241
|
+
**Detected merge commits**:
|
|
242
|
+
\`\`\`
|
|
243
|
+
${MERGE_COMMITS}
|
|
244
|
+
\`\`\`
|
|
245
|
+
|
|
246
|
+
Human review required before this branch can be pushed.
|
|
247
|
+
|
|
248
|
+
<!-- FORGE:ANCESTRY_FAILED -->"
|
|
249
|
+
gh issue edit {NUMBER} {GH_FLAG} --add-label "needs-human"
|
|
250
|
+
# Return GATE_PASSED: false — do not push
|
|
251
|
+
exit 1
|
|
252
|
+
fi
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
If `origin/{PR_BASE}` does not exist yet (new branch), skip this check — no contamination is possible from a non-existent base. Detect with:
|
|
256
|
+
```bash
|
|
257
|
+
git ls-remote --exit-code origin {PR_BASE} >/dev/null 2>&1 || echo "PR_BASE not on origin — skipping ancestry audit"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Output
|
|
263
|
+
|
|
264
|
+
Return structured output to the caller:
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
VALIDATE_RESULT:
|
|
268
|
+
gate_passed: true | false
|
|
269
|
+
quality_gate_iterations: {COUNT}
|
|
270
|
+
format_issues_fixed: {COUNT}
|
|
271
|
+
proxy_violations_fixed: {COUNT}
|
|
272
|
+
deploy_completeness_fixes: [{VAR_NAME: location_added}, ...]
|
|
273
|
+
commits_added: [{SHA}, ...] # from V5 if any
|
|
274
|
+
blocker: {description if gate_passed=false}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Integration Point in work-on.md
|
|
280
|
+
|
|
281
|
+
This module runs at **Step 3F.5** — after implement, before commit (3J) and PR creation (Phase 4):
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
3F → Implement (by implement.md) — code written, staged (not committed)
|
|
285
|
+
3F.5 → [THIS MODULE] Validate — gate loop, format, proxy, deploy checks
|
|
286
|
+
3G → (covered by Phase V2 above)
|
|
287
|
+
3H → (covered by Phase V3 above)
|
|
288
|
+
3I → (covered by Phase V4 above)
|
|
289
|
+
3J → V5 commit happens here after GATE_PASSED=true (single commit for implementation + any fixes)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
If `VALIDATE_RESULT: gate_passed: false`, the router adds `needs-human` label and stops — no PR is created.
|