Coverage extractor now respects shell redirection. Closes #40.
dippin coverage no longer flags file-redirected echo/printf statements as uncovered tool outputs. The extractor switched from regex matching to an AST walker built on mvdan.cc/sh/v3/syntax.>, >>, &>, >&), feed into pipes, or are nested inside command substitution are now correctly skipped. Pipelines using the “log to file, printf marker on stdout” pattern flip from partial to covered.Three follow-ups to v0.28.0’s tool-routing surface. Closes #42, #43, #44.
DIP138 reserved for a future advisory: “tool node routes on stdout but declares no marker_grep / outputs”. Code + description + explanation entry only; no firing logic in this release.outputs: now survives a .dip → DOT → .dip round-trip. DOT export emits outputs="a,b,c" on tool nodes that declare outputs, and dippin migrate dot→.dip reads it back.DIP101 / DIP102 no longer fire on tool nodes that declare marker_grep:. Those nodes route via the typed ctx.tool_marker channel — outgoing conditional edges on them are intentional routing, not unsafe reachability. Removes the false-positive coverage hit that tracker’s TRK101 option (d) guidance triggered.goal_gate, auto_status, cache_tools, route_required) now accept true/false, 1/0, yes/no, on/off case-insensitively via a new shared parseBoolAttr helper. Anything else now produces a parse diagnostic instead of silently coercing to false. The migrate (DOT-input) path keeps strict equality since DOT attrs are machine-emitted.None. All changes are dippin-internal; tracker is unaffected.
docs/nodes.md “Markers and Verbose Output” notes the DIP101/DIP102 suppression and the accepted boolean forms.docs/llm-reference.md common-mistakes table cross-references the suppression behavior.site/static/skill.md) updated to match.Tool-node routing fields land in the parser and IR. Authors following tracker’s TRK101 recommendation can now declare marker_grep, route_required, and output_limit directly in .dip source. Closes #39.
tool.marker_grep — regex matched line-by-line against captured stdout; populates ctx.tool_marker at runtime.tool.route_required — boolean; when true, the node fails with EventToolRouteMissing if the command emits no _TRACKER_ROUTE=<value> sentinel line.tool.output_limit — non-negative integer (bytes); 0 uses the engine default stdout tail-window. dippin fmt omits the field when the value is zero.ctx.tool_marker, ctx.tool_route.migrate/parity.go compareToolConfigs now compares all ToolConfig fields. Pre-existing Timeout / Outputs parity gaps backfilled.These fields pass through DOT export to tracker. Routing semantics require tracker to ship the matching extractToolAttrs change; see issue #39 for details.
site/content/blog/whats-new-v028.md.docs/nodes.md gains a “Best” subsection in Markers and Verbose Output demonstrating marker_grep.site/static/skill.md) updated with new context variables and best-practice bullet.Model catalog and pricing verification pass against canonical provider docs. Last verified: 2026-05-18 in validator/lint_model.go and cost/pricing.go. No breaking changes to public APIs — but the cost table values move and the catalog accepts new IDs, so downstream tooling that snapshots dippin’s data should re-snapshot.
gpt-5.5, gpt-5.5-pro, gpt-5.4-pro, gpt-5.2-pro, gpt-5, gpt-5-pro, gpt-5-mini, gpt-5-nano.grok-4.3 ($1.25/$2.50, current flagship).deepseek-v4-flash ($0.14/$0.28), deepseek-v4-pro ($1.74/$3.48 list — 75% launch discount through 2026-05-31).gemini-3.1-flash-lite (GA promotion of the preview variant, same price).mistral-medium-3-5-2604 ($1.50/$7.50, new flagship-class), mistral-medium-3-1-2508 ($0.40/$2.00), Ministral 3 generation (ministral-3-3b-2512 $0.10/$0.10, ministral-3-8b-2512 $0.15/$0.15, ministral-3-14b-2512 $0.20/$0.20).command-r-08-2024, command-r-plus-08-2024, command-r7b-12-2024 (the canonical recommended form; bare aliases kept callable but flagged as resolving to versions deprecated 2025-09-15).gpt-5.2 $0.875/$7 → $1.75/$14, gpt-5.1 $0.625/$5 → $1.25/$10, gpt-4.1-mini $0.20/$0.80 → $0.40/$1.60. Newer mini/nano tiers and the o-series held steady.grok-4.20-0309-reasoning, grok-4.20-0309-non-reasoning, grok-4.20-multi-agent-0309 all $2/$6 → $1.25/$2.50, matching grok-4.3’s tier.deepseek-chat and deepseek-reasoner are compatibility aliases resolving to V4-Flash; priced at $0.14/$0.28 (down from $0.28/$0.42) to match the redirect target.claude-haiku-3-5 repriced to $0.80/$4.00 (Bedrock/Vertex passthrough rate; was $0.25/$1.25 in the catalog). Model was retired on the first-party API 2026-02-19; remains available via Bedrock and Vertex AI.Hard-retired models that the provider returns errors for — calling them is a real bug, DIP108 surfaces:
pixtral-large (deprecated 2026-02-27), mistral-small-3.2 (deprecated 2026-04-30, past sunset).gemini-3-pro-preview (shut down 2026-03-09).Soft-retired models that the provider silently redirects (kept in the catalog, priced at the redirect target so cost analysis stays accurate):
grok-4-1-fast-reasoning and grok-4-1-fast-non-reasoning (retired 2026-05-15; xAI redirects to grok-4.3 server-side and bills at grok-4.3 rates).Still in the catalog with deprecation comments:
gemini-2.0-flash.claude-sonnet-4-0, claude-opus-4-0.deepseek-chat, deepseek-reasoner aliases.gpt-4o, gpt-4.1-nano, o3-mini, o4-mini.Inline comments in cost/pricing.go flag values held pending re-verification:
nemo and mistral-small-2603: official pricing tab is JS-rendered; third-party sources conflict.command-a-03-2025 and command-r7b-12-2024: per-token pricing removed from the public page.site/content/blog/whats-new-v027.md covers the refresh.site/content/blog/whats-new-v026.md retrospective on the v0.26 requires: keyword.related: cross-references updated.requires: keyword. New optional workflow-header field for declaring workflow-level prerequisites (e.g., tools, MCP servers, env vars) as a comma-separated identifier list. Advisory in v1 — parsed, round-tripped by the formatter, and exposed as ir.Workflow.Requires []string, but not yet validated by lint. Mirrors the shape of node-level reads: / writes:. Filed from tracker’s git-preflight design to unblock the --git= preflight mechanism. Canonical formatter order is goal → requires → start → exit. Editor support (tree-sitter, VS Code, Zed) and the hosted skill (site/static/skill.md) updated..dipx format v1.1. The spec at docs/superpowers/specs/2026-05-06-dipx-bundle-format-design.md is the canonical contract; this release closes ambiguities in it (Bundle 6), brings the implementation in line with the documented contract, and adds genuine cancellation through Pack/Open hot paths.
Breaking changes for downstream consumers (Tracker, etc.):
Source.Workflow now takes context.Context as its first argument. Bump your dippin-lang import via go install [email protected] (or @latest) and update call sites.dippin inspect --format=json status field is now an object, not a bare "VALID" string. If you parse the JSON in scripts, decode status as an object with valid, verify_skipped, file_count, byte_total, format_version.dipx.Open previously DFS’d the ref graph rooted only at m.Entry, while parseAllWorkflows already parsed every manifest-listed workflow. A cycle in a manifest-listed-but-entry-unreachable workflow could slip through. walkRefs now iterates detectCycles over m.Files. (Bundle 6 / Phase 5 L2/L3.)dippin pack/unpack/inspect exit code 2 (integrity failure) now matches the spec contract. isIntegrityErr previously routed only 5 sentinels to exit 2; 7 others (ErrUnsupportedFormatVersion, ErrFileMissing, ErrFileUnexpected, ErrEntryNotInManifest, ErrRefEscape, ErrRefCycle, ErrCapExceeded, ErrPathUnsafe) defaulted to user-error 1. Refactored to a sentinel-slice + loop covering all 12 spec-enumerated sentinels. (Bundle 6 / Phase 8 M1.)Open enriches manifest-decode errors with the bundle path. BundleError.Path for ErrManifestInvalid and ErrUnsupportedFormatVersion was previously empty or a JSON field name (e.g., "format_version"); external callers now always observe the bundle file path. The original Path is preserved in Detail when non-empty. (Bundle 5 / Phase 3 manifest-decoder error-context.)Pack subgraph parse failures attribute to ErrSubgraphParse. Previously every parse failure surfaced as ErrEntryParse regardless of which workflow failed; subgraph failures now correctly classify as ErrSubgraphParse with the subgraph’s filesystem path. (Bundle 5 / P10.9.)dippin inspect emits a structured status object. JSON output’s status was previously a bare string "VALID"; it is now an object with valid, verify_skipped, file_count, byte_total, format_version per spec § “CLI / inspect command”. Text footer now includes the byte total. Breaking for JSON consumers parsing status as a string. (Bundle 2 / Phase 8 M4, L1, L2.)dippin inspect --no-verify actually skips hash verification. Previously a no-op (warning printed, full verification still ran). Now routes through a new dipx.OpenManifest API that performs only structural-admission steps; tampered bundles can be inspected without integrity errors firing. (Bundle 2 / Phase 10 P10.4.)Source.Workflow now takes context.Context as its first argument. dirSource.Workflow checks ctx before disk I/O; Bundle.Workflow checks ctx at entry for interface consistency. Breaking for external callers (Tracker) — bump your dippin-lang import to pick up the new signature. (Bundle 1 / Phase 6 L4.)Open and Pack are cancellable mid-loop. verifyAllHashes, walkSourceTree, and writeBundle now check ctx.Err() between each entry/iteration. A long Open against a many-entry bundle or a long Pack against a deep source tree can be canceled within one entry’s processing time instead of running to completion. (Bundle 1 / Phase 10 P10.2, P10.7, P10.10.)Seven .dipx bundle-format spec clarifications (no behavior change beyond the two Fixed items above). Each is described in detail in the per-commit messages on this branch.
\ MUST be rejected” (was “Backslash \ and any other separator…”). The implementation already rejects only backslash; the spec wording was over-broad.BundleError.Path semantics across three real cases: bundle-relative (read-side, post-Open), JSON field name (manifest decode pre-bundle-context), source filesystem path (Pack-side). Spec now requires Open to enrich (b) → (a) before returning.ErrFileUnexpected added to the error precedence list at category 4.parseAllWorkflows.inspect --format=json status object schema documented with a concrete JSON example (valid, verify_skipped, file_count, byte_total, format_version).Source.Workflow(ctx, sub.Ref, parentPath) (was missing ctx). Bundle 1 will land the matching Go signature change..dipx bundle format — deterministic, content-addressed ZIP that packages a .dip entry workflow plus every transitively-reachable subgraph into a single integrity-verified artifact. Bundles carry a SHA-256-per-file manifest and a workflow-tree identity hash; integrity is verified on every Open. New package dipx/ exposes Open, OpenLax, OpenReader, Pack, Extract, Validate, and Load, plus the Source interface (Entry, Workflow) for runtime consumers like Tracker.dippin pack <entry.dip> (build a bundle, with -o, --dry-run); dippin unpack <bundle.dipx> (atomic extract via staging + rename, with -o, --force); dippin inspect <bundle.dipx> (print manifest, identity hash, file list; --format text|json)..dipx — validate, lint, doctor, parse, cost, coverage, simulate, optimize, unused, graph, diff, check, explain, export-dot now transparently load a .dipx via dipx.Load, hash-verify it, and analyze the entry workflow.0 (ok), 1 (user error), 2 (integrity error), 3 (I/O error), 4 (cancelled).dipx may import ir + parser + simulate but is forbidden from importing validator, cost, formatter, or any other analysis package. Pack-time structural validation runs at the CLI layer (cmd/dippin/cmd_pack.go).Extract --force no longer destroys the existing destination directory when the staging-into-place rename fails on a cross-device boundary (EXDEV). The new backup-aside / rename-into-place / remove-aside sequence preserves the original on failure.Pack rejects symlinked parent directories anywhere between the entry’s source root and a leaf .dip, closing a host-file exfiltration vector when packing untrusted source trees (CI-runner contributor builds, mono-repo subdirs).Pack’s ref-escape check no longer false-positives on legitimate filenames whose component name begins with .. (e.g., ..foo/bar.dip). The check now requires the literal .. component, not a .. substring.dippin pack -o foo.dipx no longer races two parallel invocations against the same temp filename — uses os.CreateTemp for a unique staging path.golang.org/x/text from v0.3.3 to v0.37.0 (defensive — only unicode/norm is consumed; the v0.3.3 CVEs were in x/text/language).WorkflowDefaults tool-safety fields (tracker#164 / tracker#169): tool_commands_allow (glob allowlist for tool-node shell commands) and tool_denylist_add (globs appended to tracker’s default denylist). Both round-trip through parser → formatter → DOT export → migrate. Values pass through verbatim — tracker owns split and glob semantics. (#28)ExportDOT now emits graph-level attributes (rankdir, tool-safety defaults, workflow vars) as a single graph [key=val, ...]; block instead of separate bare statements (rankdir=TB;). This is the form the migrate DOT parser accepts, enabling true .dip → DOT → .dip round-trips. The output remains valid DOT; consumers that only render via Graphviz are unaffected.tool_commands_allow / tool_denylist_add in vars: no longer emitted — before this release, these keys weren’t reserved, so a workflow that smuggled them through vars: would have them emitted as graph attributes. They are now reserved in favor of the dedicated defaults: fields. Any workflow that previously set either key via vars: should move it into defaults:; otherwise the value is silently dropped from DOT output (tracker would see no allowlist). This path was never documented — issue #28 filed specifically because defaults: rejected the keys — so the affected population is expected to be zero, but calling it out explicitly for anyone who found the workaround.manager_loop node kind for supervising a child sub-pipeline with polling and mid-run context steering. Maps to Tracker’s stack.manager_loop and DOT shape=house. Fields: subgraph_ref, poll_interval, max_cycles, stop_condition, steer_condition, steer_context (inline k=v,k=v or block form). Round-trips losslessly through parser → formatter → DOT export → migrate. Requires the parallel Tracker adapter update in tracker#162. (#26, #27)manager_loop validation: missing/nonexistent subgraph_ref (DIP135), invalid control field — negative poll_interval or max_cycles (DIP136), unbounded supervision with no stop_condition and no max_cycles (DIP137 — the manager_loop analog of DIP104).stack.* namespace recognized by DIP120 so stop_condition and steer_condition can reference stack.child.cycles, stack.child.outcome, stack.child.status without namespace warnings.dippin scaffold manager_loop template emits a starter supervisor workflow.manager_loop node rule, highlights coverage, corpus test, committed generated parser (src/parser.c et al.), new just tree-sitter-generate / just tree-sitter-test recipes, and CI drift check so generated files can’t drift from grammar.js without being caught.manager_loop keyword, new field names, stack.* namespace recognition.steer_context block-form routing — a single-entry block-form steer_context (one k: v line under the indent) lexes without an embedded newline; the previous newline-based heuristic mis-routed it to the inline CSV handler. Replaced with a separator-position check (: before = means block, = before : means inline).HumanConfig.Timeout / TimeoutAction on human nodes (tracker#112). Pairs with edge labels like when: timeout for auto-advance semantics. Round-trips through parser, formatter, DOT export, and migrate. (#22)WorkflowDefaults budget fields (tracker#67): max_total_tokens, max_cost_cents, max_wall_time. Allow workflows to declare global budget caps consumed by the runtime. (#22)ctx.node.<id>.* now validates as a legitimate read pattern in DIP121/DIP122, eliminating lint false-positives for cross-node state access (tracker#75). (#23).well-known/agent-skills/index.json, .well-known/mcp/server-card.json, .well-known/api-catalog, robots.txt, and hosted skill.md. Lets coding agents auto-discover dippin-lang tooling. (#24)reasoning_effort expansion — DIP119 now accepts none, minimal, low, medium, high, xhigh, and max to cover Opus 4.7 and GPT-5.4.claude-opus-4-7 (Anthropic, $5/$25), mistral-small-2603 (Mistral Small 4), command-a-03-2025 (Cohere flagship, $2.50/$10).conditional node kind and vars section introduced in v0.20.0.claude-haiku-3-5 deprecation comment corrected — retired 2026-02-19, not 2026-04-19.vars block at the workflow level for declaring user-defined variables. Vars export as DOT graph-level attributes and round-trip through parse → format → export → migrate.max_retries is set in defaults with restart: true edges but no max_restarts — catches the common confusion between per-node LLM retries and loop restart budget.releasecheck/) — validates the embedded spec is tracked, current, and buildable from a source tree without .git.mvdan.cc/sh/v3. Variable assignments, command substitutions, and command -v checks are now correctly identified. Preamble commands (mkdir) are skipped to find the real tool binary.go install ...@latest broken — cmd/dippin/generated-spec.md is now checked into the repo so the go:embed directive resolves from module proxy downloads.just check now mirror CI exactly — spec freshness, release checks, complexity exclusions all aligned.working_dir field on agent nodes for per-node working directory override (e.g., .ai/worktrees/claude). Wired through parser, formatter, DOT export, and migrate.backend field on agent nodes for per-node backend selection (e.g., native, claude-code, acp). Previously this value was silently dropped by the parser.working_dir field on agent nodes for per-node working directory override.params:, instead of being silently discarded.flatten package for resolving subgraph refs into flat workflows. Recursive resolution with cycle detection and configurable depth limit (default 10). Underscore-prefixed node IDs (Parent_Child).dippin export-dip command — exports a flattened workflow as canonical .dip text with all subgraph refs inlined.dippin export-dot now automatically flattens subgraph refs before export, producing valid DOT without external references.orchestrator.dip (parent with subgraph ref) and phases/code_review.dip (child workflow).TestLintExamples now recurses into examples/*/ subdirectories.Start/Exit fields are now correctly remapped when they point to inlined subgraph nodes.flatten.Flatten returns a clear error instead of panicking when the resolver is nil but subgraph refs are present.export-dot error rendering — flatten errors now use renderError for JSON output consistency.conditional node kind for pure branching without LLM calls. Evaluates outgoing edge conditions only — no prompt, no token cost. Maps to diamond shape in DOT export. DOT migration auto-detects: bare diamond → conditional, diamond + prompt → agent, diamond + tool_command → tool.--extra-models CLI flag on lint and doctor commands. Extends the DIP108 model catalog at runtime for private or newly-released models. Format: --extra-models "provider:model1,model2;provider2:model3".[label: ...]) now emits a clear parse error with a hint to use when/label: keyword syntax, instead of silently discarding annotations.retry blocks now emit a clear parse error suggesting flat attributes (retry_policy, max_retries, retry_target, fallback_target, base_delay), instead of a confusing indent mismatch error.response_format: force LLM to produce structured JSON output (json_object or json_schema)response_schema: inline JSON Schema definition (multiline block, like prompt:)params: generic key-value pass-through for runtime features (same syntax as subgraph params)response_format value.response_schema is set without response_format: json_schema (schema ignored); hint when json_schema is set without a schema.response_schema is not valid JSON.params key shadows a first-class field (e.g., model, provider).cmd_timeout field now parsed and formatted on agent nodes (previously only populated by DOT migrator).AgentConfig.Params initialized to empty map (matching SubgraphConfig), preventing nil-pointer issues in downstream consumers.mode: interview). Runtimes extract questions from upstream agent output and present each as an individual form field with optional suggested answers. New fields: questions_key, answers_key.default value.api_design.dip example updated to use interview mode for Q&A collection.interview_loop.dip example: reusable interview subgraph with iterative Q&A. Parameterized by topic and focus areas. LLM generates questions with suggested options, human answers via interview mode, assessor loops until requirements are clear. Grade A, ~$0.92/run.site/ to GitHub Pages on successful main builds.--version / -version flags now work (previously failed with “flag provided but not defined”)."API design") were double-quoted on each format pass. Parser now strips surrounding quotes from param values.code_health_check.dip example: self-contained pipeline that audits a Go repo. Gathers context with shell tools, runs vet/staticcheck/tests in parallel, three-model independent review, synthesized report with quality gate and retry loop. 5 test scenarios. Grade A, ~$1/run.site/_layout/nav.html is the one source of truth. scripts/sync-nav.sh propagates it to all 16 pages with correct prefixes and active states. Pre-commit hook runs it automatically. No more editing nav in 16 files.scripts/gen-changelog-html.sh emits a placeholder nav that sync-nav.sh fills.just sync-nav recipe added.just install and just build now inject commit hash and build timestamp via ldflags. dippin version shows dev (commit: abc1234, built: 2026-03-27T18:45:10Z) instead of dev (commit: none, built: unknown).display: none)..tracker/field-report-response-2026-03-27.md).docs/blog-ideas.md) with 25 post synopses, coverage plans, and approach notes.<pre> overlay. Tab key inserts 2 spaces.[] not null for zero diagnostics.pre .hl-* to .hl-* so colors work in playground output div, not just <pre> blocks.compare-code divs (like gate.test.json on Testing page) now get highlighted — skip logic checks for existing <span> tags instead of parent class.\x00N\x00 placeholders prevents regex passes from matching inside previously generated <span> class attributes.$ dippin --format json test) gets JSON highlighting applied to the embedded body.scripts/gen-changelog-html.sh. Pre-commit hook runs it when CHANGELOG.md is staged.dippin.wasm, wasm_exec.js) now deployed to gh-pages so the playground actually loads.highlight.js) for all code blocks — Dippin, shell, terminal, and diagnostic output.changelog.html with full version history.ref: file validation — warns when referenced workflow file does not exist on disk.dippin watch command: file watcher that re-runs lint on .dip changes with 200ms debounce. Uses fsnotify.dippin test --coverage flag: edge coverage summary showing which workflow edges were/weren’t traversed by test scenarios.editors/tree-sitter-dippin/ — grammar.js, external scanner for indentation, highlight queries, and test corpus. Enables proper syntax highlighting in Neovim, Helix, and Zed.site/playground.html — browser-based editor with live parse, lint, and format via WebAssembly. Build with just wasm.gemini-3.1-pro-preview-customtools added to model catalog and pricing tables.errcheck on f.Close(), funlen on buildLintExplanations (split into 4 functions), misspell false positive in DIP118 example.consensus_task_parity.dip and semport_thematic.dip model names now match DOT originals (gemini-3.1-pro-preview-customtools).validator/lint_tool_cmd.go split with //go:build !wasm / wasm tags — bash -n syntax check and exec.LookPath binary check are no-ops in WASM.validator/lint_subgraph.go similarly gated for WASM (no os.Stat).docs/validation.md — full entry for DIP126.docs/cli.md — watch command section, test --coverage flag.docs/editor-setup.md — tree-sitter grammar availability.dippin explain DIP126 — explanation with trigger and fix guidance.mode: labeled documented as not supported in docs/nodes.md.bash -n.${ctx.*} references in tool commands that expand to empty at runtime.docs/validation.md — full entries for DIP123, DIP124, DIP125.dippin explain DIP123/DIP124/DIP125 — explanations with triggers and fix guidance.preferred_label now works on human gates — scenario key preferred_label (or per-node Gate.preferred_label) matches against edge labels (case-insensitive substring). Previously silently ignored on freeform gates.prompt: blocks now parse on human nodes — HumanConfig gained a Prompt field. Multiline prompt blocks work the same as on agent nodes. Formatter round-trips correctly."Node.tool_stdout": "") now suppress the auto-seeded success default, allowing unconditional fallback edges to fire.immediately_after test assertion — assert adjacency in the execution path: "immediately_after": {"NodeX": "NodeY"} checks that NodeY is the very next node after NodeX.branch field for targeted parallel testing — "branch": ["WorkerA"] limits which parallel fan-out branches are simulated. Without it, all branches are walked (new default)..test.json files for vulnerability_analyzer, consensus_task, code_quality_sweep, and sprint_exec (20 tests across 4 workflows).just cover now excludes untestable files (main.go, cmd_lsp.go) from coverage reports.docs/testing.md — added Caveats section (not_visited fragility with loop-breaking), Clearing Defaults section (empty-string technique), immediately_after field documentation.buildAdjacency() included restart (back) edges, creating cycles that prevented Kahn’s algorithm from assigning layers to downstream nodes. All nodes are now rendered. Affects both full and compact modes.when ctx.tool_stdout not contains all-done loops would spin to the 500-step limit. New MaxNodeVisits option forces the loop-exit edge after N visits. The test runner sets this to 3 by default.dippin test — NodeName.key=value scenarios now work reliably because the loop-breaking fix allows the simulation to reach the target node.LoadTestFile now rejects .test.json files with zero tests.cmd/dippin coverage: 44.9% → 79.3%.and/or conditions correctly fire per-variable.just release tag msg recipe for tagging releases.explain, unused, graph, test added to commands table.appendConnector dead branch — identical if/else branches collapsed.dippin test — scenario test runner for workflow assertions. Define .test.json files alongside .dip workflows with expected status, visited/not-visited nodes, and path ordering. Supports --verbose flag for path tracing and JSON output for CI integration.testrunner/ — loads .test.json suites, runs each case through the simulator with injected scenario values, checks assertions against results.docs/testing.md — documents the .test.json format and test runner usage.IO.Writes. Skips when writes are empty (advisory) or variable is a reserved runtime key (ctx.outcome, ctx.status, ctx.internal.*, graph.*, params.*).ToolConfig.Outputs. Only fires for tool nodes with explicitly declared outputs.dippin explain.dippin explain <DIPxxx> — rich explanations for all 34 diagnostic codes. Shows trigger conditions, fix guidance, and example snippets. Supports text and JSON output.dippin unused <file> — detects dead-branch nodes (reachable from start but no path to exit) and estimates wasted cost per run. Reuses coverage.Analyze() sink detection + cost.Analyze() for cost enrichment.dippin graph [--compact] <file> — terminal-rendered ASCII DAG visualization. Full mode renders box-drawing nodes with connectors; compact mode outputs single-line [A] → [B] → [C] format. JSON mode outputs layer structure.unused/, graph/, testrunner/validator/explanations.go with Explanation struct for all DIP codes.{success, fail} pairs. Handles done/more_questions, tasks_remain/all_done, and any custom value set.outputs field, removed undocumented numeric operators (<, >, <=, >= parsed but silently returned false)state.* namespace (not implemented), removed ctx.preferred_label (not in codebase), added == as = alias, added not contains infix syntax<, >, <=, >= from valid operators (never evaluated, silent false was a trap)CHANGELOG.md with retroactive history for all versionsdocs/CONTRIBUTING.md — documentation accuracy protocol with persona matrixCLAUDE.md — project conventions, gotchas, versioning policyTestLintExamples) — lints all examples through real parseroutputs field documented in nodes.md and README.mddippin cost, dippin coverage, dippin doctor, dippin optimize, dippin diff, dippin feedback, dippin lspvar not contains val)contains X + not contains X recognized as exhaustivedocs/analysis.md, docs/editor-setup.mdLint() now calls EnsureConditionsParsed() before running checkscontains X / not contains X as overlappinggemini-3-pro → gemini-3.1-pro-preview, removed nonexistent IDs<br> instead of <br/>dippin cost and dippin coverage commandsdippin check, dippin new commands with 5 scaffold templatesbase_delay field for retry overridedippin version command