Applied Part 3. Project Constitution: First Rules Referendum
Status: Recommendation. Separating immutable_principles and mutable_rules with explicit ttl, max_scope, rollback_condition is a robust practice. An automatic agent referendum with a deterministic tie-breaker rule is frontier: its form depends on the specific team and models.
For educational walkthrough, it is sufficient to manually fill in constitution.md and verify that mutable rules have ttl, max_scope, and rollback_condition. Automatic referendum and external arbiter belong to the full production track.
"Project constitution" here is a versioned set of invariants, mutable rules, and amendment procedures. The set is checked before executing dangerous actions.
One Word — Two Different Files
In the first volume, the project constitution is distributed across three files: mission.md (why we do this), tech-stack.md (what we write on), roadmap.md (what and in what order). This contract describes the product.
In the second volume, under the same word, a fourth file appears — constitution.md. It does not describe the product, but the contour of safe automation: which agent actions are forbidden, which are permitted with restrictions, who and how changes the rules. This is an overlay, not a replacement. The first volume files remain in place, constitution.md is added alongside and is read before any dangerous action.
If you want a one-line separation: mission/tech-stack/roadmap answer the question "what we are building", constitution.md answers the question "what the agent must not do with this, even if it really wants to".
In the educational minimum, a small constitution.md with two immutable prohibitions and one mutable rule is sufficient. Agent referendum, external arbiter, and automatic playbook checking are only needed for the full track. The chapter builds on Part 6 of the first volume (where mission.md, tech-stack.md, roadmap.md come from) and Part 18 (where the understanding of SDD process security comes from).
Before Reading
- Foundation from the first volume: Part 6 introduces
mission.md,tech-stack.md,roadmap.md; Part 18 explains SDD security.
- Local educational case:
node_not_ready, because on it you can see the difference between a permitted soft action and a prohibition of dangerous operations. - Trace for
capstone/: twoimmutable_principles, onemutable_rule, and a shortgovernance_protocolforhigh_memory_usage. - Key terms for the first pass:
immutable_principlesandmutable_rules. The third layer —governance_protocol— is reference, needed only when the team introduces a voting rule. - What to defer: agent referendum, external arbiter, and automatic playbook checking.
The reason for a separate production layer is simple: scenarios like node_not_ready or autoscale_200pct leave no time for chat. A dangerous action must either pass a formal gate or be blocked. We will address the security of this gate with reference to Part 18. SDD Security. The connection to interacting with already running code is in Part 13. Supporting an Existing Project.
Chapter Roadmap
The chapter is long, and you do not need to read it linearly. The movement map:
- Minimal educational scenario. You fill
constitution.mdby hand: two immutable prohibitions, one mutable rule with six fields. This is all that is needed for credit. - Key ideas. They explain why the minimum looks like this.
- Interview via Qwen Code. One way to speed up filling
constitution.md. On the first pass, you can skip it — manual filling also works. - Full track.
governance_protocol,change_log,decision_hash, referendum. On the first pass, reading them is optional: they become needed when the team gets an automatic gate.
If you are reading for the first time, stop after the "Key Ideas" section and go do the exercise. Return to the full track after you close capstone/constitution.md with the minimum fragment.
Goal
By the end of the section, you will develop a working constitution.md for auto-remediation. Invariants and mutable norms will become clear, evolving through agent referendum and fully traceable in the genealogy of edits.
What this gives in practice. The agent no longer acts on scattered hints. It checks every decision against a formal project contract. Such a contract helps accelerate response to recurring incidents, but does not turn speed into a right to automatically bypass backups, audit, blast radius limits, and safe rollback conditions.
Minimal Educational Scenario
Educational Case
For node_not_ready, you need to permit a soft agent restart at the triage phase, but prohibit dangerous actions with production DB, backups, and audit. The goal is to get a small constitution.md that can be checked by eye before any production action.
Preparation
book2/examples/templates/proposal.md— amendment form.- One list of dangerous actions that cannot be performed automatically.
- One recurring unknown pattern that can become a mutable rule.
For the first pass, you can take this starter set:
dangerous_actions:
- delete_namespace
- restart_database
- bypass_audit_trace
candidate_mutable_rule:
incident_type: node_not_ready
pipeline_phase: triage
permitted_actions: ["soft_restart_agent"]
max_scope: "single_node"
ttl: "30d"
rollback_condition: "repeat_incidents_same_node>=2 or Safety veto"
If you are adapting the chapter for your project, replace the action names, but do not remove max_scope, ttl, and rollback_condition.
Steps
- Write at least two
immutable_principlesas prohibitions, not advice. - Add one
mutable_rulewithincident_type,pipeline_phase,permitted_actions,max_scope,ttl,rollback_condition. - Describe
governance_protocol: roles, quorum, Safety veto, and tie-breaker rule. - Fill in a short
proposal.md: why the rule appeared, who voted, when it activates, and how it rolls back. - Check the file with the question: "what action will the agent be unable to perform, even if it reduces MTTR?". *Expectation: the answer is in
immutable_principles, not in chat.* - Compare with the runnable analog from [
examples/spec-ci/](examples/spec-ci/README.md): the idea is the same — before action, there must be a verifiable gate.
Control Fact
Every mutable rule has ttl, max_scope, and rollback_condition. If at least one field is missing, the rule is not admitted to the constitution and remains a proposal draft.
You can check the file with the same runnable analog as in capstone/:
cd book2/examples/constitution
python3 scripts/check.py \
--constitution specs/constitution.yaml \
--proposal proposals/valid_proposal.md
You will get verdict: PASS. Then repeat with proposals/missing_evidence.md and proposals/conflict_with_immutable.md — you will get verdict: BLOCK with reasons. This is the educational gate before a dangerous action.
Transfer to high_memory_usage
The local case of the chapter is node_not_ready, but the graded one is high_memory_usage. The transfer is done with one line of principle, not by copying the rule.
What to take from node_not_ready | What to write in capstone/constitution.md for high_memory_usage |
|---|---|
| immutable "do not close incident without two OKs in a row" | immutable "do not close high_memory_usage without confirmation that RSS returned below 80% twice in a row" |
mutable soft_restart_agent with ttl: 30d, max_scope: single_node | mutable restart_pod with ttl: 14d, max_scope: single_pod, rollback_condition: 5xx_increase OR memory_percent>=90% after 2 windows |
| Safety-veto when expanding radius | Safety-veto when attempting to expand restart_pod to namespace |
If this line cannot be formulated, the local case has not yet yielded a transferable principle — return to it before moving to capstone/.
How This Gets into capstone/
Transfer to capstone/constitution.md two immutable_principles, one mutable_rule, and a short governance_protocol. If you made proposal.md, leave in capstone/README.md one line with the reason for the rule's appearance. Do not transfer the full agent referendum if it was not run.
Minimum fragment:
immutable_principles:
- "Do not perform auto-remediation without audit_trace."
- "Do not touch stateful workload without confirmed backup."
mutable_rules:
- incident_type: high_memory_usage
pipeline_phase: recovery
permitted_actions: ["restart_pod"]
max_scope: "single_pod"
ttl: "14d"
rollback_condition: "memory_percent>=90% after 2 windows or 5xx increases"
governance_protocol: "Any expansion of max_scope requires a separate proposal."
Reviewable Trace
In the educational package, keep constitution.md together with proposal.md or a change_log record. An amendment without provenance is not considered part of production SDD.
Key Ideas
The first layer of constitution.md is immutable_principles. Under immutable_principles (immutable principles) are understood rules that can never be automatically disabled. These include prohibitions and obligations at the security level:
- do not restart production DB without an up-to-date backup;
- do not delete backups to free up space;
- do not transition an incident to
resolvedwithout confirmed stabilization; - do not bypass in a namespace critical for security.
Formulate these norms as invariants, not as recommendations. It is they who constrain the agent at the moment of pressure, when the shortest path to reducing MTTR can create a larger cascade of failures.
The second layer is mutable_rules. These are mutable norms with a precise radius of action (unlike immutable_principles, such a rule can be canceled or rewritten through a formal procedure). For each such rule, specify at least six fields. What they mean:
incident_type— incident class for which the rule applies;pipeline_phase— response phase (triage,recovery, etc.);permitted_actions— list of permitted actions;
max_scope— blast radius limit (e.g.,single_node);ttl(time to live) — rule validity period, after which it must be reviewed or extended;rollback_condition— condition under which the rule automatically rolls back.
Without these fields, the amendment becomes too broad and starts competing with invariants. Compare two variants.
Bad:
- id: node_not_ready_soft_restart
incident_type: "NodeNotReady"
permitted_actions: ["soft_restart_agent"]
Problem: no ttl, no max_scope, no rollback_condition. The rule is indefinite and without blast radius boundaries. In half a year, no one will review it.
Good:
- id: node_not_ready_soft_restart
incident_type: "NodeNotReady"
pipeline_phase: "triage"
permitted_actions: ["soft_restart_agent"]
max_scope: "single_node"
ttl: "30d"
rollback_condition: "repeat_incidents_same_node>=2 or Safety veto"
For example, permit a soft restart for incident:NodeNotReady at the triage phase, but prohibit it for incident:DBWriteLag at the recovery phase. The same action in different contexts has different risk for data and availability.
Stop for the First Pass
If you are here for the first time, by this point you already have everything for chapter credit: two immutable prohibitions, one mutable rule with six fields, understanding of the difference between it and mission/tech-stack/roadmap from the first volume. Next comes the full track — governance_protocol, change_log, decision_hash, referendum. These mechanisms become needed when the team gets an automatic gate and three-four human roles around it. For the graded capstone/constitution.md they are not mandatory.
If your project does not yet have a single automatic action, go straight to the "Artifacts and Readiness Criteria" section, and finish the full track after chapter 8 (roles resurface there again in file arbitration).
Full Track: governance_protocol
Make the evolution trigger observable: three or more repeated unpredicted incidents with the same pattern_id trigger a mandatory amendment referendum. Such a threshold separates a single anomaly from a stable gap in rules and does not allow changing the constitution after every noisy alert.
Fix the aggregation window, for example 48 hours. In the candidate amendment (that same proposal.md put to referendum) include:
- input events;
- current
unknownclassification; - assumed risk;
- expected effect;
- cancellation condition.
Why several roles here at once, if in the first volume review was done by one person. In Part 16 of the first volume, one reviewer was enough, because the subject of review was feature code in the educational AgentClinic. The cost of error — redo the feature. In a production scenario, the subject of review is different: automatic dangerous action on a live service. The cost of error — lost data, expanded blast radius, hidden closure of P0. One reviewer fails not because they are not smart enough, but because it is hard for a human to simultaneously hold in mind invariant correctness, playbook applicability, and production risk. Therefore, checking is distributed across roles, each with their own narrow question. In the minimum form, these can still be three models of one agent, reading the same file in turn — but their questions are different.
Describe the voting procedure in governance_protocol. It includes agent roles, vote weights, quorum, convening time, and deterministic tie resolution. Minimum composition — three roles:
Verifierlooks for invariant violations;Implementorassesses applicability in the playbook;Safetychecks blast radius, privacy, and rollback conditions.
For passage, set quorum at two votes, rule 2 approve + no Safety-veto, convening within 15 minutes after trigger activation, and tie-breaker rule safety-first. With such a breaker, critical risk from Safety always leads to rejection.
The fourth role, Coordinator, in governance_protocol does not vote. It appears at the next level — in file arbitration (Part 8), where it leads judgment.md and round order. Here, in the constitution, the Coordinator only records the voting outcome in change_log.
Record every update as an immutable trace, not as an edit without provenance. In the record include:
versionandparent_version— current and previous constitution versions;reason— reason for amendment;votes— voting results by roles;
decision_hash— cryptographic hash of the decision, by which it can be recalculated and verified later;incident_context— events that triggered the trigger;activation_time— moment from which the amendment takes effect;- link to diff within the repository.
Such a journal turns edit history into a chain of evidence. If later a question arises why the agent was granted the right to perform an action, the answer will be found not in the team chat, but in a reproducible genealogy of decisions.
Examples and Application
The basic structure of constitution.md can look like this:
immutable_principles:
- id: prod_db_no_restart_without_backup
rule: "Production database restart is forbidden unless a verified backup exists."
enforcement: "always_on"
- id: backups_are_protected_assets
rule: "Backup deletion, overwrite, or quarantine bypass cannot be executed automatically."
enforcement: "always_on"
mutable_rules:
- id: node_not_ready_soft_restart_triage
incident_type: "NodeNotReady"
pipeline_phase: "triage"
permitted_actions:
- "cordon_node"
- "soft_restart_agent"
max_scope: "single_node"
ttl: "30d"
rollback_condition: "increase in repeat incidents or Safety veto"
governance_protocol:
roles:
verifier:
vote_weight: 1
implementor:
vote_weight: 1
safety:
vote_weight: 1
veto: "critical_risk"
quorum: 2
pass_rule: "at_least_2_approve_and_no_safety_veto"
convene_after: "3_unknown_incidents_same_pattern"
convene_within: "15m"
tie_breaker: "safety_first_then_latest_matching_precedent"
change_log:
- version: "1.2.0"
parent_version: "1.1.0"
reason: "3 unknown NodeNotReady incidents in 48h"
votes:
verifier: "approve"
implementor: "approve"
safety: "abstain"
decision_hash: "sha256:..."
activation_time: "2026-05-17T12:00:00Z"
Connect the constitution to gate checks before playbook execution, not after it. The step order is:
- local script checks
immutable_principlesandmutable_rules; - Qwen Code in Plan Mode explains risk and gaps;
- executor gets the right to act.
Commands /constitution and /tasks are not built-in Qwen Code commands. If they are needed, implement them as project custom commands.
Interview via Qwen Code
Before writing constitution.md by hand, conduct the same interview as in Part 6 of the first volume. The production layer adds two contours to the classic triad mission/tech-stack/roadmap, and you cannot enter these contours without explicit human decisions: which actions the agent has the right to perform without confirmation, who gets veto, what maximum blast radius is permitted at the triage phase.
Prompt:
/clear
We are expanding the AgentClinic-production constitution.
Look at @specs/mission.md, @specs/tech-stack.md, @specs/roadmap.md
and @specs/playbooks/node-not-ready.md.
Create a draft @specs/constitution.md with three sections:
- immutable_principles
- mutable_rules
- governance_protocol
Before writing to disk, ask me exactly three grouped questions:
1. Which agent actions in production are always forbidden (backups, audit, secrets).
2. Which actions can be delegated at the triage phase with a blast radius limit and time to live (ttl).
3. Who votes, who has veto, at what threshold is the referendum convened.
Do not write files yet. After my answers, show the change plan, wait for approval.
If Qwen Code immediately starts writing YAML without questions, stop it:
Stop. Do not write files before the interview.
First ask three grouped questions, as specified in QWEN.md.
A good human response to the interview contains decisions, not wishes:
Immutable principles:
No auto-restarts of production DB without verified backup.
No automatic deletion of backups, audit, and secrets — even under pressure to free up space.
Incident does not transition to resolved without two consecutive OKs.
Mutable rules:
At triage phase for NodeNotReady, soft_restart_agent is permitted with max_scope=single_node and ttl=30d.
Rule rollback — upon two repeat incidents on the same node or Safety veto.
Expanding max_scope without referendum is forbidden.
Governance:
Verifier, Implementor, Safety vote. Each vote equals 1.
Quorum — 2 approve and no Safety veto.
Referendum is convened after three unknown incidents with the same pattern_id within 48 hours.
Tie-breaker rule — safety_first.
Then ask Qwen to check its own draft:
Check @specs/constitution.md.
Find immutable rules formulated as recommendations.
Find mutable rules without ttl, max_scope, or rollback_condition.
Find governance_protocol without a tie-breaker rule.
Do not modify files, return a list of discrepancies.
Typical errors at this step:
- immutable rule written as "avoid if possible" — this is a recommendation, not a prohibition;
- mutable rule lacks
rollback_condition, and remains indefinite during an incident; governance_protocoldoes not describe a tie-breaker rule — at equal score the system hangs;change_logis absent, and the very first constitution change loses provenance.
Only after passing this list, fix the draft in your project. In the educational book2/, this step does not require git commands: a readable constitution.md with rule provenance is what matters.
> Constitution gate: runnable analog and project interface. Runnable check is in [examples/constitution/](examples/constitution/README.md) — it reads the constitution YAML and Markdown with YAML-frontmatter (amendment proposal), returns verdict: PASS|BLOCK and a list of blockers. For credit, it is sufficient. In a real project, this gate is supplemented by two more steps: a request to Qwen Code in Plan Mode, and checking playbook max_scope against rule max_scope. All three steps go as one block.
# [runnable] — checking proposal against constitution
python3 book2/examples/constitution/scripts/check.py \
--constitution book2/examples/constitution/specs/constitution.yaml \
--proposal book2/examples/constitution/proposals/valid_proposal.md
# [project script] — same checks on your constitution and playbook
python3 scripts/constitution/check.py \
--constitution specs/constitution.yaml \
--proposal proposals/<your-proposal>.md
# [project script] — Qwen in plan mode, separate gate
qwen -p "Check @specs/constitution.yaml and @specs/playbooks/node-not-ready.md.
Mode: planning only. Tell me, does the remediation plan violate immutable_principles
and which mutable_rules are needed for admission." \
--approval-mode plan \
--output-format json \
> out/node-not-ready-constitution-review.json
flowchart TD A[Incident] --> B[Plan Mode and scripts against immutable] --> C[Mutable rules check] --> D[Admission / Block] --> E[Executed action] C --> F[Unknown incident] --> G[Unknown threshold reached] --> H[Proposal formation] --> I[Referendum] --> J[Commit] --> K[New constitution]
The referendum is conveniently trained on a replay scenario. Three identical unknown incidents create proposal.md, agents vote, and the accepted amendment goes to change_log with a decision hash.
Example: a temporary rule hotfix_ticketing_flood may permit simplified ticket routing for 12 hours. Condition — presence of a checkpoint and preservation of the immutable prohibition on audit loss. After acceptance, check that the amendment did not become indefinite. Verify that ttl, rollback_condition, decision_hash, and activation_time are visible in the repository together with the change record.
Summary
constitution.md sets for auto-remediation the boundary between what the agent can adapt and what it has no right to disable for local optimization.
The roles of layers in this boundary are:
- invariants protect backups, audit, data, and critical zones;
- the mutable layer allows refining playbooks for recurring incidents;
- agent referendum makes rule change verifiable;
- edit genealogy preserves reason, votes, decision hash, and activation moment.
Next, these norms will be checked in an LLM duel: Verifier against Implementor.
Artifacts and Readiness Criteria
| Artifact | Ready when |
|---|---|
specs/constitution.md | immutable rules are formulated as prohibitions, not advice; from the file it is clear what action the agent will be unable to perform even for MTTR improvement |
One mutable_rule | incident_type, pipeline_phase, permitted_actions, max_scope, ttl, rollback_condition are filled — all six fields |
proposal.md or rule provenance record | the amendment has a reason for appearance, otherwise it is not part of the SDD package |
The full track adds several amendments with different blast radii, a change_log record with parent_version, votes and decision_hash, and a project gate that checks the constitution before playbook execution. Consider it ready if the gate actually blocks invariant layer violation before execution, the referendum has quorum, Safety veto, and a deterministic tie-breaker rule, and the accepted amendment is traceable from incident context to diff.
Practice
- Open
book2/examples/templates/proposal.mdand fill it for one dangerous domain (deploy, migrations, incidents, secrets): at least twoimmutable_principles(as prohibitions) and onemutable_rulewithincident_type,pipeline_phase,permitted_actions,max_scope,ttl,rollback_condition. Expectation: every mutable rule contains all six fields; the control fact from the educational scenario is satisfied. - Write
governance_protocol: roles, quorum, Safety veto, and tie-breaker rule; ask the question "what action will the agent be unable to perform, even if it reduces MTTR?". *Expectation: the answer is inimmutable_principles, not in chat.*
- Transfer to
capstone/constitution.mdtwoimmutable_principles, onemutable_rule, and a shortgovernance_protocol(format — fragment in the chapter's educational scenario); if you ranproposal.md, add tocapstone/README.mdone line with the reason for the rule's appearance. Expectation: an amendment without provenance does not enter the SDD package.
Control Questions
- Which project rules must be immutable, and which must not?
- Why does a mutable rule need
ttland what will happen without it in a year? - What must happen upon Safety veto and why can it not be overridden by two
approves? - After three identical
NodeNotReadys within 48 hours, the referendum trigger fired, but at this moment an active incident is ongoing. What will you do with the amendment — accept, defer, or roll back the trigger?