opentasks 0.1.2 → 0.2.0

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 (280) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +218 -49
  3. package/dist/cli.d.ts +20 -0
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +451 -15
  6. package/dist/cli.js.map +1 -1
  7. package/dist/client/client.d.ts +54 -0
  8. package/dist/client/client.d.ts.map +1 -1
  9. package/dist/client/client.js +148 -4
  10. package/dist/client/client.js.map +1 -1
  11. package/dist/client/index.d.ts +1 -1
  12. package/dist/client/index.d.ts.map +1 -1
  13. package/dist/client/index.js +1 -1
  14. package/dist/client/index.js.map +1 -1
  15. package/dist/core/discover.d.ts.map +1 -1
  16. package/dist/core/discover.js +7 -2
  17. package/dist/core/discover.js.map +1 -1
  18. package/dist/core/hash.d.ts.map +1 -1
  19. package/dist/core/hash.js +7 -0
  20. package/dist/core/hash.js.map +1 -1
  21. package/dist/core/id.d.ts +1 -1
  22. package/dist/core/id.d.ts.map +1 -1
  23. package/dist/core/id.js +2 -0
  24. package/dist/core/id.js.map +1 -1
  25. package/dist/core/worktree.js +4 -4
  26. package/dist/core/worktree.js.map +1 -1
  27. package/dist/daemon/events.d.ts +82 -0
  28. package/dist/daemon/events.d.ts.map +1 -0
  29. package/dist/daemon/events.js +71 -0
  30. package/dist/daemon/events.js.map +1 -0
  31. package/dist/daemon/flush.d.ts.map +1 -1
  32. package/dist/daemon/flush.js +12 -2
  33. package/dist/daemon/flush.js.map +1 -1
  34. package/dist/daemon/health-counters.d.ts +38 -0
  35. package/dist/daemon/health-counters.d.ts.map +1 -0
  36. package/dist/daemon/health-counters.js +42 -0
  37. package/dist/daemon/health-counters.js.map +1 -0
  38. package/dist/daemon/idempotency.d.ts +50 -0
  39. package/dist/daemon/idempotency.d.ts.map +1 -0
  40. package/dist/daemon/idempotency.js +104 -0
  41. package/dist/daemon/idempotency.js.map +1 -0
  42. package/dist/daemon/index.d.ts +2 -0
  43. package/dist/daemon/index.d.ts.map +1 -1
  44. package/dist/daemon/index.js +1 -0
  45. package/dist/daemon/index.js.map +1 -1
  46. package/dist/daemon/ipc.d.ts +32 -2
  47. package/dist/daemon/ipc.d.ts.map +1 -1
  48. package/dist/daemon/ipc.js +54 -3
  49. package/dist/daemon/ipc.js.map +1 -1
  50. package/dist/daemon/lifecycle.d.ts.map +1 -1
  51. package/dist/daemon/lifecycle.js +302 -8
  52. package/dist/daemon/lifecycle.js.map +1 -1
  53. package/dist/daemon/location-state.d.ts +60 -1
  54. package/dist/daemon/location-state.d.ts.map +1 -1
  55. package/dist/daemon/location-state.js +136 -31
  56. package/dist/daemon/location-state.js.map +1 -1
  57. package/dist/daemon/methods/context-files.d.ts.map +1 -1
  58. package/dist/daemon/methods/context-files.js +4 -3
  59. package/dist/daemon/methods/context-files.js.map +1 -1
  60. package/dist/daemon/methods/events.d.ts +22 -0
  61. package/dist/daemon/methods/events.d.ts.map +1 -0
  62. package/dist/daemon/methods/events.js +30 -0
  63. package/dist/daemon/methods/events.js.map +1 -0
  64. package/dist/daemon/methods/graph.d.ts +7 -0
  65. package/dist/daemon/methods/graph.d.ts.map +1 -1
  66. package/dist/daemon/methods/graph.js +24 -14
  67. package/dist/daemon/methods/graph.js.map +1 -1
  68. package/dist/daemon/methods/lifecycle.d.ts +16 -0
  69. package/dist/daemon/methods/lifecycle.d.ts.map +1 -1
  70. package/dist/daemon/methods/lifecycle.js +3 -1
  71. package/dist/daemon/methods/lifecycle.js.map +1 -1
  72. package/dist/daemon/methods/location.js.map +1 -1
  73. package/dist/daemon/methods/sync.d.ts +113 -0
  74. package/dist/daemon/methods/sync.d.ts.map +1 -0
  75. package/dist/daemon/methods/sync.js +158 -0
  76. package/dist/daemon/methods/sync.js.map +1 -0
  77. package/dist/daemon/methods/tools.d.ts.map +1 -1
  78. package/dist/daemon/methods/tools.js +42 -8
  79. package/dist/daemon/methods/tools.js.map +1 -1
  80. package/dist/daemon/methods/watch.d.ts +24 -0
  81. package/dist/daemon/methods/watch.d.ts.map +1 -1
  82. package/dist/daemon/methods/watch.js +178 -88
  83. package/dist/daemon/methods/watch.js.map +1 -1
  84. package/dist/daemon/sessionlog-watcher.d.ts.map +1 -1
  85. package/dist/daemon/sessionlog-watcher.js +4 -0
  86. package/dist/daemon/sessionlog-watcher.js.map +1 -1
  87. package/dist/graph/EdgeTypeRegistry.d.ts.map +1 -1
  88. package/dist/graph/EdgeTypeRegistry.js +32 -0
  89. package/dist/graph/EdgeTypeRegistry.js.map +1 -1
  90. package/dist/graph/FederatedGraph.d.ts.map +1 -1
  91. package/dist/graph/GraphologyAdapter.d.ts.map +1 -1
  92. package/dist/graph/GraphologyAdapter.js.map +1 -1
  93. package/dist/graph/HydratingFederatedGraph.d.ts.map +1 -1
  94. package/dist/graph/HydratingFederatedGraph.js +1 -1
  95. package/dist/graph/HydratingFederatedGraph.js.map +1 -1
  96. package/dist/graph/attempts.d.ts +50 -0
  97. package/dist/graph/attempts.d.ts.map +1 -0
  98. package/dist/graph/attempts.js +51 -0
  99. package/dist/graph/attempts.js.map +1 -0
  100. package/dist/graph/coordination.d.ts +4 -2
  101. package/dist/graph/coordination.d.ts.map +1 -1
  102. package/dist/graph/coordination.js +77 -85
  103. package/dist/graph/coordination.js.map +1 -1
  104. package/dist/graph/expansion.d.ts.map +1 -1
  105. package/dist/graph/expansion.js +1 -1
  106. package/dist/graph/expansion.js.map +1 -1
  107. package/dist/graph/git-graph-syncer.d.ts +24 -0
  108. package/dist/graph/git-graph-syncer.d.ts.map +1 -1
  109. package/dist/graph/git-graph-syncer.js +111 -26
  110. package/dist/graph/git-graph-syncer.js.map +1 -1
  111. package/dist/graph/provider-store.d.ts +12 -1
  112. package/dist/graph/provider-store.d.ts.map +1 -1
  113. package/dist/graph/provider-store.js +35 -8
  114. package/dist/graph/provider-store.js.map +1 -1
  115. package/dist/graph/query.d.ts.map +1 -1
  116. package/dist/graph/query.js +18 -2
  117. package/dist/graph/query.js.map +1 -1
  118. package/dist/graph/store.d.ts +18 -2
  119. package/dist/graph/store.d.ts.map +1 -1
  120. package/dist/graph/store.js +43 -0
  121. package/dist/graph/store.js.map +1 -1
  122. package/dist/graph/sync.js +1 -1
  123. package/dist/graph/sync.js.map +1 -1
  124. package/dist/graph/types.d.ts +9 -1
  125. package/dist/graph/types.d.ts.map +1 -1
  126. package/dist/graph/types.js.map +1 -1
  127. package/dist/graph/validation.d.ts.map +1 -1
  128. package/dist/graph/validation.js +20 -2
  129. package/dist/graph/validation.js.map +1 -1
  130. package/dist/index.d.ts +3 -1
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +5 -1
  133. package/dist/index.js.map +1 -1
  134. package/dist/materialization/archiver.d.ts.map +1 -1
  135. package/dist/materialization/archiver.js.map +1 -1
  136. package/dist/materialization/snapshot.d.ts.map +1 -1
  137. package/dist/materialization/snapshot.js +1 -1
  138. package/dist/materialization/snapshot.js.map +1 -1
  139. package/dist/materialization/types.d.ts +7 -5
  140. package/dist/materialization/types.d.ts.map +1 -1
  141. package/dist/materialization/types.js.map +1 -1
  142. package/dist/mcp/server.d.ts +2 -1
  143. package/dist/mcp/server.d.ts.map +1 -1
  144. package/dist/mcp/server.js +308 -11
  145. package/dist/mcp/server.js.map +1 -1
  146. package/dist/providers/beads.d.ts.map +1 -1
  147. package/dist/providers/beads.js +2 -0
  148. package/dist/providers/beads.js.map +1 -1
  149. package/dist/providers/claude-tasks.d.ts.map +1 -1
  150. package/dist/providers/claude-tasks.js.map +1 -1
  151. package/dist/providers/global.js +1 -1
  152. package/dist/providers/global.js.map +1 -1
  153. package/dist/providers/location.d.ts.map +1 -1
  154. package/dist/providers/location.js.map +1 -1
  155. package/dist/providers/map-client-factory.d.ts.map +1 -1
  156. package/dist/providers/map-client-factory.js +1 -1
  157. package/dist/providers/map-client-factory.js.map +1 -1
  158. package/dist/providers/map-connector.js +1 -1
  159. package/dist/providers/map-connector.js.map +1 -1
  160. package/dist/providers/map-event-bridge.d.ts.map +1 -1
  161. package/dist/providers/map-event-bridge.js +1 -0
  162. package/dist/providers/map-event-bridge.js.map +1 -1
  163. package/dist/providers/map.d.ts.map +1 -1
  164. package/dist/providers/map.js +5 -2
  165. package/dist/providers/map.js.map +1 -1
  166. package/dist/providers/native.d.ts.map +1 -1
  167. package/dist/providers/native.js +21 -8
  168. package/dist/providers/native.js.map +1 -1
  169. package/dist/providers/registry.js +1 -1
  170. package/dist/providers/registry.js.map +1 -1
  171. package/dist/providers/sudocode.d.ts.map +1 -1
  172. package/dist/providers/sudocode.js +5 -11
  173. package/dist/providers/sudocode.js.map +1 -1
  174. package/dist/providers/traits/Reconcilable.d.ts.map +1 -1
  175. package/dist/providers/traits/TaskManageable.d.ts +15 -1
  176. package/dist/providers/traits/TaskManageable.d.ts.map +1 -1
  177. package/dist/providers/traits/TaskManageable.js +26 -0
  178. package/dist/providers/traits/TaskManageable.js.map +1 -1
  179. package/dist/providers/traits/Watchable.d.ts +6 -0
  180. package/dist/providers/traits/Watchable.d.ts.map +1 -1
  181. package/dist/providers/traits/Watchable.js.map +1 -1
  182. package/dist/providers/types.d.ts +1 -1
  183. package/dist/providers/types.d.ts.map +1 -1
  184. package/dist/schema/edges.d.ts +5 -1
  185. package/dist/schema/edges.d.ts.map +1 -1
  186. package/dist/schema/index.d.ts +2 -2
  187. package/dist/schema/index.d.ts.map +1 -1
  188. package/dist/schema/index.js +1 -1
  189. package/dist/schema/index.js.map +1 -1
  190. package/dist/schema/nodes.d.ts +55 -2
  191. package/dist/schema/nodes.d.ts.map +1 -1
  192. package/dist/schema/storage.d.ts +2 -0
  193. package/dist/schema/storage.d.ts.map +1 -1
  194. package/dist/schema/validation.d.ts +6 -2
  195. package/dist/schema/validation.d.ts.map +1 -1
  196. package/dist/schema/validation.js +18 -1
  197. package/dist/schema/validation.js.map +1 -1
  198. package/dist/sessionlog/agent/registry.js.map +1 -1
  199. package/dist/sessionlog/agent/session-types.d.ts.map +1 -1
  200. package/dist/sessionlog/agent/types.d.ts.map +1 -1
  201. package/dist/sessionlog/commands/clean.js +1 -1
  202. package/dist/sessionlog/commands/clean.js.map +1 -1
  203. package/dist/sessionlog/commands/disable.d.ts.map +1 -1
  204. package/dist/sessionlog/commands/disable.js.map +1 -1
  205. package/dist/sessionlog/commands/doctor.js +1 -1
  206. package/dist/sessionlog/commands/doctor.js.map +1 -1
  207. package/dist/sessionlog/commands/enable.js +1 -1
  208. package/dist/sessionlog/commands/enable.js.map +1 -1
  209. package/dist/sessionlog/commands/resume.js +1 -1
  210. package/dist/sessionlog/commands/resume.js.map +1 -1
  211. package/dist/sessionlog/commands/rewind.d.ts.map +1 -1
  212. package/dist/sessionlog/commands/rewind.js +1 -1
  213. package/dist/sessionlog/commands/rewind.js.map +1 -1
  214. package/dist/sessionlog/commands/status.d.ts.map +1 -1
  215. package/dist/sessionlog/commands/status.js.map +1 -1
  216. package/dist/sessionlog/hooks/lifecycle.d.ts.map +1 -1
  217. package/dist/sessionlog/hooks/lifecycle.js +3 -3
  218. package/dist/sessionlog/hooks/lifecycle.js.map +1 -1
  219. package/dist/sessionlog/security/redaction.js +1 -1
  220. package/dist/sessionlog/security/redaction.js.map +1 -1
  221. package/dist/sessionlog/store/checkpoint-store.d.ts.map +1 -1
  222. package/dist/sessionlog/store/checkpoint-store.js +2 -2
  223. package/dist/sessionlog/store/checkpoint-store.js.map +1 -1
  224. package/dist/sessionlog/store/native-store.d.ts.map +1 -1
  225. package/dist/sessionlog/store/native-store.js.map +1 -1
  226. package/dist/sessionlog/store/session-store.d.ts.map +1 -1
  227. package/dist/sessionlog/store/session-store.js +1 -1
  228. package/dist/sessionlog/store/session-store.js.map +1 -1
  229. package/dist/sessionlog/strategy/attribution.js +2 -2
  230. package/dist/sessionlog/strategy/attribution.js.map +1 -1
  231. package/dist/sessionlog/strategy/common.d.ts +1 -1
  232. package/dist/sessionlog/strategy/common.d.ts.map +1 -1
  233. package/dist/sessionlog/strategy/common.js +3 -3
  234. package/dist/sessionlog/strategy/common.js.map +1 -1
  235. package/dist/sessionlog/strategy/content-overlap.d.ts.map +1 -1
  236. package/dist/sessionlog/strategy/content-overlap.js +1 -1
  237. package/dist/sessionlog/strategy/content-overlap.js.map +1 -1
  238. package/dist/sessionlog/strategy/manual-commit.d.ts.map +1 -1
  239. package/dist/sessionlog/strategy/manual-commit.js +6 -16
  240. package/dist/sessionlog/strategy/manual-commit.js.map +1 -1
  241. package/dist/sessionlog/utils/preview-rewind.d.ts.map +1 -1
  242. package/dist/sessionlog/utils/preview-rewind.js +1 -1
  243. package/dist/sessionlog/utils/preview-rewind.js.map +1 -1
  244. package/dist/sessionlog/utils/trailers.d.ts.map +1 -1
  245. package/dist/sessionlog/utils/trailers.js +0 -1
  246. package/dist/sessionlog/utils/trailers.js.map +1 -1
  247. package/dist/storage/interface.d.ts +64 -0
  248. package/dist/storage/interface.d.ts.map +1 -1
  249. package/dist/storage/interface.js.map +1 -1
  250. package/dist/storage/jsonl.js +2 -2
  251. package/dist/storage/jsonl.js.map +1 -1
  252. package/dist/storage/sqlite-schema.d.ts +8 -2
  253. package/dist/storage/sqlite-schema.d.ts.map +1 -1
  254. package/dist/storage/sqlite-schema.js +10 -1
  255. package/dist/storage/sqlite-schema.js.map +1 -1
  256. package/dist/storage/sqlite.d.ts +16 -1
  257. package/dist/storage/sqlite.d.ts.map +1 -1
  258. package/dist/storage/sqlite.js +134 -2
  259. package/dist/storage/sqlite.js.map +1 -1
  260. package/dist/tools/link.js +1 -1
  261. package/dist/tools/link.js.map +1 -1
  262. package/dist/tools/query.d.ts.map +1 -1
  263. package/dist/tools/query.js +8 -29
  264. package/dist/tools/query.js.map +1 -1
  265. package/dist/tools/task.d.ts.map +1 -1
  266. package/dist/tools/task.js +115 -5
  267. package/dist/tools/task.js.map +1 -1
  268. package/dist/tools/types.d.ts +84 -3
  269. package/dist/tools/types.d.ts.map +1 -1
  270. package/dist/tools/types.js.map +1 -1
  271. package/dist/version.d.ts +14 -0
  272. package/dist/version.d.ts.map +1 -0
  273. package/dist/version.js +44 -0
  274. package/dist/version.js.map +1 -0
  275. package/package.json +32 -7
  276. package/skills/opentasks/SKILL.md +226 -0
  277. package/skills/opentasks/dependency-management.md +119 -0
  278. package/skills/opentasks/feedback-and-review.md +100 -0
  279. package/skills/opentasks/linking-external-data.md +103 -0
  280. package/skills/opentasks/spec-to-implementation.md +171 -0
@@ -0,0 +1,226 @@
1
+ ---
2
+ name: opentasks
3
+ description: Use when managing work items, linking external data (Slack, docs, URLs) to tasks, querying task dependencies or blockers, leaving cross-system feedback on specs or issues, or coordinating work across multiple task systems. Use when the agent has access to the `opentasks` CLI.
4
+ user-invocable: false
5
+ ---
6
+
7
+ # OpenTasks
8
+
9
+ OpenTasks is a graph connector that adds a relationship layer across task systems. It does not replace those systems — it provides cross-system edges, feedback, and dependency tracking.
10
+
11
+ ## CLI Commands
12
+
13
+ All operations go through the `opentasks` CLI, which talks to the daemon over IPC.
14
+
15
+ ### Link — create or remove edges
16
+
17
+ ```bash
18
+ opentasks link --from t-x7k9 --to c-a2b3 --type implements
19
+ opentasks link --from t-x7k9 --to t-m4n5 --type blocks
20
+ opentasks link --from t-x7k9 --to e-k7m2 --type references --metadata '{"context":"bug report"}'
21
+ opentasks link --from t-aaa --to t-bbb --type blocks --remove
22
+ ```
23
+
24
+ Returns `{ success, edgeId? }`. Idempotent. `blocks` edges are cycle-checked.
25
+
26
+ ### Query — search nodes, edges, blockers, ready work
27
+
28
+ ```bash
29
+ opentasks query '{"ready": {}}'
30
+ opentasks query '{"blockers": {"nodeId": "t-r8s9", "activeOnly": true}}'
31
+ opentasks query '{"blocking": {"nodeId": "t-x7k9", "transitive": true}}'
32
+ opentasks query '{"edges": {"from_id": "t-x7k9", "type": "references"}}'
33
+ opentasks query '{"tasks": {"specId": "c-a2b3"}}'
34
+ opentasks query '{"feedback": {"nodeId": "c-a2b3", "resolved": false}}'
35
+ opentasks query '{"unresolvedFeedback": {}}'
36
+ ```
37
+
38
+ Exactly one query key per call. Returns `{ items, total?, hasMore }`.
39
+
40
+ | Key | Purpose |
41
+ |-----|---------|
42
+ | `nodes` | Filter nodes by type, status, tags, search |
43
+ | `edges` | Filter edges by from_id, to_id, type |
44
+ | `ready` | Unblocked open tasks (tags?, priority?, assignee?) |
45
+ | `blockers` | What blocks a node (transitive?, activeOnly?) |
46
+ | `blocking` | What a node blocks (transitive?) |
47
+ | `feedback` | Feedback on a node (type?, resolved?) |
48
+ | `unresolvedFeedback` | All unresolved feedback (targetId?) |
49
+ | `tasks` | Tasks implementing a context (specId) |
50
+ | `specs` | Specs a task implements (issueId) |
51
+
52
+ ### Annotate — feedback lifecycle
53
+
54
+ ```bash
55
+ # Create feedback
56
+ opentasks annotate '{"targetId":"c-a2b3","create":{"content":"Implemented OAuth.","type":"comment"}}'
57
+
58
+ # With source issue link
59
+ opentasks annotate '{"targetId":"c-a2b3","fromId":"t-x7k9","create":{"content":"Done.","type":"comment"}}'
60
+
61
+ # Anchored suggestion
62
+ opentasks annotate '{"targetId":"c-a2b3","create":{"content":"Add rate limiting","type":"suggestion","anchor":{"line":15}}}'
63
+
64
+ # Resolve / dismiss / reopen
65
+ opentasks annotate '{"targetId":"c-a2b3","resolve":"f-t1u2"}'
66
+ opentasks annotate '{"targetId":"c-a2b3","dismiss":"f-t1u2"}'
67
+ opentasks annotate '{"targetId":"c-a2b3","reopen":"f-t1u2"}'
68
+ ```
69
+
70
+ ### Create — add nodes
71
+
72
+ ```bash
73
+ opentasks create --type task --title "Fix SSO redirect" --status open --tags auth,bug --priority 1
74
+ opentasks create --type context --title "OAuth2 for API" --status active --content "## Requirements\n..."
75
+ opentasks create --type external --title "Slack: SSO bug" --uri "slack://C04ABCD/p123" --source slack --metadata '{"author":"alex"}'
76
+ ```
77
+
78
+ ### Get / Update / Delete
79
+
80
+ ```bash
81
+ opentasks get t-x7k9
82
+ opentasks update t-x7k9 --status closed
83
+ opentasks update t-x7k9 --title "New title" --metadata '{"key":"val"}'
84
+ opentasks delete t-x7k9
85
+ opentasks delete t-x7k9 --hard
86
+ ```
87
+
88
+ ## Node Types
89
+
90
+ | Type | Prefix | Required | Purpose |
91
+ |------|--------|----------|---------|
92
+ | `context` | `c-` | title | Requirements, specs, intent (inline or file-backed) |
93
+ | `task` | `t-` | title, status | Actionable work items |
94
+ | `feedback` | `f-` | title, target_id, feedback_type | Comments, suggestions, requests |
95
+ | `external` | `e-` | title, uri, source | References to external systems |
96
+
97
+ All nodes support optional: `content`, `priority` (0-4), `tags[]`, `parent_id`, `metadata`.
98
+
99
+ ## Context Sources
100
+
101
+ Context nodes support multiple content source types. The source type determines how content is stored and resolved.
102
+
103
+ | Source | Stored in node? | How content is accessed |
104
+ |--------|-----------------|------------------------|
105
+ | inline (default) | Yes, in `content` field | Read directly from the node |
106
+ | file | No (pointer only) | Resolved from the working tree or a pinned git commit |
107
+ | snippet | No (pointer only) | Resolved from specific line range in a file |
108
+
109
+ ### Inline context (default)
110
+
111
+ Content is stored directly in the node. Use for design decisions, requirements written by agents, meeting notes, etc.
112
+
113
+ ```bash
114
+ # CLI
115
+ opentasks create --type context --title "OAuth2 for API" --content "## Requirements\n..."
116
+ ```
117
+
118
+ ```json
119
+ // MCP: create_context
120
+ { "title": "OAuth2 for API", "content": "## Requirements\n..." }
121
+ ```
122
+
123
+ ### File-backed context
124
+
125
+ References a codebase file. Content is NOT stored — it's resolved on access from the working tree or at a specific git commit. Includes drift detection (has the file changed since it was captured?).
126
+
127
+ ```json
128
+ // MCP: create_context with source
129
+ {
130
+ "title": "Auth Middleware",
131
+ "source": { "type": "file", "path": "src/auth/middleware.ts" },
132
+ "tags": ["auth"]
133
+ }
134
+
135
+ // Pin to a specific commit
136
+ {
137
+ "source": { "type": "file", "path": "src/auth/middleware.ts", "commit": "abc123" }
138
+ }
139
+ ```
140
+
141
+ ### Snippet context
142
+
143
+ References specific lines in a file. Like file-backed, but scoped to a line range.
144
+
145
+ ```json
146
+ // MCP: create_context with snippet source
147
+ {
148
+ "title": "Token validation logic",
149
+ "source": { "type": "snippet", "path": "src/auth/middleware.ts", "startLine": 42, "endLine": 58 }
150
+ }
151
+ ```
152
+
153
+ ### Resolving content
154
+
155
+ File and snippet contexts don't store content. Use `get_context` with `resolve: true` to fetch the current file content.
156
+
157
+ ```json
158
+ // MCP: get_context — lightweight (metadata only, no file I/O)
159
+ { "id": "c-x7k9" }
160
+
161
+ // MCP: get_context — with file content resolved
162
+ { "id": "c-x7k9", "resolve": true }
163
+
164
+ // MCP: get_context — content at the originally captured commit
165
+ { "id": "c-x7k9", "resolve": true, "atCapturedCommit": true }
166
+ ```
167
+
168
+ The response includes `_resolved.drifted: true/false` indicating whether the file has changed since capture.
169
+
170
+ ### Syncing and drift detection
171
+
172
+ ```json
173
+ // MCP: update_context — re-pin to current HEAD
174
+ { "id": "c-x7k9", "sync": true }
175
+
176
+ // MCP: update_context — force re-pin even if unchanged
177
+ { "id": "c-x7k9", "sync": true, "force": true }
178
+
179
+ // MCP: list_contexts — check drift for all file-backed contexts
180
+ { "checkDrift": true }
181
+
182
+ // MCP: list_contexts — only file-backed contexts
183
+ { "filesOnly": true, "checkDrift": true }
184
+ ```
185
+
186
+ ## Edge Types
187
+
188
+ | Type | Semantics | Cycle-checked |
189
+ |------|-----------|---------------|
190
+ | `blocks` | from must complete before to can start | Yes |
191
+ | `implements` | task implements context | No |
192
+ | `references` | general reference | No |
193
+ | `related` | loose association | No |
194
+ | `child-of` | hierarchical containment | No |
195
+ | `parent-of` | inverse of child-of | No |
196
+ | `depends-on` | soft dependency (informational, not used by `ready`) | No |
197
+ | `discovered-from` | found while working on | No |
198
+ | `duplicates` | from is duplicate of to | No |
199
+ | `supersedes` | from replaces to | No |
200
+
201
+ Edge types are extensible via string.
202
+
203
+ ## URI Conventions
204
+
205
+ Nodes across systems are identified by URIs:
206
+
207
+ ```
208
+ native://c-a2b3 # OpenTasks native node
209
+ beads://./bd-x7k9 # Beads issue
210
+ taskmaster://./auth-prd # Taskmaster spec
211
+ claude://current/t-abc # Claude task
212
+ slack://C04ABCD/p1234567890 # Slack message (custom)
213
+ github://owner/repo/pull/42 # GitHub PR (custom)
214
+ ```
215
+
216
+ The `uri` field on ExternalNodes is freeform. Use consistent schemes for deduplication.
217
+
218
+ ## Specialized Workflows
219
+
220
+ **Linking external data** (Slack messages, docs, URLs): See [linking-external-data.md](linking-external-data.md)
221
+
222
+ **Spec to implementation** (create spec, break into issues, track to completion): See [spec-to-implementation.md](spec-to-implementation.md)
223
+
224
+ **Feedback and review** (cross-system feedback, suggestion lifecycle): See [feedback-and-review.md](feedback-and-review.md)
225
+
226
+ **Dependency management** (blockers, ready queries, work loops): See [dependency-management.md](dependency-management.md)
@@ -0,0 +1,119 @@
1
+ # Dependency Management
2
+
3
+ Set up dependency chains, query what's blocked and ready, manage work ordering.
4
+
5
+ ## blocks vs depends-on
6
+
7
+ | Edge | Used by `ready` query | Cycle-checked | Use when |
8
+ |------|----------------------|---------------|----------|
9
+ | `blocks` | Yes | Yes | Work genuinely can't start until blocker closes |
10
+ | `depends-on` | No | No | "Nice to have first" but not strictly required |
11
+
12
+ ## Setting Up Dependencies
13
+
14
+ ### Linear chain: A → B → C → D
15
+
16
+ ```bash
17
+ opentasks link --from t-aaa --to t-bbb --type blocks
18
+ opentasks link --from t-bbb --to t-ccc --type blocks
19
+ opentasks link --from t-ccc --to t-ddd --type blocks
20
+ ```
21
+
22
+ ### Diamond: A blocks B+C, both block D
23
+
24
+ ```bash
25
+ opentasks link --from t-aaa --to t-bbb --type blocks
26
+ opentasks link --from t-aaa --to t-ccc --type blocks
27
+ opentasks link --from t-bbb --to t-ddd --type blocks
28
+ opentasks link --from t-ccc --to t-ddd --type blocks
29
+ ```
30
+
31
+ B and C can run in parallel once A closes. D waits for both.
32
+
33
+ ### Cycle detection
34
+
35
+ Creating a `blocks` edge that would form a cycle returns an error:
36
+
37
+ ```bash
38
+ # Given: A blocks B, B blocks C
39
+ opentasks link --from t-ccc --to t-aaa --type blocks
40
+ # → { success: false, error: "Would create circular dependency" }
41
+ ```
42
+
43
+ ### Removing dependencies
44
+
45
+ ```bash
46
+ opentasks link --from t-aaa --to t-bbb --type blocks --remove
47
+ ```
48
+
49
+ ## Querying
50
+
51
+ ### What blocks a node?
52
+
53
+ ```bash
54
+ # Direct blockers
55
+ opentasks query '{"blockers": {"nodeId": "t-ddd"}}'
56
+
57
+ # Full chain (transitive)
58
+ opentasks query '{"blockers": {"nodeId": "t-ddd", "transitive": true}}'
59
+
60
+ # Only active (non-closed, non-archived)
61
+ opentasks query '{"blockers": {"nodeId": "t-ddd", "activeOnly": true}}'
62
+ ```
63
+
64
+ ### What does a node block?
65
+
66
+ ```bash
67
+ opentasks query '{"blocking": {"nodeId": "t-aaa", "transitive": true}}'
68
+ ```
69
+
70
+ ### What's ready to work on?
71
+
72
+ Returns open tasks with zero active blockers.
73
+
74
+ ```bash
75
+ # All ready work
76
+ opentasks query '{"ready": {}}'
77
+
78
+ # Filtered
79
+ opentasks query '{"ready": {"tags": ["auth"], "priority": {"min": 0, "max": 2}, "limit": 5}}'
80
+ ```
81
+
82
+ ## Agent Work Loop
83
+
84
+ ```
85
+ loop:
86
+ 1. opentasks query '{"ready": {"limit": 1}}' → pick highest-priority unblocked issue
87
+ 2. If empty, stop.
88
+ 3. opentasks update t-x7k9 --status in_progress
89
+ 4. Do the work.
90
+ 5. opentasks update t-x7k9 --status closed
91
+ 6. opentasks query '{"blocking": {"nodeId": "t-x7k9"}}' → see what's now unblocked
92
+ 7. Repeat.
93
+ ```
94
+
95
+ ## Cross-System Dependencies
96
+
97
+ `blocks` edges work across systems. The `ready` query evaluates them uniformly.
98
+
99
+ ```bash
100
+ opentasks link --from "beads://./bd-setup" --to t-x7k9 --type blocks
101
+ opentasks link --from t-x7k9 --to "claude://current/t-abc" --type blocks
102
+ ```
103
+
104
+ ## Discovering Work During Implementation
105
+
106
+ ```bash
107
+ # Create the discovered task
108
+ opentasks create --type task --title "Token refresh fails for expired sessions" --status open --tags auth,bug --priority 1
109
+ # → t-new1
110
+
111
+ # Link to where it was discovered
112
+ opentasks link --from t-new1 --to t-x7k9 --type discovered-from
113
+
114
+ # If it blocks current work:
115
+ opentasks link --from t-new1 --to t-x7k9 --type blocks
116
+
117
+ # Update original to blocked
118
+ opentasks update t-x7k9 --status blocked
119
+ ```
@@ -0,0 +1,100 @@
1
+ # Feedback and Review
2
+
3
+ Leave feedback on context and tasks, manage suggestion lifecycles, query unresolved items.
4
+
5
+ ## Feedback Types
6
+
7
+ | Type | Use For |
8
+ |------|---------|
9
+ | `comment` | Status updates, implementation notes, observations |
10
+ | `suggestion` | Proposed changes to target content |
11
+ | `request` | Action needed — blocking questions, approvals |
12
+
13
+ ## Creating Feedback
14
+
15
+ ### Basic comment
16
+
17
+ ```bash
18
+ opentasks annotate '{"targetId":"c-a2b3","create":{"content":"Implemented OAuth. Deferred SAML to follow-up.","type":"comment"}}'
19
+ ```
20
+
21
+ ### Implementation feedback (linked to source issue)
22
+
23
+ ```bash
24
+ opentasks annotate '{"targetId":"c-a2b3","fromId":"t-x7k9","create":{"content":"Google OAuth requires access_type=offline for refresh tokens — added to config.","type":"comment"}}'
25
+ ```
26
+
27
+ `fromId` creates a link from the task to the feedback for traceability.
28
+
29
+ ### Anchored suggestion
30
+
31
+ ```bash
32
+ opentasks annotate '{"targetId":"c-a2b3","create":{"content":"Rate limiting needed here — OAuth endpoints are brute-force targets.","type":"suggestion","anchor":{"line":15,"text":"OAuth2 endpoints"}}}'
33
+ ```
34
+
35
+ Anchors use `line` (exact), `text` (fuzzy match), or both. Text anchors survive content edits better.
36
+
37
+ ### Blocking request
38
+
39
+ ```bash
40
+ opentasks annotate '{"targetId":"c-a2b3","create":{"content":"Which GitHub OAuth scopes? Spec says user profile but integration may need repo access.","type":"request"}}'
41
+ ```
42
+
43
+ ## Querying Feedback
44
+
45
+ ```bash
46
+ # All feedback on a node
47
+ opentasks query '{"feedback": {"nodeId": "c-a2b3"}}'
48
+
49
+ # Unresolved suggestions only
50
+ opentasks query '{"feedback": {"nodeId": "c-a2b3", "type": "suggestion", "resolved": false}}'
51
+
52
+ # All unresolved feedback globally
53
+ opentasks query '{"unresolvedFeedback": {}}'
54
+
55
+ # Unresolved feedback for a specific target
56
+ opentasks query '{"unresolvedFeedback": {"targetId": "c-a2b3"}}'
57
+ ```
58
+
59
+ ## Lifecycle Management
60
+
61
+ ```bash
62
+ # Resolve (addressed)
63
+ opentasks annotate '{"targetId":"c-a2b3","resolve":"f-t1u2"}'
64
+
65
+ # Dismiss (not applicable)
66
+ opentasks annotate '{"targetId":"c-a2b3","dismiss":"f-t1u2"}'
67
+
68
+ # Reopen
69
+ opentasks annotate '{"targetId":"c-a2b3","reopen":"f-t1u2"}'
70
+ ```
71
+
72
+ ## Review Workflow
73
+
74
+ ```bash
75
+ # 1. Read spec
76
+ opentasks get c-a2b3
77
+
78
+ # 2. Check existing feedback
79
+ opentasks query '{"feedback": {"nodeId": "c-a2b3"}}'
80
+
81
+ # 3. Leave feedback
82
+ opentasks annotate '{"targetId":"c-a2b3","create":{"content":"...","type":"comment"}}'
83
+
84
+ # 4. Before implementing — check unresolved
85
+ opentasks query '{"feedback": {"nodeId": "c-a2b3", "resolved": false}}'
86
+
87
+ # 5. After addressing — resolve
88
+ opentasks annotate '{"targetId":"c-a2b3","resolve":"f-abc1"}'
89
+ ```
90
+
91
+ ## Cross-System Feedback
92
+
93
+ When source and target are in different systems, OpenTasks stores the feedback (native systems can't handle cross-refs).
94
+
95
+ ```bash
96
+ # Beads issue commenting on Taskmaster spec
97
+ opentasks annotate '{"targetId":"taskmaster://./auth-prd","fromId":"beads://./bd-x7k9","create":{"content":"Sections 1-3 done. Section 4 descoped.","type":"comment"}}'
98
+ ```
99
+
100
+ Same-system feedback routes to native comments when the provider supports them.
@@ -0,0 +1,103 @@
1
+ # Linking External Data
2
+
3
+ Bind non-task artifacts — Slack messages, Google Docs, Notion pages, emails, URLs — to context and tasks in the graph.
4
+
5
+ ## Pattern
6
+
7
+ Two steps: create an ExternalNode, then link it.
8
+
9
+ ### 1. Create the ExternalNode
10
+
11
+ ```bash
12
+ opentasks create --type external \
13
+ --title "Alex: SSO redirect loop after IdP response" \
14
+ --uri "slack://C04ABCD/p1234567890" \
15
+ --source slack \
16
+ --metadata '{"channel_name":"#engineering","permalink":"https://workspace.slack.com/archives/C04ABCD/p1234567890","author":"alex","text":"auth flow is broken for SSO users — getting redirect loop after IdP response"}'
17
+ # → { id: "e-k7m2", ... }
18
+ ```
19
+
20
+ ### 2. Link to the relevant node
21
+
22
+ ```bash
23
+ opentasks link --from t-x7k9 --to e-k7m2 --type references \
24
+ --metadata '{"context":"Original bug report from #engineering"}'
25
+ ```
26
+
27
+ ## URI Conventions
28
+
29
+ The `uri` field is freeform. Consistent schemes enable deduplication.
30
+
31
+ | Source | Format | Example |
32
+ |--------|--------|---------|
33
+ | Slack message | `slack://[channel]/p[ts]` | `slack://C04ABCD/p1234567890` |
34
+ | Slack thread | `slack://[channel]/t[thread_ts]` | `slack://C04ABCD/t1234567880` |
35
+ | Google Doc | `gdoc://[doc-id]` | `gdoc://1BxiMVs0XRA5nF...` |
36
+ | Notion page | `notion://[page-id]` | `notion://a1b2c3d4-e5f6-...` |
37
+ | Figma file | `figma://[file-key]` | `figma://abc123DEF456` |
38
+ | GitHub PR | `github://[owner]/[repo]/pull/[num]` | `github://org/repo/pull/42` |
39
+ | Generic URL | `web://[url]` | `web://example.com/page` |
40
+
41
+ ## Edge Type Selection
42
+
43
+ | Situation | Edge Type |
44
+ |-----------|-----------|
45
+ | Bug report, source document | `references` |
46
+ | Found during investigation | `discovered-from` |
47
+ | Loosely related context | `related` |
48
+
49
+ Direction: typically `issue → external` or `spec → external`.
50
+
51
+ ## Deduplication
52
+
53
+ Check before creating:
54
+
55
+ ```bash
56
+ opentasks query '{"nodes": {"type": "external", "search": "slack://C04ABCD/p1234567890"}}'
57
+ ```
58
+
59
+ If a node with that URI exists, skip creation and link to the existing node.
60
+
61
+ ## Phantom Nodes (URL only)
62
+
63
+ If the agent only has a URL and can't fetch content:
64
+
65
+ ```bash
66
+ opentasks create --type external \
67
+ --title "Related Slack thread" \
68
+ --uri "slack://C04ABCD/t1234567880" \
69
+ --source slack \
70
+ --metadata '{"permalink":"https://workspace.slack.com/archives/C04ABCD/p1234567880"}'
71
+ ```
72
+
73
+ An agent with access to the external system can later enrich via `opentasks update`.
74
+
75
+ ## Querying Linked Data
76
+
77
+ ```bash
78
+ # All references from a task
79
+ opentasks query '{"edges": {"from_id": "t-x7k9", "type": "references"}}'
80
+
81
+ # All external nodes from Slack
82
+ opentasks query '{"nodes": {"type": "external", "search": "slack"}}'
83
+ ```
84
+
85
+ ## Complete Example
86
+
87
+ ```
88
+ Agent working on "Fix SSO redirect loop":
89
+
90
+ 1. Search Slack via MCP → find 3 relevant messages
91
+
92
+ 2. For each, create ExternalNode:
93
+ opentasks create --type external --title "..." --uri "slack://..." --source slack --metadata '{...}'
94
+
95
+ 3. Link each to the task:
96
+ opentasks link --from t-x7k9 --to e-k7m2 --type references
97
+ opentasks link --from t-x7k9 --to e-k7m3 --type references
98
+ opentasks link --from t-x7k9 --to e-k7m4 --type discovered-from
99
+
100
+ 4. Later, another agent queries context:
101
+ opentasks query '{"edges": {"from_id": "t-x7k9", "type": ["references", "discovered-from"]}}'
102
+ → Gets back ExternalNodes with Slack content in metadata
103
+ ```