forgedock 1.0.17 → 1.0.18

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 (131) hide show
  1. package/README.md +34 -1
  2. package/bin/cross-publish.mjs +344 -0
  3. package/bin/forgedock.mjs +229 -17
  4. package/commands/autopilot.md +77 -0
  5. package/commands/design-bench.md +176 -0
  6. package/commands/design-render-critique-loop.md +103 -0
  7. package/commands/design.md +259 -0
  8. package/commands/issue.md +7 -3
  9. package/commands/orchestrate.md +121 -0
  10. package/commands/qa-sweep.md +37 -2
  11. package/commands/quality-gate.md +30 -0
  12. package/commands/review-pr-staging.md +158 -2
  13. package/commands/test-gate.md +929 -0
  14. package/commands/work-on/build/implement.md +5 -3
  15. package/commands/work-on.md +53 -3
  16. package/docs/CI.md +177 -0
  17. package/docs/FORGE-PROTOCOL.md +324 -0
  18. package/docs/articles/b-vs-c-baseline.md +210 -0
  19. package/docs/articles/full-abc-benchmark.md +205 -0
  20. package/docs/articles/selective-spec-loading-token-savings.md +140 -0
  21. package/docs/design/abc-benchmark.md +195 -0
  22. package/docs/design/design-architect-rationale.md +123 -0
  23. package/docs/design/design-memory.md +61 -0
  24. package/docs/design/design-spec-schema.md +248 -0
  25. package/docs/design/design-system-lint.md +150 -0
  26. package/docs/design/divergent-generation.md +106 -0
  27. package/docs/design/effects-appropriateness.md +133 -0
  28. package/docs/design/fixtures/briefs/README.md +47 -0
  29. package/docs/design/fixtures/briefs/cadence.md +39 -0
  30. package/docs/design/fixtures/briefs/plume.md +39 -0
  31. package/docs/design/fixtures/briefs/slipstream.md +39 -0
  32. package/docs/design/fixtures/briefs/tender.md +39 -0
  33. package/docs/design/fixtures/briefs/voltage.md +39 -0
  34. package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-1.html +364 -0
  35. package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-2.html +420 -0
  36. package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-3.html +506 -0
  37. package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-1.html +611 -0
  38. package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-2.html +594 -0
  39. package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-3.html +817 -0
  40. package/docs/design/fixtures/runs/b-vs-c-baseline/runs.json +175 -0
  41. package/docs/design/fixtures/runs/b-vs-c-baseline/scorecard.json +138 -0
  42. package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-1.html +373 -0
  43. package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-2.html +398 -0
  44. package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-3.html +595 -0
  45. package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-1.html +531 -0
  46. package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-2.html +565 -0
  47. package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-3.html +674 -0
  48. package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-1.html +388 -0
  49. package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-2.html +463 -0
  50. package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-3.html +568 -0
  51. package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-1.html +562 -0
  52. package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-2.html +618 -0
  53. package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-3.html +618 -0
  54. package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-1.html +364 -0
  55. package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-2.html +420 -0
  56. package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-3.html +506 -0
  57. package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-1.html +527 -0
  58. package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-2.html +445 -0
  59. package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-3.html +483 -0
  60. package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-1.html +611 -0
  61. package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-2.html +594 -0
  62. package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-3.html +817 -0
  63. package/docs/design/fixtures/runs/full-abc/runs.json +190 -0
  64. package/docs/design/fixtures/runs/full-abc/scorecard.json +144 -0
  65. package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-1.html +496 -0
  66. package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-2.html +447 -0
  67. package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-3.html +564 -0
  68. package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-1.html +373 -0
  69. package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-2.html +398 -0
  70. package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-3.html +595 -0
  71. package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-1.html +622 -0
  72. package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-2.html +475 -0
  73. package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-3.html +660 -0
  74. package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-1.html +531 -0
  75. package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-2.html +565 -0
  76. package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-3.html +674 -0
  77. package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-1.html +525 -0
  78. package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-2.html +446 -0
  79. package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-3.html +463 -0
  80. package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-1.html +388 -0
  81. package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-2.html +463 -0
  82. package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-3.html +568 -0
  83. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-1.html +1068 -0
  84. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-2.html +1423 -0
  85. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-3.html +1245 -0
  86. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-1.html +305 -0
  87. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-2.html +327 -0
  88. package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-3.html +428 -0
  89. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-1.html +1270 -0
  90. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-2.html +1172 -0
  91. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-3.html +1532 -0
  92. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-1.html +315 -0
  93. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-2.html +342 -0
  94. package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-3.html +353 -0
  95. package/docs/design/fixtures/runs/full-abc-opus/runs.json +190 -0
  96. package/docs/design/fixtures/runs/full-abc-opus/scorecard.json +144 -0
  97. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-1.html +345 -0
  98. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-2.html +396 -0
  99. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-3.html +502 -0
  100. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-1.html +408 -0
  101. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-2.html +446 -0
  102. package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-3.html +496 -0
  103. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-1.html +813 -0
  104. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-2.html +711 -0
  105. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-3.html +721 -0
  106. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-1.html +280 -0
  107. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-2.html +291 -0
  108. package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-3.html +366 -0
  109. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-1.html +1010 -0
  110. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-2.html +836 -0
  111. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-3.html +930 -0
  112. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-1.html +407 -0
  113. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-2.html +396 -0
  114. package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-3.html +529 -0
  115. package/docs/design/foundations/brutalist.css +294 -0
  116. package/docs/design/foundations/editorial.css +300 -0
  117. package/docs/design/foundations/minimal-luxury.css +295 -0
  118. package/docs/design/foundations/technical.css +293 -0
  119. package/docs/design/foundations/warm-photo.css +299 -0
  120. package/docs/design/reference-corpus.md +1726 -0
  121. package/docs/design/render-critique-loop.md +57 -0
  122. package/docs/spec-graph-schema.md +397 -0
  123. package/package.json +1 -1
  124. package/scripts/bench-scorecard.mjs +239 -0
  125. package/scripts/build-spec-graph.mjs +509 -0
  126. package/scripts/classify-lane.sh +0 -7
  127. package/scripts/design-system-lint.mjs +993 -0
  128. package/scripts/graph-query.sh +486 -0
  129. package/scripts/transition-label.sh +10 -2
  130. package/scripts/validate-spec-graph.sh +423 -0
  131. package/templates/workflows/forgedock-review.yml +96 -0
@@ -26,9 +26,13 @@ GH_REPO=$(yq '.project.owner + "/" + .project.repo' "$CONFIG_FILE")
26
26
  GH_FLAG="-R $GH_REPO"
27
27
  DEFAULT_BRANCH=$(yq '.branches.default' "$CONFIG_FILE")
28
28
  STAGING_BRANCH=$(yq '.branches.staging' "$CONFIG_FILE")
29
+
30
+ # Test-gate config (Phase 6.5) — read here so vars are available before first use
31
+ GATE_POSTURE=$(yq '.verification.test_gate.posture // "blocking"' "$CONFIG_FILE" 2>/dev/null || echo "blocking")
32
+ OVERRIDE_PHRASE=$(yq '.verification.test_gate.override_phrase // "OVERRIDE: shipping with test failures —"' "$CONFIG_FILE" 2>/dev/null || echo "OVERRIDE: shipping with test failures —")
29
33
  ```
30
34
 
31
- All `$DEFAULT_BRANCH` and `$STAGING_BRANCH` references below are populated from `forge.yaml`.
35
+ All `$DEFAULT_BRANCH`, `$STAGING_BRANCH`, `$GATE_POSTURE`, and `$OVERRIDE_PHRASE` references below are populated from `forge.yaml`.
32
36
 
33
37
  ---
34
38
 
@@ -342,6 +346,132 @@ Agent maps dependencies, assesses integration points (service boundaries, env va
342
346
 
343
347
  ---
344
348
 
349
+ ## Phase 6.5: Runtime Test Gate (BLOCKING — runs after static analysis, before finding triage)
350
+
351
+ **Purpose**: Verify the integrated bundle's acceptance criteria against running code before the deploy verdict. Catches runtime defects (cross-PR interactions, container/startup failures, regression in tested behaviour) that static review cannot surface.
352
+
353
+ **Why here**: Phase 6 completes all static analysis (regression risk, security, quality). Phase 6.5 adds the runtime dimension before Phase 7 triages findings — so any test-gate failures can be filed as `test-failure` issues by `/test-gate` itself, then surface in Phase 7's triage pass.
354
+
355
+ **Posture**: Controlled by `verification.test_gate.posture` in `forge.yaml` (resolved in Config Resolution as `$GATE_POSTURE`). Default: `blocking`. Set to `advisory` to surface failures without preventing deploy. <!-- Added: forge#906 -->
356
+
357
+ ```bash
358
+ echo "=== Phase 6.5: Runtime Test Gate ==="
359
+ echo "Bundle PRs: $(echo $ALL_PR_NUMBERS | tr '\n' ' ')"
360
+ echo "Posture: ${GATE_POSTURE}"
361
+
362
+ # Initialize test-gate verdict (default SKIP — safe if Phase 6.5 is bypassed)
363
+ TEST_GATE_VERDICT="SKIP"
364
+ TEST_GATE_REASON="Phase 6.5 not yet run"
365
+
366
+ # Invoke /test-gate with the bundle PRs already computed in Phase 0A
367
+ # ALL_PR_NUMBERS is the de-duplicated union of both scan methods (commit log + merge subjects)
368
+ GATE_OUTPUT=$(Skill("test-gate", "--prs \"$(echo $ALL_PR_NUMBERS | tr '\n' ' ' | xargs)\" --base $DEFAULT_BRANCH"))
369
+
370
+ # Extract machine-readable verdict from Skill output
371
+ TEST_GATE_VERDICT=$(echo "$GATE_OUTPUT" | grep -oP '(?<=FORGE:TEST_GATE:RESULT=)(BLOCK|PASS|SKIP)' | tail -1 || echo "SKIP")
372
+
373
+ echo "Test-gate verdict: ${TEST_GATE_VERDICT}"
374
+ ```
375
+
376
+ **Verdict handling**:
377
+
378
+ ```bash
379
+ case "$TEST_GATE_VERDICT" in
380
+
381
+ SKIP)
382
+ echo "ℹ️ Test gate: SKIP — no executable changes or tests not configured."
383
+ echo " This gap will appear in the Phase 8 summary. No deploy impact."
384
+ TEST_GATE_REASON="SKIP — no runtime tests ran (docs-only bundle, no integration tests configured, or manual-only criteria)"
385
+ ;;
386
+
387
+ PASS)
388
+ echo "✅ Test gate: PASS — all test clusters passed. Deploy may proceed."
389
+ TEST_GATE_REASON="PASS — all automated test clusters passed"
390
+ ;;
391
+
392
+ BLOCK)
393
+ # Check for override comment on the staging→main PR (mirrors Phase 0A pattern)
394
+ if [ -n "$PR_NUMBER" ]; then
395
+ TG_OVERRIDE=$(gh pr view "$PR_NUMBER" ${GH_FLAG} \
396
+ --json comments \
397
+ --jq "[.comments[].body | select(startswith(\"${OVERRIDE_PHRASE}\"))] | length" 2>/dev/null || echo 0)
398
+ else
399
+ TG_OVERRIDE=0
400
+ fi
401
+
402
+ if [ "${TG_OVERRIDE:-0}" -gt 0 ]; then
403
+ OVERRIDE_REASON=$(gh pr view "$PR_NUMBER" ${GH_FLAG} \
404
+ --json comments \
405
+ --jq "[.comments[].body | select(startswith(\"${OVERRIDE_PHRASE}\"))] | last" 2>/dev/null || echo "(reason not captured)")
406
+ echo "⚠️ Test gate: BLOCK — but override comment detected on PR #${PR_NUMBER}."
407
+ echo " Override: ${OVERRIDE_REASON}"
408
+ echo " Proceeding with deploy. Override is logged in Phase 8 summary."
409
+ TEST_GATE_VERDICT="PASS"
410
+ TEST_GATE_REASON="BLOCK downgraded to PASS by override: ${OVERRIDE_REASON}"
411
+
412
+ elif [ "$GATE_POSTURE" = "advisory" ]; then
413
+ echo "⚠️ Test gate: BLOCK (advisory posture) — runtime failures detected but deploy is NOT prevented."
414
+ echo " Switch verification.test_gate.posture to 'blocking' in forge.yaml to enforce this gate."
415
+ TEST_GATE_REASON="BLOCK (advisory) — runtime failures detected; deploy allowed by advisory posture"
416
+
417
+ else
418
+ # blocking posture (default) — STOP
419
+ echo "⛔ DEPLOY BLOCKED — /test-gate returned BLOCK verdict."
420
+ echo ""
421
+ echo "Runtime failures were detected in the staging→${DEFAULT_BRANCH} bundle."
422
+ echo "The failures were batch-introduced (not pre-existing on ${DEFAULT_BRANCH} baseline)."
423
+ echo ""
424
+ echo "Options:"
425
+ echo " 1. Fix the failing tests and merge fixes to staging before retrying the deploy."
426
+ echo " 2. Post a comment on this PR starting with \"${OVERRIDE_PHRASE} <reason>\" to bypass this gate."
427
+ echo " 3. Set verification.test_gate.posture: advisory in forge.yaml to downgrade to a warning."
428
+ echo ""
429
+ echo "RESULT: BLOCK DEPLOY"
430
+
431
+ # Post structured FORGE:GATE_FAILURE comment for pipeline-health tracking
432
+ GATE_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
433
+ if [ -n "$PR_NUMBER" ]; then
434
+ gh pr comment "$PR_NUMBER" ${GH_FLAG} --body "<!-- FORGE:GATE_FAILURE -->
435
+ ## Deploy Gate: BLOCKED
436
+
437
+ **Gate**: test-gate
438
+ **Timestamp**: ${GATE_TIMESTAMP}
439
+ **Bundle PRs**: $(echo $ALL_PR_NUMBERS | tr '\n' ' ')
440
+ **Posture**: ${GATE_POSTURE}
441
+
442
+ ### What Happened
443
+
444
+ \`/test-gate\` detected runtime failures in the staging→\`${DEFAULT_BRANCH}\` bundle that were NOT present on the \`${DEFAULT_BRANCH}\` baseline. These are batch-introduced regressions.
445
+
446
+ \`/test-gate\` has filed \`test-failure\` issues for each failing cluster — check the issue tracker for details.
447
+
448
+ ### Resolution
449
+
450
+ 1. Fix the failing tests and merge fixes to staging.
451
+ 2. Retry the staging→\`${DEFAULT_BRANCH}\` deploy.
452
+
453
+ To override (ship known failures with documented reason), post a comment containing:
454
+ \`${OVERRIDE_PHRASE} <reason>\`
455
+
456
+ <!-- FORGE:GATE_FAILURE:TYPE=test-gate|BUNDLE=$(echo $ALL_PR_NUMBERS | tr '\n' ' ' | xargs) -->" 2>/dev/null || true
457
+ fi
458
+ exit 1
459
+ fi
460
+ ;;
461
+
462
+ *)
463
+ echo "⚠️ Test gate: unrecognised verdict '${TEST_GATE_VERDICT}' — treating as SKIP."
464
+ TEST_GATE_VERDICT="SKIP"
465
+ TEST_GATE_REASON="SKIP — unrecognised verdict from /test-gate (treated as SKIP)"
466
+ ;;
467
+
468
+ esac
469
+ ```
470
+
471
+ If the gate exits with `RESULT: BLOCK DEPLOY` → **STOP**. A `<!-- FORGE:GATE_FAILURE -->` structured comment is automatically posted on the staging→main PR (if `$PR_NUMBER` is set) for pipeline-health tracking. `/test-gate` will have filed `test-failure` issues for each failing cluster before returning BLOCK.
472
+
473
+ ---
474
+
345
475
  ## Phase 7: Finding Triage & Issue Creation
346
476
 
347
477
  ### 7A: Extract Findings
@@ -424,10 +554,36 @@ Labels: `review-finding` + `needs-validation` + `staging-review` + priority (`pr
424
554
  Post summary with verdict:
425
555
  1. CI failed + autofix failed → BLOCK DEPLOY
426
556
  2. CI failed + autofix succeeded → continue
557
+ 2.5. Test gate returned BLOCK (blocking posture, no override) → BLOCK DEPLOY *(handled in Phase 6.5 — if Phase 8 is reached, BLOCK was either overridden or posture is advisory)*
427
558
  3. CONFIRMED CRITICAL (non-CI) → BLOCK DEPLOY
428
559
  4. CONFIRMED HIGH blocking (crashes, data loss) → NEEDS FIXES FIRST
429
560
  5. All else → APPROVE FOR DEPLOY
430
561
 
431
- Include: Material Changes Summary, Risk Matrix (CI, Build, Bugs, Security, Billing, Quality, Regression), Finding Triage Results, Blocking Issues, Deployment Checklist (pre-deploy, deploy, post-deploy verification, rollback triggers), Stats.
562
+ Include: Material Changes Summary, Risk Matrix (CI, Build, Bugs, Security, Billing, Quality, Regression, **Test Gate**), Finding Triage Results, Blocking Issues, Deployment Checklist (pre-deploy, deploy, post-deploy verification, rollback triggers), Stats.
563
+
564
+ **Risk Matrix must include a Test Gate row** (use `$TEST_GATE_VERDICT` and `$TEST_GATE_REASON` set in Phase 6.5):
565
+
566
+ | Domain | Result | Notes |
567
+ |--------|--------|-------|
568
+ | CI | ... | ... |
569
+ | Build | ... | ... |
570
+ | Bugs | ... | ... |
571
+ | Security | ... | ... |
572
+ | Billing | ... | ... |
573
+ | Quality | ... | ... |
574
+ | Regression | ... | ... |
575
+ | **Test Gate** | `${TEST_GATE_VERDICT:-SKIP}` | `${TEST_GATE_REASON:-Phase 6.5 not run}` |
576
+
577
+ If `TEST_GATE_VERDICT` is `SKIP`, surface the gap explicitly in the summary:
578
+
579
+ > **Test Gate: SKIP** — No runtime tests ran for this bundle. This means acceptance criteria were NOT verified against running code before deploy. Cause: `${TEST_GATE_REASON}`. To enable runtime testing, configure `verification.integration_tests` in `forge.yaml`.
580
+
581
+ If `TEST_GATE_VERDICT` is `PASS`, note it as a positive signal:
582
+
583
+ > **Test Gate: PASS** — Acceptance criteria verified against running code. No batch-introduced runtime failures detected.
584
+
585
+ If `TEST_GATE_VERDICT` is `BLOCK` and Phase 8 was reached (advisory posture or override active), note it as a risk:
586
+
587
+ > **Test Gate: BLOCK (override/advisory)** — Runtime failures were detected but deploy is proceeding. Reason: `${TEST_GATE_REASON}`. Filed `test-failure` issues track the failures.
432
588
 
433
589
  **CRITICAL**: This review NEVER merges staging → main. User makes deploy decision via GitHub web UI.