forgedock 1.1.1 → 1.1.3
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 +24 -2
- 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 +70 -20
- 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 +518 -361
- 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/deploy-pr.md +485 -0
- 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/fix-ci.md +577 -0
- 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/recover-orphans.md +576 -0
- 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 +16 -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 +120 -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 +386 -111
- 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 +254 -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,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
install: extras
|
|
3
|
+
---
|
|
4
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
6
|
+
|
|
7
|
+
# /pipeline-health — Configuration
|
|
8
|
+
|
|
9
|
+
Read this file at the start of every `/pipeline-health` invocation, before Phase 1.
|
|
10
|
+
|
|
11
|
+
## Config
|
|
12
|
+
|
|
13
|
+
Read project identity from `forge.yaml` before running any phase:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
CONFIG_FILE="${FORGE_CONFIG:-forge.yaml}"
|
|
17
|
+
GH_REPO=$(yq e '.project.owner + "/" + .project.repo' "$CONFIG_FILE")
|
|
18
|
+
GH_FLAG="-R $GH_REPO"
|
|
19
|
+
# FORGE_REPO: the self-pipeline repo where pipeline-health issues are filed.
|
|
20
|
+
# Set project.forge_repo in forge.yaml if your pipeline repo differs from GH_REPO.
|
|
21
|
+
# Example: project:
|
|
22
|
+
# forge_repo: "my-org/my-forge"
|
|
23
|
+
FORGE_REPO=$(yq '.project.forge_repo // ""' "$CONFIG_FILE")
|
|
24
|
+
[ -z "$FORGE_REPO" ] && FORGE_REPO="$GH_REPO"
|
|
25
|
+
FORGE_HOME=$(yq e '.paths.root' "$CONFIG_FILE")
|
|
26
|
+
echo "Forge repo: $FORGE_REPO"
|
|
27
|
+
echo "Forge home: $FORGE_HOME"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**FORGE_HOME**: `$FORGE_HOME` (set from `forge.yaml` → `paths.root`)
|
|
31
|
+
**This command is READ-ONLY on the target project.** It creates issues in the Forge repo only.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
install: extras
|
|
3
|
+
---
|
|
4
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
6
|
+
|
|
7
|
+
# /pipeline-health — Phase 1: Identify Context
|
|
8
|
+
|
|
9
|
+
## Phase 1: Identify Context
|
|
10
|
+
|
|
11
|
+
### 1A: Resolve the target project
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Default to current repo if no argument
|
|
15
|
+
if [ -z "$ARGUMENTS" ] || [ "$ARGUMENTS" = "all" ]; then
|
|
16
|
+
REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner' 2>/dev/null)
|
|
17
|
+
else
|
|
18
|
+
REPO="$ARGUMENTS"
|
|
19
|
+
fi
|
|
20
|
+
echo "Target project: $REPO"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 1B: Get the analysis window
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Last pipeline-health run (if any) — from Forge git log
|
|
27
|
+
LAST_RUN=$(cd "$FORGE_HOME" && git log --all --oneline --grep="pipeline-health: $REPO" --format="%aI" -1 2>/dev/null || echo "")
|
|
28
|
+
if [ -z "$LAST_RUN" ]; then
|
|
29
|
+
# First run — analyze last 30 days
|
|
30
|
+
SINCE=$(date -d "30 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-30d +%Y-%m-%dT%H:%M:%SZ)
|
|
31
|
+
echo "First health check — analyzing last 30 days"
|
|
32
|
+
else
|
|
33
|
+
SINCE="$LAST_RUN"
|
|
34
|
+
echo "Last health check: $LAST_RUN — analyzing since then"
|
|
35
|
+
fi
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 1C: Load Prior Health Report
|
|
39
|
+
|
|
40
|
+
Fetch the most recent `health-report` issue for the same repo and parse its metrics for trend computation. This must run before Phase 2 so that PRIOR_* variables are available when Phase 3A builds the trend column.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Find the most recent health-report issue for this repo
|
|
44
|
+
PRIOR_REPORT=$(gh issue list -R $FORGE_REPO \
|
|
45
|
+
--state all --label "health-report" --limit 10 \
|
|
46
|
+
--json number,title,body \
|
|
47
|
+
--jq "[.[] | select(.title | contains(\"$REPO\"))] | sort_by(.number) | last")
|
|
48
|
+
|
|
49
|
+
if [ -z "$PRIOR_REPORT" ] || [ "$PRIOR_REPORT" = "null" ]; then
|
|
50
|
+
echo "No prior health report found for $REPO — this is a baseline run. All trends will show '—'."
|
|
51
|
+
PRIOR_HEALTH_SCORE=""
|
|
52
|
+
PRIOR_BUILD_PASS_RATE=""
|
|
53
|
+
PRIOR_FINDINGS_PER_PR=""
|
|
54
|
+
PRIOR_FALSE_POSITIVE_RATE=""
|
|
55
|
+
PRIOR_FIXUP_RATE=""
|
|
56
|
+
PRIOR_SELF_CORRECTION_RATE=""
|
|
57
|
+
PRIOR_ORIGINAL_WORK_RATIO=""
|
|
58
|
+
PRIOR_MILESTONE_MERGE_RATE=""
|
|
59
|
+
PRIOR_POST_DEPLOY_FAILURE_RATE=""
|
|
60
|
+
PRIOR_REVIEW_ESCAPE_RATE=""
|
|
61
|
+
PRIOR_SEC=0; PRIOR_AUTH=0; PRIOR_BILL=0; PRIOR_DB=0; PRIOR_FE=0
|
|
62
|
+
PRIOR_INFRA=0; PRIOR_API=0; PRIOR_CONC=0; PRIOR_SCRP=0; PRIOR_ISSUE_SPEC=0
|
|
63
|
+
PRIOR_TRANSCRIPT_SCORE=""
|
|
64
|
+
PRIOR_SESSION_COUNT=""
|
|
65
|
+
PRIOR_COMPACTION_MEDIAN=""
|
|
66
|
+
else
|
|
67
|
+
PRIOR_BODY=$(echo "$PRIOR_REPORT" | jq -r '.body')
|
|
68
|
+
PRIOR_NUMBER=$(echo "$PRIOR_REPORT" | jq -r '.number')
|
|
69
|
+
echo "Prior health report: #$PRIOR_NUMBER — parsing metrics for trend computation"
|
|
70
|
+
|
|
71
|
+
# Parse health score: matches "**Health Score**: 78/100" or "Score: 78/100"
|
|
72
|
+
PRIOR_HEALTH_SCORE=$(echo "$PRIOR_BODY" | grep -oP '(?<=\*\*Health Score\*\*: )\d+(?=/100)' | head -1)
|
|
73
|
+
[ -z "$PRIOR_HEALTH_SCORE" ] && PRIOR_HEALTH_SCORE=$(echo "$PRIOR_BODY" | grep -oP '(?<=Score: )\d+(?=/100)' | head -1)
|
|
74
|
+
|
|
75
|
+
# Parse metric table rows — format: "| Metric name | VALUE | target | status |"
|
|
76
|
+
# Build pass rate
|
|
77
|
+
PRIOR_BUILD_PASS_RATE=$(echo "$PRIOR_BODY" | grep -i "Build pass rate" | grep -oP '\d+(?=%)' | head -1)
|
|
78
|
+
# Review findings per PR
|
|
79
|
+
PRIOR_FINDINGS_PER_PR=$(echo "$PRIOR_BODY" | grep -i "Review findings per PR" | grep -oP '[0-9]+\.?[0-9]*' | sed -n '2p')
|
|
80
|
+
# False positive rate
|
|
81
|
+
PRIOR_FALSE_POSITIVE_RATE=$(echo "$PRIOR_BODY" | grep -i "False positive rate" | grep -oP '\d+(?=%)' | head -1)
|
|
82
|
+
# Manual fix-up rate
|
|
83
|
+
PRIOR_FIXUP_RATE=$(echo "$PRIOR_BODY" | grep -i "Manual fix-up rate" | grep -oP '\d+(?=%)' | head -1)
|
|
84
|
+
# Pipeline self-correction rate
|
|
85
|
+
PRIOR_SELF_CORRECTION_RATE=$(echo "$PRIOR_BODY" | grep -i "self-correction rate" | grep -oP '\d+(?=%)' | head -1)
|
|
86
|
+
# Original work ratio
|
|
87
|
+
PRIOR_ORIGINAL_WORK_RATIO=$(echo "$PRIOR_BODY" | grep -i "Original work ratio" | grep -oP '\d+(?=%)' | head -1)
|
|
88
|
+
# Milestone merge success
|
|
89
|
+
PRIOR_MILESTONE_MERGE_RATE=$(echo "$PRIOR_BODY" | grep -i "Milestone merge success" | grep -oP '\d+(?=%)' | head -1)
|
|
90
|
+
# Post-deploy failure rate
|
|
91
|
+
PRIOR_POST_DEPLOY_FAILURE_RATE=$(echo "$PRIOR_BODY" | grep -i "Post-deploy failure rate" | grep -oP '\d+(?=%)' | head -1)
|
|
92
|
+
# Review escape rate
|
|
93
|
+
PRIOR_REVIEW_ESCAPE_RATE=$(echo "$PRIOR_BODY" | grep -i "Review escape rate" | grep -oP '\d+(?=%)' | head -1)
|
|
94
|
+
# Transcript health score (from Phase 3C — supplementary signal)
|
|
95
|
+
PRIOR_TRANSCRIPT_SCORE=$(echo "$PRIOR_BODY" | grep -i "Transcript health score" | grep -oP '\d+(?=/100)' | head -1)
|
|
96
|
+
# Pipeline sessions in window (from Transcript Flow Metrics section)
|
|
97
|
+
PRIOR_SESSION_COUNT=$(echo "$PRIOR_BODY" | grep -i "Pipeline sessions parsed" | grep -oP '^\d+' | head -1)
|
|
98
|
+
# Compaction events median (from Aggregated Session Metrics table)
|
|
99
|
+
PRIOR_COMPACTION_MEDIAN=$(echo "$PRIOR_BODY" | grep -i "Context compaction events" | grep -oP '[0-9]+\.?[0-9]*' | head -1)
|
|
100
|
+
|
|
101
|
+
# Parse defect category counts from the "Defect Category Breakdown" section
|
|
102
|
+
# Matches table rows like "| SEC | 4 | 22% | ↑ +1 |" or "| SEC | 4 | 22% | — |"
|
|
103
|
+
_parse_cat() {
|
|
104
|
+
echo "$PRIOR_BODY" | grep -P "^\| $1 \|" | grep -oP '(?<=\| )\d+(?= \|)' | head -1
|
|
105
|
+
}
|
|
106
|
+
PRIOR_SEC=$( _parse_cat "SEC"); [ -z "$PRIOR_SEC" ] && PRIOR_SEC=0
|
|
107
|
+
PRIOR_AUTH=$( _parse_cat "AUTH"); [ -z "$PRIOR_AUTH" ] && PRIOR_AUTH=0
|
|
108
|
+
PRIOR_BILL=$( _parse_cat "BILL"); [ -z "$PRIOR_BILL" ] && PRIOR_BILL=0
|
|
109
|
+
PRIOR_DB=$( _parse_cat "DB"); [ -z "$PRIOR_DB" ] && PRIOR_DB=0
|
|
110
|
+
PRIOR_FE=$( _parse_cat "FE"); [ -z "$PRIOR_FE" ] && PRIOR_FE=0
|
|
111
|
+
PRIOR_INFRA=$( _parse_cat "INFRA"); [ -z "$PRIOR_INFRA" ] && PRIOR_INFRA=0
|
|
112
|
+
PRIOR_API=$( _parse_cat "API"); [ -z "$PRIOR_API" ] && PRIOR_API=0
|
|
113
|
+
PRIOR_CONC=$( _parse_cat "CONC"); [ -z "$PRIOR_CONC" ] && PRIOR_CONC=0
|
|
114
|
+
PRIOR_SCRP=$( _parse_cat "SCRP"); [ -z "$PRIOR_SCRP" ] && PRIOR_SCRP=0
|
|
115
|
+
PRIOR_ISSUE_SPEC=$(_parse_cat "ISSUE_SPEC"); [ -z "$PRIOR_ISSUE_SPEC" ] && PRIOR_ISSUE_SPEC=0
|
|
116
|
+
|
|
117
|
+
echo "Prior health score: ${PRIOR_HEALTH_SCORE:-N/A}"
|
|
118
|
+
echo "Prior defect counts: SEC=$PRIOR_SEC AUTH=$PRIOR_AUTH BILL=$PRIOR_BILL DB=$PRIOR_DB FE=$PRIOR_FE INFRA=$PRIOR_INFRA API=$PRIOR_API CONC=$PRIOR_CONC SCRP=$PRIOR_SCRP ISSUE_SPEC=$PRIOR_ISSUE_SPEC"
|
|
119
|
+
echo "Prior transcript: score=${PRIOR_TRANSCRIPT_SCORE:-N/A} sessions=${PRIOR_SESSION_COUNT:-N/A} compaction_median=${PRIOR_COMPACTION_MEDIAN:-N/A}"
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Helper function: compute trend string for a numeric category count
|
|
123
|
+
# Usage: _trend CURRENT PRIOR → outputs "↑ +N", "↓ -N", "=", or "—"
|
|
124
|
+
_trend() {
|
|
125
|
+
local current="$1" prior="$2"
|
|
126
|
+
if [ -z "$prior" ] || [ "$prior" = "0" ] && [ "$current" = "0" ]; then
|
|
127
|
+
echo "—"
|
|
128
|
+
elif [ -z "$prior" ]; then
|
|
129
|
+
echo "—"
|
|
130
|
+
elif [ "$current" -gt "$prior" ] 2>/dev/null; then
|
|
131
|
+
echo "↑ +$(( current - prior ))"
|
|
132
|
+
elif [ "$current" -lt "$prior" ] 2>/dev/null; then
|
|
133
|
+
echo "↓ -$(( prior - current ))"
|
|
134
|
+
else
|
|
135
|
+
echo "="
|
|
136
|
+
fi
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 1D: Run deterministic pipeline-state doctor
|
|
141
|
+
|
|
142
|
+
Before any LLM analysis, run the deterministic stall-detection script. This costs zero tokens and produces machine-readable findings that Phase 2 and Phase 3 consume directly.
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Resolve script path (supports repo-local overrides via FORGE_HOME/scripts/)
|
|
146
|
+
DOCTOR_SCRIPT="${FORGE_HOME}/scripts/doctor-pipeline-state.sh"
|
|
147
|
+
if [ ! -x "$DOCTOR_SCRIPT" ]; then
|
|
148
|
+
DOCTOR_SCRIPT=$(command -v doctor-pipeline-state.sh 2>/dev/null || true)
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
if [ -n "$DOCTOR_SCRIPT" ] && [ -x "$DOCTOR_SCRIPT" ]; then
|
|
152
|
+
DOCTOR_OUTPUT=$("$DOCTOR_SCRIPT" --repo "$GH_REPO" --json 2>/dev/null || true)
|
|
153
|
+
DOCTOR_FINDINGS=$(echo "$DOCTOR_OUTPUT" | jq '.findings // []' 2>/dev/null || echo "[]")
|
|
154
|
+
DOCTOR_SUMMARY=$(echo "$DOCTOR_OUTPUT" | jq '.summary // {}' 2>/dev/null || echo "{}")
|
|
155
|
+
DOCTOR_CRITICAL=$(echo "$DOCTOR_SUMMARY" | jq '.critical // 0')
|
|
156
|
+
DOCTOR_WARNING=$(echo "$DOCTOR_SUMMARY" | jq '.warning // 0')
|
|
157
|
+
DOCTOR_CHECKS_SKIPPED=$(echo "$DOCTOR_SUMMARY" | jq '.checks_skipped // 0')
|
|
158
|
+
DOCTOR_DEGRADED=$(echo "$DOCTOR_SUMMARY" | jq '.degraded // []')
|
|
159
|
+
echo "Pipeline-state doctor: $DOCTOR_CRITICAL critical, $DOCTOR_WARNING warning, $DOCTOR_CHECKS_SKIPPED check(s) skipped"
|
|
160
|
+
else
|
|
161
|
+
echo "WARNING: doctor-pipeline-state.sh not found — skipping deterministic stall check"
|
|
162
|
+
DOCTOR_FINDINGS="[]"
|
|
163
|
+
DOCTOR_SUMMARY="{}"
|
|
164
|
+
DOCTOR_CRITICAL=0
|
|
165
|
+
DOCTOR_WARNING=0
|
|
166
|
+
DOCTOR_CHECKS_SKIPPED=0
|
|
167
|
+
DOCTOR_DEGRADED="[]"
|
|
168
|
+
fi
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**If `DOCTOR_CRITICAL > 0`**: Surface these in the Phase 3 analysis and in the Phase 5 report as P0 items. They are invariant violations, not estimates.
|
|
172
|
+
|
|
173
|
+
**`DOCTOR_FINDINGS`** is a JSON array. Each finding has: `type`, `severity`, `issue`, `label`, `hours_stuck`, `last_annotation`, `resume_command`, `detail`. Use these fields verbatim in the health report — do not paraphrase.
|
|
174
|
+
|
|
175
|
+
**If `DOCTOR_CHECKS_SKIPPED > 0`**: One or more invariant checks (I4/I5) fail-open on a real `gh` API failure rather than being confirmed-missing — this is intentional, but a check that stays skipped across consecutive runs means the underlying `gh` failure is persistent, not a transient blip. Surface this as a degraded-health signal in the Phase 3 analysis and the Phase 5 report (e.g. "I4/I5 invariants silently disabled — investigate underlying `gh` failure"), distinct from the `DOCTOR_CRITICAL` P0 items above since a skip is a coverage gap, not a confirmed violation.
|
|
176
|
+
|
|
177
|
+
**`DOCTOR_DEGRADED`** is a JSON array. Each entry has: `check`, `issue`, `reason`. Use these fields verbatim when listing which checks were skipped and why — do not paraphrase.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|