taskatlas 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. taskatlas-0.0.1/LICENSE +21 -0
  2. taskatlas-0.0.1/PKG-INFO +314 -0
  3. taskatlas-0.0.1/README.md +288 -0
  4. taskatlas-0.0.1/pyproject.toml +43 -0
  5. taskatlas-0.0.1/setup.cfg +4 -0
  6. taskatlas-0.0.1/taskatlas/__init__.py +11 -0
  7. taskatlas-0.0.1/taskatlas/_atlas.py +267 -0
  8. taskatlas-0.0.1/taskatlas/_base.py +345 -0
  9. taskatlas-0.0.1/taskatlas/_event.py +71 -0
  10. taskatlas-0.0.1/taskatlas/_filtering.py +108 -0
  11. taskatlas-0.0.1/taskatlas/_goal.py +325 -0
  12. taskatlas-0.0.1/taskatlas/_identity.py +46 -0
  13. taskatlas-0.0.1/taskatlas/_link.py +90 -0
  14. taskatlas-0.0.1/taskatlas/_task.py +217 -0
  15. taskatlas-0.0.1/taskatlas/_types.py +60 -0
  16. taskatlas-0.0.1/taskatlas/_views.py +198 -0
  17. taskatlas-0.0.1/taskatlas.egg-info/PKG-INFO +314 -0
  18. taskatlas-0.0.1/taskatlas.egg-info/SOURCES.txt +31 -0
  19. taskatlas-0.0.1/taskatlas.egg-info/dependency_links.txt +1 -0
  20. taskatlas-0.0.1/taskatlas.egg-info/requires.txt +3 -0
  21. taskatlas-0.0.1/taskatlas.egg-info/top_level.txt +1 -0
  22. taskatlas-0.0.1/tests/test_atlas.py +240 -0
  23. taskatlas-0.0.1/tests/test_event.py +100 -0
  24. taskatlas-0.0.1/tests/test_filtering.py +169 -0
  25. taskatlas-0.0.1/tests/test_goal.py +280 -0
  26. taskatlas-0.0.1/tests/test_history.py +222 -0
  27. taskatlas-0.0.1/tests/test_identity.py +71 -0
  28. taskatlas-0.0.1/tests/test_link.py +109 -0
  29. taskatlas-0.0.1/tests/test_relationships.py +322 -0
  30. taskatlas-0.0.1/tests/test_serialization.py +244 -0
  31. taskatlas-0.0.1/tests/test_task.py +318 -0
  32. taskatlas-0.0.1/tests/test_types.py +44 -0
  33. taskatlas-0.0.1/tests/test_views.py +181 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 James A. Rolfsen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,314 @@
1
+ Metadata-Version: 2.4
2
+ Name: taskatlas
3
+ Version: 0.0.1
4
+ Summary: A lean Python library for representing goals, tasks, relationships, priority, evolution, and history.
5
+ Author-email: "James A. Rolfsen" <james@think.dev>
6
+ Maintainer-email: "James A. Rolfsen" <james@think.dev>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/jrolf/taskatlas
9
+ Project-URL: Repository, https://github.com/jrolf/taskatlas
10
+ Project-URL: Issues, https://github.com/jrolf/taskatlas/issues
11
+ Keywords: tasks,goals,project-management,work-tracking
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7.0; extra == "dev"
25
+ Dynamic: license-file
26
+
27
+ # taskatlas
28
+
29
+ A lean Python library for representing goals, tasks, relationships, priority, evolution, and history.
30
+
31
+ ---
32
+
33
+ ## What is this?
34
+
35
+ `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.
36
+
37
+ An **Atlas** is a navigable world of:
38
+
39
+ - **Goals** — intended outcomes (what you're trying to achieve)
40
+ - **Tasks** — actionable work (what needs to be done)
41
+ - **Relationships** — typed links between entities (dependencies, blockers, support)
42
+ - **History** — automatic event records of every meaningful change
43
+ - **Views** — board, tree, queue, and summary representations of the current state
44
+
45
+ The library has **zero external dependencies**. It runs on Python 3.10+ using only the standard library.
46
+
47
+ ---
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ pip install taskatlas
53
+ ```
54
+
55
+ For development (includes pytest):
56
+
57
+ ```bash
58
+ git clone https://github.com/jrolf/taskatlas.git
59
+ cd taskatlas
60
+ pip install -e ".[dev]"
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Quick Example
66
+
67
+ ```python
68
+ import taskatlas as ta
69
+
70
+ # Create an atlas
71
+ atlas = ta.Atlas({"name": "My Project"})
72
+
73
+ # Define a goal — an intended outcome
74
+ goal = ta.Goal({
75
+ "title": "Launch the public API",
76
+ "summary": "Ship a stable, documented v1.",
77
+ "status": "active",
78
+ "priority": "high",
79
+ "tags": ["api", "launch"],
80
+ })
81
+ atlas.add_goal(goal)
82
+
83
+ # Add tasks — actionable work
84
+ design = goal.add_task({
85
+ "title": "Design endpoint schema",
86
+ "stage": "active",
87
+ "priority": "high",
88
+ })
89
+
90
+ tests = goal.add_task({
91
+ "title": "Write integration tests",
92
+ "stage": "ready",
93
+ "priority": "high",
94
+ })
95
+
96
+ # Decompose complex tasks into subtasks
97
+ design.add_task({"title": "Define auth endpoints", "stage": "done"})
98
+ design.add_task({"title": "Define data endpoints", "stage": "active"})
99
+
100
+ # Model dependencies with typed links
101
+ tests.link(design, kind="depends_on")
102
+
103
+ # Move tasks through stages
104
+ design.move("review", reason="Implementation complete")
105
+
106
+ # Add notes to capture context
107
+ design.note("Using OpenAPI 3.1 for all endpoint specs.")
108
+
109
+ # Check goal progress
110
+ print(goal.progress())
111
+ # {'goal_id': 'g-...', 'task_count': 2, 'by_stage': {'review': 1, 'ready': 1},
112
+ # 'done_count': 0, 'done_ratio': 0.0, ...}
113
+
114
+ # View the board
115
+ print(atlas.board())
116
+
117
+ # Inspect history — every mutation is recorded automatically
118
+ for event in atlas.recent(limit=5):
119
+ print(f"{event.event_type}: {event.reason or ''}")
120
+
121
+ # Save the entire atlas to JSON
122
+ atlas.save("project.json")
123
+
124
+ # Reload it later — everything is preserved
125
+ atlas2 = ta.Atlas.load("project.json")
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Core Concepts
131
+
132
+ ### Atlas
133
+
134
+ The root container. It owns all goals, tasks, links, and events. It's the single object you serialize and restore.
135
+
136
+ ```python
137
+ atlas = ta.Atlas({"name": "Q3 Roadmap"})
138
+ ```
139
+
140
+ ### Goal
141
+
142
+ A higher-order intended outcome. Goals have **statuses**: `proposed`, `active`, `paused`, `achieved`, `archived`.
143
+
144
+ ```python
145
+ goal = ta.Goal({"title": "Improve reliability", "status": "active", "priority": "high"})
146
+ atlas.add_goal(goal)
147
+ ```
148
+
149
+ ### Task
150
+
151
+ An actionable work unit. Tasks have **stages**: `inbox`, `ready`, `active`, `blocked`, `review`, `done`, `archived`.
152
+
153
+ ```python
154
+ task = ta.Task({"title": "Add retry logic", "stage": "ready", "priority": "high"})
155
+ atlas.add_task(task)
156
+ ```
157
+
158
+ ### Containment vs. Links
159
+
160
+ These are two distinct relationship types that are never conflated:
161
+
162
+ **Containment** is structural nesting — subtasks under tasks, subgoals under goals, tasks attached to goals:
163
+
164
+ ```python
165
+ goal.add_task(task) # attach task to goal
166
+ task.add_task(subtask) # nest subtask under task
167
+ goal.add_goal(subgoal) # nest subgoal under goal
168
+ ```
169
+
170
+ **Links** are typed cross-references — dependencies, blockers, and other semantic relationships:
171
+
172
+ ```python
173
+ task_a.link(task_b, kind="depends_on")
174
+ task_c.link(task_d, kind="blocks")
175
+ goal.link(other_goal, kind="supports")
176
+ ```
177
+
178
+ Available link kinds: `depends_on`, `blocks`, `relates_to`, `supports`, `duplicates`, `derived_from`, `conflicts_with`.
179
+
180
+ ### Notes
181
+
182
+ Append-only, timestamped annotations on any goal or task:
183
+
184
+ ```python
185
+ task.note("Switched approach after profiling showed the bottleneck.")
186
+ task.note("Results look good.", meta={"runtime_ms": 340})
187
+ ```
188
+
189
+ ### Automatic History
190
+
191
+ Every mutation generates an `Event` — stage changes, status changes, priority changes, notes, links, attachments. You never manually log history; the library does it.
192
+
193
+ ```python
194
+ task.history() # per-entity, newest first
195
+ atlas.get_events(limit=20) # global, newest first
196
+ atlas.recent(limit=10) # shortcut for recent activity
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Filtering and Retrieval
202
+
203
+ Simple keyword arguments, conjunctive (AND) logic:
204
+
205
+ ```python
206
+ atlas.get_tasks(stage="active", priority="high")
207
+ atlas.get_tasks(tags=["backend"], order_by="priority")
208
+ atlas.get_tasks(goal_id=goal.id, blocked=True)
209
+ atlas.get_tasks(title_contains="auth")
210
+
211
+ atlas.get_goals(status="active")
212
+ atlas.get_goals(priority="high", tags=["core"])
213
+ ```
214
+
215
+ Archived items are excluded by default. Use `archived=True` to query them explicitly.
216
+
217
+ ---
218
+
219
+ ## Views
220
+
221
+ Four built-in views return structured Python data (dicts and lists), ready for rendering however you need:
222
+
223
+ | Method | Returns | Purpose |
224
+ |---|---|---|
225
+ | `atlas.board()` | Tasks grouped by stage | Kanban-style workflow view |
226
+ | `atlas.tree()` | Nested goal/task hierarchy | Structural overview |
227
+ | `atlas.queue()` | Priority-sorted actionable tasks | "What should I do next?" |
228
+ | `atlas.summary()` | Aggregate counts and recent events | Dashboard / status check |
229
+
230
+ Each goal and task also has a `.context()` method that returns a focused situational summary:
231
+
232
+ ```python
233
+ task.context() # compact: id, title, stage, priority, latest note
234
+ task.context(mode="full") # everything: links, notes, events, parent/children
235
+ goal.context(mode="full") # includes progress snapshot
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Serialization
241
+
242
+ Full round-trip serialization to JSON files or JSON-compatible dicts:
243
+
244
+ ```python
245
+ # File-based (recommended)
246
+ atlas.save("atlas.json")
247
+ atlas = ta.Atlas.load("atlas.json")
248
+
249
+ # Dict-based
250
+ payload = atlas.to_dict() # atlas → dict
251
+ atlas = ta.Atlas.from_dict(payload) # dict → atlas
252
+ ```
253
+
254
+ Everything is preserved: IDs, relationships, notes, links, events, timestamps, metadata.
255
+
256
+ ---
257
+
258
+ ## Project Structure
259
+
260
+ ```
261
+ taskatlas/
262
+ ├── __init__.py # Public API: Atlas, Goal, Task, Link, Event
263
+ ├── _atlas.py # Atlas container and registry
264
+ ├── _goal.py # Goal class
265
+ ├── _task.py # Task class
266
+ ├── _base.py # Shared WorkItem base class
267
+ ├── _link.py # Typed relationship model
268
+ ├── _event.py # Historical event model
269
+ ├── _filtering.py # Query and sort helpers
270
+ ├── _views.py # Board, tree, queue, summary renderers
271
+ ├── _identity.py # ID generation
272
+ └── _types.py # Constants and defaults
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Tutorials
278
+
279
+ The `tutorials/` directory contains detailed walkthroughs:
280
+
281
+ 1. **[Quickstart](tutorials/01_quickstart.md)** — Your first atlas, goals, tasks, and board
282
+ 2. **[Modeling a Real Project](tutorials/02_modeling_a_real_project.md)** — End-to-end example with a data platform
283
+ 3. **[Relationships and Structure](tutorials/03_relationships_and_structure.md)** — Containment vs. links in depth
284
+ 4. **[History and Evolution](tutorials/04_history_and_evolution.md)** — Automatic events and audit trails
285
+ 5. **[Views and Context](tutorials/05_views_and_context.md)** — Board, tree, queue, summary, and context()
286
+ 6. **[Persistence and Programmatic Use](tutorials/06_persistence_and_programmatic_use.md)** — Serialization, agents, and automation
287
+ 7. **[Filtering and Retrieval](tutorials/07_filtering_and_retrieval.md)** — Every filter option with examples
288
+
289
+ ---
290
+
291
+ ## Running Tests
292
+
293
+ ```bash
294
+ pytest
295
+ ```
296
+
297
+ The test suite contains 213 tests covering all modules, relationships, history, views, and serialization round-trips.
298
+
299
+ ---
300
+
301
+ ## Design Philosophy
302
+
303
+ - **Goals are not tasks.** Goals represent intended outcomes. Tasks represent work. They have different lifecycles and different semantics.
304
+ - **Containment is not linking.** Subtask nesting is structural. Dependencies and blockers are cross-references. These are kept separate.
305
+ - **History is automatic.** Every meaningful mutation creates an event. You never have to manually log what happened.
306
+ - **Retrieval returns context, not rows.** The library should feel like asking a colleague, not querying a database.
307
+ - **The board is a view, not the ontology.** Tasks may move through stages, but the underlying reality is richer than columns on a board.
308
+ - **Stay lean.** Zero dependencies. Small API surface. No enterprise ceremony.
309
+
310
+ ---
311
+
312
+ ## License
313
+
314
+ MIT
@@ -0,0 +1,288 @@
1
+ # taskatlas
2
+
3
+ A lean Python library for representing goals, tasks, relationships, priority, evolution, and history.
4
+
5
+ ---
6
+
7
+ ## What is this?
8
+
9
+ `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.
10
+
11
+ An **Atlas** is a navigable world of:
12
+
13
+ - **Goals** — intended outcomes (what you're trying to achieve)
14
+ - **Tasks** — actionable work (what needs to be done)
15
+ - **Relationships** — typed links between entities (dependencies, blockers, support)
16
+ - **History** — automatic event records of every meaningful change
17
+ - **Views** — board, tree, queue, and summary representations of the current state
18
+
19
+ The library has **zero external dependencies**. It runs on Python 3.10+ using only the standard library.
20
+
21
+ ---
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pip install taskatlas
27
+ ```
28
+
29
+ For development (includes pytest):
30
+
31
+ ```bash
32
+ git clone https://github.com/jrolf/taskatlas.git
33
+ cd taskatlas
34
+ pip install -e ".[dev]"
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Quick Example
40
+
41
+ ```python
42
+ import taskatlas as ta
43
+
44
+ # Create an atlas
45
+ atlas = ta.Atlas({"name": "My Project"})
46
+
47
+ # Define a goal — an intended outcome
48
+ goal = ta.Goal({
49
+ "title": "Launch the public API",
50
+ "summary": "Ship a stable, documented v1.",
51
+ "status": "active",
52
+ "priority": "high",
53
+ "tags": ["api", "launch"],
54
+ })
55
+ atlas.add_goal(goal)
56
+
57
+ # Add tasks — actionable work
58
+ design = goal.add_task({
59
+ "title": "Design endpoint schema",
60
+ "stage": "active",
61
+ "priority": "high",
62
+ })
63
+
64
+ tests = goal.add_task({
65
+ "title": "Write integration tests",
66
+ "stage": "ready",
67
+ "priority": "high",
68
+ })
69
+
70
+ # Decompose complex tasks into subtasks
71
+ design.add_task({"title": "Define auth endpoints", "stage": "done"})
72
+ design.add_task({"title": "Define data endpoints", "stage": "active"})
73
+
74
+ # Model dependencies with typed links
75
+ tests.link(design, kind="depends_on")
76
+
77
+ # Move tasks through stages
78
+ design.move("review", reason="Implementation complete")
79
+
80
+ # Add notes to capture context
81
+ design.note("Using OpenAPI 3.1 for all endpoint specs.")
82
+
83
+ # Check goal progress
84
+ print(goal.progress())
85
+ # {'goal_id': 'g-...', 'task_count': 2, 'by_stage': {'review': 1, 'ready': 1},
86
+ # 'done_count': 0, 'done_ratio': 0.0, ...}
87
+
88
+ # View the board
89
+ print(atlas.board())
90
+
91
+ # Inspect history — every mutation is recorded automatically
92
+ for event in atlas.recent(limit=5):
93
+ print(f"{event.event_type}: {event.reason or ''}")
94
+
95
+ # Save the entire atlas to JSON
96
+ atlas.save("project.json")
97
+
98
+ # Reload it later — everything is preserved
99
+ atlas2 = ta.Atlas.load("project.json")
100
+ ```
101
+
102
+ ---
103
+
104
+ ## Core Concepts
105
+
106
+ ### Atlas
107
+
108
+ The root container. It owns all goals, tasks, links, and events. It's the single object you serialize and restore.
109
+
110
+ ```python
111
+ atlas = ta.Atlas({"name": "Q3 Roadmap"})
112
+ ```
113
+
114
+ ### Goal
115
+
116
+ A higher-order intended outcome. Goals have **statuses**: `proposed`, `active`, `paused`, `achieved`, `archived`.
117
+
118
+ ```python
119
+ goal = ta.Goal({"title": "Improve reliability", "status": "active", "priority": "high"})
120
+ atlas.add_goal(goal)
121
+ ```
122
+
123
+ ### Task
124
+
125
+ An actionable work unit. Tasks have **stages**: `inbox`, `ready`, `active`, `blocked`, `review`, `done`, `archived`.
126
+
127
+ ```python
128
+ task = ta.Task({"title": "Add retry logic", "stage": "ready", "priority": "high"})
129
+ atlas.add_task(task)
130
+ ```
131
+
132
+ ### Containment vs. Links
133
+
134
+ These are two distinct relationship types that are never conflated:
135
+
136
+ **Containment** is structural nesting — subtasks under tasks, subgoals under goals, tasks attached to goals:
137
+
138
+ ```python
139
+ goal.add_task(task) # attach task to goal
140
+ task.add_task(subtask) # nest subtask under task
141
+ goal.add_goal(subgoal) # nest subgoal under goal
142
+ ```
143
+
144
+ **Links** are typed cross-references — dependencies, blockers, and other semantic relationships:
145
+
146
+ ```python
147
+ task_a.link(task_b, kind="depends_on")
148
+ task_c.link(task_d, kind="blocks")
149
+ goal.link(other_goal, kind="supports")
150
+ ```
151
+
152
+ Available link kinds: `depends_on`, `blocks`, `relates_to`, `supports`, `duplicates`, `derived_from`, `conflicts_with`.
153
+
154
+ ### Notes
155
+
156
+ Append-only, timestamped annotations on any goal or task:
157
+
158
+ ```python
159
+ task.note("Switched approach after profiling showed the bottleneck.")
160
+ task.note("Results look good.", meta={"runtime_ms": 340})
161
+ ```
162
+
163
+ ### Automatic History
164
+
165
+ Every mutation generates an `Event` — stage changes, status changes, priority changes, notes, links, attachments. You never manually log history; the library does it.
166
+
167
+ ```python
168
+ task.history() # per-entity, newest first
169
+ atlas.get_events(limit=20) # global, newest first
170
+ atlas.recent(limit=10) # shortcut for recent activity
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Filtering and Retrieval
176
+
177
+ Simple keyword arguments, conjunctive (AND) logic:
178
+
179
+ ```python
180
+ atlas.get_tasks(stage="active", priority="high")
181
+ atlas.get_tasks(tags=["backend"], order_by="priority")
182
+ atlas.get_tasks(goal_id=goal.id, blocked=True)
183
+ atlas.get_tasks(title_contains="auth")
184
+
185
+ atlas.get_goals(status="active")
186
+ atlas.get_goals(priority="high", tags=["core"])
187
+ ```
188
+
189
+ Archived items are excluded by default. Use `archived=True` to query them explicitly.
190
+
191
+ ---
192
+
193
+ ## Views
194
+
195
+ Four built-in views return structured Python data (dicts and lists), ready for rendering however you need:
196
+
197
+ | Method | Returns | Purpose |
198
+ |---|---|---|
199
+ | `atlas.board()` | Tasks grouped by stage | Kanban-style workflow view |
200
+ | `atlas.tree()` | Nested goal/task hierarchy | Structural overview |
201
+ | `atlas.queue()` | Priority-sorted actionable tasks | "What should I do next?" |
202
+ | `atlas.summary()` | Aggregate counts and recent events | Dashboard / status check |
203
+
204
+ Each goal and task also has a `.context()` method that returns a focused situational summary:
205
+
206
+ ```python
207
+ task.context() # compact: id, title, stage, priority, latest note
208
+ task.context(mode="full") # everything: links, notes, events, parent/children
209
+ goal.context(mode="full") # includes progress snapshot
210
+ ```
211
+
212
+ ---
213
+
214
+ ## Serialization
215
+
216
+ Full round-trip serialization to JSON files or JSON-compatible dicts:
217
+
218
+ ```python
219
+ # File-based (recommended)
220
+ atlas.save("atlas.json")
221
+ atlas = ta.Atlas.load("atlas.json")
222
+
223
+ # Dict-based
224
+ payload = atlas.to_dict() # atlas → dict
225
+ atlas = ta.Atlas.from_dict(payload) # dict → atlas
226
+ ```
227
+
228
+ Everything is preserved: IDs, relationships, notes, links, events, timestamps, metadata.
229
+
230
+ ---
231
+
232
+ ## Project Structure
233
+
234
+ ```
235
+ taskatlas/
236
+ ├── __init__.py # Public API: Atlas, Goal, Task, Link, Event
237
+ ├── _atlas.py # Atlas container and registry
238
+ ├── _goal.py # Goal class
239
+ ├── _task.py # Task class
240
+ ├── _base.py # Shared WorkItem base class
241
+ ├── _link.py # Typed relationship model
242
+ ├── _event.py # Historical event model
243
+ ├── _filtering.py # Query and sort helpers
244
+ ├── _views.py # Board, tree, queue, summary renderers
245
+ ├── _identity.py # ID generation
246
+ └── _types.py # Constants and defaults
247
+ ```
248
+
249
+ ---
250
+
251
+ ## Tutorials
252
+
253
+ The `tutorials/` directory contains detailed walkthroughs:
254
+
255
+ 1. **[Quickstart](tutorials/01_quickstart.md)** — Your first atlas, goals, tasks, and board
256
+ 2. **[Modeling a Real Project](tutorials/02_modeling_a_real_project.md)** — End-to-end example with a data platform
257
+ 3. **[Relationships and Structure](tutorials/03_relationships_and_structure.md)** — Containment vs. links in depth
258
+ 4. **[History and Evolution](tutorials/04_history_and_evolution.md)** — Automatic events and audit trails
259
+ 5. **[Views and Context](tutorials/05_views_and_context.md)** — Board, tree, queue, summary, and context()
260
+ 6. **[Persistence and Programmatic Use](tutorials/06_persistence_and_programmatic_use.md)** — Serialization, agents, and automation
261
+ 7. **[Filtering and Retrieval](tutorials/07_filtering_and_retrieval.md)** — Every filter option with examples
262
+
263
+ ---
264
+
265
+ ## Running Tests
266
+
267
+ ```bash
268
+ pytest
269
+ ```
270
+
271
+ The test suite contains 213 tests covering all modules, relationships, history, views, and serialization round-trips.
272
+
273
+ ---
274
+
275
+ ## Design Philosophy
276
+
277
+ - **Goals are not tasks.** Goals represent intended outcomes. Tasks represent work. They have different lifecycles and different semantics.
278
+ - **Containment is not linking.** Subtask nesting is structural. Dependencies and blockers are cross-references. These are kept separate.
279
+ - **History is automatic.** Every meaningful mutation creates an event. You never have to manually log what happened.
280
+ - **Retrieval returns context, not rows.** The library should feel like asking a colleague, not querying a database.
281
+ - **The board is a view, not the ontology.** Tasks may move through stages, but the underlying reality is richer than columns on a board.
282
+ - **Stay lean.** Zero dependencies. Small API surface. No enterprise ceremony.
283
+
284
+ ---
285
+
286
+ ## License
287
+
288
+ MIT
@@ -0,0 +1,43 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "taskatlas"
7
+ version = "0.0.1"
8
+ description = "A lean Python library for representing goals, tasks, relationships, priority, evolution, and history."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.10"
13
+ authors = [
14
+ { name = "James A. Rolfsen", email = "james@think.dev" }
15
+ ]
16
+ maintainers = [
17
+ { name = "James A. Rolfsen", email = "james@think.dev" }
18
+ ]
19
+ keywords = ["tasks", "goals", "project-management", "work-tracking"]
20
+ classifiers = [
21
+ "Development Status :: 3 - Alpha",
22
+ "Intended Audience :: Developers",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Topic :: Software Development :: Libraries",
29
+ ]
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/jrolf/taskatlas"
33
+ Repository = "https://github.com/jrolf/taskatlas"
34
+ Issues = "https://github.com/jrolf/taskatlas/issues"
35
+
36
+ [project.optional-dependencies]
37
+ dev = ["pytest>=7.0"]
38
+
39
+ [tool.pytest.ini_options]
40
+ testpaths = ["tests"]
41
+
42
+ [tool.setuptools.packages.find]
43
+ include = ["taskatlas*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,11 @@
1
+ """taskatlas — A lean Python library for representing goals, tasks,
2
+ relationships, priority, evolution, and history."""
3
+
4
+ from taskatlas._atlas import Atlas
5
+ from taskatlas._event import Event
6
+ from taskatlas._goal import Goal
7
+ from taskatlas._link import Link
8
+ from taskatlas._task import Task
9
+
10
+ __all__ = ["Atlas", "Goal", "Task", "Link", "Event"]
11
+ __version__ = "0.0.1"