task dependency graph (#104)#139
Open
atomikpanda wants to merge 20 commits into
Open
Conversation
First-class depends_on edges between tasks, persisted in state.yaml. Design covers state model, mship depends verb group, integration with spawn/finish/close/status/dispatch/reconcile, cycle detection, and the hard/soft edge model. All 8 design questions from the issue resolved.
Simpler model: single edge type with hard semantics. Tracking-without- enforcement is what mship journal already covers. Soft edges become an additive future change if a use case surfaces.
14 tasks, TDD-first. Covers state model, task_graph.py utilities, mship depends verb group, integration with spawn/finish/close/status/ dispatch/reconcile, docs, and an end-to-end integration test. Divergence from spec: new code lives in src/mship/core/task_graph.py (not graph.py, which already models repo dependency topology).
…ecks (#104) Adds --depends-on option to mship spawn. Validates upstream slugs exist, runs cycle detection, and persists DependencyEdge list on the new task.
…verride (#104) Add a dependency-readiness gate to `mship finish` that checks each depends_on upstream via is_ready() before any push. Names the offending upstreams in the error. --bypass-deps skips the gate. Module-level _dependency_decisions() helper enables monkeypatching in tests.
…wnstream created (#104)
Adds test_dependency_flow covering: spawn task-a, spawn task-b --depends-on a, status shows blocked==True/blocked_by==[a], finish refuses with upstream message, finish --bypass-deps clears the gate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First-class task-to-task dependency edges.
task B depends_on task Ais now expressed in workspace state (state.yaml), and the rest ofmshipreads it:mship depends add/remove/list (--graph)to manage edges on existing tasks.mship spawn --depends-on a,b,...declares upstream task(s) at creation. Unknown upstream and cycles are rejected loudly at write time.mship finishrefuses to ship a downstream task whose upstream isn't merged.--bypass-depsoverrides.mship close --cascade/--detach-downstreamhandle the downstream case. Non-TTY refuses without an explicit flag; TTY prompts.mship statusexposes the graph at.resolved_task.dependencies(upstream / downstream / blocked / blocked_by).mship dispatchincludes a## Dependenciessection in the subagent prompt body, with per-edge ready/not-ready state.mship reconcilegrows adependency_stalestate — surfaced when a downstream that's otherwise in-sync has an upstream that merged after the downstream was created (i.e. needs rebase).Closes #104.
Design and plan
docs/superpowers/specs/2026-05-14-task-dependency-graph-design.mddocs/superpowers/plans/2026-05-14-task-dependency-graph.mdKey design decisions
mship journalalready handles "informed by task-a" relationships.task_graph.pyis a new module distinct fromgraph.py(which models repo topology). Mixing the two semantically-different graphs in one module would confuse readers.Task.depends_onis additive, defaults to[]. Existingstate.yamlfiles load unchanged.What changed on the wire
mship statusenvelope grows one additive key underresolved_task:dependencies(upstream/downstream/blocked/blocked_by).mship reconcileUpstreamStateenum gains one variant:dependency_stale.Both are additive. No consumer breakage.
Test plan
task_graph.py— cycle detection (self, 2-node, 3-node, diamond), transitive upstream/downstream, readiness queries.mship depends add/remove/list— happy path, unknown upstream, self-edge, cycle, idempotent add, missing edge on remove, task-scoped list, --graph DAG output.spawn --depends-on— persists edges, errors loudly on unknown upstream.finish— blocked by unready upstream;--bypass-depsclears.close— non-TTY refuses with downstream;--cascaderemoves from state;--detach-downstreamclears edges.status—resolved_task.dependenciesblock with correct shape.dispatch—## Dependenciessection emitted with readiness signal.reconcile.dependency_stale— only overridesin_syncdecisions, only when upstream merged after downstream created.spawn a → spawn b --depends-on a → status shows blocked → finish blocks → finish --bypass-deps clears.Full test suite: 1235 passed, 0 failures.
Known follow-ups (intentionally deferred)
status.resolved_task.dependencies.readyis alwaysfalsefor unmerged upstreams (uses an empty reconcile decisions dict to avoid a network round-trip on the hot path). A future change could read the existingReconcileCacheto populate readiness without a fetch.--cascaderemoves downstream tasks from state but does NOT tear down their worktrees — left tomship prune. Documented in the flag's help text.--cascadedoesn't clean reconcile cache entries for removed downstream tasks. Harmless (cache is TTL-bound).reconcile.dependency_stalesurfaces the need; user runs the rebase.Out of scope (v2 concerns)
Multi-agent orchestration, cross-workspace edges, critical-path scheduling, parallel-execution coordination. The graph being a first-class primitive in v1 is the seam these features will sit on top of without speculative design.
Closes #104