Skip to content

Commit b5e3a8e

Browse files
committed
docs(architecture): ADR-0007 -- engine/virtue (seven sin/virtue axes, standalone)
Third and final ADR of the triad: heritage / hierarchy / virtue. Standalone from the start -- no file-level imports from heritage or hierarchy; conceptual composition at the persona level only. The triad is now an independence triad: each engine ships on its own base, names its own concepts, is invokable in isolation. ADR-0005 (heritage) and ADR-0006 (hierarchy) have been aligned to the same rule; ADR-0007 ships with it baked in. Decisions locked: 1. Anchor flavour: process-anchor (process_virtue.md, IDLE) Virtue fires; it does not sit. The room reads which pole the persona moved toward, not whether they are "a virtuous person" or "a vicious person" -- the firing is the event. 2. Seven axes, fourteen poles, each pole its own file: Pride / Humility Wrath / Patience Greed / Generosity Gluttony / Temperance Envy / Gratitude Lust / Chastity Sloth / Diligence 3. Pole position files describe how the persona MOVES, not who they ARE. Action and speech signatures of one pole firing in one scene. The persona may produce different pole-firings across scenes; the file describes the firing, not the persona's permanent stance. 4. Behaviour is the evidence; the engine never explains. No pole-position file uses the word naming its own pole in its body. The room reads the firing through the move, not through narrator commentary. 5. Invocation mode: global. Every scene has pressure of some shape; every persona slides on at least one axis when pressure arrives. 6. Standalone. No file imports from heritage or hierarchy. The four capital concepts (if they appear) are named here in this engine's own prose; the formation-vs-current-standing bias lives in scene-authoring, not in any engine file. 7. Scholarly backbone: Aristotle (virtue as active mean) + Baumeister (self-regulation failure, ego depletion) + Haidt (moral intuition first, reason second). VIA Classification (Seligman/Peterson) excluded for trademark reasons; Evagrius Ponticus is historical context only. 8. Sub-engine structure -- 17 files: Anchor (process): 1 IDLE Pole positions: 14 HOLD (one per pole) Meta: 2 (README + REFERENCES) Alternatives considered and rejected (full reasoning in the ADR): - position_virtue.md anchor (virtue fires, doesn't sit) - 7 axis files vs 14 pole files (the latter preserves per-file voice; one file per pole) - VIA Classification as backbone (trademark friction) - Separate process_depletion.md (folds into the anchor's Initiated by + Lever) - Coupling to heritage's capital pieces or hierarchy's positions (violates the standalone rule) - A psychological-explanation layer (violates behaviour-as- evidence) - Per-culture cultural-bias as engine rule (bias is upstream; the engine models the firing) Open follow-ups (sequenced): 1. Engine implementation PR (~17 files, culture/engine) 2. instructions.md registry entry (virtue as global) 3. Per-persona virtue annotation (deferred content sweep) 4. Possible eighth axis or axis split (deferred until scene-authoring evidence accumulates) 5. Optional validator: pole files do not use the word naming their own pole (the behaviour-as-evidence rule as a gate) 6. Composition guides for heritage-virtue and hierarchy-virtue authoring (not engine files; future docs) Files: docs/architecture/adrs/0007-engine-virtue.md NEW docs/architecture/README.md +2 lines (ADR table updated with 0006 + 0007) Refs: #568 (virtue proposal), #571 (heritage), #575 (hierarchy), ADR-0005 (heritage), ADR-0006 (hierarchy), ADR-0004 (engine anchor pattern)
1 parent d7ee5d1 commit b5e3a8e

3 files changed

Lines changed: 377 additions & 1 deletion

File tree

.validation-stamp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f5c20f1a85137c2ee98b65666172b4ebfac3a26a
1+
7803b17721128c802b4ed91661fec04254f0d012

docs/architecture/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ Decision Records under [`adrs/`](adrs/):
213213
| [0003](adrs/0003-multi-variety-language-files.md) | Multi-variety language files and personas | Proposed |
214214
| [0004](adrs/0004-engine-anchor-as-instructions-entry.md) | Engine anchor files as instructions spine | Proposed |
215215
| [0005](adrs/0005-engine-heritage-bourdieu.md) | engine/heritage -- Bourdieu's habitus, capital, and hysteresis | Proposed |
216+
| [0006](adrs/0006-engine-hierarchy-bourdieu.md) | engine/hierarchy -- current rank as capital positions plus structural role | Proposed |
217+
| [0007](adrs/0007-engine-virtue.md) | engine/virtue -- seven sin/virtue axes; pull-and-resist under pressure | Proposed |
216218

217219
ADRs follow the convention `NNNN-kebab-case.md`, numbered in
218220
acceptance order. An accepted ADR is immutable; a new decision that
Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
# ADR-0007: engine/virtue -- seven sin/virtue axes; pull-and-resist under pressure
2+
3+
**Status:** Proposed
4+
**Date:** 2026-05-27
5+
**Author:** KAI HACKS AI (LLM-with-maintainer collaboration)
6+
**Supersedes:** --
7+
**Superseded by:** --
8+
9+
## Context
10+
11+
Issue #568 proposes a new engine domain: virtue. Each of the seven
12+
classical sin/virtue pairs is modelled as a continuous axis. At any
13+
moment in a scene, a persona sits somewhere on each axis. Where they
14+
sit at any moment is a choice -- not a fixed trait. Hard priming
15+
(culture, place, accumulated stress, formation) biases the slide but
16+
never locks it.
17+
18+
The persona is under tension on every axis at all times -- pulled
19+
toward both poles simultaneously. The scene determines which pull
20+
is stronger in this moment. Behaviour is the evidence. The engine
21+
never explains.
22+
23+
Virtue is the third of three interlocking engine ADRs:
24+
25+
- ADR-0005 (heritage, merged) -- what the persona was *formed into*
26+
- ADR-0006 (hierarchy, open) -- what the persona *currently holds*
27+
- ADR-0007 (this ADR) -- what the persona *does under pressure*
28+
29+
The three engines compose conceptually at the persona level. None
30+
of the three depends on the others at the file level: each engine
31+
ships on its own base and is invokable in isolation. The
32+
composition is meaningful (a persona under pressure draws on
33+
formation and current standing in choosing which pole pulls
34+
stronger), but the files do not import each other. Virtue names
35+
its own concepts in its own prose.
36+
37+
## Decision
38+
39+
1. **Add `engine/virtue/` as the tenth domain axis.** Follows
40+
ADR-0004's engine-anchor pattern.
41+
42+
2. **Anchor flavour: process-anchor.** `process_virtue.md` is the
43+
axis's entry, IDLE-shaped (Initiated by / Direction / Lever /
44+
Echo). Virtue *fires*; it does not sit. The room reads which
45+
pole the persona moved toward, not whether the persona was
46+
"a virtuous person" or "a vicious person" -- the engine treats
47+
the firing as the event.
48+
49+
3. **Seven axes, fourteen poles, each pole its own file.** The
50+
seven classical sin/virtue pairings, each pole as one
51+
HOLD-shaped position file describing the observable behaviour
52+
when that pole has just fired.
53+
54+
| Axis | Sin pole | Virtue pole |
55+
|---|---|---|
56+
| Pride | `position_pride.md` | `position_humility.md` |
57+
| Wrath | `position_wrath.md` | `position_patience.md` |
58+
| Greed | `position_greed.md` | `position_generosity.md` |
59+
| Gluttony | `position_gluttony.md` | `position_temperance.md` |
60+
| Envy | `position_envy.md` | `position_gratitude.md` |
61+
| Lust | `position_lust.md` | `position_chastity.md` |
62+
| Sloth | `position_sloth.md` | `position_diligence.md` |
63+
64+
4. **Pole position files describe how the persona *moves*, not
65+
who they *are*.** This is a different framing from the other
66+
engine position files. Where `position_dominant.md` describes
67+
what dominance *is* as a standing read on the persona,
68+
`position_pride.md` describes what the persona *does* when
69+
pride fires. The position file is the action and speech
70+
signature of one pole firing in one scene. The same persona
71+
may produce different pole-firings in different scenes; the
72+
file describes the firing, not the persona's permanent stance.
73+
74+
5. **Behaviour is the evidence; the engine never explains.** No
75+
pole-position file names which pole fired in psychological
76+
terms. The narrator does not say "this is a moment of pride";
77+
the narrator shows what pride looks like as it lands. The
78+
reader infers the firing from the move. This rule is load-
79+
bearing on the engine's purpose -- the engine models how the
80+
room reads the firing, and the room never reads a label.
81+
82+
6. **Invocation mode: global.** Virtue is invoked for every
83+
persona, in every scene where pressure arrives. Per ADR-0004's
84+
`instructions.md` registry:
85+
86+
```
87+
| virtue | engine/virtue/process_virtue.md | global | every persona |
88+
```
89+
90+
7. **Standalone, like heritage and hierarchy.** This engine does
91+
not import from the other two. Concepts that the three engines
92+
share -- pressure, formation, current standing -- are named in
93+
each engine's own prose. A reader extracting `engine/virtue/`
94+
alone from a deployment zip has everything they need to invoke
95+
the engine.
96+
97+
8. **Scholarly backbone:** Aristotle (virtue as the active mean,
98+
not the resting state), Baumeister (self-regulation failure
99+
and ego depletion -- why the sin pole pulls automatically when
100+
resources thin), Haidt (moral positioning as fast intuition
101+
first, slow reason second -- why behaviour-first matters).
102+
The Values-In-Action Classification (Seligman/Peterson) is
103+
deliberately excluded due to trademark constraints; Evagrius
104+
Ponticus is noted as historical context only.
105+
106+
9. **Sub-engine structure -- three classes of file:**
107+
108+
| Class | Count | Schema | Files |
109+
|---|---|---|---|
110+
| Anchor (process) | 1 | IDLE | `process_virtue.md` |
111+
| Pole positions | 14 | HOLD | one file per pole (7 sin + 7 virtue) |
112+
| Meta | 2 | per type | `README.md`, `REFERENCES.md` |
113+
114+
Total: 17 files. Larger than heritage (14) or hierarchy (12),
115+
driven by the seven axes and two poles per axis.
116+
117+
## Architecture
118+
119+
### The anchor
120+
121+
`process_virtue.md` is IDLE-shaped:
122+
123+
- **Initiated by**: pressure arrives in a scene that the persona
124+
has to respond to. The pressure may be a demand, an absence, a
125+
threat, a temptation, a comparison, a delay -- whatever the
126+
scene puts in the persona's way that asks for a move along one
127+
of the seven axes.
128+
- **Direction**: along one or more of the seven axes; toward one
129+
of the two poles per axis. The persona slides toward the sin
130+
pole when the resources for resisting (attention, energy,
131+
practice, formation, capital) have thinned; toward the virtue
132+
pole when they hold. The direction is multi-axis simultaneously:
133+
one scene fires multiple poles, sometimes in opposite-axis
134+
directions.
135+
- **Lever**: the gap between the pull and the practice. The sin
136+
pole is the default when capacity is depleted; the virtue pole
137+
is the active practice that costs something to hold. The lever
138+
is the cost of holding the virtue pole versus the relief of
139+
letting the sin pole take over.
140+
- **Echo**: the room sees the persona's behaviour as the shape of
141+
which pole fired. The narrator does not name the firing; the
142+
reader infers it. The persona may or may not be aware which
143+
pole they just moved toward; their next move starts from where
144+
this one landed.
145+
146+
The anchor enumerates the seven axes and the fourteen poles in
147+
its body with sibling links, per ADR-0004's down-link convention.
148+
149+
### Pole positions
150+
151+
Each of the fourteen pole-position files is HOLD-shaped, but the
152+
content describes the *firing of a pole* rather than a held
153+
position. The schema sections read:
154+
155+
- **Has**: what just activated this pole. The pressure that lands
156+
and pulls the persona here in this scene.
157+
- **Orders**: what the pole demands of the persona's behaviour in
158+
the next beat -- the specific action or speech signature that
159+
is the room's evidence the pole has fired.
160+
- **Loses**: what the persona gives up by moving to this pole in
161+
this scene. (Even the virtue poles cost something; humility
162+
loses the credit one was owed, patience loses the relief of
163+
the response.)
164+
- **Drives**: how the persona handles the pull -- continues into
165+
the pole, or recoils, or resists, or oscillates. The pole's
166+
signature in the next beats.
167+
168+
The room reads the pole-firing through the action and the speech,
169+
not through narrator commentary. Authoring discipline: a pole-
170+
position file that uses the word "pride" (or whichever sin) in
171+
its body has likely slipped into explaining; the engine fails
172+
when the engine names the firing.
173+
174+
### The seven axes in shape
175+
176+
The axes are not symmetric in the cost they impose. Each axis has
177+
its own texture; the pole-position files honour the difference.
178+
179+
| Axis | What the persona is moving between |
180+
|---|---|
181+
| Pride / Humility | The claim of standing the room did not ask for, against the cost of asking for what is needed |
182+
| Wrath / Patience | The fast discharge of frustration, against the slow holding of the room together until the issue resolves |
183+
| Greed / Generosity | The take that protects the persona's own line, against the give that protects the others' |
184+
| Gluttony / Temperance | The reach for more of what soothes, against the stopping at what is enough |
185+
| Envy / Gratitude | The reading of others' having as the persona's own absence, against the reading of one's own portion as enough |
186+
| Lust / Chastity | The reach for the body or the position outside the persona's standing, against the holding of the standing the persona is in |
187+
| Sloth / Diligence | The refusal of the small effort the room needs, against the doing of the next thing required even when the room is not watching |
188+
189+
These descriptions live in `process_virtue.md` and in the README;
190+
each individual pole file goes further into how its specific
191+
firing reads in the room.
192+
193+
### Cross-engine composition (no file imports across the triad)
194+
195+
Virtue composes at the persona level with every other engine in
196+
the codebase, but does not import files from heritage or
197+
hierarchy:
198+
199+
- **`engine/heritage/`** -- conceptually paired. A persona's
200+
formation biases which sin pole is most accessible under
201+
pressure (the family field that rewarded patience produces a
202+
persona more practiced at it; the field that rewarded
203+
acquisition produces a persona more familiar with greed). The
204+
bias lives in the persona's history; this engine does not
205+
encode it as a rule. Virtue's pole files name the firing
206+
abstractly; the persona-level composition with heritage
207+
happens at scene-authoring time.
208+
- **`engine/hierarchy/`** -- conceptually paired. A persona's
209+
current standing biases which pole the room will read first.
210+
The dominant persona's wrath reads as authority; the excluded
211+
persona's wrath reads as insubordination. The pole fires the
212+
same; the room reads it differently. Virtue's files do not
213+
enumerate the reading-shifts; they name the firing.
214+
- **`engine/stress/`** (existing, non-triad) -- adjacent.
215+
Baumeister's depletion is why the sin pole pulls automatically
216+
under stress. The wiring is acknowledged in the README's
217+
cross-engine section; no file links.
218+
- **`engine/gender/`** (existing, non-triad) -- adjacent. The
219+
same pole-firing reads differently by gender position; the
220+
reading-shift is the room's, not the engine's.
221+
- **`engine/group/`**, **`engine/org/`**, **`engine/wow/`**
222+
(existing, non-triad) -- each may host pressures that trigger
223+
the firing; none has files imported here.
224+
225+
### `instructions.md` registry entry
226+
227+
Per ADR-0004 follow-up #1:
228+
229+
```
230+
| virtue | engine/virtue/process_virtue.md | global | every persona |
231+
```
232+
233+
Global because every scene has pressure of some shape, and every
234+
persona slides along at least one axis when pressure arrives.
235+
236+
## Alternatives considered and rejected
237+
238+
- **Position-anchor (`position_virtue.md`).** Considered: anchor
239+
virtue as the *current moral standing* the persona holds.
240+
Rejected: virtue is dynamic in this engine's framing -- it
241+
fires, it does not sit. The IDLE shape matches the firing; the
242+
HOLD shape would force the engine to model a "current virtue
243+
standing" that the issue (#568) explicitly excludes.
244+
245+
- **Seven axis files instead of fourteen pole files.** Considered:
246+
one file per axis, with both poles in subsections. Rejected:
247+
loses the per-file voice that the engine convention requires.
248+
A `position_pride_humility.md` would have to carry two voices
249+
in one document; that contradicts the rule that each file in
250+
its own voice. Fourteen files is the cost.
251+
252+
- **VIA Classification (Seligman/Peterson) as backbone.**
253+
Considered briefly. Rejected: trademark constraints in applied
254+
contexts. The Aristotle + Baumeister + Haidt synthesis covers
255+
the same ground without IP friction.
256+
257+
- **Enumerating depletion-driven pull as a process file.**
258+
Considered: a separate `process_depletion.md` that fires when
259+
the persona's resources thin and the sin pole pulls
260+
automatically. Rejected: the depletion mechanism is part of the
261+
anchor's Initiated by + Lever sections. A separate process
262+
fragments the engine without adding distinction.
263+
264+
- **Coupling virtue files to heritage's piece_*_capital.md or
265+
hierarchy's position_*.md.** Rejected by the standalone rule.
266+
Conceptual composition at the persona level is the model;
267+
file-level imports across the triad are not.
268+
269+
- **A psychological-explanation layer.** Rejected by the
270+
behaviour-as-evidence rule. The engine ships the firing's
271+
shape; psychology is the reader's inference.
272+
273+
- **Numbering the sin/virtue pairs by traditional order
274+
(capital-sins list).** Considered: the historical ordering
275+
(pride first, sloth last) carries weight. Adopted in the ADR
276+
table and the README ordering, since the historical order is
277+
also a reasonable reading order. Not enforced as a runtime
278+
property -- the engine reads any pole at any moment.
279+
280+
- **Per-culture cultural-bias of which pole pulls first.**
281+
Considered: e.g. high-MAS cultures bias toward pride-pull;
282+
high-PDI cultures bias toward humility-pull. Rejected for the
283+
engine layer: the bias lives in the persona's heritage and the
284+
scene's culture, not in the virtue engine's files. The engine
285+
models the firing; the bias is upstream.
286+
287+
## Consequences
288+
289+
**Positive:**
290+
291+
- Cultures gains a model of pressure-response that the existing
292+
engines do not have. Stress (fight / flight / freeze / fawn)
293+
models the body's response; virtue models the *moral-emotional*
294+
response, along seven well-defined axes.
295+
- The triad is complete. Heritage / hierarchy / virtue covers
296+
formation, current standing, and response-under-pressure. Each
297+
ships standalone; the composition at the persona level is the
298+
reading-power.
299+
- The behaviour-as-evidence rule generalises a discipline that
300+
good scene-authoring already practiced informally. The engine
301+
makes the rule explicit and supports authors in keeping the
302+
narrator silent about the firing.
303+
- Cross-engine composition without coupling. Virtue interacts
304+
with every other engine at the persona level (heritage biases
305+
which pole pulls; hierarchy biases which read the room
306+
performs; stress is the depletion mechanism; gender shifts the
307+
reading) without importing any of their files. The engine
308+
graph stays loose where it should be loose.
309+
310+
**Negative:**
311+
312+
- Authorial load. Fourteen pole-position files, each in its own
313+
voice, with the no-explaining discipline. Higher per-file
314+
authorial care than any preceding engine. The risk of slipping
315+
into "this is the moment of envy" prose is real and only
316+
authorial care catches it.
317+
- The behaviour-as-evidence discipline is unenforceable by
318+
validator. A pole-position file that names its own pole
319+
inside its body fails the rule; no test catches that. Review
320+
is the gate.
321+
- Seven axes is a strong claim about the dimensionality of
322+
moral-emotional response. Some sin/virtue pairings are more
323+
contested than others (lust/chastity has wider cultural
324+
variance than pride/humility, for example). The engine ships
325+
the seven; future ADRs may add additional axes or split an
326+
axis if scene-authoring evidence accumulates.
327+
- The triad-independence rule means the persona-level
328+
composition (heritage formation biases virtue's pulls,
329+
hierarchy standing biases the room's reading) lives in scene-
330+
authoring practice, not in any engine file. The composition
331+
must be carried by the authors; the files do not enforce it.
332+
333+
## Open follow-ups
334+
335+
1. **Engine implementation PR.** `culture/engine` branch into
336+
`culture/release`, the ~17 files described above. Standalone:
337+
does not block on heritage or hierarchy being on any specific
338+
branch. The engine implementation PR ships independently.
339+
340+
2. **`instructions.md` registry entry.** Add the virtue row
341+
alongside heritage's and hierarchy's. Folds into the in-
342+
progress `instructions.md` work or a tiny follow-up PR.
343+
344+
3. **Per-persona virtue annotation.** Not in scope for the
345+
engine itself. The 28 existing personas do not declare which
346+
poles fire most accessibly for them under pressure. A future
347+
content sweep can backfill if scene-authoring needs it; the
348+
engine ships without per-persona declarations.
349+
350+
4. **An eighth axis or a split of an existing axis.** Deferred
351+
until scene-authoring accumulates evidence that the seven do
352+
not cover the response space. Examples of candidates:
353+
shame/dignity (related to but not the same as pride/humility),
354+
despair/hope (related to but not the same as sloth/diligence),
355+
fear/courage (not currently modelled). Out of scope for this
356+
ADR; recorded here so they are not silently lost.
357+
358+
5. **Validator for virtue shape.** Optional governance after the
359+
engine lands and is used in practice: a test that walks pole-
360+
position files and asserts no file uses the word naming its
361+
own pole in its body. The behaviour-as-evidence rule
362+
formalised as a gate. Promotable to hard after some authoring
363+
experience confirms the rule is workable.
364+
365+
6. **Heritage-virtue and hierarchy-virtue composition guides.**
366+
Not engine files; authoring documentation for how a persona's
367+
heritage biases which sin pole pulls, and how a persona's
368+
current hierarchy position shifts the room's reading of the
369+
pole-firing. Belongs in `docs/` or in a future authoring
370+
guide; out of scope for this engine ADR.
371+
372+
---
373+
374+
*ADR-0007 -- v0.1.0 -- KAI Worlds*

0 commit comments

Comments
 (0)