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.
Files changed (44) hide show
  1. package/LICENSE +244 -0
  2. package/README.md +251 -0
  3. package/bin/forgedock.mjs +232 -0
  4. package/commands/analytics.md +777 -0
  5. package/commands/audit-agents.md +410 -0
  6. package/commands/audit.md +410 -0
  7. package/commands/autopilot.md +432 -0
  8. package/commands/cleanup.md +264 -0
  9. package/commands/deploy-info.md +292 -0
  10. package/commands/failure-recon.md +375 -0
  11. package/commands/forge-stats.md +183 -0
  12. package/commands/geo-audit.md +343 -0
  13. package/commands/incident-response.md +384 -0
  14. package/commands/issue.md +506 -0
  15. package/commands/milestone.md +599 -0
  16. package/commands/orchestrate.md +1044 -0
  17. package/commands/pipeline-health.md +2343 -0
  18. package/commands/qa-sweep.md +237 -0
  19. package/commands/quality-gate.md +777 -0
  20. package/commands/review-pr-agents.md +1711 -0
  21. package/commands/review-pr-staging.md +325 -0
  22. package/commands/review-pr.md +888 -0
  23. package/commands/rollback.md +253 -0
  24. package/commands/security-audit.md +529 -0
  25. package/commands/sync-ecosystem.md +527 -0
  26. package/commands/validate.md +131 -0
  27. package/commands/work-on/build/architect.md +291 -0
  28. package/commands/work-on/build/context.md +349 -0
  29. package/commands/work-on/build/implement.md +280 -0
  30. package/commands/work-on/build/validate.md +292 -0
  31. package/commands/work-on/build.md +262 -0
  32. package/commands/work-on/close.md +350 -0
  33. package/commands/work-on/decompose.md +254 -0
  34. package/commands/work-on/investigate.md +437 -0
  35. package/commands/work-on/review.md +245 -0
  36. package/commands/work-on-monolithic.md +298 -0
  37. package/commands/work-on.md +1089 -0
  38. package/docs/CODEX.md +92 -0
  39. package/docs/WORKFLOW.md +104 -0
  40. package/package.json +45 -0
  41. package/scripts/verify-env-vars.sh +201 -0
  42. package/scripts/verify-host-headers.sh +117 -0
  43. package/scripts/verify-route-registration.sh +118 -0
  44. 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.