@backburner/cli 0.1.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/LICENSE +21 -0
- package/README.md +329 -0
- package/dist/src/agents/antigravity-launch.js +162 -0
- package/dist/src/agents/antigravity.js +251 -0
- package/dist/src/agents/claude-launch.js +117 -0
- package/dist/src/agents/claude.js +271 -0
- package/dist/src/agents/codex-launch.js +82 -0
- package/dist/src/agents/codex.js +261 -0
- package/dist/src/agents/composite-runner.js +13 -0
- package/dist/src/agents/extraction.js +442 -0
- package/dist/src/agents/failure-feedback.js +132 -0
- package/dist/src/agents/gemini-launch.js +96 -0
- package/dist/src/agents/gemini.js +392 -0
- package/dist/src/agents/job-agent-assignments.js +180 -0
- package/dist/src/agents/lifecycle-feedback.js +147 -0
- package/dist/src/agents/limit-detector.js +83 -0
- package/dist/src/agents/opencode-launch.js +138 -0
- package/dist/src/agents/opencode.js +156 -0
- package/dist/src/agents/plan-breakdown-feedback.js +97 -0
- package/dist/src/agents/pool.js +168 -0
- package/dist/src/agents/prompt.js +462 -0
- package/dist/src/agents/provider-sessions.js +105 -0
- package/dist/src/agents/review-feedback.js +255 -0
- package/dist/src/agents/selection.js +113 -0
- package/dist/src/agents/service.js +1087 -0
- package/dist/src/agents/types.js +1 -0
- package/dist/src/agents/wave-assessment-feedback.js +69 -0
- package/dist/src/attention/derive.js +337 -0
- package/dist/src/capabilities/index.js +2 -0
- package/dist/src/capabilities/projection.js +183 -0
- package/dist/src/capabilities/types.js +1 -0
- package/dist/src/capabilities/validator.js +87 -0
- package/dist/src/cli/commands/broker-smoke.js +96 -0
- package/dist/src/cli/commands/broker.js +56 -0
- package/dist/src/cli/commands/init.js +4 -0
- package/dist/src/cli/commands/journal.js +43 -0
- package/dist/src/cli/commands/run-loop.js +56 -0
- package/dist/src/cli/commands/run.js +1241 -0
- package/dist/src/cli/commands/tui.js +187 -0
- package/dist/src/cli/dispatcher.js +51 -0
- package/dist/src/cli/errors.js +2 -0
- package/dist/src/cli/init.js +92 -0
- package/dist/src/cli/options.js +86 -0
- package/dist/src/cli/output.js +231 -0
- package/dist/src/cli/run-journal.js +342 -0
- package/dist/src/cli/run-types.js +1 -0
- package/dist/src/cli/run.js +32 -0
- package/dist/src/cli/runtime/dispatch-lifecycle.js +772 -0
- package/dist/src/cli/runtime/provider-runtime-types.js +1 -0
- package/dist/src/cli/runtime/provider-runtime.js +152 -0
- package/dist/src/cli/runtime/provider-tools.js +73 -0
- package/dist/src/cli/runtime/providers/antigravity.js +26 -0
- package/dist/src/cli/runtime/providers/claude.js +20 -0
- package/dist/src/cli/runtime/providers/codex.js +20 -0
- package/dist/src/cli/runtime/providers/gemini.js +20 -0
- package/dist/src/cli/runtime/providers/opencode.js +20 -0
- package/dist/src/cli/runtime/run-context.js +131 -0
- package/dist/src/cli/tui/index.js +3 -0
- package/dist/src/cli/tui/screen.js +388 -0
- package/dist/src/cli/tui/tracker.js +558 -0
- package/dist/src/cli/tui/types.js +1 -0
- package/dist/src/cli/tui/views.js +1006 -0
- package/dist/src/config/loader.js +136 -0
- package/dist/src/config/schemas.js +403 -0
- package/dist/src/config/types.js +1 -0
- package/dist/src/context/types.js +331 -0
- package/dist/src/domain/entities.js +1 -0
- package/dist/src/git/backburner-git-tool-service.js +680 -0
- package/dist/src/git/gitops-lifecycle.js +56 -0
- package/dist/src/git/merge-prep-workspace.js +357 -0
- package/dist/src/git/types.js +484 -0
- package/dist/src/github/broker-model-content.js +215 -0
- package/dist/src/github/broker-server.js +237 -0
- package/dist/src/github/broker.js +638 -0
- package/dist/src/github/composed.js +53 -0
- package/dist/src/github/gateway.js +478 -0
- package/dist/src/github/normalize.js +222 -0
- package/dist/src/github/pr-classification.js +73 -0
- package/dist/src/github/scoped-broker.js +35 -0
- package/dist/src/github/security.js +126 -0
- package/dist/src/github/service.js +332 -0
- package/dist/src/github/types.js +1 -0
- package/dist/src/github/utils.js +16 -0
- package/dist/src/journal/index.js +4 -0
- package/dist/src/journal/reader.js +62 -0
- package/dist/src/journal/renderer.js +50 -0
- package/dist/src/journal/service.js +72 -0
- package/dist/src/journal/types.js +1 -0
- package/dist/src/journal/writer.js +19 -0
- package/dist/src/mcps/bridge.js +166 -0
- package/dist/src/mcps/index.js +5 -0
- package/dist/src/mcps/reconcile.js +113 -0
- package/dist/src/mcps/smithery-client.js +186 -0
- package/dist/src/mcps/smithery.js +164 -0
- package/dist/src/mcps/types.js +1 -0
- package/dist/src/memory/json-store.js +71 -0
- package/dist/src/memory/prompt.js +16 -0
- package/dist/src/memory/scope.js +31 -0
- package/dist/src/memory/store.js +1 -0
- package/dist/src/memory/tool-service.js +142 -0
- package/dist/src/memory/types.js +12 -0
- package/dist/src/onboarding/config-writer.js +96 -0
- package/dist/src/onboarding/engine.js +86 -0
- package/dist/src/onboarding/prompt.js +102 -0
- package/dist/src/onboarding/services/provider-discovery.js +58 -0
- package/dist/src/onboarding/services/repo-discovery.js +246 -0
- package/dist/src/onboarding/steps/check-github-auth.js +32 -0
- package/dist/src/onboarding/steps/check-requirements.js +34 -0
- package/dist/src/onboarding/steps/configure-models.js +105 -0
- package/dist/src/onboarding/steps/configure-paths.js +33 -0
- package/dist/src/onboarding/steps/discover-providers.js +38 -0
- package/dist/src/onboarding/steps/discover-repos.js +39 -0
- package/dist/src/onboarding/steps/generate-config.js +106 -0
- package/dist/src/onboarding/steps/readiness-validation.js +158 -0
- package/dist/src/onboarding/steps/select-repos.js +76 -0
- package/dist/src/onboarding/steps/show-summary.js +97 -0
- package/dist/src/onboarding/steps/welcome.js +27 -0
- package/dist/src/onboarding/types.js +1 -0
- package/dist/src/onboarding/validators/git-access.js +63 -0
- package/dist/src/onboarding/validators/github-auth.js +85 -0
- package/dist/src/onboarding/validators/tool-checker.js +153 -0
- package/dist/src/onboarding/validators/workspace.js +83 -0
- package/dist/src/prompts/resolver.js +106 -0
- package/dist/src/retrospectives/candidates.js +224 -0
- package/dist/src/retrospectives/derive.js +169 -0
- package/dist/src/retrospectives/ingest.js +321 -0
- package/dist/src/retrospectives/management-prs.js +380 -0
- package/dist/src/retrospectives/proposals.js +199 -0
- package/dist/src/retrospectives/scopes.js +272 -0
- package/dist/src/retrospectives/scoring.js +171 -0
- package/dist/src/retrospectives/types.js +1 -0
- package/dist/src/state/loader.js +473 -0
- package/dist/src/state/types.js +15 -0
- package/dist/src/tasks/derivation/builders.js +70 -0
- package/dist/src/tasks/derivation/handlers/comment-response.js +169 -0
- package/dist/src/tasks/derivation/handlers/implement-plan.js +103 -0
- package/dist/src/tasks/derivation/handlers/index.js +54 -0
- package/dist/src/tasks/derivation/handlers/packet-pr-control.js +92 -0
- package/dist/src/tasks/derivation/handlers/packet-worktree.js +29 -0
- package/dist/src/tasks/derivation/handlers/plan-breakdown.js +45 -0
- package/dist/src/tasks/derivation/handlers/prepare-for-merge.js +91 -0
- package/dist/src/tasks/derivation/handlers/product-discovery.js +36 -0
- package/dist/src/tasks/derivation/handlers/retry-failed-task.js +125 -0
- package/dist/src/tasks/derivation/handlers/review-pr.js +28 -0
- package/dist/src/tasks/derivation/handlers/shared.js +24 -0
- package/dist/src/tasks/derivation/handlers/sync-parent-branch.js +100 -0
- package/dist/src/tasks/derivation/handlers/wave-assessment.js +223 -0
- package/dist/src/tasks/derivation/handlers/write-plan.js +101 -0
- package/dist/src/tasks/derivation/handlers/write-product-spec.js +49 -0
- package/dist/src/tasks/derivation/runner.js +18 -0
- package/dist/src/tasks/derivation/types.js +1 -0
- package/dist/src/tasks/derive.js +810 -0
- package/dist/src/tasks/mcp-skip.js +10 -0
- package/dist/src/tasks/retry.js +10 -0
- package/dist/src/tasks/task.js +184 -0
- package/dist/src/tasks/types.js +1 -0
- package/dist/src/utils/command-runner.js +192 -0
- package/dist/src/utils/json.js +38 -0
- package/dist/src/utils/logger.js +43 -0
- package/dist/src/utils/paths.js +38 -0
- package/dist/src/utils/slug.js +10 -0
- package/dist/src/workflows/registry.js +174 -0
- package/dist/src/workflows/triage.js +90 -0
- package/dist/src/workflows/workstream-machine/derive-events.js +121 -0
- package/dist/src/workflows/workstream-machine/evaluate.js +24 -0
- package/dist/src/workflows/workstream-machine/events.js +1 -0
- package/dist/src/workflows/workstream-machine/machine.js +355 -0
- package/dist/src/workflows/workstream-machine/selectors.js +19 -0
- package/dist/src/workflows/workstream-machine/types.js +1 -0
- package/dist/src/workstreams/branch-sync.js +87 -0
- package/dist/src/workstreams/derive.js +629 -0
- package/dist/src/workstreams/mcp-blockers.js +420 -0
- package/dist/src/workstreams/packet-candidates.js +42 -0
- package/dist/src/workstreams/packet-lifecycle-feedback.js +60 -0
- package/dist/src/workstreams/packet-lifecycle-report.js +199 -0
- package/dist/src/workstreams/packet-plan.js +597 -0
- package/dist/src/workstreams/packet-projections.js +190 -0
- package/dist/src/workstreams/parent-branch-sync-action.js +312 -0
- package/dist/src/workstreams/parent-branch-sync.js +148 -0
- package/dist/src/workstreams/phases.js +4 -0
- package/dist/src/workstreams/plan-breakdown-generator/export.js +19 -0
- package/dist/src/workstreams/plan-breakdown-generator/index.js +6 -0
- package/dist/src/workstreams/plan-breakdown-generator/inspect.js +50 -0
- package/dist/src/workstreams/plan-breakdown-generator/patch.js +139 -0
- package/dist/src/workstreams/plan-breakdown-generator/session.js +19 -0
- package/dist/src/workstreams/plan-breakdown-generator/store.js +27 -0
- package/dist/src/workstreams/plan-breakdown-generator/tools.js +407 -0
- package/dist/src/workstreams/plan-breakdown-generator/types.js +6 -0
- package/dist/src/workstreams/plan-breakdown-generator/validate.js +212 -0
- package/dist/src/workstreams/plan-breakdown-schema.js +175 -0
- package/dist/src/workstreams/utils.js +15 -0
- package/dist/src/workstreams/wave-assessment/checkpoint.js +172 -0
- package/dist/src/workstreams/wave-assessment/index.js +3 -0
- package/dist/src/workstreams/wave-assessment/session.js +84 -0
- package/dist/src/workstreams/wave-assessment/store.js +51 -0
- package/dist/src/workstreams/wave-assessment/tools.js +419 -0
- package/dist/src/workstreams/wave-assessment/types.js +1 -0
- package/dist/src/workstreams/wave-assessment/validate.js +78 -0
- package/dist/src/worktrees/service.js +839 -0
- package/dist/src/worktrees/workspace-ownership.js +34 -0
- package/dist/src/worktrees/workspace-recovery.js +177 -0
- package/package.json +61 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Journal helper functions for run.ts.
|
|
3
|
+
*
|
|
4
|
+
* Extracted here to keep run.ts clean. Handles:
|
|
5
|
+
* - buildEntityMaps: builds lookup maps from scan data
|
|
6
|
+
* - resolveTaskJournalIds: resolves issueNumber/prNumber for a task
|
|
7
|
+
* - resolveRepoActionState: comprehensive no-action logic per repo
|
|
8
|
+
* - journalWorkstreamTransitions: journals workstream phase/attention/status changes
|
|
9
|
+
* - journalTaskTransitions: journals task status changes after dispatch
|
|
10
|
+
* - journalWorktreeTransitions: journals worktree status changes
|
|
11
|
+
* - journalNewExecutions: journals only newly-created executions
|
|
12
|
+
* - journalPacketWaveEvents: journals packet wave advancements and blocks
|
|
13
|
+
*/
|
|
14
|
+
export function buildEntityMaps(issues, prs, enabledRepos) {
|
|
15
|
+
const issueIdToNumber = new Map();
|
|
16
|
+
for (const issue of issues) {
|
|
17
|
+
issueIdToNumber.set(issue.id, issue.number);
|
|
18
|
+
}
|
|
19
|
+
const prIdToNumber = new Map();
|
|
20
|
+
for (const pr of prs) {
|
|
21
|
+
prIdToNumber.set(pr.id, pr.number);
|
|
22
|
+
}
|
|
23
|
+
const repoSlugToId = new Map();
|
|
24
|
+
for (const repo of enabledRepos) {
|
|
25
|
+
repoSlugToId.set(`${repo.owner}/${repo.name}`, repo.id);
|
|
26
|
+
repoSlugToId.set(repo.id, repo.id); // fallback: repoKey stored as id resolves to itself
|
|
27
|
+
}
|
|
28
|
+
return { issueIdToNumber, prIdToNumber, repoSlugToId };
|
|
29
|
+
}
|
|
30
|
+
export function resolveTaskJournalIds(task, maps, workstreams) {
|
|
31
|
+
let issueNumber;
|
|
32
|
+
let prNumber;
|
|
33
|
+
if (task.sourceKind === "issue") {
|
|
34
|
+
issueNumber = maps.issueIdToNumber.get(task.sourceId);
|
|
35
|
+
}
|
|
36
|
+
else if (task.sourceKind === "pull_request") {
|
|
37
|
+
prNumber = maps.prIdToNumber.get(task.sourceId);
|
|
38
|
+
}
|
|
39
|
+
else if (task.sourceKind === "comment") {
|
|
40
|
+
if (task.parentSourceKind === "issue" && task.parentSourceId !== undefined) {
|
|
41
|
+
issueNumber = maps.issueIdToNumber.get(task.parentSourceId);
|
|
42
|
+
}
|
|
43
|
+
else if (task.parentSourceKind === "pull_request" && task.parentSourceId !== undefined) {
|
|
44
|
+
prNumber = maps.prIdToNumber.get(task.parentSourceId);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Also check workstream's activePrNumber if task belongs to one
|
|
48
|
+
if (task.workstreamId && workstreams) {
|
|
49
|
+
const ws = workstreams.find((w) => w.id === task.workstreamId);
|
|
50
|
+
if (ws?.activePrNumber !== undefined && prNumber === undefined) {
|
|
51
|
+
prNumber = ws.activePrNumber;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
...(issueNumber !== undefined ? { issueNumber } : {}),
|
|
56
|
+
...(prNumber !== undefined ? { prNumber } : {})
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function resolveRepoActionState(input) {
|
|
60
|
+
const { repoId, repoSlug, syncRecord, tasks, workstreams, issues, prs } = input;
|
|
61
|
+
// 1. Sync failed
|
|
62
|
+
if (syncRecord?.status === "failed") {
|
|
63
|
+
const reason = syncRecord.error?.message ?? syncRecord.message ?? "Unknown sync error";
|
|
64
|
+
return { hasAction: false, noActionReason: `Repository failed to sync: ${reason}` };
|
|
65
|
+
}
|
|
66
|
+
// 2. Scan failed
|
|
67
|
+
const scan = syncRecord?.githubScan;
|
|
68
|
+
if (scan?.status === "failed") {
|
|
69
|
+
return { hasAction: false, noActionReason: "GitHub scan failed — issue and PR data unavailable" };
|
|
70
|
+
}
|
|
71
|
+
// 3. Pending relevant tasks → has action
|
|
72
|
+
const pendingRelevant = tasks.filter((t) => t.repoId === repoId && t.status === "pending" && t.relevant);
|
|
73
|
+
if (pendingRelevant.length > 0) {
|
|
74
|
+
return { hasAction: true };
|
|
75
|
+
}
|
|
76
|
+
// 4. Dispatched tasks → has action
|
|
77
|
+
const dispatched = tasks.filter((t) => t.repoId === repoId && t.status === "dispatched");
|
|
78
|
+
if (dispatched.length > 0) {
|
|
79
|
+
return { hasAction: true };
|
|
80
|
+
}
|
|
81
|
+
// Check workstreams for this repo
|
|
82
|
+
const repoWorkstreams = workstreams.filter((ws) => {
|
|
83
|
+
return ws.repoKey === repoSlug || ws.repoKey === repoId;
|
|
84
|
+
});
|
|
85
|
+
for (const ws of repoWorkstreams) {
|
|
86
|
+
const wsTasks = tasks.filter((t) => t.workstreamId === ws.id);
|
|
87
|
+
const hasFailedTasks = wsTasks.some((t) => t.status === "failed");
|
|
88
|
+
const hasPendingOrDispatched = wsTasks.some((t) => t.status === "pending" || t.status === "dispatched");
|
|
89
|
+
// 5. Workstream blocked by failed tasks
|
|
90
|
+
if (hasFailedTasks && !hasPendingOrDispatched) {
|
|
91
|
+
return { hasAction: false, noActionReason: "Workstream blocked by failed prior execution" };
|
|
92
|
+
}
|
|
93
|
+
// 6. Waiting for Product approval
|
|
94
|
+
if (ws.phase === "product_discovery") {
|
|
95
|
+
const approvalLabel = ws.product?.approvalLabel ?? "agent-product-approved";
|
|
96
|
+
const num = ws.origin.number;
|
|
97
|
+
return {
|
|
98
|
+
hasAction: false,
|
|
99
|
+
noActionReason: `Waiting for ${approvalLabel} label on issue #${num} to proceed`
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// 7. Waiting for plan approval
|
|
103
|
+
if (ws.phase === "plan_feedback") {
|
|
104
|
+
const num = ws.origin.number;
|
|
105
|
+
const kind = ws.origin.type === "issue" ? "issue" : "PR";
|
|
106
|
+
return {
|
|
107
|
+
hasAction: false,
|
|
108
|
+
noActionReason: `Waiting for plan approval (${kind} #${num})`
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// 8. Waiting for implementation feedback
|
|
112
|
+
if (ws.phase === "implementation_feedback") {
|
|
113
|
+
return { hasAction: false, noActionReason: "Waiting for implementation feedback" };
|
|
114
|
+
}
|
|
115
|
+
// 9. Waiting for PR review
|
|
116
|
+
if (ws.phase === "pr_review") {
|
|
117
|
+
return { hasAction: false, noActionReason: "Waiting for PR review" };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// 10. No issues or PRs at all
|
|
121
|
+
const repoIssues = issues.filter((i) => i.repoId === repoId);
|
|
122
|
+
const repoPrs = prs.filter((p) => p.repoId === repoId);
|
|
123
|
+
if (repoIssues.length === 0 && repoPrs.length === 0) {
|
|
124
|
+
return { hasAction: false, noActionReason: "No open issues or PRs found for this repository" };
|
|
125
|
+
}
|
|
126
|
+
// 11. Default
|
|
127
|
+
return { hasAction: false, noActionReason: "No open issues or PRs requiring attention this cycle" };
|
|
128
|
+
}
|
|
129
|
+
// ── Workstream Transitions ────────────────────────────────────────────────────
|
|
130
|
+
export async function journalWorkstreamTransitions(opts) {
|
|
131
|
+
const { cycleId, previousWorkstreams, currentWorkstreams, journal, entityMaps } = opts;
|
|
132
|
+
const prevById = new Map(previousWorkstreams.map((ws) => [ws.id, ws]));
|
|
133
|
+
for (const ws of currentWorkstreams) {
|
|
134
|
+
const prev = prevById.get(ws.id);
|
|
135
|
+
if (!prev)
|
|
136
|
+
continue; // new workstream, not a transition
|
|
137
|
+
// Resolve repoId from repoKey (slug format "owner/name")
|
|
138
|
+
const repoId = entityMaps.repoSlugToId.get(ws.repoKey);
|
|
139
|
+
// Resolve issueNumber/prNumber from workstream origin
|
|
140
|
+
let issueNumber;
|
|
141
|
+
let prNumber;
|
|
142
|
+
if (ws.origin.type === "issue") {
|
|
143
|
+
issueNumber = ws.origin.number;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
prNumber = ws.origin.number;
|
|
147
|
+
}
|
|
148
|
+
if (ws.activePrNumber !== undefined) {
|
|
149
|
+
prNumber = ws.activePrNumber;
|
|
150
|
+
}
|
|
151
|
+
const commonOpts = {
|
|
152
|
+
cycleId,
|
|
153
|
+
scope: "workstream",
|
|
154
|
+
scopeId: ws.id,
|
|
155
|
+
workstreamId: ws.id,
|
|
156
|
+
...(repoId !== undefined ? { repoId } : {}),
|
|
157
|
+
...(issueNumber !== undefined ? { issueNumber } : {}),
|
|
158
|
+
...(prNumber !== undefined ? { prNumber } : {})
|
|
159
|
+
};
|
|
160
|
+
// Phase change
|
|
161
|
+
if (prev.phase !== ws.phase) {
|
|
162
|
+
await journal.recordStateTransition({
|
|
163
|
+
...commonOpts,
|
|
164
|
+
from: prev.phase,
|
|
165
|
+
to: ws.phase,
|
|
166
|
+
trigger: "cycle",
|
|
167
|
+
summary: `Workstream ${ws.id} phase: ${prev.phase} → ${ws.phase}`
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// Attention change
|
|
171
|
+
if (prev.attention !== ws.attention) {
|
|
172
|
+
await journal.recordStateTransition({
|
|
173
|
+
...commonOpts,
|
|
174
|
+
from: prev.attention,
|
|
175
|
+
to: ws.attention,
|
|
176
|
+
trigger: "cycle",
|
|
177
|
+
summary: `Workstream ${ws.id} attention: ${prev.attention} → ${ws.attention}`
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
// Status change
|
|
181
|
+
if (prev.status !== ws.status) {
|
|
182
|
+
await journal.recordStateTransition({
|
|
183
|
+
...commonOpts,
|
|
184
|
+
from: prev.status,
|
|
185
|
+
to: ws.status,
|
|
186
|
+
trigger: "cycle",
|
|
187
|
+
summary: `Workstream ${ws.id} status: ${prev.status} → ${ws.status}`
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// ── Task Transitions ──────────────────────────────────────────────────────────
|
|
193
|
+
const MEANINGFUL_TRANSITIONS = new Set([
|
|
194
|
+
"pending→dispatched",
|
|
195
|
+
"pending→completed",
|
|
196
|
+
"dispatched→completed",
|
|
197
|
+
"dispatched→failed",
|
|
198
|
+
"pending→failed",
|
|
199
|
+
"pending→queued",
|
|
200
|
+
"queued→dispatched",
|
|
201
|
+
"queued→failed",
|
|
202
|
+
"dispatched→queued",
|
|
203
|
+
"queued→pending"
|
|
204
|
+
]);
|
|
205
|
+
export async function journalTaskTransitions(opts) {
|
|
206
|
+
const { cycleId, tasksBefore, tasksAfter, journal, entityMaps, workstreams } = opts;
|
|
207
|
+
const prevById = new Map(tasksBefore.map((t) => [t.id, t]));
|
|
208
|
+
for (const task of tasksAfter) {
|
|
209
|
+
const prev = prevById.get(task.id);
|
|
210
|
+
if (!prev)
|
|
211
|
+
continue;
|
|
212
|
+
if (prev.status === task.status)
|
|
213
|
+
continue;
|
|
214
|
+
const transitionKey = `${prev.status}→${task.status}`;
|
|
215
|
+
if (!MEANINGFUL_TRANSITIONS.has(transitionKey))
|
|
216
|
+
continue;
|
|
217
|
+
const ids = resolveTaskJournalIds(task, entityMaps, workstreams);
|
|
218
|
+
await journal.recordStateTransition({
|
|
219
|
+
cycleId,
|
|
220
|
+
scope: task.workstreamId ? "workstream" : "repo",
|
|
221
|
+
scopeId: task.workstreamId ?? task.repoId,
|
|
222
|
+
repoId: task.repoId,
|
|
223
|
+
...(task.workstreamId !== undefined ? { workstreamId: task.workstreamId } : {}),
|
|
224
|
+
...(ids.issueNumber !== undefined ? { issueNumber: ids.issueNumber } : {}),
|
|
225
|
+
...(ids.prNumber !== undefined ? { prNumber: ids.prNumber } : {}),
|
|
226
|
+
from: prev.status,
|
|
227
|
+
to: task.status,
|
|
228
|
+
trigger: "dispatch",
|
|
229
|
+
summary: `Task ${task.id} status: ${prev.status} → ${task.status}`,
|
|
230
|
+
derivedState: { taskId: task.id, kind: task.kind, taskStatus: task.status }
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// ── Worktree Transitions ──────────────────────────────────────────────────────
|
|
235
|
+
export async function journalWorktreeTransitions(opts) {
|
|
236
|
+
const { cycleId, previousWorktrees, currentWorktrees, journal } = opts;
|
|
237
|
+
const prevById = new Map(previousWorktrees.map((wt) => [wt.id, wt]));
|
|
238
|
+
for (const wt of currentWorktrees) {
|
|
239
|
+
const prev = prevById.get(wt.id);
|
|
240
|
+
if (!prev)
|
|
241
|
+
continue;
|
|
242
|
+
if (prev.status === wt.status)
|
|
243
|
+
continue;
|
|
244
|
+
const workstreamId = wt.packet?.parentWorkstreamId;
|
|
245
|
+
await journal.recordStateTransition({
|
|
246
|
+
cycleId,
|
|
247
|
+
scope: "worktree",
|
|
248
|
+
scopeId: wt.id,
|
|
249
|
+
repoId: wt.repoId,
|
|
250
|
+
...(workstreamId !== undefined ? { workstreamId } : {}),
|
|
251
|
+
...(wt.issueNumber !== undefined ? { issueNumber: wt.issueNumber } : {}),
|
|
252
|
+
...(wt.prNumber !== undefined ? { prNumber: wt.prNumber } : {}),
|
|
253
|
+
from: prev.status,
|
|
254
|
+
to: wt.status,
|
|
255
|
+
trigger: "cycle",
|
|
256
|
+
summary: `Worktree ${wt.id} status: ${prev.status} → ${wt.status}`,
|
|
257
|
+
derivedState: { worktreeId: wt.id, branchName: wt.branchName }
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// ── Execution Journaling ──────────────────────────────────────────────────────
|
|
262
|
+
export async function journalNewExecutions(opts) {
|
|
263
|
+
const { cycleId, executionIdsBeforeCycle, dispatchResult, journal, entityMaps, workstreams } = opts;
|
|
264
|
+
const allNewExecutions = dispatchResult.executions.filter((e) => !executionIdsBeforeCycle.has(e.id));
|
|
265
|
+
for (const exec of allNewExecutions) {
|
|
266
|
+
const task = dispatchResult.tasks.find((t) => t.id === exec.taskId);
|
|
267
|
+
if (!task)
|
|
268
|
+
continue;
|
|
269
|
+
if (task.status !== "completed" && task.status !== "failed")
|
|
270
|
+
continue;
|
|
271
|
+
if (task.lastExecutionId !== exec.id)
|
|
272
|
+
continue;
|
|
273
|
+
const ids = resolveTaskJournalIds(task, entityMaps, workstreams);
|
|
274
|
+
await journal.write({
|
|
275
|
+
cycleId,
|
|
276
|
+
scope: "execution",
|
|
277
|
+
scopeId: exec.id,
|
|
278
|
+
repoId: task.repoId,
|
|
279
|
+
...(task.workstreamId !== undefined ? { workstreamId: task.workstreamId } : {}),
|
|
280
|
+
executionId: exec.id,
|
|
281
|
+
...(ids.issueNumber !== undefined ? { issueNumber: ids.issueNumber } : {}),
|
|
282
|
+
...(ids.prNumber !== undefined ? { prNumber: ids.prNumber } : {}),
|
|
283
|
+
category: task.status === "completed" ? "execution_completed" : "execution_failed",
|
|
284
|
+
severity: task.status === "completed" ? "info" : "error",
|
|
285
|
+
summary: task.status === "completed"
|
|
286
|
+
? `Completed ${task.kind} for ${task.repoSlug}`
|
|
287
|
+
: `Failed ${task.kind} for ${task.repoSlug}`,
|
|
288
|
+
observedState: {
|
|
289
|
+
exitCode: exec.exitCode,
|
|
290
|
+
startedAt: exec.startedAt,
|
|
291
|
+
endedAt: exec.endedAt,
|
|
292
|
+
agentProvider: exec.agentProvider,
|
|
293
|
+
promptArtifactPath: exec.promptArtifactPath,
|
|
294
|
+
stdoutArtifactPath: exec.stdoutArtifactPath,
|
|
295
|
+
stderrArtifactPath: exec.stderrArtifactPath
|
|
296
|
+
},
|
|
297
|
+
derivedState: {
|
|
298
|
+
taskId: task.id,
|
|
299
|
+
taskKind: task.kind,
|
|
300
|
+
taskStatus: task.status
|
|
301
|
+
},
|
|
302
|
+
...(task.status === "failed"
|
|
303
|
+
? { noActionReason: exec.errorMessage ?? "Agent execution failed" }
|
|
304
|
+
: {})
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// ── Packet Wave Events ────────────────────────────────────────────────────────
|
|
309
|
+
export async function journalPacketWaveEvents(opts) {
|
|
310
|
+
const { cycleId, packetWaveAdvancementsThisRun, packetWaveBlockedThisRun, journal } = opts;
|
|
311
|
+
for (const adv of packetWaveAdvancementsThisRun) {
|
|
312
|
+
await journal.recordStateTransition({
|
|
313
|
+
cycleId,
|
|
314
|
+
scope: "workstream",
|
|
315
|
+
scopeId: adv.workstreamId,
|
|
316
|
+
workstreamId: adv.workstreamId,
|
|
317
|
+
...(adv.parentPrNumber !== undefined ? { prNumber: adv.parentPrNumber } : {}),
|
|
318
|
+
from: `wave:${adv.fromWaveIndex}`,
|
|
319
|
+
to: `wave:${adv.toWaveIndex}`,
|
|
320
|
+
trigger: "packet_wave_advancement",
|
|
321
|
+
summary: `Packet wave advanced: wave ${adv.fromWaveIndex} → wave ${adv.toWaveIndex} for workstream ${adv.workstreamId}`,
|
|
322
|
+
derivedState: {
|
|
323
|
+
completedPacketIds: adv.completedPacketIds,
|
|
324
|
+
newlyCurrentPacketIds: adv.newlyCurrentPacketIds
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
for (const blocked of packetWaveBlockedThisRun) {
|
|
329
|
+
await journal.recordBlocked({
|
|
330
|
+
cycleId,
|
|
331
|
+
scope: "workstream",
|
|
332
|
+
scopeId: blocked.workstreamId,
|
|
333
|
+
workstreamId: blocked.workstreamId,
|
|
334
|
+
...(blocked.parentPrNumber !== undefined ? { prNumber: blocked.parentPrNumber } : {}),
|
|
335
|
+
reason: `Packet wave blocked: ${blocked.reason}`,
|
|
336
|
+
observedState: {
|
|
337
|
+
currentWaveIndex: blocked.currentWaveIndex,
|
|
338
|
+
incompletePacketIds: blocked.incompletePacketIds
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
export { runCli, buildPacketWaveAdvancementEvaluationForRun } from "./commands/run.js";
|
|
5
|
+
export { buildEffectiveProviderBrokerToolAllowLists } from "./runtime/provider-tools.js";
|
|
6
|
+
export { runDispatchWithMergePrepLifecycle } from "./runtime/dispatch-lifecycle.js";
|
|
7
|
+
export { runLoopCli, SerializedCycleRunner } from "./commands/run-loop.js";
|
|
8
|
+
export { runJournalCli } from "./commands/journal.js";
|
|
9
|
+
export { shouldUseRuntimeStatusScreen } from "./commands/tui.js";
|
|
10
|
+
export { main } from "./dispatcher.js";
|
|
11
|
+
import { main } from "./dispatcher.js";
|
|
12
|
+
import { CliUsageError } from "./errors.js";
|
|
13
|
+
const entrypointPath = process.argv[1];
|
|
14
|
+
if (entrypointPath) {
|
|
15
|
+
const executedAsScript = resolveEntrypointPath(entrypointPath) === resolveEntrypointPath(fileURLToPath(import.meta.url));
|
|
16
|
+
if (executedAsScript) {
|
|
17
|
+
main(process.argv.slice(2)).catch((error) => {
|
|
18
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
19
|
+
const prefix = error instanceof CliUsageError ? "Usage error" : "Run failed";
|
|
20
|
+
process.stderr.write(`${prefix}: ${message}\n`);
|
|
21
|
+
process.exitCode = 1;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function resolveEntrypointPath(entrypointPathValue) {
|
|
26
|
+
try {
|
|
27
|
+
return realpathSync(entrypointPathValue);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return entrypointPathValue;
|
|
31
|
+
}
|
|
32
|
+
}
|