forgedock 1.1.10 → 1.2.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 (76) hide show
  1. package/README.md +1 -1
  2. package/bin/cli-spawn-shared.mjs +25 -0
  3. package/bin/engine-cli.mjs +22 -1
  4. package/bin/engine.mjs +46 -4
  5. package/bin/forgedock.mjs +166 -20
  6. package/bin/hooks/pre-tool-use.mjs +331 -10
  7. package/bin/init-detect.mjs +1 -1
  8. package/bin/init-enrich-api.mjs +12 -4
  9. package/bin/init-enrich-cli.mjs +328 -0
  10. package/bin/init-enrich.mjs +137 -0
  11. package/bin/journey.mjs +328 -50
  12. package/bin/runner.mjs +653 -10
  13. package/commands/adopt.md +1 -1
  14. package/commands/analytics.md +10 -7
  15. package/commands/audit-agents.md +29 -6
  16. package/commands/audit.md +9 -20
  17. package/commands/autopilot.md +52 -78
  18. package/commands/changelog.md +1 -1
  19. package/commands/ci-audit.md +19 -10
  20. package/commands/cleanup.md +1 -1
  21. package/commands/compat-audit.md +1 -1
  22. package/commands/deploy-info.md +1 -1
  23. package/commands/deploy-pr.md +1 -1
  24. package/commands/design-bench.md +1 -1
  25. package/commands/design-render-critique-loop.md +1 -1
  26. package/commands/diagnose.md +1 -1
  27. package/commands/forge-stats.md +1 -1
  28. package/commands/forgedock-init.md +1 -1
  29. package/commands/geo-audit.md +9 -6
  30. package/commands/incident-response.md +15 -5
  31. package/commands/issue.md +298 -15
  32. package/commands/milestone.md +45 -18
  33. package/commands/optimize.md +1 -1
  34. package/commands/orchestrate/phase-1-resolve.md +20 -5
  35. package/commands/orchestrate/phase-4-execution.md +6 -1
  36. package/commands/orchestrate/phase-5-cleanup.md +43 -2
  37. package/commands/orchestrate/phase-6-report.md +1 -0
  38. package/commands/orchestrate.md +1 -1
  39. package/commands/pipeline-health/phase-4-proposals.md +40 -10
  40. package/commands/pipeline-health/phase-5-report.md +140 -13
  41. package/commands/pipeline-health.md +1 -1
  42. package/commands/pipeline-resume.md +1 -1
  43. package/commands/pipeline-status.md +1 -1
  44. package/commands/qa-sweep.md +10 -4
  45. package/commands/recover-orphans.md +1 -1
  46. package/commands/review-pr-agents/protocols.md +4 -0
  47. package/commands/review-pr-agents.md +7 -4
  48. package/commands/review-pr-staging.md +44 -15
  49. package/commands/review-pr.md +73 -28
  50. package/commands/rollback.md +15 -5
  51. package/commands/security-audit.md +14 -11
  52. package/commands/signal-planner.md +32 -12
  53. package/commands/spec-doctor.md +1 -1
  54. package/commands/sync-ecosystem.md +54 -11
  55. package/commands/test-gate.md +49 -11
  56. package/commands/validate.md +28 -9
  57. package/commands/work-on/build/architect.md +1 -1
  58. package/commands/work-on/build/context.md +1 -1
  59. package/commands/work-on/build/implement.md +2 -2
  60. package/commands/work-on/build/validate.md +3 -1
  61. package/commands/work-on/build.md +1 -1
  62. package/commands/work-on/close.md +1 -1
  63. package/commands/work-on/decompose.md +27 -24
  64. package/commands/work-on/investigate.md +2 -2
  65. package/commands/work-on/remediate.md +11 -3
  66. package/commands/work-on/review.md +5 -3
  67. package/commands/work-on-monolithic.md +1 -1
  68. package/commands/work-on.md +38 -8
  69. package/docs/CI.md +18 -0
  70. package/docs/CONFIG.md +5 -2
  71. package/docs/site/annotations-explained.md +2 -2
  72. package/docs/site/command-reference.md +21 -0
  73. package/docs/spec/review-protocol.md +6 -0
  74. package/package.json +1 -1
  75. package/scripts/danger-zones.mjs +3 -1
  76. package/scripts/transition-label.sh +80 -28
@@ -83,8 +83,25 @@ if [ "${1:-}" = "--validate" ]; then
83
83
  fi
84
84
 
85
85
  # Check if issue carries needs-validation (idempotent gate)
86
- CURRENT_LABELS=$(gh issue view "$ISSUE_NUMBER" "${GH_ARGS[@]}" --json labels \
87
- --jq '[.labels[].name] | join(",")' 2>/dev/null || echo "")
86
+ #
87
+ # forge#1991: a bare `2>/dev/null || echo ""` here collapsed "fetch
88
+ # failed" and "fetch succeeded, issue has no labels" into the same empty
89
+ # string, so a failed fetch fell through to the "no needs-validation —
90
+ # no action taken (idempotent)" branch below and exited 0, silently
91
+ # misreporting a transient API failure as successful idempotent no-op.
92
+ # Use the same `if VAR=$(cmd); then ... else ... fi` idiom already
93
+ # applied to the workflow-mode label fetches (forge#1977/#1988/#1990) to
94
+ # keep the two outcomes distinguishable. This block has no
95
+ # TRANSITION_EXIT_CODE deferred-exit convention (that only exists in the
96
+ # workflow-mode block below), so failure exits 1 directly here, matching
97
+ # this script's documented exit codes (0 = success, 1 = error).
98
+ if CURRENT_LABELS=$(gh issue view "$ISSUE_NUMBER" "${GH_ARGS[@]}" --json labels \
99
+ --jq '[.labels[].name] | join(",")' 2>/dev/null); then
100
+ : # fetch succeeded; CURRENT_LABELS may legitimately be an empty string
101
+ else
102
+ echo "ERROR: needs-validation label fetch failed (transient network error / rate limit?) for issue #$ISSUE_NUMBER — cannot determine finding-lifecycle state. Aborting without action." >&2
103
+ exit 1
104
+ fi
88
105
 
89
106
  if ! echo "$CURRENT_LABELS" | grep -q "needs-validation"; then
90
107
  echo "OK: Issue #$ISSUE_NUMBER does not have needs-validation — no action taken (idempotent)"
@@ -282,9 +299,27 @@ gh issue edit "$ISSUE_NUMBER" "${GH_ARGS[@]}" --add-label "$EFFECTIVE_LABEL"
282
299
  # have doesn't need removing anyway — so intersecting against the issue's
283
300
  # current labels sidesteps the all-or-nothing failure mode entirely instead
284
301
  # of relying on `|| true` to mask it.
302
+ #
303
+ # forge#1990: this fetch itself can fail (transient network error, rate
304
+ # limit) independently of whether the issue actually has any stale labels.
305
+ # A bare `2>/dev/null || echo ""` collapsed "fetch failed" and "fetch
306
+ # succeeded, issue has no labels" into the same empty string — so a failed
307
+ # fetch here silently skipped the ENTIRE removal/verification block below
308
+ # (not just its post-hoc confirmation) while the script still reported `OK`
309
+ # on exit 0. Use the same `if VAR=$(cmd); then ... else ... fi` idiom
310
+ # already applied to the post-removal verification fetch below (forge#1977/
311
+ # #1988) to keep the two outcomes distinguishable, and defer a non-zero
312
+ # exit via TRANSITION_EXIT_CODE (forge#1929 convention) instead of masking
313
+ # the failure as success.
285
314
  # ---------------------------------------------------------------------------
286
- CURRENT_ISSUE_LABELS=$(gh issue view "$ISSUE_NUMBER" "${GH_ARGS[@]}" --json labels \
287
- --jq '[.labels[].name] | join(",")' 2>/dev/null || echo "")
315
+ if CURRENT_ISSUE_LABELS=$(gh issue view "$ISSUE_NUMBER" "${GH_ARGS[@]}" --json labels \
316
+ --jq '[.labels[].name] | join(",")' 2>/dev/null); then
317
+ : # fetch succeeded; CURRENT_ISSUE_LABELS may legitimately be an empty string
318
+ else
319
+ echo "ERROR: pre-removal label fetch failed (transient network error / rate limit?) for issue #$ISSUE_NUMBER — cannot determine which stale workflow:* labels to remove. Skipping removal to avoid acting on incomplete data." >&2
320
+ CURRENT_ISSUE_LABELS=""
321
+ TRANSITION_EXIT_CODE=1
322
+ fi
288
323
 
289
324
  TO_REMOVE=""
290
325
  IFS=',' read -ra REMOVE_CANDIDATES <<< "$REMOVE_LABELS"
@@ -327,35 +362,52 @@ if [ -n "$TO_REMOVE" ]; then
327
362
  # step in the one case (persistent removal failure) it's most important
328
363
  # for the caller to see a consistent, fully-applied label state.
329
364
  # -------------------------------------------------------------------------
330
- POST_REMOVE_LABELS=$(gh issue view "$ISSUE_NUMBER" "${GH_ARGS[@]}" --json labels \
331
- --jq '[.labels[].name] | join(",")' 2>/dev/null || echo "")
332
-
333
- STILL_PRESENT=""
334
- IFS=',' read -ra TO_REMOVE_CHECK <<< "$TO_REMOVE"
335
- for candidate in "${TO_REMOVE_CHECK[@]}"; do
336
- case ",$POST_REMOVE_LABELS," in
337
- *",$candidate,"*)
338
- STILL_PRESENT="${STILL_PRESENT:+$STILL_PRESENT,}$candidate"
339
- ;;
340
- esac
341
- done
365
+ # forge#1977: the fetch itself can fail (transient network error, rate
366
+ # limit) independently of whether the label was actually removed. A bare
367
+ # `2>/dev/null || echo ""` collapses "fetch failed" and "fetch succeeded,
368
+ # label absent" into the same empty string, so a failed verification call
369
+ # was previously indistinguishable from a confirmed-clean result — masking
370
+ # the exact failure mode this block exists to catch. Use `if VAR=$(cmd);
371
+ # then ... else ... fi` (set -e-safe: command substitution failure inside
372
+ # an `if` condition does not trigger `set -e`) to keep the two outcomes
373
+ # distinguishable, and treat a failed fetch as "still present" so it flows
374
+ # into the existing retry / fail-loud path below instead of silently
375
+ # reporting success.
376
+ if POST_REMOVE_LABELS=$(gh issue view "$ISSUE_NUMBER" "${GH_ARGS[@]}" --json labels \
377
+ --jq '[.labels[].name] | join(",")' 2>/dev/null); then
378
+ STILL_PRESENT=""
379
+ IFS=',' read -ra TO_REMOVE_CHECK <<< "$TO_REMOVE"
380
+ for candidate in "${TO_REMOVE_CHECK[@]}"; do
381
+ case ",$POST_REMOVE_LABELS," in
382
+ *",$candidate,"*)
383
+ STILL_PRESENT="${STILL_PRESENT:+$STILL_PRESENT,}$candidate"
384
+ ;;
385
+ esac
386
+ done
387
+ else
388
+ echo "WARNING: post-removal verification API call failed (transient network error / rate limit?) — cannot confirm removal, treating ($TO_REMOVE) as unverified..." >&2
389
+ STILL_PRESENT="$TO_REMOVE"
390
+ fi
342
391
 
343
392
  if [ -n "$STILL_PRESENT" ]; then
344
393
  echo "WARNING: label removal did not take effect for ($STILL_PRESENT) — retrying once..." >&2
345
394
  gh issue edit "$ISSUE_NUMBER" "${GH_ARGS[@]}" --remove-label "$STILL_PRESENT" 2>/dev/null || true
346
395
 
347
- POST_RETRY_LABELS=$(gh issue view "$ISSUE_NUMBER" "${GH_ARGS[@]}" --json labels \
348
- --jq '[.labels[].name] | join(",")' 2>/dev/null || echo "")
349
-
350
- STILL_PRESENT_AFTER_RETRY=""
351
- IFS=',' read -ra RETRY_CHECK <<< "$STILL_PRESENT"
352
- for candidate in "${RETRY_CHECK[@]}"; do
353
- case ",$POST_RETRY_LABELS," in
354
- *",$candidate,"*)
355
- STILL_PRESENT_AFTER_RETRY="${STILL_PRESENT_AFTER_RETRY:+$STILL_PRESENT_AFTER_RETRY,}$candidate"
356
- ;;
357
- esac
358
- done
396
+ if POST_RETRY_LABELS=$(gh issue view "$ISSUE_NUMBER" "${GH_ARGS[@]}" --json labels \
397
+ --jq '[.labels[].name] | join(",")' 2>/dev/null); then
398
+ STILL_PRESENT_AFTER_RETRY=""
399
+ IFS=',' read -ra RETRY_CHECK <<< "$STILL_PRESENT"
400
+ for candidate in "${RETRY_CHECK[@]}"; do
401
+ case ",$POST_RETRY_LABELS," in
402
+ *",$candidate,"*)
403
+ STILL_PRESENT_AFTER_RETRY="${STILL_PRESENT_AFTER_RETRY:+$STILL_PRESENT_AFTER_RETRY,}$candidate"
404
+ ;;
405
+ esac
406
+ done
407
+ else
408
+ echo "WARNING: post-retry verification API call also failed (transient network error / rate limit?) — cannot confirm removal after retry, treating ($STILL_PRESENT) as unverified..." >&2
409
+ STILL_PRESENT_AFTER_RETRY="$STILL_PRESENT"
410
+ fi
359
411
 
360
412
  if [ -n "$STILL_PRESENT_AFTER_RETRY" ]; then
361
413
  echo "ERROR: failed to remove stale label(s) ($STILL_PRESENT_AFTER_RETRY) from issue #$ISSUE_NUMBER after retry — label state machine now inconsistent (issue carries both '$EFFECTIVE_LABEL' and the stale label(s) above)." >&2