fix: close dogfood reliability issues 1–8#75
Merged
Conversation
…rompt diagnostics + tree reduce
Implements dogfood reliability issues 1, 3, and 7.
BREAKING — reduce.from + {previous.output} now aggregates all sources
(0.2.0 dogfood issue 1):
- A reduce phase's {previous.output} resolves to ALL completed from[]
outputs in from-array order — not just the last completed dependency.
One completed input → raw output; multiple →
sections joined by . join:any includes only completed
branches (skipped/failed omitted). Explicit {steps.*} refs unchanged.
- Observed reads include the aggregated from IDs (staleness tracks them).
- Imperative + event-kernel parity: executeReduceBody now threads the
aggregated previousOutput via interpCtx, mirroring aggregateReduceFrom.
Configurable idle watchdog (issue 2):
- New flow-level + phase-level DSL field (ms). Positive
(>= 1000) overrides the host default (300000); disables the
watchdog but validation requires a finite wall >= 1000 on
every agent-running phase that can use it. Per-phase overrides flow.
- Threaded into RunOptions.idleTimeoutMs on both imperative and
event-kernel paths (runAgentCall + runOneAgent). runSubagentProcess
+ the pi runner already honor idleMs<=0 as disabled.
- Included in cache identity/fingerprints automatically via the FlowIR
definition hash: idleTimeout/reduceStrategy/batchSize added to
compile.ts SIDECAR_PHASE_FIELDS; flow-level idleTimeout added to the
CanonicalFlowIR type + canonicalizeFlowIR + translate stub.
Prompt diagnostics + hierarchical (tree) reduce (issue 3):
- Durable PhaseState.promptStats for each agent call's resolved prompt:
exact UTF-8 bytes, char count, ceil(chars/4) estTokens. A warning
fires when a prompt crosses a conservative ~32K-token threshold.
reduce phases also record reduceInputs aggregate stats (count + totals).
- Opt-in reducer tree via reduceStrategy:"tree" + batchSize (>= 2):
batches aggregated from[] inputs, runs intermediate reducer calls
reusing the phase's runOne (same agent/model/options/timeout/
idleTimeout + retry/budget), reduces round outputs until one remains.
Default remains one-shot; corrected {previous.output} always applies.
- reduceStrategy:"tree" forces imperative fallback (encoded in
kernelUnsupportedReason); one-shot reduce stays on the kernel.
- Event-kernel parity: promptStats + reduceInputs mirrored on the
StepResult/BodyResult → driver → PhaseState path.
Docs:
- skills-src configuration.md + core.md updated (reduceStrategy/
batchSize/idleTimeout rows; {previous.output} aggregation note).
- website interpolation docs (en + zh) updated with the breaking
reduce aggregation semantics.
- build-skills regenerated all per-host skill files (drift guard green).
- CHANGELOG: prominent migration note for the reduce.from + {previous.output}
breaking change, plus Added entries for the three features.
Tests: 28 focused tests in dogfood-reliability.test.ts covering all
three categories (reduce aggregation + parity, idleTimeout validation/
threading/cache-identity, prompt diagnostics + tree reduce + kernel
admission). FlowIR hash sensitivity tests extended for the new fields.
Typecheck + full core suite green (3 pre-existing flaky tests unchanged).
…put source attribution Implements dogfood reliability issues 2, 4, 5, 6, and 8 (first-run trace regression). Builds on the already-shipped reduce/idle/tree-reduce work (issues 1, 3, 7) without reverting it. Issue 2 — shorthand cwd: - Top-level + per-step `cwd` for shorthand specs (single / chain / parallel). Single+chain propagate to each Phase.cwd (full workspace-keyword lifecycle). Parallel honors each branch's own literal cwd (mixed values across branches); per-branch workspace keywords are rejected at validation time (the workspace lifecycle is per-phase — use the phase-level cwd). - New ParallelTask.cwd field; runFanout/baseRun/runOne thread a per-call cwd override so a branch runs in its own literal cwd. - Pi tool TypeBox params + desugar/readStep carry cwd; skills + tests updated. Issue 4 — version/build/host identity: - New exported getBuildInfo() (packageVersion, gitCommit, schemaVersion, buildTime). Package version read from package metadata; git commit stamped at BUILD time into dist/build-info.json (gitignored) — git is NEVER invoked at runtime (deterministic "unknown" fallback; PI_TASKFLOW_BUILD_COMMIT env override). New scripts/stamp-build-info.mjs wired into the core build. - RunState gains optional packageVersion/gitCommit/host/schemaVersion/ parentRunId; index entries preserve host/packageVersion/parentRunId. - Pi runs stamp host=pi; MCP runs stamp the bound host. Pi action=version + MCP taskflow_version tool; MCP initialize serverInfo name reflects the host (taskflow-codex, …). Host adapters thread host via a backward-compatible McpHostOptions. Issue 5 — resume overrides + immutable history: - Resume now FORKS a new run (new runId + parentRunId); the original run file is never mutated or overwritten. ResumeOverrides API (phaseId + optional task/model/timeout/idleTimeout; at least one override required) re-runs exactly one phase with overrides applied to the CHILD's def only; the target + transitive downstream re-run, completed unaffected phases are reused. Without overrides, ordinary resume forks + re-runs non-done phases. - Pure helpers (forkRunForResume/applyResumeOverrides/validateResumeOverrides/ transitiveDownstream) in taskflow-core/resume.ts. Pi action=resume accepts phaseId + resumeTask/resumeModel/resumeTimeout/resumeIdleTimeout; new MCP taskflow_resume tool; resume rendering reports new run id + parent run id. Issue 6 — output source attribution: - RuntimeResult/EventKernelResult gain outputSourcePhaseId (the phase whose output supplied finalOutput — the fallback final phase, or the blocking gate/approval phase for a gate/budget prefix; undefined when no phase output). Final-phase selection/fallback + no-output default unified between the imperative runtime and the event kernel via shared resolveFinalOutput (taskflow-core/final-output.ts). Pi finalResult + MCP taskflow_run/resume rendering label the ACTUAL source phase, never the designated skipped/failed final phase. Issue 8 — first-run trace regression: - New integration test: FileTraceSink built before the runs dir exists, a first run executes, and the trace is immediately readable + non-empty. Docs: CHANGELOG, README, AGENTS.md, and skills-src (cwd/resume/version) + regenerated per-host skills. Tests: +6 focused suites (output-source-attribution, shorthand-cwd, build-info, resume, trace-firstrun; updated all four host MCP tests for the new taskflow_version + taskflow_resume tools and host-identity serverInfo). Full suite 1685 pass; typecheck clean.
Close event-kernel parity gaps, make prompt diagnostics count every actual subagent attempt, harden tree-reduce interruption handling, and validate immutable resume forks.\n\nAdd release-build and packed-artifact guards for deterministic build metadata, portable Pi declarations, and host-specific MCP identity.
Harden budgeted fan-out, tree-reduce caching and context spawning, resume overrides, build metadata, and host discovery surfaces. Add regression coverage and synchronize the 0.2.2 release documentation.
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.
Summary
Closes all eight reliability gaps found while dogfooding taskflow 0.2 across the core runtime, event kernel, Pi adapter, MCP adapters, release artifacts, tests, and generated skills.
Core behavior
reduce.from+{previous.output}aggregate every completed source in deterministicfrom[]orderidleTimeoutwith the0 = disabled only with finite wall timeoutsafety invariantcwd, including containment and workspace-binding hardeningserverInfo.nameoutputSourcePhaseIdselected by final-output fallback logicReliability hardening
SOURCE_DATE_EPOCHor immutable commit time) and valid plain JavaScriptCompatibility notes
reduce.from+{previous.output}now receives all completed sources. Use explicit{steps.ID.output}refs when a reducer should consume only one source.failedandpausedruns. Use a fresh run for terminal work orrecomputefor stale-frontier refresh.serverInfo.namemust accepttaskflow-codex,taskflow-claude,taskflow-opencode, ortaskflow-grokfor the corresponding adapter.Validation
pnpm run typecheckpnpm test— 1887/1887 passedpnpm run buildnode scripts/smoke-packed-packages.mjs— 9 packages, 24 explicit imports, 63 wildcard exports, 5 binspnpm run build:website— docs/sample/typecheck/static-export checks passednode scripts/build-skills.mjs --checkgit diff --checkLive-provider E2E suites were not invoked locally; all corresponding host metadata assertions and packed MCP binary checks were updated and passed.