Development Methodology Brief¶
Version: 1.0 — April 2026
Status: Living document; update alongside this.i when practice evolves.
This project is developed using an emerging AI-assisted development methodology with structured intent artifacts. The methodology is actively being designed in two public projects:
- dhh1128/intent — the Intent Layer: a structured, version-controlled representation of human purpose that sits above code and is the true source of truth for design decisions.
- dhh1128/ai-dev-practices — organizational design principles for teams working with AI coding assistants.
Using this methodology for contributions is encouraged but not required.
For AI agents: If it seems useful to understand the methodology more fully, read
docs/origin-platform/intent-briefing.md in this repository. For the full intellectual lineage
and design rationale, you may also prompt the user for permission to read
../intent/project-constitution.md and ../ai-dev-practices/constitution.md.
1. The Intent Layer and this.i¶
this.i at the root of this repository is the source of truth for design decisions — not
supplementary documentation. Code is a derived artifact. For the full format spec, node types,
marks, and the reconciliation cycle, see intent-briefing.md §2–8.
Node anatomy¶
Every entry in this.i is a node. The minimum valid form:
Decision Name = decision:
id: p4wn7k # random base32, 6–12 chars — NEVER a semantic label like 'auth-decision'
why: >
Chose X over Y because Z, accepting tradeoff W.
Optional but common fields: children: (nested nodes), tensions: (recorded conflicts).
The key line encodes the name and type: Name = [marks...] type:. IDs must be opaque — AIs
consistently default to meaningful labels, which is always wrong. A valid ID matches
^[a-z2-7]{6,12}$.
Cold-start epistemic stance¶
When encountering this.i at the start of a new session:
- The tree describes a destination, not just current state. Nodes may describe completed work
or planned futures; the
stage-statusfield on a node records which (planned,in-progress,done, etc.). Read it before assuming a node reflects existing code. - Tension resolutions are binding. Implement consistently with recorded resolutions. Do not re-open them or silently resolve them differently.
whyfields are primary evidence. When touching any node, thewhyis the most important thing to read.deviation:nodes are the complete list of approved gaps. Discovery is by node type (everydeviation:node in the tree), not by a numbered list; any gap not represented by adeviation:node is a defect requiring approval before acceptance. Some files still use the legacycd-Nconvention — migrate each such node to adeviation:node with a fresh opaque base32 id, populatedeviates-from:/scope:/why:/approved-by:, and leave a YAML comment# was: cd-Nnnnon the node's name line recording the old id.- Before making any decision not already in
this.i, record it there first. A decision not in the intent tree is not yet made — it is implicit, which is exactly what the intent layer exists to prevent.
2. The why Field and the Rebuttal-Surface Standard¶
The why field is the most important field in every node — authored at the moment of decision,
it is evidence that the decision was genuinely understood when it was made. For the theory behind
why this matters, see intent-briefing.md §6.
The rebuttal-surface standard¶
A why field is complete when a challenger can identify specifically what they disagree with.
- Meets the standard: "Chose X over Y because Z, accepting tradeoff W."
- Does not meet the standard: "Chose X for performance."
- Does not meet the standard: "Standard practice."
- Does not meet the standard: A sentence that restates the node name.
The test: can a reviewer say "I disagree because ___"? If the why is too vague to locate a
specific point of disagreement, it hasn't communicated the reasoning — it has only signaled that
reasoning exists somewhere.
When the standard matters¶
The rebuttal-surface standard is most valuable for:
- Decisions that constrain future options
- Tension resolutions (recorded conflicts between goals)
- External contracts (wire codes, DSL keywords, API surfaces, serialization formats)
- Deviations from project standards (the
deviation:node type — see §6)
It is less critical for simple decisions where no reasonable person would choose differently. Apply judgment; the operative question is whether a future reader — human or AI — would benefit from knowing the actual reasoning.
3. The this.i Update Trigger¶
"No architectural decision without recording it in this.i first" is too vague to apply
consistently. Here is the concrete trigger list. Any of these events requires a corresponding
node in this.i before the code change is pushed:
- Any new public type: class, interface, enum, sealed hierarchy member
- Any new class or interface that embodies a behavioral invariant (even if package-private)
- Any new external contract: wire codes, DSL keywords, API surface changes, serialization formats
- Any tension identified between competing goals or constraints
- Any deliberate decision not to do something that might seem obvious ("why not" decisions)
- Any deviation from a project standard — coverage, dependency rules, Java version, test
discipline. These become
deviation:nodes (see §6). - Any rename of a significant type or concept
If you are uncertain whether something qualifies, err toward creating a node. A node that turns out to be unnecessary costs little. An implicit decision costs a great deal when it must later be understood by someone who wasn't in the room.
4. Naming as a Design Signal¶
Names are the most concentrated form of communicated design intent. A name that doesn't survive inspection is a signal the design isn't finished.
What this means in practice¶
At stage boundaries, review all names introduced since the last gate. For each name ask: - Does this name say what the thing is, not just what it does? - Is it consistent with the vocabulary already established in the codebase? - Does it introduce a metaphor or analogy that will confuse readers who encounter it without context? - Does it encode a correct mental model of this thing, or the model we had when we first wrote it?
A name that requires a comment to understand is a design smell. If the Javadoc sentence restates the name in other words, the name is fine. If it explains what the thing "really" is because the name is misleading, the name should change.
A change in understanding should often produce a rename. When the model of what a class represents evolves during development, the name must evolve with it. A stale name is technical debt that compounds faster than most other kinds, because every subsequent reader forms a wrong model from it.
Consistency beats cleverness. If the codebase uses Rule in four places for a related family
of concepts, a new class in that family should also use Rule unless there is a recorded reason
not to.
Names are proposals. During the speculative interview (see §5), surface any names you intend to introduce. The human may have context — from domain vocabulary, from other systems, from prior conversations — that makes a better name obvious. Don't finalize a name you invented in isolation.
5. The Speculative Interview¶
The speculative interview is the required process before any phase of implementation. Its purpose
is to ensure that design decisions are made explicitly, recorded in this.i, and approved by
the user before code is written — not discovered during or after.
Steps:
- Trace the entire implementation mentally — every class, method, test. Do not generate code yet.
- Identify every consequential fork — places where different answers lead to different architectures, different APIs, or different test strategies.
- Surface all forks to the user in a single structured conversation — architectural decisions first, then API surface, then naming, then test strategy.
- Record the user's answers in
this.ibefore writing a line of code. Each decision becomes a node with anid:and awhy:meeting the rebuttal-surface standard. - Present the test plan for approval before implementing.
Commit discipline for this.i. The this.i update that records a decision must be committed
on its own — never bundled with the code change that implements the decision — and the this.i
commit must appear earlier in git log than the code commit it justifies. "Recorded before writing
code" is not satisfied by an edit in the same commit as the code; the commit boundary is the
verifiable artifact. This ordering forces the speculative interview to actually happen — the human
cannot rubber-stamp an AI-drafted this.i retroactively when there is no code yet to retroactively
justify — and it produces an audit trail in which the absence of a prior this.i commit for a
significant code change is a visible defect rather than a hidden one.
Proportionality: The depth of the speculative interview should be proportional to the blast radius of the change. A new class with an external API warrants the full five-step interview. A method body change within a private class that has no external surface may not. The §3 trigger list is a good proxy for "blast radius is large enough to require the full interview."
For the theory behind the speculative interview and why the mental-trace step matters, see intent-briefing.md §11.
6. Approved Deviations (the deviation: Node Type)¶
Any deviation from a project standard — 100% branch coverage, no runtime dependencies, language
version, test discipline, etc. — must be approved by the user and recorded in this.i as a
deviation: node.
deviation: is a first-class node type, peer to decision:, constraint:, and tension:. Its
id: is opaque base32 like every other node — no semantic prefix, no sequential numbering. The
discoverability of deviations comes from the node type, not from the id.
Required fields¶
Permission to Skip Branch X Coverage = deviation:
id: q7m2px4n # opaque base32, 6–12 chars
deviates-from: 3cbfnobm # opaque id of the standard's node
scope: >
Exactly what is exempted, in narrow terms. A reader must be able to tell
whether new code falls inside or outside the exception without guessing.
why: >
Rebuttal-surface rationale (see §2). A challenger should be able to identify
the specific point they disagree with.
approved-by: <user>, <YYYY-MM-DD>
Placement and linkage¶
The deviation: node lives as a child of the standard it relaxes — preserving the parent-child
relationship that the legacy cd-N "under the relevant parent" rule served. The deviates-from:
field carries the opaque id of the standard's node, so the linkage survives even if the deviation
is later moved, surfaced in a query, or cross-referenced from another part of the tree.
Discovery¶
The complete list of approved deviations is always findable by node type. No central list to maintain, no numbering to keep in sync. In practice:
or simply by reading every node whose type is deviation:.
Legacy migration¶
Some existing this.i files and related code still use the legacy cd-N convention; any AI maintaining such a file must migrate each cd-N node by changing its type to deviation:, minting a fresh opaque base32 id, populating deviates-from: / scope: / why: / approved-by:, and leaving a YAML comment # was: cd-Nnnn recording the old id on the node's name line.
Defect status¶
A deviation without a deviation: node is a defect, not a judgment call. The AI cannot
unilaterally decide that a gap is acceptable; that requires the user's explicit approval and a
recorded rationale.
7. TDD Discipline¶
Read the tests. Run the tests. Make your change. Run the tests again.
New code requires tests written before or alongside the implementation — never after. The test plan must be approved by the user in the speculative interview before implementation begins. The test suite is the primary specification and the primary evidence of developer comprehension; if the tests aren't written first, the primary specification was never reviewed.
8. Tech Debt Documentation¶
When you identify technical debt during development — a known shortcut, a structural compromise, a workaround for an external constraint — mark it in code at the point of the debt:
// TECH_DEBT: <name, e.g., "Refactor X to Y"> [VC-NNN]
// Optional explanation — especially what future feature or maturity milestone depends on resolution.
When a Jira ticket is required (include the [VC-NNN] reference):
| Condition | Action |
|---|---|
| Small/local cleanup | Comment only |
| Cross-module impact | Comment + Create ticket (mandatory) |
| Performance/security risk | Comment + Create ticket (mandatory) |
| Blocks future work | Comment + Create ticket (mandatory) |
Add the tech-debt label to every Jira ticket created. When debt is paid off, remove the comment
and close the ticket. Undocumented debt is more dangerous than documented debt: the next developer
will fix it incorrectly, not knowing it was intentional.
Do not leave raw TODO or FIXME comments in committed code. Convert them to TECH_DEBT:
comments (if they represent real debt) or resolve them.
9. Gate Approval and Phase Boundaries¶
A phase boundary is an explicit, named checkpoint. No code may be pushed to the remote until the gate is approved by the user. Commits may happen freely at any time; pushes require gate approval.
Gate criteria (all must be satisfied)¶
mvn testpasses with no failures.- Coverage satisfies the 100% branch target, or all gaps have approved
deviation:nodes. this.ihas nodes for all changes since the last gate that meet the trigger criteria in §3.- All new
whyfields meet the rebuttal-surface standard (§2). - All new names have been reviewed for clarity, consistency, and model accuracy (§4).
- Any technical debt introduced or discovered during this phase is marked with
TECH_DEBT:comments, and Jira tickets are created where required (see §8). - the user has explicitly approved — the gate must be explicitly requested; it is not implicit in a passing test run.
- The adversarial review question has been asked and answered: "Is now an appropriate time for adversarial review?" The AI should recommend an answer, but the user decides. If yes, adversarial review (§10) must be completed and all findings addressed before the gate closes.
How to request a gate¶
State explicitly: "I am requesting gate approval for [phase name]. Tests pass. Coverage is [X
with Y approved deviations]. this.i updates are [description]. Is now an appropriate time for
adversarial review? My recommendation: [yes/no and brief rationale]."
Then wait for the user's explicit answer. Gate approval is never assumed.
10. Adversarial Review¶
Adversarial review is a structured challenge of the code and design by AI in named critic roles. Each role must have a fresh context window — it must not have read the author's reasoning, or the criticism is compromised. The objective is to find what the author missed, not to confirm what the author found.
Named critic roles¶
| Role | Prompt focus |
|---|---|
| Security Hawk | What assumptions does this code make about its environment that could be violated? What trust boundaries are crossed? What data is handled insecurely? |
| Maintainability Expert | Given this code and no other context, what would a developer unfamiliar with it misunderstand, get wrong, or want to change without realizing why it exists? |
| Testability Hawk | What production code is structured in a way that makes an entire category of tests impossible or misleading? What does the test suite allow to ship undetected? |
| Compliance Auditor | If something went wrong — a breach, a regulatory inquiry, a data loss event — could this organization reconstruct what happened and demonstrate that appropriate controls were operating? |
| DevOps Engineer | Will this survive production? Are CI, deployment, and observability correct, automated, and version-controlled, or are there manual steps and untracked state? |
| UX Guru | What would a real user experience under non-ideal conditions? Where does the UI architecture make good UX impossible regardless of visual fixes? (Applicable only to services with user-facing interfaces.) |
| Performance Hawk | What code is categorically wasteful regardless of load? What patterns will become expensive at realistic scale? Where are the hot paths, and are they measurable? |
Handling findings¶
- Findings are ranked by severity: critical, significant, minor.
- The human author must explicitly accept, defer, or rebut each finding at severity critical or significant.
- Accepted findings are resolved before the gate closes.
- Deferred findings become tension nodes in
this.iwith a recorded rationale for deferral. - Rebuttals become tension resolutions in
this.i— thewhymust meet the rebuttal-surface standard.
Adversarial review is not always warranted. For small changes with narrow blast radius, the user may decide it is not appropriate. The point of the gate question is to make the decision explicit and recorded rather than silently skipped every time.
11. PR-Level Obligation¶
Any pull request that introduces new public types, new external contracts, or new behavioral
invariants must include corresponding this.i nodes. A PR is incomplete in either of
two ways: (a) the required nodes are missing entirely, or (b) the required nodes are present
but were committed in the same commit as the code they justify, or in a later commit. Per §5,
each this.i update is its own commit and must precede the code commit that depends on it.
Both failure modes are defects, not stylistic preferences.
This is a reviewer responsibility, not only an author responsibility. Reviewers should inspect
this.i as part of every PR review, the same way they inspect tests. The questions to ask:
"For every significant new abstraction or external contract in this PR, is there a node in
this.i with an id: and a why: that meets the rebuttal-surface standard? And does
git log show that node's commit landing before the code commit that depends on it?"