ADR 0005 — Operating Model terminology and structure
Status
Accepted 2026-04-29. Implemented across the repo through Commits 1, 2, and 3 of the operating-model refactor.
Context
The repo's original vocabulary was Loop → Activity Area → Workflow. Three problems emerged as the spec matured.
First, "Activity Area" implied a coherent grouping of activities-by-type but the term itself didn't enforce that constraint. The boundary between an activity area and a goal-shaped sequence got fuzzy in practice — for example, Match, nurture and conversion was simultaneously a responsibility cluster (matching, nurturing, converting are all things the loop does) and a progression sequence (match comes before nurture comes before conversion). Two readers would walk away with two different mental models.
Second, "Workflow" collides with established orchestration-tooling parlance — Temporal workflows, Airflow DAGs, n8n workflows. Once a runtime is in scope (and it is, given the deliberate signal/closed_state/depends_on/automation fields in the frontmatter), the collision becomes load-bearing: are we describing org-level units of work, or runtime objects in a specific execution engine? Two different things, same word.
Third, the model had no clean place for a journey — a goal-shaped sequence of work that crosses several activity areas in pursuit of a single outcome. The Viewing Journey was the prompting case: intent capture starts in conversational engagement, anchoring and booking start in conversion, viewing-coordination is in conversion, post-viewing decision capture is in conversion, handoff terminates the journey. Trying to call this a sub-loop dilutes "loop" (a loop has a single accountable owner end-to-end; the Viewing Journey doesn't add an owner). Trying to call it an activity area conflates progression with responsibility. The model was missing a construct.
Decision
The operating model has a four-layer spine plus an orthogonal overlay:
Spine — Org → Loop → Domain → Operation
- Loop — a full accountable chain from signal to closed outcome, owned end-to-end by one person. Six exist: renter, operator, platform, financial, fundraise, strategy. Definition unchanged from prior versions.
- Domain — a responsibility-shaped grouping of work within a Loop. Classifies the type of work being performed. Domains do not represent progression or goals. Was previously called "Activity Area".
- Operation — the smallest executable, signal-driven unit in the system. Has a signal, a closed state, depends_on, and an automation level. Was previously called "Workflow".
Overlay — Loop → Journeys → references Operations across Domains
- Journey — a goal-directed, ordered composition of Operations within a Loop, used to define progression toward a specific outcome. Journeys reference Operations across one or more Domains. They do not contain or own Operations, do not introduce ownership, and do not execute work. They define what correct progression looks like and what must happen if progression stalls. The Loop owner remains accountable for journey outcomes.
Naming rationale
- Domain over Activity Area: tighter semantic load. A domain is a bounded responsibility area; "activity area" was too generic.
- Operation over Workflow: deliberate disambiguation from the Temporal/Airflow tooling sense of "workflow", which becomes load-bearing once a runtime is on the table. "Operation" reads as an atomic unit of execution in this repo's specific operating model.
- Journey over alternatives (process, thread, sequence, arc): "journey" reads naturally as goal-directed and ordered, and is already in common usage for renter/customer arcs in this product space.
Constraints (non-negotiable)
These constraints are part of the decision, not implementation detail.
- Journeys MUST NOT contain Operations. They reference by ID.
- Journeys MUST NOT duplicate Operation definitions.
- Journeys MUST NOT introduce ownership. The Loop owner is accountable for journey outcomes.
- Journeys are read-only orchestration constructs from the Operations' perspective — adding a journey does not change any Operation.
- Domains MUST NOT be reorganised around journeys. The spine stays responsibility-shaped; the overlay carries the goal shape.
- Operations MUST NOT be duplicated across Domains. Each Operation lives in exactly one Domain.
Identifier scheme
- Loops:
<loop-name>(e.g.renter-loop). - Domains:
<loop-name>.<domain-slug>(e.g.renter-loop.matching). Letter-based prefixes (a–g) retired. - Operations:
<loop-name>.<domain-slug>.<operation-slug>(e.g.renter-loop.matching.perfect-fit-alert). - Journeys:
<loop-name>.journeys.<journey-slug>(e.g.renter-loop.journeys.viewing-journey). - Platform capabilities:
platform.<capability-slug>(unchanged).
Validator behaviour
verify_org.py enforces the schema:
- Files of
type: loop,type: domain,type: journeyare recognised; their IDs and structure are validated. - A Domain's
operations:list defines Operation IDs. A Journey'sstages[*].operations[*].idmust resolve to a real Operation. A Journey'sstages[*].planned_operations[*].idmust NOT yet exist and must carry acommit:field naming a future commit number. - Audit passes flag any letter-prefixed IDs (the old scheme) and any "Activity Area" / "Workflow" wording so regressions are loud.
Consequences
The repo now has a clean separation between what classifies the work (Domain), what executes the work (Operation), what owns the work end-to-end (Loop owner), and what defines correct progression (Journey). Each construct has one job; the constructs do not overlap.
Runtime work — when it lands — has a clean contract to satisfy. The Operation frontmatter (signal, closed_state, depends_on, automation) is the runtime-binding contract. Journeys are the orchestration overlay a runtime can use to enforce progression invariants without owning the Operations themselves.
Cross-loop journeys (e.g. the Closing Journey, which crosses Renter, Operator, and Financial loops) are explicitly allowed. Ownership stays with the Loop the journey belongs to (the loop most directly responsible for the outcome).
This rename is the largest single structural change in the repo's history. The validator's regression guards exist specifically because mixing the old and new vocabulary would silently produce a model nobody understands.
Alternatives considered
- Keep "Activity Area" and "Workflow", add "Journey". Rejected. The two original problems (fuzzy boundary between activity-shaped and goal-shaped clusters; collision with orchestration-tooling parlance) would persist. Adding Journey alone doesn't solve them.
- Promote Journey into the spine (Loop → Domain → Journey → Operation). Rejected. Journeys would have to contain Operations, which couples Operations to a specific progression and prevents reuse across journeys. Operations would also gain implicit ownership inside their journey, eroding the single-Loop-owner guarantee.
- Keep "Workflow", rename "Activity Area" to "Domain" only. Rejected. The Workflow/Operation collision remains, which becomes painful once any orchestration tooling is on the table. The two renames are connected; doing one without the other is half a fix.
- Reorganise Domains around Journeys (e.g. give the Renter Loop a domain per journey). Rejected. This collapses the responsibility/progression distinction we just opened up — and makes shared Operations like
engagement.stuck-conversation(used by every journey's failure-handling) impossible to home cleanly.
Related
- ADR 0001 — Loops over functional teams — establishes the loop concept this ADR builds on.
- ADR 0002 — Conversation as the unit of interaction — references "workflow" prior to this ADR; rewritten in Commit 1's cascade.
- ADR 0003 — Concierge as defining feature — references "workflow" prior to this ADR; rewritten in Commit 1's cascade.
- ADR 0006 — Rentiful owns viewing booking — uses the new vocabulary from inception.