T-8I15-adapt-task-next-onto-graph-scheduler
Status: closed/superseded · Impact: high · Complexity: large
sdlc task next + plugin/lib/model/corpus/ hand-roll the exact machinery the
graph-scheduler library (PR-DZTZ-graph-scheduler, D-BPD8-graph-scheduler-api)
generalizes: build a dependency DAG, detect cycles, lift priority through edges,
drop tasks whose depends_on is unsatisfied, cap at N. Re-base them onto
graph-scheduler as its first consumer / reference adapter, so SDLC keeps one
scheduling implementation instead of two and the library earns a real user. This
retires the duplicate frontier/cycle/lift code T-7EJO-extract-corpus-depgraph-module
consolidated into corpus/.
| Location | Role today |
|---|---|
plugin/lib/model/entities/task/ops/next.ts | The sdlc task next op. Its handler is a getReady(graph, state) by hand: buildEdges → findCycles → liftSortKeys → drop unsatisfied depends_on (isSatisfied) → .slice(limit). |
plugin/lib/model/corpus/graph.ts | buildEdges (forward/reverse edges) + findCycles (all elementary cycles) — the DAG core, duplicating graph-scheduler/graph (C-409J-dag-core). |
plugin/lib/model/corpus/satisfied.ts | SATISFIED_BY_TYPE / isSatisfied — per-entity-type status→satisfied bands; the domain form of graph-scheduler’s status model (C-PPXU-status-model-and-trigger-rules). |
plugin/lib/model/corpus/resolve.ts | resolveTarget — bare-id/basename depends_on resolution, done at graph-build time in the adapter. |
plugin/lib/model/corpus/loader.ts | loadCorpus — the corpus the adapter turns into nodes + attrs + state. |
plugin/lib/model/ops/audit.ts | Shares plugin/lib/model/corpus/graph.ts cycle detection (post-T-7EJO-extract-corpus-depgraph-module); a second caller to migrate in lockstep. |
plugin/lib/model/entities/task/ops/tests/next-golden.test.ts | Golden output the adaptation must reproduce byte-for-byte (behavior parity). |
package.json | Root workspace manifest; must declare the graph-scheduler package dependency. |
Proposed
Section titled “Proposed”next.ts is a thin adapter over graph-scheduler: it loads the corpus, builds
a graph-scheduler/graph (cross-entity depends_on resolved via resolve.ts),
derives each node’s Status from SATISFIED_BY_TYPE, and calls
getReady(graph, state, { limit, order }). The line-per-basename output,
skipped_blocked, CYCLE marker, --explain, and --include-blocked are all
projected from the library’s result. plugin/lib/model/corpus/graph.ts’s cycle/edge code and
next.ts’s liftSortKeys are removed (or reduced to the adapter); audit.ts
cycle detection runs through the same library. SDLC carries one scheduling
implementation, in graph-scheduler.
This depends on graph-scheduler shipping with the four consumer-driven
improvements recorded in D-BPD8-graph-scheduler-api (§First consumer): the
comparable-key downstream lift (A), cycle members (B), unknown-dep fail-safe (C),
and typed-status derivation (D). Until those land the ordering/behavior cannot be
preserved.
Approach
Section titled “Approach”- Add
graph-scheduleras a workspace dependency inpackage.json; confirm it resolves under bun. - Write the adapter in
corpus/:loadCorpus→ nodes (id + attrs carrying the sort tuple) + edges (viaresolveTarget) → agraph-scheduler/graph; deriveStateby mapping each entity’s(type, domainStatus)throughisSatisfied→Status(improvement D). - Replace
next.ts’s hand-rolled frontier: callgetReady(graph, state, { limit, order: <sdlc sort chain + downstream lift> }). The lift uses improvement A (comparable-key downstream), the default filter is dependency satisfaction, and unresolved targets rely on improvement C. - Project the op’s output (ordered basenames,
skipped_blockedwith reasons viaexplain/whatBlocks,CYCLE basenames=…via improvement B,--explain,--include-blocked) from the library result. - Migrate
audit.tscycle detection to the library; deleteplugin/lib/model/corpus/graph.ts’sfindCycles/buildEdges(or reduce to a re-export). - Keep
next-golden.test.tsgreen with only the parity-preserving edits; add a fixture pinning the lift (low-impact blocker of high-impact work sorts first).
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
package.json | modify | add the graph-scheduler workspace dependency |
plugin/lib/model/corpus/schedule_adapter.ts | new | corpus → graph-scheduler graph + state + sort/order; the SDLC adapter |
plugin/lib/model/entities/task/ops/next.ts | modify | call getReady instead of the hand-rolled frontier; project output |
plugin/lib/model/corpus/graph.ts | modify | remove local buildEdges/findCycles (or reduce to a re-export over graph-scheduler/graph) |
plugin/lib/model/corpus/satisfied.ts | modify | feed the (type,status)→Status derivation (improvement D) |
plugin/lib/model/corpus/resolve.ts | modify | used at graph-build time by the adapter |
plugin/lib/model/corpus/loader.ts | modify | consumed by the adapter |
plugin/lib/model/ops/audit.ts | modify | migrate cycle detection to the library |
plugin/lib/model/entities/task/ops/tests/next-golden.test.ts | modify | parity + a lift-preservation fixture |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: for every fixture in
next-golden.test.ts,sdlc task nextproduces the sameorderedandskipped_blockedoutput (and the sameCYCLEmarker on cyclic fixtures) as the pre-adaptation op. - AC-2:
next.tsbuilds agraph-schedulergraph + state and callsgetReady;git grep -nE 'buildEdges|findCycles|liftSortKeys' -- plugin/lib/model/entities/task/opsreturns nothing (the frontier/cycle/lift now come from the library). - AC-3:
git grep -nE 'function (findCycles|detectCycle|buildEdges)' -- plugin/libreturns nothing — the plugin holds no cycle/edge implementation; bothnext.tsandaudit.tsusegraph-scheduler. - AC-4: a fixture where a low-impact task blocks a high-impact task shows the blocker sorted first (D-Q2WR-task-pickup-order’s lift, preserved through improvement A).
- AC-5: an unresolved
depends_ontarget still blocks its dependent (improvement C fail-safe), matching current behavior. - AC-6:
bun test plugin/is green and the typecheck is clean. - AC-7:
package.jsondeclares thegraph-schedulerdependency and it resolves underbun install.
Out of scope
Section titled “Out of scope”- Building graph-scheduler itself and its improvements A–D — those are the
library’s own work (C-PC3N-push-readiness-frontier, C-409J-dag-core,
C-V44L-priority-ordering-sorters, C-PPXU-status-model-and-trigger-rules).
This task is the SDLC-side adaptation only and is blocked on them
(
depends_on). - Goal-directed / pull consumption (
toward,graph-scheduler/pull) — the orchestrator’s milestone-focus use case is a later adoption, not this parity cutover. - Changing SDLC’s sort chain or satisfied-band semantics — behavior is preserved; only the implementation moves onto the library.
- The stateful
tracker— SDLC stays stateless (re-reads task files each tick), which is exactly the puregetReadyfit.
Dependencies
Section titled “Dependencies”- graph-scheduler must ship with improvements A–D — tracked via
depends_onon C-PC3N-push-readiness-frontier, C-409J-dag-core, and C-V44L-priority-ordering-sorters. Until those capabilities are verified the adaptation cannot preserve D-Q2WR-task-pickup-order’s behavior.
Discovery context
Section titled “Discovery context”Surfaced 2026-07-02 reviewing the graph-scheduler product/decision series against
this session’s T-7EJO-extract-corpus-depgraph-module. task next/corpus/
already implement ~80% of graph-scheduler’s core, and the two efforts had not
referenced each other. Making task next the library’s first consumer avoids
re-duplicating — at a larger scale — the exact frontier/cycle logic T-7EJO just
consolidated. The four improvements A–D are the gaps found when mapping
next.ts’s behavior onto D-BPD8-graph-scheduler-api’s API.