forgedock 1.0.5 → 1.0.7

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 (42) hide show
  1. package/README.md +7 -1
  2. package/bin/forgedock.mjs +496 -364
  3. package/bin/labels.json +152 -0
  4. package/commands/audit-agents.md +4 -2
  5. package/commands/autopilot.md +19 -11
  6. package/commands/cleanup.md +27 -12
  7. package/commands/deploy-info.md +36 -17
  8. package/commands/incident-response.md +15 -10
  9. package/commands/issue.md +8 -6
  10. package/commands/milestone.md +97 -48
  11. package/commands/orchestrate.md +109 -65
  12. package/commands/pipeline-health.md +8 -1
  13. package/commands/qa-sweep.md +14 -3
  14. package/commands/review-pr-agents.md +1 -1
  15. package/commands/review-pr-staging.md +129 -23
  16. package/commands/review-pr.md +237 -90
  17. package/commands/rollback.md +26 -7
  18. package/commands/security-audit.md +27 -25
  19. package/commands/sync-ecosystem.md +2 -2
  20. package/commands/work-on/build/architect.md +154 -2
  21. package/commands/work-on/build/context.md +131 -3
  22. package/commands/work-on/build/validate.md +32 -13
  23. package/commands/work-on/decompose.md +2 -0
  24. package/commands/work-on-monolithic.md +9 -5
  25. package/commands/work-on.md +67 -23
  26. package/docs/CONFIG.md +117 -0
  27. package/package.json +2 -1
  28. package/scripts/verify-route-registration.sh +36 -15
  29. package/scripts/verify-sops-chain.sh +18 -0
  30. package/templates/devdocs/README.md +96 -0
  31. package/templates/devdocs/agent/using-forgedock.md +245 -0
  32. package/templates/devdocs/agent/using-github.md +325 -0
  33. package/templates/devdocs/project/architecture.md +122 -0
  34. package/templates/devdocs/project/conventions.md +158 -0
  35. package/templates/devdocs/project/custom-instructions.md +73 -0
  36. package/templates/devdocs/project/glossary.md +84 -0
  37. package/templates/devdocs/project/stack.md +80 -0
  38. package/templates/devdocs/templates/commit-convention.md +147 -0
  39. package/templates/devdocs/templates/issue.md +141 -0
  40. package/templates/devdocs/templates/pull-request.md +115 -0
  41. package/templates/devdocs/templates/review-finding.md +147 -0
  42. package/bin/github-app-manifest.json +0 -24
@@ -7,7 +7,7 @@ argument-hint: [--repo <prefix>] [--phase 1|2|3|4|all] [--dry-run]
7
7
 
8
8
  **Input**: $ARGUMENTS
9
9
 
10
- You are the security posture auditor. Run a scripted 4-phase checklist against the **current state** of the target repository (not a PR diff). Each check uses bash/grep against repo files. Confirmed findings are posted as GitHub issues in the target repo, labeled `security,audit-finding,P1/P2/P3`.
10
+ You are the security posture auditor. Run a scripted 4-phase checklist against the **current state** of the target repository (not a PR diff). Each check uses bash/grep against repo files. Confirmed findings are posted as GitHub issues in the target repo, labeled `security,audit-finding,priority:P1/priority:P2/priority:P3`.
11
11
 
12
12
  This command is designed to be run:
13
13
  - **Manually** after a pen test engagement
@@ -119,7 +119,7 @@ done
119
119
 
120
120
  **Confirm**: For each hit, verify the port is NOT a web-facing port (80, 443, 8080, 3000). Ports like 6432 (PgBouncer), 6379 (Redis), 5432 (Postgres), 27017 (MongoDB) bound to `0.0.0.0` are confirmed findings.
121
121
 
122
- **Severity**: P1 if no external firewall documented; P2 otherwise.
122
+ **Severity**: `priority:P1` if no external firewall documented; `priority:P2` otherwise.
123
123
 
124
124
  **Issue title**: `security: {SERVICE} port {PORT} bound to 0.0.0.0 — exposed beyond localhost`
125
125
 
@@ -142,7 +142,7 @@ done
142
142
 
143
143
  **Confirm**: Check if the Dockerfile is for a long-running service (not a one-shot build image). If service container with no USER → confirmed finding.
144
144
 
145
- **Severity**: P2 (standard finding; exploitability depends on runtime isolation).
145
+ **Severity**: `priority:P2` (standard finding; exploitability depends on runtime isolation).
146
146
 
147
147
  **Issue title**: `security: {SERVICE} Dockerfile has no USER directive — runs as root`
148
148
 
@@ -167,7 +167,7 @@ done
167
167
 
168
168
  **Manual review**: Check for `POSTGRES_PASSWORD` and `requirepass` in compose environment sections. Flag any service using a blank/trivial password as a documented value.
169
169
 
170
- **Severity**: P3 for dev compose; P1 if the compose file is used in production.
170
+ **Severity**: `priority:P3` for dev compose; `priority:P1` if the compose file is used in production.
171
171
 
172
172
  **Issue title**: `security: {SERVICE} in {FILE} has no authentication configured`
173
173
 
@@ -198,7 +198,7 @@ done
198
198
 
199
199
  **Confirm**: Verify the flagged step is indeed a security scanner step (not a notification or deploy step). Confirmed if scanner produces failure exit codes that are being swallowed.
200
200
 
201
- **Severity**: P2 (scanner present but findings are silently ignored).
201
+ **Severity**: `priority:P2` (scanner present but findings are silently ignored).
202
202
 
203
203
  **Issue title**: `security: {SCANNER} step in {WORKFLOW} has continue-on-error: true — findings silently ignored`
204
204
 
@@ -219,7 +219,7 @@ done
219
219
 
220
220
  **Confirm**: Distinguish intentional comments (documentation) from disabled access control rules. Confirmed if the commented line is a functional directive that would restrict access.
221
221
 
222
- **Severity**: P1 if the endpoint is publicly accessible; P2 otherwise.
222
+ **Severity**: `priority:P1` if the endpoint is publicly accessible; `priority:P2` otherwise.
223
223
 
224
224
  **Issue title**: `security: commented-out access control in {FILE} — {DIRECTIVE} disabled`
225
225
 
@@ -242,7 +242,7 @@ done
242
242
 
243
243
  **Confirm**: Verify the CSP header applies to the production site (not just dev/storybook). Check if a nonce-based approach is already in use (nonce + unsafe-inline is still a finding but lower severity).
244
244
 
245
- **Severity**: P2 (XSS protection materially weakened).
245
+ **Severity**: `priority:P2` (XSS protection materially weakened).
246
246
 
247
247
  **Issue title**: `security: CSP script-src includes unsafe-inline in {FILE} — XSS protection bypassed`
248
248
 
@@ -261,9 +261,9 @@ for f in $HEADER_FILES; do
261
261
  done
262
262
  ```
263
263
 
264
- **Confirm**: Check if the header is set in a response (not just read). If set in outbound responses → confirmed finding. Internal-only APIs (not publicly routed) are P3; public APIs are P2.
264
+ **Confirm**: Check if the header is set in a response (not just read). If set in outbound responses → confirmed finding. Internal-only APIs (not publicly routed) are `priority:P3`; public APIs are `priority:P2`.
265
265
 
266
- **Severity**: P2 for public APIs; P3 for internal.
266
+ **Severity**: `priority:P2` for public APIs; `priority:P3` for internal.
267
267
 
268
268
  **Issue title**: `security: {HEADER} response header leaks deployment/version information`
269
269
 
@@ -291,7 +291,7 @@ grep -rn '@router.get\("/health"\|@app.route("/health"\|@router.get\("/metrics"\
291
291
 
292
292
  **Confirm**: Manually verify the route has no authentication dependency. Check if it's behind a network-level gate (traefik middleware, nginx ACL). Confirmed if publicly routable and returns system state.
293
293
 
294
- **Severity**: P2 (information disclosure enables targeted attacks).
294
+ **Severity**: `priority:P2` (information disclosure enables targeted attacks).
295
295
 
296
296
  **Issue title**: `security: unauthenticated {ROUTE} endpoint exposes system state`
297
297
 
@@ -326,7 +326,7 @@ grep -rn "new Map\(\)" "$REPO_PATH/web" --include="*.ts" --include="*.tsx" --inc
326
326
 
327
327
  **Confirm**: Verify the rate limiter is not backed by Redis, a database, or a distributed cache. Confirmed if per-process store with no TTL-based external backend.
328
328
 
329
- **Severity**: P2 (rate limit bypass possible in scaled deployments).
329
+ **Severity**: `priority:P2` (rate limit bypass possible in scaled deployments).
330
330
 
331
331
  **Issue title**: `security: in-memory rate limiter in {FILE} has no cross-replica enforcement`
332
332
 
@@ -363,9 +363,9 @@ grep -rn "document\.cookie\s*=\|res\.cookie(" "$REPO_PATH/web" --include="*.ts"
363
363
  done
364
364
  ```
365
365
 
366
- **Confirm**: Verify the cookie stores user-controlled data or authentication state. Internal-only cookies (debug flags, feature flags with no sensitive data) are P3. Auth/session cookies without flags are P1.
366
+ **Confirm**: Verify the cookie stores user-controlled data or authentication state. Internal-only cookies (debug flags, feature flags with no sensitive data) are `priority:P3`. Auth/session cookies without flags are `priority:P1`.
367
367
 
368
- **Severity**: P1 for auth/session tokens; P2 for user-controlled data; P3 for non-sensitive cookies.
368
+ **Severity**: `priority:P1` for auth/session tokens; `priority:P2` for user-controlled data; `priority:P3` for non-sensitive cookies.
369
369
 
370
370
  **Issue title**: `security: {COOKIE_NAME} cookie missing {FLAGS} — vulnerable to XSS/CSRF/MITM`
371
371
 
@@ -395,7 +395,7 @@ grep -rn '||\s*["'"'"'][a-zA-Z0-9]\{4,\}["'"'"']\|default.*password\|default.*se
395
395
 
396
396
  **Confirm**: Verify the fallback value is a real credential (not a placeholder like `""` or `"REPLACE_ME"` which would fail explicitly). Confirmed if a non-trivial value would silently succeed authentication.
397
397
 
398
- **Severity**: P1 if the credential protects a production service; P2 otherwise.
398
+ **Severity**: `priority:P1` if the credential protects a production service; `priority:P2` otherwise.
399
399
 
400
400
  **Issue title**: `security: credential placeholder fallback in {FILE} — {VAR} defaults to hardcoded value`
401
401
 
@@ -445,7 +445,7 @@ done
445
445
 
446
446
  **Confirm**: Verify the event type appears in a handler dispatch (not just a comment). Confirmed if the event would change user entitlements or financial state but has no handler.
447
447
 
448
- **Severity**: P1 for events that affect billing state (subscription.deleted, payment_failed, dispute); P2 for informational events.
448
+ **Severity**: `priority:P1` for events that affect billing state (subscription.deleted, payment_failed, dispute); `priority:P2` for informational events.
449
449
 
450
450
  **Issue title**: `security: Stripe event {EVENT_TYPE} not handled in {FILE} — financial state may diverge`
451
451
 
@@ -466,7 +466,7 @@ grep -rn "pre_reserve\|prereserve\|reserve_credits\|MAX_COST\|max_cost\|PRE_RESE
466
466
 
467
467
  **Manual review required**: Compare the pre-reserve amount against the maximum operation cost for the highest-tier model. If pre-reserve < max possible cost, users can overdraw.
468
468
 
469
- **Severity**: P2 (financial loss; users can consume credits they don't have).
469
+ **Severity**: `priority:P2` (financial loss; users can consume credits they don't have).
470
470
 
471
471
  **Issue title**: `security: pre-reservation credit cap {AMOUNT} is below maximum operation cost {MAX_COST}`
472
472
 
@@ -483,8 +483,8 @@ After all phases complete, produce a summary table:
483
483
 
484
484
  | # | Phase | Finding | File | Severity | Status |
485
485
  |---|-------|---------|------|----------|--------|
486
- | 1 | 1A | Port binding | docker-compose.prod.yml:12 | P1 | CONFIRMED |
487
- | 2 | 1B | No USER directive | services/worker/Dockerfile | P2 | CONFIRMED |
486
+ | 1 | 1A | Port binding | docker-compose.prod.yml:12 | priority:P1 | CONFIRMED |
487
+ | 2 | 1B | No USER directive | services/worker/Dockerfile | priority:P2 | CONFIRMED |
488
488
  ...
489
489
  ```
490
490
 
@@ -492,12 +492,14 @@ If `--dry-run` was passed, print the table and STOP. Do not create issues.
492
492
 
493
493
  ### 5B: Ensure labels exist in target repo
494
494
 
495
- Before creating any issues, ensure all required labels exist:
495
+ Before creating any issues, ensure all required labels exist. Colors match the canonical ForgeDock label manifest (`bin/labels.json`). Run `npx forgedock labels setup` to bootstrap all managed labels at once.
496
496
 
497
497
  ```bash
498
- for label in "security" "audit-finding" "P1" "P2" "P3"; do
499
- gh label create "$label" --color "d73a4a" --force -R "{GH_REPO}" 2>/dev/null || true
500
- done
498
+ gh label create "security" --color "B60205" --description "Security vulnerability or hardening. Managed by ForgeDock." --force -R "{GH_REPO}" 2>/dev/null || true
499
+ gh label create "audit-finding" --color "D93F0B" --description "Security or compliance defect found during audit. Managed by ForgeDock." --force -R "{GH_REPO}" 2>/dev/null || true
500
+ gh label create "priority:P1" --color "D93F0B" --description "High priority — major feature broken, no workaround. Managed by ForgeDock." --force -R "{GH_REPO}" 2>/dev/null || true
501
+ gh label create "priority:P2" --color "FBCA04" --description "Medium priority — impaired functionality, workaround exists. Managed by ForgeDock." --force -R "{GH_REPO}" 2>/dev/null || true
502
+ gh label create "priority:P3" --color "C2E0C6" --description "Low priority — minor issue or polish. Managed by ForgeDock." --force -R "{GH_REPO}" 2>/dev/null || true
501
503
  ```
502
504
 
503
505
  ### 5C: Create GitHub issues for CONFIRMED findings
@@ -559,9 +561,9 @@ gh issue comment "{CALLER_ISSUE}" -R {FORGE_REPO} --body "$(cat <<'COMMENT_EOF'
559
561
 
560
562
  | Severity | Count |
561
563
  |----------|-------|
562
- | P1 | {P1_COUNT} |
563
- | P2 | {P2_COUNT} |
564
- | P3 | {P3_COUNT} |
564
+ | priority:P1 | {P1_COUNT} |
565
+ | priority:P2 | {P2_COUNT} |
566
+ | priority:P3 | {P3_COUNT} |
565
567
 
566
568
  ### Issues Created
567
569
 
@@ -217,7 +217,7 @@ Create issues in the affected repos:
217
217
  # For satellite repos (separate GitHub repos):
218
218
  gh issue create -R {TARGET_REPO} \
219
219
  --title "feat(sync): {description of what API change needs to be reflected}" \
220
- --label "feature,P2" \
220
+ --label "feature,priority:P2" \
221
221
  --body "$(cat <<'BODY_EOF'
222
222
  ## Problem
223
223
 
@@ -254,7 +254,7 @@ BODY_EOF
254
254
  # For monorepo issues (SDKs, packages inside a single repo):
255
255
  gh issue create \
256
256
  --title "feat(sync): {description of what API change needs to be reflected}" \
257
- --label "feature,P2" \
257
+ --label "feature,priority:P2" \
258
258
  --body "$(cat <<'BODY_EOF'
259
259
  ## Problem
260
260
 
@@ -65,6 +65,134 @@ gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
65
65
 
66
66
  ---
67
67
 
68
+ ## Phase A0: Read Custom Instructions and Project Conventions
69
+
70
+ Read project-resident authoritative docs **before** any code path tracing. `project/custom-instructions.md` has the highest precedence of all knowledge sources — its directives are BINDING and override agent defaults, training knowledge, and all other context. Other applicable `project/*.md` files provide authoritative project conventions the architect must enforce.
71
+
72
+ **Time budget**: 30 seconds. If exceeded, log a skip note and continue to Phase A1.
73
+
74
+ **Skip if**: `{REPO_PATH}` is not set, devdocs path does not exist, or path contains no markdown files.
75
+
76
+ ### Step 0: Resolve devdocs path
77
+
78
+ Read `forge.yaml → devdocs.path` from the project root. Default to `devdocs` if the key is absent or unreadable.
79
+
80
+ ```bash
81
+ DEVDOCS_PATH=""
82
+
83
+ FORGE_YAML_PATH="{REPO_PATH}/forge.yaml"
84
+
85
+ if [ -f "$FORGE_YAML_PATH" ]; then
86
+ DEVDOCS_REL=$(grep -A5 '^devdocs:' "$FORGE_YAML_PATH" \
87
+ | grep '^\s*path:' \
88
+ | head -1 \
89
+ | sed 's/.*path:\s*//' \
90
+ | tr -d '"'"'"' \
91
+ | tr -d '[:space:]')
92
+ fi
93
+
94
+ DEVDOCS_REL="${DEVDOCS_REL:-devdocs}"
95
+ DEVDOCS_PATH="{REPO_PATH}/${DEVDOCS_REL}"
96
+
97
+ if [ ! -d "$DEVDOCS_PATH" ]; then
98
+ echo "Devdocs path '${DEVDOCS_PATH}' does not exist — skipping Phase A0 (no blocking)"
99
+ DEVDOCS_PATH=""
100
+ fi
101
+ ```
102
+
103
+ > **Note**: `devdocs/` must be tracked in git for the worktree to contain it. If the project gitignores `devdocs/`, the path will not exist in the worktree and this phase silently skips — this is by design. Run `git check-ignore -v devdocs/` to confirm tracking status.
104
+
105
+ ### Step 1: Priority read — custom instructions (HIGHEST PRECEDENCE)
106
+
107
+ Always read `project/custom-instructions.md` first if it exists. Directives in this file are BINDING — they override everything else.
108
+
109
+ ```bash
110
+ CUSTOM_INSTRUCTIONS=""
111
+
112
+ if [ -n "$DEVDOCS_PATH" ]; then
113
+ CUSTOM_INSTRUCTIONS_FILE="${DEVDOCS_PATH}/project/custom-instructions.md"
114
+ if [ -f "$CUSTOM_INSTRUCTIONS_FILE" ]; then
115
+ TOTAL_LINES=$(wc -l < "$CUSTOM_INSTRUCTIONS_FILE" 2>/dev/null || echo 0)
116
+ if [ "$TOTAL_LINES" -gt 200 ]; then
117
+ CUSTOM_INSTRUCTIONS=$(head -200 "$CUSTOM_INSTRUCTIONS_FILE")
118
+ CUSTOM_INSTRUCTIONS="${CUSTOM_INSTRUCTIONS}
119
+
120
+ _[Truncated at 200 lines — ${TOTAL_LINES} total. Read full file for complete directives.]_"
121
+ else
122
+ CUSTOM_INSTRUCTIONS=$(cat "$CUSTOM_INSTRUCTIONS_FILE")
123
+ fi
124
+ fi
125
+ fi
126
+ ```
127
+
128
+ ### Step 2: Secondary reads — other applicable project files
129
+
130
+ Read all other `*.md` files under `DEVDOCS_PATH` where `applies_to` contains `work-on`. Skip `project/custom-instructions.md` (already read). Sort by authority (`required` first).
131
+
132
+ ```bash
133
+ PROJECT_CONVENTIONS=""
134
+
135
+ if [ -n "$DEVDOCS_PATH" ]; then
136
+ APPLICABLE_FILES=""
137
+
138
+ while IFS= read -r -d '' mdfile; do
139
+ # Skip custom-instructions — already read as priority
140
+ [ "$mdfile" = "${DEVDOCS_PATH}/project/custom-instructions.md" ] && continue
141
+
142
+ FRONTMATTER=$(awk '/^---/{c++; if(c==1){next} if(c==2){exit}} c==1{print}' "$mdfile" 2>/dev/null)
143
+
144
+ if echo "$FRONTMATTER" | grep -q 'applies_to:.*work-on'; then
145
+ AUTHORITY=$(echo "$FRONTMATTER" | grep 'authority:' | head -1 | sed 's/.*authority:\s*//' | tr -d ' ')
146
+ case "$AUTHORITY" in
147
+ required) SORT_KEY="1" ;;
148
+ recommended) SORT_KEY="2" ;;
149
+ *) SORT_KEY="3" ;;
150
+ esac
151
+ APPLICABLE_FILES="${APPLICABLE_FILES}${SORT_KEY}|${mdfile}\n"
152
+ fi
153
+ done < <(find "$DEVDOCS_PATH" -name "*.md" -print0 2>/dev/null)
154
+
155
+ APPLICABLE_FILES=$(printf "$APPLICABLE_FILES" | sort | cut -d'|' -f2-)
156
+
157
+ while IFS= read -r mdfile; do
158
+ [ -z "$mdfile" ] && continue
159
+ TOTAL_LINES=$(wc -l < "$mdfile" 2>/dev/null || echo 0)
160
+ if [ "$TOTAL_LINES" -gt 200 ]; then
161
+ FILE_CONTENT=$(head -200 "$mdfile")
162
+ TRUNCATION_NOTE="_[Truncated at 200 lines — ${TOTAL_LINES} total.]_"
163
+ else
164
+ FILE_CONTENT=$(cat "$mdfile")
165
+ TRUNCATION_NOTE=""
166
+ fi
167
+
168
+ REL_PATH="${mdfile#${DEVDOCS_PATH}/}"
169
+ PROJECT_CONVENTIONS="${PROJECT_CONVENTIONS}
170
+
171
+ #### \`${REL_PATH}\`
172
+ ${FILE_CONTENT}
173
+ ${TRUNCATION_NOTE}"
174
+ done <<< "$APPLICABLE_FILES"
175
+ fi
176
+ ```
177
+
178
+ ### Step 3: Precedence rules to enforce
179
+
180
+ When `CUSTOM_INSTRUCTIONS` or `PROJECT_CONVENTIONS` is non-empty, the architect MUST apply them throughout the plan. The precedence order is:
181
+
182
+ ```
183
+ project/custom-instructions.md ← HIGHEST PRIORITY (binding directives)
184
+ ↑
185
+ other project/*.md ← Authoritative project conventions
186
+ agent/*.md ← ForgeDock/GitHub usage instructions
187
+ agent memory ← Recalled knowledge
188
+ agent defaults ← Built-in behaviors
189
+ ↓ LOWEST PRIORITY
190
+ ```
191
+
192
+ `CUSTOM_INSTRUCTIONS` and `PROJECT_CONVENTIONS` are used in the `### Custom Instructions (HIGHEST PRECEDENCE)` and `### Project Conventions` sections of the FORGE:ARCHITECT output. If both are empty (devdocs path absent), these sections are replaced with skip notes.
193
+
194
+ ---
195
+
68
196
  ## Phase A1: Read Entry Points
69
197
 
70
198
  Identify every entry point that initiates the affected logic. Start from the files named in the investigation report.
@@ -226,6 +354,20 @@ Post the following as a GitHub comment on `{NUMBER}`:
226
354
  gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:ARCHITECT -->
227
355
  ## Implementation Plan for #{NUMBER}
228
356
 
357
+ ### Custom Instructions (HIGHEST PRECEDENCE)
358
+ <!-- Binding directives from project/custom-instructions.md (Phase A0).
359
+ These override agent defaults, training knowledge, and all other context.
360
+ Builder MUST follow these exactly — violations are elevated to HIGH severity in review.
361
+ If devdocs path was absent or file not found: 'No custom-instructions.md found at
362
+ {DEVDOCS_PATH}/project/custom-instructions.md — skipping. Run `npx forgedock docs init`.' -->
363
+ {CUSTOM_INSTRUCTIONS}
364
+
365
+ ### Project Conventions
366
+ <!-- Authoritative project knowledge from project/*.md and agent/*.md files
367
+ with applies_to: work-on (Phase A0). Read these before finalizing the plan.
368
+ If devdocs path was absent or no applicable files found: 'No applicable devdocs found.' -->
369
+ {PROJECT_CONVENTIONS}
370
+
229
371
  ### Affected Paths (ALL must be updated)
230
372
  | # | File | Function/Class | Change Required | Why |
231
373
  |---|------|----------------|-----------------|-----|
@@ -259,9 +401,10 @@ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:ARCHITECT -->
259
401
 
260
402
  ## Timing Rules
261
403
 
262
- - Each file read: skip if the file exceeds 500 lines and only the first 100 lines are needed for structure
404
+ - Phase A0 devdocs read: 30s total budget (path resolution + file enumeration + content reads); skip if exceeded
405
+ - Each file read (A1): skip if the file exceeds 500 lines and only the first 100 lines are needed for structure
263
406
  - Each `grep -r` call: timeout after 10s, skip if exceeded
264
- - Total wall time budget: **3 minutes**. If budget exceeded, post partial results with `<!-- FORGE:ARCHITECT:PARTIAL -->` marker instead of `COMPLETE`.
407
+ - Total wall time budget: **3 minutes** (A0 through A5 combined). If budget exceeded, post partial results with `<!-- FORGE:ARCHITECT:PARTIAL -->` marker instead of `COMPLETE`.
265
408
 
266
409
  ---
267
410
 
@@ -285,7 +428,16 @@ This module runs at **Step 3C.6** — after Context Gathering, before Implement:
285
428
  3C → Builder Contract posted
286
429
  3C.5 → Context Gathering (FORGE:CONTEXT comment)
287
430
  3C.6 → [THIS MODULE] Architecture Planning (FORGE:ARCHITECT comment)
431
+ Phase A0: Read Custom Instructions and Project Conventions (highest precedence)
432
+ Phase A1: Read Entry Points
433
+ Phase A2: Trace the Data Flow
434
+ Phase A2.5: Pipeline Phase-Dependency Check
435
+ Phase A3: Consistency Rules
436
+ Phase A4: Sequence the Implementation
437
+ Phase A5: Risk Assessment
288
438
  3F → Implement (builder reads plan, implements ALL affected paths)
289
439
  ```
290
440
 
291
441
  The builder agent reads the `<!-- FORGE:ARCHITECT -->` comment as its **primary input** before writing any code. The raw issue body is secondary context. If the architect step was skipped, the builder falls back to investigation report + contract.
442
+
443
+ **Devdocs precedence** (Phase A0): `project/custom-instructions.md` has ABSOLUTE priority over all other context. The architect's plan must reflect any directives in that file — if custom instructions mandate a specific pattern, the implementation order and approach MUST follow it, even if the architect's general reasoning suggests an alternative. <!-- Added: forge#259 -->
@@ -33,6 +33,117 @@ Parse from `$ARGUMENTS`:
33
33
 
34
34
  ---
35
35
 
36
+ ## Phase C-1: Authoritative Devdocs
37
+
38
+ Read project-resident authoritative docs **before** any institutional-memory queries. Devdocs contain binding project knowledge (conventions, architecture, custom instructions) that must inform the builder's mental model from the start.
39
+
40
+ **Time budget**: 30 seconds. If exceeded, log a skip note and continue to Phase C0.
41
+
42
+ **Skip if**: `{REPO_PATH}` is not set, devdocs path does not exist, or path contains no markdown files.
43
+
44
+ ### Step 0: Resolve devdocs path
45
+
46
+ Read `forge.yaml → devdocs.path` from the project root. Default to `devdocs` if the key is absent or unreadable.
47
+
48
+ ```bash
49
+ DEVDOCS_PATH=""
50
+
51
+ # Read forge.yaml directly from repo root (REPO_PATH points to the project root — no directory walk)
52
+ FORGE_YAML_PATH="{REPO_PATH}/forge.yaml"
53
+
54
+ if [ -f "$FORGE_YAML_PATH" ]; then
55
+ # Extract devdocs.path key (simple grep — value is on the same or next line under "devdocs:")
56
+ DEVDOCS_REL=$(grep -A5 '^devdocs:' "$FORGE_YAML_PATH" \
57
+ | grep '^\s*path:' \
58
+ | head -1 \
59
+ | sed 's/.*path:\s*//' \
60
+ | tr -d '"'"'"' \
61
+ | tr -d '[:space:]')
62
+ fi
63
+
64
+ # Default to "devdocs" if not found
65
+ DEVDOCS_REL="${DEVDOCS_REL:-devdocs}"
66
+ DEVDOCS_PATH="{REPO_PATH}/${DEVDOCS_REL}"
67
+
68
+ if [ ! -d "$DEVDOCS_PATH" ]; then
69
+ echo "Devdocs path '${DEVDOCS_PATH}' does not exist — skipping Phase C-1 (no blocking)"
70
+ DEVDOCS_PATH=""
71
+ fi
72
+ ```
73
+
74
+ > **Note**: `devdocs/` must be tracked in git for the worktree to contain it. If the project gitignores `devdocs/`, the path will not exist in the worktree and this phase silently skips — this is by design. Run `git check-ignore -v devdocs/` to confirm tracking status.
75
+
76
+ ### Step 1: Enumerate and filter applicable files
77
+
78
+ Find all `.md` files under `DEVDOCS_PATH`, parse YAML frontmatter, keep those with `work-on` in `applies_to`. Sort by authority (`required` first, then `recommended`, then `reference`).
79
+
80
+ ```bash
81
+ DEVDOCS_APPLICABLE="" # list of paths that apply
82
+
83
+ if [ -n "$DEVDOCS_PATH" ]; then
84
+ # Find all markdown files recursively
85
+ while IFS= read -r -d '' mdfile; do
86
+ # Extract frontmatter block (between first two --- markers)
87
+ FRONTMATTER=$(awk '/^---/{c++; if(c==1){next} if(c==2){exit}} c==1{print}' "$mdfile" 2>/dev/null)
88
+
89
+ # Check if applies_to contains work-on
90
+ if echo "$FRONTMATTER" | grep -q 'applies_to:.*work-on'; then
91
+ AUTHORITY=$(echo "$FRONTMATTER" | grep 'authority:' | head -1 | sed 's/.*authority:\s*//' | tr -d ' ')
92
+ # Prepend sort key: 1=required, 2=recommended, 3=reference, 4=other
93
+ case "$AUTHORITY" in
94
+ required) SORT_KEY="1" ;;
95
+ recommended) SORT_KEY="2" ;;
96
+ reference) SORT_KEY="3" ;;
97
+ *) SORT_KEY="4" ;;
98
+ esac
99
+ DEVDOCS_APPLICABLE="${DEVDOCS_APPLICABLE}${SORT_KEY}|${mdfile}\n"
100
+ fi
101
+ done < <(find "$DEVDOCS_PATH" -name "*.md" -print0 2>/dev/null)
102
+
103
+ # Sort by authority key and extract paths
104
+ DEVDOCS_APPLICABLE=$(printf "$DEVDOCS_APPLICABLE" | sort | cut -d'|' -f2-)
105
+ fi
106
+
107
+ if [ -z "$DEVDOCS_APPLICABLE" ]; then
108
+ echo "No devdocs files with 'applies_to: work-on' found — skipping Phase C-1 content read"
109
+ fi
110
+ ```
111
+
112
+ ### Step 2: Read content of applicable files
113
+
114
+ For each applicable file: read its content (max 200 lines; truncate with note if longer). Accumulate for output.
115
+
116
+ ```bash
117
+ DEVDOCS_CONTENT=""
118
+
119
+ while IFS= read -r mdfile; do
120
+ [ -z "$mdfile" ] && continue
121
+ TOTAL_LINES=$(wc -l < "$mdfile" 2>/dev/null || echo 0)
122
+ if [ "$TOTAL_LINES" -gt 200 ]; then
123
+ FILE_CONTENT=$(head -200 "$mdfile")
124
+ TRUNCATION_NOTE="_[Truncated at 200 lines — ${TOTAL_LINES} total. Read full file for complete context.]_"
125
+ else
126
+ FILE_CONTENT=$(cat "$mdfile")
127
+ TRUNCATION_NOTE=""
128
+ fi
129
+
130
+ # Relative path for display
131
+ REL_PATH="${mdfile#${DEVDOCS_PATH}/}"
132
+
133
+ DEVDOCS_CONTENT="${DEVDOCS_CONTENT}
134
+
135
+ #### \`${REL_PATH}\`
136
+ ${FILE_CONTENT}
137
+ ${TRUNCATION_NOTE}"
138
+ done <<< "$DEVDOCS_APPLICABLE"
139
+ ```
140
+
141
+ ### Step 3: Store for output
142
+
143
+ `DEVDOCS_CONTENT` is used in the `### Authoritative Devdocs` section of the FORGE:CONTEXT comment output. If empty (path absent or no applicable files), the section is replaced with a skip note.
144
+
145
+ ---
146
+
36
147
  ## Phase C0: Prior Investigation Findings (from Gists)
37
148
 
38
149
  Scan the issue body for `<!-- FORGE:PRIOR_GIST: {url} -->` annotations embedded by the decompose or orchestrate phases (GIST-02). Also check for `<!-- FORGE:MILESTONE_INDEX: {url} -->` annotations — these reference a milestone-level index Gist (GIST-04) that aggregates all investigation Gist URLs for a milestone into a single reference. Both annotation types reference Knowledge Gists created during upstream investigation (GIST-01) and contain structured findings — verdict, root cause, recommendation, affected files — that the builder needs before writing code.
@@ -278,6 +389,14 @@ Post the following as a GitHub comment on `{NUMBER}`:
278
389
  gh issue comment {NUMBER} -R {GH_REPO} --body "<!-- FORGE:CONTEXT -->
279
390
  ## Implementation Context for #{NUMBER}
280
391
 
392
+ ### Authoritative Devdocs
393
+ <!-- Project-resident authoritative knowledge read from devdocs/ (Phase C-1).
394
+ These files have the highest precedence — they override agent defaults and memory.
395
+ custom-instructions.md directives are BINDING and MUST be followed exactly.
396
+ If devdocs path was absent or no files matched applies_to: work-on — write:
397
+ 'No devdocs found at {DEVDOCS_PATH} — skipping. Run `npx forgedock docs init` to scaffold.' -->
398
+ {DEVDOCS_CONTENT}
399
+
281
400
  ### Prior Investigation Findings
282
401
  <!-- Summarized Knowledge Gist content from upstream investigations (Phase C0).
283
402
  If no FORGE:PRIOR_GIST annotations were found in the issue body: omit this section entirely.
@@ -317,11 +436,12 @@ gh issue comment {NUMBER} -R {GH_REPO} --body "<!-- FORGE:CONTEXT -->
317
436
 
318
437
  ## Timing Rules
319
438
 
439
+ - Phase C-1 devdocs read: 30s total budget (file enumeration + content reads combined); skip if exceeded
320
440
  - Phase C0 `gh gist view` calls: timeout after 15s each, 30s total budget for all Gist fetches
321
441
  - Each `gh issue list` call: timeout after 20s, skip if exceeded
322
442
  - Each `gh pr list` call: timeout after 20s, skip if exceeded
323
443
  - Each `grep -r` call: timeout after 10s, skip if exceeded
324
- - Total wall time budget: **2 minutes** (C0 through C4 combined). If budget exceeded, post partial results with `<!-- FORGE:CONTEXT:PARTIAL -->` marker instead of `COMPLETE`.
444
+ - Total wall time budget: **2 minutes** (C-1 through C4 combined). If budget exceeded, post partial results with `<!-- FORGE:CONTEXT:PARTIAL -->` marker instead of `COMPLETE`.
325
445
 
326
446
  ---
327
447
 
@@ -339,11 +459,19 @@ Skip this entire step (post nothing, return empty briefing) if:
339
459
  This module runs at **Step 3C.5** — after Builder Contract is posted, before Implement:
340
460
 
341
461
  ```
342
- 3C → Builder Contract posted
462
+ 3C → Builder Contract posted
343
463
  3C.5 → [THIS MODULE] Context gathering (max 2 min)
344
- 3F → Implement (builder now has context briefing)
464
+ Phase C-1: Authoritative Devdocs (project-resident knowledge — highest precedence)
465
+ Phase C0: Prior Investigation Findings (from Gists)
466
+ Phase C1: Past Review Findings on These Files
467
+ Phase C2: Past Bugs in the Same Module
468
+ Phase C3: Related Code Paths
469
+ Phase C4: Successful Similar Implementations
470
+ 3F → Implement (builder now has context briefing)
345
471
  ```
346
472
 
347
473
  The builder agent reads the `<!-- FORGE:CONTEXT -->` comment before writing any code. If the context step was skipped, the builder proceeds with investigation report + contract only.
348
474
 
475
+ **Devdocs precedence** (Phase C-1): Content from `project/custom-instructions.md` has the HIGHEST precedence of all context sources. Directives there override agent defaults, training knowledge, and all other devdocs. Other `project/*.md` and `agent/*.md` files with `applies_to: work-on` provide authoritative project conventions and ForgeDock usage guidance. <!-- Added: forge#259 -->
476
+
349
477
  When prior investigation Gists are available (Phase C0), the `### Prior Investigation Findings` section gives the builder cross-issue context — root causes, recommendations, and affected files from upstream investigations — without requiring manual Gist lookups. When a milestone-level index Gist exists (GIST-04), Phase C0 can resolve the index to discover all investigation Gists for the milestone from a single URL — providing full milestone-wide context automatically. <!-- Updated: forge#341 -->
@@ -88,31 +88,50 @@ Needs human review before proceeding to commit.
88
88
 
89
89
  ## Phase V2: Format and Verify
90
90
 
91
- Run after quality gate passes. Format checks are per-language:
91
+ Run after quality gate passes. All tool commands are read from `forge.yaml → verification.commands`; each step logs `SKIPPED — not configured` when the corresponding key is absent rather than silently passing:
92
92
 
93
93
  **Python**:
94
94
  ```bash
95
95
  cd {WORKTREE_PATH}
96
- black {PYTHON_FILES}
97
- isort {PYTHON_FILES}
96
+
97
+ PYTHON_FORMAT=$(awk '/^ commands:/{f=1;next} f && /^[^ \t]/{exit} f' forge.yaml 2>/dev/null | awk '/^ python:/{f=1;next} f && /^ [^ \t]/{exit} f' | grep 'format:' | head -1 | sed "s/.*format: *['\"]//;s/['\"].*//")
98
+ if [ -n "$PYTHON_FORMAT" ]; then
99
+ eval "$PYTHON_FORMAT" 2>&1
100
+ else
101
+ echo "SKIPPED — python.format not configured in verification.commands"
102
+ fi
103
+
104
+ # Compile check always runs for Python files (no config needed — catches syntax errors)
98
105
  python -m py_compile {PYTHON_FILES}
99
106
  ```
100
107
  Failures in `py_compile` are BLOCKING — fix before continuing.
101
108
 
102
- **TypeScript (tsc)**:
109
+ **TypeScript**:
103
110
  ```bash
104
111
  cd {WORKTREE_PATH}
105
- prettier --write {TS_FILES}
106
- tsc --noEmit
107
- ```
108
- `tsc --noEmit` failures are BLOCKING — fix type errors before continuing.
109
112
 
110
- **TypeScript (satellite repos — MCP, n8n)**:
111
- ```bash
112
- cd {WORKTREE_PATH}
113
- npm run build
114
- prettier --write {TS_FILES}
113
+ TS_FORMAT=$(awk '/^ commands:/{f=1;next} f && /^[^ \t]/{exit} f' forge.yaml 2>/dev/null | awk '/^ typescript:/{f=1;next} f && /^ [^ \t]/{exit} f' | grep 'format:' | head -1 | sed "s/.*format: *['\"]//;s/['\"].*//")
114
+ TS_TYPECHECK=$(awk '/^ commands:/{f=1;next} f && /^[^ \t]/{exit} f' forge.yaml 2>/dev/null | awk '/^ typescript:/{f=1;next} f && /^ [^ \t]/{exit} f' | grep 'typecheck:' | head -1 | sed "s/.*typecheck: *['\"]//;s/['\"].*//")
115
+ TS_BUILD=$(awk '/^ commands:/{f=1;next} f && /^[^ \t]/{exit} f' forge.yaml 2>/dev/null | awk '/^ typescript:/{f=1;next} f && /^ [^ \t]/{exit} f' | grep 'build:' | head -1 | sed "s/.*build: *['\"]//;s/['\"].*//")
116
+
117
+ if [ -n "$TS_FORMAT" ]; then
118
+ eval "$TS_FORMAT" 2>&1
119
+ else
120
+ echo "SKIPPED — typescript.format not configured in verification.commands"
121
+ fi
122
+
123
+ if [ -n "$TS_TYPECHECK" ]; then
124
+ eval "$TS_TYPECHECK" 2>&1
125
+ TS_EXIT=$?
126
+ elif [ -n "$TS_BUILD" ]; then
127
+ eval "$TS_BUILD" 2>&1 | tail -30
128
+ TS_EXIT=$?
129
+ else
130
+ echo "SKIPPED — typescript.typecheck and typescript.build not configured in verification.commands"
131
+ TS_EXIT=0
132
+ fi
115
133
  ```
134
+ Typecheck or build failures are BLOCKING — fix type errors before continuing.
116
135
 
117
136
  **Shell scripts**: Verify service interactions — read target middleware files, document what was verified in V4 summary.
118
137
 
@@ -40,6 +40,8 @@ gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
40
40
  - If FORGE:INVESTIGATOR comment is absent → EXIT with `DECOMPOSE_RESULT: status: BLOCKED`, blocker: "No investigation report found — run investigate first"
41
41
  - If investigation report has no Decomposition Assessment section, OR the assessment does not list any sub-issues → EXIT with `DECOMPOSE_RESULT: status: BLOCKED`, blocker: "Investigation report has no decomposition plan — re-run investigate with explicit decomposition scope"
42
42
 
43
+ > **Shared Scoping Convention**: This investigation gate (blocks without a `FORGE:INVESTIGATOR` comment) is the **reference pattern** for investigation-gated issue creation across the pipeline. `milestone.md` Step 4 and `orchestrate.md` MUST apply the same principle: read code and identify all affected call sites BEFORE writing any issue body. Sub-issue bodies created in Phase D3 MUST use the Pipeline Issue Template defined in `issue.md` Phase 3D — that template is the single canonical standard for all automated issue creation. <!-- Added: forge#293 -->
44
+
43
45
  Extract from investigation report:
44
46
  - Decomposition Assessment section: list of proposed sub-issues with titles and dependencies
45
47
  - Milestone (from issue metadata)
@@ -89,16 +89,20 @@ Mission: Validate whether the issue is real. Assume description is wrong until p
89
89
 
90
90
  **Domain file hints** (start search here):
91
91
 
92
- | Domain | Key files |
93
- |--------|-----------|
94
- | BILLING | `routers/billing.py`, `core/pricing.py`, `services/credit_service.py` |
95
- | SCRAPING | `unified_consumer.py`, `queues.py`, `domain_playbooks.json` |
92
+ Configure domain-to-file mappings for your project in `forge.yaml → review.key_paths`. The table below shows the standard layout — override any entry that doesn't match your codebase:
93
+
94
+ | Domain | Default key files (override via forge.yaml) |
95
+ |--------|---------------------------------------------|
96
+ | BILLING | `routers/billing.py`, `core/pricing.py`, `services/payment_service.py` |
97
+ | WORKER | `worker/main.py`, `worker/queues.py`, `worker/tasks.py` |
96
98
  | AUTH | `core/auth.py`, `routers/auth.py`, `dependencies.py` |
97
99
  | DATABASE | `infra/migrations/`, `models/`, `db/` |
98
100
  | FRONTEND | `web/src/app/`, `web/src/components/`, `web/src/lib/` |
99
- | CORTEX | `cortex_client.py`, `routers/cortex.py` |
101
+ | AI | `services/ai_client.py`, `routers/ai.py` |
100
102
  | INFRA | `.github/workflows/`, `docker-compose.yml`, `infra/traefik/` |
101
103
 
104
+ If `forge.yaml → review.key_paths` is present, use those mappings instead of the defaults above.
105
+
102
106
  **Steps**: Check right branch → read domain files → verify claims → git blame → determine root cause → identify affected files → validate proposed fixes against full system stack.
103
107
 
104
108
  **Fix-Approach Validation**: If issue proposes a fix, don't adopt it as spec. Trace through target system's middleware, auth, routing.