How Topolog works
Three system layers, three things you do. You author the graph; the scheduler lays it across your week; you execute the day. Each does exactly one job. The list and the completion spectrum are just the graph, read back to you.
The dependency graph
Every goal has a plan. Every plan in Topolog is a rigorous Directed Acyclic Graph (DAG): a structure that knows what depends on what. Milestones contain tasks. Tasks have estimated hours. Edges express ordering: what must finish before what.
Topolog's AI proposes structure; you sign off. Click empty canvas to add a node, drag from one node onto another to draw an edge, click a node or edge to edit it in the inspector, press Delete to remove the selection, or drop into the Source tab to author the plan directly in our domain-specific language, Total Orchestration Language (TOL). Cycles at the task level are rejected automatically, so the structure stays a valid Directed Acyclic Graph (DAG) by construction.

Prefer a list? It's the same graph.
A plan is a DAG, and every DAG has a topological order, so Topolog can flatten the exact same graph into the familiar nested list you already think in. Milestones expand into their tasks and iterations, each with its hour estimate, always in an order that respects every dependency.
Graph, list, and TOL source are three lenses on one data model: sketch on the canvas, scan the list, fine-tune the source. Whatever you change shows up in all three.

Every plan is a program
The graph isn't a drawing; it's source code. Every plan is written in TOL, our Total Orchestration Language: a typed, executable description of the work, its uncertainty, and its dependencies.
It earns the word Total twice over: mathematically, every plan, gate, and script is guaranteed to terminate, because the grammar cannot express an infinite loop or anything the engine cannot reason about, so your schedule and odds are always computable; and in scope, one file holds the whole endeavour, its structure, its probabilities, and the logic of each task.
That logic is TOLScript: optional, sandboxed per-task scripts that compute a task's own outputs. Because they always terminate, the Monte Carlo engine can run your plan, not just approximate it from priors.
plan "Remodel the kitchen in 6 weeks" {
agent contractor { type: internal }
outcome on_budget: boolean
milestone m_finish "Second fix + sign-off" {
task t_tile "Paint + tile" {
agent: contractor
estimate: 4h cv 0.3
produces: [on_budget]
script: "let waste = 0.1; 18.0 * (1 + waste)"
}
}
sentinel s_done { end_state: success }
edge e_done m_finish -> s_done { carries: null }
}Decidable by construction
This puts TOL in a deliberate tradition: total languages like Starlark, Dhall, and Lustre, in the lineage of Turner's Total Functional Programming, that give up Turing-completeness in exchange for decidability. You lose the ability to write a plan that might never halt; you gain a plan whose schedule, odds, and critical path are always computable.
Because of that trade, the validator can prove things about your plan before it ever runs. Five of the structural invariants it enforces, each on every edit:
- Acyclicity SI-1No circular dependencies at the task level, once the plan is fully decomposed. Higher up, at the milestone level, cycles are allowed while you author; each resolves into a bounded iteration before execution.
- Bounded loops Axiom 1Every iteration declares a max_count, so the fully expanded plan is always finite.
- Typed carries SI-46Every edge carries a value of a known type, and consumers must accept what producers emit.
- No dangling work SI-16Every deliverable a task consumes has an upstream task that produces it.
- Reachable outcomes SI-6Every outcome the plan declares has a task that can actually produce it.
Loops that are guaranteed to end
A plan is more than a dependency graph with code bolted on. The clearest proof is the iteration: a loop that repeats a milestone until an outcome lands, like revising a paper until it's accepted.
But every iteration is bounded: it runs over a finite generator (a fixed count, a query over your deliverables, or an until-gate) and always declares a max_count cap on top. That is why a plan with a feedback loop is still a program that terminates instead of running forever, and why its schedule and odds stay computable.
plan "Get the paper accepted" {
agent author { type: internal }
outcome accepted: boolean
milestone m_publish "Submit, then revise to acceptance" {
iteration it_revise "Revise until accepted" {
over: until(accepted = true)
max_count: 4
template: milestone m_round "One revision round" {
task t_revise "Address reviews + resubmit" {
agent: author
estimate: 3h cv 0.4
produces: [accepted]
}
}
}
}
sentinel s_done { end_state: success }
edge e_done m_publish -> s_done { carries: null }
}The completion spectrum
Topolog runs a Monte Carlo over the whole graph (every task's estimate carries an uncertainty, every dependency is respected) and rolls the results into a completion spectrum: the probability you land on time, partially, or miss.
You get an honest forecast instead of one fake date: a P50 end, a budget vs. expected cost, and the full success / partial / failure split, not a single number you'll miss.

Money, and the odds it buys
Give the plan a budget and Topolog tracks the cash trajectory: expected spend, the P10-P90 band, and the worst cash position (max drawdown) over the life of the plan.
It also ties how you allocate that budget to whether the plan succeeds. The Pareto frontier plots the trade-off directly: for every level of spend, the best probability of success you can buy, so you pick the point that fits your appetite for risk.


The deterministic scheduler
The scheduler is pure TypeScript. No AI in the scheduling path. Dependency ordering, time-budgeted scheduling, deadline propagation. Fast, debuggable, free of hallucination.
Milestone→milestone edges are expanded into the cross-product of their atomic tasks before scheduling, hours are bin-packed into your real availability windows, and tasks are split across days when they exceed remaining capacity.
- → Every dependency respected, every cycle blocked at edge-add
- → Hours bin-packed into your real weekly availability
- → Per-Plan and portfolio-level uncertainty bands on every done-by date
- → Bayesian per-area + per-bucket learning layer that sharpens over time
- → Layered DAG layout that keeps the canvas readable as plans grow
try {
const schedulableNodes = params.nodes.filter((n) => isSchedulable(n));
const expandedEdges = expandMilestoneEdges(
params.nodes,
params.edges,
) as unknown as Edge[];
topologicalSort(schedulableNodes, expandedEdges);
} catch {
const schedulableNodes = params.nodes.filter((n) => isSchedulable(n));
const expandedEdges = expandMilestoneEdges(params.nodes, params.edges).map(
(e) => ({ from: e.from, to: e.to }),
);
const cycle = findLeafCycle(schedulableNodes, expandedEdges);
let cycleDiagnostics: MetaScheduleOutput["cycleDiagnostics"];
if (cycle) {
const workspacesByNode: Record<NodeId, WorkspaceId> = {};
for (const id of cycle.nodeIds) {
const goalId = params.nodeToGoal[id];
if (!goalId) continue;
const wsId = params.goalToWorkspace[goalId];
if (!wsId) continue;
workspacesByNode[id] = wsId;
}
cycleDiagnostics = {
nodeIds: cycle.nodeIds,
edges: cycle.edges,
workspacesByNode,
};
}
// return { error: "cycle_detected", cycleDiagnostics, ... };
}Your day
The Execute board shows exactly what you can act on: a task turns Ready the moment its dependencies clear, you pick it up, and mark it done as you finish. Anything you don't get to carries forward silently and re-prioritises against what remains.
No streaks, no shaming, no "you're behind" pressure. Just a plan that adapts.

Every plan at a glance
One goal is a graph; your life is a portfolio of them. The Plans dashboard shows each plan as a card with its own completion spectrum, P50 end date, budget vs. expected cost, and live status.
Active plans surface their spread at a glance; an overloaded plan (one whose schedule can't fit your availability) is flagged before its deadline slips, and paused plans sit quietly until you pick them back up.
