A lean Python library for representing goals, tasks, relationships, priority, evolution, and history.
taskatlas gives you a clean, Pythonic object model for tracking work. It sits in the space between a simple task list and an enterprise issue tracker — expressive enough to model real project structure, lightweight enough to feel like writing regular Python.
An Atlas is a navigable world of:
- Goals — intended outcomes (what you're trying to achieve)
- Tasks — actionable work (what needs to be done)
- Relationships — typed links between entities (dependencies, blockers, support)
- History — automatic event records of every meaningful change
- Views — board, tree, queue, and summary representations of the current state
The library has zero external dependencies. It runs on Python 3.10+ using only the standard library.
pip install taskatlasFor development (includes pytest):
git clone https://github.com/jrolf/taskatlas.git
cd taskatlas
pip install -e ".[dev]"import taskatlas as ta
# Create an atlas
atlas = ta.Atlas({"name": "My Project"})
# Define a goal — an intended outcome
goal = ta.Goal({
"title": "Launch the public API",
"summary": "Ship a stable, documented v1.",
"status": "active",
"priority": "high",
"tags": ["api", "launch"],
})
atlas.add_goal(goal)
# Add tasks — actionable work
design = goal.add_task({
"title": "Design endpoint schema",
"stage": "active",
"priority": "high",
})
tests = goal.add_task({
"title": "Write integration tests",
"stage": "ready",
"priority": "high",
})
# Decompose complex tasks into subtasks
design.add_task({"title": "Define auth endpoints", "stage": "done"})
design.add_task({"title": "Define data endpoints", "stage": "active"})
# Model dependencies with typed links
tests.link(design, kind="depends_on")
# Move tasks through stages
design.move("review", reason="Implementation complete")
# Add notes to capture context
design.note("Using OpenAPI 3.1 for all endpoint specs.")
# Check goal progress
print(goal.progress())
# {'goal_id': 'g-...', 'task_count': 2, 'by_stage': {'review': 1, 'ready': 1},
# 'done_count': 0, 'done_ratio': 0.0, ...}
# View the board
print(atlas.board())
# Inspect history — every mutation is recorded automatically
for event in atlas.recent(limit=5):
print(f"{event.event_type}: {event.reason or ''}")
# Save the entire atlas to JSON
atlas.save("project.json")
# Reload it later — everything is preserved
atlas2 = ta.Atlas.load("project.json")The root container. It owns all goals, tasks, links, and events. It's the single object you serialize and restore.
atlas = ta.Atlas({"name": "Q3 Roadmap"})A higher-order intended outcome. Goals have statuses: proposed, active, paused, achieved, archived.
goal = ta.Goal({"title": "Improve reliability", "status": "active", "priority": "high"})
atlas.add_goal(goal)An actionable work unit. Tasks have stages: inbox, ready, active, blocked, review, done, archived.
task = ta.Task({"title": "Add retry logic", "stage": "ready", "priority": "high"})
atlas.add_task(task)These are two distinct relationship types that are never conflated:
Containment is structural nesting — subtasks under tasks, subgoals under goals, tasks attached to goals:
goal.add_task(task) # attach task to goal
task.add_task(subtask) # nest subtask under task
goal.add_goal(subgoal) # nest subgoal under goalLinks are typed cross-references — dependencies, blockers, and other semantic relationships:
task_a.link(task_b, kind="depends_on")
task_c.link(task_d, kind="blocks")
goal.link(other_goal, kind="supports")Available link kinds: depends_on, blocks, relates_to, supports, duplicates, derived_from, conflicts_with.
Append-only, timestamped annotations on any goal or task:
task.note("Switched approach after profiling showed the bottleneck.")
task.note("Results look good.", meta={"runtime_ms": 340})Every mutation generates an Event — stage changes, status changes, priority changes, notes, links, attachments. You never manually log history; the library does it.
task.history() # per-entity, newest first
atlas.get_events(limit=20) # global, newest first
atlas.recent(limit=10) # shortcut for recent activitySimple keyword arguments, conjunctive (AND) logic:
atlas.get_tasks(stage="active", priority="high")
atlas.get_tasks(tags=["backend"], order_by="priority")
atlas.get_tasks(goal_id=goal.id, blocked=True)
atlas.get_tasks(title_contains="auth")
atlas.get_goals(status="active")
atlas.get_goals(priority="high", tags=["core"])Archived items are excluded by default. Use archived=True to query them explicitly.
Four built-in views return structured Python data (dicts and lists), ready for rendering however you need:
| Method | Returns | Purpose |
|---|---|---|
atlas.board() |
Tasks grouped by stage | Kanban-style workflow view |
atlas.tree() |
Nested goal/task hierarchy | Structural overview |
atlas.queue() |
Priority-sorted actionable tasks | "What should I do next?" |
atlas.summary() |
Aggregate counts and recent events | Dashboard / status check |
Each goal and task also has a .context() method that returns a focused situational summary:
task.context() # compact: id, title, stage, priority, latest note
task.context(mode="full") # everything: links, notes, events, parent/children
goal.context(mode="full") # includes progress snapshotFull round-trip serialization to JSON files or JSON-compatible dicts:
# File-based (recommended)
atlas.save("atlas.json")
atlas = ta.Atlas.load("atlas.json")
# Dict-based
payload = atlas.to_dict() # atlas → dict
atlas = ta.Atlas.from_dict(payload) # dict → atlasEverything is preserved: IDs, relationships, notes, links, events, timestamps, metadata.
taskatlas/
├── __init__.py # Public API: Atlas, Goal, Task, Link, Event
├── _atlas.py # Atlas container and registry
├── _goal.py # Goal class
├── _task.py # Task class
├── _base.py # Shared WorkItem base class
├── _link.py # Typed relationship model
├── _event.py # Historical event model
├── _filtering.py # Query and sort helpers
├── _views.py # Board, tree, queue, summary renderers
├── _identity.py # ID generation
└── _types.py # Constants and defaults
The tutorials/ directory contains detailed walkthroughs:
- Quickstart — Your first atlas, goals, tasks, and board
- Modeling a Real Project — End-to-end example with a data platform
- Relationships and Structure — Containment vs. links in depth
- History and Evolution — Automatic events and audit trails
- Views and Context — Board, tree, queue, summary, and context()
- Persistence and Programmatic Use — Serialization, agents, and automation
- Filtering and Retrieval — Every filter option with examples
pytestThe test suite contains 213 tests covering all modules, relationships, history, views, and serialization round-trips.
- Goals are not tasks. Goals represent intended outcomes. Tasks represent work. They have different lifecycles and different semantics.
- Containment is not linking. Subtask nesting is structural. Dependencies and blockers are cross-references. These are kept separate.
- History is automatic. Every meaningful mutation creates an event. You never have to manually log what happened.
- Retrieval returns context, not rows. The library should feel like asking a colleague, not querying a database.
- The board is a view, not the ontology. Tasks may move through stages, but the underlying reality is richer than columns on a board.
- Stay lean. Zero dependencies. Small API surface. No enterprise ceremony.
Contributions are welcome. Please read CONTRIBUTING.md for the branch model, how to run tests, and PR guidelines.
MIT