diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 65e70e7..edd23f9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,6 +1,6 @@ name: Publish & Release -# Publishes taskflow-core + taskflow-mcp + taskflow-hosts + pi-taskflow + codex-taskflow + +# Publishes taskflow-core + taskflow-mcp-core + taskflow-hosts + pi-taskflow + codex-taskflow + # claude-taskflow + opencode-taskflow to npmjs.com and creates a GitHub Release, when a v* tag is # pushed (e.g. `git tag v0.1.0 && git push origin v0.1.0`). All seven workspace # versions must equal the tag. @@ -46,7 +46,7 @@ jobs: echo "::error::Tag $TAG does not match root version $EXPECT" exit 1 fi - for pkg in taskflow-core taskflow-mcp taskflow-hosts pi-taskflow codex-taskflow claude-taskflow opencode-taskflow; do + for pkg in taskflow-core taskflow-mcp-core taskflow-hosts pi-taskflow codex-taskflow claude-taskflow opencode-taskflow; do V="v$(node -p "require('./packages/$pkg/package.json').version")" if [ "$V" != "$TAG" ]; then echo "::error::Tag $TAG does not match $pkg version $V" @@ -103,7 +103,7 @@ jobs: fi } publish_one taskflow-core - publish_one taskflow-mcp + publish_one taskflow-mcp-core publish_one taskflow-hosts publish_one pi-taskflow publish_one codex-taskflow @@ -129,7 +129,7 @@ jobs: } } catch {} const text = body.join('\n').trim(); - fs.writeFileSync('/tmp/release-notes.md', text || ('Release ' + process.argv[1] + ' \u2014 taskflow-core, taskflow-mcp, taskflow-hosts, pi-taskflow, codex-taskflow, claude-taskflow, opencode-taskflow.')); + fs.writeFileSync('/tmp/release-notes.md', text || ('Release ' + process.argv[1] + ' \u2014 taskflow-core, taskflow-mcp-core, taskflow-hosts, pi-taskflow, codex-taskflow, claude-taskflow, opencode-taskflow.')); " "$VERSION" gh release create "$GITHUB_REF_NAME" \ --notes-file /tmp/release-notes.md \ diff --git a/AGENTS.md b/AGENTS.md index f4b1b41..d3979f6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,8 +8,8 @@ taskflow is a **declarative DAG orchestration runtime** for coding agents — it **Language:** TypeScript (ES2022, ESM, `--experimental-strip-types` for direct execution in dev)\ **Runtime:** Node.js ≥ 22.19 (uses `fs.globSync`, `Atomics.wait`)\ -**Dependencies:** Zero runtime deps. The Pi adapter (`pi-taskflow`) peer-depends on `@earendil-works/pi-{agent-core,ai,coding-agent,tui}`; the host-neutral MCP server (`taskflow-mcp`) and the three MCP host adapters (`codex-taskflow`, `claude-taskflow`, `opencode-taskflow`) all depend on `taskflow-core` (the adapters also depend on `taskflow-mcp`). Everything depends on `typebox`.\ -**Layout:** pnpm-workspace monorepo of seven published packages — `taskflow-core` (host-neutral engine), `taskflow-mcp` (the host-neutral MCP server + DAG renderer, depends on core), `taskflow-hosts` (shared host-runner collection: the codex/claude/opencode SubagentRunner impls + argv builders + event-stream parsers, depends on core), `pi-taskflow` (Pi extension adapter, installed via `pi install npm:pi-taskflow`), `codex-taskflow` (Codex MCP server + bin + a `plugin/` scaffold installable via `codex plugin add`; re-exports the runner from `taskflow-hosts`), `claude-taskflow` (Claude Code MCP server + bin + a `plugin/` scaffold installable via `claude plugin install`; re-exports the runner from `taskflow-hosts`), and `opencode-taskflow` (OpenCode MCP server + bin + an `opencode.json` config scaffold; re-exports the runner from `taskflow-hosts`).\ +**Dependencies:** Zero runtime deps. The Pi adapter (`pi-taskflow`) peer-depends on `@earendil-works/pi-{agent-core,ai,coding-agent,tui}`; the host-neutral MCP server (`taskflow-mcp-core`) and the three MCP host adapters (`codex-taskflow`, `claude-taskflow`, `opencode-taskflow`) all depend on `taskflow-core` (the adapters also depend on `taskflow-mcp-core`). Everything depends on `typebox`.\ +**Layout:** pnpm-workspace monorepo of seven published packages — `taskflow-core` (host-neutral engine), `taskflow-mcp-core` (the host-neutral MCP server + DAG renderer, depends on core), `taskflow-hosts` (shared host-runner collection: the codex/claude/opencode SubagentRunner impls + argv builders + event-stream parsers, depends on core), `pi-taskflow` (Pi extension adapter, installed via `pi install npm:pi-taskflow`), `codex-taskflow` (Codex MCP server + bin + a `plugin/` scaffold installable via `codex plugin add`; re-exports the runner from `taskflow-hosts`), `claude-taskflow` (Claude Code MCP server + bin + a `plugin/` scaffold installable via `claude plugin install`; re-exports the runner from `taskflow-hosts`), and `opencode-taskflow` (OpenCode MCP server + bin + an `opencode.json` config scaffold; re-exports the runner from `taskflow-hosts`).\ **Build:** each package compiles to `dist/*.js` + `.d.ts` (`tsc`); published packages ship `dist` (Node refuses to type-strip `.ts` under `node_modules`). Dev resolves the TypeScript sources directly via a `development` export condition — no build needed to typecheck or test. ## Architecture @@ -39,7 +39,7 @@ packages/ │ │ ├─ typebox-helpers.ts / frontmatter.ts / paths.ts ← vendored pi-SDK helpers (zero-dep) │ │ └─ agents/ ← 18 built-in agent definitions (*.md with YAML frontmatter; copied to dist) │ └─ test/ ← engine unit tests -├─ taskflow-mcp/ ← host-neutral MCP server (depends on taskflow-core) +├─ taskflow-mcp-core/ ← host-neutral MCP server (depends on taskflow-core) │ ├─ src/mcp/ ← jsonrpc.ts (stdio JSON-RPC), server.ts (taskflow_* tools; parameterized by │ │ a SubagentRunner), svg.ts (DAG SVG/outline renderer) │ └─ test/ ← (covered by the host adapters' MCP tests) @@ -59,7 +59,7 @@ packages/ │ │ └─ init.ts ← /tf init command: scaffolds a taskflow / model roles interactively │ ├─ test/ ← pi-adapter unit tests + .mts e2e scripts │ └─ skills/ ← GENERATED per-host skill files (do not edit; see skills-src/) -└─ codex-taskflow/ ← Codex DELIVERY package (depends on taskflow-hosts + taskflow-mcp) +└─ codex-taskflow/ ← Codex DELIVERY package (depends on taskflow-hosts + taskflow-mcp-core) ├─ src/ │ ├─ index.ts ← re-exports the codex runner from taskflow-hosts (back-compat public surface) │ └─ mcp/ ← thin bind: server.ts re-exports core's MCP server bound to codexSubagentRunner; bin.ts @@ -69,7 +69,7 @@ packages/ │ ├─ skills/taskflow/ ← GENERATED per-host skill files (do not edit; see skills-src/) │ └─ assets/ ← plugin icons (taskflow.svg, taskflow-small.svg) └─ test/ ← mcp-server unit test + .mts e2e scripts -└─ claude-taskflow/ ← Claude Code DELIVERY package (depends on taskflow-hosts + taskflow-mcp) +└─ claude-taskflow/ ← Claude Code DELIVERY package (depends on taskflow-hosts + taskflow-mcp-core) ├─ src/ │ ├─ index.ts ← re-exports the claude runner from taskflow-hosts (back-compat public surface) │ └─ mcp/ ← thin bind: server.ts re-exports core's MCP server bound to claudeSubagentRunner; bin.ts @@ -79,7 +79,7 @@ packages/ │ ├─ skills/taskflow/ ← GENERATED per-host skill files (do not edit; see skills-src/) │ └─ assets/ ← plugin icons (taskflow.svg, taskflow-small.svg) └─ test/ ← mcp-server unit test + .mts e2e scripts -└─ opencode-taskflow/ ← OpenCode DELIVERY package (depends on taskflow-hosts + taskflow-mcp) +└─ opencode-taskflow/ ← OpenCode DELIVERY package (depends on taskflow-hosts + taskflow-mcp-core) ├─ src/ │ ├─ index.ts ← re-exports the opencode runner from taskflow-hosts (back-compat public surface) │ └─ mcp/ ← thin bind: server.ts re-exports core's MCP server bound to opencodeSubagentRunner; bin.ts @@ -211,7 +211,7 @@ pnpm run test:e2e-opencode-mcp # opencode MCP stdio e2e (src; no live opencod ### File Structure Rules - **Source**: `.ts` source lives in `packages//src/`. Host-neutral logic goes in `taskflow-core`; host **runner** code (the `SubagentRunner` impl, argv builder, event-stream parser for codex/claude/opencode) goes in `taskflow-hosts`; host **delivery** code (the MCP server/bin + plugin scaffold) goes in the `codex-taskflow` / `claude-taskflow` / `opencode-taskflow` packages; the pi adapter (which peer-depends the pi SDK) stays in `pi-taskflow`. `taskflow-core` must never import a host SDK (`@earendil-works/*`). -- **Imports**: adapters import the engine via the bare specifier `taskflow-core` (never a relative path into `../taskflow-core/src`). The MCP server lives in the separate `taskflow-mcp` package — host adapters import it via `taskflow-mcp/server` / `taskflow-mcp/jsonrpc`. `detached-runner.ts` is spawn-only — reference it by `taskflow-core/detached-runner.js`, never via the barrel. `runSubagentProcess` (in `runner-core.ts`, re-exported from the `taskflow-core` barrel) is the shared spawn+classify helper every host runner delegates to. +- **Imports**: adapters import the engine via the bare specifier `taskflow-core` (never a relative path into `../taskflow-core/src`). The MCP server lives in the separate `taskflow-mcp-core` package — host adapters import it via `taskflow-mcp-core/server` / `taskflow-mcp-core/jsonrpc`. `detached-runner.ts` is spawn-only — reference it by `taskflow-core/detached-runner.js`, never via the barrel. `runSubagentProcess` (in `runner-core.ts`, re-exported from the `taskflow-core` barrel) is the shared spawn+classify helper every host runner delegates to. - **Tests**: `.test.ts` in the owning package's `test/`. Named `.test.ts` or `.test.ts`. - **Agents**: built-in agent `.md` files in `packages/taskflow-core/src/agents/` (copied to `dist/agents` at build). - **Examples**: flow definitions as `.json` in `examples/`. @@ -264,7 +264,7 @@ All engine files live in `packages/taskflow-core/src/`; the pi entry lives in `p | `runtime.ts` | Core orchestration: `executeTaskflow()`, `executePhase()`, all 10 phase types | | `schema.ts` | DSL types, validation, desugar, topo sort, cycle detection | | `runner-core.ts` | Host-neutral runner helpers: failure classification, NDJSON accumulator, error sanitization, `mapWithConcurrencyLimit`, AND `runSubagentProcess` (the shared spawn/idle/abort/classify block every host runner delegates to) + `unknownAgentResult` | -| `taskflow-mcp/src/mcp/server.ts` | Host-neutral MCP server: the `taskflow_*` tool schemas + handlers, parameterized by a `SubagentRunner` (codex/claude/opencode adapters bind their runner + a thin bin) | +| `taskflow-mcp-core/src/mcp/server.ts` | Host-neutral MCP server: the `taskflow_*` tool schemas + handlers, parameterized by a `SubagentRunner` (codex/claude/opencode adapters bind their runner + a thin bin) | | `pi-taskflow/src/runner.ts` | Pi subagent spawn (`pi --mode json`), idle watchdog; re-exports the core helpers | | `taskflow-hosts/src/codex-runner.ts` | Codex subagent spawn (`codex exec --json`); `codexSubagentRunner` + `buildCodexArgs` | | `taskflow-hosts/src/claude-runner.ts` | Claude Code subagent spawn (`claude -p --output-format stream-json`); `claudeSubagentRunner` + `buildClaudeArgs` + permission mapping | diff --git a/CHANGELOG.md b/CHANGELOG.md index 917cf7e..dfd7d8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,13 @@ All notable changes to taskflow are documented here. This project follows [Keep ## [0.1.6] — 2026-07-06 ### Changed -- **Extracted the MCP server into its own `taskflow-mcp` package** (sixth +- **Extracted the MCP server into its own `taskflow-mcp-core` package** (sixth package). The stdio JSON-RPC server + `taskflow_*` tool handlers + DAG - SVG/outline renderer moved out of `taskflow-core` into `taskflow-mcp`, so + SVG/outline renderer moved out of `taskflow-core` into `taskflow-mcp-core`, so core is again purely the portable engine (DSL/runtime/cache/verify) and the MCP presentation layer is an independently-publishable unit. The host - adapters (codex/claude/opencode) now depend on `taskflow-mcp` and import it - via `taskflow-mcp/server` / `taskflow-mcp/jsonrpc`. `pi-taskflow` is + adapters (codex/claude/opencode) now depend on `taskflow-mcp-core` and import it + via `taskflow-mcp-core/server` / `taskflow-mcp-core/jsonrpc`. `pi-taskflow` is unaffected (it never used the MCP server). - **De-duplicated the three host runners.** The codex/claude/opencode runners each copy-pasted ~82 lines of identical process-handling boilerplate @@ -22,9 +22,17 @@ All notable changes to taskflow are documented here. This project follows [Keep parameterized by a per-host `SubagentAccumulator` + `foldLine`. Each host runner shrank to just its host-specific bits (argv, model-id rule, permission mapping, event parser): codex 366→217, claude 417→266, opencode - 397→247 lines. Behavior is identical (1092/1092 tests pass); adding a new + 397→247 lines. Behavior is identical (1140/1140 tests pass); adding a new host can no longer drift the process/classify contract. +- **Renamed the MCP server package from `taskflow-mcp` to `taskflow-mcp-core`** + at release time: `taskflow-mcp` (and `taskflow-mcp-server`) had been squatted + on npm by an unrelated package, so the host-neutral MCP server ships as + `taskflow-mcp-core`. The directory (`packages/taskflow-mcp-core`), the host + adapters dependency pins, and all `taskflow-mcp/server` / `taskflow-mcp/jsonrpc` + imports were updated accordingly. The adapters own bin names + (`codex-taskflow-mcp` / `claude-taskflow-mcp` / `opencode-taskflow-mcp`) are unchanged. + ### Added - **Library Phase 1: search-before-author + reusable-flow assets.** A new reusable-flow asset layer with sidecar `.meta.json` metadata @@ -44,7 +52,7 @@ All notable changes to taskflow are documented here. This project follows [Keep config scaffold, mirroring the Codex/Claude adapters. A flow's subagents can now execute as isolated `opencode run` sessions, and taskflow is exposed to OpenCode via the same `taskflow_*` MCP tools. Register with - `opencode mcp add taskflow -- npx -y -p opencode-taskflow opencode-taskflow-mcp` + `opencode mcp add taskflow -- npx -y -p opencode-taskflow opencode-taskflow-mcp-core` (or an `opencode.json` `mcp` entry). See `docs/opencode-mcp.md`. - Read-only phases inject a deny-mutations permission policy via `OPENCODE_CONFIG_CONTENT` (genuinely enforced); mutating phases run with @@ -91,6 +99,15 @@ All notable changes to taskflow are documented here. This project follows [Keep and saved flows from the library. `safeParse()` for LLM output remains strict. Re-exported from the `taskflow-core` barrel as `parseJsonc`. +### Fixed +- **The pi-taskflow "built-in agents upgrade" hint is now truly one-time.** It + previously re-printed every session while `settings.json` lacked a `taskflow` + key and the project had `.pi/agents/*.md`. A marker file + (`~/.pi/agent/.taskflow-upgrade-hint-shown`) is now written atomically (`wx` + flag) after the first print, so subsequent sessions skip it. Best-effort: an + unwritable agent dir only means the hint may show once more; it never blocks + session startup. + ## [0.1.5] — 2026-07-03 ### Added @@ -325,7 +342,7 @@ All notable changes to taskflow are documented here. This project follows [Keep - **Codex plugin** (`packages/codex-taskflow/plugin/`) for zero-config, plug-and-play install: `codex plugin marketplace add heggria/taskflow` then `codex plugin add taskflow@taskflow`. Ships a `.codex-plugin/plugin.json` - manifest, a `.mcp.json` that launches the MCP server via `npx -y -p codex-taskflow@ codex-taskflow-mcp` + manifest, a `.mcp.json` that launches the MCP server via `npx -y -p codex-taskflow@ codex-taskflow-mcp-core` (no separate global install), and a routing `SKILL.md` so Codex reaches for the `taskflow_*` tools on multi-phase / fan-out work automatically. A repo-root `.claude-plugin/marketplace.json` makes the plugin discoverable. @@ -403,9 +420,9 @@ All notable changes to taskflow are documented here. This project follows [Keep typebox). Vendors the three small pi helpers it used (`StringEnum`, `parseFrontmatter`, `getAgentDir`) so it is fully standalone. - **`codex-taskflow`** — run taskflow on OpenAI Codex: a `codex exec`-backed - subagent runner, plus a dependency-free MCP server (`codex-taskflow-mcp`) that + subagent runner, plus a dependency-free MCP server (`codex-taskflow-mcp-core`) that exposes `taskflow_run/list/show/verify/compile` to Codex users. Register with - `codex mcp add taskflow -- codex-taskflow-mcp`. + `codex mcp add taskflow -- codex-taskflow-mcp-core`. - **Host-neutral `SubagentRunner` seam** — the engine drives any host via an injected `runTask`; `piSubagentRunner` and `codexSubagentRunner` are the two implementations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c6d4fa3..bb19d95 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,7 +41,7 @@ See [`AGENTS.md`](./AGENTS.md) for the full layout and conventions. `taskflow` i |---------------------|------| | `packages/taskflow-core/` | Host-neutral engine: runtime, schema, agents, store, cache, verify, compile, context-store (zero host-SDK deps) | | `packages/taskflow-core/src/agents/` | 18 built-in agent definitions (`.md` with YAML frontmatter) | -| `packages/taskflow-mcp/` | Host-neutral MCP server: stdio JSON-RPC + `taskflow_*` tools + DAG SVG/outline renderer (depends on taskflow-core) | +| `packages/taskflow-mcp-core/` | Host-neutral MCP server: stdio JSON-RPC + `taskflow_*` tools + DAG SVG/outline renderer (depends on taskflow-core) | | `packages/pi-taskflow/` | Pi extension adapter (`taskflow` tool + `/tf` commands, TUI) + `skills/` | | `packages/codex-taskflow/` | Codex subagent runner + MCP bin + Codex plugin | | `packages/claude-taskflow/` | Claude Code subagent runner + MCP bin + Claude Code plugin | diff --git a/DECISIONS.md b/DECISIONS.md index 2bc516e..de820d0 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -1,7 +1,7 @@ # Architecture Decisions (taskflow) > Status: **living document**. Records the structural decisions behind the -> multi-host layout (taskflow-core / taskflow-mcp / taskflow-hosts / pi-taskflow / +> multi-host layout (taskflow-core / taskflow-mcp-core / taskflow-hosts / pi-taskflow / > codex-taskflow / claude-taskflow / opencode-taskflow), the trade-offs that > were considered, and the direction to take as the host count grows. > @@ -164,12 +164,12 @@ error blob. - **`runner-core.ts` lives in `taskflow-core`.** It is host-neutral (no host SDK import — only `node:child_process`), so keeping it in core does not violate the "core has zero host-SDK deps" rule. Moving it out (e.g. into - `taskflow-mcp`) would force every host adapter to depend on a second package + `taskflow-mcp-core`) would force every host adapter to depend on a second package for no benefit. - **Skill generation is single-sourced** (`skills-src/` + `build-skills.mjs` + a drift-guard test). New hosts add one `entry..md` and extend the comma host list; the skill body is shared. Do not per-host the skill body. -- **MCP server is its own package (`taskflow-mcp`)** — a pure presentation +- **MCP server is its own package (`taskflow-mcp-core`)** — a pure presentation layer over core. Pi users never pull MCP code. This boundary is correct. - **Lockstep versioning is kept for now** (all seven packages share a version). It is crude but it is *less* work than tracking which subset of packages need diff --git a/README.md b/README.md index 8030be4..84b74b7 100644 --- a/README.md +++ b/README.md @@ -895,7 +895,7 @@ Our `self-improve` flow is a 10-phase DAG — it audits the codebase, patches de ## Status & limits -**v0.1.6** (current release) — adds **library Phase 1** (search-before-author + reusable-flow sidecar metadata), the **`defineFile`** parameter (verify/compile/run a flow from a path on disk), and **JSONC comment support** in flow definition files (`//` and `/* */` comments + trailing commas, parsed by the new zero-dependency `parseJsonc`). **v0.1.5** added **Claude Code and OpenCode as hosts**, **extracted the MCP server into its own `taskflow-mcp` package**, and **de-duplicated the three host runners** into a shared `runSubagentProcess`. See [CHANGELOG](./CHANGELOG.md) for the full history. Baseline: **multi-host monorepo of seven packages** — the host-neutral `taskflow-core` engine, the host-neutral `taskflow-mcp` MCP server, the shared host-runner `taskflow-hosts`, plus `pi-taskflow` (Pi adapter), `codex-taskflow`, `claude-taskflow`, and `opencode-taskflow` (the three delivery packages re-export their runners from `taskflow-hosts` and each ships an MCP bin + plugin/config), all sharing the host-neutral MCP server in `taskflow-mcp`. **Library Phase 1**: save flows with `purpose`+`tags` via `taskflow_save` (MCP) or `action=save` (Pi), search them with structural + CJK-aware keyword scoring via `taskflow_search`/`action=search`, and track `reuseCount` via `reusedFromSearch`. **`defineFile`**: pass a `defineFile` path (or `{defineFile, name}`) to `action=run` (Pi) or `taskflow_run`/`taskflow_verify`/`taskflow_compile` (MCP) instead of an inline `define`, and the engine reads the flow from disk — pair it with JSONC comments to annotate saved flows. **JSONC**: flow-definition `.json` files may now carry `//` and `/* */` comments and trailing commas (parsed by `parseJsonc`, re-exported from the `taskflow-core` barrel); LLM-output parsing via `safeParse` stays strict. **Shared Context Tree**: opt-in (`shareContext` / `contextSharing`) blackboard + supervision tools (`ctx_read`/`ctx_write` horizontal reuse, `ctx_report`/`ctx_spawn` vertical supervision); `ctx_spawn` accepts a flat task **or** a dependency-bearing `subflow` (a runtime-validated nested DAG), depth-capped on a unified nesting counter with budget accounting. **Workspace isolation**: a phase's `cwd` accepts reserved keywords `temp`/`dedicated`/`worktree` — the runtime allocates an isolated dir (or a git worktree on a throwaway branch) and tears it down after the phase, fail-open, rejected in LLM-authored sub-flows. **Detached execution**: runs can execute in the background, detached from the Pi session. Prior: loop-until-done (`loop`), tournament (best-of-N with a judge), cross-run memoization (content-addressed cache with git/file/glob/env fingerprints and TTL), interactive `/tf init`, configurable built-in agents, 18 built-in agents with 6 model roles. Full control-flow & reliability layer (`when` guards, `join: any`, `retry`/backoff, `approval`, `flow` composition, `budget` caps, `onBlock: "retry"`, `eval` machine gates, idle watchdog) on top of the DSL + DAG runtime (`agent`/`parallel`/`map`/`gate`/`reduce`). Inline + saved flows, cross-session resume, live progress, and isolated context. A run executes as one streaming tool call. +**v0.1.6** (current release) — adds **library Phase 1** (search-before-author + reusable-flow sidecar metadata), the **`defineFile`** parameter (verify/compile/run a flow from a path on disk), and **JSONC comment support** in flow definition files (`//` and `/* */` comments + trailing commas, parsed by the new zero-dependency `parseJsonc`). **v0.1.5** added **Claude Code and OpenCode as hosts**, **extracted the MCP server into its own `taskflow-mcp-core` package**, and **de-duplicated the three host runners** into a shared `runSubagentProcess`. See [CHANGELOG](./CHANGELOG.md) for the full history. Baseline: **multi-host monorepo of seven packages** — the host-neutral `taskflow-core` engine, the host-neutral `taskflow-mcp-core` MCP server, the shared host-runner `taskflow-hosts`, plus `pi-taskflow` (Pi adapter), `codex-taskflow`, `claude-taskflow`, and `opencode-taskflow` (the three delivery packages re-export their runners from `taskflow-hosts` and each ships an MCP bin + plugin/config), all sharing the host-neutral MCP server in `taskflow-mcp-core`. **Library Phase 1**: save flows with `purpose`+`tags` via `taskflow_save` (MCP) or `action=save` (Pi), search them with structural + CJK-aware keyword scoring via `taskflow_search`/`action=search`, and track `reuseCount` via `reusedFromSearch`. **`defineFile`**: pass a `defineFile` path (or `{defineFile, name}`) to `action=run` (Pi) or `taskflow_run`/`taskflow_verify`/`taskflow_compile` (MCP) instead of an inline `define`, and the engine reads the flow from disk — pair it with JSONC comments to annotate saved flows. **JSONC**: flow-definition `.json` files may now carry `//` and `/* */` comments and trailing commas (parsed by `parseJsonc`, re-exported from the `taskflow-core` barrel); LLM-output parsing via `safeParse` stays strict. **Shared Context Tree**: opt-in (`shareContext` / `contextSharing`) blackboard + supervision tools (`ctx_read`/`ctx_write` horizontal reuse, `ctx_report`/`ctx_spawn` vertical supervision); `ctx_spawn` accepts a flat task **or** a dependency-bearing `subflow` (a runtime-validated nested DAG), depth-capped on a unified nesting counter with budget accounting. **Workspace isolation**: a phase's `cwd` accepts reserved keywords `temp`/`dedicated`/`worktree` — the runtime allocates an isolated dir (or a git worktree on a throwaway branch) and tears it down after the phase, fail-open, rejected in LLM-authored sub-flows. **Detached execution**: runs can execute in the background, detached from the Pi session. Prior: loop-until-done (`loop`), tournament (best-of-N with a judge), cross-run memoization (content-addressed cache with git/file/glob/env fingerprints and TTL), interactive `/tf init`, configurable built-in agents, 18 built-in agents with 6 model roles. Full control-flow & reliability layer (`when` guards, `join: any`, `retry`/backoff, `approval`, `flow` composition, `budget` caps, `onBlock: "retry"`, `eval` machine gates, idle watchdog) on top of the DSL + DAG runtime (`agent`/`parallel`/`map`/`gate`/`reduce`). Inline + saved flows, cross-session resume, live progress, and isolated context. A run executes as one streaming tool call. Known boundaries (tracked, bounded — no surprises mid-flow): @@ -914,7 +914,7 @@ Known boundaries (tracked, bounded — no surprises mid-flow): | Package | Role | |---------|------| | [`taskflow-core`](./packages/taskflow-core) | Host-neutral orchestration engine (zero host-SDK deps; only `typebox`) — runtime, DSL, cache, verify | -| [`taskflow-mcp`](./packages/taskflow-mcp) | Host-neutral MCP server (stdio JSON-RPC + `taskflow_*` tools + DAG renderer); depends on core | +| [`taskflow-mcp-core`](./packages/taskflow-mcp-core) | Host-neutral MCP server (stdio JSON-RPC + `taskflow_*` tools + DAG renderer); depends on core | | [`taskflow-hosts`](./packages/taskflow-hosts) | Shared host-runner collection — the codex/claude/opencode `SubagentRunner` impls + their argv builders + event-stream parsers; depends on core | | [`pi-taskflow`](./packages/pi-taskflow) | Pi extension adapter — `taskflow` tool + `/tf` commands (what `pi install npm:pi-taskflow` gives you) | | [`codex-taskflow`](./packages/codex-taskflow) | Codex MCP server + bin + [Codex plugin](./packages/codex-taskflow/plugin) (re-exports the runner from `taskflow-hosts`) ([guide](./docs/codex-mcp.md)) | diff --git a/README.zh-CN.md b/README.zh-CN.md index addb2e9..4f4646b 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -770,7 +770,7 @@ provided files. Report violations grouped by file. No fixes. ## 状态与边界 -**v0.1.6**——当前发布版。完整历史详见 [CHANGELOG](./CHANGELOG.md)。本版新增 **库 Phase 1**(先搜后写 + 可复用流程资产)、**`defineFile` 参数**(从磁盘路径 verify/compile/run 流程)、以及流程定义文件的 **JSONC 注释支持**(`//` 与 `/* */` 注释 + 尾逗号,由零依赖的 `parseJsonc` 解析)。**v0.1.5** 新增了 **Claude Code 与 OpenCode 两个宿主**、**将 MCP 服务器拆为独立的 `taskflow-mcp` 包**,并**将三个宿主运行器去重**为共享的 `runSubagentProcess`。基线:**七个包的多宿主 monorepo**——宿主无关的 `taskflow-core` 引擎、宿主无关的 `taskflow-mcp` MCP 服务器、共享宿主运行器的 `taskflow-hosts`,加上 `pi-taskflow`(Pi 适配器)、`codex-taskflow`、`claude-taskflow`、`opencode-taskflow`(后三者为交付包,通过 `taskflow-hosts` 复用 runner + MCP bin + 插件/配置),共享 `taskflow-mcp` 中的宿主无关 MCP 服务器。**共享上下文树**:可选开启(`shareContext` / `contextSharing`)的黑板 + 监督工具(`ctx_read`/`ctx_write` 水平复用、`ctx_report`/`ctx_spawn` 垂直监督)。**工作区隔离**:阶段的 `cwd` 接受保留关键字 `temp`/`dedicated`/`worktree`,运行时分配隔离目录(或一条一次性分支上的 git worktree)并在阶段结束后拆除。**后台(detached)执行**:运行可脱离会话后台执行。早期功能:循环至完成(`loop`)、锦标赛(best-of-N 带评判者)、跨运行记忆化(基于 git/文件/glob/环境指纹和 TTL 的内容寻址缓存)、交互式 `/tf init`、18 个内置代理及模型角色。完整的控制流与可靠性层(`when` 守卫、`join: any`、`retry`/回退、`approval`、`flow` 组合、`budget` 上限、`eval` 机器门控、空闲看门狗)构建在 DSL + DAG 运行时(`agent`/`parallel`/`map`/`gate`/`reduce`)之上。支持内联 + 已保存流程、跨会话恢复、实时进度和上下文隔离。一次运行作为一个流式工具调用执行。 +**v0.1.6**——当前发布版。完整历史详见 [CHANGELOG](./CHANGELOG.md)。本版新增 **库 Phase 1**(先搜后写 + 可复用流程资产)、**`defineFile` 参数**(从磁盘路径 verify/compile/run 流程)、以及流程定义文件的 **JSONC 注释支持**(`//` 与 `/* */` 注释 + 尾逗号,由零依赖的 `parseJsonc` 解析)。**v0.1.5** 新增了 **Claude Code 与 OpenCode 两个宿主**、**将 MCP 服务器拆为独立的 `taskflow-mcp-core` 包**,并**将三个宿主运行器去重**为共享的 `runSubagentProcess`。基线:**七个包的多宿主 monorepo**——宿主无关的 `taskflow-core` 引擎、宿主无关的 `taskflow-mcp-core` MCP 服务器、共享宿主运行器的 `taskflow-hosts`,加上 `pi-taskflow`(Pi 适配器)、`codex-taskflow`、`claude-taskflow`、`opencode-taskflow`(后三者为交付包,通过 `taskflow-hosts` 复用 runner + MCP bin + 插件/配置),共享 `taskflow-mcp-core` 中的宿主无关 MCP 服务器。**共享上下文树**:可选开启(`shareContext` / `contextSharing`)的黑板 + 监督工具(`ctx_read`/`ctx_write` 水平复用、`ctx_report`/`ctx_spawn` 垂直监督)。**工作区隔离**:阶段的 `cwd` 接受保留关键字 `temp`/`dedicated`/`worktree`,运行时分配隔离目录(或一条一次性分支上的 git worktree)并在阶段结束后拆除。**后台(detached)执行**:运行可脱离会话后台执行。早期功能:循环至完成(`loop`)、锦标赛(best-of-N 带评判者)、跨运行记忆化(基于 git/文件/glob/环境指纹和 TTL 的内容寻址缓存)、交互式 `/tf init`、18 个内置代理及模型角色。完整的控制流与可靠性层(`when` 守卫、`join: any`、`retry`/回退、`approval`、`flow` 组合、`budget` 上限、`eval` 机器门控、空闲看门狗)构建在 DSL + DAG 运行时(`agent`/`parallel`/`map`/`gate`/`reduce`)之上。支持内联 + 已保存流程、跨会话恢复、实时进度和上下文隔离。一次运行作为一个流式工具调用执行。 已知边界(已追踪、有限定——不会在流程中途出现意外): @@ -789,7 +789,7 @@ provided files. Report violations grouped by file. No fixes. | 包 | 角色 | |----|------| | [`taskflow-core`](./packages/taskflow-core) | 宿主无关的编排引擎(零宿主 SDK 依赖;仅 `typebox`)——运行时、DSL、缓存、验证 | -| [`taskflow-mcp`](./packages/taskflow-mcp) | 宿主无关的 MCP 服务器(stdio JSON-RPC + `taskflow_*` 工具 + DAG 渲染);依赖 core | +| [`taskflow-mcp-core`](./packages/taskflow-mcp-core) | 宿主无关的 MCP 服务器(stdio JSON-RPC + `taskflow_*` 工具 + DAG 渲染);依赖 core | | [`taskflow-hosts`](./packages/taskflow-hosts) | 共享宿主 runner 集合(codex / claude / opencode 的 `SubagentRunner` + argv 构建器 + 事件流解析器);依赖 core | | [`pi-taskflow`](./packages/pi-taskflow) | Pi 扩展适配器——`taskflow` 工具 + `/tf` 命令(即 `pi install npm:pi-taskflow` 安装的内容) | | [`codex-taskflow`](./packages/codex-taskflow) | Codex 子代理运行器 + MCP bin,及 [Codex 插件](./packages/codex-taskflow/plugin)([指南](./docs/codex-mcp.md)) | diff --git a/RELEASE.md b/RELEASE.md index ab63c11..2719126 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -5,18 +5,18 @@ taskflow is a monorepo of seven independently published packages: | Package | npm name | What it is | |---------|----------|------------| | `packages/taskflow-core` | **`taskflow-core`** | Host-neutral engine (DSL, runtime, cache, verify). Zero host SDK deps. | -| `packages/taskflow-mcp` | **`taskflow-mcp`** | Host-neutral MCP server (stdio JSON-RPC + taskflow_* tools + DAG renderer). Depends on core. | +| `packages/taskflow-mcp-core` | **`taskflow-mcp-core`** | Host-neutral MCP server (stdio JSON-RPC + taskflow_* tools + DAG renderer). Depends on core. | | `packages/taskflow-hosts` | **`taskflow-hosts`** | Shared host-runner collection: codex/claude/opencode `SubagentRunner` impls + argv builders + event-stream parsers. Depends on core. | | `packages/pi-taskflow` | **`pi-taskflow`** | Pi extension adapter. Keeps the original published name (no break for existing users). | | `packages/codex-taskflow` | **`codex-taskflow`** | Codex delivery package: re-exports the runner from `taskflow-hosts` + MCP bin + plugin. | | `packages/claude-taskflow` | **`claude-taskflow`** | Claude Code delivery package: re-exports the runner from `taskflow-hosts` + MCP bin + plugin. | | `packages/opencode-taskflow` | **`opencode-taskflow`** | OpenCode delivery package: re-exports the runner from `taskflow-hosts` + MCP bin + config scaffold. | -Dependency order: `taskflow-mcp`, `taskflow-hosts`, `pi-taskflow`, `codex-taskflow`, `claude-taskflow`, and `opencode-taskflow` all depend on `taskflow-core` (`taskflow-mcp` and `taskflow-hosts` directly; the adapters via both `taskflow-hosts` and `taskflow-mcp`), so **core publishes first, then taskflow-mcp, then taskflow-hosts, then the adapters**. +Dependency order: `taskflow-mcp-core`, `taskflow-hosts`, `pi-taskflow`, `codex-taskflow`, `claude-taskflow`, and `opencode-taskflow` all depend on `taskflow-core` (`taskflow-mcp-core` and `taskflow-hosts` directly; the adapters via both `taskflow-hosts` and `taskflow-mcp-core`), so **core publishes first, then taskflow-mcp-core, then taskflow-hosts, then the adapters**. ## One-time setup -All seven names are non-scoped and available on public npm — **no npm org needed**. `pi-taskflow` is already owned by `heggria`; the rest (`taskflow-core`, `taskflow-mcp`, `taskflow-hosts`, `codex-taskflow`, `claude-taskflow`, `opencode-taskflow`) are unclaimed (publishing creates them). +All seven names are non-scoped and available on public npm — **no npm org needed**. `pi-taskflow` is already owned by `heggria`; the rest (`taskflow-core`, `taskflow-mcp-core`, `taskflow-hosts`, `codex-taskflow`, `claude-taskflow`, `opencode-taskflow`) are unclaimed (publishing creates them). ```sh # 1. Point at PUBLIC npm (the repo's default registry may be a private mirror) @@ -69,7 +69,7 @@ this release's CHANGELOG section, verify: ```sh # core FIRST — the adapters depend on it pnpm publish --filter taskflow-core --registry=https://registry.npmjs.org/ --provenance -pnpm publish --filter taskflow-mcp --registry=https://registry.npmjs.org/ --provenance +pnpm publish --filter taskflow-mcp-core --registry=https://registry.npmjs.org/ --provenance pnpm publish --filter taskflow-hosts --registry=https://registry.npmjs.org/ --provenance pnpm publish --filter pi-taskflow --registry=https://registry.npmjs.org/ --provenance pnpm publish --filter codex-taskflow --registry=https://registry.npmjs.org/ --provenance @@ -79,12 +79,12 @@ pnpm publish --filter opencode-taskflow --registry=https://registry.npmjs.org/ - `publishConfig.access: public` is set on each package, so scoped/unscoped both publish publicly. -> **Note on `taskflow-core` as a dependency.** `taskflow-mcp`, `taskflow-hosts`, and the host adapters +> **Note on `taskflow-core` as a dependency.** `taskflow-mcp-core`, `taskflow-hosts`, and the host adapters > (`pi-taskflow` / `codex-taskflow` / `claude-taskflow` / `opencode-taskflow`) > declare `"taskflow-core": "0.1.6"` (an exact version, not `workspace:*`), so the > published tarballs resolve the real npm package once it exists. Always publish -> `taskflow-core` first and bump all seven in lockstep. (`taskflow-mcp` and `taskflow-hosts` are the -> other internal dependencies: the MCP host adapters pin `"taskflow-mcp"`; the codex/claude/opencode +> `taskflow-core` first and bump all seven in lockstep. (`taskflow-mcp-core` and `taskflow-hosts` are the +> other internal dependencies: the MCP host adapters pin `"taskflow-mcp-core"`; the codex/claude/opencode > delivery packages pin `"taskflow-hosts"`.) ## Tag + GitHub Release (automated) @@ -101,7 +101,7 @@ git tag v0.1.6 && git push origin v0.1.6 ```sh pnpm view taskflow-core version --registry=https://registry.npmjs.org/ -pnpm view taskflow-mcp version --registry=https://registry.npmjs.org/ +pnpm view taskflow-mcp-core version --registry=https://registry.npmjs.org/ pnpm view taskflow-hosts version --registry=https://registry.npmjs.org/ pnpm view pi-taskflow version --registry=https://registry.npmjs.org/ pnpm view codex-taskflow version --registry=https://registry.npmjs.org/ diff --git a/docs/claude-mcp.md b/docs/claude-mcp.md index e51ae70..5d725d2 100644 --- a/docs/claude-mcp.md +++ b/docs/claude-mcp.md @@ -8,13 +8,13 @@ directions, both built on the host-neutral `SubagentRunner` seam sessions (`packages/taskflow-hosts/src/claude-runner.ts`). 2. **Claude Code as the caller** — taskflow is exposed to a Claude Code user as an **MCP server**, so the `taskflow_*` tools appear inside the session. The - MCP protocol, tools, and rendering all live in the host-neutral taskflow-mcp package - (`packages/taskflow-mcp/src/mcp/`); the claude adapter just binds them to + MCP protocol, tools, and rendering all live in the host-neutral taskflow-mcp-core package + (`packages/taskflow-mcp-core/src/mcp/`); the claude adapter just binds them to the `claude -p` subagent runner (`packages/claude-taskflow/src/mcp/`). This is the direction described here. The MCP server is dependency-free: it speaks JSON-RPC 2.0 over stdio on Node -built-ins (`packages/taskflow-mcp/src/mcp/jsonrpc.ts`), so taskflow keeps its +built-ins (`packages/taskflow-mcp-core/src/mcp/jsonrpc.ts`), so taskflow keeps its **zero runtime dependencies** guarantee — no `@modelcontextprotocol/sdk`. ## Install (recommended): the Claude Code plugin diff --git a/docs/codex-mcp.md b/docs/codex-mcp.md index 6e5a02b..c165c13 100644 --- a/docs/codex-mcp.md +++ b/docs/codex-mcp.md @@ -11,7 +11,7 @@ both built on the host-neutral `SubagentRunner` seam (`packages/codex-taskflow/src/mcp/`). This is the direction described here. The MCP server is dependency-free: it speaks JSON-RPC 2.0 over stdio on Node -built-ins (`packages/taskflow-mcp/src/mcp/jsonrpc.ts`), so taskflow keeps its +built-ins (`packages/taskflow-mcp-core/src/mcp/jsonrpc.ts`), so taskflow keeps its **zero runtime dependencies** guarantee — no `@modelcontextprotocol/sdk`. ## Install (recommended): the Codex plugin diff --git a/docs/opencode-mcp.md b/docs/opencode-mcp.md index a1228ac..8885307 100644 --- a/docs/opencode-mcp.md +++ b/docs/opencode-mcp.md @@ -8,13 +8,13 @@ on the host-neutral `SubagentRunner` seam sessions (`packages/taskflow-hosts/src/opencode-runner.ts`). 2. **OpenCode as the caller** — taskflow is exposed to an OpenCode user as an **MCP server**, so the `taskflow_*` tools appear in the session. The MCP - protocol, tools, and rendering all live in the host-neutral taskflow-mcp package - (`packages/taskflow-mcp/src/mcp/`); the opencode adapter just binds them to + protocol, tools, and rendering all live in the host-neutral taskflow-mcp-core package + (`packages/taskflow-mcp-core/src/mcp/`); the opencode adapter just binds them to the `opencode run` subagent runner (`packages/opencode-taskflow/src/mcp/`). This is the direction described here. The MCP server is dependency-free: it speaks JSON-RPC 2.0 over stdio on Node -built-ins (`packages/taskflow-mcp/src/mcp/jsonrpc.ts`), so taskflow keeps its +built-ins (`packages/taskflow-mcp-core/src/mcp/jsonrpc.ts`), so taskflow keeps its **zero runtime dependencies** guarantee — no `@modelcontextprotocol/sdk`. ## Install: register the MCP server diff --git a/docs/rfc-library-reuse.md b/docs/rfc-library-reuse.md index d6c078e..9c8d75d 100644 --- a/docs/rfc-library-reuse.md +++ b/docs/rfc-library-reuse.md @@ -472,7 +472,7 @@ function buildReuseHint(result: SearchResult): string { ### 5.4 新增 MCP 工具清单(A5/N2 修复) -当前 MCP server(`taskflow-mcp`)的 TOOLS 数组只有 `taskflow_run`/`taskflow_list`/`taskflow_show`/`taskflow_verify`/`taskflow_compile`/`taskflow_peek`。library 功能需要新增以下 MCP 工具: +当前 MCP server(`taskflow-mcp-core`)的 TOOLS 数组只有 `taskflow_run`/`taskflow_list`/`taskflow_show`/`taskflow_verify`/`taskflow_compile`/`taskflow_peek`。library 功能需要新增以下 MCP 工具: | 工具名 | 参数 | 说明 | |--------|------|------| diff --git a/package.json b/package.json index d5e8ffd..dfa874e 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,14 @@ "name": "pi-taskflow-monorepo", "version": "0.1.6", "private": true, - "description": "Monorepo for taskflow-core, taskflow-mcp, taskflow-hosts, pi-taskflow, codex-taskflow, claude-taskflow, opencode-taskflow, and the documentation website.", + "description": "Monorepo for taskflow-core, taskflow-mcp-core, taskflow-hosts, pi-taskflow, codex-taskflow, claude-taskflow, opencode-taskflow, and the documentation website.", "type": "module", "engines": { "node": ">=22.19.0" }, "packageManager": "pnpm@9.15.0", "scripts": { - "build": "pnpm run build:skills && pnpm --filter taskflow-core build && pnpm --filter taskflow-mcp build && pnpm --filter taskflow-hosts build && pnpm --filter pi-taskflow build && pnpm --filter codex-taskflow build && pnpm --filter claude-taskflow build && pnpm --filter opencode-taskflow build", + "build": "pnpm run build:skills && pnpm --filter taskflow-core build && pnpm --filter taskflow-mcp-core build && pnpm --filter taskflow-hosts build && pnpm --filter pi-taskflow build && pnpm --filter codex-taskflow build && pnpm --filter claude-taskflow build && pnpm --filter opencode-taskflow build", "build:website": "cd website && npm run build", "build:skills": "node scripts/build-skills.mjs", "typecheck": "tsc --noEmit", diff --git a/packages/claude-taskflow/package.json b/packages/claude-taskflow/package.json index f6fedcd..633dd34 100644 --- a/packages/claude-taskflow/package.json +++ b/packages/claude-taskflow/package.json @@ -56,6 +56,6 @@ "dependencies": { "taskflow-core": "0.1.6", "taskflow-hosts": "0.1.6", - "taskflow-mcp": "0.1.6" + "taskflow-mcp-core": "0.1.6" } } diff --git a/packages/claude-taskflow/src/mcp/server.ts b/packages/claude-taskflow/src/mcp/server.ts index 170598a..f6e291d 100644 --- a/packages/claude-taskflow/src/mcp/server.ts +++ b/packages/claude-taskflow/src/mcp/server.ts @@ -1,5 +1,5 @@ /** - * The Claude Code binding of the host-neutral MCP server (taskflow-mcp/server). + * The Claude Code binding of the host-neutral MCP server (taskflow-mcp-core/server). * * The protocol layer, tool schemas, and handlers all live in core; this shim * only closes the loop for Claude Code: every subagent a flow spawns is itself @@ -11,8 +11,8 @@ import { makeMcpHandlers as coreMakeMcpHandlers, makeToolHandlers as coreMakeToolHandlers, startMcpServer as coreStartMcpServer, -} from "taskflow-mcp/server"; -import type { RpcHandler } from "taskflow-mcp/jsonrpc"; +} from "taskflow-mcp-core/server"; +import type { RpcHandler } from "taskflow-mcp-core/jsonrpc"; import { claudeSubagentRunner } from "taskflow-hosts"; /** Per-call tool handlers with claude subagent execution bound in. */ diff --git a/packages/claude-taskflow/test/mcp-server.test.ts b/packages/claude-taskflow/test/mcp-server.test.ts index a2b910c..72c8c35 100644 --- a/packages/claude-taskflow/test/mcp-server.test.ts +++ b/packages/claude-taskflow/test/mcp-server.test.ts @@ -10,7 +10,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { PassThrough } from "node:stream"; -import { serveStdio } from "taskflow-mcp/jsonrpc"; +import { serveStdio } from "taskflow-mcp-core/jsonrpc"; import { makeMcpHandlers, makeToolHandlers } from "../src/mcp/server.ts"; /** Send a list of JSON-RPC messages through the server, collect responses. */ diff --git a/packages/codex-taskflow/package.json b/packages/codex-taskflow/package.json index 8d9c2b2..1c61757 100644 --- a/packages/codex-taskflow/package.json +++ b/packages/codex-taskflow/package.json @@ -56,6 +56,6 @@ "dependencies": { "taskflow-core": "0.1.6", "taskflow-hosts": "0.1.6", - "taskflow-mcp": "0.1.6" + "taskflow-mcp-core": "0.1.6" } } diff --git a/packages/codex-taskflow/src/mcp/server.ts b/packages/codex-taskflow/src/mcp/server.ts index 1086669..5d6f613 100644 --- a/packages/codex-taskflow/src/mcp/server.ts +++ b/packages/codex-taskflow/src/mcp/server.ts @@ -1,5 +1,5 @@ /** - * The Codex binding of the host-neutral MCP server (taskflow-mcp/server). + * The Codex binding of the host-neutral MCP server (taskflow-mcp-core/server). * * The protocol layer, tool schemas, and handlers all live in core; this shim * only closes the loop for Codex: every subagent a flow spawns is itself a @@ -11,8 +11,8 @@ import { makeMcpHandlers as coreMakeMcpHandlers, makeToolHandlers as coreMakeToolHandlers, startMcpServer as coreStartMcpServer, -} from "taskflow-mcp/server"; -import type { RpcHandler } from "taskflow-mcp/jsonrpc"; +} from "taskflow-mcp-core/server"; +import type { RpcHandler } from "taskflow-mcp-core/jsonrpc"; import { codexSubagentRunner } from "taskflow-hosts"; /** Per-call tool handlers with codex subagent execution bound in. */ diff --git a/packages/codex-taskflow/test/mcp-server.test.ts b/packages/codex-taskflow/test/mcp-server.test.ts index 0d41b2a..e9187c9 100644 --- a/packages/codex-taskflow/test/mcp-server.test.ts +++ b/packages/codex-taskflow/test/mcp-server.test.ts @@ -11,7 +11,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { PassThrough } from "node:stream"; -import { serveStdio } from "taskflow-mcp/jsonrpc"; +import { serveStdio } from "taskflow-mcp-core/jsonrpc"; import { makeMcpHandlers, makeToolHandlers } from "../src/mcp/server.ts"; /** Send a list of JSON-RPC messages through the server, collect responses. */ diff --git a/packages/opencode-taskflow/package.json b/packages/opencode-taskflow/package.json index c2d2c57..5a0f103 100644 --- a/packages/opencode-taskflow/package.json +++ b/packages/opencode-taskflow/package.json @@ -55,6 +55,6 @@ "dependencies": { "taskflow-core": "0.1.6", "taskflow-hosts": "0.1.6", - "taskflow-mcp": "0.1.6" + "taskflow-mcp-core": "0.1.6" } } diff --git a/packages/opencode-taskflow/src/mcp/server.ts b/packages/opencode-taskflow/src/mcp/server.ts index 025803f..8478167 100644 --- a/packages/opencode-taskflow/src/mcp/server.ts +++ b/packages/opencode-taskflow/src/mcp/server.ts @@ -1,5 +1,5 @@ /** - * The OpenCode binding of the host-neutral MCP server (taskflow-mcp/server). + * The OpenCode binding of the host-neutral MCP server (taskflow-mcp-core/server). * * The protocol layer, tool schemas, and handlers all live in core; this shim * only closes the loop for OpenCode: every subagent a flow spawns is itself an @@ -12,8 +12,8 @@ import { makeMcpHandlers as coreMakeMcpHandlers, makeToolHandlers as coreMakeToolHandlers, startMcpServer as coreStartMcpServer, -} from "taskflow-mcp/server"; -import type { RpcHandler } from "taskflow-mcp/jsonrpc"; +} from "taskflow-mcp-core/server"; +import type { RpcHandler } from "taskflow-mcp-core/jsonrpc"; import { opencodeSubagentRunner } from "taskflow-hosts"; /** Per-call tool handlers with opencode subagent execution bound in. */ diff --git a/packages/opencode-taskflow/test/mcp-server.test.ts b/packages/opencode-taskflow/test/mcp-server.test.ts index 470ffb5..421af20 100644 --- a/packages/opencode-taskflow/test/mcp-server.test.ts +++ b/packages/opencode-taskflow/test/mcp-server.test.ts @@ -10,7 +10,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { PassThrough } from "node:stream"; -import { serveStdio } from "taskflow-mcp/jsonrpc"; +import { serveStdio } from "taskflow-mcp-core/jsonrpc"; import { makeMcpHandlers, makeToolHandlers } from "../src/mcp/server.ts"; /** Send a list of JSON-RPC messages through the server, collect responses. */ diff --git a/packages/pi-taskflow/src/index.ts b/packages/pi-taskflow/src/index.ts index 8e84f3b..6b27694 100644 --- a/packages/pi-taskflow/src/index.ts +++ b/packages/pi-taskflow/src/index.ts @@ -18,6 +18,7 @@ import { RECOMMENDED_DEFAULTS, readSettings, writeSettings, + getSettingsPath, formatRolesReport, formatDiffReport, formatFlowResult, @@ -516,23 +517,32 @@ export default function (pi: ExtensionAPI) { // Upgrade hint: if the project already has .pi/agents/ with agent // files but no explicit taskflow settings, the user is upgrading // from the old default (sync=true) and may be surprised that sync - // is now disabled by default. + // is now disabled by default. Tracked by a marker file so it is shown + // at most once per agent dir (never repeats every session). try { const raw = readSettings(); if (!("taskflow" in raw)) { const fs = await import("node:fs"); const path = await import("node:path"); - const projectAgentsDir = path.join(ctx.cwd, ".pi", "agents"); - try { - const entries = fs.readdirSync(projectAgentsDir).filter((e: string) => e.endsWith(".md")); - if (entries.length > 0) { - console.warn( - `[taskflow] Note: built-in agents are no longer synced to .pi/agents/ by default. ` + - `If you rely on this, run /tf init → 'Configure taskflow preferences' to re-enable. ` + - `(This is a one-time upgrade hint.)`, - ); - } - } catch { /* .pi/agents/ doesn't exist — no hint needed */ } + const markerPath = path.join(path.dirname(getSettingsPath()), ".taskflow-upgrade-hint-shown"); + if (!fs.existsSync(markerPath)) { + const projectAgentsDir = path.join(ctx.cwd, ".pi", "agents"); + try { + const entries = fs.readdirSync(projectAgentsDir).filter((e: string) => e.endsWith(".md")); + if (entries.length > 0) { + console.warn( + `[taskflow] Note: built-in agents are no longer synced to .pi/agents/ by default. ` + + `If you rely on this, run /tf init → 'Configure taskflow preferences' to re-enable. ` + + `(This is a one-time upgrade hint.)`, + ); + // Persist the marker so the hint is not shown again. Best-effort: + // an unwritable agent dir just means it may show once more. + try { + fs.writeFileSync(markerPath, new Date().toISOString() + "\n", { flag: "wx" }); + } catch { /* marker already exists or unwritable — best effort */ } + } + } catch { /* .pi/agents/ doesn't exist — no hint needed */ } + } } } catch { // Best-effort: settings.json missing or unreadable is not an error. diff --git a/packages/taskflow-mcp/package.json b/packages/taskflow-mcp-core/package.json similarity index 92% rename from packages/taskflow-mcp/package.json rename to packages/taskflow-mcp-core/package.json index d7646ce..7dd0e68 100644 --- a/packages/taskflow-mcp/package.json +++ b/packages/taskflow-mcp-core/package.json @@ -1,5 +1,5 @@ { - "name": "taskflow-mcp", + "name": "taskflow-mcp-core", "version": "0.1.6", "description": "Host-neutral MCP server for taskflow: a dependency-free stdio JSON-RPC server exposing the taskflow_* tools, plus the DAG SVG/outline renderer. Shared by the codex/claude/opencode adapters — depends only on taskflow-core.", "keywords": [ @@ -19,7 +19,7 @@ "repository": { "type": "git", "url": "git+https://github.com/heggria/taskflow.git", - "directory": "packages/taskflow-mcp" + "directory": "packages/taskflow-mcp-core" }, "type": "module", "engines": { @@ -53,7 +53,7 @@ "dist" ], "scripts": { - "build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/copy-readme.mjs taskflow-mcp", + "build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/copy-readme.mjs taskflow-mcp-core", "prepublishOnly": "npm run build" }, "publishConfig": { diff --git a/packages/taskflow-mcp/src/mcp/jsonrpc.ts b/packages/taskflow-mcp-core/src/mcp/jsonrpc.ts similarity index 100% rename from packages/taskflow-mcp/src/mcp/jsonrpc.ts rename to packages/taskflow-mcp-core/src/mcp/jsonrpc.ts diff --git a/packages/taskflow-mcp/src/mcp/server.ts b/packages/taskflow-mcp-core/src/mcp/server.ts similarity index 100% rename from packages/taskflow-mcp/src/mcp/server.ts rename to packages/taskflow-mcp-core/src/mcp/server.ts diff --git a/packages/taskflow-mcp/src/mcp/svg.ts b/packages/taskflow-mcp-core/src/mcp/svg.ts similarity index 100% rename from packages/taskflow-mcp/src/mcp/svg.ts rename to packages/taskflow-mcp-core/src/mcp/svg.ts diff --git a/packages/taskflow-mcp/tsconfig.build.json b/packages/taskflow-mcp-core/tsconfig.build.json similarity index 100% rename from packages/taskflow-mcp/tsconfig.build.json rename to packages/taskflow-mcp-core/tsconfig.build.json diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 106fa6d..ac37ca2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,9 +38,9 @@ importers: taskflow-hosts: specifier: 0.1.6 version: link:../taskflow-hosts - taskflow-mcp: + taskflow-mcp-core: specifier: 0.1.6 - version: link:../taskflow-mcp + version: link:../taskflow-mcp-core packages/codex-taskflow: dependencies: @@ -50,9 +50,9 @@ importers: taskflow-hosts: specifier: 0.1.6 version: link:../taskflow-hosts - taskflow-mcp: + taskflow-mcp-core: specifier: 0.1.6 - version: link:../taskflow-mcp + version: link:../taskflow-mcp-core packages/opencode-taskflow: dependencies: @@ -62,9 +62,9 @@ importers: taskflow-hosts: specifier: 0.1.6 version: link:../taskflow-hosts - taskflow-mcp: + taskflow-mcp-core: specifier: 0.1.6 - version: link:../taskflow-mcp + version: link:../taskflow-mcp-core packages/pi-taskflow: dependencies: @@ -103,7 +103,7 @@ importers: specifier: ^6.0.3 version: 6.0.3 - packages/taskflow-mcp: + packages/taskflow-mcp-core: dependencies: taskflow-core: specifier: 0.1.6 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 56b4563..2cad3ee 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,7 +3,7 @@ # that field and requires this file instead.) packages: - "packages/taskflow-core" - - "packages/taskflow-mcp" + - "packages/taskflow-mcp-core" - "packages/taskflow-hosts" - "packages/pi-taskflow" - "packages/codex-taskflow" diff --git a/scripts/copy-readme.mjs b/scripts/copy-readme.mjs index 97d06fa..ebab4ea 100644 --- a/scripts/copy-readme.mjs +++ b/scripts/copy-readme.mjs @@ -21,7 +21,7 @@ const here = dirname(fileURLToPath(import.meta.url)); const repoRoot = join(here, ".."); // Packages that are published to npm and should carry the README. -const PUBLISHABLE = new Set(["taskflow-core", "taskflow-mcp", "pi-taskflow", "codex-taskflow", "claude-taskflow", "opencode-taskflow"]); +const PUBLISHABLE = new Set(["taskflow-core", "taskflow-mcp-core", "pi-taskflow", "codex-taskflow", "claude-taskflow", "opencode-taskflow"]); const REPO = "heggria/taskflow"; const BRANCH = "main";