misterspec

Reference

Command Reference

Every command misterspec currently registers — the public surface and the hidden, agent-facing internal surface alike. misterspec treats internal as a real, documented contract (Constitution Principle IX: structured JSON, stable error codes) — never a hidden implementation detail.

Every command below accepts --dir <path> (default .) unless noted otherwise. Every failure returns {"ok":false,"error":{"code","message"}} with a distinct process exit code.

misterspec init public

Purpose: Bootstrap a new misterspec project.

Flags: --dir (target directory, default .); --agent <id> (agent to install Skills for — omit for the interactive TUI in a real terminal).

misterspec init --agent claude-code --dir ./my-project

misterspec --version public

Purpose: Print the running binary's own version. Never touches the network or the filesystem.

misterspec --version
{"ok":true,"version":"v1.2.0"}

A build with no embedded version (e.g. go build without -ldflags) reports "development build" instead of a blank or misleading value.

misterspec --update public

Purpose: Check GitHub for a newer release and, once confirmed, replace the running binary and refresh Skills — the one deliberate exception to misterspec's otherwise network-free command surface.

Behavior: reports the current and latest version; if already current, stops there with no download and no prompt. If a newer release exists, it asks for explicit confirmation before changing anything. Once confirmed, it downloads the release asset matching the running OS/architecture, verifies it against the release's own published SHA256SUMS file, and only then atomically replaces the binary — any failure at any step (release check, no matching asset, checksum mismatch, a declined prompt) leaves the installed binary and Skills completely untouched. If the current directory is an already-initialized misterspec project (a .misterspec/install.json is present), it also reinstalls Skills for that project's own recorded agent integration, reusing the exact same install path misterspec init uses.

misterspec --update
{"ok":true,"update":{"current":"v1.1.5-alpha","latest":"v1.2.0","status":"updated","skills_refreshed":true}}

Other status values: "up_to_date" (nothing to do) and "declined" (you said no). skills_refreshed is always present — false, not an error, when the current directory isn't an initialized project.

internal resolve <id>

Purpose: Resolve an entity ID to its canonical artifact.

misterspec internal resolve SPEC-014
{"ok":true,"id":"SPEC-014","path":"ai/programs/PRG-001/features/FEAT-004/specs/SPEC-014/spec.md"}

internal inspect <id>

Purpose: Return deterministic metadata for an artifact.

misterspec internal inspect SPEC-014
{"ok":true,"entity":{"id":"SPEC-014","type":"spec","status":"ready","parent":"FEAT-004","depends_on":["SPEC-011"],"supersedes":[]}}

A Task number is only unique within its owning Spec — two different Specs may each have their own TASK-001. To name a Task unambiguously from outside its own Spec, use the composite form SPEC-###:TASK-###:

misterspec internal inspect SPEC-014:TASK-003
{"ok":true,"entity":{"id":"TASK-003","type":"tasks","status":"pending","parent":"SPEC-014","depends_on":[],"supersedes":[]}}

A bare TASK-### (no Spec given) still resolves when exactly one Spec in the project claims that number. When more than one Spec claims it, the command fails with spec_context_required instead of guessing — retry with the composite form.

internal parent <id>

Purpose: Return the structural parent.

misterspec internal parent SPEC-014
{"ok":true,"parent":{"id":"FEAT-004","type":"feature"}}

internal children <id>

Purpose: Return structural children.

Flags: --type <entity-type> (filter to one entity type).

misterspec internal children FEAT-004 --type spec
{"ok":true,"children":[{"id":"SPEC-011","type":"spec"},{"id":"SPEC-014","type":"spec"}]}

internal create <type>

Purpose: Atomically allocate the next ID and scaffold its initial artifact.

Flags: --parent <id> (required for feature, spec); --slug <name> (required for knowledge, learning).

misterspec internal create spec --parent FEAT-004
{"ok":true,"created":{"id":"SPEC-015","type":"spec","path":"ai/.../specs/SPEC-015/spec.md"}}

internal create-artifact <kind>

Purpose: Create a canonical subordinate artifact (plan, tasks, validation) for a Spec.

Flags: --for <spec-id> (required).

misterspec internal create-artifact plan --for SPEC-014
{"ok":true,"created":{"type":"plan","path":"ai/.../SPEC-014/plan.md","for":"SPEC-014"}}

internal fingerprint <path>

Purpose: Calculate a source file's content fingerprint.

misterspec internal fingerprint ai/.../SPEC-014/spec.md
{"ok":true,"source":{"path":"ai/.../spec.md","algorithm":"sha256","fingerprint":"sha256:..."}}

internal inventory <dir>

Purpose: Return a deterministic file inventory for a directory.

misterspec internal inventory ai/raw
{"ok":true,"files":[{"path":"ai/raw/notes.md","extension":".md","size":842}]}

internal validate [<id>]

Purpose: Run structural validation — one entity if an ID is given, the whole project otherwise.

misterspec internal validate SPEC-014
{"ok":true,"valid":true,"findings":[]}

Duplicate Task IDs are flagged only within the same Spec's Tasks artifact — two different Specs legitimately sharing a TASK-NNN number is not reported as a duplicate.

Validation also checks a Spec's declared requirements (### R1, ### R2, …) against each Task's own Serves: SPEC-###:R# reference: an uncovered requirement, a reference to a nonexistent or cross-Spec requirement, and a Task with no Serves: line at all are all reported. A Spec still in draft is exempt from this coverage check; any later status blocks on incomplete coverage (phase_gate_blocked, emitted alongside the underlying finding it escalates). Separately, every Spec's depends_on graph is checked for cycles — including a Spec depending on itself — reported with the full cycle path.

internal migration-check-tasks

Purpose: Read-only diagnostic listing every Task number claimed by more than one Spec project-wide — the cases that would have collided under the old, project-wide Task numbering. Never modifies any artifact.

misterspec internal migration-check-tasks
{"ok":true,"collisions":[{"task_number":1,"specs":["SPEC-001","SPEC-002"],"paths":["ai/.../SPEC-001/tasks.md#TASK-001","ai/.../SPEC-002/tasks.md#TASK-001"]}]}

An empty collisions array is the common, healthy outcome — it is not an error.

internal next-task-id

Purpose: Read-only operation reporting the next available Task number, project-wide — never scoped to a single Spec (045-global-task-numbering). Never writes to the filesystem or reserves the returned number.

misterspec internal next-task-id
{"ok":true,"next_task_id":"TASK-048"}

The number returned is always the project's own highest existing TASK-NNN (across every Spec's tasks.md) plus one — or TASK-001 when no Task exists anywhere yet. This is what lets the Task-decomposition Skill number a brand-new Spec's first Task correctly, without ever restarting at TASK-001 just because that Spec has no Tasks of its own yet. A pre-existing cross-Spec collision (see internal migration-check-tasks above) is unaffected — this command only changes how a new number is chosen, never how an existing one is judged.

internal prepare SPEC-### [--task TASK-###]

Purpose: Assemble everything needed to start one Task — identity, readiness, served requirements' own text, declared scope, verification method, and associated Plan sections — in a single, read-only response. No command is ever executed.

Flags: --task <id> (optional — bare TASK-### or composite SPEC-###:TASK-###; omit to auto-select the lowest-numbered Ready Task in the Spec).

misterspec internal prepare SPEC-014 --task TASK-003
{"ok":true,"preparation":{"task":"SPEC-014:TASK-003","heading":"Add refresh-token rotation",
"ready":true,"blockers":[],
"requirements":[{"ref":"SPEC-014:R1","content":"### R1 — ...","fingerprint":"sha256:..."}],
"scope":"internal/auth/refresh.go","verify":"go test ./internal/auth/... -run TestRefreshRotation",
"plan_sections":[{"heading":"Implementation Sequence","content":"...","fingerprint":"sha256:...","matched_requirements":["SPEC-014:R1"]}],
"code_context":[{"path":"internal/auth/refresh.go","heading":"RotateRefreshToken",
"content":"func RotateRefreshToken() error { ... }","location":{"path":"internal/auth/refresh.go","start_line":40,"end_line":40},
"fingerprint":"sha256:9c1a..."}],
"code_scope_not_found":[]}}

code_context/code_scope_not_found (044-architecture-code-context-rules) resolve scope against a disposable, fingerprinted index of the project's own .go declarations — one entry per declaration named by Scope:, plus any test already associated with it, rendered in the same shape internal context --mode package already uses for content. Each item's own content is the declaration's full body when the owning file's total estimated size is small enough, its signature alone otherwise — never the full body of every file unconditionally. A Scope: path that no longer resolves to an indexed file is named explicitly in code_scope_not_found, never silently dropped.

A blocked Task keeps ok:true but sets ready:false with named blockers, and exits 10 — distinct from internal validate's own 4, since "this Task isn't actionable yet" is a different condition than a structural project problem.

When no Task is named and none in the Spec is currently ready:

misterspec internal prepare SPEC-014
{"ok":true,"preparation":null,"message":"no Task in SPEC-014 is ready — every Task is either complete or blocked"}

Recognizes three new Task-body labels, alongside the existing Serves:: Depends on: TASK-### (or none — absence means the same thing), Scope:, and Verify:. A Depends on: cycle or a reference to a nonexistent/cross-Spec Task is also caught by internal validate as task_dependency_cycle / invalid_task_dependency.

internal check-architecture

Purpose: Evaluate the project's own declared architecture rules (forbidden dependency, layer boundary, required contract — architecture_rules in .misterspec/config.yaml) against the current Go source tree. Every rule always reports exactly one of three statuses: pass, fail, or not_evaluated — never a silent pass for a rule or a project the one shipped adapter (Go) can't actually check.

Flags: none beyond the universal --dir; rules and code_exclusions come entirely from the project's own config.

misterspec internal check-architecture
{"ok":true,"architecture":{"adapter":"go",
"results":[{"rule_index":0,"status":"fail","path":"internal/artifacts/parser.go","line":12,
"message":"internal/artifacts imports internal/cli/internalcmd, which this rule forbids","reason":""},
{"rule_index":1,"status":"not_evaluated","path":"","line":0,
"message":"rule kind \"required_contract\" is not supported by the go adapter","reason":"rule_kind_unsupported"}]}}

A project with no go.mod at its root returns "adapter":"" with every declared rule reported not_evaluated/"reason":"no_adapter_for_project" — never approved by default just because nothing could check it. Zero declared rules still returns ok:true with an empty results array, not an error. A rule's own to pattern names an import path relative to the project's own module (e.g. internal/cli/internalcmd), not the full github.com/... import string — the module prefix is stripped automatically for an internal import; an external dependency's own full import path is matched as-is.

internal capture-evidence SPEC-### --task TASK-###

Purpose: Compute a Task's own content fingerprint and Git snapshot, optionally run one explicit, fully-specified verification command, and return the result as structured Evidence-*: fields — the framework's answer to "this Task is checked complete" no longer being trusted on its own (a checked box with no evidence still reports "pending" from internal prepare and unverified_task from internal validate). Never writes into tasks.md itself — recording the returned fields as the Task's own Evidence-*: body lines stays /mister-implement's job.

Flags: --task <id> (required — bare TASK-### or composite SPEC-###:TASK-###); --origin automated|declared (required); --by <string> (required — the tool or person capturing this evidence); --result pass|fail (required iff --origin declared; forbidden otherwise — an automated result is derived from the command's own exit code, never asserted); --command <string> (required iff --origin automated; forbidden otherwise — never inferred from prose); --args <string> (repeatable); --exec-dir <path> (default ., relative to the project root — distinct from --dir, which names the *project* directory on every internal command); --timeout <duration> (default 2m).

misterspec internal capture-evidence SPEC-014 --task TASK-003 \
  --origin declared --by "reviewer:alice" --result pass
{"ok":true,"evidence":{"task":"TASK-003","result":"pass","origin":"declared",
"by":"reviewer:alice","captured_at":"2026-09-22T14:30:00Z",
"git_revision":"a1b2c3d","working_tree":"clean","input_fingerprint":"sha256:9f2c..."}}

Automated origin — runs the given command, captures its real exit code as result, and writes its full combined output to a new sibling <specDir>/evidence/<Task>-<timestamp>.log (never inlined into the response):

misterspec internal capture-evidence SPEC-014 --task TASK-003 \
  --origin automated --by "go test" \
  --command go --args test --args ./internal/foo/... \
  --exec-dir . --timeout 90s
{"ok":true,"evidence":{"task":"TASK-003","result":"fail","origin":"automated",
"by":"go test","captured_at":"2026-09-22T14:31:12Z","command":"go test ./internal/foo/...",
"git_revision":"a1b2c3d","working_tree":"dirty","input_fingerprint":"sha256:9f2c...",
"log":"ai/.../SPEC-014/evidence/TASK-003-20260922T143112Z.log"}}

A command that runs and exits non-zero still returns ok:true with result:"fail" — that is a successful *capture* of a failure, not an operational error. working_tree is "clean" or "dirty": the SHA alone is never treated as sufficient when the working tree had relevant local changes at capture time. A failed capture (bad --exec-dir, malformed request — --origin declared with --command, or vice versa) returns invalid_argument, never a silently accepted half-populated result.

internal status

Purpose: Return a machine-facing structural status summary for the whole project.

misterspec internal status
{"ok":true,"counts":{"program":1,"feature":1,"spec":9,"knowledge":2,"learning":1,"task":0},"specs":{"ready":9},"structural_errors":0}

internal references <id>

Purpose: Return an artifact's outgoing formal and semantic relationships.

misterspec internal references SPEC-014
{"ok":true,"references":{"formal":[{"relation":"depends_on","target":"SPEC-011",
"source_path":"ai/.../SPEC-014/spec.md","source_section":"","source_line":0}],
"semantic":[{"relation":"wikilink","target":"KNOW-003",
"source_path":"ai/.../SPEC-014/spec.md","source_section":"Requirements","source_line":42}]}}

source_path is always populated — the queried artifact's own path, regardless of relation kind. source_section/source_line are populated only for a semantic (wikilink) entry — empty/zero for a formal one, which has no line-level wikilink origin to report (038-wikilink-chunk-provenance).

Purpose: Return every artifact that formally or semantically references the given artifact.

misterspec internal backlinks SPEC-011
{"ok":true,"backlinks":{"formal":[{"relation":"depends_on","source":"SPEC-014",
"source_path":"ai/.../SPEC-014/spec.md","source_section":"","source_line":0}],"semantic":[]}}

Same source_path/source_section/source_line fields as internal references, from the referencing (source) artifact's own perspective.

internal context <id>

Purpose: Return a budgeted, ranked context pack for an artifact — the Context Engine's own single entry point.

Flags:

  • --intent — planning, tasks, implementation, validation, or analysis.
  • --task <text> — the current task's own text.
  • --query <text> — free-text query.
  • --budget <int> — the soft limit: the target for how much optional content to include, including negative (default: 6000 when omitted). Must be a valid integer, or the command fails with invalid_argument. Never used to flag mandatory content as excessive — see --hard-limit.
  • --hard-limit <int> — the hard limit: the ceiling above which mandatory content is reported as exceeded (default: 12000, twice --budget's own default, when omitted — never treated as "no limit"). Independent of --budget; a smaller --hard-limit than --budget is accepted, not rejected. Must be a valid integer, or the command fails with invalid_argument.
  • --render — additionally include a rendered Markdown context pack. Unchanged since before --mode existed; cannot be combined with --mode package.
  • --mode — manifest (default — metadata only, exactly today's shape), package (every item also carries content, a file-absolute location, and a fingerprint), or markdown (an explicit name for --render's own shape).
  • --query-mode — free (default — every token in --query/--task is literal text; FTS5 reserved characters/keywords can never cause a syntax error) or advanced (the query is passed to FTS5's own MATCH grammar unmodified — phrase, prefix, boolean, and NEAR syntax honored). Never inferred from the query text — always this explicit flag. An unrecognized value fails with invalid_argument; a malformed advanced expression fails with query_syntax_error.
  • --diagnostic-scores — additionally include each item's own score_components breakdown (tier, relation_weight, intent_bonus, text_relevance, section_preference, total). Omitted by default in every mode.
  • --provenance — additionally include, for every item whose inclusion is backed by real wikilink occurrence data (a wikilink reason, or a backlink reason built from a semantic wikilink), a provenance array naming the exact referencing artifact, section, and line. An item with no such occurrence data (e.g. target, constitution, a formal relation) never gets the key at all — not even an empty array. Omitted by default in every mode.
  • --prefer-section — experimental, off by default. Scores a wikilink-derived reference higher when its own occurrence's section case-insensitively matches Requirements or Functional Requirements. Omitting this flag leaves ordering byte-identical to this feature never having existed — it exists only so the evaluation harness can record a comparison against default ordering before any future Spec considers promoting it.
  • --base <pack_id> — --mode package only. A pack_id returned by a previous --mode package call (for the same or a different request) — returns only what changed since it (diff), or the full package explicitly marked recovered: true when the base can't be confirmed. Never trusted as an assertion: a --base value alone, with no matching stored pack, is always treated as unknown. Combined with any mode other than package, fails with invalid_argument.
misterspec internal context SPEC-014 --intent implementation --budget 700
{"ok":true,"context":{"schema_version":4,"target":"SPEC-014","intent":"implementation","budget":700,
"estimated_tokens":589,"budget_exceeded":false,"overage":0,
"items":[{"path":"ai/.../SPEC-014/spec.md","tier":"mandatory","reasons":["target"],"score":100,"tokens":107}],
"diagnostics":{"candidates_considered":18,"items_selected":9,"reduction_percent":61.7,"payload_tokens":589,
"estimator":"default","hard_limit":12000,"exclusions":[],"ranking_version":1},
"rendered":null}}

schema_version is now 4 (038-wikilink-chunk-provenance's new opt-in --provenance field). It was bumped to 3 by 036-text-search-ranking: same-tier free-text ordering is now driven by SQLite's own bm25() relevance value instead of a recomputed term-occurrence heuristic, and diagnostics.ranking_version identifies the scoring formula/weight set that produced a response's ordering — bumped only after comparative evaluation evidence supports a change, never silently under the same value. Earlier fields (diagnostics.estimator, diagnostics.hard_limit, diagnostics.exclusions) and behavior are unchanged.

--diagnostic-scores — each item gains a score_components breakdown, in every mode:

misterspec internal context SPEC-014 --query "refresh token" --diagnostic-scores
{"ok":true,"context":{"schema_version":4, ...
"items":[{"path":"ai/knowledge/KNOW-002.md","tier":"text","reasons":["text_match"],"score":27,"tokens":42,
"score_components":{"tier":3,"relation_weight":0,"intent_bonus":0,"text_relevance":27,"section_preference":0,"total":27}}],
"diagnostics":{"...":"...","ranking_version":1},
"rendered":null}}

--provenance — every wikilink-backed item names exactly where it was referenced from:

misterspec internal context KNOW-003 --provenance
{"ok":true,"context":{"schema_version":4, ...
"items":[{"path":"ai/.../SPEC-014/spec.md","tier":"semantic","reasons":["backlink"],"score":65,"tokens":11,
"provenance":[{"source_path":"ai/.../SPEC-014/spec.md","source_section":"Requirements","source_line":42}]}],
"rendered":null}}

--mode package — every item's own selected text, delivered directly, with a file-absolute location and a content fingerprint, so a caller never has to re-read the source file for content already in the response. Every --mode package response also carries its own pack_id (043-incremental-context-reuse), reusable as a future --base:

misterspec internal context SPEC-014 --mode package
{"ok":true,"context":{"schema_version":6,"target":"SPEC-014", ...
"pack_id":"sha256:6614b8dd...",
"items":[{"path":"ai/.../SPEC-014/spec.md","heading":"R1 — First","tier":"mandatory",
"reasons":["target"],"score":100,"tokens":107,
"content":"### R1 — First\n\nThe system MUST ...\n",
"location":{"path":"ai/.../SPEC-014/spec.md","start_line":14,"end_line":18},
"fingerprint":"sha256:3a7bd3e2360a3d..."}],
"diagnostics":{"...":"...","payload_tokens":742,"estimator":"default","hard_limit":12000,"exclusions":[],"ranking_version":1},
"rendered":null}}

--base <pack_id> (043-incremental-context-reuse) — pass a previously returned pack_id back in, and get only what changed since it. A caller that repeats the same request with no source change gets an all-"reuse" diff — no content resent at all:

misterspec internal context SPEC-014 --mode package --base sha256:6614b8dd...
{"ok":true,"context":{"schema_version":6,"pack_id":"sha256:6614b8dd...",
"diff":{"base_pack_id":"sha256:6614b8dd...","entries":[{"kind":"reuse","base_index":0}],"removed":[]},
"reuse":{"items_reused":1,"items_sent":0,"tokens_saved_estimate":10},
"...":"... every other field unchanged ..."}}

Applying the diff — replacing each "reuse" entry with the named base pack's own item at base_index, keeping every "added"/"modified" entry's own item, in the response's own entries order — reproduces the exact full package a direct, --base-less call would return. A --base the system can't confirm (unknown, or computed under a different --intent/--budget/ranking or contract version) never returns a partial result — it falls back to the full package, explicitly marked:

misterspec internal context SPEC-014 --mode package --base sha256:0000...
{"ok":true,"context":{"pack_id":"sha256:af02...","recovered":true,"reason":"unknown_base",
"items":[ "... full package, same shape as a --base-less call ..." ],
"reuse":{"items_reused":0,"items_sent":2,"tokens_saved_estimate":0}}}

reason is "unknown_base" (no stored pack for that pack_id) or "invalidated" (a stored pack existed, but this call's own request configuration no longer matches it — a pure content-only change never triggers this, it stays diffable). This local reuse mechanism is entirely independent of any LLM provider's own prompt caching — reuse reports a locally measured item/token count, never a claimed dollar or provider-side cost saving.

internal commits-since-file

Purpose: Return every commit on the current branch since a given file was first added — the real basis /mister-wrap-up uses to synthesize a Spec's own downstream documentation.

Flags: --path <path> (required, repo-relative — the file whose own "added" commit anchors the range).

misterspec internal commits-since-file --path specs/014-sqlite-index/plan.md
{"ok":true,"available":true,"commits":[{"hash":"...","subject":"...","author_date":"2026-08-01"}]}

available is false (never an error) when the target isn't a Git repository or the file was never committed.

internal eval-retrieval

Purpose: Run a fixed, versioned set of deterministic retrieval evaluation cases — entirely offline, no LLM session required, safe to run in CI on every change. Part of the evaluation harness (Spec 037) that supersedes the one-off exercise described in Dogfooding & Evaluation.

Flags: --cases <dir> (required — a directory of case YAML files, each naming a target, required/forbidden content, and the fixture directory to run against); --out <path> (optional — also write the full run record JSON to this path); --variant/--repo-revision (optional config labels recorded on the run, for later comparison).

misterspec internal eval-retrieval --cases specs/037-.../fixture/cases
{"ok":true,"schema_version":1,
"result":{"run":{"run_id":"retrieval-2026-...","kind":"retrieval",
"config":{"variant":"default","ranking_version":"1"},
"results":[{"case_id":"free-text-query-01","passed":true,"missing":[],"unexpected":[],
"positions":{"SPEC-100":8}}]},
"summary":{"total":6,"passed":6,"failed":0}}}

A failing case is reported inside result, not surfaced as a command failure — the run still succeeds (ok:true); a specific case's missing/unexpected arrays name exactly what didn't match, never only a lowered aggregate score.

internal eval-compare

Purpose: Compare a candidate run record against a named, recorded baseline — flagging when more than one configuration dimension changed at once, and surfacing a per-case regression even when an unrelated aggregate metric improves in the same comparison.

Flags: --baseline <name> (required — a baseline recorded under eval/baselines/); --candidate <path> (required — a run record JSON file, e.g. from eval-retrieval --out); --repetitions <dir> (optional — additional same-config run records, used to tell a real change apart from normal run-to-run variance).

misterspec internal eval-compare --baseline retrieval-2026-09 --candidate /tmp/candidate.json
{"ok":true,"schema_version":1,
"result":{"comparison":{"baseline_name":"retrieval-2026-09","candidate_run_id":"retrieval-2026-...",
"dimension_diff":[],"changed_cases":[{"id":"free-text-query-01","baseline_outcome":"fail",
"candidate_outcome":"pass","direction":"improved"}],
"aggregate":{"success_rate":1.0}}}}

A non-empty dimension_diff means the candidate's own config differs from the baseline's in more than the one dimension the comparison was meant to isolate — the comparison still runs, but a caller reading it knows not to trust changed_cases as isolating a single cause. A baseline recorded against an older ranking_version/context_schema_version than the candidate is flagged as stale (result.comparison.stale) rather than silently trusted.

internal analyze-impact

Purpose: Report every artifact or Task with a known relation to what changed between two Git revisions — a Requirement's text change propagated to the Tasks that Serves: it, a formal depends_on/parent/supersedes backlink, a Task whose own recorded evidence is already stale/failed, or a wikilink-only mention (reported, but never as a certainty of breakage). Read-only — never mutates the filesystem.

Flags: --from <revision> (required); --to <revision> (optional — default: the working tree); --path <path> (optional — scope the diff to one artifact instead of the whole project).

misterspec internal analyze-impact --from a1b2c3d
{"ok":true,"analyze_impact_schema_version":1,
"change_set":{"from":"a1b2c3d","to":"working-tree",
"elements":[{"id":"SPEC-014","path":"ai/.../SPEC-014/spec.md","status":"modified","requirement_number":2}],
"unmapped_code_paths":0},
"affected_items":[{"id":"SPEC-014:TASK-003","path":"ai/.../SPEC-014/tasks.md#TASK-003",
"classification":"deterministic_invalidation","severity":"medium",
"reason":"TASK-003 serves SPEC-014:R2, whose content changed between a1b2c3d and working-tree",
"paths":[{"hops":[{"relation":"coverage","from":"SPEC-014","to":"SPEC-014:TASK-003",
"source_path":"ai/.../SPEC-014/tasks.md","source_section":"","source_line":0}]}],
"reverification_candidate":"SPEC-014:TASK-003"}],
"no_known_relation_elements":[]}

classification is always exactly one of deterministic_invalidation (a formal, coverage, or already-broken-evidence relation) or suggested_review — a wikilink-only mention is never promoted to deterministic_invalidation, structurally, not just by convention. A multi-hop dependency chain is reported with its full paths[].hops sequence, not only the nearest hop, and the same item reached by more than one distinct relation keeps every path separately. An element with zero known relations is named explicitly in no_known_relation_elements — its absence from affected_items is never presented as a verified absence of impact. unmapped_code_paths counts changed paths this feature has no Requirement mapping for yet (source code, pending a future architecture-rules Spec) — declared, never silently dropped from the response.

Error codes

Every command shares the same error shape and code set:

CodeExitMeaning
entity_not_found3The ID doesn't resolve to any artifact.
entity_ambiguous3The ID resolves to more than one artifact.
spec_context_required3A bare TASK-### is claimed by more than one Spec — retry as SPEC-###:TASK-###.
invalid_target2Wrong entity type for this operation.
invalid_argument2A CLI-boundary problem (bad flag value, unrecognized type/kind).
unsupported_intent2internal context --intent value not recognized.
query_syntax_error2internal context --query-mode advanced expression is malformed FTS5 syntax.
invalid_case2An eval-retrieval case file failed validation, or referenced an identifier that doesn't resolve.
incompatible_run2eval-compare's baseline and candidate run records have different kind (e.g. one retrieval, one task_execution) — refused rather than compared meaninglessly.
revision_not_found2analyze-impact's --from or a non-empty --to doesn't resolve in the project's Git repository.
invalid_parent5The given --parent can't have this child type.
already_exists5The target artifact already exists.
unsupported_type2Unrecognized entity/artifact type or kind.
path_outside_project5A resolved path would escape the project root.
project_not_initialized6No .misterspec/config.yaml found.
not_a_repository6analyze-impact targeted a directory that isn't a Git repository — there's no history to diff.
already_initialized5init targeted an already-bootstrapped project.
unknown_agent5--agent ID not registered.
checksum_mismatch7--update's downloaded binary didn't match the published checksum — nothing was replaced.
release_check_failed8--update couldn't reach or parse the GitHub release check.
no_compatible_asset8--update found no release asset for the current OS/architecture.
permission_denied9--update lacked permission to replace the installed binary.
unexpected_failure1Anything else (e.g. an index I/O error).