claude-dev-env 1.57.1 → 1.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/install.mjs +217 -27
- package/bin/install.test.mjs +344 -1
- package/hooks/blocking/intent_only_ending_blocker.py +155 -0
- package/hooks/blocking/session_handoff_blocker.py +190 -0
- package/hooks/blocking/test_intent_only_ending_blocker.py +175 -0
- package/hooks/blocking/test_session_handoff_blocker.py +312 -0
- package/hooks/hooks.json +10 -0
- package/hooks/hooks_constants/messages.py +4 -0
- package/hooks/hooks_constants/session_handoff_blocker_constants.py +10 -0
- package/hooks/workflow/auto_formatter.py +26 -1
- package/hooks/workflow/test_auto_formatter.py +134 -0
- package/package.json +1 -1
- package/rules/conservative-action.md +1 -0
- package/rules/long-horizon-autonomy.md +43 -0
- package/skills/autoconverge/SKILL.md +56 -6
- package/skills/autoconverge/reference/closing-report.md +44 -0
- package/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
- package/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +105 -0
- package/skills/autoconverge/workflow/converge.contract.test.mjs +30 -1
- package/skills/autoconverge/workflow/converge.mjs +12 -14
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +2 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +2 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +2 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +2 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +2 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +2 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +2 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +2 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +259 -0
- package/skills/autoconverge/workflow/render_report.py +903 -0
- package/skills/autoconverge/workflow/test_render_report.py +484 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Closing Report
|
|
2
|
+
|
|
3
|
+
When an autoconverge run converges (the workflow returns `converged: true`), the main session generates a convergence insights HTML report and publishes it as a secret gist with an idempotent PR comment linking to it.
|
|
4
|
+
|
|
5
|
+
## Data source
|
|
6
|
+
|
|
7
|
+
The report reads two file types written by the workflow during the run:
|
|
8
|
+
|
|
9
|
+
- **Run journal** — `~/.claude/projects/**/workflows/wf_<runId>.json` — the PR args, round log lines, `workflowProgress` array (one entry per agent step), and the final result.
|
|
10
|
+
- **Agent transcripts** — `~/.claude/projects/**/subagents/workflows/<runId>/agent-<agentId>.jsonl` — one file per agent; each line is a JSON object; the renderer extracts the last `StructuredOutput` tool_use from each file.
|
|
11
|
+
|
|
12
|
+
`converge.mjs` is not modified. The report is a pure reader of files the workflow already writes.
|
|
13
|
+
|
|
14
|
+
## Building the report
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
python "<skill>/workflow/render_report.py" \
|
|
18
|
+
--journal "<journal path>" \
|
|
19
|
+
--out "<output path>.html" \
|
|
20
|
+
--pr <owner>/<repo>#<n> \
|
|
21
|
+
--final-sha <sha> \
|
|
22
|
+
--rounds <N> \
|
|
23
|
+
--repo <worktree path>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The script reads the journal and transcripts, computes aggregated metrics (findings by severity, round, and theme; fix commits; tests added per round), and writes a self-contained HTML report. It prints the output path to stdout and exits 0 on success.
|
|
27
|
+
|
|
28
|
+
All aggregation is deterministic: `generated_date` comes from the journal `timestamp`, not the system clock, so the same inputs always produce the same HTML.
|
|
29
|
+
|
|
30
|
+
## Publishing
|
|
31
|
+
|
|
32
|
+
After rendering, the main session:
|
|
33
|
+
|
|
34
|
+
1. **Uploads the HTML as a secret gist** using `doc-gist/scripts/gist_upload.py --no-open`. Captures the htmlpreview URL from stdout.
|
|
35
|
+
2. **Posts one idempotent PR comment** marked with `<!-- autoconverge-report -->`. If a comment with that marker already exists on the PR, it is edited in place; otherwise a new comment is created. The comment body has the gist URL and a summary of findings by severity, rounds, and tests added, followed by the full finding list grouped by severity (`file:line — P# — title`). Write the body to a BOM-free temp file and pass `--body-file` to `gh issue comment` (never `--body`), or use the GitHub MCP `add_issue_comment` tool.
|
|
36
|
+
3. **Opens the report** with `Start-Process chrome -ArgumentList '--new-window', '<report path>'`. A missing Chrome does not abort teardown.
|
|
37
|
+
|
|
38
|
+
## Live-dashboard seam
|
|
39
|
+
|
|
40
|
+
The marker comment and gist together form a seam for future per-round dashboard refreshes: a live-dashboard step re-renders with the same `render_report_html` function (pure, no side effects), runs `gh gist edit` on the same gist, and edits the same marker comment. That per-round refresh path is out of scope here; this document describes the one-shot closing report only.
|
|
41
|
+
|
|
42
|
+
## Scope
|
|
43
|
+
|
|
44
|
+
The closing report runs only when `converged === true`. On a blocker exit (`blocker: "budget"` or similar), the report, gist, comment, and Chrome open are all skipped.
|
|
File without changes
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Named constants for render_report.py."""
|
|
2
|
+
|
|
3
|
+
STRUCTURED_OUTPUT_TOOL_NAME = "StructuredOutput"
|
|
4
|
+
|
|
5
|
+
LABEL_RESOLVE_HEAD = "resolve-head"
|
|
6
|
+
LABEL_PREFIX_LENS = "lens:"
|
|
7
|
+
LABEL_PREFIX_FIX = "fix:"
|
|
8
|
+
LABEL_COPILOT_GATE = "copilot-gate"
|
|
9
|
+
|
|
10
|
+
JOURNAL_SIBLING_SUBAGENTS = "subagents"
|
|
11
|
+
JOURNAL_SIBLING_WORKFLOWS = "workflows"
|
|
12
|
+
|
|
13
|
+
THEME_PATH_SEGMENT_COUNT = 2
|
|
14
|
+
THEME_FALLBACK = "other"
|
|
15
|
+
|
|
16
|
+
SEVERITY_CRITICAL_BUCKET = "Critical"
|
|
17
|
+
SEVERITY_MINOR_BUCKET = "Minor"
|
|
18
|
+
SEVERITY_CRITICAL_LEVELS = frozenset({"P0", "P1"})
|
|
19
|
+
SEVERITY_BADGE_CLASS_BY_LEVEL = {
|
|
20
|
+
"P0": "b-p0",
|
|
21
|
+
"P1": "b-p1",
|
|
22
|
+
"P2": "b-p2",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
BAR_COLOR_SEVERITY_CRITICAL = "#dc2626"
|
|
26
|
+
BAR_COLOR_SEVERITY_MINOR = "#eab308"
|
|
27
|
+
BAR_COLOR_ROUND = "#2563eb"
|
|
28
|
+
BAR_COLOR_TESTS = "#10b981"
|
|
29
|
+
BAR_COLOR_THEME = "#8b5cf6"
|
|
30
|
+
|
|
31
|
+
TEST_DEFINITION_PATTERN = r"^\+\s*(async\s+)?def\s+(test|should)"
|
|
32
|
+
TEST_PATH_GLOBS = ("*test*.py", "**/*test*.py")
|
|
33
|
+
|
|
34
|
+
BAR_FILL_MAX_PERCENT = 100
|
|
35
|
+
|
|
36
|
+
GITHUB_PR_URL_TEMPLATE = "https://github.com/{owner}/{repo}/pull/{number}"
|
|
37
|
+
|
|
38
|
+
HTML_DOCTYPE = "<!DOCTYPE html>"
|
|
39
|
+
|
|
40
|
+
HTML_HEAD_TEMPLATE = """\
|
|
41
|
+
<head>
|
|
42
|
+
<meta charset="utf-8">
|
|
43
|
+
<title>PR #{pr_number} Convergence Insights</title>
|
|
44
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
45
|
+
{style_block}
|
|
46
|
+
</head>"""
|
|
47
|
+
|
|
48
|
+
HTML_STYLE_BLOCK = """\
|
|
49
|
+
<style>
|
|
50
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
51
|
+
body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; background: #f8fafc; color: #334155; line-height: 1.65; padding: 48px 24px; }
|
|
52
|
+
.container { max-width: 800px; margin: 0 auto; }
|
|
53
|
+
h1 { font-size: 32px; font-weight: 700; color: #0f172a; margin-bottom: 8px; }
|
|
54
|
+
h2 { font-size: 20px; font-weight: 600; color: #0f172a; margin-top: 48px; margin-bottom: 16px; }
|
|
55
|
+
.subtitle { color: #64748b; font-size: 15px; margin-bottom: 32px; }
|
|
56
|
+
.nav-toc { display: flex; flex-wrap: wrap; gap: 8px; margin: 24px 0 32px 0; padding: 16px; background: white; border-radius: 8px; border: 1px solid #e2e8f0; }
|
|
57
|
+
.nav-toc a { font-size: 12px; color: #64748b; text-decoration: none; padding: 6px 12px; border-radius: 6px; background: #f1f5f9; transition: all 0.15s; }
|
|
58
|
+
.nav-toc a:hover { background: #e2e8f0; color: #334155; }
|
|
59
|
+
.stats-row { display: flex; gap: 24px; margin-bottom: 40px; padding: 20px 0; border-top: 1px solid #e2e8f0; border-bottom: 1px solid #e2e8f0; flex-wrap: wrap; }
|
|
60
|
+
.stat { text-align: center; }
|
|
61
|
+
.stat-value { font-size: 24px; font-weight: 700; color: #0f172a; }
|
|
62
|
+
.stat-label { font-size: 11px; color: #64748b; text-transform: uppercase; }
|
|
63
|
+
.at-a-glance { background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); border: 1px solid #f59e0b; border-radius: 12px; padding: 20px 24px; margin-bottom: 32px; }
|
|
64
|
+
.glance-title { font-size: 16px; font-weight: 700; color: #92400e; margin-bottom: 16px; }
|
|
65
|
+
.glance-sections { display: flex; flex-direction: column; gap: 12px; }
|
|
66
|
+
.glance-section { font-size: 14px; color: #78350f; line-height: 1.6; }
|
|
67
|
+
.glance-section strong { color: #92400e; }
|
|
68
|
+
.section-intro { font-size: 14px; color: #64748b; margin-bottom: 16px; }
|
|
69
|
+
.charts-row { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin: 24px 0; }
|
|
70
|
+
.chart-card { background: white; border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px; }
|
|
71
|
+
.chart-title { font-size: 12px; font-weight: 600; color: #64748b; text-transform: uppercase; margin-bottom: 12px; }
|
|
72
|
+
.bar-row { display: flex; align-items: center; margin-bottom: 6px; }
|
|
73
|
+
.bar-label { width: 116px; font-size: 11px; color: #475569; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
74
|
+
.bar-track { flex: 1; height: 6px; background: #f1f5f9; border-radius: 3px; margin: 0 8px; }
|
|
75
|
+
.bar-fill { height: 100%; border-radius: 3px; }
|
|
76
|
+
.bar-value { width: 28px; font-size: 11px; font-weight: 500; color: #64748b; text-align: right; }
|
|
77
|
+
.bugs { display: flex; flex-direction: column; gap: 16px; margin-bottom: 24px; }
|
|
78
|
+
.bug-card { border-radius: 8px; padding: 16px; }
|
|
79
|
+
.bug-card.crit { background: #fef2f2; border: 1px solid #fca5a5; }
|
|
80
|
+
.bug-card.minor { background: #fffbeb; border: 1px solid #fcd34d; }
|
|
81
|
+
.bug-head { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
|
|
82
|
+
.bug-num { font-size: 13px; font-weight: 700; color: #94a3b8; min-width: 28px; }
|
|
83
|
+
.bug-title { flex: 1 1 300px; font-weight: 600; font-size: 15px; }
|
|
84
|
+
.bug-card.crit .bug-title { color: #991b1b; }
|
|
85
|
+
.bug-card.minor .bug-title { color: #92400e; }
|
|
86
|
+
.badges { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
87
|
+
.badge { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; padding: 3px 8px; border-radius: 20px; white-space: nowrap; }
|
|
88
|
+
.b-p0 { background: #fee2e2; color: #991b1b; }
|
|
89
|
+
.b-p1 { background: #fee2e2; color: #991b1b; }
|
|
90
|
+
.b-p2 { background: #fef3c7; color: #92400e; }
|
|
91
|
+
.b-fixed { background: #dcfce7; color: #166534; }
|
|
92
|
+
.bug-impact { font-size: 13px; color: #7f1d1d; margin-top: 10px; line-height: 1.55; }
|
|
93
|
+
.bug-card.minor .bug-impact { color: #78350f; }
|
|
94
|
+
.bug-fix { background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 6px; padding: 10px 12px; margin-top: 10px; font-size: 13px; color: #166534; line-height: 1.5; }
|
|
95
|
+
.bug-fix b { color: #15803d; }
|
|
96
|
+
.bug-meta { font-size: 11px; color: #94a3b8; margin-top: 10px; }
|
|
97
|
+
.bug-meta code { background: #f1f5f9; padding: 1px 6px; border-radius: 4px; font-family: monospace; color: #475569; }
|
|
98
|
+
.horizon-card { background: linear-gradient(135deg, #faf5ff 0%, #f5f3ff 100%); border: 1px solid #c4b5fd; border-radius: 8px; padding: 16px; }
|
|
99
|
+
.horizon-title { font-weight: 600; font-size: 15px; color: #5b21b6; margin-bottom: 8px; }
|
|
100
|
+
.horizon-possible { font-size: 14px; color: #334155; margin-bottom: 10px; line-height: 1.5; }
|
|
101
|
+
.horizon-tip { font-size: 13px; color: #6b21a8; background: rgba(255,255,255,0.6); padding: 8px 12px; border-radius: 4px; }
|
|
102
|
+
footer { margin-top: 40px; padding-top: 18px; border-top: 1px solid #e2e8f0; color: #94a3b8; font-size: 12px; }
|
|
103
|
+
footer code { background: #f1f5f9; padding: 1px 6px; border-radius: 4px; font-family: monospace; color: #475569; }
|
|
104
|
+
@media (max-width: 640px) { .charts-row { grid-template-columns: 1fr; } .stats-row { justify-content: center; } }
|
|
105
|
+
</style>"""
|
|
@@ -134,7 +134,9 @@ function finalizeRepairBranch() {
|
|
|
134
134
|
assert.notEqual(repairCallIndex, -1, 'expected the FINALIZE repair call to exist');
|
|
135
135
|
const transitionIndex = convergeSource.indexOf("phase = 'CONVERGE'", repairCallIndex);
|
|
136
136
|
assert.notEqual(transitionIndex, -1, 'expected a CONVERGE transition after the repair call');
|
|
137
|
-
const
|
|
137
|
+
const continueIndex = convergeSource.indexOf('continue', transitionIndex);
|
|
138
|
+
assert.notEqual(continueIndex, -1, 'expected a continue statement to close the FINALIZE repair branch');
|
|
139
|
+
const branchEnd = continueIndex + 'continue'.length;
|
|
138
140
|
return convergeSource.slice(repairCallIndex, branchEnd);
|
|
139
141
|
}
|
|
140
142
|
|
|
@@ -146,6 +148,33 @@ test('the FINALIZE repair branch does not re-assign head from the repair before
|
|
|
146
148
|
);
|
|
147
149
|
});
|
|
148
150
|
|
|
151
|
+
function fixBranchAfter(branchLabel) {
|
|
152
|
+
const labelIndex = convergeSource.indexOf(branchLabel);
|
|
153
|
+
assert.notEqual(labelIndex, -1, `expected the ${branchLabel} marker to exist`);
|
|
154
|
+
const applyFixesIndex = convergeSource.indexOf('await applyFixes(', labelIndex);
|
|
155
|
+
assert.notEqual(applyFixesIndex, -1, `expected an applyFixes call after ${branchLabel}`);
|
|
156
|
+
const continueIndex = convergeSource.indexOf('continue', applyFixesIndex);
|
|
157
|
+
assert.notEqual(continueIndex, -1, `expected a continue statement to close the ${branchLabel} branch`);
|
|
158
|
+
const branchEnd = continueIndex + 'continue'.length;
|
|
159
|
+
return convergeSource.slice(applyFixesIndex, branchEnd);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
test('the CONVERGE fix branch does not re-assign head from the fix before re-converging', () => {
|
|
163
|
+
assert.doesNotMatch(
|
|
164
|
+
fixBranchAfter('${findings.length} finding(s) — applying fixes'),
|
|
165
|
+
/head\s*=\s*fixProgress/,
|
|
166
|
+
'the next CONVERGE pass re-resolves HEAD from GitHub, so assigning the fix SHA here is dead',
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test('the COPILOT fix branch does not re-assign head from the fix before re-converging', () => {
|
|
171
|
+
assert.doesNotMatch(
|
|
172
|
+
fixBranchAfter('${copilotOutcome.findings.length} finding(s) — fixing and re-converging'),
|
|
173
|
+
/head\s*=\s*fixProgress/,
|
|
174
|
+
'the CONVERGE pass it transitions to re-resolves HEAD from GitHub, so assigning the fix SHA here is dead',
|
|
175
|
+
);
|
|
176
|
+
});
|
|
177
|
+
|
|
149
178
|
test('the CONVERGE branch re-resolves HEAD from GitHub on every entry', () => {
|
|
150
179
|
const convergeBranchStart = convergeSource.indexOf("if (phase === 'CONVERGE')");
|
|
151
180
|
assert.notEqual(convergeBranchStart, -1, 'expected the CONVERGE branch to exist');
|
|
@@ -416,7 +416,7 @@ async function resolveHead() {
|
|
|
416
416
|
`Print the current HEAD SHA of ${prCoordinates}. Run exactly:\n` +
|
|
417
417
|
`gh api repos/${input.owner}/${input.repo}/pulls/${input.prNumber} --jq .head.sha\n` +
|
|
418
418
|
`Return the full 40-character SHA in the sha field. Do not modify any files.`,
|
|
419
|
-
{
|
|
419
|
+
{ label: 'resolve-head', phase: 'Converge', schema: HEAD_SCHEMA, agentType: 'Explore' },
|
|
420
420
|
)
|
|
421
421
|
return head?.sha
|
|
422
422
|
}
|
|
@@ -434,7 +434,7 @@ function prefetchMainForRound() {
|
|
|
434
434
|
`Refresh the base ref for ${prCoordinates} so the parallel review lenses can diff against an up-to-date origin/main without each running its own fetch. Run exactly:\n` +
|
|
435
435
|
`git fetch origin main\n` +
|
|
436
436
|
`Do not edit, commit, push, rebase, or modify any files — fetch only.`,
|
|
437
|
-
{
|
|
437
|
+
{ label: 'prefetch-main', phase: 'Converge', agentType: 'Explore' },
|
|
438
438
|
)
|
|
439
439
|
}
|
|
440
440
|
|
|
@@ -463,7 +463,7 @@ function runBugbotLens(head) {
|
|
|
463
463
|
`4. No review yet on HEAD: check_bugbot_ci.py --check-active. If active (exit 0), poll: repeat check_bugbot_ci.py --check-clean / --check-active every 60 seconds (delay each iteration with "sleep 60", or the PowerShell alternative "Start-Sleep -Seconds 60") for up to 25 iterations, then re-fetch the review. If not active (exit 1), post the literal comment "bugbot run" (no @mention, no other text) via python "${CONFIG.sharedScripts}/post_fix_reply.py" --owner ${input.owner} --repo ${input.repo} --pr-number ${input.prNumber} --body "bugbot run", delay 8 seconds with "sleep 8" (PowerShell alternative "Start-Sleep -Seconds 8"), then poll as above.\n` +
|
|
464
464
|
`5. If after the full poll budget Bugbot has neither a check run nor a review on HEAD -> return {sha:${'`'}${head}${'`'}, clean:true, down:true, findings:[]} (treat as down).\n\n` +
|
|
465
465
|
`Scope is the whole PR; you are only reading Bugbot's own output here. For each finding set category: 'code-standard' when it is a pure CODE_RULES/style violation (naming, comments, type hints, magic values, structure) with no behavioral impact; 'bug' otherwise. Return strictly the schema.`,
|
|
466
|
-
{
|
|
466
|
+
{ label: 'lens:bugbot', phase: 'Converge', schema: LENS_SCHEMA },
|
|
467
467
|
)
|
|
468
468
|
}
|
|
469
469
|
|
|
@@ -479,7 +479,7 @@ function runCodeReviewLens(head) {
|
|
|
479
479
|
`Review the FULL origin/main...HEAD diff — every file the PR touches. Do NOT delta-scope to recent commits or to a single file. The workflow already fetched origin/main this round, so do NOT run git fetch; run git diff --name-only origin/main...HEAD to enumerate the changed files, then review the complete diff of each.\n\n` +
|
|
480
480
|
`Apply correctness-focused review: real bugs, broken logic, incorrect error handling, data-loss or security risks, contract mismatches, and reuse/simplification problems. Report only defensible findings with concrete file:line evidence.\n\n` +
|
|
481
481
|
`Do NOT edit, commit, or push — reporting only. Return strictly the schema: clean=true with empty findings when the diff is sound, otherwise one entry per finding (severity P0/P1/P2; category 'code-standard' for pure CODE_RULES/style violations with no behavioral impact, 'bug' otherwise; replyToCommentId=null since these are not yet GitHub threads). Set sha=${'`'}${head}${'`'}, down=false.`,
|
|
482
|
-
{
|
|
482
|
+
{ label: 'lens:code-review', phase: 'Converge', schema: LENS_SCHEMA, agentType: 'code-quality-agent' },
|
|
483
483
|
)
|
|
484
484
|
}
|
|
485
485
|
|
|
@@ -495,7 +495,7 @@ function runAuditLens(head) {
|
|
|
495
495
|
`Read the audit rubric at ${CONFIG.bugteamRubric} and apply its categories (A through P) against the FULL origin/main...HEAD diff — every file the PR touches, never a delta cut. The workflow already fetched origin/main this round, so do NOT run git fetch; run git diff --name-only origin/main...HEAD first to enumerate scope.\n\n` +
|
|
496
496
|
`This is a clean-room audit: assume nothing from other lenses. Report only findings backed by concrete file:line evidence. Do NOT edit, commit, or push.\n\n` +
|
|
497
497
|
`Return strictly the schema: clean=true with empty findings when the diff passes every category, otherwise one entry per finding (severity P0/P1/P2; category 'code-standard' for pure CODE_RULES/style violations with no behavioral impact, 'bug' otherwise; replyToCommentId=null). Set sha=${'`'}${head}${'`'}, down=false.`,
|
|
498
|
-
{
|
|
498
|
+
{ label: 'lens:bug-audit', phase: 'Converge', schema: LENS_SCHEMA, agentType: 'code-quality-agent' },
|
|
499
499
|
)
|
|
500
500
|
}
|
|
501
501
|
|
|
@@ -533,7 +533,7 @@ function applyFixes(head, findings, sourceLabel) {
|
|
|
533
533
|
`- When you commit and push a fix: newSha=the new HEAD SHA after your push, pushed=true, resolvedWithoutCommit=false.\n` +
|
|
534
534
|
`- When every finding was already addressed so no code change is needed — yet you still resolved each GitHub review thread above: newSha=${head} (the unchanged HEAD), pushed=false, resolvedWithoutCommit=true. Only set this when every thread that carries a comment id is resolved; otherwise the round is treated as stalled.\n` +
|
|
535
535
|
`Always include a one-line summary.`,
|
|
536
|
-
{
|
|
536
|
+
{ label: `fix:${sourceLabel}`, phase: 'Converge', schema: FIX_SCHEMA, agentType: 'clean-coder' },
|
|
537
537
|
)
|
|
538
538
|
}
|
|
539
539
|
|
|
@@ -549,7 +549,7 @@ function postCleanAudit(head) {
|
|
|
549
549
|
`Write an empty findings file: create a temp file containing exactly [] (an empty JSON array). Then run:\n` +
|
|
550
550
|
`python "${CONFIG.prLoopScripts}/post_audit_thread.py" --skill bugteam --owner ${input.owner} --repo ${input.repo} --pr-number ${input.prNumber} --commit ${head} --state CLEAN --findings-json <temp-file>\n` +
|
|
551
551
|
`Run the script with --help first if any flag name differs. This posts the APPROVE review body that check_convergence.py reads for the bugteam gate. Do not edit code, commit, or push.`,
|
|
552
|
-
{
|
|
552
|
+
{ label: 'post-clean-audit', phase: 'Converge', agentType: 'general-purpose' },
|
|
553
553
|
)
|
|
554
554
|
}
|
|
555
555
|
|
|
@@ -569,7 +569,7 @@ function runCopilotGate(head) {
|
|
|
569
569
|
` - Copilot findings on HEAD -> return them (each with its inline comment id in replyToCommentId; category 'code-standard' for pure CODE_RULES/style violations with no behavioral impact, 'bug' otherwise), clean:false, blocker:null.\n` +
|
|
570
570
|
` - No review after ${CONFIG.copilotMaxPolls} attempts -> return {sha:${'`'}${head}${'`'}, clean:false, findings:[], blocker:"Copilot did not surface a review on HEAD after ${CONFIG.copilotMaxPolls} polls"}.\n\n` +
|
|
571
571
|
`Return strictly the schema.`,
|
|
572
|
-
{
|
|
572
|
+
{ label: 'copilot-gate', phase: 'Copilot gate', schema: COPILOT_SCHEMA },
|
|
573
573
|
)
|
|
574
574
|
}
|
|
575
575
|
|
|
@@ -586,7 +586,7 @@ function checkConvergence(bugbotDown) {
|
|
|
586
586
|
`Exit 0 -> every gate passed: return {pass:true, failures:[]}.\n` +
|
|
587
587
|
`Exit 1 -> return {pass:false, failures:[<each printed FAIL line verbatim>]}.\n` +
|
|
588
588
|
`Exit 2 -> retry once; if it still errors, return {pass:false, failures:["check_convergence gh error"]}.`,
|
|
589
|
-
{
|
|
589
|
+
{ label: 'check-convergence', phase: 'Finalize', schema: CONVERGENCE_SCHEMA, agentType: 'Explore' },
|
|
590
590
|
)
|
|
591
591
|
}
|
|
592
592
|
|
|
@@ -601,7 +601,7 @@ function markReady(head) {
|
|
|
601
601
|
`1. Run: gh pr ready ${input.prNumber} --repo ${input.owner}/${input.repo}\n` +
|
|
602
602
|
`2. Re-query the draft state: gh api repos/${input.owner}/${input.repo}/pulls/${input.prNumber} --jq .draft\n` +
|
|
603
603
|
`Return {ready:true} only when step 2 prints false (the PR is no longer a draft). If step 1 errors or step 2 still prints true, return {ready:false}.`,
|
|
604
|
-
{
|
|
604
|
+
{ label: 'mark-ready', phase: 'Finalize', schema: READY_SCHEMA, agentType: 'general-purpose' },
|
|
605
605
|
)
|
|
606
606
|
}
|
|
607
607
|
|
|
@@ -624,7 +624,7 @@ function repairConvergence(head, failures) {
|
|
|
624
624
|
`- PR not mergeable: rebase onto origin/main and force-push (git fetch origin main; git rebase origin/main; resolve conflicts; git push --force-with-lease).\n` +
|
|
625
625
|
`- A dirty bot review or a still-pending requested reviewer: leave it; the next round re-runs that reviewer.\n` +
|
|
626
626
|
`Make at most one commit for any code fix. Return the HEAD SHA after any push in newSha (the unchanged ${head} when nothing was pushed), pushed true/false, resolvedWithoutCommit=false (this gate already accepts an unchanged HEAD), and a one-line summary.`,
|
|
627
|
-
{
|
|
627
|
+
{ label: 'repair-convergence', phase: 'Finalize', schema: FIX_SCHEMA, agentType: 'clean-coder' },
|
|
628
628
|
)
|
|
629
629
|
}
|
|
630
630
|
|
|
@@ -668,7 +668,7 @@ function spawnStandardsFollowUp(head, findings, sourceLabel) {
|
|
|
668
668
|
`2. Environment-hardening PR: in the Claude environment config repo (the repo owning ~/.claude hooks and rules — JonEcho/llm-settings for hooks, jl-cmd/claude-code-config for rules/skills; pick whichever owns the needed surface), create a branch and open a DRAFT PR that hardens hooks/rules so each violation class found here is blocked at Write/Edit time, before code is written or reviewed. Reference the issue from step 1 in the PR body.\n` +
|
|
669
669
|
`3. For each finding that carries a GitHub review comment id: post an inline reply via python "${CONFIG.sharedScripts}/post_fix_reply.py" --owner ${input.owner} --repo ${input.repo} --pr-number ${input.prNumber} --in-reply-to <id> --body "Code-standard-only finding — deferred to follow-up issue <url>." Then resolve the thread by its PRRT_ node id (GraphQL lookup on comment databaseId, then resolveReviewThread or the github MCP pull_request_review_write method=resolve_thread).\n\n` +
|
|
670
670
|
`Return a one-line summary naming the follow-up issue URL and the hardening PR URL.`,
|
|
671
|
-
{
|
|
671
|
+
{ label: `standards-followup:${sourceLabel}`, phase: 'Converge', agentType: 'clean-coder' },
|
|
672
672
|
)
|
|
673
673
|
}
|
|
674
674
|
|
|
@@ -722,7 +722,6 @@ while (iterations < CONFIG.maxIterations) {
|
|
|
722
722
|
: `fix lens landed no push for ${findings.length} finding(s) on HEAD ${head}`
|
|
723
723
|
break
|
|
724
724
|
}
|
|
725
|
-
head = fixProgress.newSha
|
|
726
725
|
continue
|
|
727
726
|
}
|
|
728
727
|
if (!roundOutcome.roundClean) {
|
|
@@ -764,7 +763,6 @@ while (iterations < CONFIG.maxIterations) {
|
|
|
764
763
|
: `copilot fix lens landed no push for ${copilotOutcome.findings.length} finding(s) on HEAD ${head}`
|
|
765
764
|
break
|
|
766
765
|
}
|
|
767
|
-
head = fixProgress.newSha
|
|
768
766
|
phase = 'CONVERGE'
|
|
769
767
|
continue
|
|
770
768
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"type": "user", "uuid": "a11d903476b803493-u", "message": {"role": "user", "content": "Return the structured result."}}
|
|
2
|
+
{"type": "assistant", "uuid": "a11d903476b803493-a", "message": {"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_a11d903476b803493", "name": "StructuredOutput", "input": {"sha": "7c2f420c4d5b7c83aa47f93d99a0f1420e3373c4", "clean": false, "findings": [{"file": "src/exports/core/export_runner.py", "line": 96, "severity": "P2", "title": "New inline log string literal flagged by Magic-values rule", "detail": "Copilot (CodingGuidelineID 1000000, \"Magic values & configuration\"): the new log message at this line introduces a new string literal in production code. Prefer reusing an existing configured UI message (e.g. web_editor_config.ui_messages.msg_detected_version) instead of adding a new inline literal.", "replyToCommentId": 3407912224}, {"file": "src/web/services/os_generation_ssot.py", "line": 265, "severity": "P2", "title": "New inline warning string literal flagged by Magic-values rule", "detail": "Copilot (CodingGuidelineID 1000000, \"Magic values & configuration\"): read_current_version_name_or_none() adds a new inline warning string in production code. Per repo convention, extract this message into a shared config constant (in src/shared/web_automation/config/) so future callers reuse it consistently.", "replyToCommentId": 3407912234}], "blocker": null}}]}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"type": "user", "uuid": "a26213978adeef6fb-u", "message": {"role": "user", "content": "Return the structured result."}}
|
|
2
|
+
{"type": "assistant", "uuid": "a26213978adeef6fb-a", "message": {"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_a26213978adeef6fb", "name": "StructuredOutput", "input": {"newSha": "620382f766c4731ba92eefeb30bdbb9d0bcd4c90", "pushed": true, "resolvedWithoutCommit": false, "summary": "Fixed all 11 Copilot findings in one commit (620382f7): renamed banned `result` to `skip_path` in test_resume_skip_export.py and added `-> None` return annotations to the test functions across test_resume_skip_export.py, test_stp_path_selection.py, test_version_export_guards.py, and test_import_isolation.py; all 9 affected tests pass; pushed to fix/example-feature, posted 11 inline replies, and all 11 review threads are resolved."}}]}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"type": "user", "uuid": "a3def0d15ed9d9110-u", "message": {"role": "user", "content": "Return the structured result."}}
|
|
2
|
+
{"type": "assistant", "uuid": "a3def0d15ed9d9110-a", "message": {"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_a3def0d15ed9d9110", "name": "StructuredOutput", "input": {"sha": "6a5169ef635ddb841e6f0465a309691ff77f033e", "clean": false, "blocker": null, "findings": [{"file": "src/exports/tests/test_resume_skip_export.py", "line": 35, "severity": "P2", "title": "Banned identifier `result` in test", "detail": "Naming guideline (CodingGuidelineID 1000000): newly introduced identifier `result` is banned; rename to a descriptive name such as `existing_apk_path` or `skip_path`.", "replyToCommentId": 3407883689}, {"file": "src/exports/tests/test_resume_skip_export.py", "line": 47, "severity": "P2", "title": "Banned identifier `result` in test", "detail": "Naming guideline (CodingGuidelineID 1000000): newly introduced identifier `result` is banned; rename to a descriptive name such as `existing_apk_path` or `skip_path`.", "replyToCommentId": 3407883707}, {"file": "src/logging/tests/test_import_isolation.py", "line": 33, "severity": "P2", "title": "Missing return type annotation on test function", "detail": "Repository guideline (CodingGuidelineID 1000000 \u2014 Types): newly added test function is missing an explicit return type annotation. Add `-> None`.", "replyToCommentId": 3407883713}, {"file": "src/logging/tests/test_import_isolation.py", "line": 43, "severity": "P2", "title": "Missing return type annotation on test function", "detail": "Repository guideline (CodingGuidelineID 1000000 \u2014 Types): newly added test function is missing an explicit return type annotation. Add `-> None`.", "replyToCommentId": 3407883717}, {"file": "src/exports/tests/test_version_export_guards.py", "line": 37, "severity": "P2", "title": "Missing return type annotation on async test", "detail": "Repository guideline (CodingGuidelineID 1000000 \u2014 Types): newly added async test is missing an explicit return type annotation. Add `-> None`.", "replyToCommentId": 3407883723}, {"file": "src/exports/tests/test_version_export_guards.py", "line": 74, "severity": "P2", "title": "Missing return type annotation on async test", "detail": "Repository guideline (CodingGuidelineID 1000000 \u2014 Types): newly added async test is missing an explicit return type annotation. Add `-> None`.", "replyToCommentId": 3407883727}, {"file": "src/exports/tests/test_stp_path_selection.py", "line": 19, "severity": "P2", "title": "Missing return type annotation on test function", "detail": "Repository guideline (CodingGuidelineID 1000000 \u2014 Types): newly added test function is missing an explicit return type annotation. Add `-> None`.", "replyToCommentId": 3407883731}, {"file": "src/exports/tests/test_stp_path_selection.py", "line": 31, "severity": "P2", "title": "Missing return type annotation on test function", "detail": "Repository guideline (CodingGuidelineID 1000000 \u2014 Types): newly added test function is missing an explicit return type annotation. Add `-> None`.", "replyToCommentId": 3407883736}, {"file": "src/exports/tests/test_stp_path_selection.py", "line": 43, "severity": "P2", "title": "Missing return type annotation on test function", "detail": "Repository guideline (CodingGuidelineID 1000000 \u2014 Types): newly added test function is missing an explicit return type annotation. Add `-> None`.", "replyToCommentId": 3407883740}, {"file": "src/exports/tests/test_resume_skip_export.py", "line": 21, "severity": "P2", "title": "Missing return type annotation on test function", "detail": "Repository guideline (CodingGuidelineID 1000000 \u2014 Types): newly added test function is missing an explicit return type annotation. Add `-> None`.", "replyToCommentId": 3407883749}, {"file": "src/exports/tests/test_resume_skip_export.py", "line": 38, "severity": "P2", "title": "Missing return type annotation on test function", "detail": "Repository guideline (CodingGuidelineID 1000000 \u2014 Types): newly added test function is missing an explicit return type annotation. Add `-> None`.", "replyToCommentId": 3407883755}]}}]}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"type": "user", "uuid": "a41f41b1b708ee3b7-u", "message": {"role": "user", "content": "Return the structured result."}}
|
|
2
|
+
{"type": "assistant", "uuid": "a41f41b1b708ee3b7-a", "message": {"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_a41f41b1b708ee3b7", "name": "StructuredOutput", "input": {"sha": "7c2f420c4d5b7c83aa47f93d99a0f1420e3373c4", "clean": true, "findings": [], "blocker": null}}]}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"type": "user", "uuid": "a758b880abecc3ff7-u", "message": {"role": "user", "content": "Return the structured result."}}
|
|
2
|
+
{"type": "assistant", "uuid": "a758b880abecc3ff7-a", "message": {"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_a758b880abecc3ff7", "name": "StructuredOutput", "input": {"newSha": "7c2f420c4d5b7c83aa47f93d99a0f1420e3373c4", "pushed": false, "resolvedWithoutCommit": true, "summary": "Both Copilot magic-value findings were already fixed at HEAD 7c2f420c (export_runner.py uses web_editor_config.ui_messages.msg_detected_version; os_generation_ssot.py uses os_generation_ssot_constants.unavailable_warning_template); posted inline replies and resolved both review threads (PRRT_kwDORiaSZc6JUqSw, PRRT_kwDORiaSZc6JUqS6)."}}]}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"type": "user", "uuid": "a8897b89656b1bd16-u", "message": {"role": "user", "content": "Return the structured result."}}
|
|
2
|
+
{"type": "assistant", "uuid": "a8897b89656b1bd16-a", "message": {"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_a8897b89656b1bd16", "name": "StructuredOutput", "input": {"newSha": "7c2f420c4d5b7c83aa47f93d99a0f1420e3373c4", "pushed": true, "resolvedWithoutCommit": false, "summary": "Fixed both Copilot magic-value findings on PR #211: export_runner.py now reuses web_editor_config.ui_messages.msg_detected_version, and os_generation_ssot.py references a new os_generation_ssot_constants.unavailable_warning_template. Added a behavioral TDD test, committed (7c2f420c) and pushed; posted inline replies to both comments (3407912224, 3407912234) and resolved both review threads (PRRT_kwDORiaSZc6JUqSw, PRRT_kwDORiaSZc6JUqS6)."}}]}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"type": "user", "uuid": "abd463d744a1437bc-u", "message": {"role": "user", "content": "Return the structured result."}}
|
|
2
|
+
{"type": "assistant", "uuid": "abd463d744a1437bc-a", "message": {"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_abd463d744a1437bc", "name": "StructuredOutput", "input": {"sha": "6a5169ef635ddb841e6f0465a309691ff77f033e", "clean": true, "down": false, "findings": []}}]}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"type": "user", "uuid": "ad19d027ae8ee1816-u", "message": {"role": "user", "content": "Return the structured result."}}
|
|
2
|
+
{"type": "assistant", "uuid": "ad19d027ae8ee1816-a", "message": {"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_ad19d027ae8ee1816", "name": "StructuredOutput", "input": {"sha": "620382f766c4731ba92eefeb30bdbb9d0bcd4c90", "clean": false, "findings": [{"file": "src/exports/core/export_runner.py", "line": 94, "severity": "P2", "title": "New inline log string literal in production code", "detail": "Copilot (CodingGuidelineID 1000000, Magic values & configuration): the new log message at this line introduces a new string literal in production code. Prefer reusing an existing configured UI message (e.g., web_editor_config.ui_messages.msg_detected_version) instead of adding a new inline literal here.", "replyToCommentId": 3407912224}, {"file": "src/web/services/os_generation_ssot.py", "line": 266, "severity": "P2", "title": "New inline warning string literal in read_current_version_name_or_none()", "detail": "Copilot (CodingGuidelineID 1000000, Magic values & configuration): read_current_version_name_or_none() adds a new inline warning string in production code. Per repo convention, extract this message into a shared config constant (in src/shared/web_automation/config/) so future callers reuse it consistently.", "replyToCommentId": 3407912234}], "blocker": null}}]}}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
{
|
|
2
|
+
"runId": "wf_881252e6-700",
|
|
3
|
+
"timestamp": "2026-06-13T12:21:55.114Z",
|
|
4
|
+
"workflowName": "autoconverge",
|
|
5
|
+
"args": "{\"owner\": \"example-owner\", \"repo\": \"example-repo\", \"prNumber\": 211, \"bugbotDisabled\": false}",
|
|
6
|
+
"result": {
|
|
7
|
+
"converged": true,
|
|
8
|
+
"rounds": 4,
|
|
9
|
+
"finalSha": "7c2f420c4d5b7c83aa47f93d99a0f1420e3373c4",
|
|
10
|
+
"blocker": null
|
|
11
|
+
},
|
|
12
|
+
"agentCount": 33,
|
|
13
|
+
"logs": [
|
|
14
|
+
"Round 1: parallel Bugbot + code-review + bug-audit on 6a5169e",
|
|
15
|
+
"Round 1: all lenses clean on 6a5169e \u2014 posting clean audit artifact",
|
|
16
|
+
"Copilot raised 11 finding(s) \u2014 fixing and re-converging",
|
|
17
|
+
"Round 2: parallel Bugbot + code-review + bug-audit on 620382f",
|
|
18
|
+
"Round 2: all lenses clean on 620382f \u2014 posting clean audit artifact",
|
|
19
|
+
"Copilot raised 2 finding(s) \u2014 fixing and re-converging",
|
|
20
|
+
"Round 3: parallel Bugbot + code-review + bug-audit on 7c2f420",
|
|
21
|
+
"Round 3: all lenses clean on 7c2f420 \u2014 posting clean audit artifact",
|
|
22
|
+
"Copilot raised 2 finding(s) \u2014 fixing and re-converging",
|
|
23
|
+
"Round 4: parallel Bugbot + code-review + bug-audit on 7c2f420",
|
|
24
|
+
"Round 4: all lenses clean on 7c2f420 \u2014 posting clean audit artifact"
|
|
25
|
+
],
|
|
26
|
+
"workflowProgress": [
|
|
27
|
+
{
|
|
28
|
+
"index": 1,
|
|
29
|
+
"label": "resolve-head",
|
|
30
|
+
"phaseTitle": "Converge",
|
|
31
|
+
"agentId": "a5fe69b589d8d7fbb",
|
|
32
|
+
"state": "done"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"index": 2,
|
|
36
|
+
"label": "prefetch-main",
|
|
37
|
+
"phaseTitle": "Converge",
|
|
38
|
+
"agentId": "ac31351235aa865f1",
|
|
39
|
+
"state": "done"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"index": 3,
|
|
43
|
+
"label": "lens:bugbot",
|
|
44
|
+
"phaseTitle": "Converge",
|
|
45
|
+
"agentId": "a62ab69718928660b",
|
|
46
|
+
"state": "done"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"index": 4,
|
|
50
|
+
"label": "lens:code-review",
|
|
51
|
+
"phaseTitle": "Converge",
|
|
52
|
+
"agentId": "abd463d744a1437bc",
|
|
53
|
+
"state": "done"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"index": 5,
|
|
57
|
+
"label": "lens:bug-audit",
|
|
58
|
+
"phaseTitle": "Converge",
|
|
59
|
+
"agentId": "ab84b5cb3e6362e6b",
|
|
60
|
+
"state": "done"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"index": 6,
|
|
64
|
+
"label": "post-clean-audit",
|
|
65
|
+
"phaseTitle": "Converge",
|
|
66
|
+
"agentId": "aee38021859a3de55",
|
|
67
|
+
"state": "done"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"index": 7,
|
|
71
|
+
"label": "copilot-gate",
|
|
72
|
+
"phaseTitle": "Copilot gate",
|
|
73
|
+
"agentId": "a3def0d15ed9d9110",
|
|
74
|
+
"state": "done"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"index": 8,
|
|
78
|
+
"label": "fix:copilot",
|
|
79
|
+
"phaseTitle": "Converge",
|
|
80
|
+
"agentId": "a26213978adeef6fb",
|
|
81
|
+
"state": "done"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"index": 9,
|
|
85
|
+
"label": "resolve-head",
|
|
86
|
+
"phaseTitle": "Converge",
|
|
87
|
+
"agentId": "a88f58b25c2721e0a",
|
|
88
|
+
"state": "done"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"index": 10,
|
|
92
|
+
"label": "prefetch-main",
|
|
93
|
+
"phaseTitle": "Converge",
|
|
94
|
+
"agentId": "aabb9c42f62fefa4e",
|
|
95
|
+
"state": "done"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"index": 11,
|
|
99
|
+
"label": "lens:bugbot",
|
|
100
|
+
"phaseTitle": "Converge",
|
|
101
|
+
"agentId": "aaba3804f6e7ecdb9",
|
|
102
|
+
"state": "done"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"index": 12,
|
|
106
|
+
"label": "lens:code-review",
|
|
107
|
+
"phaseTitle": "Converge",
|
|
108
|
+
"agentId": "a7e434e6ea14aa176",
|
|
109
|
+
"state": "done"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"index": 13,
|
|
113
|
+
"label": "lens:bug-audit",
|
|
114
|
+
"phaseTitle": "Converge",
|
|
115
|
+
"agentId": "a46f6274a36a1db05",
|
|
116
|
+
"state": "done"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"index": 14,
|
|
120
|
+
"label": "post-clean-audit",
|
|
121
|
+
"phaseTitle": "Converge",
|
|
122
|
+
"agentId": "a3da3394c6ff72250",
|
|
123
|
+
"state": "done"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"index": 15,
|
|
127
|
+
"label": "copilot-gate",
|
|
128
|
+
"phaseTitle": "Copilot gate",
|
|
129
|
+
"agentId": "ad19d027ae8ee1816",
|
|
130
|
+
"state": "done"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"index": 16,
|
|
134
|
+
"label": "fix:copilot",
|
|
135
|
+
"phaseTitle": "Converge",
|
|
136
|
+
"agentId": "a8897b89656b1bd16",
|
|
137
|
+
"state": "done"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"index": 17,
|
|
141
|
+
"label": "resolve-head",
|
|
142
|
+
"phaseTitle": "Converge",
|
|
143
|
+
"agentId": "a196c9a85c88db8a7",
|
|
144
|
+
"state": "done"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"index": 18,
|
|
148
|
+
"label": "prefetch-main",
|
|
149
|
+
"phaseTitle": "Converge",
|
|
150
|
+
"agentId": "a3154efa58640a34e",
|
|
151
|
+
"state": "done"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"index": 19,
|
|
155
|
+
"label": "lens:bugbot",
|
|
156
|
+
"phaseTitle": "Converge",
|
|
157
|
+
"agentId": "a1f2a12f1470d7c7b",
|
|
158
|
+
"state": "done"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"index": 20,
|
|
162
|
+
"label": "lens:code-review",
|
|
163
|
+
"phaseTitle": "Converge",
|
|
164
|
+
"agentId": "a6754f2df6e70aa7c",
|
|
165
|
+
"state": "done"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"index": 21,
|
|
169
|
+
"label": "lens:bug-audit",
|
|
170
|
+
"phaseTitle": "Converge",
|
|
171
|
+
"agentId": "aabdfb7eba8ff036e",
|
|
172
|
+
"state": "done"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"index": 22,
|
|
176
|
+
"label": "post-clean-audit",
|
|
177
|
+
"phaseTitle": "Converge",
|
|
178
|
+
"agentId": "aa3438f61bdd9129e",
|
|
179
|
+
"state": "done"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"index": 23,
|
|
183
|
+
"label": "copilot-gate",
|
|
184
|
+
"phaseTitle": "Copilot gate",
|
|
185
|
+
"agentId": "a11d903476b803493",
|
|
186
|
+
"state": "done"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"index": 24,
|
|
190
|
+
"label": "fix:copilot",
|
|
191
|
+
"phaseTitle": "Converge",
|
|
192
|
+
"agentId": "a758b880abecc3ff7",
|
|
193
|
+
"state": "done"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"index": 25,
|
|
197
|
+
"label": "resolve-head",
|
|
198
|
+
"phaseTitle": "Converge",
|
|
199
|
+
"agentId": "a536d1ed4bb9ad0de",
|
|
200
|
+
"state": "done"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"index": 26,
|
|
204
|
+
"label": "prefetch-main",
|
|
205
|
+
"phaseTitle": "Converge",
|
|
206
|
+
"agentId": "a89686ea20e9224e2",
|
|
207
|
+
"state": "done"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"index": 27,
|
|
211
|
+
"label": "lens:bugbot",
|
|
212
|
+
"phaseTitle": "Converge",
|
|
213
|
+
"agentId": "a82b70fdc78fe7c3a",
|
|
214
|
+
"state": "done"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"index": 28,
|
|
218
|
+
"label": "lens:code-review",
|
|
219
|
+
"phaseTitle": "Converge",
|
|
220
|
+
"agentId": "a00c5df83283e9cf6",
|
|
221
|
+
"state": "done"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"index": 29,
|
|
225
|
+
"label": "lens:bug-audit",
|
|
226
|
+
"phaseTitle": "Converge",
|
|
227
|
+
"agentId": "a89412c46f53a3218",
|
|
228
|
+
"state": "done"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"index": 30,
|
|
232
|
+
"label": "post-clean-audit",
|
|
233
|
+
"phaseTitle": "Converge",
|
|
234
|
+
"agentId": "add6f0d13e1911d87",
|
|
235
|
+
"state": "done"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"index": 31,
|
|
239
|
+
"label": "copilot-gate",
|
|
240
|
+
"phaseTitle": "Copilot gate",
|
|
241
|
+
"agentId": "a41f41b1b708ee3b7",
|
|
242
|
+
"state": "done"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"index": 32,
|
|
246
|
+
"label": "check-convergence",
|
|
247
|
+
"phaseTitle": "Finalize",
|
|
248
|
+
"agentId": "a3338954faed1eb55",
|
|
249
|
+
"state": "done"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"index": 33,
|
|
253
|
+
"label": "mark-ready",
|
|
254
|
+
"phaseTitle": "Finalize",
|
|
255
|
+
"agentId": "add93d458ce4da043",
|
|
256
|
+
"state": "done"
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
}
|