Mythify Design Specification

August 4, 2026 ยท View on GitHub

This document is the single source of truth for Mythify's contracts: the CLI command surface, the MCP tool surface, the on-disk state formats, and the output conventions. The Python CLI (scripts/mythify.py) and the MCP server (mcp-server/src/index.js) are independent implementations of the same contracts and must interoperate on the same state directory.

Goals

  1. Real verification. Completion claims are checked by executing commands and reading exit codes, not by self-report. Self-attested claims are allowed but are recorded and displayed as second-class evidence.
  2. Per-project state. Each project owns a .mythify/ directory. The only global state is the cross-project lessons store.
  3. Proportional ceremony. Protocol overhead scales with task size. Trivial tasks pay zero overhead.
  4. Durability. Atomic writes, corrupt-file recovery, and no crashes on bad state.

Writing rules (every file in this repository)

  • No emojis. Use ASCII markers: [OK], [FAIL], [WARN].
  • No em dashes (U+2014) and no en dashes (U+2013). Use commas, colons, parentheses, or plain hyphens instead.
  • No pending-work markers, no placeholder content. Every file ships complete.
  • Documentation is imperative and concise.
  • Exception: docs/research-report.md is preserved legacy content, copied verbatim, and is exempt from these character rules.

Repository layout (contract-bearing files)

This tree names the public contract files and load-bearing runtime boundaries. It is not an exhaustive inventory of every helper or test file.

mythify/
|-- README.md
|-- LICENSE                      MIT, holder "Mythify contributors", year 2026
|-- .gitignore
|-- CLAUDE.md                    generated from protocol/PROTOCOL.md
|-- AGENTS.md                    generated from protocol/PROTOCOL.md
|-- .cursorrules                 generated from protocol/PROTOCOL.md
|-- protocol/
|   |-- PROTOCOL.md              canonical protocol source
|   |-- classification-rules.json deterministic classifier keywords
|   |-- model-capabilities.json  shared model profile and provider mappings
|   |-- operation-registry.json  shared operation metadata
|   |-- release-gates.json       exact-command release readiness gates
|   |-- workflow-router.json     shared workflow route metadata
|   `-- surface-manifest.json    shared public surface metadata
|-- scripts/
|   |-- mythify.py               zero-dependency CLI orchestrator
|   |-- mythify_classification.py deterministic classification helper
|   |-- mythify_evidence_guard.py advisory evidence-quality guards
|   |-- mythify_godfiles.py      godplans PLAN.mdx and godaudits AUDIT.mdx reader
|   |-- mythify_host_model.py    host model switch record helper
|   |-- mythify_io.py            durable IO helper
|   |-- mythify_log_compaction.py verification-log compaction helper
|   |-- mythify_loopfit.py       loop-worthiness analysis helper
|   |-- mythify_map_parser.py    wayfinding map subcommand parser
|   |-- mythify_maps.py          wayfinding decision map store and gates
|   |-- mythify_memory.py        memory and lesson helper
|   |-- mythify_model_policy.py  model policy and triage helper
|   |-- mythify_model_routing.py provider-neutral topology and review helper
|   |-- mythify_outcomes.py      outcome loop helper
|   |-- mythify_parser.py        CLI argument parser construction
|   |-- mythify_plan_import.py   godplans and godaudits plan import helper
|   |-- mythify_protocol.py      protocol handshake and frozen-manifest checks
|   |-- mythify_provenance.py    verification provenance helper
|   |-- mythify_router.py        prompt packet and workflow route helper
|   |-- mythify_runtime_helpers.py shared CLI runtime helpers
|   |-- mythify_trace.py         trace analysis and playbook helper
|   |-- mythify_views.py         read-only dashboard and progress helper
|   |-- mythify_views_status.py  readiness and status view helper
|   |-- mythify_workflows.py     research and campaign workflow helper
|   |-- build_variants.py        generates CLAUDE.md, AGENTS.md, .cursorrules
|   |-- build_registry_docs.mjs  generates registry-backed docs
|   |-- check_surface_manifest.mjs checks public surface metadata drift
|   |-- check_runtime_source_size.py recursive runtime size guard
|   |-- install_user.sh          user-local CLI and MCP launcher installer
|   |-- local_model_eval.py      local bare-vs-Mythify comparison harness
|   |-- package_cli.py           builds deterministic standalone CLI tarball
|   `-- package_skill.py         builds dist/mythify.skill from skills/mythify/
|-- mcp-server/
|   |-- package.json
|   |-- mcp-config.example.json
|   |-- client-configs/
|   |-- src/capability-registry.js
|   |-- src/classification.js
|   |-- src/evidence-guard.js    JS mirror of mythify_evidence_guard.py
|   |-- src/execution-adapter.js
|   |-- src/fanout.js
|   |-- src/fanout-prompt.js
|   |-- src/godfiles-core.js     JS mirror of mythify_godfiles.py
|   |-- src/host-model.js
|   |-- src/host-cli.js
|   |-- src/index.js
|   |-- src/lifecycle-adapter.js
|   |-- src/map-tools.js         wayfinding map tools and shared map helpers
|   |-- src/model-policy.js
|   |-- src/model-provider.js
|   |-- src/operation-registry.js
|   |-- src/plan-tools.js
|   |-- src/prompt-packets.js    prompt packet builders shared by route and prompt
|   |-- src/provider-defaults.js
|   |-- src/surface-manifest.js
|   |-- src/verification-provenance.js
|   |-- protocol/classification-rules.json package copy of classifier keywords
|   |-- protocol/model-capabilities.json package copy of model profile policy
|   |-- protocol/operation-registry.json package copy of operation metadata
|   |-- protocol/release-gates.json package copy of readiness gates
|   |-- protocol/workflow-router.json package copy of route metadata
|   |-- protocol/surface-manifest.json package copy of public surface metadata
|   |-- test/capability-registry.test.js
|   |-- test/execution-probe.test.js
|   |-- test/execution-adapter.test.js
|   |-- test/host-cli-probe.test.js
|   |-- test/host-cli-run.test.js
|   |-- test/host-cli.test.js
|   |-- test/lifecycle-adapter.test.js
|   |-- test/lifecycle-probe.test.js
|   |-- test/local-model-run.test.js
|   |-- test/map-tools.test.js
|   |-- test/model-policy.test.js
|   |-- test/model-provider.test.js
|   |-- test/provider-defaults.test.js
|   |-- test/provider-probe.test.js
|   |-- test/smoke.test.js
|   `-- test/fanout.test.js
|-- skills/
|   `-- mythify/
|       |-- SKILL.md
|       `-- references/
|           |-- autonomy-loop.md
|           |-- self-verification.md
|           |-- memory-system.md
|           |-- meta-prompts.md
|           `-- godplans-godaudits.mdx
|-- tests/
|   |-- test_mythify.py          CLI unit and end-to-end tests (stdlib unittest)
|   |-- test_godfiles.py         god artifact parser, plan import, routing, views
|   |-- test_maps.py             wayfinding map gates, promotion, and surfaces
|   |-- test_routes.py           workflow router decision-tree coverage
|   |-- test_campaign_discipline.py campaign verifier gate and hygiene tests
|   |-- test_interop.py          CLI and MCP server against the same state dir
|   |-- test_local_model_eval.py offline test for the local comparison harness
|   `-- fixtures/godfiles/       shared PLAN.mdx and AUDIT.mdx parity fixtures
`-- docs/
    |-- design.md                this document
    |-- codex-integrations.md    Codex Desktop, CLI, MCP, and benchmark setup
    |-- claude-integrations.md   Claude Desktop and Claude Code guide
    |-- adapter-candidates.md    generated from the capability registry
    |-- antigravity-mcp-setup.md Antigravity CLI probe and MCP setup guide
    |-- agents-cli-adk-spike-plan.md Google Agents CLI and ADK probe plan
    |-- colab-cli-spike-plan.md  Google Colab CLI non-billable spike plan
    `-- research-report.md       preserved research report

dist/ (built skill packages) and node_modules/ are build outputs, ignored by git.

One-core architecture decision

Decision: Mythify will move toward one shared contract core, but it will not do a whole-runtime rewrite yet. The Python CLI and Node MCP server stay as separate host adapters. Shared behavior moves behind small, checked contract artifacts only after duplication has produced drift or maintenance pressure.

Evidence for the decision:

  • The CLI and MCP already duplicate state I/O, JSONL reads, atomic writes, shell verification, plan updates, outcome loops, model policy, host-model records, and dashboard formatting. Examples include build_dashboard in scripts/mythify.py and buildWorkflowDashboard in mcp-server/src/index.js, plus parallel run_shell_capture and runShellCapture implementations.
  • The shared registries are working where the duplicated facts are narrow: protocol/operation-registry.json owns memory operation metadata, and protocol/classification-rules.json owns deterministic classifier keyword metadata. protocol/workflow-router.json owns route ids, prompt mapping, and output field metadata. mcp-server/src/capability-registry.js owns host, provider, execution, and lifecycle capability metadata.
  • Drift is still easy to create in prose and copied surface metadata. The dashboard slice raised the MCP tool contract to 30 tools, while the README component summary still said 29 until this decision pass.
  • tests/test_interop.py proves the two runtimes can share one .mythify state directory for mutating state families, so migration can be incremental without breaking existing users.

Policy:

  • Keep Python CLI command handling, Node MCP handler wiring, host CLI process execution, and MCP fanout runtime code in their native adapters for now.
  • Put shared facts into explicit artifacts first: protocol files, operation registries, capability registries, generated docs, schemas, or manifests.
  • Add or expand a shared artifact only when a focused drift test protects the generated or shared output.
  • Prefer data contracts and generation over a cross-language runtime dependency until at least two more duplicated surfaces demonstrate recurring drift.
  • Every migration slice must preserve the on-disk state contract, evidence boundaries, no-mutation guarantees, and CLI/MCP interop tests.

Migration guardrails:

  • docs/design.md leads. The contract changes before implementation.
  • One surface per slice. Do not combine a registry move with unrelated feature work.
  • Each shared artifact needs an executable check, not reviewer memory.
  • Generated files must carry either a source hash or a check command.
  • Runtime output remains material unless an executed verifier records it.
  • Rollback must be simple: adapters can keep their local implementation while the shared artifact is corrected.

Dual-runtime parity discipline

The remaining architecture risk is not an open refactor task. It is the ongoing discipline of keeping the Python CLI and Node MCP server aligned while they remain separate native runtimes.

Rules:

  • If a behavior is exposed by both the CLI and MCP server, update both implementations or document the intentional asymmetry in this design spec.
  • Every shared behavior change must include at least one parity anchor: a shared manifest or registry update, a cross-runtime fixture, or an interop assertion in tests/test_interop.py.
  • Shared facts should move into protocol files, registries, generated docs, schemas, or manifests before any cross-language runtime dependency is added.
  • Do not refactor only to remove duplication. Extract shared artifacts when drift has occurred, when a focused drift test can prove the contract, or when maintenance pressure is visible in repeated edits across both runtimes.
  • Keep Python CLI command handling, Node MCP handler wiring, host process execution, and fanout runtime code in their native adapters until at least two more duplicated surfaces show recurring drift.

Required parity gates:

  • Python suite: python3 -m unittest discover -s tests -v.
  • MCP suite: npm test --prefix mcp-server.
  • Interop suite, with MCP dependencies installed: python3 -m unittest tests.test_interop -v.
  • Surface manifest check: node scripts/check_surface_manifest.mjs.
  • Classification and operation registry mirror check: node scripts/check_classification_rules_manifest.mjs.

Capability registry

The MCP server keeps host, provider, execution, and lifecycle capability metadata in mcp-server/src/capability-registry.js. The registry is a contract boundary, not a router. Listing a candidate adapter does not make it a supported public input.

Registry rules:

  • Existing public enums stay stable until this design document changes.
  • Candidate adapters can be tracked before classify_task, host_model_switch, or fanout_start accept them.
  • A true capability means Mythify has a documented or locally probed path for that adapter. Unknown capabilities default to false.
  • Runtime tools must still verify adapter availability before claiming that anything was applied.
  • Generated docs, schemas, and fixtures may be derived from the registry only after a drift test protects the generated output.
  • The first generated registry-backed document is docs/adapter-candidates.md, built from mcp-server/src/capability-registry.js by node scripts/build_registry_docs.mjs.
  • The generated adapter document is informational. It must not become a public input schema, router, or behavior switch.
  • The drift gate is byte-for-byte equality between the generated output and docs/adapter-candidates.md. The Node registry test also compares the generated text against the committed file.

Adapter kinds:

  • host: host CLI or app-backed coding agents used for bounded worker output.
  • desktop_agent: local desktop agent surface without a stable automation contract.
  • model_provider: local OpenAI-compatible model backends for reader and triage roles.
  • api_provider: hosted model APIs that need explicit billing and data movement posture before execution.
  • custom_adapter: user-defined command or future HTTP adapters.
  • execution_substrate: runtime that executes remote or local jobs and returns logs, files, or artifacts.
  • agent_lifecycle: scaffold, test, deploy, or observe tools for agents.

Stable adapter interface v1:

All candidates can be normalized to the same metadata fields: id, kind, status, locality, openai_compatible, probe_supported, run_supported, execution_enabled, writes_state, evidence_status, material_not_evidence, billing, roles, and guardrails. This interface is descriptive only. It does not add hidden provider fallback, does not turn metadata-only candidates into runnable adapters, and does not grant permission for workers to write state.

The current public host platforms remain auto, unknown, codex-desktop, codex-cli, claude-desktop, claude-code, cursor-desktop, and cursor-agent. Adapter profiles such as generic OpenAI-compatible local providers, Ollama, LM Studio, llama.cpp, vLLM, Kimi Code, OpenCode, Antigravity, Kimi Work, OpenCode Desktop, Google Colab CLI, Google Agents CLI, and Google ADK CLI live in the registry instead of the host platform enum. Kimi Work and OpenCode Desktop are metadata-only desktop_agent candidates until a documented or locally probeable automation surface exists. New candidates must enter the registry first, then earn public schema support in a separate verified slice.

Operation registry

Shared operation metadata lives in protocol/operation-registry.json. This is a runtime contract for duplicated operation facts that have already caused drift, not a broad router or code generation layer.

Prototype scope:

  • The first registered surface is memory.
  • The registry owns memory categories, the default category, the memory state filename, and the no-target memory_clear refusal strings for CLI and MCP.
  • The Python CLI and Node MCP server both load the registry at runtime.
  • Tests compare runtime behavior against the registry before any generated docs or schemas are allowed to depend on it.

Keep new surfaces out of the registry until duplication has been observed and a focused drift test proves the shared contract reduces maintenance risk.

Surface manifest

Shared public surface metadata lives in protocol/surface-manifest.json. The manifest owns duplicated metadata that is easy to drift across prose, tests, and runtime registrations.

Current scope:

  • Top-level CLI command names and command count.
  • MCP core tool names, fanout tool names, and the 44 core plus 3 fanout count split.
  • Front door, workflow, advanced, and labs tier membership for the CLI and MCP surfaces.

Rules:

  • The manifest is not a runtime router. It does not generate tool handlers, command parsers, schemas, or behavior.
  • mcp-server/src/surface-manifest.js exposes the manifest to Node tests.
  • Python tests may read the JSON file directly.
  • scripts/check_surface_manifest.mjs verifies manifest counts, tier partitions, runtime MCP registrations, public doc count phrases, documented tool names, and CLI --help output.
  • CI hygiene runs the check so README, design, protocol notes, tests, and runtime registrations cannot quietly disagree about public surface metadata.
  • Add a new surface only after drift has been observed and the check can prove the shared metadata reduces maintenance risk.

Classification rules manifest

Shared deterministic task-classification keyword rules live in protocol/classification-rules.json. The Python CLI and Node MCP server both load this manifest at startup, so keyword additions such as review wording only need one data edit.

Rules:

  • The manifest owns keyword matching data only. It does not own classification scoring, risk policy, ceremony policy, model policy, fanout policy, or verification hints.
  • Keep runtime behavior in the native CLI and MCP adapters unless duplication has already caused drift.
  • Python and Node tests must cover any newly added terms that affect public classification behavior.
  • mcp-server/protocol/classification-rules.json, mcp-server/protocol/model-capabilities.json, mcp-server/protocol/operation-registry.json, mcp-server/protocol/workflow-router.json, and mcp-server/protocol/surface-manifest.json are package-local mirrors so the npm tarball can run without access to repository-root files. Run node scripts/check_classification_rules_manifest.mjs, the MCP smoke suite, and node scripts/check_surface_manifest.mjs to verify the mirrors.

Model capability manifest

Shared model routing policy lives in protocol/model-capabilities.json. The Python CLI and Node MCP server load it at startup. Its package-local mirror is mcp-server/protocol/model-capabilities.json.

The manifest owns:

  • The provider-neutral profiles utility, balanced, strong, and max.
  • Legacy input aliases: fast to utility, standard to balanced, and frontier to strong.
  • Task-type defaults, high-risk overrides, and bounded failure escalation.
  • OpenAI and Anthropic model mappings plus Cursor runtime catalog preferences.
  • The native claude-ultracode adapter contract for dynamic-workflow candidates.
  • The no-implicit-cross-provider-fallback rule and the command-first verifier boundary.

It does not change user authority, host permissions, or verification rules. Automatic escalation moves one profile for each supplied executed-verifier failure and stops at strong. max is never selected automatically and requires an explicit profile request. Cursor mappings intentionally contain no fixed model id; the worker reads cursor-agent models or cursor agent models, selects the first matching preferred term for the requested capability profile, and falls back to Cursor auto only when that id is present. The host still owns the current chat model.

Run node scripts/check_classification_rules_manifest.mjs to verify both the classification and model capability mirrors.

Workflow router manifest

Shared workflow route metadata lives in protocol/workflow-router.json. The Python CLI route command and Node MCP workflow_route tool both load this manifest at startup.

Rules:

  • The manifest owns route ids, route priority metadata, prompt-packet mapping, and the public output field list.
  • The manifest is not an execution engine. It does not run checks, mutate state, spawn workers, or complete tasks.
  • Route behavior remains native in the CLI and MCP adapters: read active state, inspect the latest executed verification, classify the task, and return a structured route packet.
  • Route output is material for the initiating host chat. It keeps the host as executor unless the user explicitly hands work elsewhere.

Experience surface tiers

The router lets Mythify reduce the surface users have to think about without removing compatibility for scripts, MCP hosts, or power users.

Default front door:

  • CLI route, report, verify run, and status.
  • MCP workflow_route, work_report, verify_run, and workflow_status.

Workflow primitives:

  • plan, outcome, campaign, research, and prompt in the CLI.
  • plan_create, plan_add_step, plan_update_step, outcome_start, outcome_check, campaign_next_prompt, and prompt_packet in MCP.

Advanced surfaces:

  • Dashboards, history, background, evidence harness, readiness, timeline, phase, trace, memory, lessons, logs, fanout, reflections, summaries, and protocol checks.

Labs surfaces:

  • Host-model state, provider probes, local model runs, host CLI workers, execution substrate probes/runs, and lifecycle probes. These surfaces are explicit, material-only, and adapter-facing. They should not be presented as the default product path until they can perform and confirm host actions.

Public help, docs, skills, and MCP tool descriptions should present the default front door first, then workflow primitives, then advanced surfaces, then labs. Primitive commands stay available, but broad or ambiguous prompts should route through route or workflow_route before selecting a lower-level tool.

Background task view

The background task view is a read-only orientation surface for durable long running work:

  • CLI command: background [--recent N] [--json].
  • MCP tool: background_status.
  • State sources: .mythify/outcomes/*/goal.json, .mythify/outcomes/*/iterations.jsonl, and .mythify/fanout/<job_id>/job.json.
  • Output: outcome counts, active outcome, recent outcome loops, fanout job counts, fanout task counts, recent fanout jobs, and each recent job's task statuses.
  • Evidence boundary: the view reports recorded verifier iterations and durable task statuses. It must not infer progress from model confidence, host UI state, or whether an MCP server process is currently alive.
  • Mutation boundary: the normal path must not create, edit, interrupt, stop, or otherwise mutate outcome or fanout records. It is an orientation view, not a control surface.

Evidence harness view

The evidence harness view is a read-only control surface for autonomous agent work:

  • CLI command: harness [--recent N] [--json].
  • MCP tool: evidence_harness.
  • State sources: the active plan, .mythify/verifications.jsonl, .mythify/reflections.jsonl, durable outcome loop state, durable fanout job state, release readiness state, read-only git status for the project root, and godplans and godaudits artifacts when present.
  • Output: harness status, active plan and outcome, evidence mix, attention items, outcome and fanout counts, release readiness summary, recent reflections, and the next control action. Present god artifacts appear under god_artifacts with status lines; open Critical findings and counter drift become attention items, and with no active plan the next action points at plan import. Advisory evidence-quality watchers add attention items for: recent trivial passes (a green run whose command can never fail or whose output reports zero tests), active legacy gate opt-outs (MYTHIFY_REQUIRE_VERIFIED_STEP=0, MYTHIFY_REQUIRE_HUMAN_INPUT=0, MYTHIFY_DISABLE_RUN=1), steps completed under a waived strict gate, ledger chain breaks, outcome verifier drift (iterations recording different verify commands), and outcomes whose audit recheck failed. All are advisory: they never block completion or downgrade recorded evidence.
  • Evidence boundary: the view reports durable evidence and durable worker state. Worker output remains material, not verification evidence, until an executed verifier records proof for the merged work.
  • Mutation boundary: the normal path must not create, edit, complete, stop, interrupt, retry, tag, publish, push, or otherwise mutate project or Mythify state. It is a control view, not an execution surface.

Outcome progress view

The outcome progress view is a read-only progress surface for verifier-backed outcome loops:

  • CLI command: progress [--recent N] [--json].
  • MCP tool: outcome_progress.
  • State sources: .mythify/outcomes/*/goal.json, .mythify/outcomes/*/iterations.jsonl, and the active outcome pointer.
  • Output: outcome counts, active outcome, recent outcome loops, iteration budget, remaining iterations, last verifier exit, last verifier verdict, metric exit and score when present, and the recorded next action.
  • Evidence boundary: the view reports recorded outcome check and outcome_check verifier iterations. Notes, model prose, and host UI state must not become verification evidence by appearing in the progress view.
  • Mutation boundary: the normal path must not run checks, make attempts, stop loops, change active outcomes, or edit goal or iteration records. It is a progress display, not a control surface.

Release readiness view

The release readiness view is a read-only release-review surface:

  • CLI command: readiness [--json].
  • MCP tool: release_readiness.
  • State sources: .mythify/verifications.jsonl, the exact-command gate inventory in protocol/release-gates.json, roadmap.md, read-only git status for the project root, and godplans and godaudits artifacts (.godplans/PLAN.mdx and .godaudits/AUDIT.mdx, with .md fallbacks).
  • Output: release-review status, required gate rows, each gate's latest matching executed verifier record, its freshness status and reason, source file references, top-level current_provenance with the current Git commit and Mythify version, gate counts including stale, project git status, active roadmap slice, and project_state.godplans and project_state.godaudits summaries (status missing when absent; text output prints their lines only when an artifact is present, so projects without god artifacts render byte-identically to before).
  • Required gates: the shared manifest is authoritative for ids, labels, source paths, and exact normalized commands. The source manifest and packaged MCP mirror must be identical. Current gates cover Python, Node, CLI and MCP interoperability, distribution artifacts, public surface and runtime manifests, generated registry docs, runtime source size, protocol variants, whitespace, dependency audit, release tag binding, and flat release assets.
  • Evidence boundary: the view only summarizes recorded executed verifier records whose normalized command exactly matches a manifest command. Claims and output text never select a gate. A passing record satisfies a gate only when verified is true, exit_code is zero, and its provenance.git_commit, provenance.worktree_clean, and provenance.mythify_version match the clean current checkout. Legacy records without provenance stay readable but report freshness legacy, gate status stale, and do not satisfy release readiness. Missing rows stay missing, failed rows stay failed, and attested claims do not satisfy release gates. If the current Git commit is unavailable, freshness fails closed with reason current_git_commit_unavailable. Current or recorded dirty worktrees are stale with current_worktree_dirty or recorded_worktree_dirty; unavailable recorded cleanliness is stale with recorded_worktree_cleanliness_unavailable.
  • Mutation boundary: the normal path must not append, edit, compact, or remove Mythify state, must not rerun release gates, and must not tag, publish, push, or declare the release safe.

Verification history

The verification history is a read-only evidence surface for recorded checks:

  • CLI command: history [--recent N] [--json].
  • MCP tool: verification_history.
  • State source: .mythify/verifications.jsonl.
  • Record kinds: executed records from verify run and verify_run, plus attested records from verify claim and verify_claim.
  • Output: total counts, executed passed count, executed failed count, attested count, recent records, verdicts, command or evidence fields, exit code, duration, output-tail byte counts, and plan or step context when present.
  • Evidence boundary: executed records are machine-checked evidence. Attested records remain self-reported and must not be upgraded by appearing in the history view.
  • Mutation boundary: the normal path must not append, compact, edit, remove, rerun, or reclassify verification records. It is a history view, not a verifier or log maintenance command.

Work report

The work report is a chat-ready progress surface for visible live narration:

  • CLI command: report [--since last|start] [--format chat|json] [--recent N] [--cursor NAME] [--peek] [--mark].
  • MCP tool: work_report.
  • State sources: active and inactive plan files, .mythify/verifications.jsonl, .mythify/reflections.jsonl, and .mythify/reports/<cursor>.json.
  • Output: an Attention section for failed verification, failed step, failure reflection, and attested warning events, followed by chronological plan creation, step updates, verification verdicts, and reflection events. chat output is intended to be pasted or summarized in the host conversation.
  • Cursor behavior: by default the selected cursor advances to the newest known event so later --since last reports show only new events. --peek leaves the cursor unchanged. --mark advances the cursor to the newest known event without showing old events and is incompatible with --since.
  • Evidence boundary: the report does not rerun checks, does not upgrade attested claims, and does not prove work beyond recorded Mythify evidence.
  • Mutation boundary: the only normal mutation is the cursor file. It must not edit plans, verifications, reflections, memory, lessons, outcomes, fanout jobs, git state, or project files.

Fanout worker timeline

The fanout worker timeline is a read-only orientation surface for delegated worker history:

  • CLI command: timeline [--recent N] [--json].
  • MCP tool: fanout_timeline.
  • State sources: .mythify/fanout/<job_id>/job.json, including job created, job last_updated, task started_at, task finished_at, task duration_seconds, task status, task error, and output metadata.
  • Output: fanout job counts, fanout task counts, recent job records, and chronological events for job creation, task starts, task finishes, failures, interruptions, and pending tasks.
  • Evidence boundary: the timeline reports durable worker state. Worker output remains material, not verification evidence, until the orchestrator verifies merged work with an executed check.
  • Mutation boundary: the normal path must not create, edit, interrupt, retry, stop, or otherwise mutate fanout jobs or worker tasks. It is a timeline, not a process-control surface.

Phase view

The phase view is a read-only orientation surface for the current workflow shape:

  • CLI command: phase [--recent N] [--json].
  • MCP tool: phase_status.
  • Phase buckets: Understand, Design, Build, Judge, and Verify.
  • State sources: the active plan in .mythify/plans/, recent verification records, recent reflection records, durable outcome loop state, durable fanout job state, memory counts, and lesson counts.
  • Output: active plan, goal, each phase's plan steps, each phase's derived step status, evidence count summaries, and the next recorded plan action for that phase.
  • Evidence boundary: the view summarizes durable state and executed evidence counts. It must not grade confidence, infer success from prose, or replace verify run, verify_run, or outcome_check.
  • Mutation boundary: the normal path must not create, edit, complete, fail, archive, interrupt, stop, or otherwise mutate any plan, verification, reflection, outcome, fanout, memory, or lesson state.

State model (shared contract)

State directory resolution

  1. If the MYTHIFY_DIR environment variable is set, use that path directly as the state directory. Create it (and subdirectories) on demand.
  2. Otherwise walk from the current working directory upward; the first directory containing a .mythify/ folder wins, and that .mythify/ is the state directory.
  3. Otherwise:
    • Python CLI: init creates ./.mythify and adds .mythify/ to the project .gitignore for the default in-repo state directory. Every other command prints [FAIL] No .mythify workspace found. Run: mythify init and exits 1.
    • MCP server: lazily creates <cwd>/.mythify on first write. Reads with no state respond gracefully (for example "No memory entries yet."), never with a crash.

Global lessons live in ~/.mythify/lessons/ and are independent of project state. Both implementations must resolve the home directory through the HOME environment variable when it is set (Python Path.home(), Node os.homedir() both already do).

Layout of a state directory

.mythify/
|-- memory.json
|-- host-model.json              optional recorded host chat model request
|-- plans/
|   |-- active                   text file containing the slug of the active plan
|   |-- <slug>.json
|   `-- archive/
|       `-- <slug>.json
|-- lessons/
|   `-- <slug>.json
|-- outcomes/
|   |-- active
|   `-- <slug>/
|       |-- goal.json
|       `-- iterations.jsonl
|-- research/
|   |-- active
|   `-- <slug>.json
|-- campaigns/
|   |-- active
|   `-- <slug>.json
|-- maps/
|   |-- active
|   `-- <slug>.json
|-- reports/
|   `-- <cursor>.json
|-- fanout/
|   `-- <job-id>/
|       |-- job.json
|       `-- task-<id>-output.md
|-- logs/
|   `-- archive/
|       `-- <log-stem>-<YYYYMMDDHHMMSS>.jsonl
|-- locks/
|   `-- jsonl-<digest>.lock/
|-- tmp/
|   `-- fanout worker prompt files
|-- provider-audit.jsonl
|-- verifications.jsonl
`-- reflections.jsonl

File formats (exact field names; both implementations identical)

memory.json:

{
  "entries": [
    {"key": "str", "value": "str", "category": "fact|decision|discovery|state", "timestamp": "ISO-8601"}
  ],
  "metadata": {"created": "ISO-8601", "last_updated": "ISO-8601", "total_entries": 0}
}

Keys are unique; set on an existing key overwrites the entry.

host-model.json:

{
  "platform": "codex-desktop|codex-cli|claude-desktop|claude-code|cursor-desktop|cursor-agent|unknown",
  "requested_platform": "auto|unknown|codex-desktop|codex-cli|claude-desktop|claude-code|cursor-desktop|cursor-agent",
  "target_model": "str",
  "current_model": "str",
  "target_model_tier": "unknown|small|fast|standard|strong|frontier",
  "thinking": "auto|low|medium|high|xhigh|max",
  "speed": "auto|standard|fast",
  "reason": "str",
  "status": "recorded_requires_host_action",
  "control": "host_selected",
  "can_apply_current_chat": false,
  "host_capability": {
    "kind": "host",
    "status": "supported|unknown|unsupported",
    "can_switch_current_thread": false,
    "can_set_new_thread_model": true,
    "can_set_worker_model": true,
    "can_set_thinking": true,
    "can_list_models": false,
    "can_confirm_current_model": false
  },
  "switch_result": {
    "status": "manual",
    "requested_model": "str",
    "requested_thinking": "auto|low|medium|high|xhigh|max",
    "requested_speed": "auto|standard|fast",
    "current_model": "str",
    "current_thinking": "",
    "current_chat_supported": false,
    "current_chat_confirmed": false,
    "manual_action_required": true,
    "applied_by": "none",
    "reason": "host_current_chat_unconfirmed"
  },
  "host_confirmation": {
    "requested_model": "str",
    "user_reported_current_model": "str",
    "user_reported_current_thinking": "",
    "current_model_confirmed": false,
    "confirmed_current_model": "",
    "confirmed_current_thinking": "",
    "confirmation_status": "unsupported|unconfirmed|confirmed|blocked",
    "confirmation_source": "none|host_adapter",
    "confirmation_checked_at": "ISO-8601",
    "confirmed_at": "",
    "unsupported_reason": "host_capability_cannot_confirm_current_model"
  },
  "adapter_proof_scan": {
    "status": "metadata_only",
    "platform": "codex-desktop",
    "proof_source": "host_capability_registry",
    "checked_at": "ISO-8601",
    "host_state_mutated": false,
    "writes_state": false,
    "verification_recorded": false,
    "material_not_evidence": true,
    "guardrail": "current_chat_apply_or_confirm_requires_executed_host_evidence",
    "paths": {
      "current_chat_model_apply": {"status": "supported|unsupported|unknown"},
      "current_chat_model_confirm": {"status": "supported|unsupported|unknown"},
      "new_thread_model_apply": {"status": "supported|unsupported|unknown"},
      "worker_model_apply": {"status": "supported|unsupported|unknown"},
      "thinking_apply": {"status": "supported|unsupported|unknown"}
    }
  },
  "updated": "ISO-8601",
  "host_actions": ["str"]
}

host-model.json is optional. Explicit session_model and MYTHIFY_SESSION_MODEL beat it; otherwise it supplies the default session model for classify_task and fanout_start.

Host model switch status rules:

  • switch_result.status is manual when Mythify recorded a target model but no host adapter applied or confirmed the current chat.
  • switch_result.status is requested only when a future host adapter accepts a request but cannot yet confirm the current chat.
  • switch_result.status is applied only when a host adapter confirms the current chat model or thinking changed.
  • switch_result.status is blocked only when an adapter proves the requested change cannot be requested or applied.
  • current_chat_confirmed must stay false unless host_capability has can_confirm_current_model: true and the host returns positive evidence.
  • host_confirmation.current_model_confirmed must stay false unless a host adapter returns positive current-chat evidence. User-supplied current_model is recorded as user_reported_current_model, not proof.
  • host_confirmation.confirmation_status is unsupported when the capability registry cannot confirm the current model, unconfirmed when a future adapter can check but has not produced evidence, confirmed only after positive host evidence, and blocked only after adapter evidence proves confirmation cannot be performed.
  • adapter_proof_scan is a non-mutating metadata scan. Its path statuses are supported, unsupported, or unknown, and host_state_mutated must stay false. A supported path means the registry or probe found a possible path; it is not proof that the host changed.
  • CLI and MCP status output must expose host_capability, can_apply_current_chat, switch_result, host_confirmation, and adapter_proof_scan so callers can distinguish desired state, user-reported state, host-confirmed state, and future apply or confirm paths.
  • docs/host-apply-confirm-proof-watchlist.md names the proof gates for current-chat apply, current-chat confirm, worker model override, and thinking override before any host mutation path can be enabled.

outcomes/<slug>/goal.json:

{
  "id": "slug",
  "goal": "str",
  "success_criteria": "str",
  "verify_command": "str",
  "metric_command": "str (empty when absent)",
  "metric_floor": "number or null (requires metric_command)",
  "agent_command": "str (CLI self-driving loop; empty when supervised)",
  "max_iterations": 3,
  "iteration_count": 0,
  "max_cost": "number or null (CLI self-driving loop)",
  "cost_spent": 0.0,
  "escalate_after": "integer or null (CLI self-driving loop)",
  "allowed_paths": ["str"],
  "frozen_paths": ["str"],
  "scope_baseline": "Git commit or absent (CLI self-driving scoped loop)",
  "visibility": "auto|quiet|summary|verbose|threaded",
  "status": "active|succeeded|failed|stopped",
  "created": "ISO-8601",
  "updated": "ISO-8601",
  "last_verified": "boolean or null",
  "best_metric_score": "number or null",
  "stop_reason": "str or null",
  "supersedes": "slug or null",
  "superseded_by": "slug or absent",
  "evidence_stale": "boolean or absent (set by outcome check --audit)",
  "last_audit": "ISO-8601 or absent"
}

allowed_paths are not a sandbox. The supervised CLI and MCP outcome check paths report available Git scope hints without blocking. CLI outcome run enforces the same list after each agent attempt. frozen_paths is the opposite contract: an enforced deny-list in every mode, supervised checks included. It is the held-out set the loop must never touch (tests are the canonical case, so a scoped agent cannot rewrite its own verifier); a change under a frozen prefix stops the loop, and the .mythify/ exemption does not apply to it. metric_floor turns the optional metric into a counter-watcher: a green verifier whose parsed score is missing or below the floor does not succeed, and a score below best_metric_score stamps metric_regressed on the iteration. Starting a second outcome while one is active is refused unless --supersede REASON retires the old loop, which records superseded_by and the reason on the old goal and supersedes on the new one. A success on iteration 1, before any recorded failed attempt, carries a vacuity caution in next_action: confirm the verifier can fail. outcome check --audit re-runs a finished outcome's verifier without mutating iteration_count or status, appends the run flagged audit, and sets evidence_stale to whether the run failed; audits are the loop whose only job is checking that a recorded result still touches reality. A scoped self-driving run requires a clean Git worktree before the first agent executes, records the current commit as scope_baseline, and compares the baseline commit plus the working tree against every allowed path. Rename and copy checks include both source and destination paths. A non-Git directory, dirty starting worktree, diverged baseline, or failed Git inspection stops the loop before unsafe work can continue.

outcomes/<slug>/iterations.jsonl, one JSON object per verifier attempt:

{
  "iteration": 1,
  "timestamp": "ISO-8601",
  "notes": "str",
  "agent": "object or null (CLI self-driving attempt)",
  "cost": 0.0,
  "cost_spent": 0.0,
  "verify": {"command": "str", "exit_code": 0, "duration_seconds": 0.03, "stdout_tail": "str", "stderr_tail": "str", "verified": true},
  "metric": "result object or null",
  "verified": true,
  "scope_violations": ["str"],
  "frozen_violations": ["str"],
  "metric_regressed": false,
  "metric_floor_unmet": false,
  "status_after": "succeeded|active|failed|stopped",
  "next_action": "str"
}

outcomes/active stores the active outcome slug. Outcome loops are supervised: the host chat acts between outcome check calls, while Mythify records the verifier result, optional metric, iteration budget, and next action. Every check also appends an executed verification record tagged with the outcome slug and iteration number. Its top-level verdict is the combined verifier and metric result, while outcome_verify and outcome_metric preserve the individual command results.

plans/<slug>.json:

{
  "name": "slug",
  "goal": "str",
  "steps": [
    {"id": 1, "title": "str", "success_criteria": "str", "verify_command": "str (optional and absent unless supplied)", "verification_cursor": "nonnegative integer (present once started)", "status": "pending|in_progress|completed|failed|skipped", "result": null, "updated_at": "ISO-8601 (present once updated)"}
  ],
  "created": "ISO-8601",
  "last_updated": "ISO-8601"
}

Step ids are 1-based integers assigned in order. success_criteria defaults to an empty string. verify_command is absent unless supplied; plan create and plan add-step both persist a supplied verifier. Every transition to in_progress stores verification_cursor, the count of verification records that existed before the step started. Completion considers only records after that cursor, which prevents old same-second evidence from being reused. result is a string or null.

Plans created by plan import carry additional optional fields; all views read step fields with tolerant lookups, so their absence on legacy plans is safe:

  • Plan level: strict_context: true (step completion accepts only verifications recorded with explicit matching plan and step context, closing the legacy context-free acceptance for bulk-imported plans) and source: {kind: "godplans"|"godaudits", path, version, imported_at} (provenance; re-import of the same artifact path is refused while the plan exists).
  • Step level: source_id (the GP or GA task id), the imported task's exact verify_command echoed by plan show and the next-pending line, wave, phase (artifact phase title; the phase view prefers it over keyword guessing), and optional depends_on and fixes lists.

lessons/<slug>.json:

{"title": "str", "detail": "str", "tags": ["str"], "created": "ISO-8601"}

Lesson filename: slugify(title) truncated to 50 chars, then -YYYYMMDDHHMMSS, then .json. This makes same-title lessons collision-free.

verifications.jsonl, one JSON object per line. Two kinds:

{"kind": "executed", "claim": "str or null", "command": "str", "exit_code": 0, "duration_seconds": 0.03, "stdout_tail": "str", "stderr_tail": "str", "verified": true, "timestamp": "ISO-8601", "provenance": {"git_commit": "hex string or null", "worktree_clean": "boolean or null", "mythify_version": "semver string"}, "plan": "slug or null", "step_id": 1, "step_title": "str or null", "step_status": "in_progress or null", "prev_sha256": "hex string or null"}
{"kind": "attested", "claim": "str", "evidence": "str", "verified": null, "timestamp": "ISO-8601", "plan": "slug or null", "step_id": 1, "step_title": "str or null", "step_status": "in_progress or null", "prev_sha256": "hex string or null"}

verified is a boolean only for executed verifications (true when exit_code == 0). Attested entries always have verified: null: a self-report is never marked verified. On timeout, record exit_code: -1, verified: false, and append "(timed out after N seconds)" to stderr_tail. Output tails keep the last 4000 characters of each stream.

Outcome-generated executed records add outcome, iteration, outcome_verify, and outcome_metric. Their top-level verified and exit_code describe the combined verifier and metric gate. The nested objects retain each command's independent exit code, duration, and redacted tails.

Every new executed verification record also captures best-effort source provenance and active step context. provenance.mythify_version is always the runtime version; provenance.git_commit is the project HEAD or null when Git provenance is unavailable; provenance.worktree_clean reports whether Git found no tracked or untracked changes, or is null when Git inspection is unavailable. If an active plan exists and exactly the first currently in_progress step can be found, record plan, step_id, step_title, and step_status. If no active plan or in-progress step exists, write those fields with null. Readers must tolerate older verification records that do not contain provenance or step context, but readiness must not silently upgrade a legacy record to fresh evidence.

Every new verification record is chained: prev_sha256 is the sha256 of the raw line preceding it in the file, or null for the first record. The chain is tamper evidence, not cryptography: an edited, inserted, or deleted line breaks the next record's link, and the evidence harness flags the break as an attention item. The first line of the active file is never judged (its predecessor may live in a compaction archive), and legacy records without prev_sha256 stay silent.

reflections.jsonl, one JSON object per line:

{"action": "str", "outcome": "success|partial|failure", "observation": "str", "root_cause": "str or null", "next": "str", "lesson": "str or null", "timestamp": "ISO-8601"}

logs/archive/*.jsonl:

  • Raw snapshots created by logs compact.
  • Names are <log-stem>-<YYYYMMDDHHMMSS>.jsonl, with a numeric suffix on collision.
  • The first compacted logs are the top-level verifications.jsonl and reflections.jsonl files. Outcome iteration logs stay in their outcome directories.
  • Archives preserve the original bytes of the active log before compaction, including unparseable lines. The compacted active log keeps only the most recent valid JSONL records.

Durability rules

  • All JSON file writes are atomic: write to a temp file in the same directory, then rename over the target (Python os.replace, Node fs.renameSync).
  • Corrupt JSON on read: rename the bad file to <filename>.corrupt-<YYYYMMDDHHMMSS>, print [WARN] to stderr, and continue with a fresh default. Never crash.
  • jsonl logs are plain appends.
  • logs compact [--keep N] [--dry-run] [--json] is maintenance, not verification evidence. Default --keep is 1000. When a target log has more than N valid records, write a raw archive first, then atomically replace the active log with the most recent N valid records, preserved as their original raw line bytes so retained prev_sha256 links survive compaction. --dry-run reports candidates and counts without writing files.

Slugs

slugify(text): lowercase, replace runs of non-alphanumeric characters with -, strip leading and trailing -, truncate to 40 characters. For plan slugs, on collision with an existing plan file append -2, -3, and so on.

Output conventions (both implementations)

  • Event markers: [OK], [FAIL], [WARN].
  • Step status icons: pending [ ], in_progress [>], completed [x], failed [!], skipped [~].
  • Verification verdict lines:
    • [OK] VERIFIED: <claim or command> (exit 0, 0.03s)
    • [FAIL] UNVERIFIED: <claim or command> (exit 2, 0.10s) followed by --- stdout (tail) --- and --- stderr (tail) --- blocks when non-empty.
    • [WARN] ATTESTED: <claim> (self-reported, not machine-checked; prefer verify run)
  • ASCII only in all program output.

CLI: scripts/mythify.py

Modular Python 3.9+ CLI using only the standard library. scripts/mythify.py owns the public entry point and delegates cohesive command families to sibling scripts/mythify_*.py modules. Subcommand grammar:

CommandBehaviorExit code
initCreate ./.mythify with subdirectories and empty memory.json, and add .mythify/ to the project .gitignore for the default in-repo state directory. If already inside a workspace, print [WARN] and exit 0.0
protocol check [PATH ...] [--json]Verify copied protocol files match the CLI's embedded source protocol hash. With no paths, check source protocol when present and local CLAUDE.md, AGENTS.md, and .cursorrules files. Every invocation also pins any present protocol/release-gates.json (and its packaged mirror) against the embedded RELEASE_GATES_SHA256.0 if every checked file matches; 1 on missing metadata or drift
statusOrientation: active plan with step icons, next pending step and its criteria, one-line counts (memory, lessons, verifications, reflections).0; 1 if no workspace
dashboard [--recent N] [--json]Read-only workflow dashboard: active plan, current and next step, active outcome, memory and lesson counts, verification totals, recent verification records, and recent reflections. It does not mutate state or report model confidence.0; 1 if no workspace
harness [--recent N] [--json]Read-only evidence harness: active steering state, evidence mix, attention items, delegated work counts, release readiness, and the next control action from durable state. It does not mutate state or treat worker output as verification.0; 1 if no workspace
history [--recent N] [--json]Read-only verification history: executed and attested records, verdicts, commands, exit codes, duration, and plan or step context from durable state. It does not mutate state, rerun checks, or upgrade attested claims.0; 1 if no workspace
report [--since last|start] [--format chat|json] [--recent N] [--cursor NAME] [--peek] [--mark]Chat-ready live work report over durable plan, step, verification, and reflection events, with an Attention section for failed checks, failed steps, failure reflections, and attested warnings. By default it advances a cursor so repeated calls show only new events; --peek leaves the cursor unchanged; --mark advances the cursor to the latest event without showing old events and cannot be combined with --since.0; 1 if no workspace, invalid recent value, or incompatible flags
route TASK [--json] [--triage never|auto|always] [--platform P] [--effort E] [--speed S] [--session-model M] [--model-profile P] [--failure-count N] [--spawn-ceiling C] [--reviewer-strength R]Read-only workflow router. It classifies the task, selects the capability profile and topology, inspects durable state and the latest executed verification, then returns a route, reason, a loop-collision note naming every active loop family and which one steers when more than one is live, next command, prompt packet, verification strategy, chat policy, pause rules, expected state writes, and evidence. It must not mutate state or move execution out of the initiating host unless the user explicitly asks.0; 1 if no workspace
prompt KIND [NAME] [--goal TEXT] [--verify COMMAND] [--json]Render a read-only workflow prompt packet. Kinds are research, analysis, failure, handoff, review, campaign, map, and next; packet output is steering material for the host, not verification evidence. next selects failure recovery only when the latest executed check is red, then campaign, map, research, handoff, or analysis based on active state.0; 1 if no workspace or named state is missing
background [--recent N] [--json]Read-only background task view: outcome loops, fanout jobs, task counts, current statuses, and next actions from durable state. It does not mutate state or report model confidence as progress.0; 1 if no workspace
progress [--recent N] [--json]Read-only outcome loop progress: active and recent outcomes, iteration budget, verifier exit details, metric score when present, and next action from durable state. It does not mutate state, run checks, stop loops, or treat notes as verification.0; 1 if no workspace
readiness [--json]Read-only release readiness: recorded verification gates, project git state, roadmap state, and release-review status without rerunning gates or declaring the release safe.0; 1 if no workspace
timeline [--recent N] [--json]Read-only fanout worker timeline: recent fanout jobs, task start and finish events, duration, status, errors, and output metadata from durable state. It does not mutate state or report worker output as verification evidence.0; 1 if no workspace
phase [--recent N] [--json]Read-only phase view: active plan steps grouped into Understand, Design, Build, Judge, and Verify, with supporting evidence counts from durable state. It does not mutate state or report model confidence as progress.0; 1 if no workspace
outcome start GOAL --success TEXT --verify COMMAND [--metric COMMAND] [--metric-floor N] [--agent COMMAND] [--max-iterations N] [--max-cost N] [--escalate-after N] [--allowed-paths CSV] [--frozen-paths CSV] [--supersede REASON] [--visibility MODE] [--name NAME] [--json]Start an outcome loop, set it active, and record the verifier, optional metric and metric floor, optional self-driving agent_command?: string, iteration and cost budgets, escalation threshold, Git-enforced allowed paths, the enforced frozen-path deny-list, and visibility policy. A second start while another outcome is active requires --supersede REASON, which stops the old loop with recorded lineage.0; 1 if no workspace, invalid budget, a floor without a metric, or an unsuperseded active loop
outcome check [NAME] [--notes TEXT] [--audit] [--timeout N] [--json]Run the verifier and optional metric for the active or named outcome, append an iteration record, append executed verification evidence, and return the next action. --audit re-runs a finished outcome's verifier without mutating its iteration count or status and sets evidence_stale from the result.0 if verified, 2 if still unmet or failed, 1 if not found or auditing an active loop
outcome run [NAME] [--notes TEXT] [--timeout N]Drive a self-driving loop started with --agent: run the bounded agent command, execute the verifier and optional metric, record evidence, enforce iteration, cost, path, and escalation limits, and stop on success or a guard. CLI-only.0 if verified; 2 if still unmet, blocked, or budget-exhausted; 1 if not found or not self-driving
outcome status [NAME] [--json]Show outcome status, verifier, metric, iteration budget, and latest next action.0; 1 if not found
outcome results [NAME] [--json]Show every recorded verifier iteration plus final state.0 if succeeded, 2 otherwise, 1 if not found
outcome stop [NAME] --reason TEXT [--json]Mark an active or named outcome stopped and clear the active pointer when it matches.0; 1 if not found
map create DESTINATION [--name NAME] [--notes TEXT] [--fog TEXT] [--json]Chart a wayfinding decision map and set it active. --fog is repeatable and seeds the Not-yet-specified register.0; 1 if no workspace
map list [--json]List maps with active marker, open and frontier counts, decisions, fog, and status.0; 1 if no workspace
map show [NAME] [--json]Show the map at low resolution: destination, notes, decisions so far, frontier, claimed, blocked, fog, out of scope, and the next action. Read-only.0; 1 if not found
map ticket TITLE --type research|prototype|grilling|task [--question TEXT] [--mode afk|hitl] [--blocked-by IDS] [--verify COMMAND] [--from-fog ID] [--map NAME]Add a decision ticket (id = T + next number). The type fixes the mode: research and task are afk, prototype and grilling are hitl; --mode is accepted only for task. --blocked-by accepts repeated or comma-separated ids that must already exist. --from-fog graduates a fog patch exactly once.0; 1 on unknown blocker, unknown or already-graduated fog, or a mode override on a non-task ticket
map claim ID [--by WHO] [--map NAME]Claim an open, unblocked ticket and record a verification cursor. Refuses a blocked ticket, a ticket claimed by someone else, and a second non-research ticket held by the same claimant. Defaults to MYTHIFY_MAP_CLAIMANT or session.0; 1 if refused
map verify ID [--map NAME] [--timeout N]Run the ticket's verify_command and record the executed verification stamped with map, ticket_id, ticket_title, and ticket_type, satisfying the ticket's resolution gate. Requires a prior claim. CLI-only.0 verified; 2 command failed or run disabled; 1 usage error
map resolve ID --answer TEXT [--gist TEXT] [--human-input TEXT] [--out-of-scope] [--fog TEXT] [--scope-out TEXT] [--map NAME]Close a claimed ticket. --answer is required. A hitl ticket REQUIRES --human-input unless MYTHIFY_REQUIRE_HUMAN_INPUT=0. A ticket storing verify_command requires a passing executed record with exit code 0 and a matching normalized command at or after the claim cursor. --out-of-scope closes the ticket into the Out-of-scope register instead of Decisions and skips the claim, block, and verifier gates, but never the human-input gate: ruling a human's question out of scope is itself the human's call.0; 1 if refused
map fog NOTE [--map NAME]Record an in-scope question too dim to ticket. Reopens a clear map to charting.0; 1 if no map
map scope-out NOTE --reason TEXT [--map NAME]Record work ruled past the destination. Out-of-scope work never graduates.0; 1 if no map
map promote [NAME] [--plan NAME] [--steps JSON] [--horizon N]Create a plan from a map with no open tickets and no ungraduated fog. The plan's goal is the destination and its source block carries {kind: "map", map, destination, decisions, out_of_scope}. Marks the map promoted, records promoted_plan, and clears the active map pointer.0; 1 if the map is unclear, missing, or already promoted
plan create GOAL [--steps JSON] [--horizon N] [--name NAME]Create plan, set it active. --steps is a JSON array of {"title": str, "success_criteria": str (optional), "verify_command": str (optional)}. --horizon N creates N default lookahead steps when --steps is omitted. MYTHIFY_PLAN_HORIZON sets the direct plan default. Without any of those, create an empty plan and suggest plan add-step. Invalid JSON: [FAIL], exit 1.0
plan import [PATH] [--source godplans|godaudits] [--name NAME]Convert godplans PLAN.mdx or godaudits AUDIT.mdx checkbox tasks into a plan and set it active. Discovers the artifact at the project root when PATH is omitted; both present without --source is an error. Live tasks import in document order (superseded strikethrough tasks skipped, checked boxes import completed); each step keeps source_id, verify_command, wave, phase, plus depends_on and fixes when present. Sets strict_context and a source provenance block; re-importing the same artifact path is refused while the imported plan exists. Warns on frontmatter counter drift. Never edits the artifact.0; 1 on missing, ambiguous, unrecognized, or already-imported artifacts
plan add-step TITLE [--criteria TEXT] [--verify COMMAND] [--plan NAME]Append a step (id = max + 1) to the named or active plan, optionally with an executable verify_command.0; 1 if plan not found
plan verify ID [--plan NAME] [--timeout N]Run the step's verify_command, mark the step in progress, and record the executed verification scoped to that step so the strict-evidence gate is satisfied. CLI-only.0 verified; 2 command failed; 1 usage error
plan listList plans with active marker and per-plan progress, plus archived count.0
plan show [NAME]Full detail of the named or active plan.0; 1 if not found
plan switch NAMESet the active plan pointer.0; 1 if not found
plan archive [NAME]Move plan file to plans/archive/; clear the active pointer if it pointed there. On filename conflict in archive, append a timestamp.0; 1 if plan not found
step ID STATUS [RESULT] [--plan NAME]Update step status. STATUS must be one of the five enum values, otherwise [FAIL], exit 1. completed and failed REQUIRE the RESULT argument (evidence or failure description); without it print [FAIL] Evidence required: pass a RESULT describing what proves this status. and exit 1. By default, completed ALSO requires an executed verification with verified: true, exit_code: 0, and a timestamp after the step began. When the step stores verify_command, the record's normalized command must match. Otherwise print the verified-evidence refusal and exit 1 without modifying the plan. Set MYTHIFY_REQUIRE_VERIFIED_STEP=0 to opt out. After updating, print the next pending step.0
memory set KEY VALUE [--category C]Category one of fact, decision, discovery, state; default fact.0
memory get [QUERY] [--category C]Case-insensitive substring match over keys and values; optional category filter.0
memory clear [KEY] [--all]KEY removes one entry. --all clears everything. Neither: [FAIL] explaining the guard, exit 1.0
lesson add TITLE DETAIL [--tags a,b] [--global]Record a lesson in the project store, or the global store with --global.0
lesson list [--tag TAG] [--scope project|global|all]Default scope all; label each lesson (project) or (global); --tag filters.0
logs compact [--keep N] [--dry-run] [--json]Archive raw top-level verification and reflection logs, then keep the most recent valid records in active logs. Default keep is 1000. --dry-run writes nothing.0; 1 if keep is invalid
verify run COMMAND [--claim TEXT] [--timeout N]Execute COMMAND through the shell, capture exit code, duration, and redacted output tails, append an executed record, print the verdict. Default timeout 300 seconds. If MYTHIFY_DISABLE_RUN=1, refuse: execute nothing, record nothing, print [FAIL] verify run is disabled: MYTHIFY_DISABLE_RUN=1 is set. No command was executed and nothing was recorded. Unset it to enable execution, or use verify claim to record a self-reported attestation. and exit 2 (the unverified code, so callers branching on verify run treat a disabled run as not verified).0 if verified, 2 if unverified or disabled
verify claim CLAIM EVIDENCEAppend an attested record and print the [WARN] ATTESTED line.0
reflect [JSON] or reflect --action A --outcome O --observation OBS --next N [--root-cause R] [--lesson L]Record a structured reflection. Required keys: action, outcome (enum success, partial, failure), observation, next. A provided lesson is auto-recorded as a project lesson tagged auto-reflected. JSON positional takes precedence over flags. Missing keys or bad outcome: [FAIL], exit 1.0
classify TASK [--json] [--triage never|auto|always] [--platform auto|unknown|codex-desktop|codex-cli|claude-desktop|claude-code|cursor-desktop|cursor-agent] [--effort auto|low|medium|high] [--speed auto|standard|fast] [--session-model MODEL] [--model-profile auto|utility|balanced|strong|max|fast|standard|frontier] [--failure-count N] [--spawn-ceiling auto|lower_only|same_or_lower|allow_stronger] [--reviewer-strength auto|same_or_lower|allow_stronger]Classify a task before planning. Returns task type, risk, ambiguity, ceremony level, execution profile, verification strategy, fanout recommendation, fast model triage fit, capability-profile router, host-aware model policy, signals, and next action. --failure-count accepts a nonnegative executed-verifier failure count and cannot escalate beyond strong; max must be explicit. --triage auto runs one utility model only when the gate is recommended or required. Does not require .mythify state unless the selected local model command does.0
loop-fit TASK [--json]Read-only loop-fit advisory. Assess a task against ordered gates: is there a machine-checkable done-condition, does the work recur, is there a reproduction environment (git repo), does it need human judgment. Recommend loop (bounded outcome run), supervised (verifier-gated plan or outcome check), or direct, with the criteria, matched signals, and a suggested next command. Runs nothing, records no evidence, and needs no .mythify workspace.0
summaryFull session report: plans and progress, memory count, project and global lesson counts, verification stats (executed passed, executed failed, attested count), reflection count.0

Implementation notes:

  • verify run executes the command through the shell, streams stdout and stderr to temporary files, enforces timeout and output-size caps, and redacts common secret patterns before persisting or printing output tails.
  • init, protocol check, trace analysis commands, classify, and loop-fit do not require a workspace. route treats the workspace as optional and uses durable state when it is present. Other commands require a resolvable state directory, or MYTHIFY_DIR, which is created on demand.
  • --help output for the top level and each subcommand must be accurate.

MCP server: mcp-server/

Node 20+, ESM ("type": "module"). Dependencies: @modelcontextprotocol/sdk (current 1.x) and zod (4.x). package.json: name mythify-mcp, version 5.2.0, scripts {"start": "node src/index.js", "test": "node --test test/*.test.js"} (the glob form, because modern Node treats a bare directory argument to --test as a literal file and fails), engines node >= 20. Use the registration API that the installed SDK version supports (prefer registerTool); verify against the installed package, not from memory.

Exactly 47 tools: the 44 core tools below plus the 3 fanout tools defined in the "Fanout: parallel delegation" section. Tool descriptions must state what the tool does AND when to use it, since descriptions drive tool selection.

ToolInput schemaBehavior
classify_task{task: string, format?: enum(text, json), triage?: enum(never, auto, always), triage_engine?: enum(claude-cli, codex-cli, cursor-agent, command), triage_model?: string, triage_timeout_seconds?: number, platform?: enum(auto, unknown, codex-desktop, codex-cli, claude-desktop, claude-code, cursor-desktop, cursor-agent), effort?: enum(auto, low, medium, high), speed?: enum(auto, standard, fast), session_model?: string, model_profile?: enum(auto, utility, balanced, strong, max, fast, standard, frontier), failure_count?: nonnegative integer, spawn_ceiling?: enum(auto, lower_only, same_or_lower, allow_stronger), reviewer_strength?: enum(auto, same_or_lower, allow_stronger)}Classify a task before planning. Returns task type, risk, ambiguity, ceremony level, execution profile, verification strategy, fanout recommendation, utility model triage fit, capability-profile router, host-aware model policy, signals, and next action. failure_count supports bounded escalation through strong; max must be explicit. With triage: auto, run one utility local model only when the deterministic gate recommends it.
host_model_switch{action?: enum(switch, status, clear), platform?: enum(auto, unknown, codex-desktop, codex-cli, claude-desktop, claude-code, cursor-desktop, cursor-agent), target_model?: string, current_model?: string, thinking?: enum(auto, low, medium, high, xhigh, max), speed?: enum(auto, standard, fast), reason?: string, format?: enum(text, json)}Record, show, or clear a requested host chat model switch. switch writes .mythify/host-model.json, returns platform-specific switch guidance, registry-backed host_capability, switch_result, host_confirmation, and adapter_proof_scan, and makes later classify_task and fanout_start calls use the recorded target as the session model when no explicit or env session model is supplied. It does not claim to mutate or confirm the current host chat unless a future host integration exposes that capability and confirms the result.
provider_probe{provider?: enum(generic-openai-compatible, ollama, lm-studio, llama-cpp, vllm), base_url?: string, model?: string, check?: enum(models, chat, both), api_key_env?: string, timeout_seconds?: number, prompt?: string, format?: enum(text, json)}Probe an OpenAI-compatible provider by calling /v1/models and, when requested, /v1/chat/completions. Generic defaults: MYTHIFY_OPENAI_COMPAT_BASE_URL, MYTHIFY_OPENAI_COMPAT_MODEL, and MYTHIFY_OPENAI_COMPAT_API_KEY. api_key_env is restricted to the fixed allowlist containing MYTHIFY_OPENAI_COMPAT_API_KEY; arbitrary process variables are rejected before any request. provider: "ollama" defaults to MYTHIFY_OLLAMA_BASE_URL or http://localhost:11434/v1; provider: "lm-studio" defaults to MYTHIFY_LM_STUDIO_BASE_URL or http://localhost:1234/v1; provider: "llama-cpp" defaults to MYTHIFY_LLAMA_CPP_BASE_URL or http://localhost:8080/v1; provider: "vllm" defaults to MYTHIFY_VLLM_BASE_URL or http://localhost:8000/v1. Local profiles use provider-specific model env vars and no auth header by default. Returns provider availability, model presence, chat response tail, and material_not_evidence: true. It does not write state, spawn workers, or count as verification evidence.
local_model_run{provider?: enum(generic-openai-compatible, ollama, lm-studio, llama-cpp, vllm), role?: enum(reader, triage), base_url?: string, model?: string, prompt: string, api_key_env?: string, timeout_seconds?: number, max_tokens?: number, format?: enum(text, json)}Run a role-limited prompt against a localhost OpenAI-compatible provider. Generic defaults: MYTHIFY_OPENAI_COMPAT_BASE_URL, MYTHIFY_OPENAI_COMPAT_MODEL, and MYTHIFY_OPENAI_COMPAT_API_KEY. api_key_env uses the same fixed allowlist as provider_probe. provider: "ollama", provider: "lm-studio", provider: "llama-cpp", and provider: "vllm" default to local profiles. The base URL must be localhost, 127.0.0.1, ::1, or 0.0.0.0. Returns model output with material_not_evidence: true, evidence_status: "model_output_not_verification", writes_state: false, and verification_recorded: false. It does not edit files, run commands, write state, or count model output as verification evidence.
host_cli_probe{host?: enum(kimi-code, opencode, antigravity), bin?: string, timeout_seconds?: number, format?: enum(text, json)}Probe Kimi Code, OpenCode, or Antigravity CLI availability by running only version and help commands. Explicit bin basenames must match the selected host family. Defaults to MYTHIFY_KIMI_BIN, MYTHIFY_OPENCODE_BIN, or MYTHIFY_ANTIGRAVITY_BIN, then PATH and common install paths. Returns binary resolution, feature evidence, proof statuses for current-chat apply, current-chat confirm, worker model override, and thinking override, plus material_not_evidence: true. It does not execute a prompt, write state, spawn workers, or count as verification evidence. Antigravity MCP setup guidance lives in docs/antigravity-mcp-setup.md; the probe does not install or mutate MCP config.
host_cli_run{host?: enum(kimi-code, opencode, antigravity), bin?: string, prompt: string, cwd?: string, timeout_seconds?: number, model?: string, agent?: string, format?: enum(text, json)}Run a bounded non-interactive prompt through Kimi Code, OpenCode, or Antigravity. Kimi uses kimi --print -p PROMPT --final-message-only. OpenCode uses opencode run --format json [--model MODEL] [--agent AGENT] PROMPT. Antigravity uses agy [--model MODEL] -p PROMPT, requires explicit cwd, and never passes permission-bypass flags. Explicit bin basenames must match the selected host family. Defaults to MYTHIFY_KIMI_BIN, MYTHIFY_OPENCODE_BIN, or MYTHIFY_ANTIGRAVITY_BIN, then PATH and common install paths. Returns stdout and stderr tails, timeout and exit metadata, trust_policy, permission_policy, material_not_evidence: true, evidence_status: "worker_output_not_verification", writes_state: false, and verification_recorded: false. It does not edit files directly, write Mythify state, or count worker output as verification evidence; merged work must still be verified with verify_run.
execution_probe{adapter?: enum(google-colab-cli), bin?: string, timeout_seconds?: number, format?: enum(text, json)}Probe Google Colab CLI availability by running only version and help commands. Defaults to MYTHIFY_COLAB_BIN, then PATH and common install paths. Returns binary resolution, feature evidence, non_billable: true, job_execution_enabled: false, and material_not_evidence: true. It does not provision a runtime, request an accelerator, execute notebooks, upload data, write state, or count as verification evidence.
execution_run{adapter?: enum(google-colab-cli), bin?: string, cwd?: string, script_path: string, script_args?: string[], accelerator_type?: enum(cpu, gpu, tpu), accelerator?: enum(T4, L4, G4, H100, A100, v5e1, v6e1), billing_ack?: boolean, data_movement_ack?: boolean, cleanup_ack?: boolean, timeout_seconds?: number, format?: enum(text, json)}Run a guarded Google Colab CLI ephemeral job through colab run. Defaults to MYTHIFY_COLAB_BIN, then PATH and common install paths. It requires billing_ack: true, data_movement_ack: true, and cleanup_ack: true before invoking the CLI, resolves script_path locally, supports CPU by default or explicit GPU/TPU accelerator flags, never passes --keep, and returns stdout and stderr tails plus exit metadata. It writes no Mythify state and returns material_not_evidence: true, evidence_status: "remote_output_not_verification", and verification_recorded: false; remote logs or artifacts must be consumed by a separate verifier before any completion claim is verified.
lifecycle_probe{adapter?: enum(google-agents-cli, google-adk-cli), bin?: string, timeout_seconds?: number, format?: enum(text, json)}Probe Google Agents CLI or ADK CLI availability by running only version, help, and eval-help commands. Defaults to MYTHIFY_AGENTS_CLI_BIN or MYTHIFY_ADK_BIN, then PATH and common install paths. Returns binary resolution, feature evidence, can_probe_eval: true, eval_execution_enabled: false, deployment_enabled: false, material_not_evidence: true, and lifecycle_lane_contract with allowed probe commands, disabled lifecycle actions, future guarded actions, eval and deployment prerequisites, mutation policy, and material-only evidence status. It does not scaffold projects, run agents, execute evals, deploy, publish, mutate cloud resources, write project state, or count as verification evidence.
workflow_status{recent?: number, format?: enum(text, json)}Show a read-only dashboard of active plan, current step, next step, active outcome, memory and lesson counts, verification totals, recent verification records, and recent reflections. It must not mutate state and must not report model confidence as evidence.
verification_history{recent?: number, format?: enum(text, json)}Show a read-only history of executed and attested verification records, including verdict, command or evidence, exit code, duration, and plan or step context. It must not mutate state, rerun checks, or upgrade attested claims.
work_report{since?: enum(last, start), recent?: number, cursor?: string, peek?: boolean, mark?: boolean, format?: enum(chat, json)}Show a chat-ready live work report over durable plan, step, verification, and reflection events, with an Attention section for failed checks, failed steps, failure reflections, and attested warnings. By default it advances a cursor so repeated calls show only new events; peek leaves the cursor unchanged; mark advances the cursor to the latest event without showing old events and cannot be combined with since.
background_status{recent?: number, format?: enum(text, json)}Show a read-only background task view of durable outcome loops and fanout jobs, including task counts, statuses, and next actions. It must not mutate state and must not report model confidence as progress.
evidence_harness{recent?: number, format?: enum(text, json)}Show a read-only control view for autonomous agent work, including active steering state, evidence mix, attention items, delegated work counts, release readiness, and the next control action. It must not mutate state and must not treat worker output as verification.
outcome_progress{recent?: number, format?: enum(text, json)}Show a read-only progress view of active and recent outcome loops, including iteration budget, verifier exit details, metric score when present, and next action. It must not run checks, make attempts, stop loops, or treat notes as verification.
release_readiness{format?: enum(text, json)}Show a read-only release readiness view from recorded verification gates, project git state, and roadmap state. It must not rerun gates, mutate state, tag, publish, push, or declare the release safe.
fanout_timeline{recent?: number, format?: enum(text, json)}Show a read-only timeline of fanout job creation, task starts, task finishes, duration, status, errors, and output metadata. It must not mutate state and must not treat worker output as verification evidence.
phase_status{recent?: number, format?: enum(text, json)}Show a read-only Understand, Design, Build, Judge, Verify phase view of active plan steps and durable evidence counts. It must not mutate state and must not report model confidence as progress.
campaign_next_prompt{name?: string, format?: enum(text, json)}Render a chat-ready next prompt for the active or named campaign's current task and phase. It must not mutate state, run checks, advance a phase, or treat prompt output as verification evidence. Hosts may display or inject the returned prompt, then the host agent does the work and advances the campaign with evidence.
prompt_packet{kind?: enum(research, analysis, failure, handoff, review, campaign, next), name?: string, goal?: string, verify_command?: string, format?: enum(text, json)}Render a chat-ready prompt packet for research to implementation, analysis to plan, failure recovery, handoff, review, campaign, or the next useful workflow move. It must not mutate state, run checks, advance work, or treat prompt output as verification evidence. Hosts may display or inject the returned prompt, then the host agent does the work and records evidence.
workflow_route{task: string, format?: enum(text, json), triage?: enum(never, auto, always), triage_engine?: enum(claude-cli, codex-cli, cursor-agent, command), triage_model?: string, triage_timeout_seconds?: number, platform?: enum(auto, unknown, codex-desktop, codex-cli, claude-desktop, claude-code, cursor-desktop, cursor-agent), effort?: enum(auto, low, medium, high), speed?: enum(auto, standard, fast), session_model?: string, model_profile?: enum(auto, utility, balanced, strong, max, fast, standard, frontier), failure_count?: nonnegative integer, spawn_ceiling?: enum(auto, lower_only, same_or_lower, allow_stronger), reviewer_strength?: enum(auto, same_or_lower, allow_stronger)}Choose the next workflow route from prompt text, capability-profile policy, and durable state. It returns route, reason, loop_collision (the active loop families and which one steers, or null), next_command, prompt_packet, verification_strategy, chat_policy, pause_rules, state_writes, and evidence. It must not mutate state, run checks, advance work, or move execution out of the initiating host unless the user explicitly asks.
outcome_start{goal: string, success: string, verify_command: string, metric_command?: string, metric_floor?: number, max_iterations?: number, allowed_paths?: string[], frozen_paths?: string[], supersede?: string, visibility?: enum(auto, quiet, summary, verbose, threaded), name?: string, format?: enum(text, json)}Start a supervised outcome loop and set it active. The host agent acts between checks; Mythify records the verifier, metric, budget, and visibility policy. allowed_paths supplies advisory Git scope reporting to supervised checks. CLI outcome run enforces it against a clean Git baseline and stops on violations or inspection failures. The self-driving outcome run loop, --agent, --max-cost, and --escalate-after are CLI-only, like plan verify and plan import.
outcome_check{name?: string, notes?: string, audit?: boolean, timeout_seconds?: number, format?: enum(text, json)}Run the verifier and optional metric for the active or named outcome, append an iteration, append executed verification evidence, and return success, retry, or budget-exhausted guidance. audit: true re-runs a finished outcome's verifier without mutating its history and sets evidence_stale from the result. If MYTHIFY_DISABLE_RUN=1, refuse and record nothing.
outcome_status{name?: string, format?: enum(text, json)}Show active or named outcome status, verifier, metric, iteration budget, and next action.
outcome_results{name?: string, format?: enum(text, json)}Show all recorded verifier iterations and final state.
outcome_stop{name?: string, reason: string, format?: enum(text, json)}Mark an outcome stopped and clear the active pointer when it matches.
memory_store{key: string, value: string, category: enum(fact, decision, discovery, state) = "fact"}Upsert by key. Returns [OK] summary.
memory_recall{query?: string, category?: enum(fact, decision, discovery, state, all)}Substring search as in the CLI.
memory_clear{key?: string, confirm_clear_all?: boolean}With key: remove one. Without key and without confirm_clear_all: true: refuse with an explanation, do not clear.
lesson_record{title: string, detail: string, tags?: string[], scope: enum(project, global) = "project"}Write a lesson file per the format.
lesson_recall{tag?: string, scope: enum(project, global, all) = "all"}List lessons, labeled by scope.
plan_create{goal: string, name?: string, steps?: [{title: string, success_criteria?: string, verify_command?: string}], horizon?: number}Ids auto-assigned 1-based. Sets active plan. horizon creates default lookahead steps when steps is omitted.
plan_add_step{title: string, success_criteria?: string, verify_command?: string, plan?: string}Append to named or active plan.
plan_update_step{step_id: number, status: enum(pending, in_progress, completed, failed, skipped), result?: string, plan?: string}Enforce the evidence rule: completed or failed without result returns [FAIL] Evidence required ... and does NOT modify the plan. Every in_progress transition records a verification cursor. By default, completed also requires a later recorded executed verification with verified: true, exit_code: 0, and any stored verify_command matched exactly after normalization (see "Verified-step gate"). Otherwise it returns the same [FAIL] Verified evidence required ... text the CLI uses, without modifying the plan. Set MYTHIFY_REQUIRE_VERIFIED_STEP=0 to opt out. On success, include the next pending step in the response.
plan_status{plan?: string}Goal, progress count, step list with icons.
map_create{destination: string, name?: string, notes?: string, fog?: string[]}Chart a wayfinding decision map and set it active. Fog entries become F-prefixed Not-yet-specified patches.
map_add_ticket{title: string, type: enum(research, prototype, grilling, task), question?: string, mode?: enum(afk, hitl), blocked_by?: string[], verify_command?: string, from_fog?: string, map?: string}Add a decision ticket. The type fixes the mode (research and task afk, prototype and grilling hitl); mode is accepted only for task and otherwise returns [FAIL] Mode is fixed for .... Unknown blockers and already-graduated fog patches are refused.
map_claim{ticket_id: string, by?: string, map?: string}Claim an open, unblocked ticket and record a verification cursor. Refuses blocked tickets, tickets claimed by another party, and a second non-research ticket held by the same claimant.
map_resolve{ticket_id: string, answer: string, gist?: string, human_input?: string, out_of_scope?: boolean, fog?: string[], scope_out?: string[], map?: string}Close a claimed ticket. A hitl ticket without human_input returns the human-input refusal and does NOT modify the map, unless MYTHIFY_REQUIRE_HUMAN_INPUT=0. A ticket storing verify_command requires a passing executed record with exit code 0 and a matching normalized command at or after the claim cursor. out_of_scope: true files the ticket under Out of scope instead of Decisions.
map_status{map?: string}Read-only low-resolution map: destination, notes, decisions so far, frontier, claimed, blocked, fog, out of scope, and next action.
map_promote{map?: string, plan?: string, steps?: [{title: string, success_criteria?: string, verify_command?: string}], horizon?: number}Create a plan from a map with no open tickets and no ungraduated fog. The plan carries source: {kind: "map", ...} with the decisions and out-of-scope register. Refuses an unclear or already-promoted map.
verify_run{command: string, claim?: string, timeout_seconds?: number = 300}Execute through the shell, record an executed verification, return the verdict with output tails. If env MYTHIFY_DISABLE_RUN=1, refuse with an explanation and record nothing.
verify_claim{claim: string, evidence: string}Record an attested entry, return the [WARN] ATTESTED line.
reflect{action_taken: string, outcome: enum(success, partial, failure), observation: string, root_cause?: string, next_action: string, lesson?: string}Append reflection; auto-record lesson if provided (project scope, tag auto-reflected). Note: jsonl field names follow the file format (action, next), not the tool parameter names.

All tool results are text content prefixed with [OK], [FAIL], or [WARN]. Handlers never throw on bad state; they return explanatory text.

mcp-config.example.json: a complete example client configuration using a local absolute path placeholder like /absolute/path/to/mythify/mcp-server/src/index.js and a MYTHIFY_DIR env entry. This is the one allowed "placeholder", since the install path is genuinely user-specific.

Classification, execution profiles, and fast model triage

Classification is two-stage:

  1. Deterministic gate. classify and classify_task always compute task type, risk, ambiguity, ceremony, execution profile, verification hint, fanout fit, and model_triage.
  2. Optional fast model pass. The caller must opt in with --triage auto, --triage always, or the matching MCP triage argument. auto runs only when model_triage is recommended or required.

execution_profile may be direct, fast, standard, or full:

  • direct: answer or make one reversible edit with no protocol state.
  • fast: focused low-risk work skips plan state but still requires an executed verify run before completion is claimed.
  • standard: create a plan with verifiable steps, act step by step, and run verify run before completion.
  • full: use plan, memory, step updates, executed verification, reflection on failures, and summary.

Classification always returns model_policy. It separates:

  • model_router: provider-neutral routing across six independent axes: autonomy policy, execution topology, model profile, reasoning effort, review policy, and verification gate. Task classification selects utility, balanced, or strong. An explicit model_profile may also select max. failure_count moves one tier per supplied executed-verifier failure and is capped at strong. For independently parallel work, the router may recommend the MCP-only claude-ultracode adapter. The initiating host launches one native Claude workflow through fanout_start, monitors it with fanout_status, and ingests its material with fanout_results. Its autonomy policy inherits the user's request, its permissions remain host-owned, and its verifier is always deterministic-command-first.
  • provider_defaults: advisory provider defaults for each role. These are policy metadata only and do not route work by themselves. Precedence is future explicit role input, MYTHIFY_ROLE_<ROLE>_PROVIDER, then built-in defaults. Invalid env values are ignored with status: "invalid_env_ignored". Every role uses fallback_policy: "no_implicit_cross_provider_fallback". The object also declares timeout_metadata_fields and cost_metadata_fields so hosts know which fields are intentionally standardized.
  • provider_defaults.provider_catalog: provider-specific posture metadata for host, host_cli, local_openai_compatible, api_provider, command, and local_command. It records allowed roles, default roles, billing posture, execution boundary, evidence status, state-write posture, and fallback policy. Each resolved role also includes its selected provider_profile.
  • provider_defaults.adapter_interface_contract: stable metadata shape shared by the registry-backed adapter lanes. It records version, fields, lanes, fallback policy, and an execution policy of metadata_shape_only_no_runtime_change. MCP also includes a normalized candidate catalog from the capability registry; CLI exposes the same contract fields without using them as a router.
  • provider_defaults.role_assignment_contract: stable role-to-lane metadata for session, triage, reader, fanout worker, reviewer, verifier, remote execution, and agent lifecycle roles. It records default and selected providers, eligible adapter-interface lanes, evidence boundaries, state-write posture, and no-hidden-fallback guardrails. MCP additionally lists eligible candidate IDs from the adapter registry. The contract keeps runtime_routing_changed: false; role metadata never enables hidden fallback, remote execution, evals, deployments, or new state writes.
  • provider_defaults.api_provider_contract: metadata for hosted providers before Mythify can spend API credits. It currently covers OpenAI, Anthropic, and hosted OpenAI-compatible endpoints. It records auth env names, billing posture, timeout metadata fields, cost metadata fields, pricing URLs, and execution_enabled: false for general provider role routing. The explicit fanout API path is recorded separately with fanout_execution_enabled: true, engines anthropic and openai, required acknowledgement fields, .mythify/provider-audit.jsonl, and fanout_output_material_status: "material_not_verification".
  • provider_defaults.custom_adapter_contract: metadata for user-defined adapter paths. The command adapter is enabled only through MYTHIFY_TRIAGE_COMMAND and MYTHIFY_FANOUT_COMMAND, reads prompts on stdin, obeys role timeouts, writes no Mythify state, and returns material, not verification evidence. The http adapter is metadata-only with execution_enabled: false; it records env names for a future custom HTTP worker and lists the execution blockers that must be solved first.
  • Resolved role records include timeout and cost objects. timeout records timeout_seconds, timeout_source, timeout_enforced_by, and can_override. cost records billing posture, cost_estimate_supported: false, cost_estimate_status: "not_estimated", cost_estimate_cents: null, pricing references, and usage metadata field names. Pricing URLs are advisory references only.
  • session: host-selected current conversation model, model source, rough tier, effort policy, spawn ceiling, and recommendation. host_model_switch records intended host model changes in .mythify/host-model.json; the host still owns the actual current chat model switch. The optional host_confirmation record separates user-reported current model input from host-confirmed current model evidence. The adapter_proof_scan record reports supported, unsupported, or unknown apply and confirm paths without mutating host state.
  • session.recommendation: task-based host settings with action, legacy target_profile, canonical capability_profile, target_provider, target_model, target_api_model, target_model_source, target_model_status, target_model_tier, thinking, speed, resolution metadata, and reason. The action is one of keep, downgrade, upgrade, recommend_set, or recommend_discover.
  • spawn_ceiling: policy object with policy, source, session_model, session_model_source, session_model_tier, default, and opt-in rule.
  • reader: optional read-only model role for inspecting supplied material. It defaults to the localhost OpenAI-compatible provider path and can use the explicit Ollama profile. It returns material, not verification evidence.
  • triage: spawned problem-framing worker, engine, spawned model policy, model tier, relation to the session model, provider default, effort, timeout, max turns, and sandbox.
  • fanout_worker: default policy for independent fanout tasks, including canonical capability profile, provider-specific recommended model and effort, plus chat visibility (quiet, summary, verbose, or threaded).
  • reviewer: whether a separate reviewer worker is useful, its effort, and its independently selected capability profile and explicit stronger-model policy. Reviewers default to same-or-lower than the initiating session; reviewer_strength: "allow_stronger" records classifier policy. Actual fanout still requires role: "reviewer" plus reviewer_allow_stronger: true before reviewer fanout may exceed the session without the broader spawn_ceiling: "allow_stronger" escape hatch.
  • verifier: command-first verification policy, no model when an executable check exists.

Built-in role provider defaults:

RoleDefault providerAllowed provider values
sessionhosthost
triagehost_clihost_cli, local_openai_compatible, command
readerlocal_openai_compatiblelocal_openai_compatible, host
fanout_workerhost_clihost_cli, api_provider, command
reviewerhost_clihost_cli, api_provider, command
verifierlocal_commandlocal_command

Built-in role provider catalog:

ProviderDefault rolesAllowed rolesExecution boundaryEvidence
hostsessionsession, readerHost-selected current conversationHost output is not verification
host_clitriage, fanout_worker, reviewertriage, fanout_worker, reviewerBounded local host CLI workerWorker output is material, not verification
local_openai_compatiblereadertriage, readerLocalhost OpenAI-compatible model providerModel output is material, not verification
api_providernonefanout_worker, reviewerGuarded fanout API execution with explicit hosted provider acknowledgementsProvider output is material, not verification
commandnonetriage, fanout_worker, reviewerExplicit user commandCommand output is material, not verification
local_commandverifierverifierLocal executed verifierExit code is verification evidence

--platform and MCP platform may be auto, unknown, codex-desktop, codex-cli, claude-desktop, claude-code, cursor-desktop, or cursor-agent. --effort and MCP effort may be auto, low, medium, or high. --speed and MCP speed may be auto, standard, or fast. --model-profile, MCP model_profile, and MYTHIFY_MODEL_PROFILE may be auto, utility, balanced, strong, max, or the compatibility aliases fast, standard, and frontier. --failure-count, MCP failure_count, and MYTHIFY_FAILURE_COUNT accept a nonnegative count derived from executed verifier failures. Automatic escalation is capped at strong; max requires an explicit request. Auto speed preserves the host or CLI default; fast maps to Codex fast mode where supported; standard explicitly disables Codex fast mode for that spawned worker. --session-model, MCP session_model, and MYTHIFY_SESSION_MODEL provide the initiating model when the host can name it; if neither is set, Mythify uses .mythify/host-model.json when present. --spawn-ceiling, MCP spawn_ceiling, and MYTHIFY_SPAWN_CEILING may be auto, lower_only, same_or_lower, or allow_stronger; auto defaults to same_or_lower. --reviewer-strength, MCP reviewer_strength, and MYTHIFY_REVIEWER_STRENGTH may be auto, same_or_lower, or allow_stronger; auto defaults to same_or_lower. Auto effort keeps triage cheap and scales fanout or reviewer effort by risk and ceremony.

Host recommendations are capability-profile based, then resolved within the selected host provider. Direct low-risk prompts use utility; normal implementation, debugging, review, and docs use balanced; research, benchmark, design, security, release, and migration use strong; and max is explicit only.

ProfileOpenAIClaudeCursor
utilitygpt-5.6-luna, lowhaiku (claude-haiku-4-5), lowDiscover Luna, Haiku, Mini, Flash, or Composer
balancedgpt-5.6-terra, mediumsonnet (claude-sonnet-5), highDiscover Terra, Sonnet, Composer, or auto
stronggpt-5.6-sol, highopus (claude-opus-4-8), xhighDiscover Opus, Sol, or Gemini 3.1 Pro
maxgpt-5.6-sol, max or pro modefable (claude-fable-5), maxDiscover Fable, Opus, or Sol

Cursor discovery reads the installed runtime catalog. If no preferred match is available, it uses auto only when the catalog lists it; otherwise it leaves the model unset for the Cursor default. It never crosses to another provider. Canonical model overrides use MYTHIFY_HOST_UTILITY_MODEL, MYTHIFY_HOST_BALANCED_MODEL, MYTHIFY_HOST_STRONG_MODEL, and MYTHIFY_HOST_MAX_MODEL. Legacy MYTHIFY_HOST_FAST_MODEL and MYTHIFY_HOST_STANDARD_MODEL remain accepted after their canonical forms.

The fast model pass is not verification. It returns a problem frame that the main agent may use before planning. The required JSON shape is:

{
  "primary_type": "string",
  "secondary_types": ["string"],
  "ambiguity": "low|medium|high",
  "hidden_questions": ["string"],
  "likely_files_or_surfaces": ["string"],
  "verification_plan": ["string"],
  "fanout_plan": ["string"],
  "risk_notes": ["string"],
  "recommended_first_step": "string"
}

Supported fast triage engines are local-first and API-free: claude-cli, codex-cli, cursor-agent, and command. Selection order is explicit argument, MYTHIFY_TRIAGE_ENGINE, codex-cli when available, local CLI auto-detection, then MYTHIFY_TRIAGE_COMMAND. Fanout binary env vars are accepted as fallbacks for CLI paths. claude-cli defaults to model haiku; codex-cli and cursor-agent use their local defaults unless MYTHIFY_TRIAGE_MODEL or an explicit model is set. The command engine reads the triage prompt on stdin and must print JSON. It is the custom command adapter path for triage only; its output is material, not verification evidence.

Trace analysis

trace analyze is a CLI-only read-only surface for turning exported agent traces into Mythify product and eval signals. It intentionally has no hard runtime dependency on Hugging Face or datasets; callers export bounded JSONL or JSON slices first, then pass local files to Mythify.

Supported row shapes:

  • session traces: rows with trace, messages, metadata, and optional num_tool_calls
  • action rows: rows with context, completion, output_type, and an output object such as { "tool": "Bash", "input": { "command": "..." } }
  • scenario rows: rows with instruction, input, output, and prompt

The analyzer records counts for formats, sessions, models, harnesses, output types, trace event types, tool names, repeated shell commands, verifier-like command signals, verifier-like text signals, and error or recovery language. It then emits recommendations such as classifier scenario evals, action-first runtime behavior, automatic evidence detection, background monitoring, visual verification, and context-limit recovery.

The trace surface also has a playbook layer:

  • trace distill filters one model slice and renders a Markdown behavior profile.
  • trace compare filters target and baseline slices, compares visible metrics, and renders target-minus-baseline guidance.
  • trace playbook compresses a target slice into session-start operating rules for chat-native agent work.
  • trace install-playbook installs generated Markdown as a local Code or Codex skill with overwrite protection.

The measured signals are intentionally visible and reproducible: tool density, command density, read/edit rhythm, test/edit rhythm, verify/edit rhythm, top tools, verifier-like commands, and recovery language. Mythify does not attempt to extract private reasoning. The output is a practical behavior scaffold for agents that already run inside a host chat.

Guardrail: trace analysis is material, not verification. A Fable or Mythos trace can suggest what Mythify should do, but it cannot prove local work is complete. Completion claims still require verify run, verify_run, or an explicit attested warning when no executable check exists.

Research workflow

research is a CLI state surface for source-backed inquiry:

  • research start QUESTION [--name NAME] [--json]
  • research list [--json]
  • research add-source TITLE [--url URL] [--note TEXT] [--credibility C]
  • research add-claim CLAIM --evidence TEXT [--source ID] [--confidence C]
  • research add-question QUESTION
  • research summary [NAME] [--json]
  • research close [NAME] --decision TEXT

State lives under .mythify/research/:

  • active: current research record pointer.
  • <slug>.json: question, status, sources, claims, open questions, decision, created timestamp, and updated timestamp.

Research records are deliberately material-only. A claim inside a research record can guide a design or product decision, but it does not prove that local implementation work is complete. When research turns into code or docs, the host must move through a plan, outcome, or campaign and record executable verification where available.

Wayfinding map workflow

map is the state surface for the phase before a plan exists: work too big for one session whose route to the destination is not visible yet. A map holds questions to settle, not slices to build. The shape is adapted from the wayfinder skill (https://github.com/mattpocock/skills); the evidence gates are Mythify's.

State lives under .mythify/maps/:

  • active: current map pointer, cleared when a map is promoted.
  • <slug>.json: id, destination, notes, status (charting, clear, promoted), tickets, fog, out_of_scope, decisions, created, updated, and promoted_plan once promoted.

A ticket carries id (T-prefixed), title, question, type, mode, status (open, closed, out_of_scope), blocked_by, claimed_by, claimed_at, verification_cursor, optional verify_command and verified_command, resolution, human_input, resolved_at, and created. A fog patch carries id (F-prefixed), note, graduated_to, and created. An out-of-scope entry carries id (X-prefixed), note, reason, ticket_id, and created.

Four ticket types, each fixing whether a human is in the loop:

TypeModeResolution requirement
researchafkan answer; exempt from the one-ticket rule and runs in parallel
taskafk by default, hitl on requestan answer, plus a passing executed run matching verify_command when one is stored
prototypehitlan answer and human_input
grillinghitlan answer and human_input

--mode and the MCP mode field are accepted only for task. A mode override on any other type is refused, so a conversation cannot be quietly downgraded into something the agent answers by itself.

Four gates make a map Mythify rather than a decision board, and each refuses without mutating state:

  1. Claim before work. map claim refuses a blocked ticket, a ticket already claimed by someone else, and a second non-research ticket held by the same claimant. Claiming records verification_cursor, the append position of verifications.jsonl at claim time.
  2. Human input for HITL. map resolve refuses a hitl ticket without --human-input unless MYTHIFY_REQUIRE_HUMAN_INPUT=0, the explicit legacy opt-out that mirrors MYTHIFY_REQUIRE_VERIFIED_STEP. This is the attested claim rule applied to decisions: an agent's own words never settle a question that belongs to a human. The gate covers every resolution path, including --out-of-scope, because ruling a human's question out of scope is itself the human's call. Resolving under the opt-out stamps human_input_waived on the ticket and prints a [WARN], so a thawed gate always leaves a trace.
  3. Executed evidence for verifiable tasks. A ticket storing verify_command requires an executed record with verified: true, exit_code: 0, and a normalized command equal to the stored one, at or after the claim cursor. map verify runs that command and stamps the record with map, ticket_id, ticket_title, and ticket_type. Evidence recorded before the claim can never be reused.
  4. A clear way before handoff. map promote refuses a map with any open ticket or ungraduated fog patch.

--out-of-scope is the scoping escape hatch, not a bypass: it closes the ticket into the Out-of-scope register with its reason, leaves Decisions untouched, and skips the claim, block, human-input, and verifier gates because nothing is being decided. Out-of-scope work never graduates.

map promote calls the same plan-writing helper as plan create (create_plan_record in the CLI, createPlanRecord in the MCP runtime), so a promoted plan is byte-shaped like a hand-written one plus a source block of {kind: "map", map, destination, decisions, out_of_scope}. plan show renders that block as the decisions carried from the map and the plan's scope boundary.

map verify is CLI-only, like plan verify and plan import: it executes a command, so it stays on the surface that owns execution ergonomics.

Prompt packet workflow

prompt is a CLI read-only surface for chat-native reprompting:

  • prompt research [NAME] [--goal TEXT] [--verify COMMAND] [--json]
  • prompt analysis [--goal TEXT] [--verify COMMAND] [--json]
  • prompt failure [--goal TEXT] [--verify COMMAND] [--json]
  • prompt handoff [--goal TEXT] [--verify COMMAND] [--json]
  • prompt review [--goal TEXT] [--verify COMMAND] [--json]
  • prompt campaign [NAME] [--goal TEXT] [--verify COMMAND] [--json]
  • prompt map [NAME] [--goal TEXT] [--verify COMMAND] [--json]
  • prompt next [--goal TEXT] [--verify COMMAND] [--json]

Each packet returns:

  • kind: the requested kind.
  • selected_kind: the packet type actually rendered.
  • title: human-readable packet label.
  • source: the durable state source, such as research, campaign, verification, workflow state, or git state.
  • context: structured context for hosts that want JSON.
  • next_prompt: the chat-ready prompt to display or inject.
  • guardrail: material-only warning.

prompt next chooses the packet from durable state. It routes to failure recovery only when the latest executed verification is red, then to an active campaign, active research, active plan handoff, and finally analysis. MCP clients use prompt_packet for the same contract. Both surfaces must be read-only and must not convert prompt text into verification evidence.

Workflow router

route is the CLI decision-tree surface for choosing the next workflow shape without performing it:

  • route TASK [--json]
  • MCP clients use workflow_route with the same contract.
  • For broad or ambiguous prompts, chat hosts should call this before lower-level primitives such as classify, plan, outcome, campaign, prompt, or fanout.

The router combines deterministic classification, the active durable state, the latest executed verification, and protocol/workflow-router.json. It returns a route packet with the route id, reason, suggested next command, prompt packet kind, verification strategy, chat policy, pause rules, expected state writes, and evidence. It is read-only: the host chat still executes edits, runs checks, reports issues, and records evidence.

Priority order favors recovery and durable loops:

  1. latest executed verification is red: failure;
  2. full-send language such as "one shot", "in one go", "address all", or "yolo": campaign;
  3. active campaign or outcome with continue language: campaign or outcome;
  4. explicit wayfinding language, or an active map with continue language: map;
  5. explicit godaudits or godplans language: review or plan;
  6. explicit research or review language: research or review;
  7. active plan continuation: handoff;
  8. direct low-risk prompts: direct;
  9. otherwise: plan.

Full-send language keeps its higher priority, so a prompt that asks for execution routes to campaign even when it also sounds foggy. A map that has been promoted stops steering: its state view is null and routing falls through to the plan it produced. When a map is active and already clear, the next command becomes map promote rather than another ticket.

The route state view also carries godplans_plan and godaudits_audit summaries (null when the artifact is absent), read from .godplans/PLAN.mdx and .godaudits/AUDIT.mdx (with .md fallbacks) at the project root via mythify_godfiles.py and its JS mirror godfiles-core.js. When the routed shape is plan or review and the matching artifact has open tasks, the reason names the artifact and the next command becomes plan import --source godplans|godaudits so the artifact's own tasks and verify commands drive the work. Without god artifacts, route output is byte-identical to the pre-integration behavior. The CLI route command works without a .mythify workspace (needs_state is optional), so a fresh godplans project can be routed before init.

Campaign workflow

campaign is a CLI state surface for long-running "one-shot a project" work:

  • campaign start GOAL [--tasks JSON] [--name NAME] [--success TEXT] [--verify COMMAND]
  • campaign list [--json]
  • campaign status [NAME] [--json]
  • campaign prompt [NAME] [--json]
  • campaign watch [NAME] [--interval N] [--max-iterations N] [--json]
  • campaign add-task TITLE [--criteria TEXT]
  • campaign advance [NAME] --result TEXT
  • campaign task ID STATUS [RESULT]
  • campaign learn LESSON [--task ID] [--apply-next]
  • campaign stop [NAME] --reason TEXT

State lives under .mythify/campaigns/:

  • active: current campaign pointer.
  • <slug>.json: goal, success criteria, optional campaign verifier, current task id, generated or explicit tasks, phase events, learnings, status, created timestamp, and updated timestamp.

Each campaign task moves through the same loop:

  1. understand
  2. design
  3. build
  4. judge
  5. verify
  6. reflect

Advancing from reflect completes the current task and moves the frontier to the next pending task. campaign learn records a small improvement that should shape later tasks. This is the productized version of the long-horizon loop: durable task frontier, visible phase, verification slot, reflection, and learning carried forward.

When the campaign was started with --verify COMMAND, advancing from the verify phase executes that command, appends an executed record to verifications.jsonl (claim campaign <slug> task <id> verifier), and stamps the verifier exit onto the phase event. A failing verifier blocks the advance: the task stays in verify until the cause is fixed. Campaigns without a verifier keep the legacy prose-only advance. MYTHIFY_DISABLE_RUN=1 skips execution, consistent with verify run. Failed tasks display phase failed with explicit recovery guidance instead of silently rendering as understand, and skipping the final task releases the active pointer the same way completing it does.

Campaigns do not execute arbitrary project work by themselves. The host agent does the work, runs checks, and calls campaign advance or campaign task with the result. This keeps Mythify as the evidence and control layer rather than a hidden executor. campaign prompt renders the current task and phase as a host prompt without mutating state. campaign watch repeats that read-only render on an interval so a host-managed background loop can pick up the next prompt after an external advance. MCP clients use the read-only campaign_next_prompt tool for the same contract, workflow_route when they need Mythify to choose the next workflow path, or prompt_packet when they need the shared packet contract across research, analysis, failure recovery, handoff, review, campaign, and next.

The failure packet carries failed_command_streak: the count of consecutive failed executed runs of the latest failed command. At a streak of two or more, the packet adds a question-the-reference instruction: ask whether the success criterion itself is right, route that doubt to a human with a grilling ticket, and never weaken the verifier to pass. Repeated failure is the one moment the reference is most likely wrong, and reference doubt belongs to the surface that already requires outside judgment.

Smoke test: mcp-server/test/smoke.test.js

Uses node:test and the SDK Client with StdioClientTransport, spawning the server with MYTHIFY_DIR and HOME pointed at fresh temp directories. Assertions:

  1. tools/list returns exactly the manifest tool names (set equality), the 44 core tools plus fanout_start, fanout_status, fanout_results.
  2. classify_task returns a benchmark classification in text form with execution profile full, a question classification in JSON form with execution profile direct, and a command-backed fast triage result when requested.
  3. memory_store then memory_recall round-trips a value.
  4. plan_create with one step, then plan_update_step to completed without a result returns the evidence refusal and leaves the step pending. A result alone does not satisfy strict completion; a passing step-scoped verify_run recorded after the step starts is also required by default.
  5. verify_run with node -e "process.exit(0)" reports VERIFIED; with node -e "process.exit(3)" reports UNVERIFIED.
  6. memory_clear with no arguments refuses.
  7. Outcome tools start a loop, run a successful verifier, record iteration evidence, and fail cleanly when the retry budget is exhausted.
  8. After the calls, read memory.json and the plan file from the temp dir and assert the exact field names from the format contract (this enforces interop at the byte level).

Protocol: protocol/PROTOCOL.md

The canonical behavioral protocol is generated and hash-checked across host copies. Its size follows the behavior required by the current public surface; compactness is preferred, but no stale fixed line ceiling overrides contract completeness. It is written to steer a model, not to document the project. Required structure:

  1. Title and one-paragraph identity: "You are operating under the Mythify Protocol", an operational discipline layer; it changes how reliably the model works, not what it can do.
  2. Core rules, always active: act don't ask; lead with outcome; ground every claim (a completion claim requires an executed verification); bounded autonomy (pause only for destructive or irreversible actions, real scope changes, or input only the user can provide); anti-overengineering; persist state outside the context window on long tasks.
  3. Proportional ceremony table: trivial task (single edit or question) uses no protocol commands; focused low-risk fix or test tasks use the fast profile with verify run but no plan state; multi-step single-session task uses a plan plus executed verification of completion claims; long-horizon or multi-session work uses the full loop with memory and lessons.
  4. The autonomy loop: PLAN, ACT, VERIFY, REFLECT, then CORRECT or ADVANCE, with the exact CLI commands for each stage.
  5. Verification doctrine: executed beats attested; verify run whenever anything executable exists (tests, builds, linters, a curl, a file check); verify claim only when nothing executable exists, and it never counts as verified.
  6. Memory and lessons: what to store, when to recall (before architectural decisions, at session start), project vs global lessons.
  7. Command quick reference matching the CLI table exactly.
  8. A short MCP note listing the 38 tool names for clients using the server instead of the CLI, with delegation discipline for the fanout tools.

Protocol handshake

The CLI embeds the SHA-256 hash of protocol/PROTOCOL.md in PROTOCOL_SOURCE_SHA256. Generated protocol variants include the same hash in a metadata header:

<!-- Mythify protocol-sha256: HASH -->

python3 scripts/mythify.py protocol check [PATH ...] [--json] compares the embedded CLI hash with explicit protocol copy paths. With no paths, it checks the source repo protocol when present and any CLAUDE.md, AGENTS.md, and .cursorrules files in the current working directory. Every invocation also hash-pins any present protocol/release-gates.json and its packaged mirror against the embedded RELEASE_GATES_SHA256: the gate list an optimizer is graded against is a frozen node, so a legitimate change must also update the constant in scripts/mythify_protocol.py. A missing manifest is skipped, not failed; release readiness already surfaces its absence.

Failure modes:

  • Missing metadata header: print [FAIL], name the path, and exit 1.
  • Hash mismatch: print [FAIL], show the expected and actual short hashes, and exit 1.
  • Source protocol mismatch in a source checkout: print [FAIL], name protocol/PROTOCOL.md, and exit 1.

The command reads files only; it does not create .mythify state. A copied install can therefore verify that its protocol file and CLI came from the same source protocol before an agent trusts either one.

scripts/build_variants.py

Reads protocol/PROTOCOL.md, writes three files at the repo root: CLAUDE.md, AGENTS.md, .cursorrules. Each begins with the header line:

<!-- Generated from protocol/PROTOCOL.md by scripts/build_variants.py. Edit the source, then rebuild. -->

followed by the protocol hash metadata header, a blank line, and the protocol body verbatim. Idempotent. Zero dependencies. Exit 0 on success with an [OK] line listing the files written.

Skill surfaces

skills/mythify/ is the Manus-style skill package. SKILL.md starts with YAML frontmatter:

---
name: mythify
description: Operational discipline protocol that gives any AI agent Mythos-class autonomy patterns, including planning loops, executed verification, persistent memory, and structured reflection. Use when executing multi-step or long-horizon tasks, when work spans sessions, when progress claims need grounding in evidence, or when the user asks for mythify or mythos-style autonomous execution.
---

Body: condensed protocol with pointers describing when to read each reference file. References, each under 100 lines, v2 semantics throughout:

  • references/autonomy-loop.md: the loop, proportional ceremony, step lifecycle.
  • references/self-verification.md: executed vs attested, evidence rule, examples.
  • references/memory-system.md: memory categories, project vs global lessons, read-before-decide discipline.
  • references/meta-prompts.md: the injectable behavioral constraints (act over ask, lead with outcome, grounding, bounded autonomy, anti-overengineering, persistence).
  • references/chat-experience.md: report cadence and visible-progress rules for chat hosts.
  • references/godplans-godaudits.mdx: the godplans and godaudits bridge contract (plan import mapping, strict step context, artifact ownership, MDX safety rules). GFM-safe MDX, kept .mdx to match the artifacts it documents.

Dual-runtime chat front doors ($name in Codex, /name in Claude Code) live beside the package skill:

  • skills/mythify-work/: visible multi-step work loop. It keeps execution in the initiating chat, marks the report cursor, and surfaces a report after steps and verifiers.
  • skills/mythify-route/: visible router. It shows the route decision, reason, and next action before mutating state.
  • skills/mythify-verify/: visible verifier. It turns a claim into executed evidence, reports the verdict, and completes the active step when applicable.

These focused skills exist because chat experience is an execution-model problem, not a Node-versus-Python problem. Godpowers-style visibility comes from in-band Markdown skills and report cadence. The CLI and MCP server remain the evidence ledger behind that chat surface.

scripts/package_skill.py

Zips skills/mythify/ contents so SKILL.md sits at the zip root with references/ beside it. Output: dist/mythify.skill. Stdlib zipfile only. Prints the entry list and [OK] on success.

scripts/install_user.sh

Installs a versioned, self-contained CLI under $XDG_DATA_HOME/mythify/VERSION/cli or $HOME/.local/share/mythify/VERSION/cli. The mythify and mythify-uninstall launchers do not point back to the source checkout, so the checkout can be moved or deleted after installation. The optional MCP server is staged under the same version root and exposed through mythify-mcp.

The installer is one transaction across the CLI, MCP server, launchers, chat hook, skills, and ownership metadata. It preflights and stages components before publication. Any later failure restores the byte-for-byte prior installation on update, or removes the partial version on first install. Rerunning the installer is the supported update path.

The self-hosted uninstaller removes only components named by the installation ownership manifest. File ownership is bound by content hashes and directory ownership by private markers. Missing or changed evidence makes uninstall fail closed before deletion. Project .mythify/ state, skipped components, unrelated files, and other installed versions are preserved.

By default, installation copies skills/mythify* directories into both the Codex skills root ($CODEX_HOME/skills or $HOME/.codex/skills) and Claude Code skills root ($CLAUDE_HOME/skills or $HOME/.claude/skills). --skip-skills disables both copies, --skills-root PATH overrides the Codex destination, --skip-claude-skills skips only the Claude copy, --claude-skills-root PATH overrides the Claude destination, and --install-chat-hook installs the optional report helper. The helper only prints report --since last --cursor chat --format chat output and never mutates host config.

scripts/package_cli.py

Builds dist/mythify-cli-VERSION.tar.gz, a deterministic standalone archive containing the Python runtime, protocol manifests, chat skills, and installer. Installing from the archive uses --skip-mcp because the Node package is a separate release asset. Stable entry ordering, metadata, and gzip headers make identical source trees produce identical bytes.

README.md

The README is the beginner product guide, not an exhaustive duplicate of this specification. It must keep these contracts visible:

  • Explain that Mythify improves the agent harness, not the underlying model.
  • Lead with the self-contained user installer and standalone CLI artifact.
  • Teach the minimal plan, execute, verify, and complete loop before advanced routing, outcome, campaign, and fanout surfaces.
  • State that CLI and MCP share one state directory and are kept aligned through checked manifests and interop tests. Never promise that independent runtimes cannot drift.
  • Link the committed efficacy smoke evidence with its small-sample, fixed-order, unpinned-model, no-speed-claim, and no-monetary-cost caveats.
  • Keep the complete command and tool reference here in docs/design.md.
  • State the actual distribution contract: checkout or standalone local install, GitHub release assets, and no npm registry publication.
  • Keep development gates and the MIT license discoverable.

The README also links docs/cli-to-model-runtime-migration.md, which explains the opt-in path from CLI-only usage to host, local model, API provider, execution substrate, and lifecycle lanes without hidden routing, automatic spending, or deployment.

Document only what exists. No npx instructions, no badges for services not set up.

Local Evaluation Harness

scripts/local_model_eval.py is the built-in bare-vs-Mythify smoke harness. It creates paired task workspaces, runs the selected local CLI or command engine, then verifies each workspace with python3 -m unittest. The model output is material; the evaluation metric comes from verifier exit codes. Mythify evidence success is stricter than line presence: the harness parses verifications.jsonl and requires an executed record with verified: true, exit_code: 0, and the exact expected verifier command. Attested, failed, malformed, and different-command records do not satisfy --require-pass.

The JSON report must include:

  • summary: per-mode attempts, model success, verified success, Mythify evidence success, success rates, average model duration, and the winner by verified success rate.
  • verified_task_success: the direct answer to the product question. It records metric: "verified_success_rate", comparison: "mythify_vs_bare", evidence_source: "per-workspace python3 -m unittest exit code", bare and Mythify rates, the rate delta, winner, conclusion, Mythify evidence rate, duration delta, and statistical_strength: "local_smoke".
  • false_completion_claims: the direct answer to the false-completion question. It records metric: "false_completion_rate", completion_signal: "model_exit_code_0", the evidence source, per-mode completion signals, verifier-backed claims, false completion claims, false-completion rates, rate delta, lower-rate winner, conclusion, and the local smoke-test caveat. The harness must not classify tone or confidence in model prose as evidence.
  • profile_overhead: the direct answer to the profile-overhead question. It records metric: "avg_model_duration_seconds", comparison: "mythify_profile_vs_bare", measured duration evidence source, bare and Mythify average model durations, delta, ratio, lower-duration winner, conclusion, per-profile attempts, per-profile duration deltas, speed fields, and the local smoke-test caveat. The harness must not estimate timing or use model-reported timing as evidence.
  • local_model_benefit: the direct answer to the local-model task-fit question. It records metric: "local_model_candidate_task_categories", supported local roles, per-scenario task categories, local reader or triage candidate roles, fit reasons, observed verifier-backed success rates, Mythify evidence rates, category summaries, and the local smoke-test caveat. The harness must not claim provider-specific local model benefit unless the report came from a local-model-backed command or provider check.
  • fanout_value: the direct answer to the fanout-value question. It records metric: "fanout_value_fit", helpful and waste-prone task shapes, policy rows, per-scenario fanout-fit metadata, observed verifier-backed success rates, Mythify evidence rates, single-worker sufficiency counts, and the local smoke-test caveat. The harness must not treat parallelism, worker enthusiasm, or worker output alone as value; proving real fanout value requires independent worker outputs, a merged artifact, and a verifier run after the merge.
  • role_strength: the direct answer to the stronger-model role question. It records metric: "stronger_model_role_requirement", default spawn ceiling, required stronger roles, scoped reviewer opt-in roles, broad stronger opt-in roles, per-role policy rows, observed harness rates, and the local smoke-test caveat. The harness must not claim bigger models are generally better; stronger-model benefit requires a paired run with the role isolated.
  • runs: per-workspace model exit details, verifier exit details, output tails, and Mythify evidence counts including the secret-safe passing_expected_verifications count.

The built-in scenarios are a rerunnable smoke signal, not a large benchmark. Do not upgrade verified_task_success.conclusion into a release claim without recording the exact harness command and its JSON output as evidence.

The committed July 13, 2026 Codex smoke result is linked from docs/evidence/efficacy-reproduction.md. It contains two paired trials of one small scenario. It is evidence of that run only, not a general efficacy or speed claim. The model was not pinned, pair order was fixed, monetary cost and subscription quota were not measured, and the raw report is not committed.

Housekeeping

.gitignore:

.DS_Store
.mythify/
.mcp.json
__pycache__/
*.pyc
node_modules/
dist/
*.corrupt-*
*.tgz
npm-debug.log*

LICENSE: MIT, copyright 2026 Mythify contributors.

Tests

tests/test_mythify.py

Stdlib unittest. Invoke the CLI as a subprocess with sys.executable, a scrubbed environment (MYTHIFY_DIR removed, HOME pointed at a per-test temp directory so the real global lessons store is never touched), and cwd inside a temp project directory. Required coverage:

  • init creates the documented layout, adds the default state directory to .gitignore, preserves existing ignore rules, and re-init warns and exits 0.
  • Commands without a workspace fail with exit 1 and the documented message.
  • State discovery walks up: a command run from a nested subdirectory finds the project .mythify.
  • MYTHIFY_DIR overrides discovery and is created on demand.
  • Plan lifecycle: create with steps, create without steps, add-step, list, show, switch, archive; slug collision produces -2.
  • Step updates: valid transitions; invalid status rejected with exit 1; completed and failed without RESULT rejected with exit 1 and do not modify the plan; completed with RESULT persists result and prints the next pending step.
  • Memory: set, overwrite, get with query and category filter, clear KEY, clear without args fails with exit 1, clear --all empties.
  • Lessons: project add and list; global add and list (under the temp HOME); tag filter; scope filter.
  • verify run: true-like command verified with exit 0; false-like command unverified with exit 2; timeout case (--timeout 1 on a 5-second sleep) records exit_code -1 and exits 2; the jsonl record matches the executed format.
  • verify claim: exits 0, prints ATTESTED warning, jsonl record has verified null.
  • reflect: JSON form, flags form, missing required key fails, lesson auto-recording creates a project lesson tagged auto-reflected.
  • summary and status: run without error and include the expected counts.
  • Corrupt recovery: write garbage into memory.json, run memory get, expect [WARN] on stderr, exit 0, and a memory.json.corrupt-* file.

tests/test_maps.py

Stdlib unittest over the CLI as a subprocess, with the same scrubbed environment as tests/test_mythify.py plus MYTHIFY_REQUIRE_HUMAN_INPUT and MYTHIFY_MAP_CLAIMANT removed. Required coverage:

  • Charting: map create records destination, notes, and fog; ticket type fixes the mode; a mode override on a non-task ticket is refused and the map is left unmodified; unknown blockers are refused; a fog patch graduates exactly once.
  • Claim discipline: blocked tickets cannot be claimed; one claimant holds one non-research decision ticket at a time while research claims stay parallel; a ticket claimed elsewhere is refused; resolving an unclaimed ticket is refused.
  • Resolution evidence: a HITL ticket refuses a self-authored resolution and leaves the ticket open; it resolves with --human-input; MYTHIFY_REQUIRE_HUMAN_INPUT=0 is the explicit legacy opt-out; an AFK ticket needs no human input; an empty answer is refused; a task ticket with a verifier refuses resolution until map verify passes; a failing verifier does not satisfy the gate; evidence recorded before the claim cannot be reused; the map verify record carries the ticket context.
  • Scope and fog: an out-of-scope ticket stays out of the decision index; a resolution can surface fresh fog and scope boundaries; map scope-out records a standalone boundary; new fog reopens a clear map.
  • Promotion: refused while any ticket or fog remains; carries decisions and the out-of-scope register into the plan's source block; accepts explicit steps; clears the active pointer and refuses a second promotion.
  • Surfaces: status reports the active map, map show refers to tickets by name, map list marks the active map, prompt map renders the wayfinding rules, and prompt next selects the map while one is active.

mcp-server/test/map-tools.test.js

An in-memory registrar harness (the same shape as plan-tools.test.js) asserts that the MCP runtime enforces the identical gates: the registrar wires every MAP_TOOL_NAMES handler with a title and description, mode overrides on conversation tickets are refused, blocked tickets stay off the frontier, one decision ticket is held at a time, map_resolve refuses a HITL ticket without human_input, a verifier-bearing task ticket needs a passing exit-0 record at or after the claim cursor, fog graduates once, out-of-scope work skips the decision index, map_promote refuses an unclear or already-promoted map, and map_status never mutates.

tests/test_local_model_eval.py

Offline command-engine tests verify the local benchmark harness without real model accounts. The default --mythify-profile auto resolves built-in focused bugfix scenarios to fast, requiring executed verification evidence but no plan record. --mythify-profile standard keeps the older plan-plus-verify behavior and requires both plan and verification evidence.

tests/test_interop.py

Stdlib only. Skips (unittest skip, not failure) unless node is on PATH and mcp-server/node_modules exists. It runs the Python CLI and the Node MCP server against one temp .mythify directory and covers the shared mutating state surface, not probes or MCP-only fanout.

Coverage matrix:

  • CLI writes, MCP reads: host-model switch, plan create, step in_progress, memory set, lesson add, and outcome start.
  • MCP writes, CLI reads: host_model_switch, plan_add_step, plan_update_step, memory_store, memory_clear, lesson_record, outcome_check, outcome_start, outcome_stop, verify_run, verify_claim, and reflect.
  • CLI writes after MCP writes, MCP reads: host-model clear is checked so the host model state contract is bidirectional.
  • Verification records and reflection records are checked on disk because both APIs intentionally append logs rather than exposing a read tool for individual log entries.

Whole-state refusal no-mutation checks

Refusal paths that promise "nothing was recorded", "nothing was cleared", or "the plan was not modified" must be tested with whole-state snapshots. A snapshot includes every regular file under the active .mythify directory, keyed by relative path and content hash. Representative CLI and MCP refusal tests must compare the full snapshot before and after the refused operation so new files, removed files, and unrelated file rewrites are all caught.

Representative refusal paths:

  • CLI: step completed without RESULT, step completed blocked by strict step evidence, memory clear with no target, and verify run with MYTHIFY_DISABLE_RUN=1.
  • MCP: plan_update_step without result, memory_clear with no target, and verify_run with MYTHIFY_DISABLE_RUN=1.

Fanout: parallel delegation (MCP only)

Fanout gives the orchestrating model parallel sub-workers through one-shot declarative jobs: the model emits a task list once, and the server does the spawning, sequencing, and collecting. This avoids requiring turn-by-turn worker orchestration from the initiating host, without making a model-tier capability claim. Fanout is MCP-only; the CLI does not implement it (a CLI host has shell access and usually its own parallelism), and docs/design.md is explicit about that divergence.

Implementation lives in mcp-server/src/fanout.js, wired into the server in mcp-server/src/index.js.

Engines

A worker is one fresh model invocation with no memory of the conversation. Seven engines, selected by MYTHIFY_FANOUT_ENGINE or auto-detected in this order: explicit env value, else codex-cli if a codex binary resolves, regardless of the initiating host, else claude-cli if a claude binary resolves, else cursor-agent if Cursor Agent resolves, else anthropic if ANTHROPIC_API_KEY is set, else command if MYTHIFY_FANOUT_COMMAND is set, else fanout_start refuses with a message listing all seven options. openai and claude-ultracode are explicit-only. OpenAI needs an endpoint and model; UltraCode needs a supported Claude CLI and an independently parallel objective.

EngineMechanismBillingModels
claude-cliSpawn <bin> -p --output-format json --model <model> --max-turns <N> with the assembled prompt on stdin, cwd = project root (parent of .mythify/). Parse the JSON output: result is the text, is_error true or a non-zero exit means failure.Claude subscription (or whatever auth the claude CLI resolves)Aliases haiku, sonnet, opus, fable, or any full model ID
claude-ultracodeProbe claude --version and claude --help, require Claude Code 2.1.203 or newer with UltraCode support, then spawn one <bin> -p --output-format json --model <model> --effort ultracode --max-turns <N> workflow. Reuses the fanout job, status, result, timeout, redaction, audit, and worktree lifecycle.Claude subscription or enabled usage creditsDefaults to opus; explicit models remain subject to the spawn ceiling
codex-cliSpawn <bin> --ask-for-approval never exec --cd <project> --sandbox <mode> --skip-git-repo-check --ephemeral --color never --output-last-message <tmp> [-m <model>] - with the assembled prompt on stdin. Exit 0 means success; the worker output is the output-last-message file, falling back to stdout.Codex CLI local login, usually ChatGPT/Codex subscription authAny model the local Codex CLI supports; empty model means the CLI default
cursor-agentSpawn cursor-agent --print --output-format text --trust --workspace <project> [--mode <mode>] [--model <model>] <prompt-file-instruction>, or cursor agent ... when the configured binary is cursor. The assembled prompt is written to a temporary file under .mythify/tmp/; stdout is the worker output.Cursor Agent local login, usually Cursor subscription authAny model Cursor Agent exposes; empty model means the agent default
anthropicPOST https://api.anthropic.com/v1/messages (anthropic-version 2023-06-01) with max_tokens from env. Aliases map: haiku to claude-haiku-4-5, sonnet to claude-sonnet-5, opus to claude-opus-4-8, fable to claude-fable-5. Join text blocks.API key (ANTHROPIC_API_KEY)Any Claude model ID
openaiPOST <MYTHIFY_FANOUT_BASE_URL>/chat/completions with MYTHIFY_FANOUT_API_KEY.Provider API keyAny model the endpoint serves
commandRun the MYTHIFY_FANOUT_COMMAND shell template; prompt on stdin; stdout is the output; exit 0 is success.Whatever the command doesAnything (generic CLI agents; also used by CI to test the job machinery with no network)

The command engine is the supported custom command adapter path for fanout. It is bounded by fanout validation, worker timeout, context byte caps, and the depth guard. Its output is still material for the orchestrator, never final verification evidence.

Selecting claude-cli invokes Claude Code through claude -p. That is token-cost-sensitive usage: included usage applies only within plan limits, and if usage credits are enabled and included limits are reached, continued usage can be billed at standard API pricing. Fanout start output, job metadata, task metadata, and provider audit cost metadata include a warning for claude-cli. claude-ultracode adds a stronger warning because xhigh reasoning and dynamic workflow subagents can consume substantially more quota. It accepts exactly one task per job, forces effort: ultracode, records execution_mode: ultracode, and refuses before job creation when the installed Claude CLI is too old or does not advertise UltraCode support.

The hosted provider engines, anthropic and openai, require hosted_provider_billing_ack: true, hosted_provider_data_ack: true, and hosted_provider_material_ack: true before the job is created. The guard acknowledges metered external billing, remote prompt and context transmission, and the material-only status of provider output. Refusal happens before any fanout job directory or provider audit row is written.

claude-cli binary resolution (Claude Desktop launches MCP servers with a minimal PATH): MYTHIFY_FANOUT_CLAUDE_BIN if set, else claude on PATH, else the first existing of ~/.claude/local/claude, /opt/homebrew/bin/claude, /usr/local/bin/claude. Resolution failure names the env var in the error.

codex-cli binary resolution: MYTHIFY_FANOUT_CODEX_BIN if set, else codex on PATH, else the first existing of ~/.local/bin/codex, /opt/homebrew/bin/codex, /usr/local/bin/codex. Resolution failure names the env var in the error. Workers run with HOME, TERM=dumb, an augmented PATH, CODEX_HOME when set, XDG_CONFIG_HOME when set, and the fanout guards. They do not inherit OPENAI_API_KEY; the intended path is local codex login.

cursor-agent binary resolution: MYTHIFY_FANOUT_CURSOR_BIN if set, else MYTHIFY_FANOUT_CURSOR_AGENT_BIN, else cursor-agent on PATH and common locations, else cursor on PATH and common locations. When the resolved binary name is cursor, Mythify prepends the agent subcommand. Workers run with HOME, TERM=dumb, an augmented PATH, XDG_CONFIG_HOME when set, and the fanout guards. They do not inherit CURSOR_API_KEY; the intended path is local cursor-agent login or cursor agent login.

claude-cli worker environment is curated, not inherited: HOME, TERM=dumb, PATH (server PATH augmented with ~/.local/bin, /opt/homebrew/bin, and /usr/local/bin), plus CLAUDE_CODE_OAUTH_TOKEN when present in the server environment, plus the guards below. Harness variables (CLAUDECODE, CLAUDE_CODE_*, ANTHROPIC_BASE_URL) are NOT passed through: a server spawned by Claude Code inherits harness routing that breaks nested workers. Subscription auth setup is documented as: run claude /login once in a terminal, or run claude setup-token and set CLAUDE_CODE_OAUTH_TOKEN in the MCP client's env block. A worker failure whose output contains Not logged in or 401 is reported with exactly that remediation.

Model, ceiling, and effort selection

Most specific wins: per-task model overrides per-job model overrides MYTHIFY_FANOUT_MODEL overrides the engine default (haiku for claude-cli, opus for claude-ultracode, claude-haiku-4-5 for anthropic, empty string for codex-cli and cursor-agent, which means each local CLI uses its configured default). The same precedence applies to engine, so one job may mix engines and models across tasks (for example five haiku drafters and one sonnet reviewer; the reviewer task is still independent and reviews material supplied in its prompt, not other tasks' outputs).

Spawn ceiling is checked after model resolution. session_model comes from the tool call, MYTHIFY_SESSION_MODEL, or .mythify/host-model.json; spawn_ceiling comes from the tool call or MYTHIFY_SPAWN_CEILING, defaulting to same_or_lower. Mythify classifies known model names into rough tiers: small, fast, standard, strong, frontier, or unknown. If both the session model and spawned model have known tiers, fanout_start refuses stronger spawned models unless the ceiling is allow_stronger. A safer narrow path exists for review: a task with role: "reviewer" may exceed the session under same_or_lower only when the job also sets reviewer_allow_stronger: true. That reviewer opt-in does not affect worker tasks and does not override lower_only. Unknown tiers are recorded as uncheckable; Mythify does not guess blank local CLI defaults.

Effort is a separate field with the same precedence: per-task effort overrides per-job effort, which overrides MYTHIFY_FANOUT_EFFORT, which falls back to a model-derived default. The resolved effort and effort_source are stored on both the job and task records, shown in status and result output, and included in the assembled worker prompt as Requested effort: <level>.

Speed is tracked separately from effort. Per-task speed overrides per-job speed, which overrides MYTHIFY_FANOUT_SPEED, which otherwise stays auto. auto preserves the platform default.

Platform mapping:

  • codex-cli: fast adds service_tier = "fast" and features.fast_mode = true; standard adds features.fast_mode = false.
  • claude-cli: resolved effort is passed as --effort; speed is recorded and included in the worker prompt because Claude Code exposes no separate speed flag.
  • claude-ultracode: effort is fixed to ultracode; the engine requires one task, launches one native dynamic workflow, and uses the same status and result lifecycle as other fanout jobs.
  • cursor-agent: model, effort, and speed are resolved against the local cursor-agent models list. For example, model: "gpt-5.6-sol", effort: "high", and speed: "fast" resolves to gpt-5.6-sol-high-fast when that id is available. If no matching encoded id is found, Mythify leaves the requested model unchanged.

Tools (3, total 47)

ToolInput schemaBehavior
fanout_start{tasks: [{title: string, prompt: string, context_paths?: string[], role?: enum(worker, reviewer), isolation?: enum(none, worktree), model?: string, engine?: string, effort?: enum(auto, low, medium, high), speed?: enum(auto, standard, fast)}], purpose?: string, model?: string, engine?: string, effort?: enum(auto, low, medium, high), speed?: enum(auto, standard, fast), visibility?: enum(auto, quiet, summary, verbose, threaded), session_model?: string, spawn_ceiling?: enum(auto, lower_only, same_or_lower, allow_stronger), reviewer_allow_stronger?: boolean, hosted_provider_billing_ack?: boolean, hosted_provider_data_ack?: boolean, hosted_provider_material_ack?: boolean, timeout_seconds?: number}Validate 1 to MYTHIFY_FANOUT_MAX_TASKS independent tasks, resolvable engines, context containment, model ceilings, kill switch, depth guard, and hosted-provider acknowledgements. engine: claude-ultracode requires exactly one task and a supported Claude CLI. Each task receives the full self-contained instruction for this worker; the worker sees only that prompt plus readable context_paths content. isolation: worktree gives a writing task a fresh Git worktree and branch; changed work is committed for host merge, while an unchanged branch is removed. Non-Git setup falls back to the shared root with recorded metadata. Create .mythify/fanout/<job_id>/job.json, return the job id immediately, and run workers with a concurrency pool. Each task is a fresh model call that costs real money, subscription quota, or local compute. Visibility defaults to summary unless visibility, purpose, or task prompts request quiet, verbose, or threaded reporting.
fanout_status{job_id?: string}Default: most recent job. Per-task lines with the step icon convention plus counts, engine, execution mode, model, model tier, effort, speed, visibility, and elapsed. This is also the monitoring surface for native UltraCode jobs. Quiet jobs show aggregate progress and failures only. If the job is marked running on disk but unknown to the in-memory registry (server restarted), mark its running tasks interrupted and say so.
fanout_results{job_id?: string, task_id?: number}Return outputs of completed and failed tasks (failures include the error and remediation). For UltraCode, this ingests the native workflow's final response as material, not verification evidence. Per-task text in the tool result is capped at 20000 characters with a note pointing at the task output file. Warns when tasks are still running.

Job ids: fo-<YYYYMMDDHHMMSS>-<4 random hex>. Worker prompt assembly: fixed preamble (you are a delegated worker; the task is self-contained; do not ask questions; return only the deliverable), then each context file as a labeled fenced block, then the task prompt. context_paths resolve within the project root; absolute paths are accepted only when they still resolve inside that root. Total inlined context per task is capped at MYTHIFY_FANOUT_CONTEXT_BYTES with an explicit truncation marker; an unreadable path fails the task at validation time with a clear error.

Fanout visibility controls what the host should surface in the main chat. Modes are quiet, summary, verbose, and threaded; auto is accepted on input only. summary is the resolved default and should show worker titles, status counts, and notable findings. quiet suppresses per-task status lines except failures. verbose permits detailed worker output in the chat. threaded asks the host to create visible worker chats only when the host has native thread support; otherwise hosts should fall back to summary. Auto visibility infers from purpose and task prompts, then defaults to summary.

On-disk format

.mythify/fanout/<job_id>/
|-- job.json
`-- task-<id>-output.md
.mythify/provider-audit.jsonl

job.json (atomic writes on every transition):

{
  "id": "fo-...", "created": "ISO-8601", "engine": "str", "model": "str",
  "billing": "str", "cost_tracking": "metadata_only_no_estimate",
  "cost_estimate_status": "not_estimated", "cost_estimate_cents": null,
  "pricing_url": "str",
  "model_source": "str", "model_tier": "str", "model_ceiling_status": "str",
  "session_model": "str", "session_model_source": "str",
  "session_model_tier": "str", "spawn_ceiling": "str",
  "spawn_ceiling_source": "str", "reviewer_allow_stronger": false,
  "hosted_provider_engines": ["anthropic|openai"],
  "hosted_provider_billing_acknowledged": false,
  "hosted_provider_data_acknowledged": false,
  "hosted_provider_material_acknowledged": false,
  "effort": "low|medium|high",
  "effort_source": "str", "speed": "auto|standard|fast",
  "speed_source": "str", "visibility": "quiet|summary|verbose|threaded",
  "visibility_source": "explicit|env|prompt|default",
  "visibility_requested": "auto|quiet|summary|verbose|threaded",
  "visibility_reason": "str", "purpose": "str",
  "timeout_seconds": 600,
  "timeout_source": "explicit|env:MYTHIFY_FANOUT_TIMEOUT_SECONDS|default|default_invalid_env_ignored",
  "last_updated": "ISO-8601",
  "tasks": [
    {"id": 1, "title": "str", "status": "pending|running|completed|failed|interrupted",
     "role": "worker|reviewer", "isolation": "none|worktree",
     "worktree": "absent or object with isolated, branch, path, changed, committed, cleanup_failed, and note fields",
     "engine": "str", "model": "str", "model_source": "str",
     "billing": "str", "cost_tracking": "metadata_only_no_estimate",
     "cost_estimate_status": "not_estimated", "cost_estimate_cents": null,
     "pricing_url": "str",
     "model_tier": "str", "model_ceiling_status": "str",
     "stronger_reviewer_opt_in": false,
     "effort": "low|medium|high", "effort_source": "str",
     "speed": "auto|standard|fast", "speed_source": "str",
     "timeout_seconds": 600,
     "timeout_source": "explicit|env:MYTHIFY_FANOUT_TIMEOUT_SECONDS|default|default_invalid_env_ignored",
     "started_at": "ISO-8601 or null",
     "finished_at": "ISO-8601 or null", "duration_seconds": 0.0,
     "error": "str or null", "output_file": "task-1-output.md", "output_bytes": 0}
  ]
}

Worktree metadata is written when an isolated task starts. A completed writing task keeps its branch name and records changed: true, committed: true; the temporary path is null after successful cleanup. An unchanged isolated task records null branch and path after cleanup. Setup fallback records isolated: false plus a note. Interrupted-task recovery removes only an exact job-owned temporary worktree and branch that Git still registers together. It records cleaned_on_recovery: true only when both cleanup commands succeed; otherwise it retains the surviving identifiers, records the original pair, and marks cleanup_failed: true.

provider-audit.jsonl is append-only and receives one start event and one finish event per spawned fanout task. Each row records:

  • surface: "fanout_worker", provider class, engine, model, role, effort, speed, job id, task id, and task title.
  • Billing and cost metadata fields: billing posture, cost_tracking, cost_estimate_status, cost_estimate_cents, and pricing_url.
  • Redacted request metadata: prompt SHA-256, prompt byte count, timeout seconds, timeout source, and prompt_redacted: true.
  • Hosted provider acknowledgement metadata: whether the task required hosted provider acknowledgements, the required acknowledgement fields, and whether billing, data transmission, and material-only output were acknowledged.
  • Redacted output metadata on finish: output file, output byte count, output_redacted: true, and whether an error was present.
  • output_material_status: "material_not_verification", records_verification_evidence: false, and the verifier boundary: worker output must be merged by the orchestrator and verified with verify_run or outcome_check.

The audit log must never store raw prompts, raw context blocks, API keys, authorization headers, or worker output. It audits existing fanout worker execution only; it does not enable any separate hosted provider execution path or upgrade provider output into evidence.

Configuration

EnvDefaultMeaning
MYTHIFY_DISABLE_FANOUTunset1 disables all three tools (they refuse with an explanation).
MYTHIFY_HOST_PLATFORMautoDeclares the initiating host for session policy. Worker engine selection still defaults to codex-cli when available unless explicitly overridden.
MYTHIFY_FANOUT_ENGINEautoclaude-cli, claude-ultracode, codex-cli, cursor-agent, anthropic, openai, command.
MYTHIFY_FANOUT_MODELengine defaultDefault worker model.
MYTHIFY_SESSION_MODELrecorded host model or unknownCurrent host session model used for spawn ceiling checks. Beats .mythify/host-model.json when set.
MYTHIFY_MODEL_PROFILEautoCapability profile for classification and routing: auto, utility, balanced, strong, max, or a legacy alias.
MYTHIFY_FAILURE_COUNT0Nonnegative executed-verifier failure count used for bounded one-tier escalation capped at strong.
MYTHIFY_SPAWN_CEILINGsame_or_lowerSpawn ceiling: auto, lower_only, same_or_lower, or allow_stronger.
MYTHIFY_REVIEWER_STRENGTHsame_or_lowerReviewer strength policy: auto, same_or_lower, or allow_stronger.
MYTHIFY_OLLAMA_BASE_URLhttp://localhost:11434/v1Local Ollama OpenAI-compatible /v1 endpoint for provider: "ollama".
MYTHIFY_OLLAMA_MODELunsetOllama model id for probe chat checks and local reader or triage runs.
MYTHIFY_LM_STUDIO_BASE_URLhttp://localhost:1234/v1Local LM Studio OpenAI-compatible /v1 endpoint for provider: "lm-studio".
MYTHIFY_LM_STUDIO_MODELunsetLM Studio model id for probe chat checks and local reader or triage runs.
MYTHIFY_LLAMA_CPP_BASE_URLhttp://localhost:8080/v1Local llama.cpp OpenAI-compatible /v1 endpoint for provider: "llama-cpp".
MYTHIFY_LLAMA_CPP_MODELunsetllama.cpp model id for probe chat checks and local reader or triage runs.
MYTHIFY_VLLM_BASE_URLhttp://localhost:8000/v1Local vLLM OpenAI-compatible /v1 endpoint for provider: "vllm".
MYTHIFY_VLLM_MODELunsetvLLM model id for probe chat checks and local reader or triage runs.
OPENAI_API_KEYunsetOpenAI API key env name recorded in hosted provider metadata. Fanout's OpenAI-compatible engine uses MYTHIFY_FANOUT_API_KEY instead.
MYTHIFY_OPENAI_API_MODELunsetOpenAI API model id env name recorded in hosted provider metadata.
ANTHROPIC_API_KEYunsetAnthropic API key env name recorded in hosted provider metadata and used by the guarded anthropic fanout engine after hosted provider acknowledgements.
MYTHIFY_ANTHROPIC_API_MODELunsetAnthropic API model id env name recorded in hosted provider metadata.
MYTHIFY_HOSTED_OPENAI_COMPAT_BASE_URLunsetHosted OpenAI-compatible /v1 endpoint env name recorded in provider metadata.
MYTHIFY_HOSTED_OPENAI_COMPAT_API_KEYunsetHosted OpenAI-compatible API key env name recorded in provider metadata.
MYTHIFY_HOSTED_OPENAI_COMPAT_MODELunsetHosted OpenAI-compatible model id env name recorded in provider metadata.
MYTHIFY_HOSTED_OPENAI_COMPAT_PROVIDERunsetOptional hosted OpenAI-compatible provider label env name recorded in provider metadata.
MYTHIFY_HOSTED_OPENAI_COMPAT_PRICING_URLunsetOptional hosted OpenAI-compatible pricing URL env name recorded in provider metadata.
MYTHIFY_HOST_UTILITY_MODELprovider mappingCanonical host recommendation override for utility work.
MYTHIFY_HOST_BALANCED_MODELprovider mappingCanonical host recommendation override for balanced work.
MYTHIFY_HOST_STRONG_MODELprovider mappingCanonical host recommendation override for strong work.
MYTHIFY_HOST_MAX_MODELprovider mappingCanonical host recommendation override for explicitly selected max work.
MYTHIFY_HOST_FAST_MODELcanonical utility mappingCompatibility override used after MYTHIFY_HOST_UTILITY_MODEL.
MYTHIFY_HOST_STANDARD_MODELcanonical balanced mappingCompatibility override used after MYTHIFY_HOST_BALANCED_MODEL.
MYTHIFY_ROLE_SESSION_PROVIDERhostAdvisory provider default for the session role. Invalid values are ignored.
MYTHIFY_ROLE_TRIAGE_PROVIDERhost_cliAdvisory provider default for the triage role. Invalid values are ignored.
MYTHIFY_ROLE_READER_PROVIDERlocal_openai_compatibleAdvisory provider default for the reader role. Invalid values are ignored.
MYTHIFY_ROLE_WORKER_PROVIDERhost_cliAdvisory provider default for the fanout worker role. Invalid values are ignored.
MYTHIFY_ROLE_REVIEWER_PROVIDERhost_cliAdvisory provider default for the reviewer role. Invalid values are ignored.
MYTHIFY_ROLE_VERIFIER_PROVIDERlocal_commandAdvisory provider default for the verifier role. Invalid values are ignored.
MYTHIFY_FANOUT_EFFORTmodel-derivedDefault worker effort: auto, low, medium, or high.
MYTHIFY_FANOUT_SPEEDautoDefault worker speed: auto, standard, or fast. Auto preserves platform defaults; fast enables Codex fast mode where supported.
MYTHIFY_FANOUT_VISIBILITYautoWorker visibility mode: auto, quiet, summary, verbose, or threaded. Auto infers from purpose and task prompts, then defaults to summary.
MYTHIFY_FANOUT_CONCURRENCY3Parallel workers per job.
MYTHIFY_FANOUT_MAX_TASKS16Max tasks per job.
MYTHIFY_FANOUT_MAX_TOKENS8000API engines' max_tokens.
MYTHIFY_FANOUT_MAX_TURNS25claude-cli --max-turns.
MYTHIFY_FANOUT_TIMEOUT_SECONDS600Per-worker timeout; on expiry the worker is killed and the task fails with a timeout error.
MYTHIFY_FANOUT_PRICING_URLunsetOptional pricing reference recorded for openai fanout engine cost metadata. No estimates are computed.
MYTHIFY_FANOUT_CONTEXT_BYTES200000Total inlined context per task.
MYTHIFY_FANOUT_OUTPUT_BYTES1048576Total captured stdout plus stderr per local CLI or command worker; on overflow the worker is killed and the task fails with retained diagnostic output.
MYTHIFY_FANOUT_CLAUDE_BINresolvedPath to the claude binary.
MYTHIFY_FANOUT_CLAUDE_ARGSemptyExtra claude args, for example --allowedTools "Bash".
MYTHIFY_FANOUT_CODEX_BINresolvedPath to the codex binary.
MYTHIFY_FANOUT_CODEX_SANDBOXread-onlyCodex worker sandbox mode.
MYTHIFY_FANOUT_CODEX_ARGSemptyExtra codex exec args.
MYTHIFY_FANOUT_CURSOR_BINresolvedPath to cursor-agent or cursor.
MYTHIFY_FANOUT_CURSOR_AGENT_BINresolvedPath to cursor-agent, used only when MYTHIFY_FANOUT_CURSOR_BIN is not set.
MYTHIFY_FANOUT_CURSOR_MODELSauto-listOptional whitespace or comma-separated Cursor model id list. When unset, Mythify runs cursor-agent models or cursor agent models to resolve encoded model ids.
MYTHIFY_FANOUT_CURSOR_MODEaskCursor Agent worker mode. Empty string omits --mode.
MYTHIFY_FANOUT_CURSOR_FORCEunset1 adds --force to Cursor Agent workers.
MYTHIFY_FANOUT_CURSOR_ARGSemptyExtra Cursor Agent args.
MYTHIFY_FANOUT_BASE_URL, MYTHIFY_FANOUT_API_KEYunsetopenai engine endpoint and key.
MYTHIFY_FANOUT_COMMANDunsetcommand engine shell template.

Guards

  • Depth limit of one: workers are spawned with MYTHIFY_FANOUT_DEPTH=1 and MYTHIFY_DISABLE_FANOUT=1 in their environment, and fanout_start refuses when MYTHIFY_FANOUT_DEPTH is already set in the server's own environment.
  • Fanout results are material, not verification: the orchestrator merges them and then verifies the merged work with verify_run. The protocol text says this explicitly.
  • Server lifetime caveat (documented): background workers live in the MCP server process; if the client disconnects or the server dies, running tasks die with it, and fanout_status reports them as interrupted afterward.

Smoke coverage (mcp-server/test/, runs in CI with no network)

Using the command engine with a deterministic local template and stub local CLI binaries: 47-tool set equality; a 3-task command job runs to completion and fanout_results returns the outputs; context_paths content demonstrably reaches the worker prompt; the kill switch refuses; the depth guard refuses; a failing command produces a failed task with captured stderr; job.json matches the format contract field by field; stub claude-cli, codex-cli, and cursor-agent workers prove argv, prompt delivery, environment guards, and auth remediation behavior without network access.

Verified-step gate

Strict step evidence is enabled by default. Marking a step completed requires both a non-empty RESULT string and evidence of a passing executed verification, so that a "completed" step is backed by a real exit code rather than only a prose claim. MYTHIFY_REQUIRE_VERIFIED_STEP=0 is the legacy opt-out; values 0, false, no, and off disable the gate for compatibility.

The rule, identical in the CLI step command and the MCP plan_update_step tool:

  • The gate applies ONLY to status completed. failed, in_progress, skipped, and pending are never blocked by it (you must always be able to record a failure or a state change).
  • The RESULT argument is still required first; the verified-step check runs after the non-empty-RESULT check.
  • Evidence is satisfied when verifications.jsonl contains at least one record after the step's verification_cursor with kind == "executed", verified == true, and exit_code == 0. New records with non-null plan or step_id fields must match the target plan slug and step id. Older records without step-bound fields, and new records with null step context, remain compatible only when they were appended after the cursor. Attested records (kind == "attested") never satisfy the gate. When the step stores a non-empty verify_command, the verification record's normalized command must match it exactly.
  • Every transition to in_progress stores the current verification record count as verification_cursor. plan verify sets the cursor before running the command. Legacy steps without a cursor fall back to the step's updated_at, or the parent plan's created timestamp when the step was never updated.
  • When a satisfying record exists, the gate also compares the latest one's recorded provenance against the present. Visible movement between the run and the completion claim (the commit changed, or a clean-at-run worktree is now dirty) prints a [WARN] by default and refuses under strict_context; the indeterminate dev-loop case (dirty at run, dirty now) stays silent.
  • Completing a step while MYTHIFY_REQUIRE_VERIFIED_STEP=0 disables the gate stamps strict_gate_waived on the step and prints a [WARN]. The opt-out keeps working; it never works silently, and the harness surfaces waived completions as attention items.
  • On failure the plan is NOT modified and the command prints [FAIL] Verified evidence required: strict evidence mode is enabled by default, but no passing executed 'verify run' with exit code 0 was recorded since this step started. When the step stores a verify_command, the recorded command must match it. Run the step's verifier first, or set MYTHIFY_REQUIRE_VERIFIED_STEP=0 to use legacy prose-only completion. The CLI exits 1; the MCP tool returns that text.

This is the honest-evidence upgrade: with the gate on, the autonomy loop's ACT step (step ID in_progress) sets the lower bound, the VERIFY step (verify run) records the passing check, and only then does step ID completed succeed.

Versioning

This is Mythify v5.0.0. Fanout was added in 2.1.0; 2.2.0 added local subscription-backed codex-cli and cursor-agent engines; 2.3.0 added task classification; 2.4.0 added optional fast model triage after classification, execution profiles, platform-aware model policy, initiating-model awareness, spawn ceiling checks, and additive fanout model and effort metadata; 2.5.0 makes the CLI verify run honor MYTHIFY_DISABLE_RUN for parity with the MCP server, and adds the MYTHIFY_REQUIRE_VERIFIED_STEP gate to both the CLI step command and the MCP plan_update_step tool; 3.0.0 aligns the model-runtime orchestration surface, local model lane, host CLI worker lane, hosted provider fanout guardrails, execution substrate lane, agent lifecycle lane, registry-generated adapter docs, and release-readiness surfaces under the v3 roadmap; 3.0.1 fixes standalone MCP tarball startup by packaging all runtime manifests under mcp-server/protocol/; 3.1.0 adds quick-start installation and live work reports; 3.2.0 and 3.2.1 refine report mark mode; 3.2.2 rejects mark-plus-since report calls that would otherwise hide expected events; 3.2.3 releases the follow-up documentation hygiene fixes from the continuous audit loop; 3.3.0 adds chat-visible report attention summaries for failures and warnings plus packaged skill guidance for chat-first Mythify use; 3.4.0 adds trace analysis and playbook generation; 3.5.0 adds research records, campaigns, and campaign reprompt surfaces; 3.6.0 adds workflow prompt packets for research, analysis, failure recovery, handoff, review, campaign, and next-prompt routing, plus read-only workflow route surfaces for CLI and MCP hosts; 3.6.1 makes the router the default front door in CLI help, docs, skill instructions, and MCP descriptions while keeping primitive commands available; 3.6.2 makes strict step evidence the default and divides non-core surfaces into workflow, advanced, and labs tiers backed by the checked surface manifest; 3.6.3 adds Codex-style chat front-door skills and installer support for a Godpowers-style visible Mythify experience; 3.6.4 fixes strict step evidence so explicit null-context verification records cannot complete steps while older records without context keys remain compatible; 3.6.5 fixes cross-runtime timestamp comparison in the strict evidence gate and makes CLI outcome check honor the execution kill-switch; 3.6.6 adds cross-runtime classification and verification record-shape conformance coverage; 3.6.7 caps captured subprocess output for local CLI and command fanout workers; 3.6.8 adds default .mythify/ .gitignore coverage during CLI init; 3.6.9 adds the MCP server dependency audit gate to the Node CI matrix; 3.6.10 marks MCP [FAIL] tool results with isError: true; 3.6.11 adds CLI --version and makes the MCP server read its reported version from package.json; 3.6.12 refreshes the roadmap release status after the DOC-001 audit slice; 3.6.13 clarifies README architecture wording for the DOC-002 audit slice; 3.6.14 adds stable empty-state coverage for the read-only workflow views; 3.6.15 slugifies explicit state lookup names before filesystem access; 3.6.16 labels outcome allowed_paths as advisory host-edit hints; 3.6.17 warns when malformed JSONL evidence records are skipped; 3.6.18 adds strict gate-decision conformance tests; 3.6.19 aligns CLI and MCP verifier output-cap and no-exit evidence semantics; 3.6.20 adds shared JSONL locks for appends and log compaction; 3.6.21 redacts obvious secret patterns from stored verifier output tails; 3.6.22 contains fanout context_paths to the project root; 3.6.23 restricts explicit host CLI bin overrides to selected-host binary names; 3.6.24 fsyncs atomic state-file temp files before rename and best-effort fsyncs parent directories after rename; 3.6.25 kills fanout subprocess process groups on timeout and output-cap failures; 3.6.26 uses bounded JSONL tail reads for recent strict gates and cursor-based reports; 3.6.27 moves classification policy facts into the shared classification manifest; 3.6.28 extracts deterministic classification into direct-import CLI and MCP modules; 3.6.29 extracts host model switch record helpers into direct-import CLI and MCP modules; 3.6.30 extracts trace analysis and playbook formatting into a direct-import CLI helper module; 3.6.31 extracts MCP provider probing and local model role-runner helpers into a direct-import MCP helper module; 3.6.32 extracts MCP host CLI probe and worker helpers into a direct-import MCP helper module; 3.6.33 extracts MCP execution adapter probe and run helpers into a direct-import MCP helper module; 3.6.34 extracts MCP lifecycle probe helpers into a direct-import MCP helper module; 3.6.35 extracts MCP provider defaults, adapter contracts, and role assignment metadata into a direct-import MCP helper module; 3.6.36 extracts MCP model policy construction and model triage runner helpers into a direct-import MCP helper module; 3.6.37 extracts Python model policy construction, provider-default metadata, and model triage runner helpers into a direct-import CLI helper module; 3.6.38 extracts Python durable IO helpers into a direct-import CLI helper module; 3.6.39 extracts Python research and campaign workflow stores into a direct-import CLI helper module; 3.6.40 extracts Python prompt packet and workflow route helpers into a direct-import CLI helper module; 3.6.41 extracts Python outcome loop store and command handlers into a direct-import CLI helper module; 3.6.42 extracts Python read-only dashboard, history, report, background, progress, readiness, timeline, and phase view helpers into a direct-import CLI helper module; 3.6.43 moves Python trace command handlers into the direct-import trace helper module; 3.6.44 extracts Python memory and lesson stores plus command handlers into a direct-import CLI helper module; 3.6.45 moves Python host-model state helpers and command handlers into the direct-import host-model helper module; 3.6.46 extracts MCP adapter and host integration tool registrations into a direct-import MCP helper module; 3.6.47 extracts MCP read-only view tool registrations into a direct-import MCP helper module; 3.6.48 extracts MCP memory and lesson tool registrations into a direct-import MCP helper module; 3.6.49 extracts MCP outcome loop tool registrations; 3.6.50 extracts MCP plan tool registrations; 3.6.51 extracts MCP verification and reflection tool registrations; 3.6.52 extracts Python parser, model triage, and status view helpers plus MCP workflow tools, view builders, status views, fanout policy, and fanout registration helpers; 3.6.53 adds the dual-runtime parity CI gate and documents the parity discipline for shared CLI and MCP behavior changes; 3.6.54 adds default planning horizon support, Codex-first worker selection, and Claude CLI worker cost warnings; 3.6.55 makes the Mythify chat skills dual-runtime invocable (/name in Claude Code, $name in Codex) and installs them into both the Codex and Claude Code skills roots; 3.6.56 adds the CLI harness command and MCP evidence_harness tool as a read-only control view for autonomous agent work; 3.6.57 adds godplans and godaudits artifact awareness with the CLI plan import command, artifact-gated routing and readiness and harness surfacing, an executed campaign verifier, and the mythify_godfiles.py and godfiles-core.js shared parsers; 4.0.0 unifies the evidence spine with per-step verify_command and plan verify, adds the bounded self-driving outcome run loop with a cost budget ledger, git scope enforcement, and consecutive-failure escalation, adds git-worktree isolation for parallel writing fanout workers, and routes all recorded output through a single secret-redaction choke point (redact.js); 4.1.0 adds the read-only loop-fit advisory that recommends a bounded loop, a supervised loop, or doing a task directly, assessed against the loop-worthiness gates; 4.2.0 adds interrogative-anchored freshness routing to research, a research provenance advisory that flags uncited claims as material, verification-drift and long-run reminders in the evidence harness, a high-stakes labeled-variants prompt for hard-to-reverse fixes, and the tool-use-contract doc. 4.3.0 hardens evidence provenance, release gates, scoped self-driving loops, standalone distribution, and deterministic release assets. 5.0.0 adds shared provider-neutral capability profiles, bounded verifier-failure escalation, live Cursor catalog discovery, and a native Claude UltraCode adapter over the existing fanout lifecycle. The CLI reports 5.0.0 through --version; the MCP server reads package.json and reports the package version through server info.