@ai-dossier/sched 0.48.0 → 0.48.1
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 +31 -4
- package/dist/batch-dispatch.d.ts.map +1 -1
- package/dist/batch-dispatch.js +67 -0
- package/dist/batch-dispatch.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/status.d.ts +78 -4
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +233 -3
- package/dist/status.js.map +1 -1
- package/dist/teardown.d.ts +9 -0
- package/dist/teardown.d.ts.map +1 -1
- package/dist/teardown.js +19 -10
- package/dist/teardown.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1124,6 +1124,8 @@ import {
|
|
|
1124
1124
|
TRANSITIONS, // the transition tables themselves (for previews)
|
|
1125
1125
|
buildStatusReport, // machine-readable status incl. blocked/failed sets
|
|
1126
1126
|
// (+ optional `anchorSweep` → `anchors`, #768; null without it)
|
|
1127
|
+
// (+ optional `worktreeReader` → `kept-worktree` warnings, #791)
|
|
1128
|
+
keptWorktreeCandidates, buildKeptWorktreeWarnings, defaultKeptWorktreeReader, // #791
|
|
1127
1129
|
sweepAnchors, classifyAnchor, membersShippedVerdict, anchorLedgerBlockers,
|
|
1128
1130
|
shippingEvidence, // #768 anchor-close predicate (pure; readers injected)
|
|
1129
1131
|
closeAnchor, // #768 idempotent comment-then-close, `-R <repo>` explicit
|
|
@@ -1327,10 +1329,14 @@ after-the-fact recovery, not a missing-data bug.
|
|
|
1327
1329
|
can be manual (`sched pause`) or automatic (dispatch-health, #505/#629 above); `sched
|
|
1328
1330
|
resume` clears the flag and both dispatch-health streaks.
|
|
1329
1331
|
|
|
1330
|
-
## Status health warnings (#776)
|
|
1332
|
+
## Status health warnings (#776, #791)
|
|
1331
1333
|
|
|
1332
|
-
`sched status` (and `warnings[]` in `--json
|
|
1333
|
-
|
|
1334
|
+
`sched status` (and `warnings[]` in `--json`) flags state nobody came back to, each with
|
|
1335
|
+
its exact remedy. Most kinds come from `buildStatusWarnings`, pure over state + engine
|
|
1336
|
+
lease + clock; `kept-worktree` (below) comes from the separate `buildKeptWorktreeWarnings`,
|
|
1337
|
+
since it needs local git/fs reads — it only appears when the caller passes a
|
|
1338
|
+
`KeptWorktreeReader` to `buildStatusReport` (the CLI always does; a test harness omits it
|
|
1339
|
+
to skip the check entirely):
|
|
1334
1340
|
|
|
1335
1341
|
- **`long-pause`** — paused for more than 24 h (`STATUS_HEALTH_WARNING_AGE_MS`), measured
|
|
1336
1342
|
from `paused_at`, which `setPaused` stamps on the running → paused edge and clears on
|
|
@@ -1344,6 +1350,25 @@ nobody came back to, each with its exact remedy:
|
|
|
1344
1350
|
closed issue sets the entry's sticky `stale_closed_at`, journals `stale-closed` once, and
|
|
1345
1351
|
the recovery rail never respawns it (even after `sched resume`). Report slots are exempt:
|
|
1346
1352
|
their issue is closed at merge by design. Remedy: `sched stop --issue N`.
|
|
1353
|
+
- **`kept-worktree`** (#791) — a `done` batch whose `worktree` or `member_worktree` is
|
|
1354
|
+
still set in the ledger: the `members-closed` stale-blocked reconcile below
|
|
1355
|
+
intentionally leaves it in place (it may hold unpushed operator repair work), and
|
|
1356
|
+
nothing else surfaced it until now. For each kept path, `sched status` reports:
|
|
1357
|
+
whether it still exists on disk; whether it is pool-claimed (the claim is held
|
|
1358
|
+
indefinitely until returned); and, via two local, read-only `git` probes scoped to
|
|
1359
|
+
that worktree's own `HEAD` (`git --no-optional-locks status --porcelain`, `git log
|
|
1360
|
+
HEAD --not --remotes`), whether it has uncommitted or unpushed work. The remedy is the
|
|
1361
|
+
exact `git worktree remove <path>` or `worktree-pool return --path <path>` command,
|
|
1362
|
+
properly shell-quoted — report-only, never executed. `reconcileKeptWorktrees`
|
|
1363
|
+
(`batch-dispatch.ts`, run every tick) separately clears the ledger's `worktree`/
|
|
1364
|
+
`pool_claimed` fields once there is DEFINITIVE evidence the cleanup already
|
|
1365
|
+
happened — the path no longer exists, or the pool itself reports it back as a warm
|
|
1366
|
+
spare — so the warning does not persist after the operator (or the pool) has already
|
|
1367
|
+
dealt with it; it never removes anything itself. A candidate whose path is currently
|
|
1368
|
+
claimed by a different, still in-flight batch is skipped (a returned pool worktree can
|
|
1369
|
+
be re-issued before the done batch's own field clears). Local-git-only, capped at 10
|
|
1370
|
+
probed candidates per run — no network call, so unlike `sched status --anchors` this
|
|
1371
|
+
runs by default.
|
|
1347
1372
|
|
|
1348
1373
|
## Batch anchors close only on positive evidence (#768)
|
|
1349
1374
|
|
|
@@ -1380,7 +1405,9 @@ predicate in `anchor-close.ts`) over `blocked`/`done` batches touched within the
|
|
|
1380
1405
|
for #686's stale-blocked reconcile (`members-closed`), which survives the mandated
|
|
1381
1406
|
rebase-merge that makes the ancestry probe structurally dead. It finishes the terminal
|
|
1382
1407
|
rail inline but never tears the blocked worktree down (it may hold unpushed work);
|
|
1383
|
-
the journal line says the worktree was kept
|
|
1408
|
+
the journal line says the worktree was kept, and `sched status` then raises a
|
|
1409
|
+
`kept-worktree` warning for it on every run until the ledger field clears — see
|
|
1410
|
+
above and `reconcileKeptWorktrees` (#791).
|
|
1384
1411
|
|
|
1385
1412
|
Everything else is surfaced, never closed: `sched status --anchors` (opt-in; `status`
|
|
1386
1413
|
makes no GitHub call without it) lists each still-open anchor of a batch no longer in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-dispatch.d.ts","sourceRoot":"","sources":["../src/batch-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AA8BH,OAAO,EAaL,KAAK,gBAAgB,EAGrB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAEL,KAAK,WAAW,EAWjB,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,EAWtB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AA8BpB,OAAO,
|
|
1
|
+
{"version":3,"file":"batch-dispatch.d.ts","sourceRoot":"","sources":["../src/batch-dispatch.ts"],"names":[],"mappings":"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"}
|
package/dist/batch-dispatch.js
CHANGED
|
@@ -3024,6 +3024,72 @@ function reconcileStaleBlockedBatches(deps, now, result, anchorCtx) {
|
|
|
3024
3024
|
}
|
|
3025
3025
|
}
|
|
3026
3026
|
}
|
|
3027
|
+
/**
|
|
3028
|
+
* #791: once a `done` batch's kept worktree (left in place by the
|
|
3029
|
+
* `members-closed` branch above) is DEFINITIVELY gone — the path no longer
|
|
3030
|
+
* exists on disk, or the pool itself now reports it back as a warm spare —
|
|
3031
|
+
* clear the ledger's `worktree`/`pool_claimed` (and, separately,
|
|
3032
|
+
* `member_worktree`/`member_pool_claimed`) fields so `sched status`'s
|
|
3033
|
+
* `kept-worktree` warning does not persist after the operator's cleanup
|
|
3034
|
+
* already happened. Ledger-only, by construction: this function reads
|
|
3035
|
+
* `fsExists` and `worktree-pool status --json` (both read-only) and never
|
|
3036
|
+
* builds a `git worktree remove` / `worktree-pool return` argv — the actual
|
|
3037
|
+
* removal stays entirely the operator's call, exactly like the warning
|
|
3038
|
+
* itself. Bounded the same way the warning's own candidate scan is: only
|
|
3039
|
+
* `done` batches carrying a kept worktree are considered, which in practice
|
|
3040
|
+
* is a small set.
|
|
3041
|
+
*/
|
|
3042
|
+
function reconcileKeptWorktrees(deps, now) {
|
|
3043
|
+
const state = deps.store.load();
|
|
3044
|
+
const fsExists = deps.fsExists ?? ((p) => fs.existsSync(p));
|
|
3045
|
+
const candidates = state.batches.filter((b) => b.status === 'done' && (b.worktree !== null || b.member_worktree !== null));
|
|
3046
|
+
if (candidates.length === 0)
|
|
3047
|
+
return;
|
|
3048
|
+
const needsPoolCheck = candidates.some((b) => (b.worktree !== null && b.pool_claimed) ||
|
|
3049
|
+
(b.member_worktree !== null && b.member_pool_claimed));
|
|
3050
|
+
// One pool query per TICK, not per candidate — `worktree-pool status` is a
|
|
3051
|
+
// real subprocess (`npx ...`), and this reconcile is meant to be cheap.
|
|
3052
|
+
const poolStatusJson = needsPoolCheck
|
|
3053
|
+
? deps.exec(teardown_1.POOL_BIN, [...teardown_1.POOL_ARGS_PREFIX, 'status', '--json'], deps.repoDir)
|
|
3054
|
+
: null;
|
|
3055
|
+
const goneOrReturned = (worktree, poolClaimed) => {
|
|
3056
|
+
if (!fsExists(worktree))
|
|
3057
|
+
return true;
|
|
3058
|
+
if (poolClaimed && poolStatusJson !== null) {
|
|
3059
|
+
return (0, teardown_1.poolEntryFor)(poolStatusJson, worktree) === 'warm';
|
|
3060
|
+
}
|
|
3061
|
+
return false;
|
|
3062
|
+
};
|
|
3063
|
+
for (const batch of candidates) {
|
|
3064
|
+
const clears = {};
|
|
3065
|
+
const clearedFields = [];
|
|
3066
|
+
if (batch.worktree !== null && goneOrReturned(batch.worktree, batch.pool_claimed)) {
|
|
3067
|
+
clears.worktree = null;
|
|
3068
|
+
clears.pool_claimed = false;
|
|
3069
|
+
clearedFields.push('worktree', 'pool_claimed');
|
|
3070
|
+
}
|
|
3071
|
+
if (batch.member_worktree !== null &&
|
|
3072
|
+
goneOrReturned(batch.member_worktree, batch.member_pool_claimed)) {
|
|
3073
|
+
clears.member_worktree = null;
|
|
3074
|
+
clears.member_pool_claimed = false;
|
|
3075
|
+
clearedFields.push('member_worktree', 'member_pool_claimed');
|
|
3076
|
+
}
|
|
3077
|
+
if (clearedFields.length === 0)
|
|
3078
|
+
continue;
|
|
3079
|
+
deps.store.withLock((s) => {
|
|
3080
|
+
const b = (0, state_1.findBatch)(s, batch.id);
|
|
3081
|
+
// Re-check under the lock: another tick, or an operator command, may
|
|
3082
|
+
// have already moved this batch or cleared the fields itself.
|
|
3083
|
+
if (!b || b.status !== 'done')
|
|
3084
|
+
return { state: s, result: undefined };
|
|
3085
|
+
return { state: (0, state_1.patchBatch)(s, batch.id, clears, now, false), result: undefined };
|
|
3086
|
+
});
|
|
3087
|
+
journalEvent(deps, 'kept-worktree-cleared', unit(batch.id), {
|
|
3088
|
+
cleared: clearedFields.join(','),
|
|
3089
|
+
detail: `kept-worktree ledger field(s) cleared on definitive evidence (${clearedFields.join(', ')}) — path gone or pool reports it returned; no removal command was run`,
|
|
3090
|
+
});
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
3027
3093
|
function anchorTickContext(deps) {
|
|
3028
3094
|
const reader = (0, groundtruth_1.issueCloseReader)(deps.groundTruth);
|
|
3029
3095
|
if (reader === undefined || deps.anchorRepo === undefined)
|
|
@@ -4140,6 +4206,7 @@ function runBatchTick(deps, config, dispatch) {
|
|
|
4140
4206
|
const anchorCtx = anchorTickContext(deps);
|
|
4141
4207
|
reconcileStaleBlockedBatches(deps, now, result, anchorCtx);
|
|
4142
4208
|
reconcileAnchorClosure(deps, now, anchorCtx);
|
|
4209
|
+
reconcileKeptWorktrees(deps, now);
|
|
4143
4210
|
return result;
|
|
4144
4211
|
}
|
|
4145
4212
|
//# sourceMappingURL=batch-dispatch.js.map
|