Release notes — 3.2.6
For the Spec Kitty operator or maintainer upgrading an existing project from v3.2.5.
3.2.6 is the stabilization release that makes Spec Kitty tell the truth. It closes a long list of "reported success while the thing was actually broken" defects — silent status greens, phantom mission restarts, retention policies quietly ignored, timestamps mislabelled, a startup-crashing dependency — and pairs that reliability push with one substantial new capability: orchestrator-api contract 1.4.0, which lets an external host (a CI pipeline, a custom dashboard, a native driver) run a Mission's entire design pipeline — specify → plan → tasks → analyze → decision resolution — without ever crossing into host-CLI territory. Alongside those, charter becomes the canonical governing term, sync ships off by default on a bare install, and the CLI gains explicit worktree-owned lifecycle commands, shell autocompletion, and a durable operator-config file.
The previous stable release was v3.2.5 (2026-07-08). This is the finalized 3.2.6; it supersedes the per-candidate notes for 3.2.6rc1 and 3.2.6rc2.
Install / upgrade
# New install:
pipx install spec-kitty-cli # or: pip install spec-kitty-cli
# Existing project:
spec-kitty upgrade
spec-kitty upgrade runs every 3.2.6 migration automatically; each is idempotent and safe to re-run. Read the Breaking changes section below before upgrading — several items need a one-time action, and a few need one command run before the upgrade reaches the project.
💥 Breaking changes
This section is exhaustive. Each item states what breaks and the exact action to take. Read it in full before you upgrade.
Governance, charter & doctrine packs
Built-in doctrine content moved to
packs/built-in/with no compatibility shim (missionrelocate-builtin-doctrine-packs). What breaks: any reference to the oldsrc/doctrine/<kind>/built-in/<file>path. Action: repoint each reference topacks/built-in/<kind>/<file>— drop the innerbuilt-in/segment. Doctrine.pycode,schemas/,templates/,skills/, andmissions/did not move.An org pack with an unrecognised agent-profile or DRG key now fails to load (mission
doctrine-silence-guards). What breaks: a pack carrying a typo'd or retired key that earlier releases silently dropped. Action: before upgrading, runspec-kitty doctor doctrine --jsonand check theskipped_profileslist; fix any invalid profile. A pack with an invalid profile is reported unhealthy rather than passing as healthy.The redundant
context-sources.*agent-profile block is removed from the schema (#3629; missiondoctrine-drg-silent-drop-boundary). What breaks: a custom profile that still authorscontext-sources(directives/tactics/toolguides/styleguides/doctrine-layers/additional) now fails to load loudly instead of dropping the block in silence. Action: runspec-kitty upgrade— the3_3_1_context_sources_consolidationmigration set-merges every reference id onto the canonical*-referencesfields. Author references solely ondirective-references/tactic-references/toolguide-references/styleguide-references.Cross-pack references in an org pack must now be written in full (mission
doctrine-silence-guards). What breaks: a bare id in adrg/fragment no longer resolves against a different pack in the same merge — it now raises anunresolved_edge_endpointconflict at merge time. Action: write each edge endpoint as<kind>:<id>(for examplestyleguide:acme-sty-001), or as a bare id declared in that same fragment's ownnodes:block.pack validate(anddoctrine org validate) now fail (exit 1) for three previously-passing org-pack shapes (#3387; missionorg-pack-authoring-diagnostics). What breaks: a merge-time-skipped agent profile (nowprofile_skipped), a nestedassets/<pack>/x.asset.yamlwith a schema violation (now scanned recursively), and DRG content living only underdrg/*.graph.yamlfragments with no pack-root*.graph.yaml(nowdrg_root_graph_missing). Action: if you maintain an org pack, runpack validateand fix all three shapes before adopting the pack.spec-kitty doctor doctrinenow exits non-zero when an org pack declares an edge endpoint that resolves to nothing (missiondoctrine-silence-guards). What breaks: CI that treateddoctor doctrineas a green gate over a pack with dangling endpoints. Action: resolve the dangling endpoints the report names.charter statusreports the same problems in itserrorsarray but deliberately keeps exit code 0, so scripts keying oncharter status's exit code are unaffected.The
rtk-search-toolingtoolguide is removed, including from the default charter pack (3.2.6_retire_rtk_search_toolingmigration). What breaks: a project still holding the staleactivated_toolguidesentry would hard-fail its next charter compile withUnknownArtifactIdError. Action: runspec-kitty upgrade— the migration strips the entry from.kittify/config.yaml,charter.yaml, andreferences.yaml, does nothing on a project that never had it, and is safe to re-run. If you want RTK guidance, keep it in your own org pack.
Sync, tracker & auth
The legacy local-sync surface is now deactivated by default; opt in with
SPEC_KITTY_ENABLE_SAAS_SYNC=1(#3799; missionsync-deactivate-by-default; folds#3470/#2801/#2809). What breaks: a bare install now spawns no sync daemon and emits no events — zero background processes and zero network egress on the default path. Action: existing sync users must setSPEC_KITTY_ENABLE_SAAS_SYNC=1(a per-shellexport, a per-repo.kittify/.kitty.enventry, or per-invocation) to retain the daemon and event emission. Deactivation does not kill a daemon a prior opted-in session left running —spec-kitty sync doctorsurfaces an advisory andspec-kitty doctor restart-daemonretires it. Arming stays strictly upstream of the per-project egress consent gate; it never replaces or weakens consent. The pre-review regression gate is cut off the shared sync toggles onto its ownSPEC_KITTY_PRE_REVIEW_GATE_DISABLE.Local tracker providers (
beads/fp) now require a recorded egress decision (missiontracker-egress-refusal-3108). What breaks: abeads/fpbinding that never recorded hosted-sync consent and has notracker.egresskey stops syncing on upgrade (onlysync pull/push/runare gated;bind/status/unbind/map addstay available). Action: recordtracker.egress: permittedin.kittify/config.yamlto keep local sync without consenting to hosted sync at all, or runspec-kitty sync opt-in/ setsync.enabled: trueto consent to hosted sync. Absence at both channels denies by design.Hosted-sync consent is now per-project, and the shared-store
sync migrateis retired (#3262; missionper-project-sync-consent-ledgers). What breaks: the old shared-storesync migratenow refuses with guidance, andSPEC_KITTY_ENABLE_SAAS_SYNCis strictly deny-only as a consent signal (arming it grants nothing on its own). Action: each project keeps its own isolated consent ledger;spec-kitty sync opt-inis the sole local grant. Use the copy-only, resumable cutover commands (sync project-store-preview/-migrate/-status/-quarantine/-history) to move existing history. Seedocs/guides/project-sync-consent.md.
Missions, gates & lifecycle
A legacy
{"mission": …}-only Mission now stops resolving its type and goes neutral/typeless (#3598; epic#3410). What breaks: the canonical reader drops the legacymissionfield and the silentsoftware-devdefault, and this compounds with the per-type hard-fail — a legacy Mission that used to mask assoftware-devcan go type-unresolvable. Action (program-ordered): runspec-kitty migrate backfill-mission-typeagainst the project before this change reaches it (it mints a profile-resolvingmission_typeinto every legacy Mission and never fabricates an unresolvable type), then gate withspec-kitty doctor mission-type --fail-on legacy-key-only,typeless,error.spec-kitty nextandfinalize-tasksnow block on requirements written as bare prose (#3396; missionbare-prose-requirements-uncounted). What breaks: a spec whose requirements are bare sentences (noFR/NFR/Cid) used to pass the coverage gate as covered. Action:nextnow refuses to advance past the tasks boundary andfinalize-tasksexits non-zero, listing the uncounted requirement ids — give each requirement a first-class id.A custom mission family that ships its own
expected-artifacts.yamlnow genuinely blocks on unmetblocking: truerequirements (#3704). What breaks: an in-flight custom Mission previously advancing silently past a step whose declared,blocking: trueartifact was never produced may now correctly block on its next evaluation. Action: produce the declared artifact (or fix the manifest). The four built-in families are byte-identical; an unregistered family with no manifest still runs to completion as before. In-flight Missions are not retroactively re-evaluated.An
expected-artifacts.yamlwith an unknown or typo'd key now fails loud (#3413;#3542). What breaks: a misspelled key used to be silently discarded, so the requirement vanished. Action: the loader now raisesManifestSchemaErrornaming the file (acrossreconcile, background dossier sync, and version resolution, including org-authored manifests) — fix the key to the schema.Review rejections now require a rationale (
#3307,#3444). What breaks: a rejection travels to the hosted dashboard asreview_ref, so an empty rationale is refused. Action: pass--review-feedback-fileor--notewhen rejecting a work package; the backward review move now correctly carriesforce=Trueand the rationale on the wire.The event log is the single authority for a work package's review verdict (
#3121; missionverdict-seam-write-unification). What breaks: automation that read thereview-cycle-N.mdverdictfield as truth. Action: read thereview_resultevent instatus.events.jsonl; the Markdown render is now best-effort and non-authoritative. Anupgrademigration backfills stranded terminal.mdverdicts.Mission-mutating
implement/reviewnow fail closed when run from a foreign checkout (#3128,#3129). What breaks: a command run from a linked lane worktree that used to silently act on the primary checkout. Action: run mission-mutating commands from the owned checkout (reads and planning are unaffected); a foreign checkout now raises aCheckoutIdentityErrornaming the target checkout.
Internal APIs & automation contracts
These affect only callers scripting against Spec Kitty internals, parsing its JSON, or importing its modules.
primary_feature_dir_for_missionis removed; importing it raisesImportError(#2886,#3014). Action: replace the call withplacement_seam(root, slug).read_dir(<kind>)for the artifact kind you need.Seven
spec_kitty_eventstypes are no longer re-exported fromspecify_cli.dossier(#3677). What breaks:from specify_cli.dossier import ArtifactIdentity(and the six other moved types) now raisesImportError. Action: import these types directly fromspec_kitty_events. The fouremit_*re-exports are unchanged.The two exported event emitters take a metadata object, not tail kwargs (
#3317). What breaks: out-of-tree callers ofemit_wp_status_changed/emit_token_usage_recorded(re-exported from thesyncfacade) that passedcausation_id/force/evidence/run_id/provider/modelas individual kwargs. Action: pass aWPStatusChangeMetadata/TokenUsageMetadataobject via the keyword-onlymetadata=parameter.spec-kitty agent mission setup-planchanges its unauthenticated-host contract (#3621). What breaks: automation that branched on the old exit code2/SAAS_SYNC_UNAUTHENTICATEDerror for an unauthenticated host. Action: the command now exits0whenever local verification succeeds and reports hosted-sync unavailability as a nonfatalwarnings[].codediagnostic — read that instead.charter context --jsonbumps its schema and moves its charter-presence authority (#2787,#3489). What breaks: consumers parsing the payload. Action: pin the new top-levelcontext_schema_version(now1.1.0, adding a typedprocedures[]array); readcharter.yamlas the authority of record forproject_charter.present(a project with only an uncompiledcharter.mdnow reportspresent: false, with new additivecharter_md_present/charter_md_pathkeys).record-analysis's committedanalysis-report.mdnow records repo-relativeinput_artifacts.*.pathvalues (ledger SK-63). What breaks: tooling that parsed those paths expecting absolute filesystem paths. Action: expect a repo-relative path.The printed rejection feedback-file path changed (
#3554). What breaks: automation hardcodingtasks/<wp>/review-cycle-N.mdas the feedback target (which the provenance guard always refused). Action: write feedback totasks/<wp>/review-feedback-N.md.
Spec Kitty's own CI (contributors only)
- A push to a protected branch now starts 49 of 50 test jobs instead of about 10 (
#2957). Pull requests are unaffected — path filtering still narrows a PR to the suites its diff touches. This is a deliberate trade of CI minutes for coverage on the branch where frozen contracts must actually run. No action for consumer projects.
✨ Added
orchestrator-api & external hosts
orchestrator-apicontract 1.3.0 → 1.4.0 adds 11 design-phase verbs so an external host can drivespecify → plan → tasks → check-prerequisites/record-analysis → decision resolutionwithout any host-CLI crossing (#3837; missiondesign-phase-orchestrator-api).specify,plan,tasks,check-prerequisites, andrecord-analysisscaffold and validate a Mission's design artifacts;open-decision/resolve-decision/defer-decision/cancel-decisionoperate the decision ledger (each rejecting an empty rationale/final-answer, which also hardensspec-kitty nextdecision resolution);design-statusis a read-only fail-closed query; andanswer-decisionresolves anextdecision_requiredmoment with full host-CLI event/lifecycle parity. Purely additive — all 21 commands and 51 error codes coexist and no existing verb changed. The 1.3.0 groundwork also added--review-result-jsontoorchestrator-api transitionso a host can submit a structured review outcome without forcing a lane transition. See Orchestrator API Reference § Design-Phase Commands.
Explicit worktree-owned lifecycle
--owned-checkoutnow works across the whole single-branch Mission lifecycle (#3843; extends#3346/#3787; ADR2026-09-03-1).check-prerequisites,finalize-tasks,spec-commit,accept,agent tasks move-task, andagent tasks mark-statusall accept--owned-checkout PATHand route reads, writes, status events, and commits through one validated owned root, so an agent operating from a task-owned worktree can run a Mission end-to-end. Owned mode issingle_branch-only for now (alanes/coordMission is refused with a structured error rather than mis-routed); flagless behavior is byte-for-byte unchanged.
Charter, doctrine & packs
charteris now the canonical governing term (#3664,#3732; mission arcretire-doctrine-term). The glossary authorities anddocs/context/charter.md(renamed fromdoctrine.md) speakcharter; the internaldoctrinecode package is relocated tocharter.offeringwith a realcharter.offering/charter.activationmodule split; and every operator-facingdoctrinesurface keeps working through a one-time deprecation warning —import doctrine, thespec-kitty doctrineCLI group (now an alias ofspec-kitty charter), thegovernance.doctrineselection key (mapped forward), thedoctrine.org.packspath, and thedoctrine:synthesizer URN prefix (event logs keep parsing both).spec-kitty upgrademigratesinterview/answers.yamlpreserving every answer.charter synthesizeis now non-destructive by default (#3270; folds#2777/#3052). It preserves backed governance content and reconciles against the on-disk graph;--pruneis the explicit opt-in for removal and--dry-runpreviews. Theimplement/nextboundary self-heals instead of hard-blocking until you resynthesize.- Org and project doctrine packs are now genuinely usable end-to-end — a new
ORGresolution tier ships templates and mission-FSM content, layered packs contribute end-to-end mission types with real action sequences, a chain of multiple org packs merges correctly, and cascade followsrequires/suggestsedges an org pack authors indrg/fragment.yaml(#3524,#3424,#3520,#3572,#3534,#2829). A unifiedpack-manifest.yamlschema now spans built-in/org/fetched/charter packs (#3500–#3503; ADR2026-08-16-1). - New doctrine surfaces reach the agent that earlier releases silently dropped:
assetandtemplatebecome first-class doctrine kinds (#2495,#2469,#3037); glossary packs, procedure/tactic step descriptions, andsuggests-edge paradigms/tactics now render in delivery (#3489,#3063);charter context --jsonships a typedprocedures[]array; and the four consolidated charter-bundle files fold into one authoritativecharter.yaml(schema2.0.0) with a deterministic upgrade migration (#2773). spec-kitty doctor mission-typeandcharter context --jsongain honesty surfaces:doctor mission-typeclassifies whether every Mission's type resolves (six states,--json,--fail-onfor CI);charter context --jsonexposes a top-leveldirectives_sourceprovenance field and fail-loud directive-resolution diagnostics (#3402,#3728).- The
spk-doctrine-show-meandspk-run-verdict-captureskills ship shared doctrine for choosing an explanatory diagram and for recording a review verdict identically across every agent harness (#3528,#3121).
Missions & lifecycle
- A deliberately-canceled work package is now an honest Mission ending (
#2945,#3590). Cancellation provenance is a first-class, operator-authoredreason_sourceon the status event, and a singleis_acceptable_endingauthority letsacceptandmergeadmit acanceledWP only when it carries operator provenance; a synthetic (undocumented) cancellation is refused.tasksalso gains an advisorycheck-terminabilitywarning that flags, at planning time, a work package whose acceptance can only be observed after integration. - Runtime work-package state now lives in the append-only event log (
#2684,#2816) —tasks/WP##.mdfrontmatter is no longer a runtime authority;spec-kitty migrate backfill-runtime-stateseeds and verifies the cutover. spec-kitty intakerecognises an optional v1 handoff packet so an upstream requirements tool can seed a Mission's FR/AC ids (docs/contracts/handoff-packet-v1.md);intake --autoscans.handoff/*.md.- Dashboard work-package cards now show subtask progress (
2/4 subtasks) and a deterministic colored avatar for the assigned agent profile (#2504,#647).
Sync, tracker & operator config
spec-kitty sync import-historymaterializes existing local Mission history into the hosted projection with deterministic, idempotent event ids and fail-closed server preflight (#2262).- A two-tier
.kitty.envoperator-config file (${SPEC_KITTY_HOME}/.kitty.envmachine-wide, overridden per-repo) loads before anyspec-kittymodule imports, so operator environment is durable instead of per-shell (#3495); committed doctrine provenance is now portable across machines and wheels via a${SPEC_KITTY_PACKS_ROOT}token (#3494); and an opt-inSPEC_KITTY_PRERELEASEchannel surfaces pinned release candidates (#3496). Newdoctorfacets:provenance,env-file,channel.
CLI UX
- Shell autocompletion, a
-hshort-help alias, and alphabetical command listing (#2232,#2234,#2235) — additive, with a committed completion-manifest fast path and no behavior change to existing commands.
🐛 Fixed
Startup & correctness
spec-kittyno longer crashes on startup after installing typer 0.27.2 (#3782). typer 0.27.2 removedAbort/Exitfrom a vendored module whose eagergetattrfallback broke everyspec-kittysubprocess at import; a defensive resolver now degrades gracefully across the vendored module, its submodule,typer, and standaloneclick.- Every CLI command's cold-import boundary is restored — commands no longer eagerly load the status-orchestration and workspace machinery, a regression the explicit-owned-checkout work had introduced (restores the
#1461boundary; new architectural gate enforces it). - Timestamps Spec Kitty writes into your project are now correct aware-UTC instead of local time mislabelled as UTC — ~20 sites (charter backup filenames, status-event stamps, auth-doctor report times) now flow through one
kernel.clockproducer (#3305, closes#3289).
Status honesty — "success" that was actually broken
- Auth and sync diagnostics are now derived from evidence (
#3723).sync status/auth status/auth doctorroute through one typedHealthVerdictauthority (tri-stateok/unknown/fail, headline computed from state, mandatory evidence for a definite claim); an expired token whose refresh chain can't be verified resolves tounknown, never a false green.sync doctorno longer reports "healthy" while the server probe disagrees, andsync statusnames an unreachable/decommissioned server with the exact recovery command (#3406). spec-kitty nextno longer restarts a merged Mission or stalls on a canceled work package (#2947,#3780). The loop now decides from the committed status authority — a merged Mission returnsterminal/doneinstead of fabricating a fresh run against a stale coordination worktree, and an operator-canceled-with-provenance WP advances instead of stalling.nextalso serves the charter-freshness verdict from a per-repo content-hash cache instead of re-parsing the whole charter on every call (#3787).- A fail-loud sweep closed silent-drop defects at a dozen ground-level sites (
#3578,#3548,#3517,#3412,#2991,#3624, and others). Each now emits the human-readable half of its contract through an existing operator-visible surface:orchestrator_api's_fail()keeps itsmessagewhen structureddatais passed; the sync emitter no longer returns a durably-unqueued event as publishable; a malformed manifest fails loud distinct from "absent"; and the background sync daemon resolves aspecify_cli-capable interpreter before spawning instead of trusting a baresys.executable. - Review verdicts, arbiter overrides, and approvals are durable and single-authority (
#3044,#3235, ADR2026-08-03-1). Approving a work package after a rejection sticks with no--skip-review-artifact-checkflag; a concurrent review-cycle commit can no longer race into a silently-lost verdict (a checkout-wide serialization queue wraps the whole write); and an arbiter override persists across a fresh clone and clears the merge gate on its own, recorded as its own first-class outcome rather than posing as a reviewer approval.
Merge & retention
spec-kitty mergenow honors a Mission's declared retention policy (#3131). A Mission'smeta.jsoncan carryretain_branches/retain_worktrees; merge resolves cleanup viaresolve_merge_retentionwith precedence explicit-CLI-flag > meta.json > default, failing closed toward retention on ambiguity, and tears down (or keeps) the coordination branch/worktree/marker as one coupled decision. An explicit delete override still works but prints a notice naming the contradicted policy. Mint withspec-kitty agent mission create --retain-branches --retain-worktrees.- Merge no longer discards acceptance/issue-matrix evidence or resets a filled gate artifact to a scaffold (
#2804,#2709,#3232). Custom merge drivers keep whichever side carries evidence; squash merges reconcile per artifact class; and rollback/--resumestay coherent after a failed target advance (#2711,#2786).
Commit-boundary & workspace integrity
- Lifecycle commands on a protected-primary / coordination-topology Mission no longer leave a dirty tree, report false success, or refuse with un-followable guidance (mission
commit-boundary-router-integrity; epic#2739; fixes#3784,#2693,#3716). The commit-router, the protected-primary refusal, and coordination-topology routing now agree on where planning artifacts land —implement's claim commit excludes any.worktrees/-nested path,mission createcommits its scaffold transactionally and disclosesspec.mdas uncommitted, andmission close --discardleaves a clean tree. spec-kitty implement --base <ref>actually roots the lane on the ref, and hard-errors instead of faking success when it can't (#3616,#3571, plus follow-ups). The override is threaded into the topology-aware allocator; an unhonorable route raises a typedUnhonorableBaseErrornaming the route, work package, and base rather than printing a fabricated success line. A shared allocation seam plus a CI anti-bypass guard prevent the class recurring (#3460/#3462/#3536).- A command run from a linked lane worktree no longer silently acts on the primary checkout (
#3129,#3346) — a checkout-identity guard distinguishes owned from foreign worktrees and fails closed, andmission create/nextrun correctly from a caller-owned worktree with isolated state.
Charter, doctrine & gates
spec-kitty charter context --include directive:<id>resolves the exact ids the--jsonsurface advertises (#3816) — the directive selector now normalizes slug, numeric, andDIRECTIVE_NNNforms through one canonical authority, closing a divergence that also silently dropped every directive from the gatedDoctrineService.directivesproperty.charter generate --from-interviewreports a present-but-corruptanswers.yamlhonestly instead of claiming no answers exist (#2940);charter activate mission-type <T>refuses a type that resolves an empty action sequence before writing (#3717); and a single project-localdirectives:entry is now additive instead of silently replacing the whole resolved set (#3728).charter activate --cascadenames every asset/template node it did not cascade instead of silently dropping them (#3705), and a malformeddrg/fragment.yamlin one pack no longer drops the other packs' fragments — the degrade is now per-pack with an operator-visible warning (#3629).- Governance now reaches the deciding gate, not the implementer (mission
governance-at-the-gate;#3685,#3682) — decision-documentation is delivered atreview(removed fromimplement, so smaller models stop stalling mid-implementation to demand sign-off), enforcement levels carry an explicit rank, and the review/accept gates capture real bound evidence.
Sync, tracker & auth
- Review rejections reach the hosted dashboard again (
#3307,#3444) — the backward review move now emitsforce=Trueand threadsreview_ref, satisfying the wire contract the hosted endpoint enforces. - Machines that never ran the layout migration now capture sync events for real instead of silently capturing zero while reporting success (
#3425,#3497);auth loginresolves the real hosted URLhttps://app.spec-kitty.aiwhen unset (#3297); and a batch-400 poison event no longer strands its whole batch (#2736,#2755). - Hosted event-sync delivers again for consented projects (
#3564,#3620) —sync nowno longer self-blocks on an admission gate whose server endpoint isn't deployed, andimport-history --applyhonors the server's own preflight success. sync share <team>no longer crashes first-run while it self-heals, andauth statusnow shows each team's slug thatsync sharerequires (#3699,#3731).
Upgrade & migrations
spec-kitty upgradeobeys yourauto_commitopt-out, survives its own re-run, and stops misreporting success or failure (missionupgrade-command-hardening;#3651and cluster). Read-only generated files route through one restore→write→re-protect writer (no more ~30Permission deniederrors on re-run); the commit decision defers toget_auto_commit_defaultand says so when it leaves changes uncommitted; a destructive mission-state repair is a separately-scoped consent gate; and a single finalizer derives the exit code once.upgradeno longer silently drops skill-content migrations on Windows when the managedSKILL.mdis read-only (#3771), and refreshes a stale.claude/CLAUDE.mdorientation surface rather than leaving an outdated version string (#2265).initgitignores the.worktrees/root (with anupgradebackfill) so a mission worktree no longer shows ingit status(#3689), and no longer blanket-gitignores all of.cursor/for teams versioning their own Cursor rules (#2498). Several upgrade-wedge failures that left a stuck migration with no self-service exit are fixed (#3383).
♻️ Changed
spec-kitty --version/-vis now a single copyable line — no ASCII-art banner before the version string (community contribution by @zohar).- One canonical mission-type reader replaces ~10–12 hand-rolled
meta.jsonreaders that disagreed on field order and default; the dashboard, retrospectives, and identity now show a Mission's true type instead of masking everything assoftware-dev(#3598; ADR2026-08-22-1). See the Breaking-changes note on thespec-kitty migrate backfill-mission-typeprogram ordering. --jsonoutput is plain regardless of terminal colour — ~77 ad-hocConsole()sites moved onto oneCliConsoleseam with an architectural guard (#2632; ADR2026-07-14-1).- Wall-clock performance tests moved off the PR path to a dedicated statistical
performance.ymlpipeline (pytest-benchmark, per-domain baselines), after a false-red audit found 58.6% of CI failures were inactionable flake; a weeklyci-flake-report.ymlnow measures the false-red rate, andCI Qualityfails a draft PR fast while running a ready PR to completion (ADR2026-08-22-1;#3595,#3669). - Skill projection delivers real copies, never absolute symlinks, healing dangling links in dev containers and sandboxes (
#2412; ADR2026-07-19-1). - The
ExecutionModethree-way name collision is untangled — the ownership enum is renamedWorkProductKind(member string values unchanged, so WP frontmatter stays wire-compatible), the dead runtime duplicate is retired, and a re-drift guard prevents recurrence (#3416). - Docs consolidated under one predictable
docs/root with user (guides/) vs contributor (development/) split and old-URL redirects, and docs can now be markeddurableso a standing reference is never flagged as a stale draft (#2215,#3368).
For the complete, line-by-line list of every change — every Added, Fixed, Changed, and Breaking entry with its full before→after detail — see the [3.2.6rc1], [3.2.6rc2], and [Unreleased] (3.2.6rc4) sections of the canonical CHANGELOG.