@ai-dossier/sched 0.34.0 → 0.36.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 +6 -0
- package/dist/batch-dispatch.d.ts.map +1 -1
- package/dist/batch-dispatch.js +61 -33
- package/dist/batch-dispatch.js.map +1 -1
- package/dist/dispatch.d.ts +8 -2
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +57 -7
- package/dist/dispatch.js.map +1 -1
- package/dist/persist.d.ts +3 -1
- package/dist/persist.d.ts.map +1 -1
- package/dist/persist.js +65 -18
- package/dist/persist.js.map +1 -1
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +1 -0
- package/dist/recovery.js.map +1 -1
- package/dist/status.d.ts +2 -1
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +2 -1
- package/dist/status.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -307,6 +307,12 @@ profiles exist and detection is inconclusive, enqueue fails and names the availa
|
|
|
307
307
|
profiles rather than silently choosing the default. `--dispatch` is intentionally rejected
|
|
308
308
|
for full-cycle entries; no profiles means legacy dispatch behavior remains unchanged.
|
|
309
309
|
|
|
310
|
+
Host defaults live at top-level `dispatch_profiles` in `~/.dossier/config.json`.
|
|
311
|
+
Scheduler projects inherit those profiles even before their own config exists. A
|
|
312
|
+
project's `dispatch.dispatch_profiles` overrides matching names only, leaving other
|
|
313
|
+
host profiles available. `sched status` reports every effective profile's source as
|
|
314
|
+
`user` or `project`.
|
|
315
|
+
|
|
310
316
|
Two engine-safety policies were explicit product decisions on #464:
|
|
311
317
|
|
|
312
318
|
- **Pid identity is hybrid-verified (decision 1, option C).** Every spawn records the
|
|
@@ -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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"}
|
package/dist/batch-dispatch.js
CHANGED
|
@@ -1807,6 +1807,11 @@ function resumeBlockedGate(deps, config, dispatch, batchId, now) {
|
|
|
1807
1807
|
const batch = (0, state_1.findBatch)(state, batchId);
|
|
1808
1808
|
if (!batch)
|
|
1809
1809
|
throw new types_1.SchedNotFoundError(`Batch not found: ${batchId}`);
|
|
1810
|
+
// A gate recheck can immediately advance to the next provider dispatch, so
|
|
1811
|
+
// it must use the batch's recorded profile rather than the engine default.
|
|
1812
|
+
const batchDispatch = batch.dispatch_profile === null
|
|
1813
|
+
? dispatch
|
|
1814
|
+
: (0, dispatch_1.resolveProfiledDispatch)(config, batch.dispatch_profile);
|
|
1810
1815
|
if (batch.status !== 'blocked' || !batch.blocked_reason?.startsWith('gate-inconclusive:')) {
|
|
1811
1816
|
// #677 review: the landing-failure blocks have no resume verb (same as
|
|
1812
1817
|
// `suite-unreadable`) — name the actual reason and the operator path
|
|
@@ -1855,7 +1860,7 @@ function resumeBlockedGate(deps, config, dispatch, batchId, now) {
|
|
|
1855
1860
|
outputTail: recheck.outputTail,
|
|
1856
1861
|
durationMs: recheck.durationMs,
|
|
1857
1862
|
}, now);
|
|
1858
|
-
completeMemberGate(deps, config,
|
|
1863
|
+
completeMemberGate(deps, config, batchDispatch, batchId, batch, memberIssue, now, result);
|
|
1859
1864
|
return { outcome: 'skipped', capability: capabilityId, detail: excerpt };
|
|
1860
1865
|
}
|
|
1861
1866
|
recordMemberGate(deps, batchId, memberIssue, { id: capabilityId, ...recheck }, now);
|
|
@@ -1903,7 +1908,7 @@ function resumeBlockedGate(deps, config, dispatch, batchId, now) {
|
|
|
1903
1908
|
if (recheck.outcome === 'task-failed') {
|
|
1904
1909
|
const reason = `incremental-gate-failed:${capabilityId}`;
|
|
1905
1910
|
writeGateLog(deps, batchId, capabilityId, memberIssue, recheck.outputTail);
|
|
1906
|
-
evictMemberAndContinue(deps, config,
|
|
1911
|
+
evictMemberAndContinue(deps, config, batchDispatch, batchId, batch, memberIssue, {
|
|
1907
1912
|
reason,
|
|
1908
1913
|
detail: withExcerpt(`sched resume --batch: cap run ${capabilityId} reported task-failed on recheck`, excerpt),
|
|
1909
1914
|
}, now, result);
|
|
@@ -1913,7 +1918,7 @@ function resumeBlockedGate(deps, config, dispatch, batchId, now) {
|
|
|
1913
1918
|
issue: memberIssue,
|
|
1914
1919
|
detail: `sched resume --batch: cap run ${capabilityId} reported ok on recheck`,
|
|
1915
1920
|
});
|
|
1916
|
-
completeMemberGate(deps, config,
|
|
1921
|
+
completeMemberGate(deps, config, batchDispatch, batchId, batch, memberIssue, now, result);
|
|
1917
1922
|
return { outcome: 'completed', capability: capabilityId };
|
|
1918
1923
|
}
|
|
1919
1924
|
/**
|
|
@@ -2795,9 +2800,9 @@ function runBatchTick(deps, config, dispatch) {
|
|
|
2795
2800
|
const result = emptyResult();
|
|
2796
2801
|
const now = deps.now();
|
|
2797
2802
|
// #707: each batch dispatches through ITS OWN recorded profile, not the
|
|
2798
|
-
// engine's default.
|
|
2799
|
-
//
|
|
2800
|
-
//
|
|
2803
|
+
// engine's default. Successful resolution is cached per tick (per
|
|
2804
|
+
// runBatchTick call); missing profiles are handled per batch. A profile that
|
|
2805
|
+
// no longer resolves (config edited
|
|
2801
2806
|
// mid-run) never silently falls back — the silent fallback is precisely
|
|
2802
2807
|
// the #680 incident shape (a run that looked like one agent family,
|
|
2803
2808
|
// executed as another). The reaction depends on how far the batch got:
|
|
@@ -2808,22 +2813,32 @@ function runBatchTick(deps, config, dispatch) {
|
|
|
2808
2813
|
// - post-merge (PR parked/merged — the product already shipped): dissolving
|
|
2809
2814
|
// would discard a landed PR's bookkeeping, so the remaining dispatch (the
|
|
2810
2815
|
// report agent) runs on the default and journals
|
|
2811
|
-
// `dispatch-profile-missing`
|
|
2812
|
-
// bounded phase (deployed → reported),
|
|
2816
|
+
// `dispatch-profile-missing` once while it holds the decision open — a
|
|
2817
|
+
// bounded phase (deployed → reported), with the journal acting as the
|
|
2818
|
+
// durable deduplication record across ticks and process restarts.
|
|
2813
2819
|
const profileCache = new Map();
|
|
2820
|
+
const missingProfileBatches = new Set();
|
|
2821
|
+
const missingProfileNotices = new Set(deps.journal
|
|
2822
|
+
.read()
|
|
2823
|
+
.filter((event) => event.event === 'dispatch-profile-missing' && event.unit !== undefined)
|
|
2824
|
+
.map((event) => event.unit));
|
|
2814
2825
|
const dispatchFor = (batch) => {
|
|
2815
2826
|
if (batch.dispatch_profile === null)
|
|
2816
2827
|
return dispatch;
|
|
2817
2828
|
const cached = profileCache.get(batch.dispatch_profile);
|
|
2818
2829
|
if (cached !== undefined)
|
|
2819
2830
|
return cached;
|
|
2820
|
-
|
|
2831
|
+
if (missingProfileBatches.has(batch.id))
|
|
2832
|
+
return dispatch;
|
|
2821
2833
|
try {
|
|
2822
|
-
resolved = (0, dispatch_1.resolveProfiledDispatch)(config, batch.dispatch_profile);
|
|
2834
|
+
const resolved = (0, dispatch_1.resolveProfiledDispatch)(config, batch.dispatch_profile);
|
|
2835
|
+
profileCache.set(batch.dispatch_profile, resolved);
|
|
2836
|
+
return resolved;
|
|
2823
2837
|
}
|
|
2824
2838
|
catch (err) {
|
|
2825
2839
|
if (!(err instanceof dispatch_1.DispatchProfileError))
|
|
2826
2840
|
throw err;
|
|
2841
|
+
missingProfileBatches.add(batch.id);
|
|
2827
2842
|
const current = deps.store.load();
|
|
2828
2843
|
const fresh = (0, state_1.findBatch)(current, batch.id);
|
|
2829
2844
|
const dissolvable = fresh !== undefined && (0, state_1.allowedBatchTransitions)(fresh.status).includes('dissolving');
|
|
@@ -2839,21 +2854,25 @@ function runBatchTick(deps, config, dispatch) {
|
|
|
2839
2854
|
state: applyBatchAndIssues(s, outcome.state, batch.id, outcome.requeued),
|
|
2840
2855
|
result: undefined,
|
|
2841
2856
|
}));
|
|
2857
|
+
teardownBatch(deps, batch.id);
|
|
2842
2858
|
result.failed.push(unit(batch.id));
|
|
2843
|
-
// Resolution failed:
|
|
2844
|
-
//
|
|
2845
|
-
//
|
|
2846
|
-
|
|
2859
|
+
// Resolution failed: clean up any batch/member worktrees, then skip
|
|
2860
|
+
// this batch for the rest of the pass. No further arm can claim it.
|
|
2861
|
+
// Do not cache a missing profile: every batch must receive its own
|
|
2862
|
+
// dissolve/journal reaction rather than inheriting a cached default.
|
|
2863
|
+
return null;
|
|
2847
2864
|
}
|
|
2848
2865
|
else {
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2866
|
+
const batchUnit = unit(batch.id);
|
|
2867
|
+
if (!missingProfileNotices.has(batchUnit)) {
|
|
2868
|
+
journalEvent(deps, 'dispatch-profile-missing', batchUnit, {
|
|
2869
|
+
detail: `profile '${batch.dispatch_profile}' is no longer configured; the post-merge tail runs on the default dispatch`,
|
|
2870
|
+
});
|
|
2871
|
+
missingProfileNotices.add(batchUnit);
|
|
2872
|
+
}
|
|
2873
|
+
return dispatch;
|
|
2853
2874
|
}
|
|
2854
2875
|
}
|
|
2855
|
-
profileCache.set(batch.dispatch_profile, resolved);
|
|
2856
|
-
return resolved;
|
|
2857
2876
|
};
|
|
2858
2877
|
// #565: when more ready batches exist than free capacity, claim them in
|
|
2859
2878
|
// the same priority order `runnableUnits` would (desc priority → asc
|
|
@@ -2888,13 +2907,13 @@ function runBatchTick(deps, config, dispatch) {
|
|
|
2888
2907
|
if (batch && batch.status === 'ready' && slotFor(state, batchId) === undefined) {
|
|
2889
2908
|
// #707: batch-setup dispatches through the batch's own profile too — it
|
|
2890
2909
|
// is the batch's first agent, not an engine-internal step.
|
|
2891
|
-
|
|
2910
|
+
const batchDispatch = dispatchFor(batch);
|
|
2911
|
+
if (batchDispatch !== null) {
|
|
2912
|
+
claimAndSetup(deps, config, batchDispatch, batchId, now, result);
|
|
2913
|
+
}
|
|
2892
2914
|
}
|
|
2893
2915
|
}
|
|
2894
2916
|
for (const batch of deps.store.load().batches) {
|
|
2895
|
-
// #707: resolve this batch's profile once per pass — or dissolve/fall
|
|
2896
|
-
// back loudly when it no longer resolves (see `dispatchFor` above).
|
|
2897
|
-
const batchDispatch = dispatchFor(batch);
|
|
2898
2917
|
const slot = slotFor(deps.store.load(), batch.id);
|
|
2899
2918
|
// #609: a TERMINAL batch (`done`/`dissolved`) still holding a slot matches
|
|
2900
2919
|
// none of the status arms below and would fall through their `continue`,
|
|
@@ -2906,17 +2925,26 @@ function runBatchTick(deps, config, dispatch) {
|
|
|
2906
2925
|
// `abandonBatch` that stops one from being created: it also REPAIRS state
|
|
2907
2926
|
// files that already carry a leaked slot, which is the only way an
|
|
2908
2927
|
// operator gets those three hours of held capacity back.
|
|
2909
|
-
if (
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
slot
|
|
2916
|
-
|
|
2917
|
-
|
|
2928
|
+
if (types_1.TERMINAL_BATCH_STATUSES.has(batch.status)) {
|
|
2929
|
+
if (slot) {
|
|
2930
|
+
deps.store.withLock((s) => ({
|
|
2931
|
+
state: (0, state_1.releaseBatchSlot)(s, batch.id, now),
|
|
2932
|
+
result: undefined,
|
|
2933
|
+
}));
|
|
2934
|
+
journalEvent(deps, 'slot-released', unit(batch.id), {
|
|
2935
|
+
slot: slot.id,
|
|
2936
|
+
detail: `terminal batch (${batch.status}) held slot ${slot.id}`,
|
|
2937
|
+
});
|
|
2938
|
+
}
|
|
2918
2939
|
continue;
|
|
2919
2940
|
}
|
|
2941
|
+
// #707: resolve this batch's profile once per pass — or dissolve/fall
|
|
2942
|
+
// back loudly when it no longer resolves (see `dispatchFor` above).
|
|
2943
|
+
// Terminal batches are skipped before this call so a removed profile does
|
|
2944
|
+
// not generate a missing-profile event on every later tick.
|
|
2945
|
+
const batchDispatch = dispatchFor(batch);
|
|
2946
|
+
if (batchDispatch === null)
|
|
2947
|
+
continue;
|
|
2920
2948
|
if (slot && (slot.status === 'running' || slot.status === 'assigned')) {
|
|
2921
2949
|
if (batch.status === 'executing') {
|
|
2922
2950
|
reconcileMemberSlot(deps, config, batchDispatch, batch.id, slot, now, result);
|