Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .claude/skills/gov/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ If implementation reveals a spec bug, do not silently deviate:
- Release that amendment on the normative RFC with an appropriate patch, minor, or major `govctl rfc bump`; the new version starts in `spec`.
- Continue authoring that new version in `spec` without another bump, then advance to `impl` to seal the corrected baseline.
- A current-version changelog correction uses `govctl rfc edit <RFC-ID> changelog.*` and does not affect the sealed content baseline.
- If an RFC in `impl`, `test`, or `stable` has no sealed signature, stop lifecycle mutation. Run migration, or restore a consistent known-good baseline comprising the RFC TOML and its complete Clause TOML set from version-control history; do not reconstruct it from possibly amended content. See [[RFC-0000:C-PHASE-LIFECYCLE]].
- For a Clause introduced in the current normative `spec` candidate whose `since` equals the RFC version, use `govctl clause delete`; it scans all governed artifacts and reports every referrer before allowing deletion. Inherited Clauses use deprecate or supersede. See [[RFC-0000:C-CLAUSE-DEF]].

Ask before the lifecycle-owned bump unless the user already granted full authority.

Expand Down
2 changes: 2 additions & 0 deletions .claude/skills/rfc-writer/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ Before editing an RFC, inspect its status and phase:
- In `spec`, RFC and Clause edits refine the current version candidate and do not require another version bump.
- In `impl`, `test`, or `stable`, edits that change RFC or Clause content create an unversioned amendment. Lifecycle-owned metadata updates performed by dedicated verbs and current-version changelog-only corrections are exempt. The `/spec` or `/gov` workflow must release qualifying amendments with a version bump before further phase progression.
- Entry from `spec` to `impl` seals the final RFC and Clause content as that version's implementation baseline.
- A version-changing bump is not available in `spec`; it opens the next candidate only from `impl`, `test`, or `stable` after an amendment.
- A deprecated RFC cannot start another version lifecycle.

This helper writes specification content but does not perform lifecycle verbs.
Expand All @@ -164,6 +165,7 @@ it through the generic edit surface:
- A Clause created in a draft RFC remains pending until RFC finalization assigns the current version.
- A Clause created in a normative RFC already in `spec` receives the current RFC version immediately.
- A Clause created in `impl`, `test`, or `stable` remains pending until a content-changing RFC bump assigns the next version.
- An unreferenced Clause introduced in the current normative `spec` candidate may be deleted while its `since` equals the RFC version; inherited Clauses must be deprecated or superseded.
- A deprecated RFC does not accept new Clauses.

## Rendering Rules
Expand Down
2 changes: 2 additions & 0 deletions .claude/skills/spec/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,10 @@ For RFC work:
- If the RFC is draft, do not bump it; when ready, ask permission before `govctl rfc finalize <RFC-ID> normative`
- If a normative RFC is in `spec`, edit the current version candidate directly; do not bump it again for those edits
- If a normative RFC is in `impl`, `test`, or `stable`, an RFC or Clause edit creates an unversioned amendment; after review, ask permission before using `govctl rfc bump` to release it as the next version in `spec`
- If a normative RFC in `impl`, `test`, or `stable` lacks a sealed signature, stop and run migration or restore the baseline; do not use a bump to infer it
- If the RFC is deprecated, do not edit or version-bump it
- Use `govctl rfc edit <RFC-ID> changelog.*` for current-version changelog corrections; these do not change version, phase, or the sealed content signature
- Delete an unreferenced Clause only in a draft RFC or when it was introduced in the current normative `spec` candidate (`since` equals the RFC version); inherited Clauses require deprecation or supersession

Semver guidance for RFC amendments:

Expand Down
8 changes: 8 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ RFCs are constitutional law. Code that conflicts with a normative RFC is a bug.
- No silent deviation: fix the code or propose an RFC amendment
- Normative RFC content MAY continue changing without another bump while its current version remains in `spec`
- Content changed after entry to `impl` is an unversioned amendment and MUST be released by a version bump before further phase progression
- Version-changing bumps open a new candidate only from `impl`, `test`, or `stable`; they MUST NOT be used to retarget an open `spec` candidate
- Cite RFC clauses when implementing invariants

### Law 2: Phase Discipline
Expand Down Expand Up @@ -106,13 +107,20 @@ Within one version, phase transitions are forward-only. A content-changing bump
after `impl`, `test`, or `stable` starts the next version in `spec`; it is not a
backward transition of the sealed version.

Entry from `spec` to `impl` sets or replaces the sealed content signature. If an
RFC already in `impl`, `test`, or `stable` has no sealed signature, do not bump or
advance it; run migration or restore the baseline from version-control history.

Clause version assignment follows [[RFC-0000:C-CLAUSE-DEF]] and
[[RFC-0002:C-LIFECYCLE-VERBS]].

Clause `since` is lifecycle-owned. Draft clauses receive it at finalization,
clauses created in a normative RFC already in `spec` receive the current version
immediately, and clauses created while a normative RFC is in `impl`, `test`, or
`stable` remain pending until a content bump assigns the next version.
An unreferenced Clause introduced in the current normative `spec` candidate may
be deleted while `since` equals the RFC version. Inherited Clauses must be
deprecated or superseded.

---

Expand Down
33 changes: 21 additions & 12 deletions docs/guide/rfcs.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ EOF
```

Finalization is the initial publication boundary for a draft RFC. A
version-changing bump requires normative status, so draft and deprecated RFCs
are rejected. Changelog-only corrections do not change the version and remain
available through either `rfc edit ... changelog` or `rfc bump --change`.
version-changing bump opens the next candidate from a normative RFC in `impl`,
`test`, or `stable`; draft, deprecated, and already-open `spec` RFCs are rejected.
Changelog-only corrections do not change the version and remain available
through either `rfc edit ... changelog` or `rfc bump --change`.

## Working with Clauses

Expand Down Expand Up @@ -144,18 +145,22 @@ govctl clause edit RFC-0010:C-SCOPE text --stdin < clause-text.md

### Delete a Clause

Accidentally created clauses can be deleted from **draft** RFCs only:
Accidentally created clauses can be deleted before they become part of a sealed
version:

```bash
govctl clause delete RFC-0010:C-MISTAKE -f
```

**Safety:** Deletion is only allowed when:
**Safety:** Deletion is only allowed when no artifact references the Clause and
either:

- The RFC status is `draft`
- No other artifacts reference the clause
- The RFC status is `draft`; or
- The RFC is `normative/spec` and the Clause `since` equals the current RFC version.

For normative RFCs, use `govctl clause deprecate RFC-0010:C-OLD` instead.
The second case identifies a Clause introduced only in the open candidate.
Inherited Clauses and all Clauses in sealed phases use `govctl clause deprecate`
or `govctl clause supersede` instead.

### List Clauses

Expand Down Expand Up @@ -220,14 +225,17 @@ Phase transitions are gated:
- `spec → impl` requires `status = normative`
- `spec → impl` requires every Clause to have a resolved `since` version
- `spec → impl` seals the current RFC and Clause content signature
- `impl → test` and `test → stable` require that sealed signature to remain present
- Each phase has invariants that must be satisfied

The sealed signature is a content baseline, not a file lock. A code-only defect
found during `impl` can be fixed without changing the RFC. If RFC or Clause
content must change, edit it and then release that amendment with a patch,
minor, or major bump. The bump starts the new version in `spec`; phase
progression rejects the amendment until that happens. Changelog-only corrections
do not affect the sealed baseline.
do not affect the sealed baseline. If a sealed-phase RFC has no signature, bump
and later phase progression stop without changing files; run `govctl migrate` or
restore the baseline from version-control history instead of guessing it.

## Versioning

Expand All @@ -242,9 +250,10 @@ govctl rfc bump RFC-0010 --minor -m "Add new clause for edge case"
govctl rfc bump RFC-0010 --major -m "Breaking change to API contract"
```

A content-changing bump starts the new version in `spec`. RFC and Clause content
can continue changing during that `spec` phase without another version bump;
advancing to `impl` seals the final content for the version.
A content-changing bump starts the new version in `spec` only from `impl`, `test`,
or `stable`. RFC and Clause content can continue changing during that `spec` phase
without another version bump; a second version-changing bump is rejected.
Advancing to `impl` seals the final content for the version.

Use change-only bump syntax to append categorized metadata without changing the
RFC version:
Expand Down
27 changes: 20 additions & 7 deletions docs/rfc/RFC-0000.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!-- GENERATED: do not edit. Source: RFC-0000 -->
<!-- SIGNATURE: sha256:343dc69cafb6aebb839104033582d2159a08ce43085acf7c221bebd9e7f936a4 -->
<!-- SIGNATURE: sha256:6dc7f89a6d882fa5bc4533cc7d3abcf4d8a16b954020bb6bfbde5154af6e3180 -->

# RFC-0000: govctl Governance Framework

> **Version:** 1.6.1 | **Status:** normative | **Phase:** stable
> **Version:** 1.7.0 | **Status:** normative | **Phase:** stable

---

Expand Down Expand Up @@ -104,23 +104,25 @@ Phase rules:
- Phase transitions MUST NOT skip a phase.
- Each phase transition MUST satisfy the preceding phase gate.
- `stable` MUST be terminal for one RFC version.
- A later version bump MAY start another phase lifecycle for the RFC.
- A version-changing bump MUST be rejected while the current version remains in `spec`.
- A later version-changing bump MAY start another phase lifecycle only when the current version is in `impl`, `test`, or `stable`.
- A version bump that releases a detected content amendment MUST start the new version at `spec`.
- Only a normative RFC MAY advance from `spec` to `impl`.
- While phase is `spec`, RFC and clause content belongs to the current version candidate and MAY change without another version bump.
- The `spec` -> `impl` transition MUST replace the stored amendment signature with a signature of the current RFC and clause content.
- The `spec` -> `impl` transition MUST set or replace the stored amendment signature with a signature of the current RFC and clause content.
- The `spec` -> `impl` transition MUST reject pending clauses as defined by [RFC-0000:C-CLAUSE-DEF](../rfc/RFC-0000.md#rfc-0000c-clause-def).
- Changelog-only updates MUST preserve phase.
- Changelog-only updates MUST NOT change the amendment signature.
- In `impl`, `test`, or `stable`, content that differs from the stored amendment signature is an unversioned amendment.
- An unversioned amendment MUST be released by a version bump before further phase progression.
- A normative RFC in `impl`, `test`, or `stable` MUST have a stored amendment signature. A version-changing bump or later phase progression MUST reject a missing signature without mutation and MUST leave pending clauses unchanged.
- A draft RFC MUST NOT enter `stable`.
- A deprecated RFC MUST NOT enter `impl` or `test`.

For amendment detection, RFC content is the canonical RFC and clause data other than RFC `version`, `phase`, `changelog`, and `signature` fields. Those four fields are lifecycle or changelog bookkeeping and MUST be excluded from amendment comparison. A stored signature is the sealed content baseline for the current version after it enters `impl`. While the version remains in `spec`, establishing or replacing that baseline MUST NOT be treated as a content amendment. While the version remains in `spec`, establishing or replacing that baseline MUST NOT require another version bump.

**Rationale:**
Scoping phase to one version lets later amendments reuse the existing ordered gates. The `spec` phase is the mutable authoring boundary for that version, and entry into `impl` seals the exact contract that implementation follows. Defining the comparison surface prevents phase progression and changelog bookkeeping from recursively appearing as new content amendments.
Scoping phase to one version lets later amendments reuse the existing ordered gates. The `spec` phase is the mutable authoring boundary for that version, and entry into `impl` seals the exact contract that implementation follows. Defining the comparison surface prevents phase progression and changelog bookkeeping from recursively appearing as new content amendments. Rejecting another version-changing bump from `spec` prevents an unsealed candidate from becoming compatibility history. A missing signature outside `spec` cannot establish a trustworthy amendment baseline through a version change; it requires migration or restoration of the sealed baseline.

> **Tags:** `core`, `lifecycle`

Expand Down Expand Up @@ -194,7 +196,7 @@ Clause kinds:

Deprecation is a lifecycle state (in `status`), not a document kind.

The `since` field identifies the first RFC version that contains the clause. A clause whose `since` field is absent is a pending clause.
The `since` field identifies the first RFC version that contains the clause. A clause whose `since` field is absent is a pending clause. `since` is lifecycle-owned: generic editing MUST NOT set, change, or remove it. Finalization and version bumps MUST assign `since` only to pending clauses and MUST preserve every non-pending clause's existing `since` value.

Clause creation and version assignment MUST follow these rules:
- A new clause in a draft RFC MUST be pending.
Expand All @@ -204,10 +206,12 @@ Clause creation and version assignment MUST follow these rules:
- A version bump of a normative RFC MUST assign the new RFC version to every pending clause.
- Creating a clause in a deprecated RFC MUST be rejected.

Permanent clause deletion MUST be allowed when the containing RFC is draft. Permanent clause deletion MUST also be allowed when the containing RFC is normative, its phase is `spec`, and the clause `since` equals the RFC current version. Permanent deletion MUST be rejected for every other RFC status, phase, or clause-version combination. Permanent deletion MUST reject a clause referenced by any other artifact and MUST report the referencing artifact IDs.

Advancing a normative RFC from `spec` to `impl` MUST reject every pending clause. That transition MUST NOT assign clause version metadata. That transition MUST NOT rewrite existing clause version metadata.

**Rationale:**
A clause can record its version immediately only after that target version is known. Initial draft clauses receive a version only at finalization, amendments created outside `spec` receive a version at the next normative RFC bump, and clauses added to an already-open normative `spec` version can safely use the current version. This preserves version provenance without making phase advancement own clause metadata.
A clause can record its version immediately only after that target version is known. Initial draft clauses receive a version only at finalization, amendments created outside `spec` receive a version at the next normative RFC bump, and clauses added to an already-open normative `spec` version can safely use the current version. This preserves version provenance without making phase advancement own clause metadata. Lifecycle-only assignment and preservation make `since == current version` reliable evidence that a Clause belongs only to the open candidate, while the reference gate prevents dangling governance links.

> **Tags:** `core`, `schema`

Expand Down Expand Up @@ -430,6 +434,15 @@ A guard check MUST pass only when the command exits successfully. If `pattern` i

## Changelog

### v1.7.0 (2026-07-20)

Define single-candidate RFC version boundaries

#### Changed

- Restrict version-changing bumps to sealed RFC versions
- Allow deletion of unreferenced Clauses introduced in the current spec candidate

### v1.6.1 (2026-07-16)

Clarify Clause version assignment at RFC publication boundaries
Expand Down
16 changes: 12 additions & 4 deletions docs/rfc/RFC-0001.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!-- GENERATED: do not edit. Source: RFC-0001 -->
<!-- SIGNATURE: sha256:fbe450aaa4a5efad83cfee7f99cf870737f7b593b1b96f4b9fce2bd800618844 -->
<!-- SIGNATURE: sha256:4dc870d98ade3b8b79236610e51af5b890e3e21a2be0475011031bec075466aa -->

# RFC-0001: Lifecycle State Machines

> **Version:** 0.6.0 | **Status:** normative | **Phase:** stable
> **Version:** 0.7.0 | **Status:** normative | **Phase:** stable

---

Expand Down Expand Up @@ -62,11 +62,11 @@ Within one RFC version, the following transitions MUST be rejected:
- Any skip (for example, spec -> test or spec -> stable)
- stable -> any (`stable` is terminal for that version)

A version bump that releases a detected RFC or clause content amendment MUST start the new RFC version in `spec`, regardless of the prior version's phase. This starts a new version lifecycle and is not a backward transition within one version.
A version bump that releases a detected RFC or clause content amendment MUST start the new RFC version in `spec`, regardless of the prior version's phase. This starts a new version lifecycle and is not a backward transition within one version. Version-changing bump eligibility MUST follow [RFC-0000:C-PHASE-LIFECYCLE](../rfc/RFC-0000.md#rfc-0000c-phase-lifecycle).

Only a normative RFC MAY advance from `spec` to `impl`. A normative RFC's current `spec` content is an authoring candidate rather than an implementation conformance baseline. The most recently sealed version remains the implementation baseline until the current candidate enters `impl`.

RFC and clause content MAY change while the current version remains in `spec`. Such changes belong to the current version. Such changes MUST NOT require another version bump. Advancing from `spec` to `impl` MUST seal the current amendment content as the version's stored signature. The transition MUST reject every pending clause defined by [RFC-0000:C-CLAUSE-DEF](../rfc/RFC-0000.md#rfc-0000c-clause-def).
RFC and clause content MAY change while the current version remains in `spec`. Such changes belong to the current version. Such changes MUST NOT require another version bump. Advancing from `spec` to `impl` MUST set or replace the current version's stored signature with the current amendment content. The transition MUST reject every pending clause defined by [RFC-0000:C-CLAUSE-DEF](../rfc/RFC-0000.md#rfc-0000c-clause-def).

After the current version enters `impl`, amendment content that differs from the stored signature MUST be treated as an unversioned amendment. Phase progression MUST reject that amendment until a version bump releases it and starts the next version in `spec`.

Expand Down Expand Up @@ -239,6 +239,14 @@ Future gates MAY be added via RFC amendment, but MUST NOT break existing valid w

## Changelog

### v0.7.0 (2026-07-20)

Clarify RFC candidate phase transitions

#### Changed

- Bind version bumps and signature sealing to explicit phase boundaries

### v0.6.0 (2026-07-16)

Align RFC phase gates with current-version sealing
Expand Down
Loading
Loading