forgedock 1.0.22 → 1.1.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.
- package/README.md +255 -211
- package/bin/batch-runner.mjs +339 -0
- package/bin/cinema.mjs +320 -0
- package/bin/demo.mjs +92 -7
- package/bin/engine/phases.mjs +168 -0
- package/bin/engine/projector.mjs +32 -0
- package/bin/engine/reconcile.mjs +11 -0
- package/bin/engine/runlog.mjs +79 -0
- package/bin/engine/state.mjs +32 -0
- package/bin/engine-cli.mjs +222 -0
- package/bin/engine.mjs +138 -0
- package/bin/forgedock.mjs +896 -1540
- package/bin/hooks/interactive-engine.mjs +509 -0
- package/bin/hooks/pre-tool-use.mjs +498 -0
- package/bin/hooks/subagent-stop-enforce.mjs +197 -0
- package/bin/journey.mjs +841 -0
- package/bin/registry.mjs +139 -0
- package/bin/report.mjs +447 -0
- package/bin/runner.mjs +136 -20
- package/bin/settings-hook.mjs +346 -0
- package/bin/tui.mjs +6 -3
- package/commands/adopt.md +4 -1
- package/commands/analytics.md +4 -1
- package/commands/audit-agents.md +110 -27
- package/commands/audit.md +20 -1
- package/commands/autopilot.md +84 -12
- package/commands/changelog.md +2 -1
- package/commands/ci-audit.md +2 -1
- package/commands/cleanup.md +161 -1
- package/commands/compat-audit.md +2 -1
- package/commands/deploy-info.md +63 -4
- package/commands/design-bench.md +6 -1
- package/commands/design-render-critique-loop.md +2 -1
- package/commands/design.md +1 -0
- package/commands/diagnose.md +2 -1
- package/commands/explain.md +2 -1
- package/commands/forge-stats.md +122 -2
- package/commands/forgedock-init.md +1 -1
- package/commands/geo-audit.md +3 -0
- package/commands/incident-response.md +2 -1
- package/commands/issue.md +24 -3
- package/commands/milestone.md +77 -12
- package/commands/optimize.md +2 -1
- package/commands/orchestrate/config.md +67 -0
- package/commands/orchestrate/phase-1-resolve.md +159 -0
- package/commands/orchestrate/phase-2-triage.md +126 -0
- package/commands/orchestrate/phase-2.5-synthesis.md +156 -0
- package/commands/orchestrate/phase-3-dependency.md +591 -0
- package/commands/orchestrate/phase-4-execution.md +962 -0
- package/commands/orchestrate/phase-5-cleanup.md +47 -0
- package/commands/orchestrate/phase-6-report.md +198 -0
- package/commands/orchestrate/safety.md +62 -0
- package/commands/orchestrate.md +25 -2027
- package/commands/pipeline-health/config.md +34 -0
- package/commands/pipeline-health/phase-1-context.md +180 -0
- package/commands/pipeline-health/phase-2-metrics.md +1729 -0
- package/commands/pipeline-health/phase-3-analyze.md +204 -0
- package/commands/pipeline-health/phase-4-proposals.md +117 -0
- package/commands/pipeline-health/phase-5-report.md +284 -0
- package/commands/pipeline-health/phase-6-summary.md +52 -0
- package/commands/pipeline-health.md +25 -2401
- package/commands/pipeline-resume.md +24 -1
- package/commands/pipeline-status.md +65 -0
- package/commands/qa-sweep.md +4 -1
- package/commands/quality-gate.md +326 -42
- package/commands/replay.md +2 -1
- package/commands/review-pr-agents/api.md +135 -0
- package/commands/review-pr-agents/auth.md +137 -0
- package/commands/review-pr-agents/billing.md +101 -0
- package/commands/review-pr-agents/concurrency.md +145 -0
- package/commands/review-pr-agents/database.md +103 -0
- package/commands/review-pr-agents/frontend.md +89 -0
- package/commands/review-pr-agents/infra.md +385 -0
- package/commands/review-pr-agents/protocols.md +185 -0
- package/commands/review-pr-agents/scraper.md +185 -0
- package/commands/review-pr-agents/security.md +406 -0
- package/commands/review-pr-agents.md +45 -1722
- package/commands/review-pr-staging.md +196 -40
- package/commands/review-pr.md +612 -56
- package/commands/rollback.md +2 -1
- package/commands/scope.md +2 -1
- package/commands/security-audit.md +2 -1
- package/commands/signal-planner.md +623 -0
- package/commands/sync-ecosystem.md +1 -0
- package/commands/test-gate.md +17 -1
- package/commands/validate.md +2 -1
- package/commands/work-on/build/architect.md +28 -0
- package/commands/work-on/build/context.md +2 -0
- package/commands/work-on/build/implement.md +19 -5
- package/commands/work-on/build/validate.md +62 -6
- package/commands/work-on/build.md +187 -30
- package/commands/work-on/close.md +132 -5
- package/commands/work-on/decompose.md +19 -1
- package/commands/work-on/investigate.md +117 -2
- package/commands/work-on/review.md +48 -4
- package/commands/work-on-monolithic.md +8 -2
- package/commands/work-on.md +247 -7
- package/docs/BRAND.md +16 -5
- package/docs/CI.md +2 -2
- package/docs/CODEX.md +36 -1
- package/docs/CONFIG.md +44 -42
- package/docs/FORGE-PROTOCOL.md +15 -1064
- package/docs/anthropic-devrel-outreach.md +2 -2
- package/docs/articles/command-decomposition-token-savings.md +214 -0
- package/docs/articles/model-release-playbook.md +131 -0
- package/docs/articles/per-repo-adaptive-scripts-token-savings.md +27 -25
- package/docs/claude-breakpoints.json +75 -5
- package/docs/design/abc-benchmark.md +1 -1
- package/docs/design/design-spec-schema.md +1 -1
- package/docs/design/divergent-generation.md +1 -1
- package/docs/design/eval-gate-runbook.md +178 -0
- package/docs/design/show-hn-draft.md +26 -1
- package/docs/design/token-cost-baseline-1298.md +59 -0
- package/docs/eval/README.md +117 -0
- package/docs/eval/corpus/seed-v1.json +6 -0
- package/docs/eval/published/claude-sonnet-4-6-2026-07-04.json +33 -0
- package/docs/site/annotations-explained.md +24 -0
- package/docs/site/command-learning-path.md +51 -14
- package/docs/site/command-reference.md +339 -113
- package/docs/site/for-companies.md +95 -0
- package/docs/site/forge-annotation-protocol.md +12 -256
- package/docs/site/getting-started.md +58 -12
- package/docs/site/github-is-the-memory.md +113 -0
- package/docs/site/how-it-works.md +3 -13
- package/docs/site/index.md +10 -2
- package/docs/spec/eval-run-result.md +147 -0
- package/docs/spec/forge-protocol-v1.md +441 -18
- package/docs/spec/label-state-machine.md +55 -0
- package/docs/spec/review-protocol.md +158 -0
- package/docs/spec-graph-schema.md +28 -0
- package/docs/superpowers/plans/2026-07-03-cinematic-onboarding-tui.md +2339 -0
- package/docs/superpowers/plans/2026-07-03-durable-execution-engine.md +1223 -0
- package/docs/superpowers/specs/2026-07-03-cinematic-onboarding-tui-design.md +157 -0
- package/docs/superpowers/specs/2026-07-03-durable-execution-engine-design.md +194 -0
- package/docs/superpowers/specs/2026-07-04-economic-self-governance-design.md +181 -0
- package/docs/superpowers/specs/2026-07-04-provenance-trail-design.md +189 -0
- package/examples/forgedock-demo/README.md +41 -22
- package/examples/forgedock-demo/issues/06-bug-tags-type-validation.md +43 -0
- package/examples/forgedock-demo/issues/07-bug-negative-offset-pagination.md +42 -0
- package/examples/forgedock-demo/issues/08-bug-patch-mass-assignment.md +49 -0
- package/examples/forgedock-demo/issues/09-bug-count-injection.md +47 -0
- package/examples/forgedock-demo/issues/10-feature-sort-param.md +39 -0
- package/examples/forgedock-demo/issues/11-feature-patch-tags.md +37 -0
- package/examples/forgedock-demo/issues/12-feature-bulk-create.md +42 -0
- package/examples/forgedock-demo/issues/13-feature-archive-notes.md +46 -0
- package/examples/forgedock-demo/issues/14-refactor-extract-title-validation.md +41 -0
- package/examples/forgedock-demo/issues/15-refactor-protected-route-flag.md +43 -0
- package/examples/forgedock-demo/issues/16-refactor-extract-store.md +45 -0
- package/examples/forgedock-demo/issues/17-perf-tags-dedup-set.md +35 -0
- package/examples/forgedock-demo/issues/18-perf-remove-redundant-sort.md +37 -0
- package/examples/forgedock-demo/issues/19-docs-api-reference-full.md +53 -0
- package/examples/forgedock-demo/issues/20-docs-intentional-flaw-convention.md +46 -0
- package/examples/forgedock-demo/scripts/smoke.js +18 -1
- package/examples/forgedock-demo/src/db.js +36 -11
- package/examples/forgedock-demo/src/routes/notes.js +106 -9
- package/examples/forgedock-demo/src/server.js +4 -1
- package/package.json +12 -4
- package/packages/protocol/LICENSE +21 -0
- package/packages/protocol/src/cli.js +135 -0
- package/packages/protocol/src/emit.js +146 -0
- package/packages/protocol/src/index.js +43 -0
- package/packages/protocol/src/parse.js +229 -0
- package/packages/protocol/src/types.js +171 -0
- package/packages/protocol/src/validate.js +122 -0
- package/scripts/bench-topology-cost.mjs +372 -0
- package/scripts/check-command-docs-drift.sh +198 -0
- package/scripts/check-protocol-restatements.sh +176 -0
- package/scripts/check-registry/README.md +72 -0
- package/scripts/check-registry/manifest.json +6 -0
- package/scripts/code-index.sh +454 -0
- package/scripts/conformance-check.mjs +168 -0
- package/scripts/doctor-pipeline-state.sh +484 -0
- package/scripts/eval-gate-baseline.json +17 -0
- package/scripts/eval-gate-scorecard.mjs +242 -0
- package/scripts/eval-scorecard-aggregator.mjs +252 -0
- package/scripts/flaky-quarantine.sh +241 -0
- package/scripts/forge-annotation.sh +567 -0
- package/scripts/issue-dedup.sh +236 -0
- package/scripts/validate-annotation-node.mjs +233 -0
- package/scripts/verify-env-vars.sh +18 -2
- package/scripts/verify-host-headers.sh +4 -4
- package/scripts/verify-route-registration.sh +2 -2
- package/scripts/worktree-lifecycle.sh +202 -0
- package/templates/devdocs/agent/using-forgedock.md +14 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# check-command-docs-drift.sh
|
|
3
|
+
#
|
|
4
|
+
# Drift check: every installable command spec in commands/ must have a section
|
|
5
|
+
# in docs/site/command-reference.md, and every command section in the reference
|
|
6
|
+
# must have a corresponding spec file.
|
|
7
|
+
#
|
|
8
|
+
# "Installable" means: install: core (or no install: key) in YAML frontmatter.
|
|
9
|
+
# Commands with install: internal or install: extras are excluded.
|
|
10
|
+
#
|
|
11
|
+
# Exit codes:
|
|
12
|
+
# 0 — no drift
|
|
13
|
+
# 1 — drift detected (missing docs or orphaned reference sections)
|
|
14
|
+
#
|
|
15
|
+
# Usage:
|
|
16
|
+
# bash scripts/check-command-docs-drift.sh [commands-dir] [reference-file]
|
|
17
|
+
#
|
|
18
|
+
# Defaults:
|
|
19
|
+
# commands-dir = commands/
|
|
20
|
+
# reference-file = docs/site/command-reference.md
|
|
21
|
+
|
|
22
|
+
set -euo pipefail
|
|
23
|
+
|
|
24
|
+
# Normalise COMMANDS_DIR: strip trailing slash so path arithmetic is consistent
|
|
25
|
+
# regardless of whether the caller passes "commands" or "commands/".
|
|
26
|
+
COMMANDS_DIR="${1:-commands}"
|
|
27
|
+
COMMANDS_DIR="${COMMANDS_DIR%/}"
|
|
28
|
+
REFERENCE="${2:-docs/site/command-reference.md}"
|
|
29
|
+
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
# Helpers
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
# get_install_tier <file>
|
|
35
|
+
# Reads the first `install:` key from YAML frontmatter. Echoes: core | extras | internal
|
|
36
|
+
get_install_tier() {
|
|
37
|
+
local file="$1"
|
|
38
|
+
# Read up to 20 lines looking for frontmatter and the install key.
|
|
39
|
+
local in_fm=0
|
|
40
|
+
local line_no=0
|
|
41
|
+
while IFS= read -r line; do
|
|
42
|
+
line_no=$(( line_no + 1 ))
|
|
43
|
+
if [ $line_no -eq 1 ]; then
|
|
44
|
+
if [[ "$line" == "---"* ]]; then in_fm=1; continue; fi
|
|
45
|
+
# No frontmatter — default to core
|
|
46
|
+
echo "core"; return
|
|
47
|
+
fi
|
|
48
|
+
if [ $in_fm -eq 1 ]; then
|
|
49
|
+
if [[ "$line" == "---"* ]]; then
|
|
50
|
+
# End of frontmatter — key not found, default to core
|
|
51
|
+
echo "core"; return
|
|
52
|
+
fi
|
|
53
|
+
if [[ "$line" =~ ^install:[[:space:]]*(.*) ]]; then
|
|
54
|
+
local val="${BASH_REMATCH[1]}"
|
|
55
|
+
# Strip surrounding quotes
|
|
56
|
+
val="${val#\"}" ; val="${val%\"}"
|
|
57
|
+
val="${val#\'}" ; val="${val%\'}"
|
|
58
|
+
val="${val// /}" # trim spaces
|
|
59
|
+
case "$val" in
|
|
60
|
+
internal|extras) echo "$val"; return ;;
|
|
61
|
+
core) echo "core"; return ;;
|
|
62
|
+
*) echo "core"; return ;;
|
|
63
|
+
esac
|
|
64
|
+
fi
|
|
65
|
+
fi
|
|
66
|
+
done < <(head -25 "$file")
|
|
67
|
+
echo "core"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
# 1. Collect installable command names from commands/
|
|
72
|
+
# ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
declare -a INSTALLABLE_COMMANDS=()
|
|
75
|
+
|
|
76
|
+
while IFS= read -r -d '' spec; do
|
|
77
|
+
tier="$(get_install_tier "$spec")"
|
|
78
|
+
if [[ "$tier" == "core" ]]; then
|
|
79
|
+
# Derive command name from path relative to COMMANDS_DIR.
|
|
80
|
+
# e.g. commands/work-on.md → /work-on
|
|
81
|
+
# commands/work-on/build.md → /work-on/build
|
|
82
|
+
# commands/work-on/build/impl.md → /work-on/build/impl
|
|
83
|
+
rel="${spec#${COMMANDS_DIR}/}"
|
|
84
|
+
cmd="/${rel%.md}"
|
|
85
|
+
INSTALLABLE_COMMANDS+=("$cmd")
|
|
86
|
+
fi
|
|
87
|
+
done < <(find "$COMMANDS_DIR" -name '*.md' -print0 | sort -z)
|
|
88
|
+
|
|
89
|
+
# ---------------------------------------------------------------------------
|
|
90
|
+
# 2. Extract documented command names from command-reference.md
|
|
91
|
+
# ---------------------------------------------------------------------------
|
|
92
|
+
# We look for lines of the form: ### `/some-command`
|
|
93
|
+
# The reference uses backtick-wrapped command names under H3 headings.
|
|
94
|
+
|
|
95
|
+
declare -a DOCUMENTED_COMMANDS=()
|
|
96
|
+
|
|
97
|
+
while IFS= read -r line; do
|
|
98
|
+
# Match H3 heading: ### `/command-name` or ### `/command/sub`
|
|
99
|
+
if [[ "$line" =~ ^###[[:space:]]+\`(/[a-zA-Z0-9_/-]+)\` ]]; then
|
|
100
|
+
cmd="${BASH_REMATCH[1]}"
|
|
101
|
+
DOCUMENTED_COMMANDS+=("$cmd")
|
|
102
|
+
# Match table cell containing a bare command path: | `/command-name` | ...
|
|
103
|
+
# This covers the Sub-Phase Commands table which lists commands without H3 headings.
|
|
104
|
+
# We require the line to look like a markdown table row (starts with |) to avoid
|
|
105
|
+
# matching inline code examples in prose or fix-instruction blocks.
|
|
106
|
+
elif [[ "$line" =~ ^\| ]]; then
|
|
107
|
+
# Extract all backtick-wrapped tokens that look like command paths
|
|
108
|
+
while [[ "$line" =~ \`(/[a-zA-Z0-9_/-]+)\` ]]; do
|
|
109
|
+
cmd="${BASH_REMATCH[1]}"
|
|
110
|
+
DOCUMENTED_COMMANDS+=("$cmd")
|
|
111
|
+
# Remove the matched portion so the loop can find multiple tokens per line
|
|
112
|
+
line="${line#*\`${cmd}\`}"
|
|
113
|
+
done
|
|
114
|
+
fi
|
|
115
|
+
done < "$REFERENCE"
|
|
116
|
+
|
|
117
|
+
# Deduplicate DOCUMENTED_COMMANDS (table rows may repeat H3-listed commands)
|
|
118
|
+
declare -a _DEDUPED=()
|
|
119
|
+
declare -A _SEEN=()
|
|
120
|
+
for cmd in "${DOCUMENTED_COMMANDS[@]}"; do
|
|
121
|
+
if [[ -z "${_SEEN[$cmd]+x}" ]]; then
|
|
122
|
+
_DEDUPED+=("$cmd")
|
|
123
|
+
_SEEN[$cmd]=1
|
|
124
|
+
fi
|
|
125
|
+
done
|
|
126
|
+
DOCUMENTED_COMMANDS=("${_DEDUPED[@]}")
|
|
127
|
+
|
|
128
|
+
# ---------------------------------------------------------------------------
|
|
129
|
+
# 3. Compare
|
|
130
|
+
# ---------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
FAIL=0
|
|
133
|
+
|
|
134
|
+
echo "=== ForgeDock command docs drift check ==="
|
|
135
|
+
echo ""
|
|
136
|
+
echo "Installable specs : ${#INSTALLABLE_COMMANDS[@]}"
|
|
137
|
+
echo "Documented commands: ${#DOCUMENTED_COMMANDS[@]}"
|
|
138
|
+
echo ""
|
|
139
|
+
|
|
140
|
+
# 3a. Installable commands missing from the reference
|
|
141
|
+
echo "--- Installable commands not documented in command-reference.md ---"
|
|
142
|
+
MISSING_DOCS=0
|
|
143
|
+
for cmd in "${INSTALLABLE_COMMANDS[@]}"; do
|
|
144
|
+
found=0
|
|
145
|
+
for doc_cmd in "${DOCUMENTED_COMMANDS[@]}"; do
|
|
146
|
+
if [[ "$doc_cmd" == "$cmd" ]]; then
|
|
147
|
+
found=1
|
|
148
|
+
break
|
|
149
|
+
fi
|
|
150
|
+
done
|
|
151
|
+
if [[ $found -eq 0 ]]; then
|
|
152
|
+
echo " MISSING DOC: $cmd"
|
|
153
|
+
MISSING_DOCS=$(( MISSING_DOCS + 1 ))
|
|
154
|
+
FAIL=1
|
|
155
|
+
fi
|
|
156
|
+
done
|
|
157
|
+
if [[ $MISSING_DOCS -eq 0 ]]; then
|
|
158
|
+
echo " OK — all installable commands are documented"
|
|
159
|
+
fi
|
|
160
|
+
echo ""
|
|
161
|
+
|
|
162
|
+
# 3b. Reference sections whose spec no longer exists (orphaned docs)
|
|
163
|
+
echo "--- Reference sections with no matching installable spec ---"
|
|
164
|
+
ORPHANED=0
|
|
165
|
+
for doc_cmd in "${DOCUMENTED_COMMANDS[@]}"; do
|
|
166
|
+
found=0
|
|
167
|
+
for cmd in "${INSTALLABLE_COMMANDS[@]}"; do
|
|
168
|
+
if [[ "$cmd" == "$doc_cmd" ]]; then
|
|
169
|
+
found=1
|
|
170
|
+
break
|
|
171
|
+
fi
|
|
172
|
+
done
|
|
173
|
+
if [[ $found -eq 0 ]]; then
|
|
174
|
+
echo " ORPHANED REF: $doc_cmd (no matching installable spec)"
|
|
175
|
+
ORPHANED=$(( ORPHANED + 1 ))
|
|
176
|
+
FAIL=1
|
|
177
|
+
fi
|
|
178
|
+
done
|
|
179
|
+
if [[ $ORPHANED -eq 0 ]]; then
|
|
180
|
+
echo " OK — all reference sections have a matching spec"
|
|
181
|
+
fi
|
|
182
|
+
echo ""
|
|
183
|
+
|
|
184
|
+
# ---------------------------------------------------------------------------
|
|
185
|
+
# 4. Result
|
|
186
|
+
# ---------------------------------------------------------------------------
|
|
187
|
+
|
|
188
|
+
if [[ $FAIL -eq 1 ]]; then
|
|
189
|
+
echo "FAIL: command/docs drift detected."
|
|
190
|
+
echo ""
|
|
191
|
+
echo "Fix:"
|
|
192
|
+
echo " - MISSING DOC → add a section for the command to docs/site/command-reference.md"
|
|
193
|
+
echo " - ORPHANED REF → remove the section or restore the spec under commands/"
|
|
194
|
+
exit 1
|
|
195
|
+
else
|
|
196
|
+
echo "OK: no drift between commands/ and docs/site/command-reference.md"
|
|
197
|
+
exit 0
|
|
198
|
+
fi
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
#
|
|
5
|
+
# check-protocol-restatements.sh — Guard against future restatements of normative
|
|
6
|
+
# FORGE protocol content in commands/**/*.md.
|
|
7
|
+
#
|
|
8
|
+
# ForgeDock keeps three protocol definitions in designated normative source files:
|
|
9
|
+
#
|
|
10
|
+
# docs/FORGE-PROTOCOL.md — FORGE annotation format (annotation types,
|
|
11
|
+
# schemas, completion sentinels)
|
|
12
|
+
# docs/WORKFLOW.md — Label state machine (workflow:* transitions)
|
|
13
|
+
# commands/review-pr-agents.md — Evidence-Based Review Protocol (review agent
|
|
14
|
+
# behaviour, structured findings format)
|
|
15
|
+
#
|
|
16
|
+
# Once these are single-sourced, command specs should reference them via a
|
|
17
|
+
# one-line pointer, NOT restate the full content. This script detects
|
|
18
|
+
# heading-level signatures that indicate a full restatement has crept back in.
|
|
19
|
+
#
|
|
20
|
+
# Detected patterns (heading-level restatement signatures):
|
|
21
|
+
#
|
|
22
|
+
# FORGE_ANNOTATION_PROTOCOL — "# FORGE Annotation Protocol"
|
|
23
|
+
# "## FORGE Annotation Protocol"
|
|
24
|
+
# ANNOTATION_TYPES — "## Annotation Types"
|
|
25
|
+
# "### Annotation Types"
|
|
26
|
+
# WORKFLOW_STATE_MACHINE — "# Workflow State Machine"
|
|
27
|
+
# "## Workflow State Machine"
|
|
28
|
+
# LABEL_STATE_MACHINE — "# Label State Machine"
|
|
29
|
+
# "## Label State Machine"
|
|
30
|
+
# REVIEW_PROTOCOL — "## Evidence-Based Review Protocol"
|
|
31
|
+
# (outside its normative source)
|
|
32
|
+
#
|
|
33
|
+
# Each pattern is keyed to a NORMATIVE_SOURCE — the one file allowed to contain
|
|
34
|
+
# that heading. All other files in commands/ that match are flagged as
|
|
35
|
+
# restatements.
|
|
36
|
+
#
|
|
37
|
+
# Allowlist: to permit a heading in an additional file (e.g. a migration guide),
|
|
38
|
+
# add an HTML comment directly after the heading on the same line:
|
|
39
|
+
#
|
|
40
|
+
# ## Evidence-Based Review Protocol <!-- allowlist:check-protocol-restatements -->
|
|
41
|
+
#
|
|
42
|
+
# Usage:
|
|
43
|
+
# check-protocol-restatements.sh [<commands_dir> [<docs_dir>]]
|
|
44
|
+
# commands_dir: path to the commands/ directory (default: ./commands)
|
|
45
|
+
# docs_dir: path to the docs/ directory (default: ./docs)
|
|
46
|
+
#
|
|
47
|
+
# Exit codes:
|
|
48
|
+
# 0 no restatements found
|
|
49
|
+
# 1 one or more restatement headings found (listed to stderr)
|
|
50
|
+
# 2 usage / dependency error (directory not found)
|
|
51
|
+
#
|
|
52
|
+
# <!-- Added: forge#1270 -->
|
|
53
|
+
|
|
54
|
+
set -euo pipefail
|
|
55
|
+
|
|
56
|
+
COMMANDS_DIR="${1:-./commands}"
|
|
57
|
+
DOCS_DIR="${2:-./docs}"
|
|
58
|
+
|
|
59
|
+
if [ ! -d "$COMMANDS_DIR" ]; then
|
|
60
|
+
echo "ERROR: commands directory not found: $COMMANDS_DIR" >&2
|
|
61
|
+
echo "Usage: $0 [<commands_dir> [<docs_dir>]]" >&2
|
|
62
|
+
exit 2
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
if [ ! -d "$DOCS_DIR" ]; then
|
|
66
|
+
echo "ERROR: docs directory not found: $DOCS_DIR" >&2
|
|
67
|
+
echo "Usage: $0 [<commands_dir> [<docs_dir>]]" >&2
|
|
68
|
+
exit 2
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Normalise paths so comparisons against normative sources work correctly.
|
|
72
|
+
COMMANDS_DIR="$(cd "$COMMANDS_DIR" && pwd)"
|
|
73
|
+
DOCS_DIR="$(cd "$DOCS_DIR" && pwd)"
|
|
74
|
+
REPO_ROOT="$(dirname "$COMMANDS_DIR")"
|
|
75
|
+
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
# Pattern table — parallel arrays (same index = one pattern rule)
|
|
78
|
+
#
|
|
79
|
+
# PATTERN_NAMES : human-readable pattern ID (for error messages)
|
|
80
|
+
# PATTERN_REGEXES : grep -E regex, anchored to line start (^)
|
|
81
|
+
# NORMATIVE_SOURCES: repo-root-relative path of the one file that MAY contain
|
|
82
|
+
# the heading; all other files in commands/ are violations
|
|
83
|
+
# ---------------------------------------------------------------------------
|
|
84
|
+
PATTERN_NAMES=(
|
|
85
|
+
"FORGE_ANNOTATION_PROTOCOL"
|
|
86
|
+
"ANNOTATION_TYPES"
|
|
87
|
+
"WORKFLOW_STATE_MACHINE"
|
|
88
|
+
"LABEL_STATE_MACHINE"
|
|
89
|
+
"REVIEW_PROTOCOL"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Each regex matches one or more heading levels for the given protocol section.
|
|
93
|
+
# Anchored (^) so prose references mid-sentence are not false positives.
|
|
94
|
+
# Trailing content after the key phrase is permitted (e.g. parentheticals like
|
|
95
|
+
# "(ALL Agents Follow)") — the anchored key phrase is the restatement signal.
|
|
96
|
+
# The allowlist comment token exclusion is handled in a separate grep -v pass.
|
|
97
|
+
PATTERN_REGEXES=(
|
|
98
|
+
"^#{1,2} FORGE Annotation Protocol"
|
|
99
|
+
"^#{2,3} Annotation Types[[:space:]]*$"
|
|
100
|
+
"^#{1,2} Workflow State Machine"
|
|
101
|
+
"^#{1,2} Label State Machine"
|
|
102
|
+
"^#{1,2} Evidence-Based Review Protocol"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
NORMATIVE_SOURCES=(
|
|
106
|
+
"docs/FORGE-PROTOCOL.md"
|
|
107
|
+
"docs/FORGE-PROTOCOL.md"
|
|
108
|
+
"docs/WORKFLOW.md"
|
|
109
|
+
"docs/WORKFLOW.md"
|
|
110
|
+
"commands/review-pr-agents.md"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# ---------------------------------------------------------------------------
|
|
114
|
+
# Scan: for each pattern, grep all .md files in commands/, exclude the
|
|
115
|
+
# normative source and allowlisted lines, collect violations.
|
|
116
|
+
# ---------------------------------------------------------------------------
|
|
117
|
+
VIOLATIONS=()
|
|
118
|
+
|
|
119
|
+
for i in "${!PATTERN_NAMES[@]}"; do
|
|
120
|
+
pattern_name="${PATTERN_NAMES[$i]}"
|
|
121
|
+
regex="${PATTERN_REGEXES[$i]}"
|
|
122
|
+
normative_rel="${NORMATIVE_SOURCES[$i]}"
|
|
123
|
+
normative_abs="${REPO_ROOT}/${normative_rel}"
|
|
124
|
+
|
|
125
|
+
# grep -rn: recursive, print filename:lineno:content
|
|
126
|
+
# --include: only .md files
|
|
127
|
+
# We pipe through grep -v to:
|
|
128
|
+
# 1. Exclude the normative source file itself
|
|
129
|
+
# 2. Exclude lines carrying the allowlist token
|
|
130
|
+
while IFS= read -r hit; do
|
|
131
|
+
[ -n "$hit" ] || continue
|
|
132
|
+
# hit format: <filepath>:<lineno>:<line_content>
|
|
133
|
+
filepath="${hit%%:*}"
|
|
134
|
+
rest="${hit#*:}"
|
|
135
|
+
lineno="${rest%%:*}"
|
|
136
|
+
line_content="${rest#*:}"
|
|
137
|
+
|
|
138
|
+
# Display a repo-root-relative path for readability.
|
|
139
|
+
rel_path="${filepath#"${REPO_ROOT}/"}"
|
|
140
|
+
|
|
141
|
+
VIOLATIONS+=("${rel_path}:${lineno}: restatement of ${pattern_name}")
|
|
142
|
+
VIOLATIONS+=(" heading: '${line_content}'")
|
|
143
|
+
done < <(
|
|
144
|
+
grep -rnE "$regex" "$COMMANDS_DIR" --include="*.md" 2>/dev/null \
|
|
145
|
+
| grep -v "^${normative_abs}:" \
|
|
146
|
+
| grep -v '<!-- allowlist:check-protocol-restatements -->' \
|
|
147
|
+
|| true
|
|
148
|
+
)
|
|
149
|
+
done
|
|
150
|
+
|
|
151
|
+
# ---------------------------------------------------------------------------
|
|
152
|
+
# Report and exit.
|
|
153
|
+
# ---------------------------------------------------------------------------
|
|
154
|
+
if [ ${#VIOLATIONS[@]} -gt 0 ]; then
|
|
155
|
+
echo "ERROR: FORGE protocol restatement heading(s) found in commands/:" >&2
|
|
156
|
+
echo "" >&2
|
|
157
|
+
for v in "${VIOLATIONS[@]}"; do
|
|
158
|
+
echo " $v" >&2
|
|
159
|
+
done
|
|
160
|
+
echo "" >&2
|
|
161
|
+
echo "These headings indicate a full restatement of normative protocol content." >&2
|
|
162
|
+
echo "Replace the section with a one-line pointer to the normative source, e.g.:" >&2
|
|
163
|
+
echo " > Protocol reference: see docs/FORGE-PROTOCOL.md" >&2
|
|
164
|
+
echo "" >&2
|
|
165
|
+
echo "To permit a heading in this file intentionally, add the allowlist token:" >&2
|
|
166
|
+
echo " ## <Heading> <!-- allowlist:check-protocol-restatements -->" >&2
|
|
167
|
+
echo "" >&2
|
|
168
|
+
echo "Normative sources (these files may contain the headings):" >&2
|
|
169
|
+
echo " docs/FORGE-PROTOCOL.md — FORGE annotation format" >&2
|
|
170
|
+
echo " docs/WORKFLOW.md — Label state machine" >&2
|
|
171
|
+
echo " commands/review-pr-agents.md — Evidence-Based Review Protocol" >&2
|
|
172
|
+
exit 1
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
echo "OK: No FORGE protocol restatement headings detected in $COMMANDS_DIR"
|
|
176
|
+
exit 0
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# ForgeDock Check Registry
|
|
2
|
+
|
|
3
|
+
The check registry is the feedback edge from review findings back into deterministic quality-gate enforcement. When the same defect class (identified by its `FORGE:PATTERN` tag) recurs 3+ times in a pipeline health window, `/pipeline-health` Phase 4 emits a check-promotion issue. Once the check is written and merged, it is registered here and runs automatically in Step 2 of `/quality-gate`.
|
|
4
|
+
|
|
5
|
+
## How it works
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Review finding filed
|
|
9
|
+
→ FORGE:PATTERN tag added to issue body (review-pr.md Phase 6C)
|
|
10
|
+
→ pipeline-health Phase 4 counts pattern recurrences across issues
|
|
11
|
+
→ at threshold (3+): emits check-promotion issue referencing all source findings
|
|
12
|
+
→ check is written (LLM, once) and placed in scripts/check-registry/
|
|
13
|
+
→ check is registered in manifest.json
|
|
14
|
+
→ quality-gate.md Step 2 runs all registered checks — blocks commit on match
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## manifest.json schema
|
|
18
|
+
|
|
19
|
+
Each entry in the `checks` array:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"slug": "migration-number-collision",
|
|
24
|
+
"description": "Detects duplicate migration number prefixes (e.g. two 0220_*.sql files)",
|
|
25
|
+
"pattern_tag": "migration-number-collision",
|
|
26
|
+
"script": "scripts/check-registry/migration-number-collision.sh",
|
|
27
|
+
"source_findings": ["#1234", "#1298", "#1315"],
|
|
28
|
+
"promoted_at": "2026-07-04",
|
|
29
|
+
"severity": "HIGH",
|
|
30
|
+
"domains": ["DATABASE"]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Fields:
|
|
35
|
+
|
|
36
|
+
| Field | Required | Description |
|
|
37
|
+
|-------|----------|-------------|
|
|
38
|
+
| `slug` | yes | Unique identifier, matches the `FORGE:PATTERN` slug and the script filename |
|
|
39
|
+
| `description` | yes | One sentence: what the check detects |
|
|
40
|
+
| `pattern_tag` | yes | The slug used in `<!-- FORGE:PATTERN: {slug} -->` annotations on finding issues |
|
|
41
|
+
| `script` | yes | Relative path from repo root to the executable check script |
|
|
42
|
+
| `source_findings` | yes | Issue numbers of the review findings that triggered promotion (minimum 3) |
|
|
43
|
+
| `promoted_at` | yes | ISO date when the check was added to the registry |
|
|
44
|
+
| `severity` | yes | `HIGH` (blocks commit) or `MEDIUM` (warning) |
|
|
45
|
+
| `domains` | yes | Quality-gate domain(s) that trigger this check (used for domain-scoped runs) |
|
|
46
|
+
|
|
47
|
+
## Check script contract
|
|
48
|
+
|
|
49
|
+
Each check script:
|
|
50
|
+
|
|
51
|
+
- **Receives**: A space-separated list of changed files on `$1` (same format as `{CHANGED_FILES}` in quality-gate.md), and the worktree path on `$2`.
|
|
52
|
+
- **Exits 0**: No match — check passed.
|
|
53
|
+
- **Exits 1**: Match found — check failed. Print one line per finding to stdout in the format: `{SLUG} | {SEVERITY} | {file:line} | {description}`
|
|
54
|
+
- **Exits 2**: Check not applicable (no relevant files in changeset) — treated as pass.
|
|
55
|
+
- **Runtime**: Must complete in ≤5s for a typical change set. Registry checks add ≤5s total to gate runtime.
|
|
56
|
+
- **No side effects**: Must not write files, network calls, or modify git state.
|
|
57
|
+
|
|
58
|
+
Example output on exit 1:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
migration-number-collision | HIGH | migrations/0220_add_user_table.sql | Duplicate migration prefix 0220 — migrations/0220_existing.sql already uses this prefix
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Adding a new check
|
|
65
|
+
|
|
66
|
+
1. Write `scripts/check-registry/{slug}.sh` following the contract above.
|
|
67
|
+
2. Test it: `bash scripts/check-registry/{slug}.sh "path/to/changed/file" /path/to/repo`
|
|
68
|
+
3. Add an entry to `manifest.json`.
|
|
69
|
+
4. PR and merge — the check runs on all subsequent quality-gate invocations.
|
|
70
|
+
|
|
71
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
72
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|