diff --git a/canon/definitions/software-virtues-vocabulary.md b/canon/definitions/software-virtues-vocabulary.md new file mode 100644 index 0000000..ad8a4af --- /dev/null +++ b/canon/definitions/software-virtues-vocabulary.md @@ -0,0 +1,132 @@ +--- +uri: klappy://canon/definitions/software-virtues-vocabulary +title: "Software Virtues Vocabulary — Ten Quality Attributes That Compete for Priority" +audience: canon +exposure: nav +tier: 2 +voice: neutral +stability: stable +tags: ["canon", "definitions", "software-virtues", "quality-attributes", "ilities", "prioritization", "tradeoffs"] +epoch: E0008.4 +date: 2026-05-10 +derives_from: "https://medium.com/@klappy/what-are-software-virtues-and-how-to-prioritize-them-f0b583741afe (2018-09-09 — origin article)" +complements: "canon/principles/quality-attributes-are-in-tension.md, canon/observations/quality-attribute-tension-matrix.md, odd/maturity.md" +governs: "Vocabulary used across canon when discussing tradeoffs between competing software properties. 'Virtues' is the rhetorical/historical name; 'quality attributes' or 'ilities' is the operational synonym. Both are first-class." +status: active +--- + +# Software Virtues Vocabulary — Ten Quality Attributes That Compete for Priority + +> Ten properties every software project optimizes for, in tension with each other: usability, originality, stability, urgency, efficiency, maintainability, versatility, interoperability, affordability, and reality. Each is a virtue (a thing worth pursuing) and a quality attribute (an "-ility" the engineering literature already names). Each stands in tension with others. Priority among them shifts by team, by project, and by lifecycle phase. The vocabulary is from a 2018 article that has stayed load-bearing for nearly a decade; this entry canonizes it for ODD. The ten are a canonical worked example, not an exhaustive set — the universe of quality attributes is far larger, and the principle holds across all of it. + +--- + +## Summary — A Stable Naming for the Tradeoff Space + +Software has no single objective function. Every project optimizes for a bundle of competing properties, and every choice that advances one property tends to retreat from at least one other. The engineering literature names many of these properties — usually with the suffix "-ility" — and treats them as orthogonal axes. The 2018 source article reframed them as **virtues**: things worth pursuing, with intrinsic moral weight, that nevertheless conflict. + +This document defines the ten virtues that have proven generative across nearly a decade of use. The name "virtue" is preserved because the moral framing is load-bearing — these are not just metrics, they are values a team holds. The phrase "quality attribute" (or "-ility") is the operational synonym that integrates with industry vocabulary and ODD's existing language. Both names refer to the same set; canon documents may use either depending on register. + +The tensions among these virtues — which optimize against which, and under what conditions — are mapped at `canon/observations/quality-attribute-tension-matrix.md`. The principle that the tensions are real and irreducible is at `canon/principles/quality-attributes-are-in-tension.md`. The phase-by-phase shift in which virtues take priority is grounded in `odd/maturity.md`. + +--- + +## The Ten Virtues + +Each virtue is named with its primary form first, followed by its companion synonym in the original article. The definition states what the virtue measures or rewards; the operational note states how it is observed in practice. + +### 1. Usability / Simplicity + +**Definition.** The degree to which the user can accomplish their intended task without unnecessary friction, training, or guesswork. Includes learnability (how quickly a new user becomes effective) and intuitiveness (how much the interface aligns with prior expectations). + +**Operational note.** Observed through user testing, time-to-task, error rates, and the volume of support requests asking how to do basic things. A product whose documentation is required to use it is failing on usability before the manual is opened. + +### 2. Originality / Innovation + +**Definition.** The degree to which the project does something not already done — a new approach, a new combination, a new affordance. Differentiation from existing alternatives; intrinsic novel value. + +**Operational note.** Observed through the question "what would have to be true elsewhere for this to be unnecessary?" If the honest answer is "nothing — there are five products that already do this," the project is not original. + +### 3. Stability / Reliability + +**Definition.** Two related properties often treated as one: stability (the system does not freeze, crash, or corrupt state) and reliability (when something goes wrong, the system recovers without losing the user's work). Either may dominate depending on the use case. + +**Operational note.** Observed through error rates, mean time between failures, recovery times, and the question "if a user trusts this with their work, will the trust be repaid?" + +### 4. Urgency / Timeliness + +**Definition.** The degree to which the project ships in time to serve its purpose. Urgency is not speed for its own sake; it is the temporal fit between the delivery and the window in which delivery still matters. Late software solving a no-longer-urgent problem has failed on this virtue. + +**Operational note.** Observed through schedule fit, market timing, and the question "if we ship six months from now, do users still need this?" + +### 5. Efficiency / Scalability + +**Definition.** The degree to which the system performs its work without wasted resources — CPU, memory, hardware, latency, energy, dollars. Scalability is the time-shape of efficiency: does the system stay efficient as load grows? + +**Operational note.** Observed through profiling, cost-per-request, throughput under load, and the question "what does it cost to serve the next user, and is that cost sustainable?" + +### 6. Maintainability / Manageability + +**Definition.** The degree to which the project can be continued by people who did not write it. Includes understandability (how readable the code is to a new contributor), modularity (whether parts can be changed independently), testability (whether changes can be verified before shipping), and hire-ability (whether the technologies and patterns chosen permit finding qualified maintainers). + +**Operational note.** Observed through onboarding time for new contributors, the rate at which untouched code becomes feared code, and the question "if the original team disappeared tomorrow, could the project continue?" + +### 7. Versatility / Adaptability + +**Definition.** The breadth of use cases the project can serve without modification. The degree to which the project handles related tasks beyond its primary one. The opposite of single-purpose narrowness. + +**Operational note.** Observed through the variety of users finding value in the project and the rate at which feature requests are answered with "actually, you can already do that." Watch for the failure mode: versatility chased prematurely produces software that does many things badly instead of one thing well. + +### 8. Interoperability + +**Definition.** The degree to which the project can exchange data and behavior with adjacent systems. Includes import/export of data formats, adherence to standards, API surface area, and the absence of artificial lock-in. + +**Operational note.** Observed through the friction a user experiences when bringing data in or taking data out, and the question "does this project make the user's larger workflow easier or harder?" + +### 9. Affordability / Sustainability + +**Definition.** Two coupled properties: affordability (the price the user pays is appropriate to the value received) and sustainability (the cost of building and operating the project is sustainable for the team that produces it). The intersection is whether the project's economic model survives contact with reality. + +**Operational note.** Observed through unit economics, retention, runway, and the question "can the team that built this afford to keep building it?" Affordability has cost gravity over every other virtue: each virtue is purchased with effort or money. + +### 10. Reality + +**Definition.** The meta-virtue that grounds all other virtues against the world as it is, rather than the world as planned. Reality includes: + +- **Costs** — effort and resources actually required +- **Benefits** — advantages of success, weighted by probability +- **Risks** — probability of failure and its consequences +- **Dependencies** — what must be true for this to work +- **Penalties** — consequences of not delivering +- **Compliance** — regulatory and contractual constraints + +**Operational note.** Observed through the gap between stated plans and observed outcomes. Reality is the virtue that keeps the other nine honest. When teams optimize for usability without testing with real users, for originality without checking what already exists, or for urgency without checking what users actually need, reality has been demoted below where it belongs. + +--- + +## "Virtues" and "Quality Attributes" Are the Same Set + +The 2018 source article called these virtues. The engineering literature calls them quality attributes, non-functional requirements, or "-ilities" (a suffix that fits most of them awkwardly). Both vocabularies refer to the same ten properties. + +Canon uses both names depending on register: + +- **Virtue** — moral, rhetorical, used when emphasizing that these are values a team chooses to pursue +- **Quality attribute / "-ility"** — operational, technical, used when integrating with industry frameworks (ISO/IEC 25010, ATAM, etc.) or when discussing measurement and tradeoff analysis + +Neither vocabulary is preferred. A canon document discussing prioritization may use "virtues" for the framing and "quality attributes" for the worked detail without contradiction. + +--- + +## What This Document Does Not Define + +Three things deliberately left to other canon documents: + +- **Which virtues take priority when** — see `odd/maturity.md` for phase-weighting and `canon/observations/quality-attribute-tension-matrix.md` for pair-by-pair detail across the canonical ten. +- **How to elicit team priorities** — the 2018 article suggested MoSCoW voting and the Hundred Dollar Method. Both are surfaced as starting points, not endorsed as load-bearing. ODD's mature answer to elicitation lives elsewhere. +- **The full universe of quality attributes** — there are dozens more. Auditability, securability, debugability, deployability, recoverability, observability, portability, accessibility, localizability, and many others are real. The ten here are the canonical worked example used as a reference corpus; the principle at `canon/principles/quality-attributes-are-in-tension.md` holds across the broader set, and project-specific tension graphs are generated against the principle rather than restricted to this list. + +--- + +## Lineage + +The vocabulary is from "Software Virtues — How to Prioritize" by Chris Klapp, published on Medium in September 2018. The article seeded `odd/maturity.md` (phase-weighting) and is now the source of this definition. The companion canon — the in-tension principle and the worked-example tension matrix — completes the systematic build the original article only sketched. diff --git a/canon/methods/quality-attribute-tension-survey.md b/canon/methods/quality-attribute-tension-survey.md new file mode 100644 index 0000000..f1eb9cc --- /dev/null +++ b/canon/methods/quality-attribute-tension-survey.md @@ -0,0 +1,422 @@ +--- +uri: klappy://canon/methods/quality-attribute-tension-survey +title: "Quality Attribute Tension Survey — Pick Ilities, Surface Tensions, Encode Constraints, Inherit" +audience: canon +exposure: nav +tier: 2 +voice: neutral +stability: semi_stable +tags: ["canon", "methods", "quality-attributes", "software-virtues", "tradeoffs", "tensions", "constraints", "elicitation", "survey", "agent-work", "scope-setting"] +epoch: E0008.4 +date: 2026-05-10 +derives_from: "canon/principles/quality-attributes-are-in-tension.md, canon/observations/quality-attribute-tension-matrix.md, canon/observations/observability-tension-extension.md, canon/definitions/software-virtues-vocabulary.md, odd/maturity.md, canon/values/axioms.md, https://medium.com/@klappy/what-are-software-virtues-and-how-to-prioritize-them-f0b583741afe, https://medium.com/@klappy/lean-expectations-poc-prototype-mvp-140749383fd4" +complements: "canon/methods/borrow-bend-break-beget-build.md, odd/encoding-types/constraint.md, odd/encoding-types/observation.md, canon/constraints/borrow-evaluation-before-implementation.md" +governs: "How a project's quality-attribute priorities are surfaced, ranked, sacrificed-against, and encoded as constraints the agents working on the project inherit. Runnable in a single planning turn by an agent or a human operator. Re-runnable at phase transitions. Outputs are typed DOLCHEO Constraints, not free prose." +status: active +--- + +# Quality Attribute Tension Survey — Pick Ilities, Surface Tensions, Encode Constraints, Inherit + +> A seven-phase method for surfacing a project's quality-attribute priorities at scope-setting time. Pick the ilities that matter for this project. Rank them at the project's current phase. Consult the tension matrix (or generate dynamically for ilities outside the canonical ten) to surface predicted sacrifices. Acknowledge each sacrifice explicitly. Encode the result as DOLCHEO Constraints the agents inherit. Re-run at phase transitions. The method is the operational layer that turns the static principle into a per-project artifact — a constraints survey, not a reference table. + +--- + +## Summary — From Principle to Per-Project Artifact + +The principle at `canon/principles/quality-attributes-are-in-tension.md` asserts that quality attributes are structurally in tension. The matrix at `canon/observations/quality-attribute-tension-matrix.md` shows what that looks like for the canonical ten. Neither doc tells a project team — or an agent starting a task — what to actually do with that knowledge at scope-setting time. This method does. + +The method runs in seven phases, each phase producing one artifact for the next phase to consume. It can be run by a human operator scoping a project, by a single agent at the start of a task, or by a team in a planning session. The output is a small typed artifact — a list of ranked ilities, a list of accepted sacrifices, and a set of DOLCHEO Constraints — that the agents working on the project inherit. + +The method's spirit is borrowed from a prior elicitation loop in the `agent-skill` PRD-guide pack (now archived; see borrow evaluation below). The loop's *philosophy* — agent-as-elicitor not agent-as-author, stage typing before questioning, explicit ambiguity capture — proved durable. The loop's *implementation* (lanes, pack compilation, Cloudflare Pages distribution, no update propagation to downstream consumers) proved brittle. This method takes the philosophy and rebuilds the apparatus on canon-and-tools instead of compiled-pack-distribution. Same questions, durable substrate. + +The method's economic argument: the operator's attention is the system bottleneck. A constraints survey that runs in one planning turn and produces a typed artifact saves hours of mid-execution debate about which virtue is being prioritized. The cost is one ten-minute survey at scope-setting time. The savings are paid in every downstream decision the agent makes without needing to re-ask. + +--- + +## Runtime Contract — How oddkit Governs the Survey + +> The seven phases each have a governance handle on the oddkit MCP server, and the boundary between phases is a gate rather than a transition by convention. Five oddkit actions wire the method to existing canon machinery: `oddkit_preflight` opens the survey, `oddkit_gate` enforces every phase boundary, `oddkit_challenge` pressure-tests sacrifices in Phase 4, `oddkit_encode` produces Phase 5's typed output, and `oddkit_validate` closes the survey. The contract mechanizes canon. It adds none. + +The section follows the per-dimension contract pattern from `klappy://canon/methods/spawned-agent-session-runtime-contract` (same-day canon, 2026-05-10). That doc maps the five canonical epistemic modes to runtime configurations; this section maps the survey's seven phases to oddkit actions. Both treat the runtime as a mechanizer of existing rules rather than a source of new ones. + +### The governance handles + +| Action | What it guarantees | Where it fires | Failure response | +|---|---|---|---| +| `oddkit_preflight` | Loads canon prerequisites (principle, matrix, vocabulary, maturity prior) plus the survey's definition of done | Once, before Phase 0 opens | `NO_CANON_FOUND`: name the missing canon, either fix it or run the survey with the gap explicitly recorded | +| `oddkit_gate` | Confirms the preceding phase's output is present and well-formed before the next phase opens | Six gates: 0→1, 1→2, 2→3, 3→4, 4→5, 5→6 | `NEEDS_PREREQ`: stay in the current phase. Placeholders are not acceptable substitutes | +| `oddkit_challenge` | Pressure-tests each predicted sacrifice against canon constraints and the matrix's recorded relationship types | Inside Phase 4, once per sacrifice | `CHALLENGE_FOUND`: revert to Phase 2 with the failing sacrifice's tension as the named cause | +| `oddkit_encode` | Produces typed DOLCHEO artifacts (Constraints, Observations, Opens) from Phase 4's accepted outputs | Inside Phase 5, after Phase 4 closes | Encode does not persist (per `klappy://canon/definitions/dolcheo-vocabulary`); the caller saves the output explicitly | +| `oddkit_validate` | Verifies all seven Output Format artifacts exist before the survey is declared complete | Once, after Phase 6 closes | `NEEDS_ARTIFACTS`: keep the survey open; do not claim completion | + +### Session discipline + +A survey run is a **planning-mode** artifact per `klappy://canon/epistemic-modes`. The seven phases live within a single planning-mode session. Per `klappy://canon/principles/sessions-mirror-modes`, planning hands off to execution through the Constraint set saved at the end of Phase 5; the survey itself does not need to be re-entered for downstream work to consume it. + +Phase 4 reversion to Phase 2 stays inside planning. The prior ranking is what the reversion pressure-tests; the next ranking is the new output. Per `klappy://canon/constraints/mode-discipline-and-bottleneck-respect`, this is reversion-as-designed; the method anticipates the loop. A reversion *out of the survey itself* — back into planning at the project level — happens when an unsurfaced tension forces the project's scope to be renamed rather than its ilities re-ranked. The runtime detects this case when `oddkit_gate` at the Phase 2 → 3 boundary cannot validate the ility set against the freshly renamed scope. + +### What the contract does not promise + +The wiring is mechanical at the phase-boundary level. Content-level drift inside a phase — a fabricated ility, a mislabeled tension relationship, an unjustifiable sacrifice that survives the challenge — can still pass each gate's prerequisite check. Phase 4's `oddkit_challenge` is the deepest content-level pressure this contract guarantees. Everything finer (peer review, downstream validation against produced artifacts, operator inspection) lives outside the contract. + +**Retraction condition.** If the gates fire false-positives (blocking on prerequisites that exist in non-standard formats) or false-negatives (passing outputs downstream agents cannot consume), this section retracts and the wiring is rewritten with the failure mode as the new design constraint. + +--- + +## When to Run the Survey + +The survey is the right move at four entry points: + +1. **Project scope-setting** — at the start of a new project, feature, or substantive sub-project, before the first artifact is produced. +2. **Phase transition** — when the project moves between maturity levels (PoC → Pilot → Production, per `odd/maturity.md`). The ranking that was correct at PoC is rarely correct at Production. +3. **Significant scope change** — when a project's scope expands or contracts enough that the previously-named ilities no longer cover the new shape. +4. **Tension surprise** — when a failure mode reveals a tension the original survey did not surface. The survey re-runs with the new tension named. + +The survey is **not** the right move for routine tasks within an already-scoped project. Once the constraints are encoded, they govern. The survey is run rarely and re-run only when something material changes. + +--- + +## The Seven Phases + +Each phase has an entry condition, a question, an output artifact, and a transition rule to the next phase. The phases are sequential; an agent or operator running the method works through them in order and stops if a reversion is required. + +### Phase 0 — Stage Identification + +**Entry.** Project description in any form (a paragraph, a ticket, a conversation transcript). Current working state. + +**Question.** What stage is this project at, and what does the stage imply about evidence expectations and ambiguity tolerance? + +**Output.** One classification: PoC / Pilot / Production / Refactor / Other (with explicit name). + +**Transition.** If the stage cannot be classified within the listed types, the method reverts to planning and the operator names the missing stage. Continuing without a stage is not allowed; every other phase depends on it. + +**Governance.** `oddkit_preflight` is called once at survey entry, just before Phase 0 opens, to load canon prerequisites and the survey's definition of done. Phase 0 has no internal oddkit handle; stage classification is a single observation. Transition to Phase 1 fires `oddkit_gate` against the existence and validity of the stage classification. + +### Phase 1 — Ility Selection + +**Entry.** Stage from Phase 0. + +**Question (dual-state).** Which quality attributes does this project optimize for **today**, and which should it optimize for **going forward**? The two lists are usually close but not identical; the survey asks for both in one pass. + +**Output.** A pair of lists with explicit removals. The canonical ten from `canon/definitions/software-virtues-vocabulary.md` are the starting set; additions come from the broader universe (observability has its own extension at `canon/observations/observability-tension-extension.md`; auditability, securability, accessibility, portability, etc., may apply). Each ility is tagged with a current-state inclusion flag and a desired-state inclusion flag. Removals are listed explicitly for each state: "this project does not optimize for X today because Y" and "this project will not optimize for X going forward because Z." Differences between the lists are the *scope-shift* component of the roadmap. + +**Transition.** When both lists are stable — every retained ility has a reason in both states, every removed ility has a reason in the state where it was removed. Aim for between four and twelve ilities in either list. Fewer than four usually means the project is too narrowly framed; more than twelve usually means the survey will not converge. + +**Governance.** Entry is gated by `oddkit_gate` against Phase 0's stage classification. Inside the phase, `oddkit_search` is the supported method for discovering ilities outside the canonical ten; observability, auditability, accessibility, and similar extensions are sourced from canon rather than improvised. Transition to Phase 2 fires `oddkit_gate` against the dual-state ility set's completeness: every retained ility has a reason in both states, every removed ility has a reason in the state where it was removed. + +### Phase 2 — Phase-Weighted Ranking + +**Entry.** Selected ilities (current + desired) from Phase 1, stage from Phase 0. + +**Question (dual-state).** For each selected ility, what level is the project at **today** (1–4 MoSCoW), and what level **should it be** going forward? Answer both for each ility in the same pass. + +**Output.** A pair-of-ranks per ility: `(current, desired)`. MoSCoW scale — 1 (Won't), 2 (Could), 3 (Should), 4 (Must). The ranking is project-and-stage-specific; do not reuse a ranking from another project. Where current equals desired, the project is on-target on that axis. Where they differ, the gap *is* the roadmap item for that axis (Phase 5 will encode it). + +**Transition.** The phase-weighting prior at `odd/maturity.md` gives the default shape for the *desired* column (PoC tolerates more originality and less stability; Production demands more stability and tighter affordability; etc.). The *current* column comes from observation — code investments, telemetry, contributor surveys, spec compliance, lived experience of the team. Both columns may override the prior, but every override should be named. If the override list is longer than three items in either column, the project is doing something genuinely unusual and the operator should pause. + +**Governance.** Entry is gated by `oddkit_gate` against Phase 1's ility sets. Inside the phase, `oddkit_get` retrieves the maturity-stage prior at `klappy://odd/maturity` for the desired column's default; the current column comes from observation, not from canon. Transition to Phase 3 fires `oddkit_gate` against rank-pair completeness: every selected ility has both a current and a desired rank, every override against the prior is named. + +### Phase 3 — Tension Surfacing + +**Entry.** Dual-state ranked list (current + desired) from Phase 2. + +**Question (dual-state).** What tensions does the **desired** ranking expose? What tensions is the **current** ranking already exposing? Where the two differ, which tensions are being added, removed, or intensified by the planned shift? + +**Output.** Two tension sets — desired-state tensions (what the project is *committing to* live with) and current-state tensions (what the project is *already* living with) — plus a delta noting any tensions that change between them. For ility pairs within the canonical ten, consult `canon/observations/quality-attribute-tension-matrix.md` directly. For pairs that include observability, consult `canon/observations/observability-tension-extension.md`. For pairs outside the canonical ten and the worked extensions, generate the tension graph dynamically against the principle at `canon/principles/quality-attributes-are-in-tension.md`. The dynamic-generation step is described in the next subsection. + +**Transition.** When every tension involving a top-three-ranked ility (in either state) has been named with a relationship type (mutual / asymmetric / synergy / cost gravity), a phase tag, and a one-sentence operating dynamic, this phase is complete. The remaining tensions — those involving lower-ranked ilities — are surfaced as background but not analyzed in detail. + +**Governance.** Entry is gated by `oddkit_gate` against Phase 2's dual-state rankings. Inside the phase, `oddkit_get` retrieves the tension matrix (`klappy://canon/observations/quality-attribute-tension-matrix`) and the observability extension (`klappy://canon/observations/observability-tension-extension`) for canonical pairs; `oddkit_search` against the principle is the supported method for the dynamic-generation step covering non-canonical pairs (procedure in the subsection below). Transition to Phase 4 fires `oddkit_gate` against tension-set completeness: every tension involving a top-three-ranked ility (in either state) has been named with a relationship type, a phase tag, and a one-sentence operating dynamic. + +#### Dynamic Generation for Ilities Outside the Canonical Ten + +When the survey includes ilities not covered by the canonical ten or the existing extensions, the method generates the tension graph by applying the principle to each new pair. The procedure: + +1. **Define the new ility tightly.** What does it measure? What is observed when it is achieved? +2. **For each pair (new ility ↔ existing ility):** ask which is achieved by methods that erode the other. The principle's "Pairs Are Predictable" section is the rule book. +3. **Tag the relationship type:** mutual tension when both erode each other along symmetric axes; asymmetric grounding when one virtue disciplines the other without symmetric retaliation; synergy when both reinforce; cost gravity for affordability's relationship. +4. **Tag the phase weighting:** when does this tension bite hardest — PoC, Pilot, or Production? +5. **Cite evidence.** If ODD canon already discusses the new ility (case studies, epoch docs, prior writings), cite the source for each tension claim. The observability extension is the worked example of evidence-grounded generation. +6. **Surface the result for review** before treating it as authoritative. Dynamic-generation output is a hypothesis until the operator or downstream evidence corroborates it. + +Future tooling (a potential `oddkit tensions(...)` action) will codify steps 1–4 as a tool call. Until then, the procedure is run by hand or by an agent reading this section. + +### Phase 4 — Sacrifice Acknowledgment + +**Entry.** Tension list from Phase 3 (both states), dual-state ranking from Phase 2. + +**Question (dual-state).** Are the sacrifices the project is **currently** making acceptable? Are the sacrifices the **desired** ranking will require acceptable? Where they differ, name the shift explicitly. + +**Output.** Each predicted sacrifice tagged accept or reject for both states. Accepts proceed. Rejects trigger reversion to Phase 2 — the ranking that produced an unacceptable sacrifice is itself the problem, not the tension. The dual-state view often surfaces an asymmetry the single-state view misses: the project may be living with a sacrifice today that the team rejects as a future commitment, in which case the shift itself is a roadmap item — not just a re-ranking. + +**Transition.** This phase commonly produces one or two reversions. That is healthy. A survey that runs straight through Phase 4 without any reversion is suspicious; either the rankings were trivially obvious or the survey is rubber-stamping rather than surveying. + +**Governance.** Entry is gated by `oddkit_gate` against Phase 3's tension sets. **Inside the phase, `oddkit_challenge` pressure-tests each predicted sacrifice** against canon constraints and the matrix's recorded relationship types. A `CHALLENGE_FOUND` response on any sacrifice triggers reversion to Phase 2 with the failing sacrifice's tension as the named cause; the prior ranking is the problem, not the sacrifice. Transition to Phase 5 fires `oddkit_gate` only after every sacrifice carries an `accept` or `reject` disposition for both states. + +### Phase 5 — Output Encoding + +**Entry.** Accepted dual-state ranking from Phase 2, accepted sacrifices from Phase 4. + +**Question.** What artifacts does this survey produce that the agent working on the project must inherit, and how is the gap between current and desired encoded as roadmap? + +**Output.** Three DOLCHEO artifact types fall out of one survey pass — see `canon/definitions/dolcheo-vocabulary`: + +- **Constraints (C)** encode the **desired state** — these are what the agent inherits. Each one of: + - **Priority constraint** — "This project prioritizes [ility] at level [N] above [list of lower-ranked ilities]." + - **Sacrifice constraint** — "This project accepts [ility]'s erosion of [other ility] because [reason]." + - **Ility-set constraint** — "This project optimizes for these ilities and explicitly does not optimize for [removed ilities]." + - **Phase constraint** — "This project is at [stage]; constraints will be re-surveyed at the next phase transition." +- **Observations (O)** encode the **current state** — one per ility, recording the observed level as evidence rather than aspiration. "Observed: Stability at level [N] today, based on [source — telemetry, code review, contributor survey, lived experience]." +- **Opens (O-open)** encode the **gaps** — one per ility where current ≠ desired, ranked by gap magnitude. Each Open is a roadmap item: "Stability: current [N], desired [M], gap +[k] — close by [direction of investment]." Where current > desired, the Open names a *disinvestment* opportunity. + +All three sets are saved to the project's session, ledger, or whichever persistence layer the project uses. Constraints become the answer the agent gives whenever it is uncertain about which virtue to prioritize. Observations are the falsifiable baseline against which future surveys measure drift. Opens are the prioritized roadmap. + +**Transition.** When every desired-state decision has produced at least one Constraint, every selected ility has at least one Observation recording its current level, every non-zero gap has produced one Open, and all three sets are saved (encoded artifacts do not persist on their own — see `klappy://canon/definitions/dolcheo-vocabulary`), the survey is complete. + +**Governance.** Entry is gated by `oddkit_gate` against Phase 4's accepted sacrifices. **Inside the phase, `oddkit_encode` produces the three DOLCHEO artifact sets** (Constraints, Observations, Opens). Per `klappy://canon/definitions/dolcheo-vocabulary`, encode does not persist; the caller must save the encoded output to the project's session, ledger, or comparable persistence layer before Phase 6 opens. Transition to Phase 6 fires `oddkit_gate` against the persistence step's completion, not just the encode call's success. + +### Phase 6 — Re-Run Triggers + +**Entry.** Saved Constraint set, Observation set, and Open (gap/roadmap) set from Phase 5. + +**Question.** Under what conditions does the survey re-run, and what happens to the existing artifacts when it does? + +**Output.** A short list of explicit re-run triggers, with handling rules. Standard triggers: + +- **Phase transition** — the survey re-runs from Phase 0; the prior Constraints and Observations are archived as historical record; the prior Opens are evaluated for closure (did the roadmap items get done?) before being archived. The re-survey produces fresh artifact sets. +- **Scope change beyond a named threshold** — operator-defined; e.g., "if the user base or the use case fundamentally shifts, re-survey." +- **Tension surprise** — a failure mode reveals an unsurfaced tension; the survey re-runs from Phase 3 with the new tension added. +- **Stakeholder change** — if the team's composition shifts in a way that changes the priorities (a new product owner, a new technical partner with veto power), re-survey. +- **Drift detection** — if observed behavior (telemetry, code investments, contributor surveys) shows the current state has drifted measurably from the prior Observation set, re-survey Phases 1–2 minimum. + +**Transition.** This phase produces a short paragraph attached to the artifact set, describing the trigger conditions. The paragraph is itself a Constraint that the agent inherits. + +**Governance.** Entry is gated by `oddkit_gate` against Phase 5's saved DOLCHEO artifact set. Inside the phase, `oddkit_encode` produces the re-run-trigger paragraph as itself a Constraint (saved alongside the Phase 5 set). **Survey completion fires `oddkit_validate`** against the seven Output Format artifacts (Stage, Ility set, Rankings, Tension list, Accepted sacrifices, Constraint set, Re-run triggers). A `NEEDS_ARTIFACTS` response keeps the survey open; a `VERIFIED` response closes it. + +--- + +## Output Format — What the Survey Produces + +A complete survey run produces seven named outputs, all small enough to fit in one operator-readable artifact: + +1. **Stage** — single classification from Phase 0 +2. **Ility set (current + desired)** — paired lists from Phase 1 with rationale for removals in either column +3. **Rankings (current + desired)** — per-ility (current, desired) tuples from Phase 2 on the MoSCoW scale +4. **Tension list** — top tensions from Phase 3, with deltas where current and desired diverge +5. **Accepted sacrifices (current + desired)** — list from Phase 4 with one-sentence justification each +6. **Constraint set** — DOLCHEO Constraints from Phase 5 (encoding the desired state) plus Observations (current state) and Opens (gaps as roadmap) +7. **Re-run triggers** — short paragraph from Phase 6 + +The whole artifact is typically under 600 words. Surveys longer than that are usually the result of skipping Phase 1's removal step (too many ilities in play) or skipping Phase 2's prior (re-deriving the ranking from scratch instead of starting from `odd/maturity`). + +--- + +## The Survey Is a Personality Test for the Product + +The cleanest way to think about the survey output is not as a list of constraints but as a personality profile. The same shape humans use to map traits onto a person — a radar chart with one axis per trait — maps naturally onto a project. Each ility is a trait; the project's ranking on each ility is its score; the polygon connecting the scores is the project's *shape*. Two products can have similar functions and entirely different personalities, and that personality difference is the most important thing a stakeholder, a reviewer, or an inheriting agent needs to know about the project up front. + +This framing earns the radar chart for free. It is also the framing that lets the survey reach audiences who would never read a method doc — "what's your product's personality?" is a question that gets answered; "have you completed your quality-attribute tension survey?" is a question that gets ignored. + +### Format — Tension-Opposite Ordering, MoSCoW Scale, Two Polygons, Sortable + +The default radar has one axis per ility in the project's selected set, ordered such that **ilities in strong mutual tension sit across from each other on the chart**, and ilities that reinforce each other sit adjacent. The visual benefit is structural: a spike on one axis with a valley directly across it shows the polygon *leaning* toward what the project prioritizes against what it sacrifices. Adjacent synergistic ilities form smooth contours — the polygon's "natural gravity" toward coherent clusters. Tension-adjacent ordering (the earlier draft) buried both effects in local jaggedness. + +The default tension-opposite ordering for the canonical ten, clockwise from top: + +| Position | Right half (synergy chain) | Across from | Left half (tension cluster) | +|:---:|---|---|---| +| 0 (top) | Stability | ↔ (5, bottom) | Urgency | +| 1 | Maintainability | ↔ (6) | Versatility | +| 2 | Reality | ↔ (7) | Originality | +| 3 | Affordability | ↔ (8) | Usability | +| 4 | Efficiency | ↔ (9) | Interoperability | + +The right half (axes 0–4) forms a synergy chain: every adjacent pair on the right is synergistic per the matrix (Stability ↔ Maintainability, Maintainability ↔ Reality, Reality ↔ Affordability, Affordability ↔ Efficiency). Each axis is *also* mutually tense with the axis 180° across it — the article-named pair Stability/Urgency leads, then Maintainability/Versatility, Reality/Originality, Affordability/Usability, Efficiency/Interoperability. The polygon's silhouette becomes the tradeoff record by construction. + +Extensions slot in adjacent to whichever canonical ility they have the strongest *synergy* with, and (if possible) opposite their strongest *tension*. Observability sits adjacent to Stability (its strongest S) and benefits from being across the urgency-leaning portion of the chart. Auditability sits adjacent to Reality (its grounding ility). Accessibility sits adjacent to Usability. The general rule: synergy adjacent, tension opposite. + +The scale is **MoSCoW** — 1 (Won't), 2 (Could), 3 (Should), 4 (Must) — matching the elicitation method the 2018 source article surfaced and the categorical level at which Phase 2 produces its rankings. Quantitative 0–100 scoring is rejected as false precision; the categorical level matches the level at which decisions are actually made. + +Every radar shows **two polygons** because every survey produces a dual-state output (Phase 2): + +- **Desired polygon** (solid fill, full opacity) — the personality the project commits to. Encoded as DOLCHEO Constraints in Phase 5. +- **Current polygon** (dashed outline, lighter, no fill) — the personality the project actually has today. Encoded as DOLCHEO Observations in Phase 5. + +Where the polygons coincide, the project is on-target on that axis. Where they diverge, the gap is a roadmap item — Phase 5 encodes each non-zero gap as an Open. The radar *is* the roadmap, visualized. + +Renderers that present this radar interactively should support **axis reordering** so a viewer can flip from tension-opposite to alphabetical to category-grouped without losing the underlying data. The static SVG below is one ordering; the data is the same regardless of which ordering renders. + +### Worked Example — A Pilot-Stage Authentication Service + +A hypothetical authentication service for a vertical SaaS product, scoped at the Pilot stage. The dual-state survey output captures both where the project is today (current) and where it commits to going (desired): + +| Ility | Current | Desired | Gap | Why | +|---|:---:|:---:|:---:|---| +| Stability | 2 | 4 | **+2** | Auth failures are product failures; current build is mid-hardening | +| Maintainability | 2 | 3 | **+1** | Long-term maintainers will rotate; current code has legacy patterns | +| Reality | 3 | 4 | **+1** | Compliance is non-negotiable; current compliance posture has gaps | +| Affordability | 3 | 3 | 0 | Per-user cost model already on-target | +| Efficiency | 2 | 2 | 0 | Latency matters but the bar is moderate; current build meets it | +| Urgency | 1 | 1 | 0 | Don't rush auth; rank is already correctly low | +| Versatility | 1 | 1 | 0 | Auth is auth; scope correctly narrow | +| Originality | 1 | 1 | 0 | Proven patterns are good; novelty correctly low | +| Usability | 1 | 1 | 0 | Developer-facing API, not an end-user UI | +| Interoperability | 2 | 4 | **+2** | OAuth only today; SAML and OIDC are committed roadmap items | + +Four non-zero gaps. Stability (+2) and Interoperability (+2) are the top-priority roadmap items; Reality (+1) and Maintainability (+1) follow. The other six axes are on-target — the project is already living the personality it commits to on those axes. + +The radar: + + + Project Personality Radar — Pilot-stage Authentication Service (Current and Desired) + Radar chart with ten axes showing both the current and desired priority profiles of a hypothetical pilot-stage authentication service. The desired polygon (solid blue) reaches level 4 on Stability, Reality, and Interoperability and level 3 on Maintainability and Affordability. The current polygon (dashed orange) is smaller, sitting at level 2 on Stability, Maintainability, and Interoperability and level 3 on Reality and Affordability. Gaps between the two polygons on Stability, Maintainability, Reality, and Interoperability visualize the roadmap. Axes ordered tension-opposite clockwise from top: Stability, Maintainability, Reality, Affordability, Efficiency, Urgency, Versatility, Originality, Usability, Interoperability. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Stability + Maintainability + Reality + Affordability + Efficiency + Urgency + Versatility + Originality + Usability + Interoperability + + + + + 1 + 2 + 3 + 4 + + + + + Pilot-Stage Authentication Service + Personality Radar — MoSCoW (1=Won't, 2=Could, 3=Should, 4=Must) + + + + + + Desired + + Current + + + +The radar makes three things visible at a glance that the table buries: + +- **The gap between the polygons is the roadmap.** Visible *gap segments* — Stability (top, +2), Maintainability (upper-right, +1), Reality (right, +1), Interoperability (upper-left, +2) — are the four committed investment directions, ranked by gap magnitude. The bottom and bottom-left of the chart show coincident polygons: those axes are on-target. The radar audits the project's trajectory, not just its commitments. +- **Tension-opposite axes show their tradeoff structurally.** Stability sits at the top, Urgency directly opposite at the bottom — the project's spike on Stability (level 4) with valley on Urgency (level 1) shows the strongest single tradeoff being made, visualized as the radar's most pronounced lean. The same pattern across Reality/Originality, Affordability/Usability, Interoperability/Efficiency. The polygon's silhouette is structurally the tradeoff record. +- **An honest profile is asymmetric — and the two polygons should usually differ.** A near-circular polygon means Phase 2 was rubber-stamped (no real prioritization). A perfectly-coincident pair of polygons means either the project is already at its committed personality (rare on first survey) or current state was reported aspirationally rather than observationally. Both failure modes are diagnoseable from the picture. + +A standalone article framing the dual-state personality view for non-technical audiences is forthcoming; this section is the technical specification it will reference. The article will lead with "your product already has a personality, and a different one it should grow into" — the radar carries the rest. + +--- + +## How the Method Was Built — The 6B Borrow Evaluation + +This method was not invented in isolation. The borrow evaluation below names the prior art and the verdict for each item, per `canon/constraints/borrow-evaluation-before-implementation`. + +| # | Prior art | Verdict | Reasoning | +|---|---|---|---| +| 1 | Klappy 2018 — *Software Virtues, How to Prioritize* (`https://medium.com/@klappy/what-are-software-virtues-and-how-to-prioritize-them-f0b583741afe`) | borrow | Origin of the canonical ten ilities and the natural-tension framing. Already absorbed into `canon/definitions/software-virtues-vocabulary` and `canon/principles/quality-attributes-are-in-tension`. | +| 2 | Klappy 2018 — *Lean Expectations: PoC, Prototype, MVP* (`https://medium.com/@klappy/lean-expectations-poc-prototype-mvp-140749383fd4`) | borrow | Origin of the lifecycle-phase framing (PoC / Prototype / MVP) referenced by Phase 0 and Phase 2. Already partially absorbed into `klappy://odd/maturity`. Cited explicitly. | +| 3 | Archived `agent-skill` v1.3 PRD elicitation loop (`klappy://docs/archive/products/agent-skill/v1.3.1/PRD`) | bend | Loop *spirit* is borrowed (agent-as-elicitor, stage typing, asset intake, ambiguity capture). Loop *architecture* is rejected: lanes / pack-compilation / Cloudflare Pages distribution had no update propagation to downstream consumers and proved unmaintainable. The seven phases here adapt the spirit to canon-and-tools delivery. | +| 4 | SEI ATAM (Architecture Tradeoff Analysis Method, Carnegie Mellon SEI, ~2000) | bend | Scenario-driven tradeoff identification is the conceptual ancestor of Phase 3. Bend: ATAM's stakeholder-workshop format is too heavy for agent-task scoping; this method runs in one planning turn rather than a multi-day workshop. The scenario discipline is preserved; the workshop ceremony is not. | +| 5 | ISO/IEC 25010 — Software Product Quality Model | inspected-and-adopted | Cited in `canon/definitions/software-virtues-vocabulary` as the standard validating "the universe of quality attributes is larger than ten." Provides the vocabulary anchor for ility selection in Phase 1. No further borrow at this scope. | +| 6 | Bass / Clements / Kazman — *Software Architecture in Practice* | inspected-and-rejected | The book's full tactics-and-patterns framework is too heavy to absorb at this scope. The scenario-discipline content is already carried via ATAM (#4); the additional taxonomic detail does not earn its weight. Tripwire: when the matrix needs quantitative tactic mappings rather than categorical relationships, re-evaluate. | + +**Bide candidates** (tracked but not borrowed): + +- **SEI QAW** — redundant with ATAM borrow at this scope; tripwire is multi-stakeholder elicitation becoming a goal. +- **NFR Framework (Chung, Nixon, Yu, Mylopoulos)** — softgoal-satisficing math; tripwire is when the matrix needs probabilistic tension weights rather than categorical types. + +**Reversibility note.** This method is canon prose; superseding it later costs no code, no SDK choice, no architecture lock-in. Reversibility is high. + +--- + +## Integration Points + +The survey is most useful when it integrates with the rest of the operating context. Two integration points are explicit: + +- **`oddkit_preflight`.** When the preflight surfaces requirements for execution, the survey output should be among the inputs preflight has access to. An agent that runs preflight on a project with an existing constraint set inherits the survey's decisions automatically. Surfacing this method as a constraint reference in preflight is the next step. +- **Future `oddkit tensions(...)` action.** Codifies the dynamic-generation step from Phase 3 as a tool call. Inputs: list of ilities, current phase, optional context. Output: tension graph in the same format as the canonical matrix. Until that tool exists, the dynamic-generation step is run by hand or by an agent reading the procedure in Phase 3. + +--- + +## What This Method Does Not Do + +Three things the method is deliberately silent on: + +- **Stakeholder elicitation across multiple humans.** This method is single-operator or single-agent. Multi-stakeholder elicitation (the SEI QAW pattern) is a different method that may be drafted later if the need arises. The survey can be run by a team in conversation, but the method itself does not orchestrate that conversation. +- **Quantitative tension weights.** Tensions are tagged with relationship types (mutual / asymmetric / synergy / cost gravity) and phase weights (PoC / Pilot / Production), not with probabilistic or numeric scores. The categorical level matches the level at which decisions are actually made; quantitative scoring is tracked as a Bide candidate (NFR Framework above). +- **Continuous re-survey.** The survey is a discrete artifact, not a running process. Re-runs are triggered by named events (Phase 6), not by a heartbeat. Continuous tension monitoring would be a different method built on the observability extension; this one stops at scope-setting. + +--- + +## Lineage + +Two 2018 Medium articles by the same author seeded this method twenty months apart from arriving at canon: *Software Virtues — How to Prioritize* (the ility vocabulary and tensions) and *Lean Expectations — PoC, Prototype, MVP* (the lifecycle phasing). The agent-skill v1.3 PRD elicitation loop (now archived) prototyped the seven-phase shape in an elicitation context with brittle distribution; this method preserves the spirit on a durable substrate. The SEI ATAM tradition contributed the scenario-driven tradeoff framing; ISO/IEC 25010 contributed the vocabulary anchor. The principle at `canon/principles/quality-attributes-are-in-tension` is the asserted fact this method operationalizes; the matrix and observability extension are the worked examples this method consults during Phase 3. diff --git a/canon/observations/observability-tension-extension.md b/canon/observations/observability-tension-extension.md new file mode 100644 index 0000000..d26a572 --- /dev/null +++ b/canon/observations/observability-tension-extension.md @@ -0,0 +1,138 @@ +--- +uri: klappy://canon/observations/observability-tension-extension +title: "Observability Tension Extension — One Worked Example of Extending the Matrix from ODD's Existing Canon" +audience: canon +exposure: nav +tier: 2 +voice: neutral +stability: stable +tags: ["canon", "observations", "quality-attributes", "software-virtues", "tradeoffs", "tensions", "observability", "extension", "matrix-extension", "epoch-8"] +epoch: E0008.4 +date: 2026-05-10 +derives_from: "canon/principles/quality-attributes-are-in-tension.md, canon/observations/quality-attribute-tension-matrix.md, canon/definitions/software-virtues-vocabulary.md, canon/case-studies/catalog-observability-gap.md, docs/appendices/epoch-8.md, docs/appendices/epoch-8-2.md, docs/appendices/epoch-8-3.md, canon/values/axioms.md" +complements: "odd/maturity.md" +governs: "Reference for the tensions between observability and the canonical ten quality attributes. Demonstrates the extension pattern: when an ility has rich canon support, its tensions are stitched from existing canon rather than re-derived. Same shape applies to other ilities (auditability, securability, accessibility, etc.) when they earn their own extension docs." +status: active +--- + +# Observability Tension Extension — One Worked Example of Extending the Matrix from ODD's Existing Canon + +> Observability earns its own extension because ODD has been writing about it for an entire epoch already. This document maps observability's tensions against the canonical ten — ten new pairs, each grounded in either the catalog-observability-gap case study or the Epoch 8 / 8.2 / 8.3 appendices. The point is not just observability; it is the *pattern*. When an ility already has canon, its tension graph stitches from that canon. The eventual dynamic-generation method generalizes this pattern; this doc demonstrates what one well-grounded extension looks like by hand. + +--- + +## Summary — Observability Joins the Tension Graph with Its Canon Already Written + +Observability is not a new ility. ODD has lived inside it for an entire epoch — `klappy://docs/appendices/epoch-8` (Observability: Transparent Telemetry and Infrastructure Accountability), `klappy://docs/appendices/epoch-8-2` (Put the Clock in the Room), `klappy://docs/appendices/epoch-8-3` (Validation as Observable Mode), and the case study at `klappy://canon/case-studies/catalog-observability-gap` (When the Knowledge Server Cannot See Its Own Knowledge Base). Observability's tensions with the canonical ten are therefore not derived from intuition; they are stitched from canon already written. + +This document does that stitching for one ility as a worked example of the broader extension pattern. The pattern: when a project's quality attributes include something beyond the canonical ten, the tensions are not generated from nothing — they are pulled from existing canon where it exists, and from the principle (`canon/principles/quality-attributes-are-in-tension.md`) where canon is silent. + +The principle itself is unchanged. The matrix at `canon/observations/quality-attribute-tension-matrix.md` is unchanged. Observability is not promoted into the canonical set; the canonical ten stays canonical. This extension is the eleventh node added off to the side, with edges back to each of the ten and citations to the canon evidence for each edge. + +--- + +## Definition — Observability in ODD + +**Definition.** The degree to which the system makes its own state legible to those who need to act on it. In ODD specifically, observability is the structural property that lets the model, the operator, and the team observe what the system is actually doing rather than what they think it is doing. Includes telemetry (what calls happened), state visibility (what the system thinks now), process visibility (what mode it is in, what gates have fired), and infrastructure accountability (what the runtime is actually charging in cycles, bytes, dollars). + +**Operational note.** Observed by asking three questions and answering them with primary evidence rather than reasoning: (1) Did the action that the system claims happened actually happen? (2) What did it cost? (3) What state is the system in right now? If those questions cannot be answered without rebuilding the answer from inference, observability has failed regardless of what telemetry pipelines exist. + +**Why observability is not in the canonical ten.** The 2018 article was written before observability was load-bearing for the kind of work ODD orchestrates. The canonical ten still apply to most projects; observability becomes critical specifically when the work is autonomous, agent-driven, or otherwise not directly supervised by humans who can spot-check by intuition. ODD's E0008 arc was the moment observability moved from optional engineering hygiene to structural requirement. + +--- + +## Observability and the Observation Encoding Type Are Siblings Under Axiom 4 + +There is a deeper structural reason observability earns its own extension before any of the other ilities ODD might absorb. It is the system-level expression of an axiom ODD already operationalizes at the session level. The two faces share parentage; naming the parallel makes the canon's underlying architecture visible. + +**At the session level**, ODD operationalizes Axiom 4 ("You Cannot Verify What You Did Not Observe") through the `O` encoding type in DOLCHEO — see `klappy://odd/encoding-types/observation`. An Observation captures what was seen during work, separated from what it means. "The deploy took 47 seconds" is an observation; "the deploy is too slow" is a Learning. Keeping the layers separate is what makes the rest of the framework — Decisions, Learnings, Constraints — defensible. Observations that nobody recorded are, in the encoding doc's phrasing, observations that never happened for the system's purposes. + +**At the runtime system level**, observability — the quality attribute mapped in this extension — is the same discipline applied to the system's own operation. The system reports its state in primary form (telemetry, traces, structured logs) rather than requiring its operators to infer state from secondary signals. Stability, maintainability, and debugability all build on top. A system that nobody can observe is, structurally, a system whose claims about its own behavior cannot be verified. + +**The two failure modes are the same.** When the catalog-observability-gap case study (`klappy://canon/case-studies/catalog-observability-gap`) names oddkit serving 500+ documents while its primary interface could only retrieve 196, that is the runtime-system version of an unrecorded observation: the team had a model of the system's behavior that the system itself had no way to corroborate. The Observation encoding type exists to prevent the same failure at the session scale, where a team can hold a confident interpretation of work that was never grounded in recorded evidence. + +**The two principles reinforce each other.** Sessions that capture rich Observations are sessions that produce defensible Learnings, Decisions, and Constraints. Systems that are richly observable are systems whose stability, maintainability, and debugability are defensible. Both stand or fall on the same axiom: claims unsupported by observation are debts the system carries until something forces them to be paid. + +This sibling relationship is why this extension was the first one written. Other ilities — auditability, securability, accessibility, portability — will earn their own extensions as projects need them and as ODD canon accumulates. Observability earns its place at the front of the queue because the parallel is already explicit in the canon's foundations, and naming the parallel strengthens both faces of it. + +--- + +## Tensions Between Observability and the Canonical Ten + +Each entry: relationship type, phase weighting, operating dynamic, and the canon evidence for the claim. + +### Observability ↔ Usability (M*, Production) + +Mild mutual tension. Rich instrumentation surfaces — dashboards, traces, logs — complicate the user-facing UX surface and pull cognitive budget from the primary task. Conversely, observability into how users actually use the product is what *reveals* usability problems that would otherwise stay invisible. Net is mildly tense in production when instrumentation surfaces compete with task surfaces; net is positive at pilot when usage telemetry informs UX iteration. + +*Canon evidence.* The catalog-observability-gap case study (`klappy://canon/case-studies/catalog-observability-gap`) is the worked example where observability into how the catalog was *used* surfaced a usability/correctness problem the implementation team had not seen. + +### Observability ↔ Originality (M*, Pilot) + +Asymmetric mutual tension. You instrument what you already understand; truly novel mechanisms resist instrumentation because their failure modes are not yet named. Originality-first projects often defer observability ("we do not yet know what to measure"), and observability-first projects often shape the design to fit existing telemetry primitives, foreclosing some originality. Bites at pilot, when the original idea is being made operationally legible for the first time. + +*Canon evidence.* `klappy://docs/appendices/epoch-8-3` (Validation as Observable Mode) is the moment ODD turned its lens on its own process and found that the original epistemic-modes idea needed to be re-shaped for legibility — the originality of "validation as a distinct mode" required new observability primitives, not just rewiring the existing ones. + +### Observability ↔ Stability (S, Production) + +Strong synergy. Observability is the primary mechanism by which stability is achieved — you cannot fix what you cannot see. Tension only when instrumentation itself becomes a stability hazard (telemetry pipelines that fall over and take the host system with them). Bites at production, where both expectations are highest and where instrumentation reliability becomes a first-class concern. + +*Canon evidence.* `klappy://docs/appendices/epoch-8` opens with the framing that infrastructure observability is what makes stability claims falsifiable; stability without observability is a claim, not evidence. + +### Observability ↔ Urgency (M, Production) + +Mutual tension. Urgency-driven projects routinely skip telemetry; the absence of telemetry then forces urgency-mode debugging when things break in production. The cycle reinforces itself. Bites hardest at production, where the cost of un-observability is paid in compounded incident response time. + +*Canon evidence.* The catalog-observability-gap case study (`klappy://canon/case-studies/catalog-observability-gap`) explicitly names the urgency-skipping pattern: oddkit shipped without the consumer-pagination contract that would have made the gap immediately visible; the urgency cost was paid later in operator confusion and a production smoke that took hours to interpret. + +### Observability ↔ Efficiency (M, Production) + +Mutual tension, direct and measurable. Telemetry has cost: bytes on the wire, cycles in the worker, storage in the analytics engine, dashboards to maintain. Efficient systems often run lean on observation by design. The reverse tension is real too: optimizing without observability is optimizing in the dark, and many efficiency wins come from having seen the bottleneck. Bites at production, where both the cost of telemetry and the cost of inefficiency are simultaneously measurable. + +*Canon evidence.* `klappy://docs/appendices/epoch-8` introduces the Analytics Engine architecture specifically because earlier observability designs had unacceptable efficiency costs; the architectural choice was driven by the tension itself. + +### Observability ↔ Maintainability (S, Production) + +Strong synergy. Observable code is maintainable code — a new contributor reading a system with rich tracing and structured logs can answer "what does this actually do" in minutes rather than hours. The tension is mild and only at extremes: instrumentation libraries themselves can become a maintenance burden, especially when the project is small enough that the telemetry surface exceeds the business-logic surface. + +*Canon evidence.* `klappy://docs/appendices/epoch-8-2` (Put the Clock in the Room) is a case where adding one observability primitive (`server_time` in every response) directly reduced maintenance load — the model stops fabricating elapsed times, stops getting them wrong, and stops requiring operator correction. + +### Observability ↔ Versatility (M*, Production) + +Mild mutual tension. Versatile systems have more code paths and more states; instrumenting all of them is more work, and partial instrumentation often misses the rare paths that produce the rare bugs. Conversely, versatile-and-observable systems become complex enough that the observability surface itself becomes hard to navigate. Bites at production where both versatility and observability ambitions compound. + +*Canon evidence.* The catalog-observability-gap case study (`klappy://canon/case-studies/catalog-observability-gap`) hit exactly this — oddkit's versatility (serving 500+ docs across multiple consumer shapes) combined with partial observability of consumer behavior produced a gap the team did not see until a consumer surfaced it. + +### Observability ↔ Interoperability (S, Production) + +Synergy mostly. Interoperable systems benefit from observability that crosses system boundaries — distributed tracing, correlation IDs, OpenTelemetry-class standards. The integration *is* the observability work in many cases. Tension only when proprietary observability primitives conflict with interop standards (e.g., a vendor-specific tracing protocol that does not propagate across partner boundaries). Bites at production. + +*Canon evidence.* `klappy://docs/appendices/epoch-8` documents the choice to use Cloudflare Analytics Engine — a non-portable substrate — and the deliberate decision to accept the interop cost in exchange for the efficiency-and-affordability win. The decision is recorded as a tension explicitly accepted, not avoided. + +### Observability ↔ Affordability ($, Production) + +Cost gravity. Telemetry has direct ongoing cost: ingestion fees, storage tiers, dashboard licenses, on-call rotations to interpret what the dashboards show. Affordability constrains how much observability investment a project can sustain. Bites at production, where the recurring monthly cost of observation becomes a line item. + +*Canon evidence.* `klappy://docs/appendices/epoch-8` names this directly: the choice of Analytics Engine over alternatives was driven by affordability; the choice of `SUM(_sample_interval)` aggregation rather than per-event storage was driven by the same constraint. + +### Observability ↔ Reality (S, all phases) + +Strong synergy. This is the foundational pair. Axiom 4 (`canon/values/axioms.md` — "You Cannot Verify What You Did Not Observe") is the principle stated as a value; observability is the technical means by which the value becomes operative. Reality demands that the team observe what is actually happening; observability answers that demand. Tension only when the cost of observation itself outpaces what reality provides in return — i.e., when over-instrumentation becomes its own reality-distortion. Bites at all phases, since both operate continuously. + +*Canon evidence.* `klappy://canon/values/axioms.md` (Axiom 4) is the value statement; the entire E0008 arc (`klappy://docs/appendices/epoch-8`, `epoch-8-2`, `epoch-8-3`) is its operationalization. The catalog-observability-gap case study is a worked failure mode where the axiom was held in principle and violated in practice — the system made claims about its knowledge base that the system itself had no way to verify. + +--- + +## How to Read This Extension + +The extension follows the same shape as the matrix: each pair has a relationship type, a phase tag, an operating dynamic, and (new in extensions) an explicit *canon evidence* citation pointing at the document or epoch where ODD has already lived this tension. + +The citation requirement is not decoration. It is the structural reason this extension is useful: every claim in this document is grounded in canon written for other reasons, in some cases years ago. The extension is not asserting new tensions; it is *naming* tensions ODD has already paid the cost of learning, and making them retrievable in the same shape as the canonical ten. + +When the matrix is extended further — auditability, securability, accessibility, portability — the pattern holds. The extension is cheap when the canon already exists. The extension is principle-grounded when canon is silent. The extension never re-opens the canonical ten. + +--- + +## Lineage + +Observability is the first extension because ODD has the deepest existing canon on it. The case study at `klappy://canon/case-studies/catalog-observability-gap` and the three epoch appendices (`klappy://docs/appendices/epoch-8`, `epoch-8-2`, `epoch-8-3`) constitute roughly half a year of accumulated thinking that this extension stitches into the tension-graph format. Future extensions for other ilities will follow the same template — definition tight enough for canon, ten new pair entries, citations to existing canon where it exists, principle-grounded reasoning where canon is silent. The eventual method doc at `canon/methods/quality-attribute-tension-survey` (forthcoming) will operationalize this stitching dynamically; this extension is the worked example demonstrating what good output looks like. diff --git a/canon/observations/quality-attribute-tension-matrix.md b/canon/observations/quality-attribute-tension-matrix.md new file mode 100644 index 0000000..1da9b37 --- /dev/null +++ b/canon/observations/quality-attribute-tension-matrix.md @@ -0,0 +1,294 @@ +--- +uri: klappy://canon/observations/quality-attribute-tension-matrix +title: "Quality Attribute Tension Matrix — All Forty-Five Pairs Across Ten Virtues, Phase-Weighted" +audience: canon +exposure: nav +tier: 2 +voice: neutral +stability: stable +tags: ["canon", "observations", "quality-attributes", "software-virtues", "tradeoffs", "tensions", "matrix", "phase-weighting", "ilities"] +epoch: E0008.4 +date: 2026-05-10 +derives_from: "canon/definitions/software-virtues-vocabulary.md, canon/principles/quality-attributes-are-in-tension.md, odd/maturity.md, https://medium.com/@klappy/what-are-software-virtues-and-how-to-prioritize-them-f0b583741afe" +complements: "canon/values/axioms.md" +governs: "Reference for which quality attributes are in tension with which, the type and direction of each tension, and the project phase at which each tension bites hardest. Used during prioritization, design review, and tradeoff analysis." +status: active +--- + +# Quality Attribute Tension Matrix — All Forty-Five Pairs Across Ten Virtues, Phase-Weighted + +> A worked example of the tension graph across the canonical ten quality attributes: forty-five unique pairs, each tagged with relationship type (mutual tension / asymmetric grounding / synergy / cost gravity), direction (which virtue erodes which), and the project phase at which the tension bites hardest (PoC / Pilot / Production). Twenty-one of the pairs are named in the 2018 source article; twenty-four are filled in here for the first time. The matrix demonstrates the shape the tension survey produces — it is not the master reference. The universe of quality attributes is far larger than ten; this document is the corpus that shows what good looks like when the principle at `canon/principles/quality-attributes-are-in-tension.md` is applied. + +--- + +## Summary — A Worked Example of the Tension Graph for the Canonical Ten + +Every design decision moves at least one quality attribute up and at least one other down. The principle at `canon/principles/quality-attributes-are-in-tension.md` asserts that the moves are not random and that this holds for any set of quality attributes. This document maps the canonical ten as a worked example: which virtue erodes which, in which direction, and at which project phase the erosion is most consequential. + +The matrix uses four relationship types: + +- **Mutual tension (M)** — both virtues erode the other. Optimizing for one reliably costs the other. +- **Asymmetric grounding (A)** — one virtue disciplines the other without symmetric retaliation. The grounding virtue (usually reality) does not get eroded by what it constrains. +- **Synergy (S)** — both virtues reinforce each other, with mild tension only at extremes. Pursuing one tends to advance the other. +- **Cost gravity ($)** — affordability's relationship with every other virtue: each virtue is purchased with effort, time, or money, so affordability constrains how much of each can be afforded. + +Phase weighting follows the three-level maturity model from `odd/maturity.md`: + +- **PoC** (Level 0 — exploration, learning) — tension bites when the team has not yet decided whether the idea is worth pursuing. +- **Pilot** (Level 1 — pilot/product) — tension bites when the project has real users but has not yet committed to long-term operation. +- **Production** (Level 2 — production / long-term) — tension bites when the project is committed to ongoing operation under real load. + +Most tensions bite at one phase more than the others. A single phase tag per cell names where the tension is sharpest; secondary phases are noted where the bite is broad. + +--- + +## Compact Reference — The 10×10 Grid + +Quick-reference grid. Lower-left triangle is filled (each pair appears once). Reading: row virtue's relationship to column virtue. + +| | Use | Orig | Stab | Urg | Eff | Maint | Vers | Inter | Aff | Real | +|--------------|:---:|:----:|:----:|:---:|:---:|:-----:|:----:|:-----:|:---:|:----:| +| **Use**ability | · | | | | | | | | | | +| **Orig**inality | M | · | | | | | | | | | +| **Stab**ility | M* | M | · | | | | | | | | +| **Urg**ency | M | M* | M | · | | | | | | | +| **Eff**iciency | M* | M* | M* | M | · | | | | | | +| **Maint**ain | M* | M* | S | M | M | · | | | | | +| **Vers**atility | M | M* | M* | M* | M | M* | · | | | | +| **Inter**op | M* | M | M* | M | M* | M* | S | · | | | +| **Aff**ordability | $ | $ | $ | $ | S | S | $ | $ | · | | +| **Real**ity | A | A | S | A | S | S | A | S | S | · | + +Legend: M = mutual tension (named in 2018 article). M* = mutual tension (filled in here). A = asymmetric grounding. S = synergy. $ = cost gravity. · = self. + +--- + +## The Forty-Five Pairs + +Each entry: relationship type, direction (if asymmetric), bite phase, and the operating dynamic. Pairs are ordered by row index then column index from the grid above. + +### Pairs Centered on Usability + +#### 1. Usability ↔ Originality (M, Pilot) + +Mutual tension. New innovative features are rarely understood well enough to be made simple at first; usability requires patterns the user already recognizes, and originality means breaking those patterns. Bites hardest at pilot phase, when the original idea must reach actual users. Article-named. + +#### 2. Usability ↔ Stability (M*, Pilot) + +Mutual tension, mild. Polish for usability sometimes hides instability under aesthetics ("looks finished, breaks under edge cases"); defensive stability code can produce confirmation dialogs and error states that erode usability. The tension is subtle but real at pilot when the product first touches users who do not know the workarounds. + +#### 3. Usability ↔ Urgency (M, Production) + +Mutual tension. Rushing to ship leaves no time for user testing or interface refinement; user testing and refinement take time. Bites at production, where the cost of unusable software is paid in support load and churn. Article-named. + +#### 4. Usability ↔ Efficiency (M*, Pilot) + +Mutual tension, mild. Beautifully usable interfaces often involve animations, transitions, and helpful intermediate states that cost cycles; efficient backends sometimes dictate workflows that are technically correct but cognitively awkward. Bites at pilot when the product targets devices or networks where efficiency limits are felt. + +#### 5. Usability ↔ Maintainability (M*, Production) + +Mutual tension. Usability features add code paths (undo stacks, helpful errors, accessibility affordances) that increase the code surface; maintainable, conventional code structures sometimes resist the special-casing that good UX demands. Bites at production, where the maintenance cost of a usability-rich product compounds. + +#### 6. Usability ↔ Versatility (M, Pilot) + +Mutual tension. Versatility invites ambiguity that may undermine intuitiveness — software that does many things must offer choices, and choices erode the "one obvious way" that drives intuitive usability. Bites at pilot, when the product's scope is being negotiated against real-user friction. Article-named. + +#### 7. Usability ↔ Interoperability (M*, Pilot) + +Mutual tension. Interop layers expose options (which format to export, which provider to integrate with) that complicate the UX surface; UX that wants to feel decisive sometimes hides interop choices behind opinionated defaults that limit interoperability. Bites at pilot, when integration partners are negotiated. + +#### 8. Usability ↔ Affordability ($, Pilot) + +Cost gravity. Usability work — testing, iteration, design talent — has direct cost. Affordability constrains how much UX investment a project can sustain. Bites at pilot, when the unit economics of the product are first measured against the design budget. + +#### 9. Usability ↔ Reality (A, PoC) + +Asymmetric grounding. Reality keeps usability ambitions honest: an interface that tests well with the wrong user base is not usable with the right one. Reality is not eroded by usability; usability is grounded by reality. Bites at PoC, where unrealistic user assumptions are cheapest to correct. + +### Pairs Centered on Originality + +#### 10. Originality ↔ Stability (M, Pilot) + +Mutual tension. Innovative approaches are inherently less battle-tested; stability requires patterns whose failure modes are known. Bites at pilot, when the original idea is exposed to the variability of real-world conditions. Article-named. + +#### 11. Originality ↔ Urgency (M*, Pilot) + +Mutual tension, asymmetric in flavor. Urgency forces shortcuts that look like originality but are actually hurried imitation; genuine originality requires the time to discover what is actually new. Bites at pilot, when the "are we actually doing something new or just shipping fast" question becomes answerable. + +#### 12. Originality ↔ Efficiency (M*, Production) + +Mutual tension. Novel approaches usually arrive less optimized than the patterns they replace; efficiency-first design often forecloses the experimental routes that produce originality. Bites at production, where the cost of novel-but-slow becomes operational. + +#### 13. Originality ↔ Maintainability (M*, Production) + +Mutual tension. Novel patterns are harder to hire for and harder to onboard against; maintainable conventions limit the shapes a novel approach can take. Bites at production, where the team must scale beyond the founders who understood the novelty natively. + +#### 14. Originality ↔ Versatility (M*, Pilot) + +Mutual tension, mild. Strong novel ideas are usually highly specific to a narrow problem; versatility-first design rarely produces deep originality. Bites at pilot, when the project must decide whether to deepen its novel angle or widen its applicability. + +#### 15. Originality ↔ Interoperability (M, Pilot) + +Mutual tension. Interop with existing systems requires conformance to existing standards, which forecloses some innovations; pure innovation often produces formats and protocols that the rest of the ecosystem cannot read. Bites at pilot, when integration with the user's existing workflow is negotiated. Article-named. + +#### 16. Originality ↔ Affordability ($, Pilot) + +Cost gravity. Innovation is expensive — research, dead ends, prototypes that do not ship. Affordability constrains how much novelty a project can afford. Bites at pilot, when the runway shape is first matched against the experimentation budget. + +#### 17. Originality ↔ Reality (A, PoC) + +Asymmetric grounding. Reality limits originality by reminding the team what is already done, what physics permits, and what users actually want. Reality is not eroded by originality; originality is grounded (sometimes harshly) by reality. Bites at PoC, where unrealistic novelty is cheapest to redirect. Article-named. + +### Pairs Centered on Stability + +#### 18. Stability ↔ Urgency (M, Production) + +Mutual tension. Rushing increases the rate of bugs; thorough stabilization takes time the urgency budget does not have. Bites at production, where instability translates directly to user trust erosion. Article-named. + +#### 19. Stability ↔ Efficiency (M*, Production) + +Mutual tension. Hyper-optimization sometimes introduces instability (race conditions, edge-case overflow, brittle assumptions); defensive stability code adds overhead that erodes efficiency. Bites at production, where both stability and efficiency expectations are highest. + +#### 20. Stability ↔ Maintainability (S, Production) + +Synergy. Both stability and maintainability favor clean, predictable code with known failure modes. Mild tension only when "stable" code becomes "untouchable" — the legacy system whose stability comes from no one daring to change it. Bites at production, when the system is mature enough for legacy patterns to set in. + +#### 21. Stability ↔ Versatility (M*, Pilot) + +Mutual tension. Versatile code has more states, more code paths, and more configurations to test — making stabilization harder; stable code is often stable because its scope is narrow. Bites at pilot, when the scope-versus-reliability tradeoff is being negotiated. + +#### 22. Stability ↔ Interoperability (M*, Production) + +Mutual tension. External dependencies (services, APIs, formats) introduce failure modes the project cannot directly control; isolated, stability-first systems often refuse interop because every external connection is a new failure surface. Bites at production, where third-party outages become operational concerns. + +#### 23. Stability ↔ Affordability ($, Production) + +Cost gravity. Stability work — testing, redundancy, monitoring, on-call — has substantial cost. Affordability constrains how much reliability investment a project can sustain. Bites at production, where the cost of unreliability and the cost of reliability are both measurable. + +#### 24. Stability ↔ Reality (S, PoC) + +Synergy mostly. Reality demands stability where stakes are real; the meta-virtue and the technical virtue point in the same direction. Mild tension only when reality says "ship now and stabilize later" because the cost of waiting outweighs the cost of bugs. Bites at PoC, where the "ship now" pressure is highest. + +### Pairs Centered on Urgency + +#### 25. Urgency ↔ Efficiency (M, Production) + +Mutual tension. Urgency leaves no time for optimization; efficiency work pushes against shipping deadlines. Bites at production, when the cost of inefficiency at scale finally exceeds the cost of slowing down to address it. Article-named. + +#### 26. Urgency ↔ Maintainability (M, Production) + +Mutual tension. Rushing produces technical debt; clean, maintainable patterns take longer to arrive at. Bites at production, where accumulated technical debt becomes the project's primary cost driver. Article-named. + +#### 27. Urgency ↔ Versatility (M*, Pilot) + +Mutual tension. Rushing leads to ignoring related use cases that would have informed a more versatile design; versatile design takes time to surface, name, and implement. Bites at pilot, when the project's scope-versus-deadline tradeoff is most consequential. + +#### 28. Urgency ↔ Interoperability (M, Production) + +Mutual tension. Rushing skips the study and integration of existing standards; interop work has substantial up-front cost that urgency budgets cannot afford. Bites at production, when standards-non-compliance produces real integration failures. Article-named. + +#### 29. Urgency ↔ Affordability ($, Pilot) + +Cost gravity. Urgency itself is expensive — overtime, rushed contractors, parallel workstreams. Affordability constrains how much urgency a project can fund. Bites at pilot, when burn rate and timeline first collide. + +#### 30. Urgency ↔ Reality (A, Production) + +Asymmetric grounding. Reality fights the tyranny of the urgent: not every urgent thing is actually urgent, and rushing on a false deadline costs everything else. Reality is not eroded by urgency; urgency is grounded by reality. Bites at production, where false urgency creates real damage. Article-named. + +### Pairs Centered on Efficiency + +#### 31. Efficiency ↔ Maintainability (M, Production) + +Mutual tension. Optimized code is harder to read; readable conventional code is often slower. Bites at production, when both performance and maintainability bills come due. Article-named. + +#### 32. Efficiency ↔ Versatility (M, Pilot) + +Mutual tension. Efficient code is shaped tightly to its expected workload; versatile code must accommodate workloads it was not optimized for. Bites at pilot, when the scope decision determines how tight the optimization can be. Article-named. + +#### 33. Efficiency ↔ Interoperability (M*, Production) + +Mutual tension. Interop overhead — serialization, format conversion, protocol negotiation — has real cost; high-performance systems often use proprietary protocols specifically to skip that overhead. Bites at production, where high-throughput meets standards compliance. + +#### 34. Efficiency ↔ Affordability (S, Production) + +Synergy. Efficiency is a primary mechanism for affordability — fewer cycles is fewer dollars. The two reinforce each other directly. Mild tension only when the engineering cost of an efficiency win exceeds the operational cost of running un-optimized. Bites at production, where unit economics become decisive. + +#### 35. Efficiency ↔ Reality (S, Pilot) + +Synergy. Reality demands that hardware and cloud bills get paid; efficiency answers. Mild tension only when reality says "ship before optimizing" because the optimization budget is better spent learning whether anyone wants the product. Bites at pilot, where the "premature optimization" failure mode is most expensive. + +### Pairs Centered on Maintainability + +#### 36. Maintainability ↔ Versatility (M*, Production) + +Mutual tension. Versatile code has more code paths to maintain; maintainable conventions often limit the shapes a versatile system can take. Bites at production, where both maintainability and versatility expectations compound. + +#### 37. Maintainability ↔ Interoperability (M*, Production) + +Mutual tension, mild. Interop layers add code surface area to maintain; well-chosen standards reduce interop complexity by externalizing the spec. The tension net depends on which standards are chosen. Bites at production. + +#### 38. Maintainability ↔ Affordability (S, Production) + +Synergy. Maintainability reduces technical debt, which reduces ongoing development cost. The two reinforce each other directly. Tension only when maintainability investment (refactoring, documentation, test infrastructure) exceeds the cost of accumulated debt at the project's current scale. Bites at production, where the cost of un-maintainable code compounds. Article-named (implicitly). + +#### 39. Maintainability ↔ Reality (S, Pilot) + +Synergy. Reality favors hireable, conventional, well-understood code; maintainability serves that. Tension only at PoCs where conventional code costs more than throwaway code. Bites at pilot/production, where the project commits to a maintenance future or accepts a rewrite. + +### Pairs Centered on Versatility + +#### 40. Versatility ↔ Interoperability (S, Production) + +Synergy mostly. Interoperability is itself a form of versatility — the ability to participate in adjacent workflows. The two reinforce each other. Mild tension only when interop standards limit what the project can express (e.g., a REST-only standard locks out streaming designs). Bites at production. + +#### 41. Versatility ↔ Affordability ($, Pilot) + +Cost gravity. Versatile design takes more time, more testing, and more code surface — all expensive. Affordability constrains how much versatility a project can afford. Bites at pilot, when scope and budget first negotiate. + +#### 42. Versatility ↔ Reality (A, Pilot) + +Asymmetric grounding. Reality limits versatility ambitions: it is rarely realistic to achieve broad versatility, and chasing it produces software that does many things badly. Reality is not eroded by versatility; versatility is grounded by reality. Bites at pilot, where scope ambition meets evidence about what users actually do. Article-named. + +### Pairs Centered on Interoperability + +#### 43. Interoperability ↔ Affordability ($, Pilot) + +Cost gravity. Interop work — protocol implementation, format conversion, partner integration — has direct cost. Affordability constrains how much interop a project can fund. Bites at pilot, when integration partner agreements are first scoped against budget. + +#### 44. Interoperability ↔ Reality (S, Pilot) + +Synergy. Reality favors integration with the tools users already have; interoperability answers. Mild tension only when interop ambitions outrun real user needs (building bridges to systems no one bridges to). Bites at pilot, when integration scope is decided. + +### Pair Centered on Affordability and Reality + +#### 45. Affordability ↔ Reality (S, all phases) + +Synergy. Affordability and reality are both grounding meta-virtues; they reinforce each other directly. Reality's costs/benefits/risks/dependencies/penalties/compliance lens IS, in operational terms, an affordability analysis. Tension only when the framings are mismatched (e.g., reality demands compliance investment that the affordability budget cannot sustain — at which point the project's viability is itself in question). Bites at all phases, since both operate continuously. + +--- + +## How to Read the Matrix + +The matrix supports three primary uses: + +**Design review.** Before committing to a design, look up the pairs of virtues most affected by the choice. For each pair, name the predicted direction of erosion and decide whether the cost is acceptable for the project's current phase. + +**Disagreement diagnosis.** When a team disagrees about a tradeoff, the disagreement is often about which virtue is being prioritized rather than about facts. The matrix gives the disagreement a vocabulary: "you are prioritizing originality and accepting the predicted erosion of stability — at our current phase, is that the right call?" + +**Phase audit.** When a project moves between phases (PoC → Pilot → Production), the priorities shift. Use the phase tags to identify which tensions become more consequential at the new phase and which become less. Cross-reference with `odd/maturity.md` for the phase-by-phase weighting of the virtues themselves. + +--- + +## What This Matrix Does Not Claim + +Three things the matrix is deliberately silent on: + +- **The relative weight of each virtue** — that is project-specific and phase-specific. The matrix names the directions of tension, not the priority ranking. +- **The correct decision in any given case** — the matrix surfaces the costs of a choice; the choice itself is a judgment call that depends on the team's priorities and the project's phase. +- **Completeness** — there are dozens of quality attributes beyond these ten (auditability, securability, debugability, deployability, recoverability, observability, portability, accessibility, localizability, and many more). A static matrix cannot scale to the full universe; the canonical ten are a worked example that demonstrates the shape. For a project that uses a different set, the principle at `canon/principles/quality-attributes-are-in-tension.md` holds — generate the tension graph for that set dynamically rather than treating this matrix as the master reference. See `canon/observations/observability-tension-extension.md` for one worked example of the extension pattern, applied to observability because ODD has rich existing canon to stitch from. + +--- + +## Lineage + +Twenty-one of the forty-five pairs are named in "Software Virtues — How to Prioritize" (Chris Klapp, Medium, 2018), distributed across the article's per-virtue sections as "natural enemies" paragraphs. Twenty-four pairs are filled in here for the first time, completing the worked example the original article only sketched. Canon vocabulary uses "tensions" rather than the article's original "natural enemies" — the relationship is structural, and "tensions" carries the structural meaning more precisely. The phase-weighting axis is added from `odd/maturity.md`, which itself descends from the 2018 article's "Lifecycle Priorities" section. diff --git a/canon/principles/quality-attributes-are-in-tension.md b/canon/principles/quality-attributes-are-in-tension.md new file mode 100644 index 0000000..1db8661 --- /dev/null +++ b/canon/principles/quality-attributes-are-in-tension.md @@ -0,0 +1,85 @@ +--- +uri: klappy://canon/principles/quality-attributes-are-in-tension +title: "Quality Attributes Are In Tension — The Tradeoff Space Cannot Be Flattened" +audience: canon +exposure: nav +tier: 1 +voice: neutral +stability: stable +tags: ["canon", "principles", "quality-attributes", "software-virtues", "tradeoffs", "tensions", "ilities"] +epoch: E0008.4 +date: 2026-05-10 +derives_from: "canon/definitions/software-virtues-vocabulary.md, canon/values/axioms.md, https://medium.com/@klappy/what-are-software-virtues-and-how-to-prioritize-them-f0b583741afe" +complements: "odd/maturity.md, canon/constraints/mode-discipline-and-bottleneck-respect.md" +governs: "How tradeoffs between competing software properties are reasoned about across canon. Holds for any set of quality attributes, not only the canonical ten. Forbids reasoning that flattens the tradeoff space into a single objective function. Requires phase-aware weighting rather than universal rankings." +status: active +--- + +# Quality Attributes Are In Tension — The Tradeoff Space Cannot Be Flattened + +> Optimizing one quality attribute reliably degrades at least one other. The pairs are not random; they are structural. Urgency erodes stability and maintainability. Originality erodes usability and stability. Versatility erodes usability and efficiency. Affordability has cost gravity over all the others. Reality grounds them all against the world as it is. The pairs are real, the directions are predictable, and any framework that promises to optimize for everything simultaneously is selling you a flattened picture of a tradeoff space that is structurally a space of tensions. This principle holds for any set of quality attributes, not only the canonical ten worked through at `canon/observations/quality-attribute-tension-matrix.md`. + +--- + +## Summary — The Tradeoff Space Is Structured by Tensions, and Pretending Otherwise Is the Failure + +Software has no single objective function. The ten virtues catalogued in `canon/definitions/software-virtues-vocabulary.md` — usability, originality, stability, urgency, efficiency, maintainability, versatility, interoperability, affordability, reality — each name a property worth pursuing. None of them can be maximized in isolation. Optimizing one moves at least one other downward along a predictable axis. The same holds for the broader universe of quality attributes (auditability, securability, debugability, deployability, recoverability, observability, and dozens more) — the canonical ten are a worked example, not the full set. + +This is not a regrettable accident of engineering. It is the structural shape of the problem. A framework that claims to deliver "fast, reliable, maintainable, secure, scalable, and innovative" software without naming what each of those costs is not describing a tradeoff space; it is describing a wishlist. + +The principle has three operational consequences. First, **prioritization is not optional** — every project ranks its quality attributes, even if it ranks them by accident. Second, **the priorities shift** with the project's phase: a proof-of-concept that demands the same stability as a production system has misallocated its effort, and a production system that tolerates the originality budget of a prototype has accepted the wrong risk. Third, **the tension graph is the prior** — a ranking that violates the predictable directions of the graph (e.g., simultaneously claiming maximum urgency and maximum maintainability) is incoherent, not ambitious. + +The principle is grounded in `canon/values/axioms.md` Axiom 1 (Reality Is Sovereign): the tension structure of the tradeoff space is real whether or not the team acknowledges it. Refusing to name the tensions does not eliminate them; it only ensures the team will hit them without orientation. + +--- + +## The Pairs Are Predictable + +The tension graph is not random. The pairs follow from how each virtue is achieved: + +- **Urgency** is achieved by skipping checks. It erodes anything that requires checking — stability, maintainability, usability, interoperability. +- **Originality** is achieved by departing from the well-trodden path. It erodes anything that benefits from being well-trodden — usability (users know the old patterns), stability (the old patterns are battle-tested), interoperability (standards exist for a reason). +- **Versatility** is achieved by widening the surface area. It erodes anything that benefits from a narrow surface — usability (more options is more confusion), efficiency (more code paths is more cycles), maintainability (more states is more tests). +- **Efficiency** is achieved by shaping code tightly to its expected workload. It erodes anything that benefits from generality — versatility, maintainability (optimized code is harder to read), sometimes stability (defensive code costs cycles). +- **Affordability** is unique: it has cost gravity over every other virtue, because each virtue is purchased with effort, time, or money. Affordability does not erode the other virtues directly; it constrains how much of each can be afforded. +- **Reality** is also unique: it is the meta-virtue that grounds the others against the world as it is. It does not compete with them; it disciplines their pursuit. + +The full enumeration — 45 unique pairs across the ten virtues, with phase-weighting and worked examples — is at `canon/observations/quality-attribute-tension-matrix.md`. + +--- + +## The Failure Modes This Principle Forbids + +Three reasoning failures violate the principle and should be flagged when they appear: + +### Flattening — "We Optimize for All of Them" + +The claim that a project simultaneously delivers all the virtues at high levels. This claim is not ambition; it is incoherence. The tension graph predicts that maximizing one virtue moves another downward. A project claiming maximum delivery on the full set is either lying, redefining the virtues to avoid their tensions, or has not yet hit the phase where the tensions bite. + +### Universal Rankings — "Stability Is Always First" + +The claim that one virtue is universally most important. This is true only when the project's phase is held fixed. A proof-of-concept that prioritizes stability over originality has spent its effort on the wrong virtue for its phase. A production release that prioritizes originality over stability has shipped a prototype to users. The ranking shifts with the phase; see `odd/maturity.md`. + +### Hidden Tradeoffs — "We Did Not Sacrifice Anything" + +The claim that a choice optimized for one virtue at no cost to others. Sometimes this is true at small scales (a small efficiency gain that does not measurably affect maintainability). Often it is the result of not having looked. The graph predicts where to look; if the predicted cost is not visible, the question is whether it has not yet manifested or whether the team has not yet measured the right thing. + +--- + +## How to Use This Principle + +When making a substantial design or scoping decision, the principle obligates the team to answer three questions: + +1. **Which virtue is being prioritized?** +2. **Which other virtues does the tension graph predict will be sacrificed?** +3. **Is the predicted sacrifice acceptable for this project at this phase?** + +Answers to (2) come from the matrix at `canon/observations/quality-attribute-tension-matrix.md` for the canonical ten, and from dynamic generation against this principle for any other quality attributes the project happens to use. Answers to (3) come from `odd/maturity.md` and the team's project-specific weighting. + +A decision that cannot answer all three is incomplete, not because the team lacks vision, but because the team is operating on a flattened picture of a tradeoff space whose structure is tensions all the way down. + +--- + +## Lineage + +The principle is the canonical re-statement of the central observation in "Software Virtues — How to Prioritize" (Chris Klapp, Medium, 2018). The 2018 article called these tensions "natural enemies" and named them per-virtue; this principle states the structural fact behind them — quality attributes are in tension — and the matrix at `canon/observations/quality-attribute-tension-matrix.md` enumerates the canonical ten systematically. The principle holds for any set of quality attributes; the matrix is a worked example, not the master reference. diff --git a/odd/encoding-types/observation.md b/odd/encoding-types/observation.md index 11444d3..fa46bde 100644 --- a/odd/encoding-types/observation.md +++ b/odd/encoding-types/observation.md @@ -108,3 +108,4 @@ A strong Observation answers: what was seen, where it was seen, and whether it's - [DOLCHE Vocabulary](klappy://docs/oddkit/proactive/dolche-vocabulary) — the six-dimension framework this type belongs to - [Encoding Type: Learning](klappy://odd/encoding-types/learning) — the companion type that interprets observations - [Prompt Over Code](klappy://canon/principles/prompt-over-code) — why this governance doc exists instead of server code +- [Observability Tension Extension](klappy://canon/observations/observability-tension-extension) — the same axiom (Axiom 4 — You Cannot Verify What You Did Not Observe) operationalized at the runtime-system level. This encoding type is its session-level sibling. diff --git a/odd/handoffs/2026-05-10-survey-governance-wiring.md b/odd/handoffs/2026-05-10-survey-governance-wiring.md new file mode 100644 index 0000000..d162c5a --- /dev/null +++ b/odd/handoffs/2026-05-10-survey-governance-wiring.md @@ -0,0 +1,102 @@ +--- +uri: klappy://odd/handoffs/2026-05-10-survey-governance-wiring +title: "Handoff — Survey Method Governance Wiring (PR #192 continuation)" +audience: docs +exposure: nav +tier: 2 +voice: neutral +stability: semi_stable +tags: ["odd", "handoff", "session", "pr-192", "quality-attribute-tension-survey", "governance-wiring", "survey-method", "runtime-contract", "persona-shaped"] +date: 2026-05-10 +derives_from: "canon/methods/quality-attribute-tension-survey.md, odd/ledger/2026-05-10-software-virtues-canon-package.md" +governs: "Continuation of PR #192 (canon/software-virtues-tension-matrix). The next session's lane is wiring the quality-attribute-tension-survey method to oddkit's existing governance machinery (preflight, gate, challenge, validate, encode) following the persona-shaped / runtime-contract pattern landed in PR #187. The next session must read canon merged in PRs #179, #180, #186, #187 before editing the method doc." +status: closed +--- + +> **Lane is narrow.** Wire the existing survey method to oddkit governance machinery using the runtime-contract pattern from PR #187. Do not add new product surfaces. Do not draft Oddie content — Oddie already exists in canon. Do not reframe the seven phases or the dual-state radar. Both are locked and stakeholder-validated. + +## Why this handoff exists + +The prior session shipped the canon package on PR #192 (vocabulary, principle, matrix, observability extension, essay, method doc with seven phases and dual-state tension-opposite radar). The radar was stakeholder-validated by Ian Lindsley with "this is perfect." Then the prior session drifted off-lane and started drafting an "Oddie system prompt" without consulting canon — discovering only after operator correction that Oddie already exists in canon (PRs #179, #180) with voice, brand, activation rule, and methodology-personification pattern. The off-lane draft at `/mnt/user-data/outputs/oddie-system-prompt-v0.md` is **withdrawn** and should be ignored. + +The actual lane the prior session was supposed to occupy is **survey governance** — making the method doc *governance-driven* by wiring its phases to oddkit's preflight/gate/challenge/validate/encode actions, following the runtime-contract pattern PR #187 landed. + +## Current PR #192 state + +- **Branch:** `canon/software-virtues-tension-matrix` +- **Head:** `645d0b7` (pushed, on origin) +- **Mergeable:** True (last checked at 21:43Z), Bugbot `in_progress`, reference-integrity `in_progress` +- **Files in PR:** 8 — vocabulary, principle, matrix, observability extension, encoding-type cross-ref, essay, method doc, session ledger + +The method doc (`canon/methods/quality-attribute-tension-survey.md`, ~378 lines) is the file the next session will edit. It currently describes the seven phases conceptually but does NOT wire them to oddkit governance. Everything else in the PR is settled. + +## Required reading BEFORE editing + +The prior session was working off a five-PR-stale view of canon. Do not skip this step; the lane depends on understanding what's already there. + +| PR | Status | What it landed | +|---|---|---| +| **#187** | merged 2026-05-10 | Runtime method docs: persona-shaped + runtime-contract pattern. **This is the template to follow.** | +| **#186** | merged 2026-05-10 | Session-per-mode discipline + Resolution as **fifth mode** (canon now has five modes, not three) | +| **#180** | merged 2026-05-08 | Oddie voice canon wired into model operating contract — activation rule + brand guidelines | +| **#179** | merged 2026-05-08 | Oddie the river guide — voice canon, methodology-personification, critic-cannot-be-author | +| **#189** | OPEN | agents-need-their-own-wire (Tier-1) + mode-separated-conversations five-mode patch | +| **#188** | OPEN | rename audit-gates Tier-1 → spawned-agent-sessions + substrate-options method | +| **#190** | OPEN | Sweep DOLCHEO+H residue from active surfaces (P0009 enforcement) | +| **#193** | OPEN | journal: runtime canon merged provisionally | + +**Action:** before any edit, run `oddkit_search` for: `"runtime contract"`, `"persona-shaped method"`, `"governance wiring"`, `"five modes"`, `"session-per-mode"`. Then `oddkit_get` on every URI returned. Then run `oddkit_preflight` with input `"wire quality-attribute-tension-survey method to oddkit governance machinery following PR #187 runtime-contract pattern"` to load the actual constraints and DoD. + +If any of the four open PRs above merges before you start, rebase `canon/software-virtues-tension-matrix` on `main` first. PR #190 is most likely to surface conflicts in the ledger if any DOLCHEO+H residue slipped in. + +## Concrete next steps + +1. **Read canon above.** Especially PR #187's runtime-contract / persona-shaped docs. Note exact section structure used. +2. **Open `canon/methods/quality-attribute-tension-survey.md`.** +3. **Add a "Runtime Contract" section** near the top (after `## Summary`) following the #187 shape. Names the actions the survey uses: `oddkit_preflight` (entry), `oddkit_gate` (phase transitions), `oddkit_challenge` (Phase 4), `oddkit_validate` (completion), `oddkit_encode` (Phase 5 output). +4. **For each of Phases 0–6**, add a `**Governance.**` line stating which oddkit action governs phase entry, transition, and exit. Pattern from #187 will show the exact wording shape. +5. **Update ledger** (`odd/ledger/2026-05-10-software-virtues-canon-package.md`) with the new decisions, observations, and learnings from this wiring pass. Maintain DOLCHEO format. Do NOT write `DOLCHEO+H` — H is already in the acronym (P0009 anti-pattern). +6. **Commit** as `canon: wire survey method to oddkit governance machinery (runtime-contract pattern per #187)`. +7. **Push** to the same branch. Watch for Bugbot + reference-integrity audit to land `completed`. +8. **Update this handoff** with `status: closed` and a one-paragraph closeout when the wiring lands. + +## Do not + +- **Do not draft Oddie content.** Oddie already exists in canon (PR #179, #180). Reference existing voice canon if needed; do not generate new persona/posture/prompt material. +- **Do not reframe the seven phases or the dual-state survey directive.** Stakeholder-validated; locked. +- **Do not change the radar SVG, axis ordering, or two-polygon convention.** Tension-opposite ordering with Desired-solid / Current-dashed is locked. +- **Do not bundle `oddkit_tensions(...)` action work** into this PR. That's separate, in `klappy/oddkit` repo (banked as O-open P7 in the ledger). +- **Do not introduce three-mode language anywhere.** Canon now has five modes per #186 (including Resolution). The method's phase descriptions should align with five-mode canon, not the three-mode mental model the prior session was operating in. +- **Do not invent new encoding types.** Phase 5 produces Constraints, Observations, Opens — three of the seven DOLCHEO letters. Do not add a "Survey" encoding type or similar. + +## Banked / out of scope for this PR + +These are real items but they belong on different lanes. Do not pull them in: + +- **P5** — Standalone "personality test" article for non-technical audiences. Operator's verbatim framing to Ian Lindsley is preserved in the ledger as voice source. Future PR, future session. +- **P6** — Oddie pack design. **Superseded** — Oddie already exists in canon. Whatever further Oddie product work happens references the existing canon, not new drafts. +- **P7** — `oddkit_tensions(...)` action in `klappy/oddkit`. Separate repo, separate PR. +- **P11** — `oddkit_gate` mechanical enforcement of release-validation-gate. Open from prior work; not part of this lane. + +## Verified environment state + +- Working copy: `/home/claude/work/klappy.dev` on `canon/software-virtues-tension-matrix` at `645d0b7`, pushed to origin. +- Staging mirror: `/home/claude/work/canon-package/` (older snapshot, ignore in favor of working copy). +- PR helper scripts: `/home/claude/work/open_pr.py`, `/home/claude/work/check_pr.py` — use `python3` + `urllib.request` per project memory (curl unreliable in this container). +- Fresh sessions need to re-clone both repos to working dirs. + +## DOLCHEO of the off-lane drift (for the record) + +**[D]** Prior session withdrew the off-lane Oddie system-prompt draft on operator correction; lane reset to survey governance. + +**[L]** "Search Canon Before Asking Anything" is a hard rule, not a soft preference. The prior session drafted Oddie persona content without `oddkit_search` first; Oddie already had voice canon, brand guidelines, and a methodology-personification pattern in canon. Result was scope creep + lane violation + wasted operator attention. + +**[C]** Next session reads required canon BEFORE editing the method doc. Non-negotiable. + +**[H]** This handoff. Lane: survey governance wiring per #187 runtime-contract pattern. Scope: method doc + ledger update on existing PR #192 branch. + +--- + +## Closeout — 2026-05-10T22:00Z + +Lane closed cleanly. Branch `canon/software-virtues-tension-matrix` rebased on `main` to pull in PR #187's runtime-contract canon (no file overlap). The method doc at `canon/methods/quality-attribute-tension-survey.md` now carries a `## Runtime Contract — How oddkit Governs the Survey` section between `## Summary` and `## When to Run the Survey`, plus a `**Governance.**` final bullet on each of Phases 0 through 6. Five oddkit actions wired to the seven phases: `oddkit_preflight` (entry), `oddkit_gate` (every phase boundary), `oddkit_challenge` (Phase 4), `oddkit_encode` (Phase 5), `oddkit_validate` (completion). Ledger amended with a "Governance-Wiring Pass (Continuation)" section capturing D10–D11, O9–O10, L5, C4, H4, and E3. No new opens; banked items (P5, P6, P7, P11) untouched. The four Do-Not boundaries (no Oddie content, no phase reframing, no radar changes, no `oddkit_tensions(...)` work) held throughout. diff --git a/odd/ledger/2026-05-10-software-virtues-canon-package.md b/odd/ledger/2026-05-10-software-virtues-canon-package.md new file mode 100644 index 0000000..c406e89 --- /dev/null +++ b/odd/ledger/2026-05-10-software-virtues-canon-package.md @@ -0,0 +1,223 @@ +--- +uri: klappy://odd/ledger/2026-05-10-software-virtues-canon-package +title: "Ledger — Software Virtues Canon Package + Essay (Session 2026-05-10)" +audience: ledger +exposure: nav +tier: 3 +voice: neutral +stability: stable +tags: ["ledger", "session-journal", "dolcheo", "software-virtues", "quality-attributes", "tension-matrix", "epoch-8.4"] +epoch: E0008.4 +date: 2026-05-10 +session_start: 2026-05-10T17:09Z +session_end: 2026-05-10T17:30Z +governance_source: knowledge_base +governs: "Audit trail for the four-artifact canon package + essay produced in this session. Reading this ledger should reproduce the operator's view of what was decided, observed, learned, constrained, handed off, encoded, and left open." +status: active +--- + +# Ledger — Software Virtues Canon Package + Essay (Session 2026-05-10) + +> Session journal capturing the production of a four-artifact canon package and accompanying essay around Klappy's 2018 Medium article "Software Virtues — How to Prioritize". Triggered by SMS conversation between Klappy and partner Ian Lindsley earlier the same day, in which Klappy promised Ian "a massive table" expanding the article's per-section tension paragraphs into a full systematic map. Locks: vocabulary preserves "virtues" rhetorically and "quality attributes" operationally (option C); matrix is 3D — virtue × virtue × phase weighting per cell (option ii); canon and essay developed in parallel (option Z). Four drafts staged in working dir for operator PR review, not merged this session. + +--- + +## Summary — Four Drafts Produced; Operator Holds the Merge + +A planning-mode session that gated cleanly into execution and produced four coherent drafts. The trigger was Ian Lindsley's question about which "-ility tradeoffs" get maximized and which get minimized by which choices. Klappy's first answer was the answer he always gives: the balance changes by project and by phase. Ian sent 💯. Klappy then sent the 2018 Medium article and noticed mid-conversation that the article only listed tensions per-virtue and never built the full table. He committed to Ian to build it. This session is the build. + +The article enumerates twenty-one directed natural-enemy tensions across ten virtues. Ten virtues produce forty-five unique unordered pairs. Twenty-four pairs were unaddressed in the original article; this session filled them in, classifying each by relationship type (mutual tension / asymmetric grounding / synergy / cost gravity) and tagging each with the project phase at which the tension bites hardest (PoC / pilot / production). + +Outputs: definition (vocabulary), principle (axiomatic, tier 1), observation (the 10×10 matrix and 45-pair detail), and an essay framing the matrix as the systematic completion of the 2018 article. All four pass the eight-point Writing Canon checklist. Operator handles PR creation; no direct commits this session. + +--- + +## Decisions + +- **D1.** Produce coordinated four-artifact package: canon definition + canon principle + canon observation (matrix) + writings essay. All four developed in parallel rather than sequentially. Vocabulary preserves "virtues" rhetorically and "quality attributes" operationally as the same set. Matrix is 3D: virtue × virtue × phase weighting per cell. +- **D2.** Pair-relationship taxonomy locked at four types: Mutual tension (M), Asymmetric grounding (A), Synergy (S), Cost gravity ($). Article-named pairs tagged M; gap-filled pairs tagged M*. Phase weighting tags align with `klappy://odd/maturity` Levels 0/1/2 mapped to PoC/pilot/production. +- **D3.** Drafts staged in `/home/claude/work/canon-package/` rather than directly committed to a clone of `klappy/klappy.dev`. Operator handles PR scoping (likely canon docs first as one or three PRs, essay second once cross-links resolve). + +## Observations + +- **O1.** The 2018 Medium article enumerates twenty-one directed natural-enemy tensions across ten virtues, distributed as per-virtue paragraphs. The article never assembles a full N×N pair map. Ten virtues produce forty-five unique unordered pairs; twenty-four pairs were unaddressed in the original. The "massive table" Klappy promised Ian (per SMS screenshots, 2026-05-10 ~13:10 local) is exactly this systematic completion. +- **O2.** Canon already partially absorbed the 2018 article: `klappy://odd/maturity` is the modern descendant of the article's "Lifecycle Priorities" section, with Level 0/1/2 mapping to PoC/pilot/production. The article seeded canon nearly a decade ago and went unmined for the rest. The new package completes the absorption. +- **O3.** The Resonance pattern (`canon/resonance/`) does not fit Klappy's own prior writing — it is reserved for external works ODD diverges from. Klappy's 2018 article is origin/lineage, not resonance. Captured in `derives_from` frontmatter pointing at the Medium URL. + +## Learnings + +- **L1.** When investigation reveals new context (Ian's external validation, the table promise), planning shape must update before execution. Locks confirmed in writing before gating: vocabulary C, matrix dimensionality ii, sequencing Z. Four prerequisites met (decisions_locked, dod_defined, irreversibility_assessed, constraints_satisfied) before transition to execution. +- **L2.** Writing Canon checklist (`canon/meta/writing-canon`) is eight-point not seven-point. Items: title, blockquote, metadata, summary, header scan, no buried claims, axiom space, ghost writer / AI voice clichés. The eighth item was added with the Progressive Disclosure Failure incident (February 2026). + +## Constraints + +- **C1.** Files staged in `/home/claude/work/canon-package/` only. **Must not** be committed directly to `klappy/klappy.dev` or `klappy/oddkit` this session — operator handles PR creation. +- **C2.** Two repos always require separate PRs (per project memory). Only `klappy/klappy.dev` is affected this session — no `klappy/oddkit` changes. +- **C3.** 2018 article cited via external Medium URL in `derives_from` (full URL preserved, not abbreviated). The article is origin-of-record for the package; canon **must** treat it as such rather than as a resonance entry or external citation requiring divergence. + +## Handoffs + +- **H1.** Operator review needed on twenty-four gap-filled pair entries — particularly the seven Synergy classifications (stability↔maintainability, efficiency↔affordability, efficiency↔reality, maintainability↔affordability, maintainability↔reality, versatility↔interoperability, interoperability↔reality, affordability↔reality). Some Synergy calls may be debated; operator's intuition is the authoritative source. +- **H2.** Essay voice review for ghost-writer signals. Despite checking against `canon/constraints/ai-voice-cliches`, the draft may contain AI clichés (negation parallelism, formulaic transitions, generic descriptors). Operator may want to revise toward pure Klappy voice or accept current state. +- **H3.** PR sequencing decision: canon docs as one PR or three? Essay as a fourth PR after cross-links resolve, or bundled with the matrix PR? Operator's call. + +## Encodes + +- **E1.** Four canon package drafts at `/home/claude/work/canon-package/`: + - `canon/definitions/software-virtues-vocabulary.md` (132 lines) + - `canon/principles/quality-attributes-are-in-tension.md` (85 lines, tier 1) + - `canon/observations/quality-attribute-tension-matrix.md` (294 lines) + - `writings/software-virtues-revisited.md` (141 lines) +- **E2.** This ledger itself, capturing the session DOLCHEO. The encode action does not persist; this file is the persistence. + +## Opens + +- **O-open P1.** Should the matrix include observability-class virtues (auditability, securability, debugability, deployability, recoverability, observability)? The 2018 article punted on these as "secondary virtues" for engineering teams to add. Phase 2 expansion candidate. **Disposition pending operator review.** +- **O-open P2.** The essay's "Article Lacked an Operator" section claims ODD is the answer. Operator may want stronger or weaker tie depending on essay strategy: is this a klappy.dev essay that converts readers to ODD, or a stand-alone reflective piece that mentions ODD by reference only? **Disposition pending operator review.** +- **O-open P3.** MoSCoW and Hundred Dollar Method elicitation methods from the 2018 article: surface as "starting points, not endorsed" (current treatment in vocabulary doc) or write a separate canon doc that takes a stronger position? The current package is silent on elicitation methods at the operational level. **Disposition pending operator review.** + +--- + +## Process Trace + +| Step | Tool | Result | +|------|------|--------| +| 1 | `oddkit_time` | Initial timestamp 17:09Z | +| 2 | `oddkit_get` (`klappy://canon/bootstrap/model-operating-contract`) | Bootstrap fetched | +| 3 | `oddkit_search` ("software virtues ilities quality attributes tradeoffs") | No existing canon on the topic | +| 4 | `oddkit_search` ("phases of project maturity") | Found `klappy://odd/maturity` as canon descendant of article's Lifecycle Priorities section | +| 5 | `oddkit_get` (`klappy://canon/resonance/README`) | Resonance pattern is for external works; doesn't fit | +| 6 | `oddkit_orient` | Mode: planning | +| 7 | (Operator turn — SMS screenshots arrived; picture sharpened around table promise) | — | +| 8 | (Operator turn — locks: vocabulary C, matrix ii, sequencing Z) | — | +| 9 | `oddkit_preflight` | DoD surfaced | +| 10 | `oddkit_search` ("writing canon checklist") | Found `klappy://canon/meta/writing-canon` (8-point) | +| 11 | `oddkit_get` (`klappy://canon/meta/writing-canon`) | Internalized checklist | +| 12 | `oddkit_get` (`klappy://writings/agentic-software-development#Summary`) | Voice reference for essay | +| 13 | `oddkit_gate` | PASS planning → execution | +| 14 | `create_file` ×4 | Four artifacts produced | +| 15 | `oddkit_validate` | NEEDS_ARTIFACTS (visual proof, session capture, version tracking) | +| 16 | `oddkit_encode` | 15 DOLCHEO artifacts encoded | +| 17 | `create_file` (this ledger) | Session capture saved | +| 18 | (Operator turn — fourth SMS arrived; vocabulary correction and dynamic-generation reframe) | — | +| 19 | `git mv` + `str_replace` ×N | Sweep: rename principle to `quality-attributes-are-in-tension`; "natural enemies" → "tensions" across all files; "adversarial" → "tensions"/"tradeoff space"; matrix reframed as worked example not master; vocabulary updated to note universe is larger; essay closing pivoted to constraints-survey framing | + +--- + +## Late-Session Corrections + +After initial validate and present, a fourth set of operator inputs arrived (SMS screenshots + direct message). Two corrections, executed in-session: + +**Vocabulary correction (D4).** "Language should always be tensions." The 2018 article's "natural enemies" framing is preserved only when explicitly quoting the article. Canon vocabulary is now **tensions** throughout. Principle file renamed: `quality-attributes-have-natural-enemies.md` → `quality-attributes-are-in-tension.md`. URI: `klappy://canon/principles/quality-attributes-are-in-tension`. All cross-links updated. + +**Architectural reframe (O4 / D5).** The static 10-virtue matrix cannot scale — there are dozens of quality attributes the worked example does not cover. The future is dynamic generation: the principle holds for any set of quality attributes; the matrix is the canonical worked example demonstrating what good looks like; project-specific tension graphs are generated on demand against the principle. Operator's framing: "It can be our constraints survey for new work with agents." Matrix doc reframed accordingly (blockquote + Summary + Completeness section); vocabulary doc updated to call out that ten is a worked example not the universe; principle updated to assert universal applicability; essay adds a closing "What This Becomes Next" section pivoting to the constraints-survey use. + +**Open lifted from O-open list (P4).** New: a method doc — `canon/methods/quality-attribute-tension-survey` (provisional) — operationalizes the matrix as a survey instrument for project scope-setting. Includes the dynamic-generation step: pick the ilities for this project, generate the tension graph against the principle, encode chosen priorities as constraints the agents inherit. **Disposition: banked for next session per operator's lean toward focused planning.** Borrow-evaluation against operator-named "prior art" recommended before drafting. + +--- + +## Method Doc Drafted Same Session (Update) + +After initial bank, operator chose to draft the method doc in-session rather than wait. The borrow-evaluation that was proposed as next-session work was completed in-session and embedded directly in the method doc. Six prior-art rows evaluated: + +1. **Klappy 2018 — Software Virtues** (origin) — borrow. +2. **Klappy 2018 — Lean Expectations: PoC, Prototype, MVP** (lifecycle phases, the article cross-referenced by the Software Virtues piece itself) — borrow. Surfaced via web search of operator's Medium author page. +3. **agent-skill v1.3 PRD elicitation loop** (`klappy://docs/archive/products/agent-skill/v1.3.1/PRD`) — bend. Loop spirit borrowed (agent-as-elicitor, stage typing, asset intake); loop architecture (lanes, pack compilation, Pages distribution) rejected as brittle and lacking update propagation per operator. +4. **SEI ATAM** — bend. Scenario-driven tradeoff identification borrowed; workshop format compressed to single-turn agent-runnable shape. +5. **ISO/IEC 25010** — inspected-and-adopted as vocabulary anchor. +6. **Bass / Clements / Kazman *Software Architecture in Practice*** — inspected-and-rejected at this scope; tripwire is quantitative tactic mapping. + +Bide candidates: SEI QAW, NFR Framework (Chung et al). Reversibility note: high — canon prose, no SDK or architecture lock-in. + +Method doc lands as `canon/methods/quality-attribute-tension-survey.md` (~207 lines) on the same PR (#192) rather than a stacked PR. Decision rationale: keeps the canon package coherent as one merge; method doc depends on the principle file in the same branch so dependency resolves naturally; review cost is one Bugbot re-run. + +**New decision (D6).** Method doc landed in the same PR as the canon trio + observability extension + essay rather than a stacked follow-on PR. PR scope expanded by ~207 lines. + +**New observation (O5).** Web search of operator's Medium author page surfaced *Lean Expectations* (Sep 8, 2018) as the day-prior precursor to the Software Virtues article. The two articles were published 24 hours apart and explicitly cross-reference each other; both are sibling seeds to the canon package built today. + +**New decision (D7).** Personality-radar visualization added to the method doc (~120 lines, including inline SVG worked example). Operator framing locked: "the survey is a personality test for the product." Tension-adjacent axis ordering as default; MoSCoW scale (1-4); renderers expected to support reordering. Worked example: hypothetical Pilot-stage authentication service rendered as inline SVG with axis labels, scale rings, and project polygon. Asymmetric polygon shape ("an honest profile is asymmetric") named as a quality signal — circular profiles indicate Phase 2 rubber-stamping. + +**New observation (O6).** The personality-test framing earns the radar visualization for free — same shape humans already use for personality traits — and gives the survey a public-facing entry point that "have you completed your quality-attribute tension survey?" never could. The framing reframes the operational artifact (a constraint set) as something stakeholders, reviewers, and inheriting agents can grasp at a glance. + +**New open (O-open P5).** Standalone article framing the survey as a personality test for non-technical audiences. Method doc points forward to it; not drafted this session. Provisional title direction: something like "Your Product Has a Personality, and You Should Know What It Is." **Disposition: banked.** Lead with the radar, let readers self-discover the rigor underneath. + +**New decision (D8 — axis ordering correction).** Operator overrode the prior tension-adjacent ordering with **tension-opposite / synergy-adjacent**. Rationale (operator quote): "Across makes more sense. Similar parallel virtues beside each other show a natural gravity." Right half of the radar is the synergy chain (Stability → Maintainability → Reality → Affordability → Efficiency); left half is the tension cluster mirrored across the diameter (Urgency, Versatility, Originality, Usability, Interoperability). Every adjacent pair on the right is S (synergy) per the matrix; every diameter-opposite pair is M or A per the matrix. + +**New decision (D9 — dual-state survey, one flow).** Operator directive: "The survey asks you to respond with what is and what do you want it to be for each question in the survey. One flow." Survey reframed so that Phases 1, 2, 3, and 4 each elicit both current and desired state in the same pass. Phase 5 (renamed *Output Encoding*) now produces three DOLCHEO artifact types from one survey run: Constraints (desired state — what the agent inherits), Observations (current state — falsifiable baseline), Opens (the gaps — prioritized roadmap items ranked by gap magnitude). Radar shows two polygons (Desired solid, Current dashed); gap segments between them are the visible roadmap. + +**New observation (O7).** The tension-opposite ordering produces three audit signals in the radar that the tension-adjacent ordering buried: (1) the polygon's *lean* toward prioritized ilities is visible at the chart's diameter; (2) the right-side contour smoothness indicates how synergy-coherent the project's priorities are; (3) the gap between current and desired polygons is interpretable directly as roadmap. + +**New observation (O8).** The dual-state framing collapses what would have been a separate "audit pass" or "current-state assessment" into the same survey instrument. One flow, two answers per question, three artifact types out. Architecturally cleaner; operationally cheaper. + +--- + +## Stakeholder Validation — Ian's Review + +After the dual-state radar landed (commit `3509386`), operator shared the rendered page with technical partner Ian Lindsley. Ian responded "**This is perfect.**" Verbatim exchange preserved here as source material for the banked standalone article (O-open P5). + +**Operator's framing to Ian, verbatim:** + +- *"lol, it's what I'm calling the personality test for a product. What personality do you want your product to have? 😂"* +- *"Imagine oddkit survey questions. It discovers the current and aspirational personality of your project."* +- *"It renders this chart and over time you can track the movement from what was to your desired priorities."* +- *"It can help you create a roadmap and priorities for features and functions that actually move the needle towards the outcomes and impact the user in a meaningful way."* + +These four texts compress the entire arc — vocabulary, principle, matrix, method, radar, personality framing — into stakeholder-readable form. They are the spine of the standalone article when drafted. Operator wrote them in real time without canon reference; the framing crystallized from the work, not from a script. + +**New learning (L3 — voice landed first).** The voice for the standalone article emerged from operator's live stakeholder conversation before any draft was attempted. The article's job is to preserve this voice across audiences, not to derive a new one. Lesson: when the framing reaches an external technical partner cleanly, capture it verbatim before it gets re-derived in a more formal register. + +--- + +## New Product Surface — Oddie, the Dynamic Survey Interviewer + +Operator directive (verbatim): *"the dynamic oddkit survey is governance driven. You just teach a model how to interview. Oddie is the interviewer."* This crystallizes a new product surface that is distinct from both the static method doc (the canonical specification) and the future `oddkit tensions(...)` action (a tool call that codifies the dynamic-generation step from Phase 3). Oddie is the *interactive interview runtime* — a persona-pack that a model consumes to run a quality-attribute tension survey as a conversation. + +**New learning (L4 — Vodka Architecture applied to elicitation).** Oddie inherits the same architectural shape as oddkit itself: thin pack over stateful canon. The pack contains a persona, a posture, a phase-by-phase flow controller, and a list of canon URIs to fetch at runtime. The pack does *not* contain the method itself, the principle itself, or the matrix itself — those are read from canon live via oddkit each session, so canon updates propagate automatically. This explicitly rejects the archived agent-skill v1.3 pack-compilation / Cloudflare Pages distribution pattern that operator named brittle and unmaintainable (no update propagation to downstream consumers). + +**New open (O-open P6 — Oddie pack design).** Forward-pointing work for next focused session. Shape proposed (subject to operator confirmation): + +- **Identity & posture** — "You are Oddie. You help product teams discover the current and aspirational personality of their projects through quality-attribute tension surveys. You are an elicitor, not an author. You extract; you do not invent. You ask one phase at a time. You wait for the team's answer before moving on. You ground every claim in canon." +- **Runtime canon dependencies** (fetched live via oddkit, not snapshotted into the pack): + - `klappy://canon/methods/quality-attribute-tension-survey` (the method itself) + - `klappy://canon/principles/quality-attributes-are-in-tension` (the principle) + - `klappy://canon/observations/quality-attribute-tension-matrix` (the 45-pair worked example) + - `klappy://canon/observations/observability-tension-extension` (the extension pattern) + - `klappy://canon/definitions/software-virtues-vocabulary` (the canonical ten) +- **Phase-by-phase flow controller** — short instructions per phase pointing at the canon section that governs the questions to ask, with explicit dual-state elicitation prompts. +- **Output emitter** — instructions for producing the three DOLCHEO artifact types (Constraints, Observations, Opens) plus the SVG personality radar. +- **Distribution surface(s)** — model-agnostic system-prompt blob as the canonical form; wrappers may include Claude skill, custom GPT, MCP server, or system-prompt-as-pack. The same underlying pack content drives all of them. + +**Disposition: banked for next session.** Pre-implementation evaluation should re-run the 6B borrow against agent-skill v1.3 (now explicitly with the "no pack compilation, no Cloudflare Pages distribution, no snapshot lock-in" guardrails) and any other elicitation-pack prior art operator surfaces. + +**New open (O-open P7 — `oddkit tensions(...)` action remains separate).** Distinct from Oddie. Oddie is the conversational runtime; `oddkit tensions(...)` is the tool call Oddie *uses* at Phase 3 when surveying ilities outside the canonical ten. Banked in `klappy/oddkit` repo, separate PR. Sequencing: Oddie can be drafted before the action lands because Phase 3's dynamic-generation step has the hand-run procedure documented; the action just codifies what Oddie would otherwise do procedurally. + +--- + +## Governance-Wiring Pass (Continuation) + +A second working pass on PR #192 wired the method doc to oddkit governance machinery, following the runtime-contract pattern landed by PR #187 (same-day canon merge, 2026-05-10). Lane scope per `klappy://odd/handoffs/2026-05-10-survey-governance-wiring`: add a Runtime Contract section after `## Summary`, and a `**Governance.**` line on each of Phases 0–6. Branch rebased on `main` to pull #187 into the working set before editing; clean rebase, no file overlap. + +**New decision (D10 — Runtime Contract section).** A `## Runtime Contract — How oddkit Governs the Survey` section sits between `## Summary` and `## When to Run the Survey`. Five oddkit actions are named with explicit responsibilities, fire points, and failure responses: `oddkit_preflight` (survey entry), `oddkit_gate` (six phase boundaries: 0→1 through 5→6), `oddkit_challenge` (Phase 4 sacrifice pressure-test), `oddkit_encode` (Phase 5 artifact production), `oddkit_validate` (survey completion). The section explicitly mechanizes existing canon rather than coining new rules — same posture as `klappy://canon/methods/spawned-agent-session-runtime-contract` (the Tier-2 spec doc whose pattern this section follows). + +**New decision (D11 — per-phase Governance bullet).** Each of Phases 0 through 6 gained a `**Governance.**` line as the final sub-bullet (after `**Transition.**`), naming the oddkit handle that governs phase entry, the handle that governs in-phase work, and the handle that fires at the transition to the next phase. The handoff specified "entry, transition, and exit"; the line as drafted covers all three in a single sentence per phase. + +**New observation (O9 — five-mode alignment).** The wiring uses planning-mode language consistent with `klappy://canon/epistemic-modes` (five modes: exploration, planning, execution, validation, resolution per #186) and treats a survey run as a planning-mode artifact whose Phase 4 reversion to Phase 2 stays inside planning. No three-mode legacy language survives in the new section; the runtime-contract template's framing is preserved. + +**New observation (O10 — content drift not promised).** The contract explicitly disclaims content-level coverage. A fabricated ility, a mislabeled tension relationship, or an unjustifiable sacrifice that survives `oddkit_challenge` will still pass each gate's prerequisite check. The wiring catches phase-boundary violations; peer review, downstream validation, and operator inspection remain the deepest-pressure surfaces outside the contract. + +**New learning (L5 — runtime-contract pattern is reusable).** The Tier-2 contract shape from `klappy://canon/methods/spawned-agent-session-runtime-contract` adapts cleanly to a method-level governance wiring: rename "dimensions" → "phases", swap the five-mode runtime configurations for the seven survey phases, keep the action-by-action table and the "what this does not promise" disclaimer, and add per-phase `Governance.` bullets. The pattern's portability is itself evidence that the runtime-contract framing is not specific to spawned agent sessions; it works for any process with named phase boundaries and oddkit-callable governance. + +**New constraint (C4 — retraction condition for the wiring).** The Runtime Contract section retracts if the gates fire false-positives (blocking on prerequisites present in non-standard formats) or false-negatives (passing outputs that downstream agents cannot consume). The retraction trigger is itself in the section; no separate handoff is required to revisit the wiring. + +**New handoff (H4 — closeout of #192).** PR #192 lands the survey method, the matrix, the principle, the vocabulary, the observability extension, the essay, the ledger, and now the governance wiring as a single canon package. Next surface beyond this PR: Oddie pack design (banked O-open P6), standalone personality-test article (banked O-open P5), and the `oddkit_tensions(...)` action work in `klappy/oddkit` (banked O-open P7). None are part of this PR. + +**New encode (E3 — wiring artifacts).** + +- `canon/methods/quality-attribute-tension-survey.md` updated: +1 H2 section (Runtime Contract, lines 36–64), +7 Governance bullets across Phase 0–6. Final line count 422 (was 379). +- This ledger amended with the present section. + +**No new opens.** Lane closes cleanly. Bank list (P5, P6, P7, P11) unchanged. + + + +Session triggered by Klappy sharing the original 2018 Medium article and three SMS screenshots of the conversation with Ian Lindsley earlier the same day. A fourth screenshot and direct message arrived after initial delivery, surfacing the vocabulary correction and the constraints-survey reframe. Modeled the canon work on existing patterns: definition style follows `canon/definitions/dolcheo-vocabulary`; principle style follows other tier-1 principles in `canon/principles/`; matrix style is novel (no existing matrix doc in canon to model from); essay style follows `writings/agentic-software-development`. Phase axis cross-links `klappy://odd/maturity`. External link to original Medium article preserved as canonical origin throughout the package. diff --git a/writings/software-virtues-revisited.md b/writings/software-virtues-revisited.md new file mode 100644 index 0000000..fdfb3e4 --- /dev/null +++ b/writings/software-virtues-revisited.md @@ -0,0 +1,160 @@ +--- +uri: klappy://writings/software-virtues-revisited +title: "Software Virtues, Revisited — What I Wrote in 2018, What I Stand By, and What I Owed the Reader" +audience: public +exposure: published +tier: 3 +voice: klappy +stability: stable +tags: ["writings", "essay", "software-virtues", "quality-attributes", "tradeoffs", "ilities", "tension-matrix", "revisit"] +epoch: E0008.4 +date: 2026-05-10 +derives_from: "https://medium.com/@klappy/what-are-software-virtues-and-how-to-prioritize-them-f0b583741afe (2018-09-09 — original article), canon/observations/quality-attribute-tension-matrix.md, canon/principles/quality-attributes-are-in-tension.md, canon/definitions/software-virtues-vocabulary.md, odd/maturity.md" +complements: "writings/agentic-software-development.md" +status: active +--- + +# Software Virtues, Revisited — What I Wrote in 2018, What I Stand By, and What I Owed the Reader + +> I wrote about ten software virtues and the tensions among them in 2018. Eight years later, a partner asked me which "-ilities" actually trade off against which, in which use cases. I sent him the article and told him I still stand by it. Then I realized the article only listed the tensions named per-virtue — it never built the full map. So I built it, and then realized the map was a worked example of something larger: a constraints survey for new work with agents. + +--- + +## A Question from a Partner + +A partner of mine, Ian, asked me a question this morning that I am pretty sure I have been answering for a decade in fragments without ever giving a complete answer. He wanted to know which "-ility tradeoffs" get maximized and which get minimized by the choices you make, and in which use cases the abstraction shines and in which it does not. + +My first answer was the answer I always give: the balance changes for every project, and for every stage of maturity within that project. He sent back the 💯 emoji, which is the exchange between people who have built things together long enough that we both already knew this. Then I told him I stood by something I wrote almost ten years ago on the same topic, and I sent him [the article](https://medium.com/@klappy/what-are-software-virtues-and-how-to-prioritize-them-f0b583741afe). + +That article — *Software Virtues — How to Prioritize* — has been load-bearing for me since 2018. It gets shared in slack channels, surfaced in interviews, and referenced when junior engineers ask why their pull request to add a "tiny refactor" is provoking strong opinions. I refer to it about as often as I refer to anything I have ever written. And every time I send it, I notice the same thing: it overwhelms most readers. + +That used to bother me. Now I think the overwhelm is the point. + +## What the Article Got Right + +The article enumerates ten properties every software project optimizes for at the same time: + +- Usability / Simplicity +- Originality / Innovation +- Stability / Reliability +- Urgency / Timeliness +- Efficiency / Scalability +- Maintainability / Manageability +- Versatility / Adaptability +- Interoperability +- Affordability / Sustainability +- Reality + +It calls them virtues because they are things worth wanting, and the moral framing matters. The engineering literature calls them "-ilities" or "quality attributes," and that is fine too. The names refer to the same set. + +Each section in the article ends with a paragraph naming the virtue's "natural enemies" — the other virtues it tends to erode and that tend to erode it. (The canon I am building uses "tensions" rather than "natural enemies"; the structural meaning is identical, and "tensions" carries it more precisely.) Urgency erodes stability. Originality erodes usability. Versatility erodes both. Reality grounds everything. + +That structure was the article's load-bearing claim, and I still think it was correct. **There is no single objective function for software.** A team that says it is optimizing for "fast, reliable, maintainable, secure, scalable, and innovative" software has not yet decided what it is actually doing, because those properties pull against each other along predictable axes. The team will hit the tensions whether or not it has named them. The only choice is whether to hit them oriented or disoriented. + +If you have ever sat through an architecture debate where everyone agreed about the goal and disagreed about everything else, you have lived inside this tension space. The disagreement was not really about facts. It was about which virtue each person was prioritizing, and whether they were willing to say so out loud. + +## What the Article Only Sketched + +Here is the part I noticed today, eight years later, when Ian and I started typing back and forth. + +The article names tensions inside each virtue's section. Stability has its enemies. Originality has its enemies. Versatility has its enemies. But the tensions are presented one virtue at a time. The article never assembles the full map. + +Ten virtues produce forty-five unique pairs. The article names twenty-one of them — the ones each virtue's section happened to mention. Twenty-four pairs go unnamed. Maintainability versus interoperability is unnamed. Stability versus versatility is unnamed. Efficiency versus reality is unnamed. None of the gaps are random; they are just pairs the per-virtue narrative did not happen to surface. + +When Ian said he was interested in "which ones are maximized and which are minimized by the choices, and also maybe in which use cases the abstraction shines and in which not so much," I started writing the per-virtue answer again. Then I caught myself. He was asking the question my article had set up but never finished answering. + +I told him: "I am sure using that doc as a template we could expand this to all tensions in a massive table." He sent the heart. I said: "That isn't a bad idea! That sounds like a great Klappy.dev article!" + +So this is that article. And the table — the systematic completion — is now [in canon](klappy://canon/observations/quality-attribute-tension-matrix). + +## What the Matrix Looks Like + +Forty-five rows, one per pair. Four relationship types: + +- **Mutual tension.** Both virtues erode each other. Optimizing for one reliably costs the other. (Examples: urgency vs. maintainability, originality vs. stability, efficiency vs. versatility.) +- **Asymmetric grounding.** One virtue disciplines the other without symmetric retaliation. The grounding virtue — usually reality — is not eroded by what it constrains. (Examples: reality vs. originality, reality vs. urgency.) +- **Synergy.** Both virtues reinforce each other, with mild tension only at extremes. (Examples: stability and maintainability; efficiency and affordability.) +- **Cost gravity.** Affordability's relationship with every other virtue: each virtue is purchased with effort, time, or money, so affordability constrains how much of each can be afforded. + +A third axis runs through the matrix: **phase weighting.** Each tension bites hardest at one of three project phases — proof of concept, pilot, or production. The phase axis comes from the article's "Lifecycle Priorities" section, which has since become [its own canon document](klappy://odd/maturity). Demanding production stability of a proof of concept is a category error. Tolerating proof-of-concept originality budgets in production is a different category error. The matrix tags each pair with the phase at which the tension is most consequential. + +Three uses fall out naturally: + +- **Design review.** Before committing to a design, look up the pairs most affected. For each pair, name the predicted direction of erosion and decide whether the cost is acceptable at the project's current phase. +- **Disagreement diagnosis.** When a team disagrees about a tradeoff, the disagreement is usually about which virtue is being prioritized, not about facts. The matrix gives the disagreement a vocabulary. +- **Phase audit.** When the project moves between phases, the priorities shift. The matrix names which tensions become more consequential at the new phase. + +You do not memorize the matrix. You consult it. Like a phone book. + +## What I Would Add Today + +Two things the 2018 article did not yet name, that the eight years since have made unavoidable. + +### The Article Lacked an Operator + +The original article ends with prioritization methods — MoSCoW, the Hundred Dollar Method — and treats the team's elicitation of priorities as the load-bearing step. Get everyone to vote, sum the points, sort by total. I still think those methods are useful at the right phase. I no longer think they are sufficient. + +The thing I missed in 2018 is that **knowing which virtues are in tension does not, by itself, produce good prioritization.** A team can have a beautifully complete list of virtues and tensions and still build the wrong thing, because the prioritization step requires a *discipline* the article never named. The discipline is what to do when the urgent thing is fighting the right thing, when the user-stated priority is fighting the user-observed behavior, when the executive is asking for originality and the operations team is begging for stability. + +That discipline is what I have spent the last several years building. It has a name now — Outcomes-Driven Development — and an [operating system around it](https://klappy.dev). The matrix is a map. The discipline is what makes the map worth carrying. + +### The Article Was Honest, and Honest Is Overwhelming + +I used to apologize for the article overwhelming people. I would pre-explain it, soften it, send a chat summary alongside the link. I have stopped doing that. + +The article overwhelms readers because it refuses to flatten. Most software writing offers one principle. DRY. KISS. Single Responsibility. Move fast and break things. Ship it. These are easier to absorb because they pretend the tradeoff space has one axis and one direction. The 2018 article said: there are ten things, they are in tension, your priority among them shifts by team, project, and phase, and reality grounds them all. + +That is not overwhelming because it is poorly written. It is overwhelming because the world is. + +The good news is that overwhelm is a lagging indicator. A reader who is overwhelmed by the article is a reader who has noticed the tradeoff space is real. The next move is not to simplify the article; it is to give the reader the tools to live inside the tradeoff space without flinching. The matrix is one of those tools. The maturity model is another. The mode discipline that ODD operationalizes is a third. + +You do not need fewer virtues. You need a stronger spine. + +## What I Stand By + +Eight years later, the central claims still hold: + +- Software has no single objective function. +- The competing properties are predictable, named, and finite. +- Each pair has a relationship type and a phase at which it bites hardest. +- Reality grounds everything else, whether or not the team acknowledges it. +- A framework that promises to optimize for everything simultaneously is selling you a flattened picture of a tradeoff space whose structure is tensions all the way down. + +I would change the elicitation chapter today. I would add an operator. I would point at the matrix instead of leaving the work as an exercise. But I would not retract the central frame, and I would not flatten it. + +If you have read the original article and felt overwhelmed, the matrix is what you do with the overwhelm. It is the thing the original article gestured at and never built. Now it is built — at least for the canonical ten. There are dozens more "-ilities" the article and the matrix do not yet cover. The point of the matrix is not to be exhaustive. It is to show what good looks like when the principle is applied to a concrete set, so that the principle can be applied dynamically to whatever set a project actually uses. + +Ian got the table he asked for. You get the table he asked for too. + +## What This Becomes Next + +Here is the part I did not see clearly until this morning, and that I think is actually the most useful turn in the whole eight-year arc: + +The matrix is not a reference document. It is **a constraints survey for new work with agents.** + +When you scope a new project — a new product, a new service, a new feature, a new agent task — you are implicitly ranking quality attributes whether you say so or not. Most projects fail to articulate the ranking, hit the tensions sideways, and call the resulting confusion "scope creep" or "technical debt" or "we shipped the wrong thing." The article from 2018 named the ten virtues. The matrix names the tensions among them. The constraints survey is what you do *with* the matrix when you sit down to start something new. + +The flow looks like this: + +- Pick the quality attributes that matter for *this* project. (Usually a subset of the ten, occasionally with additions from the broader universe — securability, auditability, accessibility, observability, whatever the project actually requires.) +- Rank them for the project's current phase. +- Reference the tension graph — for the canonical ten, the matrix; for any other set, generate the graph dynamically against the same principle. +- Encode the chosen priorities and predicted sacrifices as constraints the agents working on the project inherit. + +That last step is what makes this an agent-work tool rather than an architectural diagram. Agents — whether you mean LLM-driven coding agents, autonomous task runners, or the next generation of whatever this becomes — work best when the constraints they are operating under are explicit. A constraints survey grounded in the tension graph gives them a coherent answer to the question "what am I optimizing for, and what am I willing to sacrifice?" That answer is what stops an agent from cheerfully refactoring for maintainability while shipping a project whose phase calls for urgency, or from optimizing for originality on a project whose users need stability above all else. + +I did not see this clearly when I started writing the matrix this morning. I saw it when I told a partner I had built the table, and the next sentence out of his mouth was that he hates reinventing the wheel and would absolutely use the abstractions. The article — once a piece of management writing aimed at a human audience that mostly bounced off it — turns out to be exactly the right shape for instrumented agent work. Or rather: the article was the seed, the matrix is the worked example, and the constraints survey is what makes both into infrastructure. + +That last layer is what I am building next. The article is staying load-bearing for one more turn. + +## Where to Go Next + +If you have not read the original, [start there](https://medium.com/@klappy/what-are-software-virtues-and-how-to-prioritize-them-f0b583741afe). It still holds. + +If you want the systematic map: [Quality Attribute Tension Matrix](klappy://canon/observations/quality-attribute-tension-matrix). + +If you want the principle behind the map: [Quality Attributes Are In Tension](klappy://canon/principles/quality-attributes-are-in-tension). + +If you want the vocabulary the canon uses: [Software Virtues Vocabulary](klappy://canon/definitions/software-virtues-vocabulary). + +If you want the discipline that makes the map worth carrying: [the rest of klappy.dev](https://klappy.dev).