OpenCode's registry calls z.object(def.args) on every plugin tool definition,
so Zod is mandatory for the tool schema — no JSON Schema escape hatch. TypeBox
is used for our own config validation where we control the schema. The two
serve different layers with different constraints. Updated both the overview
and ADR-001 with a clear table showing which library serves which concern.
- Handler signature: PluginInput is captured at init time via closure,
not passed to execute handlers. ToolContext is the per-invocation
context. This matches how open-memory actually works.
- Added @alkdev/typebox as explicit direct dependency (was transitive)
- Fixed TypeBox import path: Value comes from @alkdev/typebox/value
- Clarified cost operation args: bundled into WorkflowCostOptions object
- Added Zod/TypeBox distinction note in tool definition section
- Added todowrite to relationship table
- Resolved open question about show including full body
The built-in OpenCode 'task' tool spawns subagents for work delegation.
Naming our plugin 'tasks' would create confusion with two 'task' tools
that do completely different things. 'taskgraph' matches the core
library, clearly differentiates from the built-in, and describes what
the tool actually does.
The dispatch field is renamed from 'tool' to 'op' (operation) to
avoid collision with OpenCode's 'tool' terminology and match the
Rust CLI's subcommand pattern.
ADR-001 rewritten for taskgraph/op naming and Zod/TypeBox distinction.
ADR-007 added documenting the naming decision and the three 'task'
concepts (task, todowrite, taskgraph).
Research reports added:
- docs/research/opencode-task-tool-deep-dive.md
- docs/research/open-coordinator-deep-dive.md
Also: fixed SDD process link, resolved open question about 'show'
including full body, added todowrite to relationship table, clarified
Zod vs TypeBox roles, changed FileSource to async scan.
Config is now a discriminated union on source.type:
- FileSource: { type: 'file', tasksPath?: string }
- ApiSource (future): { type: 'api', url: string }
- No config → default FileSource('tasks'), silent if missing
OpenCode passes plugin options as raw Record<string, unknown> with
no validation — the plugin validates with TypeBox at startup. This
means no extra config files, everything in opencode.json.
Updated plugin entry code to show resolveConfig with TypeBox Check/
Cast, type-appropriate error handling, and source factory integration.
Architecture updates to support the plugin's I/O and configuration layer:
- TaskSource interface abstracts task loading from I/O, making future
sources (API, database, test) swappable without operation changes
- FileSource implements v1: Bun.Glob for directory scanning, Bun.file
for reading, parseFrontmatter for parsing (single-pass I/O)
- SourceResult provides raw file content (for show) and per-file error
detail (for validate) that parseTaskDirectory couldn't offer
- Config schema uses TypeBox (already a dep via taskgraph) for
compile-time types, runtime validation, and JSON Schema export
- ADR-005: TaskSource abstraction rationale
- ADR-006: Bun.Glob over parseTaskDirectory rationale
- Performance benchmark added (43 tasks full pipeline: ~150ms)
- AGENTS.md updated with config section and source structure
Architecture docs for the open-tasks plugin covering the registry pattern
dispatch design, operation set, error handling, data flow, and constraints.
Includes four ADRs (registry pattern, no-cache policy, risk operation merge,
frontmatter normalization). The depends_on/dependsOn compatibility issue in
@alkdev/taskgraph is resolved in v0.0.2, so the dependency is bumped and
the docs reflect the fix.
AGENTS.md updated: canonical dependsOn field, dependents operation added,
hooks clarification, field naming note.