forgedock 1.0.0 → 1.0.2

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 +19 -2
  2. package/bin/forgedock.mjs +286 -10
  3. package/commands/analytics.md +129 -52
  4. package/commands/audit-agents.md +29 -5
  5. package/commands/audit.md +55 -17
  6. package/commands/autopilot.md +11 -6
  7. package/commands/cleanup.md +44 -24
  8. package/commands/deploy-info.md +7 -3
  9. package/commands/forge-stats.md +13 -4
  10. package/commands/forgedock-init.md +534 -0
  11. package/commands/geo-audit.md +114 -26
  12. package/commands/incident-response.md +4 -1
  13. package/commands/issue.md +26 -25
  14. package/commands/milestone.md +80 -59
  15. package/commands/orchestrate.md +38 -21
  16. package/commands/pipeline-health.md +26 -15
  17. package/commands/qa-sweep.md +68 -5
  18. package/commands/quality-gate.md +18 -0
  19. package/commands/review-pr-agents.md +58 -90
  20. package/commands/review-pr.md +58 -16
  21. package/commands/rollback.md +8 -5
  22. package/commands/security-audit.md +68 -12
  23. package/commands/sync-ecosystem.md +196 -156
  24. package/commands/validate.md +1 -1
  25. package/commands/work-on/build/architect.md +2 -2
  26. package/commands/work-on/build/context.md +2 -2
  27. package/commands/work-on/build/implement.md +3 -3
  28. package/commands/work-on/build/validate.md +3 -3
  29. package/commands/work-on/build.md +6 -6
  30. package/commands/work-on/close.md +59 -30
  31. package/commands/work-on/decompose.md +6 -6
  32. package/commands/work-on/investigate.md +16 -20
  33. package/commands/work-on/review.md +4 -4
  34. package/commands/work-on-monolithic.md +15 -16
  35. package/commands/work-on.md +45 -33
  36. package/docs/CODEX.md +1 -1
  37. package/docs/CONFIG.md +398 -0
  38. package/docs/WORKFLOW.md +115 -72
  39. package/package.json +2 -2
  40. package/scripts/verify-host-headers.sh +14 -9
  41. package/scripts/verify-route-registration.sh +10 -10
  42. package/commands/failure-recon.md +0 -375
@@ -0,0 +1,534 @@
1
+ ---
2
+ description: AI-powered forge.yaml config generator — scans codebase, queries GitHub, fills all optional sections interactively
3
+ argument-hint: [--force | --section <name>]
4
+ ---
5
+
6
+ # /forgedock-init — AI-Powered Config Generator
7
+
8
+ **Input**: $ARGUMENTS
9
+
10
+ You complete the `forge.yaml` configuration that `npx forgedock init` started. The CLI generates required sections (project, paths, branches) from auto-detection. Your job is to scan the codebase, query GitHub APIs, ask targeted clarifying questions, and produce a complete `forge.yaml` with every applicable optional section filled.
11
+
12
+ **Agent model policy**: Default `model: "sonnet"`. Fallback: `model: "opus"` if Sonnet is rate-limited.
13
+ **NEVER use plan mode (EnterPlanMode).**
14
+
15
+ ---
16
+
17
+ ## Argument Parsing
18
+
19
+ | Flag | Effect |
20
+ |------|--------|
21
+ | (none) | Fill all optional sections not yet configured |
22
+ | `--force` | Overwrite ALL optional sections without asking |
23
+ | `--section <name>` | Fill only one section: `repos`, `project_board`, `services`, `review`, or `verification` |
24
+
25
+ Parse `$ARGUMENTS` and set:
26
+ ```
27
+ FORCE = true if --force present
28
+ TARGET_SECTION = value from --section <name>, or "all"
29
+ ```
30
+
31
+ If `--section` was provided, validate the value immediately:
32
+
33
+ ```bash
34
+ ALLOWED_SECTIONS="repos project_board services review verification"
35
+ if [ "$TARGET_SECTION" != "all" ]; then
36
+ VALID=false
37
+ for s in $ALLOWED_SECTIONS; do
38
+ [ "$TARGET_SECTION" = "$s" ] && VALID=true && break
39
+ done
40
+ if [ "$VALID" = "false" ]; then
41
+ echo "Error: '$TARGET_SECTION' is not a valid section name."
42
+ echo ""
43
+ echo "Valid sections: repos, project_board, services, review, verification"
44
+ echo ""
45
+ echo "Usage: /forgedock-init --section <name>"
46
+ exit 1
47
+ fi
48
+ fi
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Phase 1: Load forge.yaml
54
+
55
+ ### 1A: Locate and read
56
+
57
+ ```bash
58
+ FORGE_YAML="$(pwd)/forge.yaml"
59
+ if [ ! -f "$FORGE_YAML" ]; then
60
+ echo "forge.yaml not found in current directory."
61
+ echo ""
62
+ echo "Run first: npx forgedock init"
63
+ echo ""
64
+ echo "This generates the required skeleton (project, paths, branches)."
65
+ echo "Then re-run /forgedock-init to complete the optional sections."
66
+ exit 1
67
+ fi
68
+ cat "$FORGE_YAML"
69
+ ```
70
+
71
+ ### 1B: Extract required section values
72
+
73
+ Parse these from the existing file — they are needed for all subsequent queries:
74
+
75
+ ```
76
+ OWNER = project.owner
77
+ REPO = project.repo
78
+ REPO_ROOT = paths.root
79
+ ```
80
+
81
+ After extracting these values, validate that OWNER and REPO are non-empty and do not contain placeholder values before proceeding:
82
+
83
+ ```bash
84
+ if [ -z "$OWNER" ] || [ "$OWNER" = "your-github-org" ]; then
85
+ echo "Error: project.owner is not set in forge.yaml."
86
+ echo ""
87
+ echo "Open forge.yaml and fill in the 'project:' section:"
88
+ echo " project:"
89
+ echo " owner: \"your-actual-github-org-or-username\""
90
+ echo ""
91
+ echo "Then re-run /forgedock-init."
92
+ exit 1
93
+ fi
94
+
95
+ if [ -z "$REPO" ] || [ "$REPO" = "your-repo-name" ]; then
96
+ echo "Error: project.repo is not set in forge.yaml."
97
+ echo ""
98
+ echo "Open forge.yaml and fill in the 'project:' section:"
99
+ echo " project:"
100
+ echo " repo: \"your-actual-repo-name\""
101
+ echo ""
102
+ echo "Then re-run /forgedock-init."
103
+ exit 1
104
+ fi
105
+ ```
106
+
107
+ ### 1C: Detect already-configured optional sections
108
+
109
+ For each optional section, check if it has an UNCOMMENTED entry in the file. A commented-out section (all lines starting with `#`) is NOT configured.
110
+
111
+ ```bash
112
+ # Check which optional sections are already active (uncommented)
113
+ grep -q "^repos:" "$FORGE_YAML" && HAS_REPOS=true || HAS_REPOS=false
114
+ grep -q "^project_board:" "$FORGE_YAML" && HAS_PROJECT_BOARD=true || HAS_PROJECT_BOARD=false
115
+ grep -q "^services:" "$FORGE_YAML" && HAS_SERVICES=true || HAS_SERVICES=false
116
+ grep -q "^review:" "$FORGE_YAML" && HAS_REVIEW=true || HAS_REVIEW=false
117
+ grep -q "^verification:" "$FORGE_YAML" && HAS_VERIFICATION=true || HAS_VERIFICATION=false
118
+ ```
119
+
120
+ If `FORCE=false` and a section is already active, skip it (unless `--section` targets it explicitly). Tell the user which sections were skipped and why.
121
+
122
+ ---
123
+
124
+ ## Phase 2: Codebase Scan
125
+
126
+ Run these scans unconditionally — they populate defaults that reduce the number of clarifying questions needed.
127
+
128
+ ### 2A: Tech stack detection
129
+
130
+ ```bash
131
+ # Node.js / TypeScript
132
+ [ -f "$REPO_ROOT/package.json" ] && \
133
+ cat "$REPO_ROOT/package.json" | grep -E '"name"|"dependencies"|"devDependencies"' | head -30
134
+
135
+ # Python
136
+ [ -f "$REPO_ROOT/pyproject.toml" ] && grep -E "^\[project\]|^name|^requires-python|^dependencies" "$REPO_ROOT/pyproject.toml" | head -20
137
+ [ -f "$REPO_ROOT/requirements.txt" ] && head -20 "$REPO_ROOT/requirements.txt"
138
+
139
+ # Rust
140
+ [ -f "$REPO_ROOT/Cargo.toml" ] && grep -E "^\[package\]|^name|^edition|^\[dependencies\]" "$REPO_ROOT/Cargo.toml" | head -20
141
+
142
+ # Ruby
143
+ [ -f "$REPO_ROOT/Gemfile" ] && head -15 "$REPO_ROOT/Gemfile"
144
+
145
+ # Go
146
+ [ -f "$REPO_ROOT/go.mod" ] && head -10 "$REPO_ROOT/go.mod"
147
+ ```
148
+
149
+ Build `TECH_STACK` description from findings (e.g., "Next.js 15, FastAPI, PostgreSQL").
150
+
151
+ ### 2B: Project context
152
+
153
+ ```bash
154
+ # CLAUDE.md — primary context source
155
+ [ -f "$REPO_ROOT/CLAUDE.md" ] && cat "$REPO_ROOT/CLAUDE.md"
156
+
157
+ # README.md — fallback
158
+ [ -f "$REPO_ROOT/README.md" ] && head -60 "$REPO_ROOT/README.md"
159
+ ```
160
+
161
+ Extract a 2–4 sentence project description for `review.context`.
162
+
163
+ ### 2C: Docker / service names
164
+
165
+ ```bash
166
+ # Container name prefixes for verification section
167
+ ls "$REPO_ROOT"/docker-compose*.yml 2>/dev/null
168
+ for f in "$REPO_ROOT"/docker-compose*.yml; do
169
+ [ -f "$f" ] || continue
170
+ grep -E "^\s+container_name:|^\s+image:" "$f" | head -20
171
+ done
172
+ ```
173
+
174
+ Extract container name prefixes (e.g., `acme-`, `my-app-`) for `verification.internal_service_patterns` and `verification.services`.
175
+
176
+ ### 2D: Branch topology
177
+
178
+ ```bash
179
+ # Staging branch detection
180
+ git -C "$REPO_ROOT" branch -r | grep -E "staging|develop|dev" | head -5
181
+
182
+ # CI/CD target branches
183
+ grep -rh "branches:" "$REPO_ROOT/.github/workflows/"*.yml 2>/dev/null | head -20
184
+ ```
185
+
186
+ Use to confirm or suggest `branches.staging`.
187
+
188
+ ### 2E: API health endpoint hints
189
+
190
+ ```bash
191
+ # Look for health route definitions
192
+ grep -rn "health\|/ping\|/status" "$REPO_ROOT" --include="*.py" --include="*.ts" --include="*.go" -l 2>/dev/null | head -10
193
+ grep -rn "healthcheck\|health_endpoint\|HEALTH_URL" "$REPO_ROOT" --include="*.yml" --include="*.yaml" -l 2>/dev/null | head -5
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Phase 3: GitHub Queries
199
+
200
+ Run these to gather live IDs. Failures are non-blocking — skip the section if the query fails.
201
+
202
+ ### 3A: Check GitHub auth
203
+
204
+ ```bash
205
+ gh auth status 2>&1
206
+ ```
207
+
208
+ If not authenticated, skip all GitHub queries and note which sections will need manual completion.
209
+
210
+ ### 3B: Project board discovery
211
+
212
+ ```bash
213
+ # List projects owned by this org/user
214
+ gh project list --owner "$OWNER" --format json 2>/dev/null \
215
+ | jq '.projects[] | {number: .number, title: .title, id: .id}'
216
+ ```
217
+
218
+ If projects found: ask the user which one ForgeDock should use (or `none`). Record:
219
+ - `PROJECT_NUMBER`
220
+ - `PROJECT_ID` (the `PVT_...` node ID)
221
+
222
+ ### 3C: Project board field IDs
223
+
224
+ ```bash
225
+ # Only run if PROJECT_NUMBER is set
226
+ gh project field-list "$PROJECT_NUMBER" --owner "$OWNER" --format json 2>/dev/null \
227
+ | jq '.fields[] | {name: .name, id: .id, type: .type}'
228
+ ```
229
+
230
+ Map field names to their IDs:
231
+ - Look for fields named `Status`, `Lane`, `Component`, `Priority`, `Workflow` (case-insensitive)
232
+ - Record their `PVTSSF_...` IDs
233
+
234
+ ```bash
235
+ # Get option IDs for single-select fields
236
+ gh project field-list "$PROJECT_NUMBER" --owner "$OWNER" --format json 2>/dev/null \
237
+ | jq '.fields[] | select(.type == "SINGLE_SELECT") | {name: .name, options: [.options[] | {name: .name, id: .id}]}'
238
+ ```
239
+
240
+ Map option names to IDs for `status` (Todo/In Progress/Done), `lane` (Fast/Feature/Sync), `priority` (P0/P1/P2/P3), `workflow` (Investigating/Building/In Review/Merged).
241
+
242
+ ### 3D: Satellite repo discovery
243
+
244
+ ```bash
245
+ # List all repos under this owner
246
+ gh repo list "$OWNER" --limit 50 --json name,description,url 2>/dev/null \
247
+ | jq '.[] | select(.name != "'"$REPO"'") | {name: .name, description: .description}'
248
+ ```
249
+
250
+ Present the list and ask: "Do any of these serve as satellite repos that you'd route issues to with a prefix (e.g., `mcp:5`)?"
251
+
252
+ ---
253
+
254
+ ## Phase 4: Interactive Clarification
255
+
256
+ Ask only about items NOT already determined by Phases 2–3. Keep questions grouped by section. Use `read` or present multiple-choice.
257
+
258
+ ### 4A: repos section
259
+
260
+ Only ask if satellite repos were found in 3D:
261
+
262
+ ```
263
+ The following repos were found under {OWNER}:
264
+ - {repo_name}: {description}
265
+ (...)
266
+
267
+ Do any of these serve as satellite repos for ForgeDock routing?
268
+ If yes, enter a prefix:repo mapping (e.g., "mcp:acme-mcp-server"), or "none":
269
+ ```
270
+
271
+ ### 4B: project_board section
272
+
273
+ If project board found in 3B but field mapping is ambiguous:
274
+
275
+ ```
276
+ Found project board: "{TITLE}" (#{PROJECT_NUMBER})
277
+
278
+ Field mapping (press Enter to accept detected name, or type correct field name):
279
+ Status field → detected: "{DETECTED}" (ID: {ID})
280
+ Lane field → detected: "{DETECTED}" (ID: {ID})
281
+ ...
282
+ ```
283
+
284
+ ### 4C: services section
285
+
286
+ ```
287
+ Does your project use any of the following analytics/monitoring services?
288
+ [1] Umami (self-hosted)
289
+ [2] Microsoft Clarity
290
+ [3] Google Analytics 4
291
+ [4] None / Skip this section
292
+
293
+ Enter numbers separated by commas (e.g., "1,3"), or "4" to skip:
294
+ ```
295
+
296
+ If any selected, ask for the specific IDs/URLs required by each.
297
+
298
+ ```
299
+ Do you have an API URL for health checks? (e.g., https://api.myproject.io)
300
+ Enter URL or press Enter to skip:
301
+ ```
302
+
303
+ ### 4D: review section
304
+
305
+ ```
306
+ Detected tech stack: {TECH_STACK}
307
+
308
+ Is this accurate? Add/edit if needed, or press Enter to accept:
309
+ ```
310
+
311
+ ```
312
+ Any additional context for code reviewers? (unusual conventions, deploy setup, known pitfalls)
313
+ Press Enter to skip, or describe briefly:
314
+ ```
315
+
316
+ ### 4E: verification section
317
+
318
+ ```
319
+ Detected potential health endpoint path: {DETECTED_PATH}
320
+ Full health URL (e.g., https://api.myproject.io/health), or press Enter to skip:
321
+ ```
322
+
323
+ ```
324
+ Detected container name prefixes: {PREFIXES}
325
+ Are these correct? Add/edit prefixes, or press Enter to accept:
326
+ ```
327
+
328
+ ---
329
+
330
+ ## Phase 5: Write forge.yaml
331
+
332
+ ### 5A: Preserve required sections
333
+
334
+ Read the current `forge.yaml` content. Extract the complete `project:`, `paths:`, and `branches:` blocks verbatim — they must not change.
335
+
336
+ ### 5B: Build optional section YAML
337
+
338
+ For each optional section the user confirmed:
339
+
340
+ **repos** (if satellites confirmed):
341
+ ```yaml
342
+ repos:
343
+ default:
344
+ repo: "{OWNER}/{REPO}"
345
+ staging_branch: "{branches.staging}"
346
+ satellites:
347
+ - prefix: "{PREFIX}"
348
+ repo: "{OWNER}/{SATELLITE_REPO}"
349
+ staging_branch: "main"
350
+ local_path: "{REPO_ROOT}/../{SATELLITE_REPO}"
351
+ ```
352
+
353
+ **project_board** (if board and field IDs found):
354
+ ```yaml
355
+ project_board:
356
+ owner: "{OWNER}"
357
+ project_number: {PROJECT_NUMBER}
358
+ project_id: "{PROJECT_ID}" # Must be a PVT_... node ID — obtain via: gh project list --owner <owner> --format json | jq '.projects[] | .id'
359
+ field_ids:
360
+ status: "{STATUS_FIELD_ID}"
361
+ lane: "{LANE_FIELD_ID}"
362
+ component: "{COMPONENT_FIELD_ID}"
363
+ priority: "{PRIORITY_FIELD_ID}"
364
+ workflow: "{WORKFLOW_FIELD_ID}"
365
+ option_ids:
366
+ status:
367
+ todo: "{TODO_OPTION_ID}"
368
+ in_progress: "{IN_PROGRESS_OPTION_ID}"
369
+ done: "{DONE_OPTION_ID}"
370
+ lane:
371
+ fast: "{FAST_OPTION_ID}"
372
+ feature: "{FEATURE_OPTION_ID}"
373
+ priority:
374
+ p0: "{P0_OPTION_ID}"
375
+ p1: "{P1_OPTION_ID}"
376
+ p2: "{P2_OPTION_ID}"
377
+ p3: "{P3_OPTION_ID}"
378
+ workflow:
379
+ investigating: "{INVESTIGATING_OPTION_ID}"
380
+ building: "{BUILDING_OPTION_ID}"
381
+ in_review: "{IN_REVIEW_OPTION_ID}"
382
+ merged: "{MERGED_OPTION_ID}"
383
+ ```
384
+
385
+ **services** (if analytics/monitoring confirmed):
386
+ ```yaml
387
+ services:
388
+ domain: "{ROOT_DOMAIN}"
389
+ api_url: "{API_URL}"
390
+ analytics:
391
+ # Only include subsections the user confirmed
392
+ umami: # if selected
393
+ url: "{UMAMI_URL}"
394
+ website_id: "{UMAMI_WEBSITE_ID}"
395
+ clarity: # if selected
396
+ project_id: "{CLARITY_PROJECT_ID}"
397
+ ga4: # if selected
398
+ property_id: "{GA4_PROPERTY_ID}"
399
+ ```
400
+
401
+ **review** (if tech stack or context provided):
402
+ ```yaml
403
+ review:
404
+ tech_stack: "{TECH_STACK}"
405
+ context: |
406
+ {PROJECT_CONTEXT}
407
+ ```
408
+
409
+ **verification** (if health endpoint or containers found):
410
+ ```yaml
411
+ verification:
412
+ health_endpoint: "{HEALTH_ENDPOINT}"
413
+ health_patterns:
414
+ - '"status": "ok"'
415
+ internal_service_patterns:
416
+ - "{SERVICE_PREFIX}"
417
+ ```
418
+
419
+ ### 5C: Overwrite protection
420
+
421
+ For each optional section that is ALREADY ACTIVE in forge.yaml (detected in Phase 1C):
422
+
423
+ If `FORCE=false`:
424
+ ```
425
+ forge.yaml already has an active {section}: section.
426
+ Overwrite it with newly detected values? [y/N]
427
+ ```
428
+
429
+ If user says N: keep existing content for that section.
430
+
431
+ ### 5D: Write the file
432
+
433
+ Backup the existing file:
434
+ ```bash
435
+ cp "$FORGE_YAML" "${FORGE_YAML}.bak"
436
+ echo "Backed up: forge.yaml → forge.yaml.bak"
437
+ ```
438
+
439
+ Write the complete new file: required sections (preserved verbatim) + active optional sections (newly generated) + inactive optional sections (left as commented-out blocks matching forge.yaml.example structure).
440
+
441
+ Print a summary of what was written:
442
+ ```
443
+ forge.yaml updated:
444
+
445
+ Required sections (preserved):
446
+ ✓ project
447
+ ✓ paths
448
+ ✓ branches
449
+
450
+ Optional sections (filled):
451
+ ✓ repos — 2 satellite(s) configured
452
+ ✓ project_board — field IDs from project "Acme Board" (#1)
453
+ ✗ services — skipped (no analytics services)
454
+ ✓ review — tech stack + context
455
+ ✓ verification — health endpoint configured
456
+
457
+ Optional sections (skipped — still commented out):
458
+ - services
459
+ ```
460
+
461
+ ---
462
+
463
+ ## Phase 6: Validation
464
+
465
+ ### 6A: Repo access
466
+
467
+ ```bash
468
+ gh repo view "${OWNER}/${REPO}" --json name,url 2>/dev/null \
469
+ || echo "WARNING: Cannot access ${OWNER}/${REPO} — check project.owner and project.repo"
470
+ ```
471
+
472
+ ### 6B: Path existence
473
+
474
+ ```bash
475
+ [ -d "$(grep 'root:' "$FORGE_YAML" | head -1 | awk '{print $2}' | tr -d '"')" ] \
476
+ && echo "✓ paths.root exists" \
477
+ || echo "WARNING: paths.root does not exist on this machine"
478
+ ```
479
+
480
+ ### 6C: Project board ID resolution
481
+
482
+ `project_board.project_id` must be a GitHub Projects v2 node ID with the `PVT_` prefix (e.g. `PVT_kwHOxxxxxxxxxxxxxxxx`). This value is returned by `gh project list --owner <owner> --format json | jq '.projects[] | .id'`. A manually-edited `forge.yaml` with an incorrect value (e.g. a project number instead of a node ID) will produce a confusing GraphQL error — the format check below catches this before attempting the API call.
483
+
484
+ ```bash
485
+ # Only run if project_board section was written
486
+ if grep -q "^project_board:" "$FORGE_YAML"; then
487
+ PROJECT_ID=$(grep "project_id:" "$FORGE_YAML" | head -1 | awk '{print $2}' | tr -d '"')
488
+ # Validate PVT_ prefix before GraphQL call — any other format will produce a confusing API error
489
+ if [[ "$PROJECT_ID" != PVT_* ]]; then
490
+ echo "ERROR: project_board.project_id must start with 'PVT_' (got: '$PROJECT_ID')"
491
+ echo " Expected format: PVT_kwHOxxxxxxxxxxxxxxxx"
492
+ echo " Obtain the correct value with: gh project list --owner ${OWNER} --format json | jq '.projects[] | .id'"
493
+ else
494
+ gh api graphql -f query='query { node(id: "'"$PROJECT_ID"'") { id __typename } }' 2>/dev/null \
495
+ | jq -e '.data.node.id' > /dev/null \
496
+ && echo "✓ project_board.project_id resolves" \
497
+ || echo "WARNING: project_board.project_id may be invalid — verify with: gh project list --owner ${OWNER}"
498
+ fi
499
+ fi
500
+ ```
501
+
502
+ ### 6D: Satellite repo access
503
+
504
+ ```bash
505
+ # Only run if repos.satellites section was written
506
+ if grep -q "^repos:" "$FORGE_YAML"; then
507
+ # Extract satellite repo names and verify each is accessible
508
+ grep -A 20 "^repos:" "$FORGE_YAML" | grep "repo:" | tail -n +2 | while read -r line; do
509
+ SAT_REPO=$(echo "$line" | awk '{print $2}' | tr -d '"')
510
+ gh repo view "$SAT_REPO" --json name 2>/dev/null \
511
+ && echo "✓ satellite repo ${SAT_REPO} accessible" \
512
+ || echo "WARNING: satellite repo ${SAT_REPO} not accessible — check prefix and repo name"
513
+ done
514
+ fi
515
+ ```
516
+
517
+ ### 6E: Final report
518
+
519
+ ```
520
+ forge.yaml is ready.
521
+
522
+ Validation results:
523
+ {validation output from 6A–6D}
524
+
525
+ Next steps:
526
+ 1. If forge.yaml contains sensitive paths (credentials file, local paths):
527
+ echo "forge.yaml" >> .gitignore
528
+ 2. Test the pipeline:
529
+ /work-on next
530
+ 3. If any WARNING appeared above, edit forge.yaml to fix the flagged values.
531
+ 4. Backup file: forge.yaml.bak (delete when satisfied)
532
+
533
+ ForgeDock commands now use your project's config from forge.yaml.
534
+ ```