Skip to content

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/.

LocationRole today
plugin/lib/model/entities/task/ops/next.tsThe sdlc task next op. Its handler is a getReady(graph, state) by hand: buildEdgesfindCyclesliftSortKeys → drop unsatisfied depends_on (isSatisfied) → .slice(limit).
plugin/lib/model/corpus/graph.tsbuildEdges (forward/reverse edges) + findCycles (all elementary cycles) — the DAG core, duplicating graph-scheduler/graph (C-409J-dag-core).
plugin/lib/model/corpus/satisfied.tsSATISFIED_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.tsresolveTarget — bare-id/basename depends_on resolution, done at graph-build time in the adapter.
plugin/lib/model/corpus/loader.tsloadCorpus — the corpus the adapter turns into nodes + attrs + state.
plugin/lib/model/ops/audit.tsShares 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.tsGolden output the adaptation must reproduce byte-for-byte (behavior parity).
package.jsonRoot workspace manifest; must declare the graph-scheduler package dependency.

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.

  1. Add graph-scheduler as a workspace dependency in package.json; confirm it resolves under bun.
  2. Write the adapter in corpus/: loadCorpus → nodes (id + attrs carrying the sort tuple) + edges (via resolveTarget) → a graph-scheduler/graph; derive State by mapping each entity’s (type, domainStatus) through isSatisfiedStatus (improvement D).
  3. Replace next.ts’s hand-rolled frontier: call getReady(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.
  4. Project the op’s output (ordered basenames, skipped_blocked with reasons via explain/whatBlocks, CYCLE basenames=… via improvement B, --explain, --include-blocked) from the library result.
  5. Migrate audit.ts cycle detection to the library; delete plugin/lib/model/corpus/graph.ts’s findCycles/buildEdges (or reduce to a re-export).
  6. Keep next-golden.test.ts green with only the parity-preserving edits; add a fixture pinning the lift (low-impact blocker of high-impact work sorts first).
LocationKindChange
package.jsonmodifyadd the graph-scheduler workspace dependency
plugin/lib/model/corpus/schedule_adapter.tsnewcorpus → graph-scheduler graph + state + sort/order; the SDLC adapter
plugin/lib/model/entities/task/ops/next.tsmodifycall getReady instead of the hand-rolled frontier; project output
plugin/lib/model/corpus/graph.tsmodifyremove local buildEdges/findCycles (or reduce to a re-export over graph-scheduler/graph)
plugin/lib/model/corpus/satisfied.tsmodifyfeed the (type,status)→Status derivation (improvement D)
plugin/lib/model/corpus/resolve.tsmodifyused at graph-build time by the adapter
plugin/lib/model/corpus/loader.tsmodifyconsumed by the adapter
plugin/lib/model/ops/audit.tsmodifymigrate cycle detection to the library
plugin/lib/model/entities/task/ops/tests/next-golden.test.tsmodifyparity + a lift-preservation fixture
  • AC-1: for every fixture in next-golden.test.ts, sdlc task next produces the same ordered and skipped_blocked output (and the same CYCLE marker on cyclic fixtures) as the pre-adaptation op.
  • AC-2: next.ts builds a graph-scheduler graph + state and calls getReady; git grep -nE 'buildEdges|findCycles|liftSortKeys' -- plugin/lib/model/entities/task/ops returns nothing (the frontier/cycle/lift now come from the library).
  • AC-3: git grep -nE 'function (findCycles|detectCycle|buildEdges)' -- plugin/lib returns nothing — the plugin holds no cycle/edge implementation; both next.ts and audit.ts use graph-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_on target 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.json declares the graph-scheduler dependency and it resolves under bun install.
  • 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 pure getReady fit.

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.


← Back to Tasks