3.2.x — Doctrine-runtime depth · core-domain strangling · DevEx
Milestone: 3.2.x (open) ·
Status: active · Declared: 2026-06-16 · Advances: epics #1619 (runtime/state SSOT),
#1868 (canonical seams), #1878 (coordination strangler).
Theme
A stabilization-and-depth cycle: make the governance layer actually shape runtime, strangle our
core domains onto single sources of truth, and lower the cost of doing both. Shipped as emergent
patches (3.2.1, 3.2.2, …) that each advance one of the three goals below; the cycle stays open
until they hold. No new shadow paths — every change routes a duplicate onto an existing authority
or extracts a pure seam from an inline blob, never builds a parallel one.
Goals
G1 — Deepen Doctrine / Charter / DRG impact on runtime execution
Wire the charter + doctrine layer and the Doctrine Resolution Graph (DRG) into the runtime
execution loop, so directives, tactics, agent profiles, and mission-step contracts demonstrably shape
what next/the commands do — not just sit as resolvable config. Close the gap between "doctrine
exists" and "doctrine governs execution."
Epic #2466 — Doctrine/Charter extensibility & the pack ecosystem. Turn the doctrine substrate from built-in behaviour into an author-able pack ecosystem, so customers define/refine their own doctrine (mission types, assets, shortcodes) against the same activation/cascade/DRG machinery. Much of the core/workflow/topology/status work was the enabler. The whole epic is in 3.2.x — the dependency order is sequencing, not phasing (if items slip to 3.3.x later, that's a future call):
- #2467 (keystone · L) — split the monolithic
built-indoctrine into packs + compound packs (pack manifestdepends_on, DAG resolution + cycle-detection in the activation engine). Land as a pure refactor + compat shim first; everything below builds on it. - #2468 (L) — promote
mission-typeto a first-class doctrine artifact kind (behaviour-as-config; retires the deliberateMissionTypeNotAnArtifactKindside-channel — needs a decision record). - #2471 (M) — extract the pack validator (
validate_pack+DoctrineHealthReport) as a dependency-light CI tester with no full-CLI import (mirrors the shared-package-boundary layering). - #2469 (S) — loose-contract
assetskind · #2470 (M) — shortcodes / harness-command aliases as doctrine (extends thecommand_renderer/manifest pipeline, not a fork). - #2472 (S) — decide the
procedurekind's fate after #2468 · #2473 (M · orthogonal) — scheduled model-discipline currency pipeline (human-in-loop PR, never auto-merge).
Open decisions ride on the issues (#2469 kind-vs-template · #2472 procedure fate · #2473 fold-vs-track).
Epic #2519 — Charter authoring & lifecycle
robustness. The consume-and-govern paths for charter/doctrine are solid; the author, observe, and
reproduce paths are thin. Surfaced while authoring the mission-wrap-up-sequence procedure +
DIRECTIVE_046 directly against src/doctrine/. Sibling to #2466 (extensibility/packs) — same G1
theme from the maintainer/first-party side. A pre-spec research squad (2026-07-10) found the three
original children collide on one un-owned defect — the activation surfaces (config.activated_* ↔
answers.selected_* → references.yaml/graph.yaml) are disjoint ledgers with no reconciler — so a
foundation slice (#2526) is carved out as the prerequisite. Sequence #2526 → #2522 (C) → #2521
(B) → #2520 (A) (shared seams: charter.activation_engine.commit_plan/_save_config,
src/doctrine/graph.yaml generation, the charter-init/intake flow):
- #2526 (Slice 0 · foundation, prerequisite) — unify the charter activation surfaces: reconcile
config.activated_*↔answers.selected_*, makeactivate/deactivatewrite-through (or an explicit--resynthesize), and extendconsistency_checkto assert config↔answers↔references parity (fail closed). Unblocks and de-conflicts C and B (the divergence bit PR #2524). - #2520 (A) — charter domain events (
CharterCreated/CharterUpdated, open payload) through the existing CLI sync/SaaS event path; no charter lifecycle event exists today, so SaaS cannot observe activation/creation deltas or authorship. Spans repo-local emit wiring + externalspec_kitty_eventscontract + SaaS consumer; splittable. - #2521 (B) — charter-init harness-freshness preflight + deterministic intake inputs (stale/
missing tooling across agent harnesses; intake not deterministically loading its inputs). Notes a
future
charter discovery/updatecustom mission type as the long-term vehicle. - #2522 (C) — doctrine-authoring surface + docs: a
charter authorscaffold + maintainer how-to for editing a built-in artefact → regenerating the generatedgraph.yaml→ the freshness gate (authoring is currently reverse-engineered).
G2 — Strangle out our core domains
Continue the #1619 runtime/state decomposition: take each core domain (identity/naming, path/read-path, coordination/topology, status, lanes, ownership) onto its canonical SSOT, route every consumer to consume it, and ratchet the duplication class shut. Extract → route → enforce, domain by domain, behind characterization tests.
The full #1878 coord/primary write-side strangler is in-scope for G2 (operator decision, supersedes the earlier 3.3.x split below). Both slices land in 3.2.x: placement-routing (which partition a write targets — coord vs primary, by kind) and commit/protected-branch durability (how a write actually lands once routed). The coord-primary-partition-lock mission delivers the placement-routing slice under this cycle; the commit-durability slice is a 3.2.x fast-follow mission, not deferred to 3.3.x.
2026-08-01 scoping gap: placement-routing and commit-durability both presuppose a write already originates inside a valid mission workspace — neither checks that the invoking checkout is the one the mission actually declared. Design-spike #3129 names this precondition gap (dialectic-squad corroborated; see 3-2-x-milestone-roadmap.md § Addendum 2026-08-01). The cheap fix — #3128, a fail-closed checkout-identity check — is recommended for folding into this G2 scope now. The larger shadow-workspace redesign that #3129 itself proposes remains a separate, ungated design-spike pending an operator decision on scope.
First active slice — naming / identity routing rider (the 3-squad investigation, 2026-06-16, as narrowed by the neutral scoring panel). The static
branch_naming/mid8()seam is a sound SSOT (built by the 3.2.0 work; ADR2026-03-09-1"Prompts do not discover context. Commands do"; FR-009/FR-012) — that survived every adversarial pass. The widerExecutionContextcompute-once-thread-through design is real but not yet load-bearing (built-and-parked, mutable, internally split-brained — see the evidence trail); threading it is a later builder-hardening effort (3.2.x parallel track), not this rider. So the rider is the cheap, low-risk subset: route the ~20 baremission_id[:8]sites throughmid8()(bulk/standalone/dashboard — wrong cardinality to thread), adopt the fragment only at the 2–3 sites that already hold a context, and extend the literal-ban ratchet to bare…_id[:8]repo-wide as a tripwire. The static composes (#2000/#1899-tail/#1900), theresolve_lanes_dirseam (#1993, returns both surfaces), thelocate_project_rootcollapse (#1971-tail), and the ownership existence-check (#1888, verify-and-close) are the write/static end of the same superset. Guardrails: keepExecutionContextaction-scoped (no god-object); keep the three C-LANES-1 surfaces as three fragments; tests pin which fragment is consumed, not just the value (byte-identity masks wrong-fragment conflation under flattened topology). Full research:docs/plans/engineering-notes/naming-identity-ssot-strangler/.Other core domains (status, coordination write-side, lanes) follow as later 3.2.x slices or roll to 3.3.x as they emerge.
G3 — DevEx & enablers
Lower the cost of the above and of contributing generally: pure-seam extractions for testability
(e.g. #1993 removes ~12 mocks), the regression-proof ratchets/guards that make a strangled class
stay strangled, and the maintainer governance surface (this docs/release-goals/ convention +
how-to-maintain.md — tracker structure, priorities, types, milestones).
Evidence trail — dialectic + neutral scoring (read this before trusting any metric)
Honesty note (supersedes the earlier "evidence-grounded" framing). The first corroboration squad was briefed to corroborate the operator's goals, which primed it toward agreement. A red-team squad then refuted the framing, the metrics-as-proof, and the sequencing (it did not refute that the engineering is real). A subsequent neutral scoring panel (severity · ROI · architecture) scored the candidate 3.2.1 leads with no predetermined answer. The honest, surviving statements:
- The goals are legitimate operator intent, not a "proven data-driven continuation." The underlying epics (#1619/#1666/#1868/#1878) are real and pre-exist v3.1.10; the taxonomy mapping them to G1/G2/G3 was authored after the fact. Treat the goals as direction, not as something the metrics "prove."
- The static
branch_naming/mid8()seam is a genuine, sound SSOT — this survived every adversarial pass. The cheap routing of the baremission_id[:8]sites through it is a real, low-risk win. - Stop citing the confounded metrics as proof. "−76% status bypass", "authorities cooled",
"+550%
mission_id[:8]" measure syntax / per-block complexity, not coupling quality; system-levelsrc/SLOC grew +115% in range and no legacy path was retired (extract-then-coexist). The ratchet is a useful regression tripwire, not a completeness oracle (it passes today with ~20 live[:8]sites and is defeated bymid[:8]/[0:8]/helper shape-shifts). - "Thread the
ExecutionContexteverywhere" is NOT the spine — the composite is built-and-parked, mutable, and internally split-brained (branch_name ≠ branch_ref.target_branch,resolution.py:793-801). Fixing that is a separate, later builder-hardening effort, not this slice.
Neutral 3.2.1 scoring verdict: all three scorers leaned impact-first — open the
write-side/single-resolution authority surface (#1832 → #1716), demote naming to a parallel rider.
The operator chose safety-first (the naming rider as the opener) as a deliberate low-risk-momentum
trade-off — explicitly a values choice, not a data verdict. This declaration follows that choice:
naming-rider-first below, with the impact work sequenced as fast-following 3.2.x patches. Full evidence
and the decision record:
docs/plans/engineering-notes/3-2-x-goal-corroboration/
(SCORING-SYNTHESIS.md · DIALECTIC-SYNTHESIS.md).
Operator bug evidence intake (#2007, 2026-06-16): the "3.2.0 training bugs that Robert witnessed"
validate the same coord/read-path and mission-identity surface in this PR (STATUS_READ_PATH_NOT_FOUND,
MISSION_NOT_FOUND, finalizer missing spec.md/meta.json in coord worktrees, and implement/finalize
re-reading a different surface than the one the prior step created). They also add important
non-overlap evidence: command-contract drift (doctrine list, setup-plan, agent action implement --json), stale-charter preflight/status loops, submodule/gitfile root resolution, decision
command mission-path semantics, and raw Python template import failures. Treat #2007 as an expansion of
the 3.2.x evidence base: fold overlapping single-resolution bugs into the #1832/#1716/#1878 fast-follow,
and track the non-overlap items as separate DevEx/runtime repair work. The naming rider alone is not a
complete explanation or fix for the witnessed 3.2.0 training failures.
Non-goals (→ 3.3.x or later)
- UX / dashboard look-and-feel, user flows, SaaS tie-in — the 3.3.x focus.
- Extracting other emergent domains beyond the core set — surfaced and split in 3.3.x.
Superseded non-goal (operator decision): the #1878 coord/primary write-side strangler (placement-routing and commit/protected-branch durability) was previously tracked to 3.3.x here. It now sits entirely in 3.2.x/G2 above — see the coord-primary-partition-lock mission (placement slice) and its 3.2.x fast-follow (durability slice).
Success criteria (cycle closes when these hold)
- G1: doctrine/DRG demonstrably gates a runtime decision path (with a test proving the directive/contract changes behaviour), not just resolves.
- G2: the naming/identity/read-path class produces zero new regressions for a full cycle;
consumers route through the SSOT (no inline
mission_id[:8]/kitty/mission-{…}/.worktrees/…/parents[N]outside the seams); the ratchet covers the full recurrence shape repo-wide incl.dashboard/scanner.py, and its allow-list shrinks; ≥1 additional core domain extracted. - G3: the DevEx enablers landed (seam extractions + ratchets + governance docs) are in use; no new shadow path introduced cycle-wide.
Emergent patches
- 3.2.1 — naming routing rider (the deliberate low-risk opener; chosen over the impact lead the
neutral panel preferred). Route the ~20 bare
mission_id[:8]sites throughresolve_mid8/mid8(), extend the literal-ban ratchet as a tripwire (scoped honestly — partial, syntax-level), land theresolve_lanes_dir(#1993) /locate_project_root(#1971) seams, and verify-and-close #1888. Sequencing constraint (binding): #1993 must not ship as a bare extraction — extractingresolve_lanes_diralone half-strangles the read path into a new shadow path (the_lanes_feature_dirtwin). Either carry a minimal read-side adoption of the new seam in the same WP, or defer #1993 to the write-side patch with #1832. - 3.2.2 — write-side / single-resolution surface (the impact work the panel ranked first, sequenced
to fast-follow). Open with #1832 (
agent action implement"no workspace resolved" — the safe, verified P1 that proves "consume the resolved context, don't re-derive"), drive to #1716 (P0 coord-topology authority root, keystone of #1619/#1878). Re-test #1827 first (it may be stale — the neutral panel could not reproduce the circular failure); fast-follow if real, close-with-evidence if not. - 3.2.x (parallel / emergent) — the #1619 builder-hardening slice (un-mutate the
ExecutionContextbuilder, close the internalbranch_name ≠ branch_ref.target_branchinvariant); the #1891 residual (agent action implement --json, independent DevEx); G1 doctrine/DRG-into- runtime depth; the next core-domain strangle. Shapes pinned as each is scoped. - Tracker hygiene (do regardless of lead): milestone the currently-unmilestoned P0/P1 work (#1716, #1827, #1832, #1891, #1619/#1666) onto 3.2.x/3.3.x — the milestone currently holds only the (now-closed) naming issues, so the burndown understates the real cycle.
- Cycle stays open until all three goals' success criteria hold.
Links
- Milestone: https://github.com/Priivacy-ai/spec-kitty/milestone/4 · Convention:
README.md· Next cycle:3.3.x.md - Research (G2 first slice):
00-OVERVIEW.md - Baseline shipped:
3.2.0(PR #2001) - Tracker (G2 first slice): #2000 · #1971 · #1993 · #1888 · #1900