@ai-dossier/sched 0.57.4 → 0.57.6

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 CHANGED
@@ -1499,7 +1499,7 @@ after-the-fact recovery, not a missing-data bug.
1499
1499
  queue data.
1500
1500
  - **Schema**: state/config files from #460 (schema 1.0.0), #464 (1.1.0), #468 (1.2.0),
1501
1501
  #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)
1502
- load and migrate to the current schema (1.29.0 — 1.24.0 was #810: no backfill,
1502
+ load and migrate to the current schema (1.30.0 — 1.24.0 was #810: no backfill,
1503
1503
  `kind`/`branch` optional, absent = an `evicted` record with no branch) automatically
1504
1504
  (slot `branch`/`last_head`/`pid_start`, slot `role` (inferred from the
1505
1505
  unit's queue entry, with the persisted `phase` as a fallback — #500), entry
@@ -1529,6 +1529,9 @@ after-the-fact recovery, not a missing-data bug.
1529
1529
  Schema 1.29.0 (#844): `SlotEntry` gains `kill_sent_at`/`kill_escalated_at` (the
1530
1530
  SIGTERM → SIGKILL escalation anchor and its journal dedup marker; `null`/`null`
1531
1531
  backfilled, cleared when the slot goes idle).
1532
+ Schema 1.30.0 (#637): `QueueEntry` gains `ground_truth_unreachable_condition` (the
1533
+ `ground-truth-unreachable` streak's stable per-site key — a changed key starts a new
1534
+ streak; `null` backfilled, cleared with the other entry dedup markers).
1532
1535
  - **`max_slots`** bounds live units (`assigned | running | recovering`); dependency
1533
1536
  edges gate readiness — an issue with an unmerged dependency, and a batch behind an
1534
1537
  unmerged batch, are never runnable.
@@ -207,7 +207,7 @@ export declare function memberBranchFor(batchId: string, memberIndex: number, is
207
207
  */
208
208
  export declare function evictMemberAndContinue(deps: BatchDispatchDeps, config: SchedConfig, dispatch: ResolvedDispatch, batchId: string, batch: BatchEntry, memberIssue: number, failure: MemberFailure, now: Date, result: BatchTickResult,
209
209
  /** #844: the member's slot release (or any pre-write) — committed in the eviction's own write. */
210
- preWrite?: (s: SchedState) => SchedState): void;
210
+ preWrite?: (s: SchedState) => SchedState, afterEvict?: () => void): void;
211
211
  /**
212
212
  * `sched resume --batch <id>` (#583 AC4): an operator-triggered, synchronous
213
213
  * one-shot recheck of a batch blocked on `gate-inconclusive:<capabilityId>`
@@ -1 +1 @@
1
- {"version":3,"file":"batch-dispatch.d.ts","sourceRoot":"","sources":["../src/batch-dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"batch-dispatch.d.ts","sourceRoot":"","sources":["../src/batch-dispatch.ts"],"names":[],"mappings":"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"}
@@ -1838,10 +1838,11 @@ serialTeardown) {
1838
1838
  */
1839
1839
  function evictMemberAndContinue(deps, config, dispatch, batchId, batch, memberIssue, failure, now, result,
1840
1840
  /** #844: the member's slot release (or any pre-write) — committed in the eviction's own write. */
1841
- preWrite) {
1841
+ preWrite, afterEvict) {
1842
1842
  const { batchEnded, duplicate } = evictMemberDirectly(deps, config, batchId, memberIssue, failure, now, preWrite);
1843
1843
  if (duplicate)
1844
1844
  return;
1845
+ afterEvict?.();
1845
1846
  if (batchEnded) {
1846
1847
  result.failed.push(unit(batchId));
1847
1848
  return;
@@ -2271,7 +2272,7 @@ function resumeBlockedGate(deps, config, dispatch, batchId, now) {
2271
2272
  * full-cycle run is an independent unit), so unlike `engine.ts`'s per-unit log, a member's log file is
2272
2273
  * always one-shot and reading from offset 0 is always correct.
2273
2274
  */
2274
- function recordMemberRunLog(deps, dispatch, state, batchId,
2275
+ function prepareMemberRunLog(deps, dispatch, state, batchId,
2275
2276
  /** 1-based member index — names the per-member log file (serial: `executing_member`; parallel: `MemberRun.index`). */
2276
2277
  memberIndex, memberIssue, slot, now) {
2277
2278
  if (slot.status !== 'running' || slot.spawned_at === null) {
@@ -2309,10 +2310,17 @@ memberIndex, memberIssue, slot, now) {
2309
2310
  cwd: deps.repoDir,
2310
2311
  tier,
2311
2312
  });
2312
- (0, run_log_1.finalizeRunLogEntry)(runEntry, logContent, deps.homeDir, (event, extra) => journalEvent(deps, event, unit(batchId), extra), { issue: memberIssue, log: logFile });
2313
- // #591: the last tool this member dispatch called — attributes an
2314
- // `agent-exited-unverified` failure to a concrete cause without opening the transcript.
2315
- return (0, core_1.parseLastToolUse)(logContent);
2313
+ return {
2314
+ lastTool: (0, core_1.parseLastToolUse)(logContent),
2315
+ append: () => (0, run_log_1.finalizeRunLogEntry)(runEntry, logContent, deps.homeDir, (event, extra) => journalEvent(deps, event, unit(batchId), extra), { issue: memberIssue, log: logFile }),
2316
+ };
2317
+ }
2318
+ function recordMemberRunLog(deps, dispatch, state, batchId, memberIndex, memberIssue, slot, now) {
2319
+ const runLog = prepareMemberRunLog(deps, dispatch, state, batchId, memberIndex, memberIssue, slot, now);
2320
+ if (runLog === null)
2321
+ return null;
2322
+ runLog.append();
2323
+ return runLog.lastTool;
2316
2324
  }
2317
2325
  /**
2318
2326
  * #622: the milestone a member dispatch's fate is read from.
@@ -2724,7 +2732,7 @@ function reconcileMemberSlot(deps, config, dispatch, batchId, slot, now, result)
2724
2732
  return;
2725
2733
  }
2726
2734
  if (read.blockedNow || read.dead) {
2727
- const lastTool = recordMemberRunLog(deps, dispatch, state0, batchId, batch.executing_member, memberIssue, slot, now);
2735
+ const runLog = prepareMemberRunLog(deps, dispatch, state0, batchId, batch.executing_member, memberIssue, slot, now);
2728
2736
  // A member that never went green (RFC F.1) evicts DIRECTLY — no aggregate
2729
2737
  // suite has run yet, so there is nothing for `attributing`/`evicting` (the
2730
2738
  // AGGREGATE-suite-red pipeline, RFC F.2) to attribute or revert: the
@@ -2733,9 +2741,9 @@ function reconcileMemberSlot(deps, config, dispatch, batchId, slot, now, result)
2733
2741
  // attributing → evicting` is not even a legal edge from mid-`executing`
2734
2742
  // (BATCH_TRANSITIONS has no `executing → evicting`) — this stays entirely
2735
2743
  // within `executing`/`dissolving`, both of which ARE legal from here.
2736
- evictMemberAndContinue(deps, config, dispatch, batchId, batch, memberIssue, memberFailureFor(read, lastTool), now, result,
2744
+ evictMemberAndContinue(deps, config, dispatch, batchId, batch, memberIssue, memberFailureFor(read, runLog?.lastTool ?? null), now, result,
2737
2745
  // #844: released in the eviction's own write, never before it.
2738
- release);
2746
+ release, () => runLog?.append());
2739
2747
  }
2740
2748
  }
2741
2749
  /**
@@ -3204,10 +3212,7 @@ function clearBatchDedupMarker(deps, batch, currentReason, clearedFields, now) {
3204
3212
  * `since`/`ticks`/whether to announce.
3205
3213
  */
3206
3214
  function advanceBatchDedupStreak(priorReason, priorSince, priorTicks, reason, now) {
3207
- const isNewStreak = priorReason !== reason || priorSince === null;
3208
- const ticks = isNewStreak ? 1 : priorTicks + 1;
3209
- const since = isNewStreak || priorSince === null ? now.toISOString() : priorSince;
3210
- return { since, ticks, announce: isNewStreak || ticks % types_1.JOURNAL_DEDUP_REANNOUNCE_TICKS === 0 };
3215
+ return (0, state_1.advanceStreak)({ since: priorSince, ticks: priorTicks }, priorReason !== reason, now);
3211
3216
  }
3212
3217
  /**
3213
3218
  * Reset a batch's `pr-watch-failed` dedup marker (#630/#633). A no-op when no
@@ -4387,7 +4392,7 @@ function spawnParallelMembers(deps, config, dispatch, batchId, now, result) {
4387
4392
  */
4388
4393
  function evictParallelMember(deps, config, batchId, run, failure, now, result,
4389
4394
  /** #844: the member's own slot release — committed in the eviction's write. */
4390
- release) {
4395
+ release, afterEvict) {
4391
4396
  const { batchEnded, duplicate } = evictMemberDirectly(deps, config, batchId, run.issue, failure, now,
4392
4397
  // #844: the run's `evicted` status lands in the eviction's write too — a
4393
4398
  // separate write left an evicted member's run `running` (slotless, its
@@ -4395,6 +4400,7 @@ release) {
4395
4400
  (s) => patchRun(release ? release(s) : s, batchId, run.issue, { status: 'evicted', gate_inconclusive: null }, now));
4396
4401
  if (duplicate)
4397
4402
  return;
4403
+ afterEvict?.();
4398
4404
  result.failed.push(batchEnded ? unit(batchId) : (0, state_1.batchMemberUnit)(batchId, run.issue));
4399
4405
  if (batchEnded)
4400
4406
  return;
@@ -4465,8 +4471,8 @@ function reconcileParallelMemberSlot(deps, config, dispatch, batchId, run, slot,
4465
4471
  return;
4466
4472
  }
4467
4473
  if (read.blockedNow || read.dead) {
4468
- const lastTool = recordMemberRunLog(deps, dispatch, state0, batchId, run.index, run.issue, slot, now);
4469
- evictParallelMember(deps, config, batchId, run, memberFailureFor(read, lastTool), now, result, release);
4474
+ const runLog = prepareMemberRunLog(deps, dispatch, state0, batchId, run.index, run.issue, slot, now);
4475
+ evictParallelMember(deps, config, batchId, run, memberFailureFor(read, runLog?.lastTool ?? null), now, result, release, () => runLog?.append());
4470
4476
  }
4471
4477
  }
4472
4478
  /**