forgedock 1.1.6 → 1.1.8

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 (43) hide show
  1. package/README.md +3 -1
  2. package/bin/engine/invariants.mjs +361 -0
  3. package/bin/hooks/pre-tool-use.mjs +182 -0
  4. package/bin/journey.mjs +77 -7
  5. package/bin/labels.json +10 -0
  6. package/bin/recall.mjs +540 -0
  7. package/commands/autopilot.md +959 -78
  8. package/commands/cleanup.md +52 -3
  9. package/commands/optimize.md +585 -0
  10. package/commands/orchestrate/phase-1-resolve.md +35 -25
  11. package/commands/orchestrate/phase-3-dependency.md +465 -34
  12. package/commands/orchestrate/phase-4-execution.md +448 -29
  13. package/commands/orchestrate/phase-6-report.md +198 -9
  14. package/commands/pipeline-health/phase-2-metrics.md +305 -1
  15. package/commands/pipeline-health/phase-4-proposals.md +127 -0
  16. package/commands/quality-gate.md +417 -0
  17. package/commands/review-pr.md +391 -13
  18. package/commands/spec-doctor.md +429 -0
  19. package/commands/validate.md +52 -0
  20. package/commands/work-on/build/architect.md +77 -0
  21. package/commands/work-on/build/context.md +357 -22
  22. package/commands/work-on/build/implement.md +2 -0
  23. package/commands/work-on/build/validate.md +28 -0
  24. package/commands/work-on/build.md +44 -0
  25. package/commands/work-on/close.md +621 -8
  26. package/commands/work-on/investigate.md +221 -0
  27. package/commands/work-on.md +15 -14
  28. package/docs/FORGE-PROTOCOL.md +101 -0
  29. package/docs/design/awesome-list-submissions.md +105 -0
  30. package/docs/design/f5bot-monitoring-setup.md +43 -0
  31. package/docs/design/growth-strategy-2026.md +579 -0
  32. package/docs/spec/forge-protocol-v1.md +97 -5
  33. package/docs/spec/label-state-machine.md +6 -1
  34. package/package.json +2 -2
  35. package/packages/protocol/src/cli.js +374 -84
  36. package/packages/protocol/src/types.js +75 -1
  37. package/scripts/build-knowledge-index.mjs +1761 -0
  38. package/scripts/calibration.mjs +996 -0
  39. package/scripts/danger-zones.mjs +782 -0
  40. package/scripts/doctor-pipeline-state.sh +88 -2
  41. package/scripts/refresh-bot-token.sh +97 -0
  42. package/scripts/select-fix-targets.sh +234 -0
  43. package/scripts/transition-label.sh +157 -6
@@ -90,6 +90,171 @@ Print these blocks to stdout before Phase 1A begins. During Phase 1B (step 3 —
90
90
 
91
91
  ---
92
92
 
93
+ ## Phase 0.6: Forge Ledger Pre-Recall <!-- Added: forge#1740 -->
94
+
95
+ **Goal**: Query the Forge Ledger knowledge index for prior cards matching this issue's title terms, affected files, and symbols — **before reading any code**. Inject above-threshold results with explicit delta-verification framing so the investigator builds on prior knowledge rather than re-deriving it.
96
+
97
+ **This phase is non-blocking** — if the index is absent, empty, or returns no match above threshold, log a single line and proceed to Phase 1A. Never stall the pipeline for recall.
98
+
99
+ **Relationship to Phase 0.5**: Phase 0.5 retrieves structured priors from the Gist-based FORGE:MEMORY_INDEX (coarse keyword scoring over MEMORY_ENTRY lines). Phase 0.6 queries the Forge Ledger index (BM25 over structured knowledge cards, indexed by `build-knowledge-index.mjs`). Both are complementary and both run — neither replaces the other.
100
+
101
+ ### Step 1: Probe for index
102
+
103
+ ```bash
104
+ RECALL_PATH="${REPO_PATH:-$(git rev-parse --show-toplevel 2>/dev/null)}/bin/recall.mjs"
105
+ LEDGER_AVAILABLE=0
106
+
107
+ if [ -f "$RECALL_PATH" ]; then
108
+ # Quick probe: does the index exist and have at least one card?
109
+ PROBE=$(node "$RECALL_PATH" --doctor 2>/dev/null | grep "^Total cards:" | grep -v "^Total cards: 0" || true)
110
+ [ -n "$PROBE" ] && LEDGER_AVAILABLE=1
111
+ fi
112
+
113
+ if [ "$LEDGER_AVAILABLE" -eq 0 ]; then
114
+ echo "[recall] Forge Ledger index absent or empty — skipping Phase 0.6, proceeding to Phase 1A"
115
+ # → Continue to Phase 1A
116
+ fi
117
+ ```
118
+
119
+ ### Step 2: Build combined query (title terms + symbols + affected files)
120
+
121
+ Extract query components from the issue body and title. The recall CLI accepts free text (BM25 ranked) plus repeated `--file` flags (exact-match boost):
122
+
123
+ ```bash
124
+ # Extract title keywords: lowercase, remove stop words, keep noun/verb tokens (≥4 chars)
125
+ ISSUE_TITLE=$(gh issue view {NUMBER} {GH_FLAG} --json title --jq '.title' 2>/dev/null || echo '')
126
+ TITLE_TERMS=$(echo "$ISSUE_TITLE" | tr '[:upper:]' '[:lower:]' \
127
+ | sed 's/[^a-z0-9 ]/ /g' \
128
+ | tr ' ' '\n' \
129
+ | grep -E '^[a-z]{4,}$' \
130
+ | grep -vE '^(with|that|this|from|into|have|will|when|then|than|them|they|been|were|also|only|does|some|each|more|over|such|both|most|other|many|after|about|should|would|could|their|these|those|which|where|there|being|while|using|since|until|before|under|above)$' \
131
+ | sort -u | head -10 | tr '\n' ' ' | xargs)
132
+
133
+ # Extract affected files from the issue body's ## Affected Files section
134
+ ISSUE_BODY=$(gh issue view {NUMBER} {GH_FLAG} --json body --jq '.body' 2>/dev/null || echo '')
135
+ AFFECTED_FILES_RAW=$(echo "$ISSUE_BODY" \
136
+ | sed -n '/^## Affected Files/,/^## /p' \
137
+ | grep -oE '`[^`]+\.(md|mjs|js|ts|py|sh|yaml|yml|json)`' \
138
+ | tr -d '`' | sort -u | head -5)
139
+
140
+ # Extract symbols: backtick-quoted identifiers from the issue body (≥4 chars, camelCase or snake_case)
141
+ SYMBOLS_RAW=$(echo "$ISSUE_BODY" \
142
+ | grep -oE '`[A-Za-z_][A-Za-z0-9_]{3,}`' \
143
+ | tr -d '`' | sort -u | head -5)
144
+
145
+ # Build --file flags (one per affected file)
146
+ FILE_FLAGS=""
147
+ while IFS= read -r f; do
148
+ [ -n "$f" ] && FILE_FLAGS="$FILE_FLAGS --file $f"
149
+ done <<< "$AFFECTED_FILES_RAW"
150
+
151
+ # Build --symbol flag (first symbol only — recall supports one --symbol)
152
+ SYMBOL_FLAG=""
153
+ FIRST_SYMBOL=$(echo "$SYMBOLS_RAW" | head -1)
154
+ [ -n "$FIRST_SYMBOL" ] && SYMBOL_FLAG="--symbol $FIRST_SYMBOL"
155
+ ```
156
+
157
+ ### Step 3: Run recall query and capture results
158
+
159
+ ```bash
160
+ RECALL_RESULTS=""
161
+ RECALL_ISSUE_CITATIONS=""
162
+
163
+ if [ "$LEDGER_AVAILABLE" -eq 1 ] && [ -n "$TITLE_TERMS$FILE_FLAGS$SYMBOL_FLAG" ]; then
164
+ echo "[recall] Querying Forge Ledger: terms='${TITLE_TERMS}' files='${AFFECTED_FILES_RAW}' symbol='${FIRST_SYMBOL}'"
165
+
166
+ # Run combined query: title terms (free text) + file flags + symbol + min-score threshold
167
+ # --json for machine-readable output; --min-score 0.3 filters weak matches (noise gate)
168
+ RECALL_JSON=$(node "$RECALL_PATH" \
169
+ $TITLE_TERMS \
170
+ $FILE_FLAGS \
171
+ $SYMBOL_FLAG \
172
+ --k 5 \
173
+ --min-score 0.3 \
174
+ --json \
175
+ 2>/dev/null || echo '[]')
176
+
177
+ # Count results
178
+ RECALL_COUNT=$(echo "$RECALL_JSON" | node -e "
179
+ let d = ''; process.stdin.on('data', c => d += c);
180
+ process.stdin.on('end', () => {
181
+ try { console.log(JSON.parse(d).length); } catch { console.log(0); }
182
+ });
183
+ " 2>/dev/null || echo "0")
184
+
185
+ if [ "${RECALL_COUNT:-0}" -gt 0 ]; then
186
+ echo "[recall] Found ${RECALL_COUNT} prior card(s) above threshold — injecting with delta-verification framing"
187
+
188
+ # Extract issue citations for the Prior Investigations field in the FORGE:INVESTIGATOR comment
189
+ RECALL_ISSUE_CITATIONS=$(echo "$RECALL_JSON" | node -e "
190
+ let d = ''; process.stdin.on('data', c => d += c);
191
+ process.stdin.on('end', () => {
192
+ try {
193
+ const cards = JSON.parse(d);
194
+ const seen = new Set();
195
+ const cites = cards
196
+ .filter(c => { if (seen.has(c.issue)) return false; seen.add(c.issue); return true; })
197
+ .map(c => '#' + c.issue)
198
+ .join(', ');
199
+ console.log(cites);
200
+ } catch { console.log(''); }
201
+ });
202
+ " 2>/dev/null || echo '')
203
+
204
+ # Format cards as human-readable text for injection (not raw JSON)
205
+ RECALL_FORMATTED=$(echo "$RECALL_JSON" | node -e "
206
+ let d = ''; process.stdin.on('data', c => d += c);
207
+ process.stdin.on('end', () => {
208
+ try {
209
+ const cards = JSON.parse(d);
210
+ const lines = [];
211
+ for (const c of cards) {
212
+ lines.push('── ' + c.kind.toUpperCase() + ' from #' + c.issue + ' (score: ' + c.score.toFixed(2) + ') ──');
213
+ if (c.rootCause) lines.push('Root Cause: ' + c.rootCause);
214
+ if (c.prevention) lines.push('Fix/Prevention: ' + c.prevention);
215
+ if (c.pattern) lines.push('Pattern: ' + c.pattern);
216
+ if (c.verdict) lines.push('Verdict: ' + c.verdict + ' (' + (c.confidence || '?') + ')');
217
+ if (c.paths && c.paths.length) lines.push('Files: ' + c.paths.slice(0,3).join(', '));
218
+ }
219
+ console.log(lines.join('\n'));
220
+ } catch (e) { console.log(''); }
221
+ });
222
+ " 2>/dev/null || echo '')
223
+
224
+ # Cap at ≤ 2K chars (same budget as context C0 Gist summaries)
225
+ RECALL_RESULTS=$(echo "$RECALL_FORMATTED" | head -c 2048)
226
+ else
227
+ echo "[recall] No prior cards above threshold (min-score 0.3) — investigating from scratch"
228
+ fi
229
+ fi
230
+ ```
231
+
232
+ ### Step 4: Inject recall results into investigation context
233
+
234
+ If `RECALL_RESULTS` is non-empty, print the following block to stdout **before Phase 1A begins**. The investigation steps in Phase 1B MUST treat this as starting context — verify deltas against current code rather than re-deriving the prior model.
235
+
236
+ **If `RECALL_RESULTS` is empty**: skip this step entirely and proceed to Phase 1A.
237
+
238
+ ```
239
+ [FORGE:RECALL_PRIOR — Forge Ledger pre-recall results]
240
+ Prior cards matched this issue above threshold (min-score 0.3).
241
+
242
+ CRITICAL FRAMING: These cards describe prior findings on the same files/symbols.
243
+ → Verify the deltas against current code — do NOT re-derive the prior model.
244
+ → Stale cards (status: stale) are excluded by default — the query runs without
245
+ --include-stale. Do not treat any card as authoritative without confirming
246
+ the finding still exists in the current code.
247
+ → Cite confirmed priors in the FORGE:INVESTIGATOR "Prior Investigations" field.
248
+
249
+ ${RECALL_RESULTS}
250
+
251
+ [END FORGE:RECALL_PRIOR]
252
+ ```
253
+
254
+ Store `RECALL_ISSUE_CITATIONS` in a variable — it is used in Phase 1C to populate the `**Prior Investigations (via recall)**` field in the FORGE:INVESTIGATOR comment.
255
+
256
+ ---
257
+
93
258
  ## Phase 1A: Load Issue & Check Resume State
94
259
 
95
260
  ```bash
@@ -192,6 +357,20 @@ bash {REPO_PATH}/scripts/code-index.sh query --domain {DOMAIN_LABEL} --repo-path
192
357
 
193
358
  The comment MUST include `<!-- INVESTIGATION:COMPLETE -->` at the very end, AFTER all required sections are present. This marker signals the investigation finished successfully.
194
359
 
360
+ **CODEC PATH (forge#1727)**: Construct the annotation body via the protocol codec — do NOT hand-roll the `<!-- FORGE:INVESTIGATOR -->` header. Use `forge-annotation.sh write INVESTIGATOR --field ...` or `node packages/protocol/src/cli.js emit INVESTIGATOR --field ...` to produce the opening tag and completion sentinel. Fill in the Markdown body sections below. The full pattern:
361
+
362
+ ```bash
363
+ # Build the annotation body via codec (escaping and sentinel handled by codec)
364
+ ANNOTATION_BODY=$(node packages/protocol/src/cli.js emit INVESTIGATOR \
365
+ --field "Verdict={VERDICT}" \
366
+ --field "Confidence={CONFIDENCE}" \
367
+ --field "Severity={SEVERITY}" \
368
+ --field "Task Type={TASK_TYPE}" \
369
+ --field "Decomposition Assessment={YES|NO} — {reason}")
370
+ # ANNOTATION_BODY now has opening tag + required fields + INVESTIGATION:COMPLETE sentinel.
371
+ # Append the Markdown body sections to it before posting.
372
+ ```
373
+
195
374
  Before posting, resolve the attribution annotation link from `forge.yaml`:
196
375
 
197
376
  ```bash
@@ -234,6 +413,7 @@ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:INVESTIGATOR -->
234
413
  **Last touched**: {hash — author — date — subject}
235
414
  **Pickaxe hits (prior fixes / regressions)**: {commit(s) found via \`git log -S\`/\`-G\`, or 'None found' — max 5}
236
415
  {This field is MANDATORY — populate from the git blame + pickaxe commands in step 4/5. If a file is newly created (no history), write 'New file — no history.'}
416
+ **Prior Investigations (via recall)**: {Comma-separated issue citations from \`RECALL_ISSUE_CITATIONS\` (e.g. '#1172, #1243 — building on, not repeating'), or 'None — no Forge Ledger match above threshold' if \`RECALL_RESULTS\` was empty. Use the \`RECALL_ISSUE_CITATIONS\` variable populated in Phase 0.6.}
237
417
 
238
418
  ### Recommendation
239
419
  {what to build/fix, concrete and actionable}
@@ -541,6 +721,47 @@ fi
541
721
 
542
722
  ## Phase 1D: Update Labels & Return Verdict
543
723
 
724
+ ### 1D.0: Finding Lifecycle Label Transition (MANDATORY — run before workflow label update)
725
+
726
+ **Purpose**: Wire the investigation verdict into the finding-validation lifecycle. If the issue under investigation is a review-finding (carries `needs-validation`), translate the verdict into `validated` or `false-positive` using `transition-label.sh --validate`. This is the primary mechanism that resolves the `needs-validation → validated/false-positive` lifecycle gap. <!-- Added: forge#1730 -->
727
+
728
+ **Run this block regardless of verdict (CONFIRMED, PARTIAL, INVALID) — the verdict-to-label mapping handles all cases:**
729
+
730
+ ```bash
731
+ # Check if this issue is a finding awaiting validation
732
+ ISSUE_LABELS=$(gh issue view {NUMBER} {GH_FLAG} --json labels --jq '[.labels[].name] | join(",")' 2>/dev/null || echo "")
733
+
734
+ if echo "$ISSUE_LABELS" | grep -q "needs-validation"; then
735
+ echo "Issue #{NUMBER} has needs-validation — applying verdict label transition..."
736
+ RESOLUTION=$(resolve_script 'transition-label')
737
+ TIER="${RESOLUTION%%:*}"
738
+ SCRIPT_PATH="${RESOLUTION#*:}"
739
+ case "$TIER" in
740
+ adaptive|universal)
741
+ bash "$SCRIPT_PATH" --validate {VERDICT} {NUMBER} {GH_FLAG} || true
742
+ ;;
743
+ prose)
744
+ # Prose fallback: apply label transition directly via gh
745
+ if [ "{VERDICT}" = "CONFIRMED" ]; then
746
+ gh issue edit {NUMBER} {GH_FLAG} --add-label "validated" --remove-label "needs-validation" 2>/dev/null || true
747
+ echo "Applied: needs-validation → validated (verdict: CONFIRMED)"
748
+ else
749
+ gh issue edit {NUMBER} {GH_FLAG} --add-label "false-positive" --remove-label "needs-validation" 2>/dev/null || true
750
+ echo "Applied: needs-validation → false-positive (verdict: {VERDICT})"
751
+ fi
752
+ ;;
753
+ esac
754
+ else
755
+ echo "Issue #{NUMBER} does not have needs-validation — no finding lifecycle transition needed"
756
+ fi
757
+ ```
758
+
759
+ **Verdict → label mapping**: `CONFIRMED` → `validated`; `PARTIAL`, `NOT-CONFIRMED`, `INVALID` → `false-positive`.
760
+
761
+ **Idempotency**: `transition-label.sh --validate` is a no-op if the issue already has `validated` or `false-positive`, or if it lacks `needs-validation`. Safe to call on any issue.
762
+
763
+ ---
764
+
544
765
  **CONFIRMED or PARTIAL with decompose: NO**:
545
766
  ```bash
546
767
  gh issue edit {NUMBER} {GH_FLAG} --add-label "workflow:ready-to-build" --remove-label "workflow:investigating"
@@ -62,6 +62,7 @@ Orchestrator for the full issue lifecycle: investigate → decompose (if needed)
62
62
  - `workflow:merged` label is set
63
63
  - `workflow:invalid` label is set
64
64
  - `needs-human` label is set
65
+ - `workflow:awaiting-merge` label is set (remediated + re-reviewed, awaiting a human merge decision — see #1810) <!-- Added: forge#1810 -->
65
66
  - `workflow:decomposed` label is set (sub-issues spawned)
66
67
  - Issue state is CLOSED with terminal label
67
68
 
@@ -216,7 +217,7 @@ fi
216
217
  Worktree/branch-already-exists and stale-label conditions are surfaced later (Phase 3E worktree creation and the `## Error Handling` section) with their own recovery guidance in `docs/site/troubleshooting.md`.
217
218
 
218
219
  ### 0A: Parse input
219
- Extract project prefix and issue number. If `next`/`pick`: list open issues sorted by priority, skip `needs-human` and `workflow:decomposed`, pick highest priority.
220
+ Extract project prefix and issue number. If `next`/`pick`: list open issues sorted by priority, skip `needs-human`, `workflow:decomposed`, and `workflow:awaiting-merge`, pick highest priority.
220
221
 
221
222
  **Optional pre-flight**: Before committing to the full pipeline, run `/scope {NUMBER}` to get a complexity estimate (affected files, blast radius, risk flags, and decomposition recommendation). Especially useful for large or ambiguous issues.
222
223
 
@@ -234,7 +235,7 @@ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:HEARTBEAT -->
234
235
 
235
236
  **Also post at major phase entry points** (Phases 1, 3, and 5) — replace `Phase 0` with the correct phase name in each case. These mid-pipeline heartbeats ensure the stall detector sees recent activity during long phases (e.g., a build phase running for 20 minutes is not falsely classified as stalled). Inline snippets are embedded at Phase 1A, Phase 3A, and Phase 5A — agents resuming mid-pipeline encounter them without reading this section. <!-- Added: forge#740 -->
236
237
 
237
- **Skip if**: Issue already has a terminal label (`workflow:merged`, `workflow:invalid`, `needs-human`) — no heartbeat needed on a completed issue.
238
+ **Skip if**: Issue already has a terminal label (`workflow:merged`, `workflow:invalid`, `needs-human`, `workflow:awaiting-merge`) — no heartbeat needed on a completed issue.
238
239
 
239
240
  ### 0B: Load issue + existing context
240
241
  ```bash
@@ -242,7 +243,7 @@ gh issue view {NUMBER} {GH_FLAG} --json number,title,body,labels,state,comments,
242
243
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments --jq '.[] | {id: .id, author: .user.login, body: .body}'
243
244
  ```
244
245
 
245
- **Check**: state (closed → STOP), terminal labels (`workflow:merged`/`workflow:invalid` → STOP), existing agent comments (`FORGE:INVESTIGATOR`, `FORGE:DECOMPOSED`, `FORGE:CONTRACT`, `FORGE:BUILDER`, `FORGE:TRAJECTORY`, `FORGE:DECISION_RECORD`), parent tracker status, sub-issue status.
246
+ **Check**: state (closed → STOP), terminal labels (`workflow:merged`/`workflow:invalid`/`workflow:awaiting-merge` → STOP), existing agent comments (`FORGE:INVESTIGATOR`, `FORGE:DECOMPOSED`, `FORGE:CONTRACT`, `FORGE:BUILDER`, `FORGE:TRAJECTORY`, `FORGE:DECISION_RECORD`), parent tracker status, sub-issue status.
246
247
 
247
248
  **Determine resume point**: No comments → Phase 1. Investigation exists + ready-to-build → Phase 3. Builder:COMPLETE + no PR → Phase 4. Builder without :COMPLETE (partial/interrupted build) + no PR → Phase 3 (partial-build cleanup). Builder + PR open → Phase 5. PR merged + issue open → Phase 6.
248
249
 
@@ -471,12 +472,12 @@ case "$TIER" in
471
472
  adaptive|universal) bash "$SCRIPT_PATH" {NUMBER} {GH_FLAG} investigating ;;
472
473
  prose)
473
474
  gh issue edit {NUMBER} {GH_FLAG} --add-label "workflow:investigating" \
474
- --remove-label "workflow:ready-to-build,workflow:building,workflow:in-review,workflow:merged,workflow:invalid,workflow:decomposed" 2>/dev/null || true
475
+ --remove-label "workflow:ready-to-build,workflow:building,workflow:in-review,workflow:awaiting-merge,workflow:merged,workflow:invalid,workflow:decomposed" 2>/dev/null || true
475
476
  ;;
476
477
  esac
477
478
  ```
478
479
 
479
- **Post Phase 1 heartbeat** (skip if issue already has a terminal label — `workflow:merged`, `workflow:invalid`, `needs-human`):
480
+ **Post Phase 1 heartbeat** (skip if issue already has a terminal label — `workflow:merged`, `workflow:invalid`, `needs-human`, `workflow:awaiting-merge`):
480
481
  ```bash
481
482
  PHASE_START_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
482
483
  gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:HEARTBEAT -->
@@ -748,7 +749,7 @@ case "$TIER" in
748
749
  adaptive|universal) bash "$SCRIPT_PATH" {NUMBER} {GH_FLAG} ready-to-build ;;
749
750
  prose)
750
751
  gh issue edit {NUMBER} {GH_FLAG} --add-label "workflow:ready-to-build" \
751
- --remove-label "workflow:investigating,workflow:building,workflow:in-review,workflow:merged,workflow:invalid,workflow:decomposed" 2>/dev/null || true
752
+ --remove-label "workflow:investigating,workflow:building,workflow:in-review,workflow:awaiting-merge,workflow:merged,workflow:invalid,workflow:decomposed" 2>/dev/null || true
752
753
  ;;
753
754
  esac
754
755
  ```
@@ -797,7 +798,7 @@ case "$TIER" in
797
798
  adaptive|universal) bash "$SCRIPT_PATH" {NUMBER} {GH_FLAG} decomposed ;;
798
799
  prose)
799
800
  gh issue edit {NUMBER} {GH_FLAG} --add-label "workflow:decomposed" \
800
- --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:in-review,workflow:merged,workflow:invalid" 2>/dev/null || true
801
+ --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:in-review,workflow:awaiting-merge,workflow:merged,workflow:invalid" 2>/dev/null || true
801
802
  ;;
802
803
  esac
803
804
  ```
@@ -821,7 +822,7 @@ case "$TIER" in
821
822
  adaptive|universal) bash "$SCRIPT_PATH" {NUMBER} {GH_FLAG} invalid ;;
822
823
  prose)
823
824
  gh issue edit {NUMBER} {GH_FLAG} --add-label "workflow:invalid" \
824
- --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:in-review,workflow:merged,workflow:decomposed" 2>/dev/null || true
825
+ --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:in-review,workflow:awaiting-merge,workflow:merged,workflow:decomposed" 2>/dev/null || true
825
826
  ;;
826
827
  esac
827
828
  gh issue close {NUMBER} {GH_FLAG} --comment "Closing as invalid: {reason from investigation}"
@@ -927,7 +928,7 @@ case "$TIER" in
927
928
  adaptive|universal) bash "$SCRIPT_PATH" {NUMBER} {GH_FLAG} decomposed ;;
928
929
  prose)
929
930
  gh issue edit {NUMBER} {GH_FLAG} --add-label "workflow:decomposed" \
930
- --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:in-review,workflow:merged,workflow:invalid" 2>/dev/null || true
931
+ --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:in-review,workflow:awaiting-merge,workflow:merged,workflow:invalid" 2>/dev/null || true
931
932
  ;;
932
933
  esac
933
934
  ```
@@ -958,7 +959,7 @@ fi
958
959
 
959
960
  ### 3A: Re-read state from GitHub (MANDATORY)
960
961
 
961
- **Post Phase 3 heartbeat** (skip if issue already has a terminal label — `workflow:merged`, `workflow:invalid`, `needs-human`):
962
+ **Post Phase 3 heartbeat** (skip if issue already has a terminal label — `workflow:merged`, `workflow:invalid`, `needs-human`, `workflow:awaiting-merge`):
962
963
  ```bash
963
964
  PHASE_START_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
964
965
  gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:HEARTBEAT -->
@@ -1262,7 +1263,7 @@ case "$TIER" in
1262
1263
  adaptive|universal) bash "$SCRIPT_PATH" {NUMBER} {GH_FLAG} building ;;
1263
1264
  prose)
1264
1265
  gh issue edit {NUMBER} {GH_FLAG} --add-label "workflow:building" \
1265
- --remove-label "workflow:investigating,workflow:ready-to-build,workflow:in-review,workflow:merged,workflow:invalid,workflow:decomposed" 2>/dev/null || true
1266
+ --remove-label "workflow:investigating,workflow:ready-to-build,workflow:in-review,workflow:awaiting-merge,workflow:merged,workflow:invalid,workflow:decomposed" 2>/dev/null || true
1266
1267
  ;;
1267
1268
  esac
1268
1269
  ```
@@ -1768,7 +1769,7 @@ case "$TIER" in
1768
1769
  adaptive|universal) bash "$SCRIPT_PATH" {NUMBER} {GH_FLAG} in-review ;;
1769
1770
  prose)
1770
1771
  gh issue edit {NUMBER} {GH_FLAG} --add-label "workflow:in-review" \
1771
- --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:merged,workflow:invalid,workflow:decomposed" 2>/dev/null || true
1772
+ --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:awaiting-merge,workflow:merged,workflow:invalid,workflow:decomposed" 2>/dev/null || true
1772
1773
  ;;
1773
1774
  esac
1774
1775
  ```
@@ -1779,7 +1780,7 @@ esac
1779
1780
 
1780
1781
  ### 5A: Re-read state from GitHub (MANDATORY)
1781
1782
 
1782
- **Post Phase 5 heartbeat** (skip if issue already has a terminal label — `workflow:merged`, `workflow:invalid`, `needs-human`):
1783
+ **Post Phase 5 heartbeat** (skip if issue already has a terminal label — `workflow:merged`, `workflow:invalid`, `needs-human`, `workflow:awaiting-merge`):
1783
1784
  ```bash
1784
1785
  PHASE_START_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
1785
1786
  gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:HEARTBEAT -->
@@ -1924,7 +1925,7 @@ case "$TIER" in
1924
1925
  adaptive|universal) bash "$SCRIPT_PATH" {NUMBER} {GH_FLAG} merged ;;
1925
1926
  prose)
1926
1927
  gh issue edit {NUMBER} {GH_FLAG} --add-label "workflow:merged" \
1927
- --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:in-review,workflow:invalid,workflow:decomposed" 2>/dev/null || true
1928
+ --remove-label "workflow:investigating,workflow:ready-to-build,workflow:building,workflow:in-review,workflow:awaiting-merge,workflow:invalid,workflow:decomposed" 2>/dev/null || true
1928
1929
  ;;
1929
1930
  esac
1930
1931
  ```
@@ -13,3 +13,104 @@
13
13
  > and usable in any product with attribution. This older draft was mistakenly
14
14
  > marked AGPL-3.0; the protocol description itself has always been intended for
15
15
  > open, license-compatible adoption.
16
+
17
+ ---
18
+
19
+ ## Forge Ledger — Derived Artifact of the Protocol
20
+
21
+ The **Forge Ledger** is the persistent, file/symbol-keyed knowledge index built from FORGE
22
+ annotations. It is a _derived artifact_ of the protocol: the ledger is rebuilt by re-parsing
23
+ the annotation corpus on GitHub (source of truth), not by maintaining separate authoritative
24
+ state.
25
+
26
+ ### Architecture
27
+
28
+ ```
29
+ GitHub Issues/PRs (annotation corpus, source of truth)
30
+ │
31
+ ▼
32
+ scripts/build-knowledge-index.mjs ← incremental indexer (watermarked by issue.updated_at)
33
+ │ uses packages/protocol/src/parse.js (FORGE annotation parser)
34
+ ▼
35
+ ~/.forge/index/
36
+ knowledge.jsonl ← card records (one JSON per line, keyed by issue/kind/seq)
37
+ postings.json ← BM25-lite inverted index (term → card IDs with per-field tf)
38
+ manifest.json ← issue → content-hash map + watermark + card count
39
+ renames.jsonl ← git rename log (old path → new path for query-time resolution)
40
+ │
41
+ ▼ (mirrored to orphan branch)
42
+ forge-knowledge branch ← versioned, diffable, hydratable by any clone or CI
43
+ ```
44
+
45
+ ### Card Schema
46
+
47
+ Cards are keyed by provenance (`{issue}/{kind}/{seq}`), never by file path. Paths are
48
+ attributes maintained by the indexer; renames are metadata updates, not re-keys.
49
+
50
+ ```json
51
+ {
52
+ "schemaVersion": 1,
53
+ "id": "1370/pattern/0",
54
+ "kind": "pattern",
55
+ "issue": 1370,
56
+ "pattern": "...",
57
+ "rootCause": "...",
58
+ "prevention": "...",
59
+ "paths": ["bin/runner.mjs"],
60
+ "symbols": ["scrubEnv"],
61
+ "anchor": { "path": "bin/runner.mjs", "symbol": "scrubEnv" },
62
+ "status": "fresh",
63
+ "createdAt": "2026-07-04"
64
+ }
65
+ ```
66
+
67
+ ### CLI
68
+
69
+ ```
70
+ # Query by file path (exact lookup):
71
+ forge recall --file bin/runner.mjs --json
72
+
73
+ # Query by symbol:
74
+ forge recall --symbol scrubEnv --json
75
+
76
+ # Free-text BM25 search:
77
+ forge recall "env scrub proc environ" --k 5
78
+
79
+ # Index health:
80
+ forge recall --doctor
81
+
82
+ # Rebuild index from scratch:
83
+ node scripts/build-knowledge-index.mjs --full-rebuild
84
+
85
+ # Incremental update (used by close phase):
86
+ node scripts/build-knowledge-index.mjs --issue {NUMBER}
87
+ ```
88
+
89
+ ### Invariants
90
+
91
+ - **Full rebuild = incremental parity**: running a full rebuild produces byte-identical
92
+ card content to a sequence of incremental runs over the same issue range.
93
+ - **Idempotency**: re-indexing the same issue twice produces the same card content (card IDs
94
+ are deterministic; content is a pure function of current annotation state).
95
+ - **GitHub wins**: the index is always rebuildable from the annotation corpus alone. Deleting
96
+ `~/.forge/index/` loses nothing — a rebuild restores the same state.
97
+ - **Non-blocking**: ledger indexing at close time never stalls the pipeline. Failure is logged
98
+ and the close phase continues.
99
+
100
+ ### Staleness Detection (tiered, cheapest first)
101
+
102
+ 1. Current blob sha of `anchor.path` matches stored blob sha → **FRESH**
103
+ 2. `anchor.symbol` is still defined in the current file → **FRESH**
104
+ 3. Rolling-hash scan finds `snippetHash` elsewhere in file → **MOVED** (re-anchor)
105
+ 4. `snippetHash` found in a file touched by rename log → **MOVED** (re-anchor path)
106
+ 5. Otherwise → **STALE** (excluded from binding injection; recallable with `--include-stale`)
107
+
108
+ ### Integration Points
109
+
110
+ - **`commands/work-on/build/context.md` Phase C1**: uses `forge recall --file` for exact
111
+ file-path lookup; falls back to live `gh issue list --search` when index is absent.
112
+ - **`commands/work-on/close.md` Phase C5.3**: calls `build-knowledge-index.mjs --issue`
113
+ after merge to index the just-closed issue; advances watermark.
114
+
115
+ See issue [#1732](https://github.com/RapierCraftStudios/ForgeDock/issues/1732) for the
116
+ implementation history and design decisions.
@@ -0,0 +1,105 @@
1
+ # Awesome List Submission Drafts
2
+
3
+ Important: Have a contributor or community member submit these, not the repo owner's account. Many lists reject self-submissions.
4
+
5
+ ---
6
+
7
+ ## 1. hesreallyhim/awesome-claude-code (36.8K stars) — TOP PRIORITY
8
+
9
+ ### PR Title
10
+ ```
11
+ Add ForgeDock — autonomous pipeline commands for Claude Code
12
+ ```
13
+
14
+ ### Entry (add under "Workflow & Automation" or "Agent Frameworks" section)
15
+
16
+ ```markdown
17
+ - [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) - Structured autonomous development pipeline that adds investigate-build-review-merge workflow to Claude Code. Features 9-agent specialist PR review, 14-domain quality gate, and GitHub-native persistent memory via FORGE annotations. `npx forgedock`
18
+ ```
19
+
20
+ ### PR Description
21
+
22
+ ```markdown
23
+ Adding ForgeDock, an open-source (AGPL) tool that adds structured pipeline commands to Claude Code.
24
+
25
+ **What it does**: Turns Claude Code from a stateless chatbot into a multi-stage development pipeline. Each stage (investigate, build, review, merge) posts machine-readable annotations to GitHub issues/PRs, so agents reconstruct full context after compaction.
26
+
27
+ **Key features**:
28
+ - 20+ slash commands including `/work-on` (full pipeline), `/orchestrate` (parallel multi-issue), `/autopilot` (self-improvement cycle)
29
+ - 9-agent specialist PR review (security, database, auth, concurrency, etc.)
30
+ - 14-domain quality gate
31
+ - GitHub labels as workflow state machine
32
+ - `forge.yaml` per-repo configuration
33
+
34
+ **Install**: `npx forgedock`
35
+
36
+ **Why it belongs here**: It's the most comprehensive pipeline orchestration system in the Claude Code ecosystem — 35 command files totaling 800KB+ of structured prompt engineering.
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 2. rohitg00/awesome-claude-code-toolkit
42
+
43
+ ### Entry
44
+
45
+ ```markdown
46
+ ### Pipeline Orchestration
47
+ - [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) - Full SDLC pipeline for Claude Code: investigate → build → review → merge. 9-agent review, quality gate, GitHub-native memory via FORGE annotations. `npx forgedock`
48
+ ```
49
+
50
+ ---
51
+
52
+ ## 3. travisvn/awesome-claude-skills
53
+
54
+ ### Entry
55
+
56
+ ```markdown
57
+ - [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) - 20+ pipeline commands: `/work-on` (full pipeline), `/orchestrate` (parallel issues), `/review-pr` (9-agent review), `/autopilot` (self-improvement), `/quality-gate` (14-domain checks). Uses GitHub as persistent knowledge graph.
58
+ ```
59
+
60
+ ---
61
+
62
+ ## 4. ComposioHQ/awesome-claude-skills
63
+
64
+ ### Entry
65
+
66
+ ```markdown
67
+ - [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) - Autonomous development pipeline commands for Claude Code. Structured investigate-build-review-merge workflow with GitHub-native memory, multi-agent review, and quality gates.
68
+ ```
69
+
70
+ ---
71
+
72
+ ## 5. VoltAgent/awesome-agent-skills
73
+
74
+ ### Entry
75
+
76
+ ```markdown
77
+ - [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) - Structured autonomous dev pipeline for Claude Code agents. Uses GitHub Issues/PRs as a knowledge graph with machine-readable FORGE annotations for inter-agent context passing. 35 command specs covering the full SDLC.
78
+ ```
79
+
80
+ ---
81
+
82
+ ## 6. Broader awesome lists
83
+
84
+ ### awesome-ai-agents
85
+
86
+ ```markdown
87
+ - [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) - Open-source pipeline orchestrator for AI coding agents. Structures investigate → build → review → merge workflow using GitHub as a persistent knowledge graph. Currently supports Claude Code; multi-model planned.
88
+ ```
89
+
90
+ ### awesome-developer-tools
91
+
92
+ ```markdown
93
+ - [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) - Autonomous development pipeline that adds structured workflow commands to Claude Code. 9-agent PR review, 14-domain quality gate, GitHub-native memory. `npx forgedock`
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Submission Checklist
99
+
100
+ - [ ] Check each list's CONTRIBUTING.md for formatting requirements
101
+ - [ ] Ensure the entry follows the list's existing style (alphabetical? categorized?)
102
+ - [ ] One PR per list
103
+ - [ ] Submitter should have some GitHub activity (not a brand new account)
104
+ - [ ] Don't submit all on the same day — space them out over 1-2 weeks
105
+ - [ ] Priority order: awesome-claude-code first, then toolkit, then skills lists, then broader lists
@@ -0,0 +1,43 @@
1
+ # F5Bot Mention Monitoring Setup
2
+
3
+ F5Bot is a free service that sends email alerts when keywords appear on Reddit, Hacker News, or Lobsters.
4
+
5
+ ## Setup (5 minutes)
6
+
7
+ 1. Go to https://f5bot.com
8
+ 2. Create a free account (email only)
9
+ 3. Add these keyword alerts:
10
+
11
+ | Keyword | Why |
12
+ |---------|-----|
13
+ | `forgedock` | Direct mentions |
14
+ | `ForgeDock` | Case-sensitive variant |
15
+ | `forge dock` | Common misspelling |
16
+ | `"claude code commands"` | Users looking for what ForgeDock provides |
17
+ | `"claude code workflow"` | High-intent search phrase |
18
+ | `"autonomous development pipeline"` | Category-level interest |
19
+ | `"FORGE annotation"` | Protocol mentions |
20
+
21
+ 4. Set email notifications to immediate (not digest)
22
+
23
+ ## Response Playbook
24
+
25
+ When an alert fires:
26
+
27
+ ### Direct mention (someone talking about ForgeDock)
28
+ - Read the full thread context
29
+ - If positive: thank them, offer to help with any questions
30
+ - If a question: answer thoroughly with code examples
31
+ - If criticism: acknowledge, explain the reasoning, ask what they'd improve
32
+
33
+ ### Indirect mention (someone looking for what ForgeDock does)
34
+ - Answer their question genuinely first
35
+ - Mention ForgeDock naturally: "I've been using ForgeDock for this — it structures Claude Code into an investigate-build-review-merge pipeline"
36
+ - Never just drop a link with no context
37
+
38
+ ### Rules
39
+ - Always add genuine value to the conversation
40
+ - Never post in threads where it would feel forced
41
+ - On Reddit: post manually (never automate — ban risk)
42
+ - On HN: only comment if you have genuine insight to add
43
+ - Wait at least 10 minutes after the alert before responding (don't look like a bot)