Troubleshooting Charter Failures
This guide covers the most common Charter failure modes and how to fix them.
For background, see How Charter Works. If you haven't set up a charter yet, or want the full interview-to-generation flow rather than a specific failure fix, start at How to Set Up Project Governance instead.
1. Stale bundle
Model change: this failure mode used to be described as
charter.mddrifting from a derived bundle, withcharter syncas the fix. That model is retired..kittify/charter/charter.yamlis the authoritative, resolving source;charter.mdis a non-authoritative prose companion the runtime never parses, so it cannot cause drift.charter syncis now a confirmed no-op — it always reportssynced: Falseand writes nothing. If you have this page bookmarked from an older run, use the symptoms and fix below instead. See How Charter Works for the full authoritative-source model.
Symptoms:
uv run spec-kitty charter status --jsonreportssynthesized_drg.stateas"stale"spec-kitty nextinjects governance context that does not reflect recent edits tocharter.yaml'sgovernance:ordirectives:sections- Agent behavior does not reflect recent changes you made to
charter.yaml
What is happening: charter.yaml (the authoritative source) was edited after the last
charter synthesize run, so the synthesis manifest's stored content hash no longer matches a
freshly computed hash of charter.yaml. The synthesized doctrine graph (DRG) under
.kittify/doctrine/ is stale relative to the charter that produced it. This is expected any time
you hand-edit governance, directives, or activation in charter.yaml — it self-heals on the
next successful synthesis run, which recomputes and re-stamps the hash.
Fix:
# 1. Check for graph-native decay
uv run spec-kitty charter lint
# 2. Re-run synthesis (recomputes and re-stamps the content hash)
uv run spec-kitty charter synthesize
# 3. Re-validate the bundle
uv run spec-kitty charter bundle validate
# 4. Confirm no drift
uv run spec-kitty charter status
There is no separate re-sync step: charter sync no longer extracts anything from charter.md,
so it is not part of this fix.
2. Missing doctrine
Symptoms:
uv run spec-kitty charter statusreports no bundle, an empty bundle, or missing.kittify/doctrine/spec-kitty nextfails or warns that no governance context is available- Agent prompts receive no Charter context
What is happening: The synthesis step has not been run, or the .kittify/doctrine/ directory
is missing or empty.
Fix:
# 1. Run the full synthesis flow
uv run spec-kitty charter synthesize
# 2. Validate
uv run spec-kitty charter bundle validate
# 3. Confirm
uv run spec-kitty charter status
Model change: this failure used to be framed as "
charter synthesizefails becausecharter.mddoes not exist." That framing is stale. No failure branch incharter synthesizechecks forcharter.md— the actual gate is.kittify/charter/charter.yaml(the authoritative, resolving source), plus the interview answers it is compiled from.charter.mdis a non-authoritative prose companion. See How Charter Works.
If charter synthesize fails because charter.yaml does not exist yet (or the interview
answers it is compiled from are missing):
# Run the interview and generate charter.yaml first
uv run spec-kitty charter interview --profile minimal --defaults
uv run spec-kitty charter generate --from-interview
# Then synthesize
uv run spec-kitty charter synthesize
uv run spec-kitty charter bundle validate
Symptom: spec-kitty dispatch reports the request was "routed to the generic agent" instead
of a specialist, on a project with no charter configured yet.
What is happening: the generic-agent fallback (is_charter_empty) fires whenever
.kittify/charter/charter.yaml is absent, no org/project pack is registered, and no
agent_profiles activation is present. Plain charter pack apply minimal only writes activation
keys into .kittify/config.yaml — it does not compile charter.yaml, so the bundle stays absent
and the fallback still fires. Applying minimal alone does not resolve this symptom.
Fix: apply a starter pack and compile it into the bundle in the same step, so
.kittify/charter/charter.yaml actually exists:
uv run spec-kitty charter pack apply minimal --compile
--compile chains spec-kitty charter generate --no-from-interview, producing
.kittify/charter/charter.yaml. The fallback check only tests the bundle's presence, not its
contents, so once the file exists spec-kitty dispatch moves off the generic-agent short-circuit
and back to normal profile routing (verified directly: empty_charter_fallback flips from true
to false, and an unambiguous request routes to a real specialist profile).
Note: minimal activates a curated set of directives and tactics only — it declares no
agent_profiles key (see src/charter/packs/minimal.yaml's own header), so this fix does not by
itself narrow which specialist gets picked. With no explicit agent_profiles activation, the
router still considers every built-in profile (three-state "admit all" semantics) and may report
ROUTER_AMBIGUOUS for underspecified requests — pass --profile <profile-id> to disambiguate
when that happens.
See Quick baseline via a starter pack for the additive-merge caveat.
3. Compact-context limitation
Symptoms:
- Governed mission actions receive incomplete Charter context
- Large project governance appears to be truncated in agent prompts
- Agents reference only a subset of your directives
What is happening: When the DRG context payload for an action is too large to include in full, the runtime falls back to compact-context mode — a summarized view that includes resolved paradigms, directives, and tool list but omits full doctrine library text.
This is a known limitation (see issue #787 in the project issue tracker; check that issue for current resolution status).
Workarounds:
- Reduce the scope of
charter.yaml'sdirectives:section by removing directives that are not relevant to the current project phase or that overlap significantly with other directives. (charter.mdis a non-authoritative prose companion the runtime never parses — editing it has no effect on the DRG context payload.) - Break a very large project governance layer into smaller, focused governance domains, each with its own charter.
- Use
charter resynthesize --topic <selector>to regenerate only the high-priority directives and ensure they are correctly represented in the DRG.
4. Retrospective gate failure
Symptoms:
spec-kitty nextblocks at mission terminus with a retrospective gate error- Mission cannot transition to
done - You see a message like "Charter does not authorize operator-skip in autonomous mode"
What is happening: The retrospective learning loop gate is blocking mission completion. In autonomous mode, the retrospective is mandatory and cannot be skipped. In HiC mode, the gate offered a retrospective and requires either running it or explicitly skipping it.
Fix for HiC mode:
# 1. View pending retrospective (summary)
uv run spec-kitty retrospect summary
# 2. Preview proposals for the blocked mission
uv run spec-kitty agent retrospect synthesize --mission my-feature-slug
# 3. Apply proposals (or skip in HiC mode by responding 'n' with a reason at the terminus prompt)
uv run spec-kitty agent retrospect synthesize --mission my-feature-slug --apply
Fix for autonomous mode: The retrospective cannot be skipped. If the facilitator failed:
# Check the retrospective record
# .kittify/missions/<mission_id>/retrospective.yaml
# View the summary for diagnostics
uv run spec-kitty retrospect summary
# Check for facilitator errors in the event log
# kitty-specs/<slug>/status.events.jsonl (filter by event_name prefix "retrospective.")
If the facilitator itself errored (exit code 2 with "Retrospective facilitator failed"), check
the retrospective YAML for schema errors and the status events file for the error event. Once
the underlying data issue is fixed, re-run spec-kitty next to retry the gate.
5. Synthesizer rejection
Symptoms:
uv run spec-kitty agent retrospect synthesize --mission <slug> --applyexits with non-zero code- Proposals are not applied
- The output shows "Conflict detection is fail-closed: no proposals applied"
What is happening: Two or more proposals conflict with each other (e.g., both try to add the same glossary term with different definitions). The synthesizer fails closed and applies nothing.
Fix:
# 1. Run dry-run to see the conflict details
uv run spec-kitty agent retrospect synthesize --mission my-feature-slug
# 2. Read the conflict report — it names the conflicting proposals and the conflicting field
# 3. Apply only the non-conflicting proposals, or edit the durable target surface manually
uv run spec-kitty agent retrospect synthesize --mission my-feature-slug --proposal-id P1 --apply
# 4. If you changed charter-derived state manually, re-run synthesis/validation as needed
uv run spec-kitty charter synthesize
uv run spec-kitty charter bundle validate
# 5. Re-run retrospect synthesize for the surviving proposal set
uv run spec-kitty agent retrospect synthesize --mission my-feature-slug --proposal-id P1 --apply
Diagnostic Quick Reference
| Question | Command |
|---|---|
| Is the bundle current? | uv run spec-kitty charter status |
| Are there graph decay issues? | uv run spec-kitty charter lint |
| Is the bundle schema valid? | uv run spec-kitty charter bundle validate |
| What retrospectives are pending? | uv run spec-kitty retrospect summary |
| What proposals exist for a mission? | uv run spec-kitty agent retrospect synthesize --mission <slug> |
See Also
- How to Set Up Project Governance — the complete interview-to-generation flow
- How to Synthesize and Maintain Doctrine
- How to Use the Retrospective Learning Loop
- Retrospective Schema Reference
- How Charter Works