forgedock 1.1.1 → 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 +53 -8
- package/bin/batch-runner.mjs +339 -0
- package/bin/demo.mjs +92 -7
- package/bin/engine/phases.mjs +20 -0
- package/bin/engine/state.mjs +8 -3
- package/bin/engine-cli.mjs +177 -5
- package/bin/forgedock.mjs +409 -26
- 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 +72 -14
- package/bin/registry.mjs +139 -0
- package/bin/report.mjs +447 -0
- package/bin/runner.mjs +68 -19
- package/bin/settings-hook.mjs +235 -1
- 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 +80 -8
- 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 +58 -1
- package/commands/design-bench.md +5 -1
- package/commands/design-render-critique-loop.md +1 -1
- package/commands/diagnose.md +2 -1
- package/commands/explain.md +2 -1
- package/commands/forge-stats.md +121 -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 +23 -2
- 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 -2045
- 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 +248 -10
- 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 +591 -52
- 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 +3 -1
- package/commands/work-on/build/validate.md +26 -7
- package/commands/work-on/build.md +163 -24
- package/commands/work-on/close.md +130 -3
- package/commands/work-on/decompose.md +19 -1
- package/commands/work-on/investigate.md +117 -2
- package/commands/work-on/review.md +24 -4
- package/commands/work-on-monolithic.md +7 -2
- package/commands/work-on.md +202 -4
- package/docs/BRAND.md +14 -7
- package/docs/CI.md +2 -2
- package/docs/CODEX.md +36 -1
- package/docs/CONFIG.md +5 -8
- 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 +43 -4
- package/docs/site/github-is-the-memory.md +113 -0
- package/docs/site/how-it-works.md +3 -13
- package/docs/site/index.md +9 -1
- 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/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 +3 -1
- 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/worktree-lifecycle.sh +3 -3
- package/templates/devdocs/agent/using-forgedock.md +14 -0
- package/docs/site/.vitepress/config.mjs +0 -85
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
install: internal
|
|
3
|
+
---
|
|
4
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
6
|
+
|
|
7
|
+
# /orchestrate — Phase 2: Investigation-First Triage
|
|
8
|
+
|
|
9
|
+
## Phase 2: Investigation-First Triage
|
|
10
|
+
|
|
11
|
+
**Purpose**: Investigation issues produce NEW GitHub issues as their output. If the batch contains investigations, they must run FIRST so their output can be folded into the execution plan.
|
|
12
|
+
|
|
13
|
+
**If no investigations are found in Step 2A, skip this entire phase and proceed directly to Phase 3.**
|
|
14
|
+
|
|
15
|
+
### Step 2A: Classify each issue
|
|
16
|
+
|
|
17
|
+
For each issue in the resolved set, read its title and body to classify it:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
for NUM in {issue_numbers}; do
|
|
21
|
+
gh issue view $NUM --json title,body,labels --jq '{title: .title, labels: [.labels[].name], body_preview: (.body[:500])}'
|
|
22
|
+
done
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Classification rules:**
|
|
26
|
+
|
|
27
|
+
| Signal | Classification |
|
|
28
|
+
|--------|---------------|
|
|
29
|
+
| Title contains "Investigate", "Audit", "Research", "Evaluate", "Assess", "Deep dive" | **Investigation** |
|
|
30
|
+
| Issue body is primarily questions (`- [ ]` checklist) with no concrete code changes | **Investigation** |
|
|
31
|
+
| Issue body says "Deliverable: execution plan" or "create issues" | **Investigation** |
|
|
32
|
+
| Issue has `enhancement` label + title starts with "Enable" + body describes toggling a feature flag | **Implementation** |
|
|
33
|
+
| Issue has `bug`, `refactor`, `dead-code`, or `feature` label | **Implementation** |
|
|
34
|
+
|
|
35
|
+
Tag each issue internally as `INVESTIGATION` or `IMPLEMENTATION`.
|
|
36
|
+
|
|
37
|
+
### Step 2B: Run investigations first (Wave 0)
|
|
38
|
+
|
|
39
|
+
If ANY issues are classified as `INVESTIGATION`:
|
|
40
|
+
|
|
41
|
+
1. **Move them to Wave 0** — they run BEFORE all implementation issues
|
|
42
|
+
2. **Spawn Wave 0 agents** using the same agent template as Phase 4A, but emphasize that `/work-on` will detect the investigation task type and produce issues (not code)
|
|
43
|
+
3. **Wait for ALL Wave 0 agents to complete** before proceeding to Phase 3
|
|
44
|
+
|
|
45
|
+
### Step 2C: Collect newly created issues
|
|
46
|
+
|
|
47
|
+
After Wave 0 completes, each investigation agent will have created new GitHub issues. Collect them:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# For each investigation issue that completed successfully:
|
|
51
|
+
# Read the FORGE:BUILDER comment to find created issue numbers
|
|
52
|
+
for INV_NUM in {investigation_numbers}; do
|
|
53
|
+
gh api repos/{GH_REPO}/issues/${INV_NUM}/comments \
|
|
54
|
+
--jq '.[] | select(.body | contains("<!-- FORGE:BUILDER -->")) | .body' \
|
|
55
|
+
| grep -oP '#\K\d+' | sort -u
|
|
56
|
+
done
|
|
57
|
+
|
|
58
|
+
# Also check: if the investigation issue had a milestone, the new issues should too
|
|
59
|
+
# Verify milestone assignment:
|
|
60
|
+
for NEW_NUM in {newly_created_numbers}; do
|
|
61
|
+
gh issue view $NEW_NUM --json milestone --jq '.milestone.title // "NO MILESTONE"'
|
|
62
|
+
done
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Step 2C.5: Collect Knowledge Gist URLs from investigations
|
|
66
|
+
|
|
67
|
+
For each completed investigation issue, query its comments for `FORGE:KNOWLEDGE_GIST` annotations. Store the mapping of investigation issue number → Gist URL(s) so the agent template in Step 4A can include prior investigation context.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Build a map: investigation_number → gist_url(s)
|
|
71
|
+
declare -A INVESTIGATION_GISTS
|
|
72
|
+
for INV_NUM in {investigation_numbers}; do
|
|
73
|
+
GIST_URLS=$(gh api repos/{GH_REPO}/issues/${INV_NUM}/comments \
|
|
74
|
+
--jq '[.[] | select(.body | test("<!-- FORGE:KNOWLEDGE_GIST: https://")) | .body | capture("<!-- FORGE:KNOWLEDGE_GIST: (?<url>https://[^ ]+) -->").url] | unique | .[]')
|
|
75
|
+
if [ -n "$GIST_URLS" ]; then
|
|
76
|
+
INVESTIGATION_GISTS[$INV_NUM]="$GIST_URLS"
|
|
77
|
+
echo "Investigation #${INV_NUM}: found Gist URL(s)"
|
|
78
|
+
fi
|
|
79
|
+
done
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
When spawning agents for implementation issues in Step 4A, include any Gist URLs from parent/sibling investigations in the agent prompt's context block. See the `{GIST_CONTEXT}` variable in the agent template.
|
|
83
|
+
|
|
84
|
+
**Milestone index Gist**: If the milestone has a `<!-- FORGE:MILESTONE_INDEX: {url} -->` annotation in its description, read the index URL and store it for inclusion in agent context. The milestone index aggregates all investigation Gist URLs for the milestone into a single reference.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Read milestone index URL from milestone description (if milestone exists)
|
|
88
|
+
MILESTONE_INDEX_URL=""
|
|
89
|
+
if [ -n "$MILESTONE_NUM" ]; then
|
|
90
|
+
MILESTONE_DESC=$(gh api repos/{GH_REPO}/milestones/${MILESTONE_NUM} --jq '.description // ""' 2>/dev/null)
|
|
91
|
+
MILESTONE_INDEX_URL=$(echo "$MILESTONE_DESC" | grep -oP '(?<=<!-- FORGE:MILESTONE_INDEX: )https://[^ ]+(?= -->)' | head -1)
|
|
92
|
+
if [ -n "$MILESTONE_INDEX_URL" ]; then
|
|
93
|
+
echo "Milestone index Gist found: ${MILESTONE_INDEX_URL}"
|
|
94
|
+
fi
|
|
95
|
+
fi
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Step 2D: Merge new issues into the batch
|
|
99
|
+
|
|
100
|
+
Add the newly created issues to the issue set. Re-check each one:
|
|
101
|
+
- Filter out any that are already ineligible (same rules as Phase 1)
|
|
102
|
+
- Tag them as `IMPLEMENTATION` (investigations don't spawn more investigations)
|
|
103
|
+
- They inherit the milestone from their parent investigation if applicable
|
|
104
|
+
|
|
105
|
+
**Issue body standard**: Any new issues created by investigation agents MUST use the **Pipeline Issue Template** from `issue.md` Phase 3D as their body structure. Investigation agents that produce issues as output should be prompted to use that template — not ad-hoc body formats — so every spawned issue enters the pipeline with the correct structure (Problem, Root Cause, Affected Files, Acceptance Criteria). Verify spawned issues have all mandatory sections before adding them to the batch; if sections are missing, the `/issue` body-validation step (Phase 4C.5) will repair them. <!-- Added: forge#293 -->
|
|
106
|
+
|
|
107
|
+
**Updated issue set** = original `IMPLEMENTATION` issues + newly spawned issues from investigations.
|
|
108
|
+
|
|
109
|
+
### Step 2E: Report Wave 0 results to user
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
## Wave 0: Investigations Complete
|
|
113
|
+
|
|
114
|
+
| # | Investigation | Result | Issues Created |
|
|
115
|
+
|---|--------------|--------|---------------|
|
|
116
|
+
| #{INV1} | {title} | ✓ Closed | #{N1}, #{N2}, #{N3} |
|
|
117
|
+
| #{INV2} | {title} | ✓ Closed | #{N4}, #{N5} |
|
|
118
|
+
|
|
119
|
+
**New issues added to batch**: {count}
|
|
120
|
+
**Updated total**: {original_count} → {new_total} issues
|
|
121
|
+
|
|
122
|
+
Proceeding to dependency analysis with the expanded issue set...
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
install: internal
|
|
3
|
+
---
|
|
4
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
6
|
+
|
|
7
|
+
# /orchestrate — Phase 2.5: Investigation Synthesis
|
|
8
|
+
|
|
9
|
+
## Phase 2.5: Investigation Synthesis
|
|
10
|
+
|
|
11
|
+
<!-- Added: forge#1192 -->
|
|
12
|
+
|
|
13
|
+
**Purpose**: Reconcile *competing recommendations* across investigation outputs BEFORE they fan out to implementation agents. Phase 3's conflict detection (Step 3C) deconflicts issues at the **file** layer only — it prevents git merge conflicts. It performs **zero semantic deconfliction**: two issues can touch entirely different files while proposing **contradictory approaches to the same problem**, and the file-overlap detector passes both straight to parallel dispatch. This phase closes that gap by clustering investigations semantically (by target subsystem, not by file) and arbitrating incompatible plans into a single decision — or serializing them so the second agent inherits the first's decision.
|
|
14
|
+
|
|
15
|
+
**This phase operates ONLY on FORGE annotations and issue bodies. It NEVER reads code, and it NEVER closes, skips, or merges issues.** Reconciling plans/annotations is distinct from adjudicating *duplicate validity* (Safety Rule 9, the #3842/#4039 scar): the anti-dedup rule forbids the orchestrator from deciding two issues are the same bug and closing one — that call belongs to `/work-on` investigation agents examining actual code. Plan reconciliation touches neither code nor issue state; it only writes a synthesis brief annotation and adds `Depends on #X` serialization edges. It therefore does not violate Hard Rule 2 (dispatcher, not builder) or Safety Rule 9.
|
|
16
|
+
|
|
17
|
+
**No-op guard**: This entire phase is skipped when the batch contains **0 or 1 investigations** — there is nothing to reconcile against. Proceed directly to Phase 3.
|
|
18
|
+
|
|
19
|
+
### Step 2.5A: No-op guard
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Count investigations that completed in Wave 0 (Phase 2), regardless of whether each
|
|
23
|
+
# emitted a Knowledge Gist. Use the full completed-investigation set (the same
|
|
24
|
+
# {investigation_numbers} that Steps 2C.5, 2.5B and 2.5C iterate) — NOT the
|
|
25
|
+
# INVESTIGATION_GISTS map, which only holds gist-producing investigations and would
|
|
26
|
+
# undercount when a genuine investigation reached a recommendation without a gist.
|
|
27
|
+
# If < 2, skip synthesis entirely.
|
|
28
|
+
INVESTIGATION_NUMS=( {investigation_numbers} )
|
|
29
|
+
INVESTIGATION_COUNT=${#INVESTIGATION_NUMS[@]}
|
|
30
|
+
if [ "$INVESTIGATION_COUNT" -lt 2 ]; then
|
|
31
|
+
echo "Phase 2.5 skipped: ${INVESTIGATION_COUNT} investigation(s) in batch — nothing to reconcile. Proceeding to Phase 3."
|
|
32
|
+
SYNTHESIS_RAN=false
|
|
33
|
+
RECONCILED_COUNT=0
|
|
34
|
+
# Skip to Phase 3.
|
|
35
|
+
else
|
|
36
|
+
SYNTHESIS_RAN=true
|
|
37
|
+
fi
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If `SYNTHESIS_RAN` is false, do NOT execute Steps 2.5B–2.5D — proceed directly to Phase 3. Step 4A's `{GIST_CONTEXT}` generation will fall back to the existing raw-gist behavior (no synthesis brief exists).
|
|
41
|
+
|
|
42
|
+
### Step 2.5B: Cluster investigations by target subsystem
|
|
43
|
+
|
|
44
|
+
For each investigation that completed in Wave 0, read its `FORGE:INVESTIGATOR` comment (and the newly spawned implementation issue bodies from Step 2D) and extract its **Recommendation** and **Affected Files / target subsystem** — NOT to compare files for merge conflicts, but to group investigations that operate on the **same conceptual surface** (e.g. "auth session lifecycle", "credit metering", "orchestrate DAG construction").
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# For each investigation, pull its recommendation + affected-files block (annotations only — no code reads)
|
|
48
|
+
declare -A INV_RECOMMENDATION
|
|
49
|
+
declare -A INV_SUBSYSTEM
|
|
50
|
+
for INV_NUM in {investigation_numbers}; do
|
|
51
|
+
INV_BODY=$(gh api repos/{GH_REPO}/issues/${INV_NUM}/comments \
|
|
52
|
+
--jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body' 2>/dev/null | head -1)
|
|
53
|
+
# Extract the Recommendation section (annotation prose only)
|
|
54
|
+
INV_RECOMMENDATION[$INV_NUM]=$(echo "$INV_BODY" | awk '/^### Recommendation/{p=1;next}/^### /{p=0}p')
|
|
55
|
+
# Derive a coarse subsystem tag from Affected Files directories + title keywords
|
|
56
|
+
INV_SUBSYSTEM[$INV_NUM]=$(echo "$INV_BODY" \
|
|
57
|
+
| grep -oP '`[^`]+/[^`]+`' | xargs -r -n1 dirname 2>/dev/null | sort | uniq -c | sort -rn | head -1)
|
|
58
|
+
done
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Cluster rule**: Two investigations are in the same cluster when they share a target subsystem (overlapping affected-file directories OR the same domain tag from Step 3B applied to their recommendations). Clustering is by **conceptual surface**, deliberately coarser than Step 3C's file-level analysis — the goal is to surface plan-level contradictions the file layer cannot see.
|
|
62
|
+
|
|
63
|
+
**Forward reference — related future signal** <!-- Added: forge#1196 -->: This clustering step (Step 2.5B) runs before Phase 3, so no Layer 5 data exists yet at this point — do not treat it as an input here. For readers extending this clustering rule in the future: Step 3C Layer 5 (historical co-change coupling, computed later in Phase 3) is a related signal worth reusing — two investigations whose affected files have historically co-changed would be good candidates for the same subsystem cluster. This is purely a forward reference, not a functional dependency or phase-reordering.
|
|
64
|
+
|
|
65
|
+
### Step 2.5C: Detect and resolve competing recommendations
|
|
66
|
+
|
|
67
|
+
Within each cluster (2+ investigations on the same subsystem), compare the **Recommendation** sections for incompatibility — e.g. one recommends adding a cache layer while another recommends removing caching from the same path; one proposes a new abstraction another proposes to delete. This is a semantic comparison of *proposed approaches*, read purely from the annotation prose.
|
|
68
|
+
|
|
69
|
+
For each detected conflict, resolve it in exactly ONE of two ways:
|
|
70
|
+
|
|
71
|
+
1. **Arbitration decision** — When the two recommendations are directly incompatible and one is clearly correct given the combined evidence, record a single deconflicted decision for BOTH issues. State which approach wins and why. This decision is written into each affected issue's `FORGE:SYNTHESIS_BRIEF` (Step 2.5D) — it does NOT close either issue; both still run, but against a reconciled plan.
|
|
72
|
+
2. **Serialization edge** — When the approaches are interdependent (the second issue's correct approach depends on what the first decides) or arbitration cannot pick a winner from annotations alone, add a `Depends on #{FIRST}` marker to the SECOND issue's body so the two serialize. The second agent then inherits the first's merged result during its own investigation/context phase.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Serialization is expressed as a standard "Depends on #X" edge so Step 3A consumes it
|
|
76
|
+
# with no new plumbing (see Step 3A dependency-marker parsing).
|
|
77
|
+
RECONCILED_COUNT=0
|
|
78
|
+
N_ARBITRATED=0
|
|
79
|
+
N_SERIALIZED=0
|
|
80
|
+
for CONFLICT in "${DETECTED_CONFLICTS[@]}"; do
|
|
81
|
+
# CONFLICT = "FIRST SECOND RESOLUTION" where RESOLUTION is "arbitrate" or "serialize"
|
|
82
|
+
set -- $CONFLICT; FIRST=$1; SECOND=$2; RESOLUTION=$3
|
|
83
|
+
if [ "$RESOLUTION" = "serialize" ]; then
|
|
84
|
+
# Reverse-direction cycle guard: before adding "#SECOND depends on #FIRST", check
|
|
85
|
+
# whether #FIRST already declares "Depends on #SECOND". If it does, the requested
|
|
86
|
+
# edge would close a 2-node cycle (#FIRST -> #SECOND -> #FIRST) that Step 3D.5's
|
|
87
|
+
# cycle detector would later have to exclude from dispatch entirely (both issues
|
|
88
|
+
# stuck behind needs-human). Skip the edge and fall back to arbitration-in-place
|
|
89
|
+
# instead, so both issues still run.
|
|
90
|
+
FIRST_BODY=$(gh issue view $FIRST -R {GH_REPO} --json body --jq '.body')
|
|
91
|
+
if echo "$FIRST_BODY" | grep -qiE "depends on #${SECOND}\b"; then
|
|
92
|
+
echo "Phase 2.5: skipping serialization edge #${FIRST} -> #${SECOND}: reverse edge #${SECOND} -> #${FIRST} already exists (would create a cycle). Falling back to arbitration-in-place."
|
|
93
|
+
RESOLUTION="arbitrate"
|
|
94
|
+
else
|
|
95
|
+
SECOND_BODY=$(gh issue view $SECOND -R {GH_REPO} --json body --jq '.body')
|
|
96
|
+
if ! echo "$SECOND_BODY" | grep -qiE "depends on #${FIRST}\b"; then
|
|
97
|
+
gh issue edit $SECOND -R {GH_REPO} \
|
|
98
|
+
--body "${SECOND_BODY}
|
|
99
|
+
|
|
100
|
+
Depends on #${FIRST}
|
|
101
|
+
<!-- Serialized by orchestrate Phase 2.5: competing recommendation reconciled via dependency edge. -->"
|
|
102
|
+
fi
|
|
103
|
+
fi
|
|
104
|
+
fi
|
|
105
|
+
# Re-check RESOLUTION (may have been downgraded from "serialize" to "arbitrate" above)
|
|
106
|
+
# so the breakdown counters and the Step 2.5D per-issue decision recording both reflect
|
|
107
|
+
# the resolution that was actually applied, not the one originally proposed.
|
|
108
|
+
if [ "$RESOLUTION" = "serialize" ]; then
|
|
109
|
+
N_SERIALIZED=$((N_SERIALIZED + 1))
|
|
110
|
+
else
|
|
111
|
+
N_ARBITRATED=$((N_ARBITRATED + 1))
|
|
112
|
+
fi
|
|
113
|
+
RECONCILED_COUNT=$((RECONCILED_COUNT + 1))
|
|
114
|
+
done
|
|
115
|
+
echo "Phase 2.5 reconciled ${RECONCILED_COUNT} competing recommendation(s) (${N_ARBITRATED} arbitrated, ${N_SERIALIZED} serialized)."
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**MUST NOT**: close, skip, or merge any issue on the basis of a detected conflict. Two issues with competing recommendations are BOTH valid work items — Phase 2.5 makes their plans coherent, it does not eliminate either. (This is the Safety Rule 9 boundary — see the Purpose note above.)
|
|
119
|
+
|
|
120
|
+
### Step 2.5D: Emit one deconflicted brief per issue
|
|
121
|
+
|
|
122
|
+
For each implementation issue about to be dispatched, write a single `FORGE:SYNTHESIS_BRIEF` annotation containing ONLY the reconciled context relevant to *that* issue — the arbitration decisions affecting it and pointers to the specific sibling investigation Gists it actually needs. This replaces injecting the entire aggregated milestone-index gist (which forces each agent to independently re-arbitrate the same contradictions, wasting tokens and producing nondeterministic cross-PR incoherence).
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
for ISSUE_NUM in {implementation_issue_numbers}; do
|
|
126
|
+
# Assemble the per-issue brief: arbitration decisions touching this issue's subsystem +
|
|
127
|
+
# only the relevant sibling gist URLs (not the full milestone-index dump)
|
|
128
|
+
BRIEF_BODY="Reconciled context for this issue (see orchestrate Phase 2.5):
|
|
129
|
+
${PER_ISSUE_DECISIONS[$ISSUE_NUM]}"
|
|
130
|
+
gh issue comment $ISSUE_NUM -R {GH_REPO} --body "<!-- FORGE:SYNTHESIS_BRIEF -->
|
|
131
|
+
## Synthesis Brief
|
|
132
|
+
|
|
133
|
+
${BRIEF_BODY}
|
|
134
|
+
|
|
135
|
+
<!-- FORGE:SYNTHESIS_BRIEF:COMPLETE -->"
|
|
136
|
+
done
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The `FORGE:SYNTHESIS_BRIEF` annotation is consumed by Step 4A's `{GIST_CONTEXT}` generation (which prefers it over the raw milestone-index gist when present) and its reconciled count (`RECONCILED_COUNT`) feeds the Step 6B `Competing recommendations reconciled (Phase 2.5)` metric.
|
|
140
|
+
|
|
141
|
+
**Report**: Post a brief Phase 2.5 summary to the user before proceeding to Phase 3:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
## Phase 2.5: Investigation Synthesis
|
|
145
|
+
|
|
146
|
+
**Investigations reconciled**: {INVESTIGATION_COUNT}
|
|
147
|
+
**Competing recommendations detected**: {RECONCILED_COUNT}
|
|
148
|
+
- Arbitrated in place: {N_ARBITRATED} (includes any serialization edges downgraded by the reverse-cycle guard)
|
|
149
|
+
- Serialized via dependency edge: {N_SERIALIZED}
|
|
150
|
+
**Per-issue synthesis briefs emitted**: {N_briefs}
|
|
151
|
+
|
|
152
|
+
Proceeding to dependency analysis with a deconflicted plan set...
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|