release: v0.1.7 (gate/tournament fixes + Google Search Console verification + SEO content)#55
Merged
Conversation
The npm names `taskflow-mcp` and `taskflow-mcp-server` were squatted by an unrelated package, so the host-neutral MCP server ships as `taskflow-mcp-core`. Syncs the directory rename across dependency pins, workspace config, publish workflow, host adapters, and docs; fixes two stale references in CONTRIBUTING.md and the library RFC. Adapter bin names (codex-taskflow-mcp / claude-taskflow-mcp / opencode-taskflow-mcp) are unchanged. Part of the v0.1.6 release.
The session_start "built-in agents are no longer synced to .pi/agents/" hint claimed to be a one-time upgrade hint but had no persistence — it re-printed on every session as long as settings.json lacked a taskflow key and the project had .pi/agents/*.md. Track shown-state with a marker file (~/.pi/agent/.taskflow-upgrade-hint-shown), created atomically (flag "wx") right after the first print. Subsequent sessions skip the print. Best-effort: an unwritable agent dir only means the hint may show once more; it never blocks session startup.
…ixed The ba0249d change (marker file so the "built-in agents are no longer synced" hint stops repeating every session) ships with the 0.1.7 release branch and is now noted in the changelog under a new [0.1.7] section.
…eview
A multi-agent review of the 0.2.0 DSL RFC (run review-020-design)
cross-checked the FlowIR seam against PhaseSchema and found three
correctness bugs in the *current* engine — independent of the DSL, but
the DSL design made them load-bearing. All three affect cache/provenance
soundness or JSON↔DSL round-trip fidelity.
1. SIDECAR_PHASE_FIELDS omitted 8 Phase fields (agent, run, input,
timeout, expect, reflexion, idempotent, score). A JSON→FlowIR→JSON
round-trip silently dropped them, leaving script/gate/loop phases
unrunnable. Added them + a structural round-trip test that asserts
every author field survives the projection (so a future omission
fails loudly, not silently).
2. collectRefs did not scan `run` (array form), `input` (script stdin),
or `def` (inline sub-flow string form) — all three support {steps.X}
interpolation at runtime, so their references never entered the
declared dependency graph. recompute could skip a phase whose stdin
or argv genuinely depended on a now-stale upstream. Added scanning +
per-field tests.
3. translateTaskflow built declaredDeps.reads from interpolation refs
only; a phase's explicit `dependsOn` (a semantic ordering no
interpolation captures — e.g. sequential scripts sharing the
filesystem) was dropped from RunState.declaredDeps. Now merged
(observed ∪ declared), with a regression test.
1144/1144 tests pass (4 new). The new sidecar test is reverse-verified:
removing any covered field fails it.
Four user-facing file loaders (readDefineFile, readFlowFile/listFlows,
tryReadRunFile, readMeta/readMetaNextTo) collapsed two distinct failures —
file missing vs file malformed — into a single null / "X not found or
unparseable" result. The underlying JSON.parse SyntaxError (byte offset +
line/column) was swallowed by the lenient safeParse and never reached the
user, so a hand-authored defineFile with a stray bare newline reported
"defineFile not found or unparseable" and sent authors chasing a phantom
path/cwd problem.
Loaders now return a discriminated LoadResult<T> with reason "missing" |
"unparseable" and a detail field carrying the original parse error. A shared
describeLoadFailure(r, what) formats the user-facing message. New strict
parseStrict(text, { allowFence }) in interpolate.ts preserves the SyntaxError;
safeParse is unchanged so all ~25 LLM/subagent output paths keep their
fail-open recovery. listFlows now warns on a corrupt saved flow instead of
silently dropping it; new getFlowDiagnosed / loadRunDiagnosed distinguish
corrupt-vs-missing for by-name / by-runId resolution.
Breaking (pre-1.0): readDefineFile, readMeta, readMetaNextTo return
LoadResult<T> instead of T | null. The intentionally fail-open paths
(index-rebuild scans, cache.ts file hashing, path-traversal rejections)
are unchanged.
1392 tests pass (core 1146 + adapters 246); typecheck clean.
Bump all seven packages + internal dependency pins (taskflow-core / taskflow-hosts / taskflow-mcp-core) + plugin manifests (.mcp.json / .codex-plugin / .claude-plugin / opencode.json) + README/README.zh-CN version notes + SECURITY.md + RELEASE.md tag example to 0.1.7, and regenerate pnpm-lock.yaml. Pre-flight green: typecheck clean, 1146/1146 core tests pass, all seven packages build (dist) at 0.1.7.
#54) A genuine BLOCK was silently downgraded to PASS when models wrapped the verdict token in Markdown emphasis (VERDICT: **BLOCK**). The bare-token regex missed it and the miss fell into the fail-open default, so a blocked review could continue downstream unchecked. Three layered fixes: 1. Parser tolerance — a shared VERDICT_TOKEN_RE (scorers.ts) now tolerates `*`/`_`/`` `/`~` emphasis runs on either side of the verdict word. Used by both parseGateVerdict and parseJudgeOutput, replacing two identical bare-token regexes. 2. Fail-closed default — gate *model output* that cannot be parsed now BLOCKS instead of passing. A gate that cannot reach a verdict cannot be trusted to pass; halting is recoverable (prior phases persist, run is resumable). Config slips (unresolved score.target, malformed scorers) stay fail-open with a warning — they are authoring errors, not a judge that couldn't decide. An explicit non-blocking JSON verdict ({"verdict":"No issues found"}) is a semantic PASS, not ambiguity. 3. Auto-appended format suffix — a free-text gate whose task omits a VERDICT: instruction now gets the exact terminator auto-appended, so a model never "forgets" to emit one. Applied at all four gate-task construction sites including the onBlock:retry loop (previously missed). Skipped for gates with an output:"json" + expect contract. For maximum robustness, prefer output:"json" + expect enum ({verdict:{enum:["pass","block"]}}) which machine-validates the verdict. Breaking (pre-1.0): a gate whose model output has no parseable verdict now blocks instead of silently passing. Migration: emit VERDICT: PASS|BLOCK (auto-appended if omitted), adopt the JSON+expect contract, or mark the gate optional:true with a downstream fallback. Tests: 1148 pass (added Markdown-emphasis regression cases for both parseGateVerdict and parseJudgeOutput, the fail-closed default, and the auto-append behavior; updated the two fail-open tests to fail-closed). Docs: AGENTS.md invariant #4 + Error Handling, README, CHANGELOG, and the shared skill sources (regenerated for all four hosts). Closes #54.
- Wire the GSC verification code (iBm6KBJ...) as the hardcoded default in [lang]/layout.tsx so the meta tag emits in every build (CI never set the GOOGLE_SITE_VERIFICATION env var, so the tag was absent in production). - Enrich the root redirect page (app/page.tsx): was a bare <title>taskflow</title> shell with no description/og/canonical; now has full SEO meta + the verification tag, with canonical -> /en/. - Strengthen the homepage <title> from 'taskflow' to the keyword-rich 'taskflow — Declarative DAG Orchestration for Coding Agents' (title is the #1 on-page SEO factor); split out a field so subpages keep the short 'X | taskflow' template. - Add the missing field to taskflow-hosts/package.json so the npm page links back to the docs. Also updated via gh CLI: repo homepageUrl, description (mention all 4 hosts), and topics (+claude-code, +opencode, +mcp).
Long-tail, high-intent content pages that capture search traffic where taskflow is the best answer (the generic 'taskflow' keyword is unwinnable against Apache Airflow's TaskFlow API). All pages reuse the existing docs route, so each inherits full SEO automatically: descriptive title, description, canonical, hreflang alternates, and TechArticle + Breadcrumb JSON-LD. Comparisons (the 'X vs Y' queries, very high intent): - comparisons/index — overview + one-axis mental model - comparisons/taskflow-vs-workflow — declarative DAG vs imperative code-mode - comparisons/taskflow-vs-subagents — vs built-in task/tasks/chain shorthand - comparisons/taskflow-vs-langgraph — vs the general-purpose graph framework Blog (long-tail how-to / concept queries): - blog/index — listing - blog/orchestrate-codex-subagents — 'how to orchestrate codex subagents' - blog/claude-code-mcp-workflow — 'claude code mcp workflow' w/ gates - blog/what-is-a-task-graph — 'task graph DAG LLM' concept piece Bilingual: full EN + zh-CN mirrors. Adds 16 URLs (sitemap 81 -> 97). Registered in both root meta.json sidebars under new sections.
The Markdown-emphasis blind spot from #54 was not unique to VERDICT — the same bare-token regex pattern silently lost genuine signals in two more decision parsers: - parseTournamentWinner: `WINNER: **3**` missed the emphasis → silently reverted to variant 1, losing the judge's actual pick. - parseJudgeOutput SCORE marker: `SCORE: **0.8**` missed → score dropped. Refactor: a shared `markerRe(label, value)` factory in scorers.ts now emits all three emphasis-tolerant regexes (VERDICT_TOKEN_RE, SCORE_TOKEN_RE, WINNER_TOKEN_RE), tolerating `*`/`_`/`/`~` runs on either side of the captured value. parseTournamentWinner and the SCORE parse adopt it; VERDICT is rebuilt from the same factory for consistency (single source of truth). Fail stances are deliberate and now consistent with each marker's semantics: gate verdict / judge output → fail-closed (BLOCK); tournament winner → fail-open (variant 1, never lose work — the variants are already computed, so blocking would be worse than picking a safe default). Also promotes structured output as the documented default for ALL decision phases (gate verdict, tournament winner, router branch, judge score): prefer `output:"json"` + `expect` which machine-validates the decision and leaves no formatting the model can get subtly wrong. Free-text markers remain as a tolerant back-compat path. Skill sources + README + CHANGELOG updated and regenerated for all four hosts. Tests: 1149 pass. Added Markdown-emphasis regression cases for WINNER and SCORE markers; runtime-verified the factory-built regexes (clamp + emphasis + fail-open all correct). Refs #54.
# Conflicts: # README.md # README.zh-CN.md # packages/claude-taskflow/package.json # packages/codex-taskflow/package.json # packages/opencode-taskflow/package.json # packages/taskflow-mcp-core/package.json # pnpm-lock.yaml
PostCSS < 8.5.10 did not escape `</style>` when stringifying CSS ASTs — an XSS vector when user-submitted CSS is parsed and re-embedded in HTML <style> tags (GHSA-qx2m-qp2m-jg93 / CVE-2026-41305, medium). next@16.2.10 (a website/ transitive dep) pinned the vulnerable postcss@8.4.31. A root pnpm.overrides now forces postcss@^8.5.10 workspace-wide, hoisting the single 8.4.31 resolution to 8.5.16 (the version @tailwindcss/postcss already resolved). The website build (Next.js + Tailwind CSS pipeline) was verified unaffected (105/105 pages). Engine tests unaffected (1149 pass). Closes dependabot alert #5.
…viewport - Root redirect page referenced /opengraph-image, which 404s (the OG image route is app/[lang]/opengraph-image.tsx → only /en/opengraph-image and /zh-cn/opengraph-image exist). Point og:image + twitter:image at /en/opengraph-image so social cards render. - Move themeColor out of the metadata export into a generateViewport/viewport export (Next.js 15+ requires this; it was emitting a build warning on every docs page prerender).
Lands the trace-only slice of the deterministic-replay RFC (scoped to 0.1.7 by a 3-reviewer cross-adversarial plan review: risk-reviewer + critic + reviewer -> plan-arbiter; full replay logic defers to 0.2.0). Foundation: - trace.ts: TraceEvent schema (phase-start/end, subagent-call with resolved input + full output, decisions: gate-verdict / unreplayable), TraceSink interface, buffered FileTraceSink (per-phase buffer, one locked append at flush -> no lock contention on map/parallel fan-out), partial-line-tolerant readTrace, NoopTraceSink. - replay.ts: ReplayDecision type contract (defined now so the trace schema and diff-report shape are fixed before events are emitted; replayRun() in 0.2.0). - deterministic.ts: extract pure parseGateVerdict + a decoupled overBudget so a future replay imports them without the process-spawning runner. Runtime: - New optional RuntimeDeps.trace?: TraceSink — fail-open (missing/throwing sink never crashes a run) + host-agnostic (no host SDK in core). Runs with no sink behave identically to before. - Instrument executePhase (phase-start/end), runOne (subagent-call on completion — the load-bearing record), gate verdict (decision), and emit an unreplayable marker for context-sharing / inner-flow / context-file / unobservable-deps phases (single-phase analog of hasUnobservedDependencies). - store.ts: traceFilePath() + cleanup of .trace.jsonl + .trace.jsonl.lock in cleanupTerminalRuns (no unbounded disk accumulation). Surface: - pi: action=trace + /tf trace <runId> [--json]; wired trace into all 4 RuntimeDeps construction sites (run + 2 recompute). - MCP: taskflow_trace tool; also backfilled taskflow_why_stale + taskflow_recompute (dry-run only) — MCP previously lacked 5 analysis actions pi had. Wired trace into taskflow_run. Tests: 8 new in trace.test.ts (no-op-sink invariant, capture emission, map multi-emit, readTrace partial-line tolerance, FileTraceSink buffered round-trip + fail-open). Updated the 3 host adapters' tool-count assertions (8 -> 11). 1157 tests green; typecheck clean.
taskflow_trace / taskflow_why_stale / taskflow_recompute were added to the MCP server (backfilled analysis actions). The comprehensive e2e hardcoded the 8-tool list; bump it to the 11-tool list. The basic e2e + claude/opencode e2e use subset (includes) checks and were unaffected.
A deep cross-adversarial release-readiness review (scout -> risk/security/ quality reviewers -> critic cross-exam -> final-arbiter) returned GO-WITH-CONDITIONS. This commit lands the P0 + P1 conditions: P0 (ship-blockers): - Bump stale @0.1.6 plugin pins in codex-taskflow/plugin/.mcp.json and claude-taskflow/plugin/.mcp.json to @0.1.7. Without this, codex/claude plugin users would get a server missing taskflow_trace, taskflow_why_stale, taskflow_recompute, taskflow_save, taskflow_search (the 0.1.7 features). (opencode was already at 0.1.7.) P1 (release-quality): - Teach the 'trace' action in the skills (actions table 13 -> 15 incl. trace + search) so agents can discover/invoke it; rebuild generated SKILL.md. - Fix the README MCP tool list (said 6 tools; now lists all 11) + add /tf trace + /tf peek to the Pi command table. - Add trace decision-event tests (gate-verdict, unreplayable marker) — the events a 0.2.0 replay consumes were previously untested. - Update skills-build drift-guard (13 -> 15 actions). Arbiter verdict on the disputed trace-default/.gitignore claims: the risk + security reviewers made a deference-cascade error (both wrongly asserted trace is off-by-default; it is on-by-default at all 4 injection sites, and .pi/taskflows/ is already gitignored). Quality reviewer was correct; its findings weighted higher. Residual risk accepted: no trace opt-out yet (TASKFLOW_TRACE=0 planned for 0.1.8). Semver: ship as 0.1.7 (pre-1.0; the breaking changes are low-blast-radius internal API + a bug-fix surfacing). 1159 tests green; typecheck clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
pnpm run typecheckpasses.pnpm testpasses.TASKFLOW_BASE_PATH=/taskflow npm run build, 105 pages).mainto deploy (see below).Related issue
Unblocks Google Search Console ownership verification — the verification meta tag currently only exists on this branch, not
main, so the live site cannot be verified until this merges anddeploy-websiteruns.What changed
This PR lands the full v0.1.7 branch. Two logical groups:
1. v0.1.7 release prep + fixes
chore(release): prepare v0.1.7refactor(mcp-core): rename taskflow-mcp → taskflow-mcp-corefix(pi-taskflow): make built-in agents upgrade hint truly one-timefix(core): surface parse errors with position in file loadersfix(flowir): close three provenance/round-trip gapsfix(gate): parse Markdown verdicts, fail closed, enforce output formatfix(tournament,score): extend marker tolerance to WINNER/SCORE2. SEO — Google Search Console + on-page fixes + new content
Technical (so the live site can be verified & ranked):
iBm6KBJ…) as a hardcoded default — CI never setGOOGLE_SITE_VERIFICATION, so the meta tag was absent in production.<title>taskflow</title>shell with no description/og/canonical → now full SEO meta + verification tag, canonical →/en/.<title>fromtaskflow→taskflow — Declarative DAG Orchestration for Coding Agents(title is the feat: make built-in agents configurable via /tf init #1 on-page factor); split out abrandfield so subpages keep the shortX | taskflowtemplate.homepagetotaskflow-hosts/package.json.New content (long-tail, high-intent — the unwinnable generic "taskflow" keyword strategy):
comparisons/):taskflowvs imperative workflows, vs built-in subagents, vs LangGraph — theseX vs Yqueries have high intent and low competition.blog/): orchestrate Codex subagents, Claude Code + MCP workflow, what-is-a-task-graph.Also done via
gh(already live, not in this diff): repohomepageUrl, description (all 4 hosts), topics (+claude-code, +opencode, +mcp).After merge
deploy-websiteruns → live site gets the verification tag.https://heggria.github.io/taskflow/sitemap.xml.Screenshots / TUI output
N/A (docs site only).