@ai-dossier/sched 0.2.0 → 0.3.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.
Files changed (58) hide show
  1. package/README.md +85 -17
  2. package/dist/dispatch.d.ts +128 -0
  3. package/dist/dispatch.d.ts.map +1 -0
  4. package/dist/dispatch.js +300 -0
  5. package/dist/dispatch.js.map +1 -0
  6. package/dist/engine.d.ts +111 -0
  7. package/dist/engine.d.ts.map +1 -0
  8. package/dist/engine.js +936 -0
  9. package/dist/engine.js.map +1 -0
  10. package/dist/enqueue.d.ts +38 -0
  11. package/dist/enqueue.d.ts.map +1 -0
  12. package/dist/enqueue.js +222 -0
  13. package/dist/enqueue.js.map +1 -0
  14. package/dist/groundtruth.d.ts +135 -0
  15. package/dist/groundtruth.d.ts.map +1 -0
  16. package/dist/groundtruth.js +259 -0
  17. package/dist/groundtruth.js.map +1 -0
  18. package/dist/index.d.ts +14 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +101 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/journal.d.ts +32 -0
  23. package/dist/journal.d.ts.map +1 -0
  24. package/dist/journal.js +113 -0
  25. package/dist/journal.js.map +1 -0
  26. package/dist/persist.d.ts +54 -0
  27. package/dist/persist.d.ts.map +1 -0
  28. package/dist/persist.js +348 -0
  29. package/dist/persist.js.map +1 -0
  30. package/dist/project.d.ts +41 -0
  31. package/dist/project.d.ts.map +1 -0
  32. package/dist/project.js +124 -0
  33. package/dist/project.js.map +1 -0
  34. package/dist/readiness.d.ts +43 -0
  35. package/dist/readiness.d.ts.map +1 -0
  36. package/dist/readiness.js +102 -0
  37. package/dist/readiness.js.map +1 -0
  38. package/dist/scheduler.d.ts +78 -0
  39. package/dist/scheduler.d.ts.map +1 -0
  40. package/dist/scheduler.js +191 -0
  41. package/dist/scheduler.js.map +1 -0
  42. package/dist/state.d.ts +40 -0
  43. package/dist/state.d.ts.map +1 -0
  44. package/dist/state.js +391 -0
  45. package/dist/state.js.map +1 -0
  46. package/dist/status.d.ts +44 -0
  47. package/dist/status.d.ts.map +1 -0
  48. package/dist/status.js +82 -0
  49. package/dist/status.js.map +1 -0
  50. package/dist/teardown.d.ts +57 -0
  51. package/dist/teardown.d.ts.map +1 -0
  52. package/dist/teardown.js +242 -0
  53. package/dist/teardown.js.map +1 -0
  54. package/dist/types.d.ts +253 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +91 -0
  57. package/dist/types.js.map +1 -0
  58. package/package.json +1 -1
@@ -0,0 +1,111 @@
1
+ /**
2
+ * The scheduler engine (#464): dispatch, completion verification, and the
3
+ * stall/escalation ladder (RFC-0001 §C.1) — the deterministic organs that
4
+ * replace fleet-cycle's LLM supervision. Since #468 it also owns the
5
+ * detached-ship tail: the PR watcher, script-based teardown, and the
6
+ * cheap-tier report dispatch.
7
+ *
8
+ * One `tick()` is a full reconcile+refill cycle:
9
+ *
10
+ * 1. **Poll** ground truth for every live unit and every parked PR OUTSIDE
11
+ * the state lock (gh/git subprocesses are slow; the lock must never wait
12
+ * on a network call). Parked PRs poll on their own cadence
13
+ * (`pr_poll_interval_ms`, persisted `last_pr_poll_at`) — every 2–3 min.
14
+ * 2. **Apply** under `SchedStore.withLock`:
15
+ * - `assigned` slots (crash between assign and spawn) are spawned/re-attached
16
+ * - `running` slots: dead pid → exit rail; ground truth says complete →
17
+ * external advance (kill the leftover agent, complete); new milestone or
18
+ * pushed commit → progress; no progress for `stall_timeout_ms` →
19
+ * redispatch one tier stronger (cap 2, then failed)
20
+ * - `exited`/`verifying` slots: the agent exited — completion is verified
21
+ * against ground truth, never assumed (AC2); an exit whose milestone is
22
+ * the ship phase's `awaiting-merge` (with `pr=`) is a VERIFIED park:
23
+ * entry → parked, slot released (a parked unit holds no slot — AC5)
24
+ * - `parked` entries: the watcher applies the PR truth — merge accepted
25
+ * only when state MERGED AND mergedAt non-null AND the issue is closed
26
+ * (AC1) → shipped (gating on MERGE, never the park — AC4);
27
+ * CONFLICTING / closed-unmerged / auto-merge-blocked → failed + transitive
28
+ * dependents blocked (AC3)
29
+ * - failures block their TRANSITIVE dependents (AC4)
30
+ * - report agents are dispatched for merged units whose teardown is
31
+ * already recorded (before queue refill — cheap reports don't queue
32
+ * behind long runs)
33
+ * - **Refill** in the SAME lock pass: `computeAssignments` fills every
34
+ * freed slot — a runnable unit never waits while a slot is idle (AC5)
35
+ * 3. **Teardown** (outside the lock — pool/git subprocesses are slow): for
36
+ * every freshly-merged unit, recover the setup milestone's worktree info
37
+ * and run pool return / worktree remove, VERIFIED before claimed
38
+ * (`cleanup=failed-<step>` on mismatch, AC2). Results land in a second
39
+ * short lock pass together with the report dispatch.
40
+ *
41
+ * Everything that touches the world (processes, GitHub, git) is injected;
42
+ * the state machine is pure. Only `issue:<n>` units are dispatched — batch
43
+ * member sequencing is a follow-up (#464 non-goal).
44
+ */
45
+ import { type SpawnDeps } from './dispatch';
46
+ import { type GroundTruth } from './groundtruth';
47
+ import { type Journal } from './journal';
48
+ import type { SchedStore } from './persist';
49
+ import type { ExecFn } from './project';
50
+ import { type SchedConfig } from './types';
51
+ export interface EngineDeps {
52
+ store: SchedStore;
53
+ journal: Journal;
54
+ groundTruth: GroundTruth;
55
+ spawnDeps: SpawnDeps;
56
+ now: () => Date;
57
+ /** Repo working directory — cwd for teardown subprocesses (#468). */
58
+ repoDir: string;
59
+ /** Exec for teardown scripts (#468); injectable so tests never touch git/npx. */
60
+ teardownExec: ExecFn;
61
+ }
62
+ /** What one tick did — surfaced by `sched start`. */
63
+ export interface TickResult {
64
+ /** Units spawned this tick (first dispatch or redispatch). */
65
+ spawned: string[];
66
+ /** Units completed by external ground truth while their agent was still alive. */
67
+ externalAdvances: string[];
68
+ /** Units verified complete after an observed exit. */
69
+ completed: string[];
70
+ /** Units whose agent exited having parked its PR (#468) — now watcher-owned. */
71
+ parked: string[];
72
+ /** Parked units whose merge was accepted this tick (#468). */
73
+ mergeAccepted: string[];
74
+ /** Report agents dispatched for merged units this tick (#468). */
75
+ reportDispatched: string[];
76
+ /** Merged units whose report could not dispatch — waiting for a free slot (#468). */
77
+ reportWaiting: number;
78
+ /** Units whose teardown was verified this tick (#468). */
79
+ teardownDone: string[];
80
+ /** Units whose teardown failed a step this tick (#468) — degradation, not unit failure. */
81
+ teardownFailed: string[];
82
+ /** Units redispatched one tier stronger (stall or unverified exit). */
83
+ redispatched: string[];
84
+ /**
85
+ * Units that hit a failure rail. Full-cycle units end `failed`; MERGED
86
+ * units also land here on merged-aware REPORT failures
87
+ * (`report-escalation-cap` / report spawn-error), where the unit actually
88
+ * completes (`done`, reason recorded) — the report failed, not the work.
89
+ */
90
+ failed: string[];
91
+ /** Issues blocked transitively by a failure. */
92
+ blocked: number[];
93
+ }
94
+ /**
95
+ * One full reconcile+refill cycle. Ground truth is polled WITHOUT the lock
96
+ * (live units AND parked PRs); every state mutation happens under
97
+ * `store.withLock`; refills are computed in the same pass, so a freed slot
98
+ * is reused within this tick (AC5). Teardown subprocesses run between two
99
+ * short lock passes — a slow `npx`/`git` call never holds the lock.
100
+ */
101
+ export declare function tick(deps: EngineDeps, config: SchedConfig): TickResult;
102
+ /**
103
+ * The long-running loop behind `sched start`: tick, sleep, repeat. Returns
104
+ * when `shouldStop()` says so (the CLI wires SIGINT). A failed tick is
105
+ * journaled (`tick-failed`, with the error name — `LockTimeoutError` and
106
+ * `CorruptStateError` demand different operator actions) and reported on
107
+ * stderr, and the loop continues — one bad tick (e.g. a transient gh
108
+ * failure) never stops the scheduler.
109
+ */
110
+ export declare function runLoop(deps: EngineDeps, config: SchedConfig, shouldStop: () => boolean, onTick?: (result: TickResult) => void): Promise<void>;
111
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,EAQL,KAAK,SAAS,EAIf,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,KAAK,WAAW,EAMjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAe,KAAK,OAAO,EAAa,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAIxC,OAAO,EAKL,KAAK,WAAW,EAKjB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,UAAU;IACzB,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,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qDAAqD;AACrD,MAAM,WAAW,UAAU;IACzB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kFAAkF;IAClF,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,sDAAsD;IACtD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,gFAAgF;IAChF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,8DAA8D;IAC9D,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kEAAkE;IAClE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,qFAAqF;IACrF,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,2FAA2F;IAC3F,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,uEAAuE;IACvE,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB;;;;;OAKG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,gDAAgD;IAChD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AA06BD;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,UAAU,CAyCtE;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAC3B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,MAAM,OAAO,EACzB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,GACpC,OAAO,CAAC,IAAI,CAAC,CAcf"}