@ai-dossier/sched 0.49.0 → 0.51.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/README.md +100 -9
- package/dist/batch-dispatch.d.ts +82 -0
- package/dist/batch-dispatch.d.ts.map +1 -1
- package/dist/batch-dispatch.js +403 -55
- package/dist/batch-dispatch.js.map +1 -1
- package/dist/groundtruth.d.ts +74 -3
- package/dist/groundtruth.d.ts.map +1 -1
- package/dist/groundtruth.js +141 -14
- package/dist/groundtruth.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/recovery.d.ts +5 -0
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +11 -6
- package/dist/recovery.js.map +1 -1
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +8 -2
- package/dist/scheduler.js.map +1 -1
- package/dist/state.d.ts +15 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +65 -22
- package/dist/state.js.map +1 -1
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +29 -1
- package/dist/status.js.map +1 -1
- package/dist/types.d.ts +43 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ ai-dossier sched start --once # a single reconcile+refill tick (cron-style)
|
|
|
31
31
|
ai-dossier sched status # queue (+pr/cleanup), engine lease, slots, batches, blocked/failed; --anchors adds the ledger anchor sweep (#768) plus orphaned anchors no longer in state.batches (#790)
|
|
32
32
|
ai-dossier sched pause # prevent every new agent process; live units keep running
|
|
33
33
|
ai-dossier sched resume
|
|
34
|
-
ai-dossier sched stop --issue 42 # terminate one full-cycle agent and record it stopped (no recovery)
|
|
34
|
+
ai-dossier sched stop --issue 42 # terminate one full-cycle agent (or stop a parked batch member, #832) and record it stopped (no recovery)
|
|
35
35
|
ai-dossier sched stop --batch b1 # terminate every batch agent (incl. parallel members) and stop unfinished members
|
|
36
36
|
ai-dossier sched abandon --issue 42 --reason "operator abort"
|
|
37
37
|
ai-dossier sched abandon --batch b1 # dissolve; every unshipped member — parked and validated ones included — requeues as full-cycle
|
|
@@ -53,8 +53,10 @@ directory directly, reconstructing costs from the raw dispatch logs rather than
|
|
|
53
53
|
`pause` prevents every new agent process, including escalation and same-tier recovery
|
|
54
54
|
takeovers; it does not terminate agents that are already running. `stop --issue <n>` is the
|
|
55
55
|
single-command stop path: it PID-start-safely terminates that issue's live agent, releases its
|
|
56
|
-
slot, and records a terminal `stopped` outcome that will not recover or escalate.
|
|
57
|
-
|
|
56
|
+
slot, and records a terminal `stopped` outcome that will not recover or escalate. A slot-mode
|
|
57
|
+
member still in a live batch (pending, in work, or validated) must instead be stopped through
|
|
58
|
+
`stop --batch <id>` — a parked (`handed-back`/`evicted`) member can be stopped on its own (#832) —
|
|
59
|
+
which terminates every agent
|
|
58
60
|
the batch holds (its own slot plus one per running parallel member, `batch:<id>#<issue>`) and atomically stops the batch and its unfinished members. `abandon` only records failure
|
|
59
61
|
and releases the slot; it intentionally does not terminate its process.
|
|
60
62
|
|
|
@@ -247,7 +249,9 @@ where every mechanical supervision decision is code, not remembered prose:
|
|
|
247
249
|
`reconcileRecovering`, held in `recovering` until `sched resume`) and every batch
|
|
248
250
|
respawn wedge in `runBatchTick` (tail, member continuation, fix, report, and the
|
|
249
251
|
`ready` → `claimAndSetup` claim — `runValidate`'s local suite run is unaffected) stop
|
|
250
|
-
respawning into the wall, which previously ignored `paused` entirely.
|
|
252
|
+
respawning into the wall, which previously ignored `paused` entirely. (Unverified
|
|
253
|
+
tail/report exits that are NOT API errors are capped separately since #832 —
|
|
254
|
+
`respawn-cap:tail`, or a merged batch closed without its report.) `dispatch-
|
|
251
255
|
health.ts` is its own module (not `engine.ts`) specifically so it is shared by BOTH
|
|
252
256
|
dispatch paths without `engine.ts` and `batch-dispatch.ts` importing each other.
|
|
253
257
|
Batch dispatch logs (per-role, append-mode) are fenced to `log_offset_at_spawn`,
|
|
@@ -1011,6 +1015,51 @@ Dissolve never throws validated work away:
|
|
|
1011
1015
|
State schema 1.24.0: `IssueStatus` gains `handed-back`; `EvictionRecord` gains optional
|
|
1012
1016
|
`kind`/`branch`, `FailureEvidence` optional `branch`.
|
|
1013
1017
|
|
|
1018
|
+
### The tail runs over landed members; a tail verdict is final (#832)
|
|
1019
|
+
|
|
1020
|
+
- **Landed members only.** The tail (aggregate review + integrate/ship) is dispatched with
|
|
1021
|
+
`{members}` = the batch's validated members (`validatedMembersOf`), never the raw
|
|
1022
|
+
`batch.members`, which still lists members that were stopped, handed back, evicted,
|
|
1023
|
+
parked or requeued. Before claiming a slot the engine makes the tail's own two-way check
|
|
1024
|
+
for free (`tailMembersRefusal`): no landed members blocks `no-landed-members`; when
|
|
1025
|
+
`batch.ranges` records boundary commits, a landed member with none blocks
|
|
1026
|
+
`members-mismatch:no-boundary-commit-<n>`, and a boundary commit for a member that did
|
|
1027
|
+
not land blocks `members-mismatch:unlanded-boundary-commit-<n>`. No tail agent is spent.
|
|
1028
|
+
- **`sched stop --issue` on a parked member.** A `handed-back`/`evicted` member of a live
|
|
1029
|
+
batch can be stopped on its own (the operator's cleanup after a hand-back). It moves to
|
|
1030
|
+
`stopped` and keeps its exit record, so it stays out of the landed set. A member still in
|
|
1031
|
+
the batch (pending, in work, or validated) is still refused: use `sched stop --batch`.
|
|
1032
|
+
- **A blocked tail blocks the batch.** A `batch-review` or `batch-ship` `status=blocked`
|
|
1033
|
+
milestone posted by THIS tail dispatch (fenced by the slot's `spawned_at`, which tail and
|
|
1034
|
+
report spawns now stamp; a slot from an older engine with no `spawned_at` skips this
|
|
1035
|
+
check and falls to the capped path below) releases the slot and blocks the batch
|
|
1036
|
+
`tail-blocked:<reason>` once, in one lock. It is never read as an unverified exit to
|
|
1037
|
+
respawn. The agent's milestone is already on the anchor, so the engine posts none. The
|
|
1038
|
+
reason is reduced to a slug.
|
|
1039
|
+
- **Per-phase respawn cap.** `BatchEntry.agent_exits` (`{ phase: 'tail'|'report', count }`,
|
|
1040
|
+
schema 1.26.0) counts unverified exits of the phase's agent; each is journaled with its
|
|
1041
|
+
position (`unverified exit 2/3 (log: …)`). #629 API-error exits are not counted: they
|
|
1042
|
+
have their own pause. After `MAX_BATCH_AGENT_RESPAWNS` (2) respawns, the next unverified
|
|
1043
|
+
exit ends the phase:
|
|
1044
|
+
- **tail** → the batch blocks `respawn-cap:tail`;
|
|
1045
|
+
- **report** → the batch (whose PR is already merged and deployed) closes
|
|
1046
|
+
`deployed → reported → done` without its report, journaling `report-failed
|
|
1047
|
+
respawn-cap:report — batch closed without its report`. A block would not hold there:
|
|
1048
|
+
`reconcileStaleBlockedBatches` walks a blocked batch with a merged PR straight back to
|
|
1049
|
+
`deployed`, and the report agent would respawn.
|
|
1050
|
+
|
|
1051
|
+
Verified progress (review done, park, report done) clears the count, and so does blocking
|
|
1052
|
+
the batch. A spawn that finds the count already spent (a crash between the count and the
|
|
1053
|
+
block) refuses instead of spawning. Before #832, b-20260924-04's tail was respawned four
|
|
1054
|
+
times at the strong tier (~375k tokens) until an operator stopped the batch.
|
|
1055
|
+
- **Clearing these blocks.** `no-landed-members`, `members-mismatch:*`, `tail-blocked:*` and
|
|
1056
|
+
`respawn-cap:tail` have no `sched resume --batch` recheck. `sched status` names the
|
|
1057
|
+
evidence (the anchor's blocked milestone, or the tail log) and the exits: fix the cause
|
|
1058
|
+
on the integration branch and open its PR by hand (`gh pr create --head <branch> --base
|
|
1059
|
+
<base>`; once it merges, `reconcileStaleBlockedBatches` settles the batch), or `sched
|
|
1060
|
+
abandon --batch <id>` (requeues the landed members full-cycle; for `no-landed-members`
|
|
1061
|
+
there is nothing to lose).
|
|
1062
|
+
|
|
1014
1063
|
## API surface
|
|
1015
1064
|
|
|
1016
1065
|
```ts
|
|
@@ -1040,7 +1089,9 @@ import {
|
|
|
1040
1089
|
// runBatchCapability — #523)
|
|
1041
1090
|
createSpawnDeps, // real detached-spawn process I/O
|
|
1042
1091
|
createExecGroundTruth, // runstate/gh/git ground truth via subprocesses (injectable exec);
|
|
1043
|
-
// since #468 also gh pr view PR state + setup info from comments
|
|
1092
|
+
// since #468 also gh pr view PR state + setup info from comments;
|
|
1093
|
+
// since #789 also mergedPrForBranch when constructed with a
|
|
1094
|
+
// verified `repo` (resolveProjectRepo)
|
|
1044
1095
|
resolveDispatch, // config → resolved command/prompt/report-prompt/tier-models/timers/
|
|
1045
1096
|
// per-tier spawn specs (tiers — #527)
|
|
1046
1097
|
buildTierCommand, // resolved dispatch + tier + issue → argv, using that tier's OWN
|
|
@@ -1068,6 +1119,12 @@ import {
|
|
|
1068
1119
|
prOfMilestone, // a milestone's pr= key as a positive integer
|
|
1069
1120
|
parsePrViewJson, // gh pr view --json → PR truth (mergedAt/mergeable/blocked label)
|
|
1070
1121
|
parseOpenPrListJson, // gh pr list --head <b> --state open → the open PR we opened (#596)
|
|
1122
|
+
parseMergedPrListJson, // gh pr list --head <b> --base <base> --state merged → MergedPrLookup
|
|
1123
|
+
// found/none/ambiguous — a hand-opened batch PR the ledger never
|
|
1124
|
+
// recorded (#789)
|
|
1125
|
+
type MergedPrLookup, // { kind: 'found', pr, mergedAt } | { kind: 'none' } |
|
|
1126
|
+
// { kind: 'ambiguous', matches } — GroundTruth.mergedPrForBranch's
|
|
1127
|
+
// own return type (#789)
|
|
1071
1128
|
parseSetupInfo, // gh issue view --json comments → teardown inputs
|
|
1072
1129
|
runTeardown, // #468 script teardown for a merged unit (pool return / worktree remove)
|
|
1073
1130
|
isSafeWorktree, // worktree-path containment check (CWE-22)
|
|
@@ -1138,7 +1195,7 @@ import {
|
|
|
1138
1195
|
issueCloseReader, parseIssueCloseTruthJson, parseRepoName,
|
|
1139
1196
|
resolveProjectRepo, // #768 owner/name of the cwd repo only when it IS the project's
|
|
1140
1197
|
hasLabel, // case-insensitive label match (#768)
|
|
1141
|
-
validateState, // strict persisted-state validation (1.0.0-1.
|
|
1198
|
+
validateState, // strict persisted-state validation (1.0.0-1.23.0 files migrate)
|
|
1142
1199
|
DEFAULT_ISSUE_PRIORITY, DEFAULT_BATCH_PRIORITY, // priority defaults (0 / 10, #565)
|
|
1143
1200
|
IllegalTransitionError, EnqueueError, CorruptStateError, LockTimeoutError,
|
|
1144
1201
|
SchedNotFoundError,
|
|
@@ -1175,6 +1232,9 @@ import {
|
|
|
1175
1232
|
isMemberComplete, isMemberBlocked, // member milestone predicates (member-trail gated: mode=slot or batch=<id>, #677)
|
|
1176
1233
|
isBatchTailParked, // batch-ship awaiting-merge + pr= — the batch park signal
|
|
1177
1234
|
isBatchPhaseDone, // <phase> done on the anchor (batch-review/batch-report)
|
|
1235
|
+
batchPhaseBlockedReason, // #832: slugged reason of a `<phase> blocked` anchor milestone posted by THIS dispatch; null otherwise
|
|
1236
|
+
MAX_BATCH_AGENT_RESPAWNS, // #832: tail/report respawns after unverified exits before the phase ends (2)
|
|
1237
|
+
type BatchAgentExits, type BatchAgentPhase, // #832: BatchEntry.agent_exits ({ phase: 'tail'|'report', count })
|
|
1178
1238
|
batchOfUnit, // batch:<id> → <id>; null for issue units or malformed ids
|
|
1179
1239
|
} from '@ai-dossier/sched';
|
|
1180
1240
|
```
|
|
@@ -1306,8 +1366,9 @@ after-the-fact recovery, not a missing-data bug.
|
|
|
1306
1366
|
queue data.
|
|
1307
1367
|
- **Schema**: state/config files from #460 (schema 1.0.0), #464 (1.1.0), #468 (1.2.0),
|
|
1308
1368
|
#472 (1.3.0), #500 (1.4.0), #505 (1.5.0), #504 (1.6.0), #523 (1.7.0) and #524 (1.8.0)
|
|
1309
|
-
load and migrate to the current schema (1.
|
|
1310
|
-
optional, absent = an `evicted` record with no branch) automatically
|
|
1369
|
+
load and migrate to the current schema (1.26.0 — 1.24.0 was #810: no backfill,
|
|
1370
|
+
`kind`/`branch` optional, absent = an `evicted` record with no branch) automatically
|
|
1371
|
+
(slot `branch`/`last_head`/`pid_start`, slot `role` (inferred from the
|
|
1311
1372
|
unit's queue entry, with the persisted `phase` as a fallback — #500), entry
|
|
1312
1373
|
`pr`/`cleanup`/`failure_evidence`, batch `anchor`/`branch`/`run_id`/`eviction_groups`/
|
|
1313
1374
|
`evictions`/`fix_attempts`/`rebase_attempts`, state-level `last_pr_poll_at` backfill to
|
|
@@ -1320,7 +1381,12 @@ after-the-fact recovery, not a missing-data bug.
|
|
|
1320
1381
|
`consecutive_dispatch_api_errors`/`dispatch_pause_reset_at` backfill to `0`/`null` —
|
|
1321
1382
|
#629; batch `anchor_closed_at` and `anchor_close_failed_reason`/`_since`/`_ticks`
|
|
1322
1383
|
backfill to `null`/`null`/`null`/`0` — #768, schema 1.22.0; batch `member_dispatch`/`member_runs`
|
|
1323
|
-
backfill to `null`/`[]` — #809, schema 1.23.0 — a null mode past `ready` runs serially
|
|
1384
|
+
backfill to `null`/`[]` — #809, schema 1.23.0 — a null mode past `ready` runs serially;
|
|
1385
|
+
`IssueStatus` gains `handed-back`, `EvictionRecord`/`FailureEvidence` gain optional
|
|
1386
|
+
`kind`/`branch` — #810, schema 1.24.0; batch `pr_detect_ambiguous_reason`/`_since`/`_ticks`
|
|
1387
|
+
backfill to `null`/`null`/`0` — #789, schema 1.25.0).
|
|
1388
|
+
Schema 1.26.0 (#832): `BatchEntry` gains `agent_exits` (the per-phase tail/report
|
|
1389
|
+
respawn counter); `null` is backfilled on load.
|
|
1324
1390
|
- **`max_slots`** bounds live units (`assigned | running | recovering`); dependency
|
|
1325
1391
|
edges gate readiness — an issue with an unmerged dependency, and a batch behind an
|
|
1326
1392
|
unmerged batch, are never runnable.
|
|
@@ -1413,6 +1479,31 @@ predicate in `anchor-close.ts`) over `blocked`/`done` batches touched within the
|
|
|
1413
1479
|
the journal line says the worktree was kept, and `sched status` then raises a
|
|
1414
1480
|
`kept-worktree` warning for it on every run until the ledger field clears — see
|
|
1415
1481
|
above and `reconcileKeptWorktrees` (#791).
|
|
1482
|
+
- **PR-detection evidence (#789).** When `batch.pr` was never recorded at all — a PR
|
|
1483
|
+
opened by hand, e.g. imboard#4255 — the stale-blocked reconcile also looks for
|
|
1484
|
+
exactly one MERGED pull request whose head is the batch branch, based against
|
|
1485
|
+
`batch.base_branch`, created at or after the batch's own `created_at`, and not from a
|
|
1486
|
+
fork (`GroundTruth.mergedPrForBranch`: `gh pr list -R <repo> --head <branch> --base
|
|
1487
|
+
<base> --state merged`, gated on the same verified `resolveProjectRepo` #768 uses —
|
|
1488
|
+
absent entirely without one). Positive evidence only: zero candidates records
|
|
1489
|
+
nothing and falls through to the branch/members evidence below; two or more is
|
|
1490
|
+
`ambiguous` — no PR is recorded, and only when no OTHER evidence reconciles the
|
|
1491
|
+
batch that same tick is the ambiguity journaled (`pr-detect-ambiguous`, deduped like
|
|
1492
|
+
`pr-watch-failed`: once per `blocked` stretch, re-announced every
|
|
1493
|
+
`JOURNAL_DEDUP_REANNOUNCE_TICKS`; a batch that leaves `blocked` any way — this
|
|
1494
|
+
reconcile's own success, `sched resume --batch`, `sched abandon` — clears the marker,
|
|
1495
|
+
so a later re-block never inherits a stale streak). A batch that still reconciles via
|
|
1496
|
+
`commits-in-base`/`members-closed` does so without a PR and finishes inline, same as
|
|
1497
|
+
before #789. On a match, `batch.pr` is recorded as part of the SAME `blocked →
|
|
1498
|
+
merged` transition (the `stale-failure-reconciled` line then also carries
|
|
1499
|
+
`pr_detected: true`), so the ordinary `deployed` machinery (item 6, "Report dispatch",
|
|
1500
|
+
under "The PR watcher + tail work (#468)" below — shared infrastructure, not
|
|
1501
|
+
per-issue-only despite the section's origin) dispatches the report agent exactly as if the
|
|
1502
|
+
fleet had opened the PR itself, and `sched status`'s existing `pr` column shows it.
|
|
1503
|
+
Recording `batch.pr` never closes the anchor by itself — that stays #768's own
|
|
1504
|
+
evidence-gated `reconcileAnchorClosure`, unchanged. An ambiguous match with no
|
|
1505
|
+
explicit way to resolve it today (#824 tracks a `sched attach-pr` verb) still lets the
|
|
1506
|
+
batch reconcile via its other evidence, or falls to `sched abandon --batch`.
|
|
1416
1507
|
|
|
1417
1508
|
Everything else is surfaced, never closed: `sched status --anchors` (opt-in; `status`
|
|
1418
1509
|
makes no GitHub call without it) lists each still-open anchor of a batch no longer in
|
package/dist/batch-dispatch.d.ts
CHANGED
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
* before returning, so a member's first command is never the one that
|
|
62
62
|
* discovers `node_modules` is missing (`env-cold`, `docs/agent-traps.md`).
|
|
63
63
|
*/
|
|
64
|
+
import { type CommitInBase, type IssueCloseReader } from './anchor-close';
|
|
64
65
|
import { type ResolvedDispatch, type SpawnDeps } from './dispatch';
|
|
65
66
|
import { type GroundTruth } from './groundtruth';
|
|
66
67
|
import { type Journal } from './journal';
|
|
@@ -171,6 +172,20 @@ export interface MemberFailure {
|
|
|
171
172
|
* scheduler lands it there.
|
|
172
173
|
*/
|
|
173
174
|
export declare function memberBranchFor(batchId: string, memberIndex: number, issue: number): string;
|
|
175
|
+
/**
|
|
176
|
+
* #832: why the tail must NOT be dispatched over `landed`, or null when it may.
|
|
177
|
+
* The deterministic half of the check the tail agent itself makes before
|
|
178
|
+
* integrating (the members it is told about and the members it derives from
|
|
179
|
+
* the integration branch's boundary commits must agree) — made here for free
|
|
180
|
+
* instead of by a strong-tier agent that then exits `members-mismatch`.
|
|
181
|
+
* `batch.ranges` is the recorded boundary attribution (recomputed at every
|
|
182
|
+
* landing); when it is empty nothing was attributed, so there is nothing to
|
|
183
|
+
* cross-check. Invariant this relies on: `ranges` names only landed members —
|
|
184
|
+
* every exit path that reverts a member also drops its range
|
|
185
|
+
* (`recovery.ts`'s partial dissolve); a path that re-derived `ranges` from
|
|
186
|
+
* `git log` after a revert would make this refuse a healthy batch.
|
|
187
|
+
*/
|
|
188
|
+
export declare function tailMembersRefusal(batch: BatchEntry, landed: readonly number[]): string | null;
|
|
174
189
|
/**
|
|
175
190
|
* Evict the current member and either dissolve, or continue the batch via
|
|
176
191
|
* `advanceMemberOrValidate` — the shared tail of both member-failure rails
|
|
@@ -237,6 +252,73 @@ export declare function resumeBlockedGate(deps: BatchDispatchDeps, config: Sched
|
|
|
237
252
|
blockedBy?: 'inconclusive' | 'unevidenced-failure';
|
|
238
253
|
detail?: string;
|
|
239
254
|
};
|
|
255
|
+
/**
|
|
256
|
+
* #832: how many times one tail-work phase's agent (`tail` or `report`) is
|
|
257
|
+
* RESPAWNED after exiting unverified — the first dispatch plus this many
|
|
258
|
+
* respawns; the next unverified exit ends the phase instead. The #629 class:
|
|
259
|
+
* the tick loop's "same wedge" arm respawns a dead tail/report agent on its
|
|
260
|
+
* own, so without a cap an agent that exits without a verdict is
|
|
261
|
+
* redispatched forever (b-20260924-04: the strong-tier tail four times,
|
|
262
|
+
* ~375k tokens, stopped only by hand).
|
|
263
|
+
*/
|
|
264
|
+
export declare const MAX_BATCH_AGENT_RESPAWNS = 2;
|
|
265
|
+
/**
|
|
266
|
+
* #686: reconcile a `blocked` batch whose work demonstrably shipped anyway.
|
|
267
|
+
* `reconcilePrWatch` above only watches `awaiting-merge` batches, and
|
|
268
|
+
* `resumeBlockedGate` only re-runs the gate — so a batch blocked on a stale
|
|
269
|
+
* verdict (the concrete case: `gate-inconclusive:test.focused`, itself often
|
|
270
|
+
* a #690-declined gate TIMEOUT) whose PR merged out of band — or whose every
|
|
271
|
+
* member commit is already in the base — stayed blocked FOREVER: no report,
|
|
272
|
+
* no teardown, an operator-visible `blocked` row, and members stuck
|
|
273
|
+
* `in-work`. Sibling of the per-issue `reconcileStaleFailedParks`
|
|
274
|
+
* (engine.ts) under the same principle: ground truth beats the ledger, for
|
|
275
|
+
* ANY stale verdict — the blocked_reason is deliberately not examined.
|
|
276
|
+
*
|
|
277
|
+
* Evidence (cheapest first): the batch PR is MERGED with a real timestamp (a
|
|
278
|
+
* merged batch PR contains the whole batch branch) — including one
|
|
279
|
+
* `batch.pr` never recorded at all (#789): when `pr === null`, before falling
|
|
280
|
+
* through to the weaker branch/members evidence below, look for exactly one
|
|
281
|
+
* MERGED PR whose head is the batch branch (`imboard#4255`, a hand-opened PR
|
|
282
|
+
* the ledger never saw). Positive evidence only — zero candidates changes
|
|
283
|
+
* nothing, more than one is `ambiguous` and journaled rather than guessed —
|
|
284
|
+
* or the batch branch has fully landed in the base branch. A survivability
|
|
285
|
+
* guard applies to every path (see `everySurvivingMemberDispatched`) — a
|
|
286
|
+
* batch with a surviving member that was never dispatched is not
|
|
287
|
+
* reconcilable.
|
|
288
|
+
*
|
|
289
|
+
* On reconcile the batch joins the SAME rail a normally-merged batch takes:
|
|
290
|
+
* `blocked → merged → deployed` (the `blocked → merged` edge exists for
|
|
291
|
+
* exactly this caller), surviving members walked to `done` along legal
|
|
292
|
+
* edges, and — when the batch now carries a PR (recorded before or detected
|
|
293
|
+
* here) — the ordinary `deployed` machinery dispatches the report agent next
|
|
294
|
+
* tick, with teardown after `batch-report done`. With no PR at all no report
|
|
295
|
+
* agent can be prompted (it names the PR), so the same lock continues
|
|
296
|
+
* `deployed → reported → done` and the worktree is torn down here instead;
|
|
297
|
+
* the journal line says why no report agent was dispatched rather than
|
|
298
|
+
* leaving the gap silent.
|
|
299
|
+
*
|
|
300
|
+
* Bounded by construction: only `blocked` batches within the window are
|
|
301
|
+
* examined, the PR check is one `gh` call, git runs only when PR evidence
|
|
302
|
+
* didn't already reconcile, and a reconciled batch leaves `blocked` — the
|
|
303
|
+
* one journal line fires on the one-way transition, never per-tick (the
|
|
304
|
+
* #632 lesson: no journal inside a loop that doesn't terminate the unit).
|
|
305
|
+
*/
|
|
306
|
+
export declare function reconcileStaleBlockedBatches(deps: BatchDispatchDeps, now: Date, result: BatchTickResult, anchorCtx: AnchorTickContext | undefined): void;
|
|
307
|
+
/**
|
|
308
|
+
* #768: what one tick's anchor work reads GitHub and git through — built once
|
|
309
|
+
* per tick so the stale-blocked reconcile and the anchor close never read the
|
|
310
|
+
* same issue twice in a tick. `undefined` when the tick cannot verify anything
|
|
311
|
+
* (no issue-closure ground truth, or no verified `anchorRepo`): then neither
|
|
312
|
+
* pass acts at all.
|
|
313
|
+
*/
|
|
314
|
+
interface AnchorTickContext {
|
|
315
|
+
repo: string;
|
|
316
|
+
/** Cached for the tick — the verdict passes. */
|
|
317
|
+
read: IssueCloseReader;
|
|
318
|
+
/** Uncached — the re-read immediately before an irreversible close. */
|
|
319
|
+
readFresh: IssueCloseReader;
|
|
320
|
+
commitInBase: CommitInBase;
|
|
321
|
+
}
|
|
240
322
|
/**
|
|
241
323
|
* How a batch should dispatch its members (#809) — decided once, at the
|
|
242
324
|
* `ready → executing` claim, and persisted on `BatchEntry.member_dispatch`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-dispatch.d.ts","sourceRoot":"","sources":["../src/batch-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;
|
|
1
|
+
{"version":3,"file":"batch-dispatch.d.ts","sourceRoot":"","sources":["../src/batch-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAUH,OAAO,EAIL,KAAK,YAAY,EAGjB,KAAK,gBAAgB,EAGtB,MAAM,gBAAgB,CAAC;AAUxB,OAAO,EAaL,KAAK,gBAAgB,EAGrB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGL,KAAK,WAAW,EAYjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,OAAO,EAAa,MAAM,WAAW,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EACL,KAAK,iBAAiB,EAYtB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAgCpB,OAAO,EACL,KAAK,QAAQ,EAMd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAGV,UAAU,EAEV,oBAAoB,EAKpB,kBAAkB,EAClB,cAAc,EAId,WAAW,EACX,UAAU,EAEX,MAAM,SAAS,CAAC;AAcjB,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,8DAA8D;AAC9D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,SAAS,CAAC;IACrB,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,iBAAiB,KAAK,WAAW,CAAC;IACrE;;;;;;;;;;;;;;;;;;;OAmBG;IACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,oBAAoB,CAAC;IACjF,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,8FAA8F;AAC9F,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uFAAuF;IACvF,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,8FAA8F;IAC9F,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;OAIG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;AAklBD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3F;AAk4BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAa9F;AAikBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,IAAI,EACT,MAAM,EAAE,eAAe,GACtB,IAAI,CA+BN;AA2TD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,IAAI,GACR;IACD,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,cAAc,GAAG,qBAAqB,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CA2KA;AAslBD;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAsnB1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,iBAAiB,EACvB,GAAG,EAAE,IAAI,EACT,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,iBAAiB,GAAG,SAAS,GACvC,IAAI,CA+LN;AA4ED;;;;;;GAMG;AACH,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,IAAI,EAAE,gBAAgB,CAAC;IACvB,uEAAuE;IACvE,SAAS,EAAE,gBAAgB,CAAC;IAC5B,YAAY,EAAE,YAAY,CAAC;CAC5B;AA+QD;;;;;;;;;;;GAWG;AACH,oCAAoC;AACpC,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,WAAW,GAClB,kBAAkB,CAQpB;AAozBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,gBAAgB,GACzB,eAAe,CAgSjB"}
|