forgedock 1.16.0 → 1.16.1
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/bin/engine/phases.mjs +47 -13
- package/bin/engine/runlog.mjs +21 -3
- package/bin/engine.mjs +33 -4
- package/bin/runner.mjs +21 -2
- package/commands/forge-stats.md +2 -2
- package/commands/orchestrate/phase-1-resolve.md +6 -40
- package/commands/orchestrate/phase-4-execution.md +26 -162
- package/commands/quality-gate.md +12 -80
- package/commands/review-pr-staging.md +67 -301
- package/commands/review-pr.md +150 -752
- package/commands/work-on/build/validate.md +6 -40
- package/commands/work-on/build.md +34 -24
- package/commands/work-on/close.md +6 -21
- package/commands/work-on/decompose.md +5 -22
- package/commands/work-on/investigate.md +10 -24
- package/commands/work-on/remediate.md +25 -144
- package/commands/work-on/review.md +7 -41
- package/commands/work-on.md +10 -61
- package/docs/CONFIG.md +6 -5
- package/docs/RELEASE-NOTES.md +6 -0
- package/package.json +1 -1
- package/scripts/check-spec-size.sh +47 -27
- package/scripts/check-spec-size.test.sh +46 -3
- package/scripts/forge-root.test.sh +210 -91
- package/scripts/lib/fence-bootstrap.sh +16 -0
- package/scripts/lib/forge-resolve.sh +87 -0
- package/scripts/lib/review-delta-mode.sh +41 -0
- package/scripts/lint-dispatch-prompt.test.sh +3 -3
- package/scripts/review-pr-delta-wiring.test.sh +24 -7
- package/scripts/review-pr-staging-scope.test.sh +14 -7
- package/scripts/spec-no-worktree-script.test.sh +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forgedock",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.1",
|
|
4
4
|
"description": "Autonomous development pipeline for coding agents. GitHub as institutional memory, with native Claude Code and OpenCode entrypoints.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"forgedock": "bin/forgedock.mjs"
|
|
@@ -5,17 +5,21 @@
|
|
|
5
5
|
#
|
|
6
6
|
# Usage: check-spec-size.sh [base_ref] (default: $BASE_REF, else origin/staging)
|
|
7
7
|
# Env: PR_LABELS comma-separated PR label names (untrusted; grep-matched only)
|
|
8
|
-
#
|
|
8
|
+
# PR_HEAD_REF / PR_BASE_REF PR head and base branch names; staging -> main
|
|
9
|
+
# (a release PR) is skipped: cumulative growth is not judged here
|
|
10
|
+
# PR_SAME_REPO must be "true" for the release skip (a fork branch named
|
|
11
|
+
# staging must not bypass the budget)
|
|
9
12
|
# GITHUB_STEP_SUMMARY summary file (stdout when unset)
|
|
10
13
|
# Exit: 0 pass/exempt, 1 budget violation, 2 usage/base-ref error (fail closed)
|
|
11
14
|
#
|
|
12
|
-
# Rules (against the PR base, compared in bytes):
|
|
15
|
+
# Rules (against the merge-base of HEAD and the PR base, compared in bytes):
|
|
13
16
|
# 1. Budgeted specs may not grow by more than 2% or more than 4096 bytes.
|
|
14
|
-
# 2.
|
|
15
|
-
#
|
|
17
|
+
# 2. The NET count of canonical block markers across all of commands/**/*.md
|
|
18
|
+
# may not rise (moving a block between files, or replacing one with a stub,
|
|
19
|
+
# is allowed). Count-based until the shared helper lands (#3493).
|
|
16
20
|
# Shrinking or equal size always passes.
|
|
17
|
-
# Exemption: `spec-size-exempt` label
|
|
18
|
-
#
|
|
21
|
+
# Exemption: the `spec-size-exempt` label only (needs triage rights; a PR-body
|
|
22
|
+
# marker is NOT honoured). Failures are reported, exit 0.
|
|
19
23
|
# Bash 3.2 portable: no assoc arrays, mapfile, grep -P.
|
|
20
24
|
set -uo pipefail
|
|
21
25
|
|
|
@@ -32,15 +36,27 @@ if ! git rev-parse --verify -q "$BASE^{commit}" >/dev/null; then
|
|
|
32
36
|
exit 2
|
|
33
37
|
fi
|
|
34
38
|
|
|
35
|
-
# ---
|
|
39
|
+
# --- release PR skip (staging -> main) ---------------------------------------
|
|
40
|
+
if [ "${PR_HEAD_REF:-}" = "staging" ] && [ "${PR_BASE_REF:-}" = "main" ] && [ "${PR_SAME_REPO:-}" = "true" ]; then
|
|
41
|
+
out "## Spec-size budget"
|
|
42
|
+
out ""
|
|
43
|
+
out "Result: SKIPPED (release PR staging -> main; growth was checked per PR)"
|
|
44
|
+
echo "spec-size: skipped for release PR staging -> main"
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Compare against the merge-base, not the base tip (base moves after branching).
|
|
49
|
+
MB=$(git merge-base HEAD "$BASE" 2>/dev/null) || MB=""
|
|
50
|
+
if [ -z "$MB" ]; then
|
|
51
|
+
echo "ERROR: no merge-base between HEAD and '$BASE' (need fetch-depth: 0)" >&2
|
|
52
|
+
exit 2
|
|
53
|
+
fi
|
|
54
|
+
BASE="$MB"
|
|
55
|
+
|
|
56
|
+
# --- exemption: label only ---------------------------------------------------
|
|
36
57
|
EXEMPT_REASON=""
|
|
37
58
|
if printf '%s' "${PR_LABELS:-}" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -qxF 'spec-size-exempt'; then
|
|
38
59
|
EXEMPT_REASON="label spec-size-exempt"
|
|
39
|
-
else
|
|
40
|
-
R=$(printf '%s\n' "${PR_BODY:-}" | tr -d '\r' \
|
|
41
|
-
| sed -n 's/^[[:space:]]*<!--[[:space:]]*spec-size-exempt:[[:space:]]*\(.*\)-->[[:space:]]*$/\1/p' \
|
|
42
|
-
| head -n 1 | sed 's/[[:space:]]*$//')
|
|
43
|
-
[ -n "$R" ] && EXEMPT_REASON="PR body marker: $R"
|
|
44
60
|
fi
|
|
45
61
|
|
|
46
62
|
FAILURES=0
|
|
@@ -66,25 +82,29 @@ for f in $BUDGETED; do
|
|
|
66
82
|
out "| \`$f\` | $b | $h | $g | $p | $status |"
|
|
67
83
|
done
|
|
68
84
|
|
|
69
|
-
|
|
70
|
-
#
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
85
|
+
# Net marker total across every commands/**/*.md: head (working tree, incl. new
|
|
86
|
+
# files) vs base (incl. files deleted at head). Fail only when the total rises.
|
|
87
|
+
HEAD_TOTAL=0; BASE_TOTAL=0; MARKER_ROWS=""
|
|
88
|
+
HEAD_FILES=$(git ls-files 'commands/*.md' | sort -u)
|
|
89
|
+
BASE_FILES=$(git ls-tree -r --name-only "$BASE" -- commands | grep -E '\.md$' | sort -u)
|
|
90
|
+
for f in $(printf '%s\n%s\n' "$HEAD_FILES" "$BASE_FILES" | sort -u); do
|
|
91
|
+
[ -n "$f" ] || continue
|
|
92
|
+
hc=0; [ -f "$f" ] && hc=$(grep -cE "$MARKERS" "$f" 2>/dev/null || true); hc=${hc:-0}
|
|
74
93
|
bc=$(git show "$BASE:$f" 2>/dev/null | grep -cE "$MARKERS" 2>/dev/null || true); bc=${bc:-0}
|
|
75
|
-
|
|
76
|
-
|
|
94
|
+
HEAD_TOTAL=$((HEAD_TOTAL + hc)); BASE_TOTAL=$((BASE_TOTAL + bc))
|
|
95
|
+
[ "$hc" -ne "$bc" ] && MARKER_ROWS="$MARKER_ROWS| \`$f\` | $bc | $hc |
|
|
77
96
|
"
|
|
78
|
-
FAILURES=$((FAILURES + 1))
|
|
79
|
-
fi
|
|
80
97
|
done
|
|
81
|
-
if [ -
|
|
98
|
+
if [ "$HEAD_TOTAL" -gt "$BASE_TOTAL" ]; then
|
|
99
|
+
FAILURES=$((FAILURES + 1))
|
|
82
100
|
out ""
|
|
83
|
-
out "###
|
|
101
|
+
out "### NEW CANONICAL BLOCK COPY: net marker total rose $BASE_TOTAL -> $HEAD_TOTAL (source the shared helper instead)"
|
|
102
|
+
fi
|
|
103
|
+
if [ -n "$MARKER_ROWS" ]; then
|
|
84
104
|
out ""
|
|
85
|
-
out "| File | Base markers | Head markers |
|
|
86
|
-
out "
|
|
87
|
-
printf '%s' "$
|
|
105
|
+
out "| File | Base markers | Head markers |"
|
|
106
|
+
out "|------|-----:|-----:|"
|
|
107
|
+
printf '%s' "$MARKER_ROWS" >> "$SUMMARY"
|
|
88
108
|
fi
|
|
89
109
|
|
|
90
110
|
out ""
|
|
@@ -97,6 +117,6 @@ if [ -n "$EXEMPT_REASON" ]; then
|
|
|
97
117
|
echo "spec-size: $FAILURES violation(s) waived: $EXEMPT_REASON"
|
|
98
118
|
exit 0
|
|
99
119
|
fi
|
|
100
|
-
out "Result: FAIL ($FAILURES violation(s)). Shrink the spec, or
|
|
120
|
+
out "Result: FAIL ($FAILURES violation(s)). Shrink the spec, or ask a maintainer to add the spec-size-exempt label."
|
|
101
121
|
echo "spec-size: FAIL ($FAILURES violation(s)); see job summary" >&2
|
|
102
122
|
exit 1
|
|
@@ -18,6 +18,7 @@ gen() { awk -v n="$1" 'BEGIN{for(i=0;i<n;i++) print "line of spec text number "
|
|
|
18
18
|
gen 4000 > commands/review-pr.md # ~110 KB: 2% ~ 2.2 KB < 4 KB cap
|
|
19
19
|
gen 20000 > commands/work-on.md # ~560 KB: 2% ~ 11 KB, so the 4 KB cap binds
|
|
20
20
|
gen 100 > commands/other.md
|
|
21
|
+
printf 'HELPER_SCRIPT=""\n' > commands/donor.md
|
|
21
22
|
gen 100 > commands/work-on/remediate.md
|
|
22
23
|
git add -A; git commit -qm base; git branch -M staging; git push -q origin staging 2>/dev/null
|
|
23
24
|
git checkout -q -b feat
|
|
@@ -26,7 +27,7 @@ reset() { git reset -q --hard origin/staging; git clean -qfd; }
|
|
|
26
27
|
run() { # name want_rc [env...]
|
|
27
28
|
local name="$1" want="$2"; shift 2
|
|
28
29
|
local sum="$TMP/summary"; : > "$sum"
|
|
29
|
-
env GITHUB_STEP_SUMMARY="$sum" PR_LABELS=""
|
|
30
|
+
env GITHUB_STEP_SUMMARY="$sum" PR_LABELS="" PR_HEAD_REF="" PR_BASE_REF="" "$@" bash "$S" origin/staging >"$TMP/out" 2>"$TMP/err"
|
|
30
31
|
local rc=$?
|
|
31
32
|
if [ "$rc" = "$want" ]; then ok; else bad "$name (rc=$rc want $want)"; cat "$TMP/err"; fi
|
|
32
33
|
}
|
|
@@ -72,10 +73,52 @@ run "reduced count passes" 0
|
|
|
72
73
|
# Exemption
|
|
73
74
|
reset; gen 100 >> commands/review-pr.md
|
|
74
75
|
run "exempt by label" 0 PR_LABELS="bug,spec-size-exempt"; has "label reported" "EXEMPT"
|
|
75
|
-
run "
|
|
76
|
-
run "empty-reason marker not exempt" 1 PR_BODY='<!-- spec-size-exempt: -->'
|
|
76
|
+
run "body marker does not exempt" 1 PR_BODY=$'text\n<!-- spec-size-exempt: security fix -->\nmore'
|
|
77
77
|
run "label substring not exempt" 1 PR_LABELS="spec-size-exempt-not"
|
|
78
78
|
|
|
79
|
+
# Net counting: moves and stubs pass (the #3493 / #3590 shape)
|
|
80
|
+
reset; : > commands/donor.md; printf 'HELPER_SCRIPT=""\n' >> commands/other.md
|
|
81
|
+
run "net move between files passes" 0
|
|
82
|
+
reset; : > commands/donor.md; printf 'HELPER_SCRIPT=""\n' > commands/new-spec.md; git add -A
|
|
83
|
+
run "move to a new file passes" 0
|
|
84
|
+
reset; git rm -q commands/donor.md; gen 5 > commands/review-pr.md; printf 'HELPER_SCRIPT=""\n' > commands/helper-stub.md; git add -A
|
|
85
|
+
run "stub replaces deleted block passes" 0
|
|
86
|
+
reset; printf 'HELPER_SCRIPT=""\n' >> commands/other.md
|
|
87
|
+
run "copy without removal still fails" 1
|
|
88
|
+
|
|
89
|
+
# Shared-helper stubs (forge#3778): the sourced-helper stub shape carries none of the markers, so converting an inlined block to a stub
|
|
90
|
+
# is a net reduction, while re-pasting the full block still fails.
|
|
91
|
+
STUB_LOC='type forge_resolve >/dev/null 2>&1 || for _r in "${FORGEDOCK_HOME:-}"; do . "$_r/scripts/lib/forge-resolve.sh"; done'
|
|
92
|
+
reset; printf '%s\n' "$STUB_LOC" '. "$(forge_resolve lib/fence-bootstrap.sh)" || exit 1 # FENCE_BOOTSTRAP' 'HELPER_SCRIPT=$(forge_resolve x.sh)' >> commands/other.md
|
|
93
|
+
run "one-tag-per-stub design passes" 0
|
|
94
|
+
reset; : > commands/donor.md; printf '%s\n' "$STUB_LOC" 'HELPER_SCRIPT=$(forge_resolve x.sh)' >> commands/other.md
|
|
95
|
+
run "block converted to a stub passes" 0
|
|
96
|
+
reset; printf '%s\n' "$STUB_LOC" 'HELPER_SCRIPT=""' >> commands/other.md
|
|
97
|
+
run "stub plus a re-pasted resolver block fails" 1
|
|
98
|
+
|
|
99
|
+
# Release PR skip (staging -> main only)
|
|
100
|
+
reset; gen 100 >> commands/review-pr.md
|
|
101
|
+
run "release PR skipped" 0 PR_HEAD_REF=staging PR_BASE_REF=main PR_SAME_REPO=true; has "skip reported" "SKIPPED"
|
|
102
|
+
run "fork branch named staging still checked" 1 PR_HEAD_REF=staging PR_BASE_REF=main PR_SAME_REPO=false
|
|
103
|
+
run "release PR without same-repo flag still checked" 1 PR_HEAD_REF=staging PR_BASE_REF=main
|
|
104
|
+
run "hotfix to main still checked" 1 PR_HEAD_REF=hotfix PR_BASE_REF=main
|
|
105
|
+
run "staging to other base still checked" 1 PR_HEAD_REF=staging PR_BASE_REF=dev
|
|
106
|
+
|
|
107
|
+
# Merge-base: base advancing after branching must not count against the PR
|
|
108
|
+
reset; git checkout -q -b old-branch; git checkout -q staging 2>/dev/null || git checkout -q -B staging origin/staging
|
|
109
|
+
gen 300 >> commands/review-pr.md; git commit -qam "base grows"; git push -q origin HEAD:staging 2>/dev/null
|
|
110
|
+
git checkout -q old-branch; git fetch -q origin staging
|
|
111
|
+
run "base tip growth ignored (merge-base)" 0
|
|
112
|
+
git checkout -q feat; git branch -qD old-branch; git branch -qf staging origin/staging; reset
|
|
113
|
+
|
|
114
|
+
# Script extracted from the base ref behaves the same
|
|
115
|
+
git show origin/staging:scripts/check-spec-size.sh > "$TMP/base-script.sh" 2>/dev/null || cp "$S" "$TMP/base-script.sh"
|
|
116
|
+
gen 100 >> commands/review-pr.md
|
|
117
|
+
: > "$TMP/summary"
|
|
118
|
+
GITHUB_STEP_SUMMARY="$TMP/summary" PR_LABELS="" bash "$TMP/base-script.sh" origin/staging >/dev/null 2>&1; rc=$?
|
|
119
|
+
[ "$rc" = 1 ] && ok || bad "extracted base-ref script fails over-budget change (rc=$rc)"
|
|
120
|
+
reset
|
|
121
|
+
|
|
79
122
|
# Fail closed on unresolvable base
|
|
80
123
|
: > "$TMP/summary"
|
|
81
124
|
GITHUB_STEP_SUMMARY="$TMP/summary" bash "$S" origin/does-not-exist >/dev/null 2>&1; rc=$?
|