forgedock 1.10.3 → 1.11.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.
- package/commands/ci-audit.md +3 -3
- package/commands/compat-audit.md +1 -1
- package/commands/deploy-pr.md +6 -6
- package/commands/explain.md +2 -2
- package/commands/fix-ci.md +2 -2
- package/commands/forge-stats.md +1 -1
- package/commands/forgedock-init.md +3 -3
- package/commands/optimize.md +5 -5
- package/commands/orchestrate/phase-1-resolve.md +2 -2
- package/commands/orchestrate/phase-4-execution.md +182 -41
- package/commands/quality-gate.md +1 -1
- package/commands/recover-orphans.md +6 -6
- package/commands/review-pr-agents/protocols.md +1 -0
- package/commands/review-pr-staging.md +28 -6
- package/commands/review-pr.md +434 -120
- package/commands/security-audit.md +1 -1
- package/commands/spec-doctor.md +2 -2
- package/commands/test-gate.md +7 -7
- package/commands/work-on/build/architect.md +21 -0
- package/commands/work-on/build/context.md +1 -1
- package/commands/work-on/build/implement.md +17 -0
- package/commands/work-on/build/validate.md +2 -2
- package/commands/work-on/build.md +98 -9
- package/commands/work-on/close.md +33 -11
- package/commands/work-on/decompose.md +19 -5
- package/commands/work-on/investigate.md +34 -4
- package/commands/work-on/remediate.md +30 -6
- package/commands/work-on/review.md +10 -8
- package/commands/work-on.md +20 -11
- package/docs/CONFIG.md +30 -0
- package/docs/RELEASE-NOTES.md +9 -0
- package/docs/WORK-ON-RUNTIME.md +22 -2
- package/docs/site/architecture.md +1 -1
- package/docs/spec/forge-protocol-v1.md +10 -0
- package/docs/spec/review-protocol.md +1 -0
- package/package.json +1 -1
- package/packages/protocol/src/types.js +17 -0
- package/scripts/check-spec-bash.sh +45 -2
- package/scripts/check-spec-bash.test.sh +24 -1
- package/scripts/check-spec-markers.sh +53 -0
- package/scripts/diff-size.sh +84 -0
- package/scripts/diff-size.test.sh +117 -0
- package/scripts/forge-root.test.sh +15 -0
- package/scripts/remediation-marker-match.test.sh +51 -0
- package/scripts/review-pr-arguments.test.sh +180 -0
- package/scripts/trusted-comments.test.sh +23 -0
|
@@ -330,7 +330,7 @@ SWEEP_ID="sweep-$(date -u +%Y%m%dT%H%M%SZ)-$$"
|
|
|
330
330
|
# Both reads run under pipefail in a subshell: the pipeline status would otherwise be jq's, and a gh failure
|
|
331
331
|
# (rate limit, 403) would yield "[]" with exit 0, indistinguishable from "no live holder".
|
|
332
332
|
claim_orphan() {
|
|
333
|
-
local num="$1" now cutoff comments live resp
|
|
333
|
+
local num="${1}" now cutoff comments live resp
|
|
334
334
|
[ "$DRY_RUN" = "true" ] && return 0 # dry-run: no claim comment is posted (callers already skip dry-run resumes)
|
|
335
335
|
now=$(date -u +%s); cutoff=$(( now - RECOVERY_CLAIM_TTL_MIN * 60 ))
|
|
336
336
|
comments=$(set -o pipefail; gh api --paginate "repos/${GH_REPO}/issues/${num}/comments" 2>/dev/null \
|
|
@@ -380,7 +380,7 @@ Holder: /recover-orphans — resuming /work-on #${num}. Other sweeps and dispatc
|
|
|
380
380
|
# every time (an identical-body edit may not bump updated_at). Never carries FORGE:HEARTBEAT or the RELEASED marker.
|
|
381
381
|
refresh_orphan() {
|
|
382
382
|
[ "$DRY_RUN" = "true" ] && return 0
|
|
383
|
-
[ -n "${CLAIM_COMMENT_ID:-}" ] && [ "${CLAIM_HELD_NUM:-}" = "$1" ] || return 0
|
|
383
|
+
[ -n "${CLAIM_COMMENT_ID:-}" ] && [ "${CLAIM_HELD_NUM:-}" = "${1}" ] || return 0
|
|
384
384
|
gh api -X PATCH "repos/${GH_REPO}/issues/comments/${CLAIM_COMMENT_ID}" \
|
|
385
385
|
-f body="${CLAIM_BODY}
|
|
386
386
|
Refreshed: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >/dev/null 2>&1 || true
|
|
@@ -390,7 +390,7 @@ Refreshed: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >/dev/null 2>&1 || true
|
|
|
390
390
|
start_claim_keepalive() {
|
|
391
391
|
[ "$DRY_RUN" = "true" ] && return 0
|
|
392
392
|
stop_claim_keepalive
|
|
393
|
-
local num="$1" interval=$(( RECOVERY_CLAIM_TTL_MIN * 60 / 3 ))
|
|
393
|
+
local num="${1}" interval=$(( RECOVERY_CLAIM_TTL_MIN * 60 / 3 ))
|
|
394
394
|
[ "$interval" -ge 1 ] || interval=1
|
|
395
395
|
( while sleep "$interval"; do refresh_orphan "$num"; done ) >/dev/null 2>&1 &
|
|
396
396
|
KEEPALIVE_PID=$!
|
|
@@ -408,9 +408,9 @@ stop_claim_keepalive() {
|
|
|
408
408
|
release_orphan() {
|
|
409
409
|
[ "$DRY_RUN" = "true" ] && return 0
|
|
410
410
|
stop_claim_keepalive
|
|
411
|
-
[ "${CLAIM_HELD_NUM:-}" = "$1" ] || return 0
|
|
411
|
+
[ "${CLAIM_HELD_NUM:-}" = "${1}" ] || return 0
|
|
412
412
|
unset CLAIM_HELD_NUM CLAIM_COMMENT_ID
|
|
413
|
-
gh issue comment "$1" ${GH_FLAG} --body "<!-- FORGE:RECOVERY_CLAIM_RELEASED -->
|
|
413
|
+
gh issue comment "${1}" ${GH_FLAG} --body "<!-- FORGE:RECOVERY_CLAIM_RELEASED -->
|
|
414
414
|
**Sweep: ${SWEEP_ID}**
|
|
415
415
|
Released by /recover-orphans." >/dev/null 2>&1 || true
|
|
416
416
|
}
|
|
@@ -418,7 +418,7 @@ Released by /recover-orphans." >/dev/null 2>&1 || true
|
|
|
418
418
|
# resume_orphan_inline <issue> — run after claim_orphan succeeded. The subshell EXIT trap releases the claim always:
|
|
419
419
|
# on success and when the Skill call fails. The keepalive runs alongside the Skill call and is stopped by the release.
|
|
420
420
|
resume_orphan_inline() {
|
|
421
|
-
local num="$1"
|
|
421
|
+
local num="${1}"
|
|
422
422
|
(
|
|
423
423
|
trap 'release_orphan "$num"' EXIT
|
|
424
424
|
start_claim_keepalive "$num"
|
|
@@ -177,6 +177,7 @@ Append this block at the very end of your comment (after the `---` footer line,
|
|
|
177
177
|
7. **Empty block**: If no findings at all, include just the START/END markers
|
|
178
178
|
8. **HTML comments**: The block is invisible in rendered markdown but parseable by the review system
|
|
179
179
|
9. **Agent marker**: Include exactly one `<!-- FORGE:REVIEW-AGENT:{domain} -->` marker in the persisted body, where `{domain}` is the lowercase dispatched domain.
|
|
180
|
+
10. **Reviewed SHA**: Include exactly one line `Reviewed-SHA: [REVIEW_SHA]` (the full 40-hex head you were pinned to) in the persisted body, outside the marker. `/review-pr` scopes its completion wait and idempotent re-entry to this line, so a comment without the current head does not count as a completed review. Do NOT put the SHA inside the `<!-- FORGE:REVIEW-AGENT:{domain} -->` marker.
|
|
180
181
|
|
|
181
182
|
### Domain Prefixes
|
|
182
183
|
|
|
@@ -150,10 +150,31 @@ Agents receive `$IS_REENTRY`, `$PRIOR_OPEN_FINDINGS`, and `$PRIOR_RESOLVED_FINDI
|
|
|
150
150
|
Resolve the staging→main PR number and post a routing marker immediately. This creates an audit trail — if a staging→main PR has no `FORGE:REVIEW_ROUTE` comment after this command was invoked, the review was bypassed or never started.
|
|
151
151
|
|
|
152
152
|
```bash
|
|
153
|
-
# Resolve PR_NUMBER from
|
|
154
|
-
#
|
|
155
|
-
|
|
156
|
-
|
|
153
|
+
# Resolve PR_NUMBER from the argument string (never name the loader placeholder in this block: every
|
|
154
|
+
# occurrence is substituted textually, comments included) <!-- Added: forge#3466 -->
|
|
155
|
+
# The argument string may be: a PR number, "staging", "feature", or "staging:feature"
|
|
156
|
+
# Only the first token is the PR ref; later tokens are flags (--auto-merge, --issue, ...) <!-- allowlist:check-command-side-effects -->
|
|
157
|
+
# The loader substitutes the text before bash parses it, so read it from a quoted heredoc (never a quoted
|
|
158
|
+
# assignment) and reject any string with a quote, backtick, dollar sign, backslash, newline or tab. <!-- Added: forge#3466 -->
|
|
159
|
+
# NONCE RULE: before running, replace NONCE in BOTH delimiter lines with a fresh random hex string (e.g. `openssl rand -hex 16`) not present in the argument text. <!-- Added: forge#3466 -->
|
|
160
|
+
IFS= read -r -d '' STAGING_ARGS_RAW <<'FORGE_ARGS_EOF_NONCE'
|
|
161
|
+
$ARGUMENTS
|
|
162
|
+
FORGE_ARGS_EOF_NONCE
|
|
163
|
+
STAGING_ARGS_RAW="${STAGING_ARGS_RAW%$'\n'}"
|
|
164
|
+
STAGING_ARGS_REJECTED=false
|
|
165
|
+
case "$STAGING_ARGS_RAW" in
|
|
166
|
+
*'"'*|*'`'*|*'$'*|*'\'*|*$'\n'*|*$'\t'*)
|
|
167
|
+
echo "review-pr-staging: rejected argument string (contains a quote, backtick, dollar sign, backslash, newline or tab) - nothing parsed" >&2
|
|
168
|
+
STAGING_ARGS_REJECTED=true; STAGING_ARGS_RAW="" ;;
|
|
169
|
+
esac
|
|
170
|
+
PR_ARG="${STAGING_ARGS_RAW%% *}"
|
|
171
|
+
PR_ARG_NUM=$(printf '%s' "$PR_ARG" | sed -nE 's#^(https?://[^ ]*/pull/)?([0-9]+)$#\2#p')
|
|
172
|
+
if [ -n "$PR_ARG_NUM" ]; then
|
|
173
|
+
PR_NUMBER="$PR_ARG_NUM"
|
|
174
|
+
elif [ "$STAGING_ARGS_REJECTED" = true ]; then
|
|
175
|
+
# Rejected string: stop. Never fall through to the open staging PR lookup or run later phases with no PR. <!-- Added: forge#3466 -->
|
|
176
|
+
echo "review-pr-staging: rejected argument string - stopping (nothing reviewed, nothing posted)" >&2
|
|
177
|
+
exit 1
|
|
157
178
|
else
|
|
158
179
|
# Find the open staging→main PR
|
|
159
180
|
PR_NUMBER=$(gh pr list ${GH_FLAG} \
|
|
@@ -164,7 +185,8 @@ else
|
|
|
164
185
|
--jq '.[0].number' 2>/dev/null || echo "")
|
|
165
186
|
fi
|
|
166
187
|
|
|
167
|
-
REVIEW_SHA_STAGING
|
|
188
|
+
REVIEW_SHA_STAGING="n/a" # gh pr view "" falls back to the current branch PR, so only look up a resolved number <!-- Added: forge#3466 -->
|
|
189
|
+
[ -n "$PR_NUMBER" ] && REVIEW_SHA_STAGING=$(gh pr view "$PR_NUMBER" ${GH_FLAG} --json headRefOid --jq '.headRefOid' 2>/dev/null | cut -c1-7 || echo "n/a")
|
|
168
190
|
|
|
169
191
|
if [ -n "$PR_NUMBER" ]; then
|
|
170
192
|
gh pr comment "$PR_NUMBER" ${GH_FLAG} --body "<!-- FORGE:REVIEW_ROUTE mode=staging-deploy spec=review-pr-staging.md sha=${REVIEW_SHA_STAGING} -->"
|
|
@@ -330,7 +352,7 @@ If the gate exits with `RESULT: PASS` → a `<!-- FORGE:GATE_PASS -->` structure
|
|
|
330
352
|
```bash
|
|
331
353
|
git fetch origin $DEFAULT_BRANCH $STAGING_BRANCH
|
|
332
354
|
git diff origin/$DEFAULT_BRANCH...origin/$STAGING_BRANCH --stat | tail -20
|
|
333
|
-
git diff origin/$DEFAULT_BRANCH...origin/$STAGING_BRANCH --numstat | awk '{add+=$1; del+=$2} END {print "Added:", add, "Deleted:", del, "Total:", add+del}'
|
|
355
|
+
git diff origin/$DEFAULT_BRANCH...origin/$STAGING_BRANCH --numstat | awk '{add+=$(1); del+=$(2)} END {print "Added:", add, "Deleted:", del, "Total:", add+del}'
|
|
334
356
|
git diff origin/$DEFAULT_BRANCH...origin/$STAGING_BRANCH --name-only | sort | uniq
|
|
335
357
|
```
|
|
336
358
|
|