Files
open-tasks/AGENTS.md
glm-5.1 9342dab70c Rename tool to taskgraph, use op dispatch field, add research reports
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.
2026-04-28 11:30:20 +00:00

8.0 KiB

AGENTS.md

Project

@alkdev/open-tasks — an OpenCode plugin that gives agents structured task management with graph analysis, decomposition guidance, and workflow cost estimation. Exposes a single taskgraph tool using a registry pattern (like open-memory and open-coordinator) to keep the agent's visible tool count minimal.

Part of the alk.dev trio:

  • open-memory (memory / memory_compact): session introspection, context awareness, history browsing
  • open-coordinator (worktree): git worktree orchestration, session spawning, anomaly detection
  • open-tasks (taskgraph): task graph analysis, dependency insight, decomposition guidance

Repository

  • Git: git@git.alk.dev:alkdev/open-tasks.git
  • License: MIT OR Apache-2.0
  • Runtime: Bun
  • Language: TypeScript (strict, ESM, verbatimModuleSyntax)
  • Linter: Biome (bun run lint, bun run format)
  • Build: bun run builddist/ (bun build + tsc declarations)

Commands

bun run build        # bun build src/index.ts + tsc --emitDeclarationOnly
bun run typecheck    # tsc --noEmit
bun run lint         # biome check .
bun run format       # biome format --write .
bun run test         # bun test

Always run bun run typecheck and bun run lint after changes.

Architecture

Core Dependency: @alkdev/taskgraph

The graph operations, risk scoring, frontmatter parsing, and analysis functions come from @alkdev/taskgraph — a pure TypeScript library built on graphology. This plugin wraps that library in an OpenCode tool interface.

Key imports from @alkdev/taskgraph:

  • TaskGraph — primary graph data structure (construction, queries, mutation, export)
  • parseFrontmatter, serializeFrontmatter — YAML frontmatter I/O (we use parseFrontmatter directly; directory scanning uses Bun.Glob per ADR-006)
  • criticalPath, weightedCriticalPath, parallelGroups, bottlenecks — analysis functions
  • riskPath, riskDistribution, calculateTaskEv, workflowCost — risk & cost analysis
  • shouldDecomposeTask — decomposition guidance
  • Categorical types: TaskScope, TaskRisk, TaskImpact, TaskLevel, TaskPriority, TaskStatus

Plugin Design: Registry Pattern

Like open-memory, this plugin exposes one tool (taskgraph) with internal operation dispatch. This keeps the agent's visible tool count low.

taskgraph({op: "help"})                         → Show available operations
taskgraph({op: "list"})                         → List tasks in project
taskgraph({op: "show", args: {id: "..."}})      → Show task details
taskgraph({op: "deps", args: {id: "..."}})      → Show task prerequisites
taskgraph({op: "dependents", args: {id: "..."}}) → Show tasks that depend on a task
taskgraph({op: "validate"})                      → Validate all task files
... etc

The dispatch field is op (operation) rather than tool — this avoids confusion with OpenCode's "tool" concept and matches the Rust CLI's subcommand pattern (taskgraph parallel, taskgraph critical).

Source Structure

src/
├── index.ts              # Plugin entry: config resolution + tool registration
├── tools.ts              # Tool definitions (taskgraph router)
├── registry.ts           # Operation registry pattern (dispatch by tool name)
├── config.ts             # Plugin config schema (TypeBox, validated)
├── sources/
│   ├── types.ts          # TaskSource interface, SourceResult, SourceError
│   ├── file-source.ts    # FileSource — reads tasks/ via Bun.Glob + parseFrontmatter
│   └── index.ts          # Source factory: resolves config → TaskSource
├── operations/            # Individual operation implementations
│   ├── help.ts
│   ├── list.ts
│   ├── show.ts
│   ├── deps.ts
│   ├── dependents.ts
│   ├── validate.ts
│   ├── topo.ts
│   ├── cycles.ts
│   ├── critical.ts
│   ├── parallel.ts
│   ├── bottleneck.ts
│   ├── risk.ts
│   ├── cost.ts
│   └── decompose.ts
└── formatting.ts          # Output formatting helpers

Plugin Hooks

Hook Purpose
None initial — future: task status injection into system prompt, worktree-aware task context

The taskgraph Tool

Operations map to @alkdev/taskgraph functions, reading tasks from a TaskSource (v1: FileSource via Bun.Glob + parseFrontmatter) and returning formatted output.

Plugin Config

Optional config via opencode.json. OpenCode passes the raw options object to the plugin — the plugin validates with TypeBox at startup.

// No config = default FileSource("tasks"), silent if directory missing
{
  "plugin": ["@alkdev/open-tasks"]
}

// Explicit file source with custom path
{
  "plugin": [
    ["@alkdev/open-tasks", {
      "source": { "type": "file", "tasksPath": "docs/tasks" }
    }]
  ]
}

// Future: API source (secrets via env vars, not config)
// {
//   "plugin": [
//     ["@alkdev/open-tasks", {
//       "source": { "type": "api", "url": "https://api.example.com/tasks" }
//     }]
//   ]
// }

The source.type field is a discriminated union — each source type has its own config shape. Defaults to { type: "file", tasksPath: "tasks" } if no config is provided. Secrets (API keys) come from environment variables, not config files.

Local Development & Testing

OpenCode installs plugins from npm into ~/.cache/opencode/node_modules/. When doing local development, symlink your local repo:

Setup (one-time)

rm -rf ~/.cache/opencode/node_modules/@alkdev/open-tasks
ln -s /workspace/@alkdev/open-tasks ~/.cache/opencode/node_modules/@alkdev/open-tasks

Iteration loop

bun run build          # rebuild dist/index.js
bun run typecheck      # verify types
bun run lint           # verify style
bun run test           # run tests

After rebuilding, restart OpenCode to pick up the new build.

Also clear Bun's global cache

rm -rf ~/.bun/install/cache/@alkdev/open-tasks*

Key Conventions

  • No comments unless requested
  • ESM with .js extension in imports
  • Strict TypeScript with verbatimModuleSyntax
  • Biome for linting and formatting
  • Task files are the source of truth (markdown with YAML frontmatter)
  • Single tool with registry dispatch — minimize agent context bloat
  • Include a help operation for discoverability

Relationship to Other Plugins

  • open-memory (memory, memory_compact): session history, context awareness — complementary
  • open-coordinator (worktree): worktree orchestration — tasks drive what worktrees implement
  • taskgraph CLI (taskgraph): Rust CLI for the same operations — this plugin is the TypeScript/OpenCode equivalent
  • @alkdev/taskgraph (npm): Core library this plugin wraps — all graph operations come from here

Task File Format

Tasks are markdown files in tasks/ with YAML frontmatter:

---
id: auth-setup
name: Setup Authentication
status: pending
dependsOn: []
scope: moderate
risk: medium
impact: component
level: implementation
---

## Description

Implement OAuth2 authentication with provider abstraction.

## Acceptance Criteria

- [ ] OAuth2 flow works with Google provider
- [ ] Tokens stored securely

## Notes

> Agent fills this during implementation.

## Summary

> Agent fills this on completion.

Note on field naming: The @alkdev/taskgraph library uses camelCase (dependsOn, scope, risk, etc.) in its schema. The Rust CLI historically used snake_case (depends_on). As of @alkdev/taskgraph v0.0.2, the parser accepts both forms — but camelCase is the canonical form for new files.

Build & Test Commands

bun run build          # bun build src/index.ts + tsc declarations
bun run typecheck      # tsc --noEmit
bun run lint           # biome check .
bun run format         # biome format --write .
bun run test           # bun test

License

Dual-licensed under MIT OR Apache-2.0. Both license files must be present at repository root.