Upgrading to edikt v0.7.0
This is the real upgrade path. diktahq/edikt's public releases stop at v0.4.5 — v0.5.x was cut but never released, and v0.6.0 has a git tag but no published release. No public project has ever upgraded through those in isolation. If you have an installed project today, it's on v0.4.x, and /edikt:upgrade carries it to v0.7.0 in one run — the sentinel-to-sidecar migration (originally shipped as v0.6.0's headline change) followed by this page's schema and enforcement changes, back to back, in a single pass.
v0.7.0 also changes what happens the next time you write to a file .claude/rules/ governs — not because any of your rules changed, but because edikt now enforces them the way they were actually written. Read Before you upgrade below before running /edikt:upgrade; the mechanical migration step is smaller than the behavior change.
TL;DR
/edikt:upgradeThe slash command runs the sentinel-to-sidecar migration (the real case for essentially every existing install, since none started past v0.4.x), the required sidecar schema v1→v2 upgrade, and recompiles. Read the warning below first — nothing about /edikt:upgrade itself asks you to confirm the enforcement change, because it isn't a migration step; it's the corpus you already have, graded correctly for the first time.
Before you upgrade
Two independent fixes land together, and their combined effect is the thing to plan for.
- Grade derivation now reads actual obligation strength, not a keyword list. Before this release, a directive only graded
mustif its text literally contained "MUST NOT", "NEVER", or "NO EXCEPTIONS". A bare, unconditional "MUST" — how most directives in a typical corpus are actually phrased — fell through toadvisoryregardless of intent. That's fixed: grading now classifies the real RFC-2119 modal force (MUST / SHALL / REQUIRED, either polarity). Measured directly against this project's own compileddirective-index.yamlbefore shipping: 404 of the 420 directives previously gradedadvisorymove tomust. - The deny channel now actually denies. Independently of the grading fix, a
must-grade write that should have been refused was instead allowed onto disk, with only the assistant's turn killed afterward — measured at 14 of 14 sampled denied writes still landing. That's fixed: amust-grade write is now refused before it happens, citing the specific rule.
Combined, on an unchanged corpus: roughly 400 rules that were previously informational-only become enforced, write-blocking rules. If your team writes ADRs and invariants with plain, unconditional MUST language — the common style, and arguably the correct one — expect edits that used to go through silently to start getting refused, correctly, the moment you upgrade.
This is not a regression to work around. A refusal after upgrading means a rule you already wrote, as must-strength language, is now doing what you wrote it to do. If a specific refusal looks wrong for what you actually meant:
- Reword the directive to genuinely conditional language (
SHOULD,MAY, or a qualifiedMUSTwith a stated exception) if the rule was never meant to be absolute. - Don't treat this as a bug to route around by disabling the gate — the fix is in the directive's wording, which is exactly the lever ADR-064 hands back to you: grade now follows what you actually wrote, so a directive that's too strict grades that way because it reads that way.
Do a quick pass over your own ADRs and invariants before upgrading if you want to anticipate which directives will flip, rather than discover it live: any bare "MUST"/"SHALL"/"REQUIRED" statement, not just ones containing "MUST NOT"/"NEVER", is a candidate.
What changed
| Area | v0.6.0 | v0.7.0 |
|---|---|---|
| Grade derivation | Three-word negative-marker match (MUST NOT/NEVER/NO EXCEPTIONS) | Full RFC-2119 modal-force classification (MUST/SHALL/REQUIRED, either polarity) |
| Deny-channel effect | continue:false — write already landed, turn killed after the fact | permissionDecision: "deny" — write refused before it happens |
| Sidecar schema | v1 — one source_excerpt anchor per directive | v2 — source_excerpts[], one to many anchors per directive |
| Compile's Phase B gate | Runs on any schema-valid sidecar | Refuses outright — "Run bin/edikt migrate to-v2 first" — while any v1-shaped sidecar exists |
What /edikt:upgrade does
In order:
- Runs the sentinel-to-sidecar migration if any legacy in-body sentinel remains — the real case for nearly every existing project, since v0.6.0 was never a standalone public step (see Sidecar Migration for the full per-artifact mechanics of this step).
- Runs the required schema upgrade —
edikt migrate to-v2— converting every v1-shaped sidecar to the v2 multi-anchor shape. This step is not optional:/edikt:gov:compile's Phase B dispatch gate refuses to run at all while any v1-shaped sidecar exists in the corpus. - Recompiles (
/edikt:gov:compile), which re-derives every directive's grade under the fixed rule from step 1 above — this is where the 404-of-420 reclassification actually happens for your project. - Reports the result. Run
/edikt:gov:grade-compileafterward if you want a quality score on the freshly re-extracted corpus — not required, but the tool exists and a fresh migration is exactly when it's most useful.
If you're scripting the migration directly rather than going through the slash command, run both migration steps explicitly — edikt migrate sidecars --apply alone leaves any pre-existing sidecar in its old v1 shape:
edikt migrate sidecars --apply # only if migrating from pre-v0.6.0; skip if already on sidecars
edikt migrate to-v2 # required regardless of starting version
/edikt:gov:compile # re-derives grades under the fixed ruleAfter the upgrade
- [ ]
/edikt:doctor— should report sidecars at schema v2 and no pending migration. - [ ] Skim
directive-index.yaml(or/edikt:gov:score's output) for directives that moved fromadvisorytomustand confirm each one is intentionally absolute. - [ ] If a write gets refused that shouldn't be, reword the underlying directive — don't bypass the gate.
- [ ] Commit the recompiled
.claude/rules/and any sidecar schema changes as one commit.
Rollback
edikt rollback reverts the launcher payload only. Neither the schema-v2 migration nor the grade reclassification is reversed by rollback — both are structural/derived changes, the same category the sentinel-to-sidecar migration is documented as permanent (rollback mechanics). If you need to go back further than one payload generation, use edikt use <version> — but your sidecars stay v2-shaped and your directives stay correctly graded regardless of which payload version is active.
Related
- Keeping edikt Up to Date — the general upgrade flow and prior-version history
- Sidecar Architecture — the v2 schema in full
edikt migrate— CLI reference for both migration steps/edikt:upgrade— the orchestrated path