@ai-dossier/sched 0.48.1 → 0.50.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 +94 -7
- package/dist/anchor-close.d.ts +160 -0
- package/dist/anchor-close.d.ts.map +1 -1
- package/dist/anchor-close.js +319 -36
- package/dist/anchor-close.js.map +1 -1
- package/dist/batch-dispatch.d.ts +58 -0
- package/dist/batch-dispatch.d.ts.map +1 -1
- package/dist/batch-dispatch.js +174 -41
- package/dist/batch-dispatch.js.map +1 -1
- package/dist/groundtruth.d.ts +63 -3
- package/dist/groundtruth.d.ts.map +1 -1
- package/dist/groundtruth.js +115 -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 +16 -5
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +9 -0
- package/dist/labels.d.ts.map +1 -1
- package/dist/labels.js +10 -1
- package/dist/labels.js.map +1 -1
- package/dist/state.d.ts +12 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +47 -21
- package/dist/state.js.map +1 -1
- package/dist/status.d.ts +33 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +20 -1
- package/dist/status.js.map +1 -1
- package/dist/types.d.ts +20 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ ai-dossier sched enqueue --issues 101,105..109 --deps 100 --tier strong # flag
|
|
|
28
28
|
ai-dossier sched enqueue --from-manifest batch-prep.json # batch-prep output
|
|
29
29
|
ai-dossier sched start # the dispatch engine: spawn, verify, escalate, watch parked PRs (Ctrl-C stops it)
|
|
30
30
|
ai-dossier sched start --once # a single reconcile+refill tick (cron-style)
|
|
31
|
-
ai-dossier sched status # queue (+pr/cleanup), engine lease, slots, batches, blocked/failed; --anchors adds the
|
|
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
34
|
ai-dossier sched stop --issue 42 # terminate one full-cycle agent and record it stopped (no recovery)
|
|
@@ -1040,7 +1040,9 @@ import {
|
|
|
1040
1040
|
// runBatchCapability — #523)
|
|
1041
1041
|
createSpawnDeps, // real detached-spawn process I/O
|
|
1042
1042
|
createExecGroundTruth, // runstate/gh/git ground truth via subprocesses (injectable exec);
|
|
1043
|
-
// since #468 also gh pr view PR state + setup info from comments
|
|
1043
|
+
// since #468 also gh pr view PR state + setup info from comments;
|
|
1044
|
+
// since #789 also mergedPrForBranch when constructed with a
|
|
1045
|
+
// verified `repo` (resolveProjectRepo)
|
|
1044
1046
|
resolveDispatch, // config → resolved command/prompt/report-prompt/tier-models/timers/
|
|
1045
1047
|
// per-tier spawn specs (tiers — #527)
|
|
1046
1048
|
buildTierCommand, // resolved dispatch + tier + issue → argv, using that tier's OWN
|
|
@@ -1068,6 +1070,12 @@ import {
|
|
|
1068
1070
|
prOfMilestone, // a milestone's pr= key as a positive integer
|
|
1069
1071
|
parsePrViewJson, // gh pr view --json → PR truth (mergedAt/mergeable/blocked label)
|
|
1070
1072
|
parseOpenPrListJson, // gh pr list --head <b> --state open → the open PR we opened (#596)
|
|
1073
|
+
parseMergedPrListJson, // gh pr list --head <b> --base <base> --state merged → MergedPrLookup
|
|
1074
|
+
// found/none/ambiguous — a hand-opened batch PR the ledger never
|
|
1075
|
+
// recorded (#789)
|
|
1076
|
+
type MergedPrLookup, // { kind: 'found', pr, mergedAt } | { kind: 'none' } |
|
|
1077
|
+
// { kind: 'ambiguous', matches } — GroundTruth.mergedPrForBranch's
|
|
1078
|
+
// own return type (#789)
|
|
1071
1079
|
parseSetupInfo, // gh issue view --json comments → teardown inputs
|
|
1072
1080
|
runTeardown, // #468 script teardown for a merged unit (pool return / worktree remove)
|
|
1073
1081
|
isSafeWorktree, // worktree-path containment check (CWE-22)
|
|
@@ -1123,17 +1131,22 @@ import {
|
|
|
1123
1131
|
// so batch-dispatch.ts can share it.
|
|
1124
1132
|
TRANSITIONS, // the transition tables themselves (for previews)
|
|
1125
1133
|
buildStatusReport, // machine-readable status incl. blocked/failed sets
|
|
1126
|
-
// (+ optional `anchorSweep` → `anchors`, #768
|
|
1134
|
+
// (+ optional `anchorSweep` → `anchors`/`orphan_anchors`, #768/#790)
|
|
1127
1135
|
// (+ optional `worktreeReader` → `kept-worktree` warnings, #791)
|
|
1128
1136
|
keptWorktreeCandidates, buildKeptWorktreeWarnings, defaultKeptWorktreeReader, // #791
|
|
1129
1137
|
sweepAnchors, classifyAnchor, membersShippedVerdict, anchorLedgerBlockers,
|
|
1130
1138
|
shippingEvidence, // #768 anchor-close predicate (pure; readers injected)
|
|
1131
1139
|
closeAnchor, // #768 idempotent comment-then-close, `-R <repo>` explicit
|
|
1132
1140
|
anchorCloseMarker, renderAnchorCloseComment, openAnchorBatches, formatBatchStatus,
|
|
1141
|
+
sweepOrphanAnchors, classifyOrphanAnchor, parseOrphanAnchorBody, batchAnchorStillOpen,
|
|
1142
|
+
// #790 orphan sweep — batches gone from state.batches entirely;
|
|
1143
|
+
// pure, GitHub/git only via the injected list/read (never exec)
|
|
1144
|
+
ORPHAN_SWEEP_MAX_ANCHORS, ORPHAN_SWEEP_MAX_MEMBERS, DEFAULT_ORPHAN_BASE_BRANCH, // #790
|
|
1145
|
+
BATCH_ANCHOR_LABEL, // #790, also used by cli/src/batch-compose.ts (single source)
|
|
1133
1146
|
issueCloseReader, parseIssueCloseTruthJson, parseRepoName,
|
|
1134
1147
|
resolveProjectRepo, // #768 owner/name of the cwd repo only when it IS the project's
|
|
1135
1148
|
hasLabel, // case-insensitive label match (#768)
|
|
1136
|
-
validateState, // strict persisted-state validation (1.0.0-1.
|
|
1149
|
+
validateState, // strict persisted-state validation (1.0.0-1.23.0 files migrate)
|
|
1137
1150
|
DEFAULT_ISSUE_PRIORITY, DEFAULT_BATCH_PRIORITY, // priority defaults (0 / 10, #565)
|
|
1138
1151
|
IllegalTransitionError, EnqueueError, CorruptStateError, LockTimeoutError,
|
|
1139
1152
|
SchedNotFoundError,
|
|
@@ -1301,8 +1314,9 @@ after-the-fact recovery, not a missing-data bug.
|
|
|
1301
1314
|
queue data.
|
|
1302
1315
|
- **Schema**: state/config files from #460 (schema 1.0.0), #464 (1.1.0), #468 (1.2.0),
|
|
1303
1316
|
#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)
|
|
1304
|
-
load and migrate to the current schema (1.
|
|
1305
|
-
optional, absent = an `evicted` record with no branch) automatically
|
|
1317
|
+
load and migrate to the current schema (1.25.0 — 1.24.0 was #810: no backfill,
|
|
1318
|
+
`kind`/`branch` optional, absent = an `evicted` record with no branch) automatically
|
|
1319
|
+
(slot `branch`/`last_head`/`pid_start`, slot `role` (inferred from the
|
|
1306
1320
|
unit's queue entry, with the persisted `phase` as a fallback — #500), entry
|
|
1307
1321
|
`pr`/`cleanup`/`failure_evidence`, batch `anchor`/`branch`/`run_id`/`eviction_groups`/
|
|
1308
1322
|
`evictions`/`fix_attempts`/`rebase_attempts`, state-level `last_pr_poll_at` backfill to
|
|
@@ -1315,7 +1329,10 @@ after-the-fact recovery, not a missing-data bug.
|
|
|
1315
1329
|
`consecutive_dispatch_api_errors`/`dispatch_pause_reset_at` backfill to `0`/`null` —
|
|
1316
1330
|
#629; batch `anchor_closed_at` and `anchor_close_failed_reason`/`_since`/`_ticks`
|
|
1317
1331
|
backfill to `null`/`null`/`null`/`0` — #768, schema 1.22.0; batch `member_dispatch`/`member_runs`
|
|
1318
|
-
backfill to `null`/`[]` — #809, schema 1.23.0 — a null mode past `ready` runs serially
|
|
1332
|
+
backfill to `null`/`[]` — #809, schema 1.23.0 — a null mode past `ready` runs serially;
|
|
1333
|
+
`IssueStatus` gains `handed-back`, `EvictionRecord`/`FailureEvidence` gain optional
|
|
1334
|
+
`kind`/`branch` — #810, schema 1.24.0; batch `pr_detect_ambiguous_reason`/`_since`/`_ticks`
|
|
1335
|
+
backfill to `null`/`null`/`0` — #789, schema 1.25.0).
|
|
1319
1336
|
- **`max_slots`** bounds live units (`assigned | running | recovering`); dependency
|
|
1320
1337
|
edges gate readiness — an issue with an unmerged dependency, and a batch behind an
|
|
1321
1338
|
unmerged batch, are never runnable.
|
|
@@ -1408,6 +1425,31 @@ predicate in `anchor-close.ts`) over `blocked`/`done` batches touched within the
|
|
|
1408
1425
|
the journal line says the worktree was kept, and `sched status` then raises a
|
|
1409
1426
|
`kept-worktree` warning for it on every run until the ledger field clears — see
|
|
1410
1427
|
above and `reconcileKeptWorktrees` (#791).
|
|
1428
|
+
- **PR-detection evidence (#789).** When `batch.pr` was never recorded at all — a PR
|
|
1429
|
+
opened by hand, e.g. imboard#4255 — the stale-blocked reconcile also looks for
|
|
1430
|
+
exactly one MERGED pull request whose head is the batch branch, based against
|
|
1431
|
+
`batch.base_branch`, created at or after the batch's own `created_at`, and not from a
|
|
1432
|
+
fork (`GroundTruth.mergedPrForBranch`: `gh pr list -R <repo> --head <branch> --base
|
|
1433
|
+
<base> --state merged`, gated on the same verified `resolveProjectRepo` #768 uses —
|
|
1434
|
+
absent entirely without one). Positive evidence only: zero candidates records
|
|
1435
|
+
nothing and falls through to the branch/members evidence below; two or more is
|
|
1436
|
+
`ambiguous` — no PR is recorded, and only when no OTHER evidence reconciles the
|
|
1437
|
+
batch that same tick is the ambiguity journaled (`pr-detect-ambiguous`, deduped like
|
|
1438
|
+
`pr-watch-failed`: once per `blocked` stretch, re-announced every
|
|
1439
|
+
`JOURNAL_DEDUP_REANNOUNCE_TICKS`; a batch that leaves `blocked` any way — this
|
|
1440
|
+
reconcile's own success, `sched resume --batch`, `sched abandon` — clears the marker,
|
|
1441
|
+
so a later re-block never inherits a stale streak). A batch that still reconciles via
|
|
1442
|
+
`commits-in-base`/`members-closed` does so without a PR and finishes inline, same as
|
|
1443
|
+
before #789. On a match, `batch.pr` is recorded as part of the SAME `blocked →
|
|
1444
|
+
merged` transition (the `stale-failure-reconciled` line then also carries
|
|
1445
|
+
`pr_detected: true`), so the ordinary `deployed` machinery (item 6, "Report dispatch",
|
|
1446
|
+
under "The PR watcher + tail work (#468)" below — shared infrastructure, not
|
|
1447
|
+
per-issue-only despite the section's origin) dispatches the report agent exactly as if the
|
|
1448
|
+
fleet had opened the PR itself, and `sched status`'s existing `pr` column shows it.
|
|
1449
|
+
Recording `batch.pr` never closes the anchor by itself — that stays #768's own
|
|
1450
|
+
evidence-gated `reconcileAnchorClosure`, unchanged. An ambiguous match with no
|
|
1451
|
+
explicit way to resolve it today (#824 tracks a `sched attach-pr` verb) still lets the
|
|
1452
|
+
batch reconcile via its other evidence, or falls to `sched abandon --batch`.
|
|
1411
1453
|
|
|
1412
1454
|
Everything else is surfaced, never closed: `sched status --anchors` (opt-in; `status`
|
|
1413
1455
|
makes no GitHub call without it) lists each still-open anchor of a batch no longer in
|
|
@@ -1419,6 +1461,51 @@ Journal: `anchor-closed` (including "found already closed") and `anchor-close-fa
|
|
|
1419
1461
|
(deduped like `pr-watch-failed`: once per streak, re-announced every
|
|
1420
1462
|
`JOURNAL_DEDUP_REANNOUNCE_TICKS`).
|
|
1421
1463
|
|
|
1464
|
+
### Orphaned anchors — batches dropped from the ledger entirely (#790)
|
|
1465
|
+
|
|
1466
|
+
The sweep above only ever walks `state.batches` (`openAnchorBatches`) — an anchor whose
|
|
1467
|
+
batch fell out of the ledger ENTIRELY (a lost or reset `state.json`; imboard#4244/#4253
|
|
1468
|
+
were exactly this shape: `sched status --json` showed `batches: []` with both anchors
|
|
1469
|
+
still open) is invisible to it. The same `--anchors` flag also runs a GitHub-only sweep
|
|
1470
|
+
for exactly that: `gh issue list --label batch-epic --state open` for the pinned
|
|
1471
|
+
project repo, excluding anchors the ledger sweep already covers, recovering each
|
|
1472
|
+
orphan's members from its own issue-body checklist (`parseOrphanAnchorBody`) and
|
|
1473
|
+
classifying with the same shipping-evidence logic (`classifyOrphanAnchor`, sharing
|
|
1474
|
+
`readMembersShipping`/`anchorGroundVerdict` with `classifyAnchor` above) — minus the
|
|
1475
|
+
ledger check, which cannot apply to something not in the ledger. Reported under
|
|
1476
|
+
`== Orphaned batch anchors (not in ledger) ==` (`orphan_anchors` in `--json`, `null` when
|
|
1477
|
+
the sweep did not run OR the GitHub list call itself failed — rendered `(unavailable)`,
|
|
1478
|
+
never silently as `(none)`) as `orphan-closable-candidate`, `orphan-needs-operator`, or
|
|
1479
|
+
`orphan-unknown` — deliberately never the ledger sweep's bare `closable`: without a
|
|
1480
|
+
ledger there is no eviction/requeue trail to rule out, so even a clean read is a
|
|
1481
|
+
CANDIDATE for a human to confirm. Capped at `ORPHAN_SWEEP_MAX_ANCHORS` (20) classified
|
|
1482
|
+
per run — ledger-tracked anchors are excluded BEFORE that cap, from a GitHub fetch
|
|
1483
|
+
(`ORPHAN_LIST_FETCH_LIMIT`, 100) wider than it, so a busy repo's tracked anchors cannot
|
|
1484
|
+
crowd real orphans out; `orphan_anchors_truncated` (`StatusReport`) and a rendered
|
|
1485
|
+
truncation line fire when candidates still exceeded the cap. The anchor body is
|
|
1486
|
+
untrusted input (anyone who can edit an open `batch-epic` issue controls it): member
|
|
1487
|
+
numbers outside the valid GitHub issue range are dropped, a body over
|
|
1488
|
+
`ORPHAN_SWEEP_MAX_MEMBERS` (50) refuses with NO reads at all (`members-over-cap`), and
|
|
1489
|
+
`base_branch` is checked twice — syntactically (`SAFE_REF_RE`, falling back to
|
|
1490
|
+
`DEFAULT_ORPHAN_BASE_BRANCH`/`main` when unsafe) and then against the expected/configured
|
|
1491
|
+
base (`expectedBaseBranch`, default `main`): a value that names a DIFFERENT — even
|
|
1492
|
+
syntactically valid — branch can never produce `orphan-closable-candidate`, only
|
|
1493
|
+
`orphan-needs-operator` with reason `base-branch-nonstandard:<value>`, since it decides
|
|
1494
|
+
what counts as shipped and an editable issue field is not trusted to pick that
|
|
1495
|
+
unsupervised. Report-only by construction, exactly like the ledger sweep — `list`/`read`
|
|
1496
|
+
are pure lookups with no write capability, proven by a recording-`ExecFn` test over the
|
|
1497
|
+
real gh-argv-building path (`anchor-close.test.ts`).
|
|
1498
|
+
|
|
1499
|
+
Separately, `sched abandon --batch` warns — stderr line plus a journaled
|
|
1500
|
+
`batch-anchor-open-on-abandon` event, and an additive `anchor_open` field on
|
|
1501
|
+
`abandon --json` — rather than refuses, when it dissolves a batch whose anchor is still
|
|
1502
|
+
open on GitHub. Nothing in this codebase currently removes a batch row from
|
|
1503
|
+
`state.batches` (`abandonBatch` dissolves in place, status `dissolved`, still
|
|
1504
|
+
ledger-swept above), so this is a courtesy at the one real moment an operator ends a
|
|
1505
|
+
batch's active lifecycle — never a gate, and never a substitute for the orphan sweep. The
|
|
1506
|
+
CLI's repo-verification exec is timed (10s) on this path too, so an abandon that used to
|
|
1507
|
+
make no network calls at all cannot hang on an unresponsive `gh`.
|
|
1508
|
+
|
|
1422
1509
|
## Hard-block labels are re-read every tick (#544)
|
|
1423
1510
|
|
|
1424
1511
|
#507's enqueue pre-screen resolves an issue's GitHub labels in the CLI and lands the
|
package/dist/anchor-close.d.ts
CHANGED
|
@@ -169,4 +169,164 @@ export declare function sweepAnchors(state: SchedState, read: IssueCloseReader,
|
|
|
169
169
|
repo?: string;
|
|
170
170
|
commitInBase?: CommitInBase;
|
|
171
171
|
}): AnchorReportItem[];
|
|
172
|
+
/** The base branch `parseOrphanAnchorBody` falls back to, and `classifyOrphanAnchor` treats as the expected/project-standard base absent an `expectedBaseBranch` override — what `gate-issue` itself defaults to. */
|
|
173
|
+
export declare const DEFAULT_ORPHAN_BASE_BRANCH = "main";
|
|
174
|
+
/**
|
|
175
|
+
* #790 (security review): the anchor body is untrusted input — anyone who can
|
|
176
|
+
* comment-and-edit an open `batch-epic` issue controls it. Without a cap, a
|
|
177
|
+
* body with thousands of checklist lines would cost thousands of GraphQL
|
|
178
|
+
* reads per sweep (`classifyOrphanAnchor` runs `exhaustive: true`), and one
|
|
179
|
+
* crafted out-of-range member number would error that member's read,
|
|
180
|
+
* `orphan-unknown` it, and abort {@link sweepOrphanAnchors}'s reads for every
|
|
181
|
+
* later anchor. Both are answered the same way: a body over the cap is
|
|
182
|
+
* reported `orphan-needs-operator` (reason `members-over-cap`) with NO reads
|
|
183
|
+
* performed at all — see {@link classifyOrphanAnchor}.
|
|
184
|
+
*/
|
|
185
|
+
export declare const ORPHAN_SWEEP_MAX_MEMBERS = 50;
|
|
186
|
+
/**
|
|
187
|
+
* Recover a batch anchor's members and base branch from its own issue body —
|
|
188
|
+
* the only record left once the batch has dropped out of `state.batches`.
|
|
189
|
+
* The body is the batch-compose format (RFC-0001): one member checklist line
|
|
190
|
+
* per issue, then metadata lines including `base_branch: <name>`. Nothing in
|
|
191
|
+
* this codebase edits an anchor's body after creation (verified: no
|
|
192
|
+
* `gh issue edit ... --body` targets an anchor), so the checklist is already
|
|
193
|
+
* the complete, stable membership — a `batch-setup` runstate milestone would
|
|
194
|
+
* only repeat the same list less reliably (missing entirely for an anchor
|
|
195
|
+
* that predates runstate, or belonging to a requeued run's earlier attempt).
|
|
196
|
+
*
|
|
197
|
+
* Both fields are untrusted (#790 security review) and validated before use:
|
|
198
|
+
* a member number outside `1..MAX_GITHUB_ISSUE_NUMBER` is dropped (never sent
|
|
199
|
+
* to `read`), and `base_branch` falls back to `main` — never propagating a
|
|
200
|
+
* string {@link SAFE_REF_RE} would reject as a git ref — when the metadata
|
|
201
|
+
* line is missing OR unsafe. `main` is what `gate-issue` defaults to, so it
|
|
202
|
+
* is what `shippingEvidence` checks a closer against either way.
|
|
203
|
+
* `members_over_cap` is set (members truncated to {@link ORPHAN_SWEEP_MAX_MEMBERS})
|
|
204
|
+
* rather than silently proceeding on a partial list — the caller reports it,
|
|
205
|
+
* never reads a partial membership as if it were the whole batch.
|
|
206
|
+
*/
|
|
207
|
+
export declare function parseOrphanAnchorBody(body: string): {
|
|
208
|
+
members: number[];
|
|
209
|
+
base_branch: string;
|
|
210
|
+
members_over_cap: boolean;
|
|
211
|
+
};
|
|
212
|
+
/** A batch-epic anchor recovered from GitHub, with no `state.batches` row behind it. */
|
|
213
|
+
export interface OrphanAnchorCandidate {
|
|
214
|
+
anchor: number;
|
|
215
|
+
members: number[];
|
|
216
|
+
base_branch: string;
|
|
217
|
+
/** Set when {@link parseOrphanAnchorBody} truncated the member list at {@link ORPHAN_SWEEP_MAX_MEMBERS} — `classifyOrphanAnchor` refuses to read a partial membership. */
|
|
218
|
+
members_over_cap?: boolean;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* {@link classifyOrphanAnchor}'s answer. Deliberately its own vocabulary —
|
|
222
|
+
* `orphan-closable-candidate`, never bare `closable` — because without a
|
|
223
|
+
* ledger there is no failure-trail evidence (no eviction/requeue record to
|
|
224
|
+
* rule out, the operator's rule from #768 is POSITIVE evidence only): even a
|
|
225
|
+
* verdict with zero disqualifying reasons is a CANDIDATE for a human to
|
|
226
|
+
* confirm, not the ledger-backed `sweepAnchors`' stronger `closable`.
|
|
227
|
+
*/
|
|
228
|
+
export type OrphanAnchorVerdict = {
|
|
229
|
+
kind: 'orphan-closable-candidate' | 'orphan-needs-operator' | 'orphan-unknown';
|
|
230
|
+
reasons: string[];
|
|
231
|
+
members: AnchorMemberReport[];
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* Classify one orphan anchor candidate, or `null` when it turns out not to be
|
|
235
|
+
* an orphan at all — the anchor CLOSED between the GitHub list and this read
|
|
236
|
+
* (the caller only ever lists open anchors), the same list-then-read race
|
|
237
|
+
* `sweepAnchors` answers by `continue`-ing past a freshly `anchor-closed`
|
|
238
|
+
* verdict rather than reporting one. Deliberately NOT `classifyAnchor` /
|
|
239
|
+
* `membersShippedVerdict` verbatim: those consult `anchorLedgerBlockers`,
|
|
240
|
+
* which pushes `member-not-in-ledger:#N` for every member of ANY batch not
|
|
241
|
+
* in `state.batches` — for an orphan that is true by construction, so the
|
|
242
|
+
* ledger-backed predicate would answer `needs-operator` unconditionally and
|
|
243
|
+
* this sweep could never report a clean batch as a candidate. This reuses
|
|
244
|
+
* the SAME shipping-evidence logic ({@link readMembersShipping}, which is
|
|
245
|
+
* {@link shippingEvidence} plus the open/not-completed/handed-back checks)
|
|
246
|
+
* and the SAME anchor-level ground truth ({@link anchorGroundVerdict}) that
|
|
247
|
+
* `classifyAnchor` uses — the ledger check is the one piece structurally
|
|
248
|
+
* inapplicable to something not in the ledger.
|
|
249
|
+
*/
|
|
250
|
+
export declare function classifyOrphanAnchor(candidate: OrphanAnchorCandidate, read: IssueCloseReader, opts?: {
|
|
251
|
+
repo?: string;
|
|
252
|
+
commitInBase?: CommitInBase;
|
|
253
|
+
expectedBaseBranch?: string;
|
|
254
|
+
}): OrphanAnchorVerdict | null;
|
|
255
|
+
/** One open `batch-epic` anchor issue, as listed from GitHub. */
|
|
256
|
+
export interface OpenAnchorIssue {
|
|
257
|
+
number: number;
|
|
258
|
+
title: string;
|
|
259
|
+
body: string;
|
|
260
|
+
}
|
|
261
|
+
/** Lists open `batch-epic` anchor issues for the pinned project repo, or `undefined` on a failed read (unverified repo, `gh` unreachable). */
|
|
262
|
+
export type OpenAnchorLister = () => OpenAnchorIssue[] | undefined;
|
|
263
|
+
/**
|
|
264
|
+
* The exact `gh issue list` argv for the #790 orphan lister — exported so
|
|
265
|
+
* the CLI's real lister (`orphanAnchorListerFor`, `cli/src/commands/sched.ts`)
|
|
266
|
+
* and this package's own tests build the SAME command from ONE definition
|
|
267
|
+
* (#790 review: the earlier AC6 test built its own copy of this argv, so a
|
|
268
|
+
* future change to the production command would not have been caught by
|
|
269
|
+
* it). Read-only by construction — `gh issue list` never writes.
|
|
270
|
+
*/
|
|
271
|
+
export declare function orphanAnchorListArgs(repo: string, limit: number): string[];
|
|
272
|
+
/** `sched status --anchors`' orphan sweep (#790): bounded read cost per run — a GitHub-side sweep must never grow with the repo's total anchor count. */
|
|
273
|
+
export declare const ORPHAN_SWEEP_MAX_ANCHORS = 20;
|
|
274
|
+
/** One `sched status --anchors` orphan-sweep row. */
|
|
275
|
+
export interface OrphanAnchorReportItem {
|
|
276
|
+
anchor: number;
|
|
277
|
+
title: string;
|
|
278
|
+
verdict: OrphanAnchorVerdict['kind'];
|
|
279
|
+
reasons: string[];
|
|
280
|
+
members: AnchorMemberReport[];
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* {@link sweepOrphanAnchors}'s result: the classified rows plus whether the
|
|
284
|
+
* cap left anything unprobed. `truncated` distinguishes "these are ALL the
|
|
285
|
+
* open orphans" from "more may exist beyond what was classified" — silently
|
|
286
|
+
* capping without saying so would read as a complete, clean sweep on a busy
|
|
287
|
+
* repo where it is neither.
|
|
288
|
+
*/
|
|
289
|
+
export interface OrphanAnchorSweepResult {
|
|
290
|
+
items: OrphanAnchorReportItem[];
|
|
291
|
+
/** True when more ledger-unbound open `batch-epic` anchors existed than {@link ORPHAN_SWEEP_MAX_ANCHORS} could classify this run. */
|
|
292
|
+
truncated: boolean;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* `sched status --anchors`' orphan sweep (#790): every open `batch-epic`
|
|
296
|
+
* anchor in the pinned project repo whose batch is no longer in
|
|
297
|
+
* `state.batches` — invisible to {@link sweepAnchors}, which only walks the
|
|
298
|
+
* ledger. Report-only by construction, exactly like `sweepAnchors`: `list`
|
|
299
|
+
* and `read` are both pure lookups with no write capability, so this
|
|
300
|
+
* function has no way to close, comment on, label, or edit anything — it
|
|
301
|
+
* only ever builds and returns {@link OrphanAnchorReportItem} rows.
|
|
302
|
+
*
|
|
303
|
+
* `null` means the list itself failed (an unverified repo, or `gh`
|
|
304
|
+
* unreachable) — distinct from `{items: [], truncated: false}` ("asked,
|
|
305
|
+
* found zero orphans"), the same null-vs-empty convention
|
|
306
|
+
* `StatusReport.anchors`/`orphan_anchors` already use for "the sweep did not
|
|
307
|
+
* run at all". Ledger-tracked anchors are excluded BEFORE the
|
|
308
|
+
* {@link ORPHAN_SWEEP_MAX_ANCHORS} cap is applied — a busy repo with 20+ open
|
|
309
|
+
* ledger-tracked `batch-epic` anchors must not let them crowd out the
|
|
310
|
+
* orphans this sweep exists to find; `truncated=true` when the cap still
|
|
311
|
+
* left real orphan candidates unprobed. Classifying stops at the first
|
|
312
|
+
* failed member/anchor read (the same fail-closed posture as
|
|
313
|
+
* `sweepAnchors`): every anchor after that point is reported `orphan-unknown`
|
|
314
|
+
* without a further call.
|
|
315
|
+
*/
|
|
316
|
+
export declare function sweepOrphanAnchors(state: SchedState, list: OpenAnchorLister, read: IssueCloseReader, opts?: {
|
|
317
|
+
repo?: string;
|
|
318
|
+
commitInBase?: CommitInBase;
|
|
319
|
+
expectedBaseBranch?: string;
|
|
320
|
+
}): OrphanAnchorSweepResult | null;
|
|
321
|
+
/**
|
|
322
|
+
* Whether dissolving `batch` (`sched abandon --batch`) should warn an
|
|
323
|
+
* operator: its anchor is set and, per `read`, still OPEN. Pure predicate —
|
|
324
|
+
* the CLI performs the actual GitHub read and the print/journal side effect
|
|
325
|
+
* (`sched abandon --batch`'s handler). `null` covers both "no anchor to warn
|
|
326
|
+
* about" and "read failed / anchor already closed or missing" alike: this
|
|
327
|
+
* function only ever tells the caller whether to warn, never why not to —
|
|
328
|
+
* `abandonBatch` itself must NEVER refuse over this (#790: refusing would
|
|
329
|
+
* wedge exactly the cleanup `abandon` exists for).
|
|
330
|
+
*/
|
|
331
|
+
export declare function batchAnchorStillOpen(batch: Pick<BatchEntry, 'anchor'>, read: IssueCloseReader): number | null;
|
|
172
332
|
//# sourceMappingURL=anchor-close.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor-close.d.ts","sourceRoot":"","sources":["../src/anchor-close.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;
|
|
1
|
+
{"version":3,"file":"anchor-close.d.ts","sourceRoot":"","sources":["../src/anchor-close.ts"],"names":[],"mappings":"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"}
|