Skip to main content

ADR 0013 — Canonical Pattern: Scope with State Channel plus Template Archetypes

Context

The Foundation Hardening's Wave 2b dispatch authored six resolver-decision ADRs in parallel (R1, R2, R3, R5, R8, R9, recorded as ad-0007 through ad-0012). Four of those six commit new gameplay primitives that share an underlying shape: ./ad-0007-quest-thread-and-mission-scope-primitives.md commits scope QuestThread plus LifecycleState plus template<QuestThread>; ./ad-0008-pressure-to-front-emergence-scope-state-machine.md commits scope ThreatSource and scope FrontCandidate plus Severity and AggregatedSeverity channels (and the existing Front scope already follows this pattern via its committed FrontStatus channel); ./ad-0009-realm-scope-and-polity-rank-orthogonality.md commits scope Realm plus PolityRank channel; ./ad-0010-act-progression-actstate-scope.md commits scope ActState plus CurrentAct channel.

The pattern is repeated four times in parallel and is the implicit canonical shape for every new persistent gameplay primitive added by Foundation Hardening. Without an explicit pattern ADR, the pattern is discoverable only by reading all four ADRs together and inferring the shared shape. Future Foundation Hardening or post-Hardening waves under deadline pressure are likely to invent a fourth primitive shape (e.g., "state-as-Modifier-flag" or "state-as-host-field-only" or "state-as-tag-set") for the next new gameplay primitive, exactly the drift the no-fallback redesign-propagation rule forbids.

The pattern is workspace-internal Valenar authoring convention over the existing SECS primitives (scope, channel, template, Modifier per .claude/rules/secs-concepts.md). It is not a new SECS engine pattern and does not belong in the workspace-root docs/decisions/ engine ADR tree per ./ad-0004-lore-adr-folder.md. Documenting it only as informal guidance in .claude/rules/valenar-generation.md would not give it the load-bearing authority it needs to prevent future drift; a rule file is not the canonical decision record for a pattern this structurally load-bearing.

Decision

Every new Valenar gameplay primitive added in Foundation Hardening (and post-Hardening waves that introduce a persistent gameplay primitive) uses the following canonical shape:

(a) Scope declaration. A scope X declaration carries the persistent identity, the binding-propagation root for related scopes that walk to it, and the row-instance lifecycle. The scope is the queryable entity for events, Modifier attach / detach, dynamic quest pressure binding, and Journal readback.

(b) State channel. One or more channels on the scope carry the current lifecycle position. Names follow the pattern: LifecycleState, Status, Rank, Phase, Severity, or another domain-appropriate noun consistent with the existing FrontStatus and OperationStatus precedent. The state channel uses a typed enum where the lifecycle has discrete rungs (LifecycleState, PolityRank) and uses a numeric channel where the lifecycle is continuous (Severity). The channel is read via the 6-phase channel resolution pipeline per .claude/rules/secs-concepts.md.

(c) Template archetypes. One or more template<X> archetypes supply authored content rows: identity, narrative metadata, declared relationships to other scopes, and the binding rules for how a scope instance gets created from the archetype. The scope row references the archetype via a DefinitionTemplateId field or equivalent typed template id.

The three components together — scope identity, state channel, and template archetype — form the canonical Valenar primitive shape.

Instantiations of the pattern committed by parallel Wave 2b ADRs:

  • ./ad-0007: scope QuestThread plus LifecycleState (QuestThreadLifecycleState enum) plus template<QuestThread>. Also scope Mission plus LifecycleState (MissionLifecycleState enum) plus template<Mission>. Two pattern instantiations in one ADR.
  • ./ad-0008: scope ThreatSource plus Severity channel plus template<ThreatSource> (the archetype is implicit in the ThreatSource.Kind enum's per-kind authored data; the explicit template<ThreatSource> declaration follows the same shape). scope FrontCandidate plus AggregatedSeverity channel; archetype is implicit at the FrontCandidate layer since FrontCandidates are generated from ThreatSource clusters rather than from an authored catalog. The existing scope Front (already committed in ../../systems/gd-fronts.md) follows the pattern via FrontStatus and the existing Front archetype shape.
  • ./ad-0009: scope Realm plus PolityRank channel. Archetype is implicit because Realm is a singleton and its initial state is authored as campaign-start data rather than as a per-instance template.
  • ./ad-0010: scope ActState plus CurrentAct channel. Archetype is implicit for the same singleton reason as Realm.

Two parallel Wave 2b ADRs deliberately do NOT instantiate the pattern, and the difference is documented as intentional:

  • ./ad-0012: conditions and injuries are Modifier templates, not scopes. Modifiers are transient effect bundles per .claude/rules/secs-concepts.md; they describe mutable state on named characters that decay, refresh, or clear. The persistent identity is the named character (already a scope) and the condition / injury is a Modifier attached to that scope. This difference is intentional: the pattern committed in this ADR applies to persistent gameplay primitives that need their own identity (QuestThread, Mission, ThreatSource, FrontCandidate, Realm, ActState), not to transient effects attached to an existing identity.
  • ./ad-0011: placeholder marker conventions are authoring policy, not a primitive shape. The True Harm placeholder convention applies to how deferred names are referenced in prose, header lines, and typed-id sketches; it does not introduce a new gameplay primitive and therefore does not instantiate the scope + state-channel + template-archetype pattern.

Alternatives Considered

Leave the pattern implicit across the four ADRs (no cross-cutting pattern ADR). Rejected because implicit-across-multiple-ADRs patterns cause future drift. Each later wave reading one of the four ADRs in isolation has to re-derive the pattern from a single example. Under deadline pressure, that re-derivation produces parallel shapes (state-as-tag, state-as-host-field, state-as-Modifier- flag) that violate the no-fallback redesign-propagation rule. An explicit pattern ADR turns the convention into a load-bearing authority a verifier can check.

Promote the pattern to a workspace-root ADR under docs/decisions/. Rejected because the pattern is a Valenar coding convention over existing SECS primitives, not a SECS engine pattern. The split between Valenar-local ADRs and workspace-root engine ADRs is committed at ./ad-0004-lore-adr-folder.md, and this ADR fits the Valenar-local layer.

Document the pattern only in .claude/rules/valenar-generation.md (a guidance rule file). Rejected because rule files are not the canonical decision record for a load-bearing pattern. The four Wave 2b ADRs and any later pattern instantiations need a single citable ADR to reference; valenar-generation.md may cross-reference this ADR but does not replace it.

Tenets Applied

  • "Future-proofed solutions only." A documented canonical pattern prevents future waves from inventing a fourth primitive shape under deadline pressure.
  • "When you patch the same subsystem 3+ times, the original design is wrong" (inverted application). The pattern is repeated four times intentionally; documenting it explicitly is the redesign that prevents the next wave from patching with a fifth ad-hoc shape. Explicit-pattern-ADR is the architectural fix; implicit-pattern is the silent drift.
  • "No hacks, no shortcuts, no workarounds." A shortcut here would be to invent a state-as-tag-set fallback the next time a primitive is added; this ADR pre-empts that shortcut by committing the canonical shape.
  • "Research before designing." Documented-canonical-pattern records in shipped projects (Unity AddressableAsset pattern doc; Witcher 3 quest pipeline internal authoring conventions; CK3 trait / Modifier / Story cycle authoring conventions in Paradox's internal docs) all elevate repeated authoring patterns to citable authority. This ADR commits Valenar to the same discipline.

Runtime Backing Status

Status at this ADR's acceptance time: contract-only (the pattern itself is authoring guidance, not a runtime entity; individual instantiations carry their own runtime-backing status).

  • Host/runtime owner: not applicable — the pattern documents existing SECS primitives (scope, channel, template) and does not introduce a new runtime entity. Each pattern instantiation (ad-0007 through ad-0010) carries its own host data classes per its own Runtime Backing Status section.
  • Generated/.secs owner: not applicable for the pattern itself; each instantiation declares its own scope, channel, and template archetypes per its own ADR.
  • Read-model/UI owner: not applicable; the pattern is authoring convention.
  • Tests: any structural test that walks the lore ADR tree to verify the pattern is correctly applied is added during the Wave 5a runtime-backing wave's verifier pass.
  • Known gaps: no runtime gap — the pattern is contract-only by its nature as a cross-cutting authoring convention.
  • Illegal fallback behavior: any new Valenar persistent gameplay primitive committed after this ADR that uses a state-as-tag-set, state-as-host-field-only, state-as-Modifier-flag, or state-as-implicit-host-store shape — without superseding this ADR — is a tenet FAIL.
  • Next closure wave: not applicable; the pattern stays contract-only permanently as authoring guidance.

Glossary Propagation

No new glossary terms are added by this ADR. The pattern documents existing SECS vocabulary (scope, channel, template, Modifier) per .claude/rules/secs-concepts.md and existing Valenar vocabulary (LifecycleState, Status, Rank, FrontStatus, OperationStatus, PolityRank, CurrentAct, Severity). Future glossary entries for specific pattern instantiations are propagated by the instantiating ADR (ad-0007 propagates QuestThread / Mission etc.; ad-0008 propagates ThreatSource / FrontCandidate etc.; ad-0009 propagates Realm / PolityRank etc.; ad-0010 propagates ActState etc.).

Consequences

For Foundation Hardening waves that add new persistent gameplay primitives, the pattern is binding. Any new primitive must declare its scope, its state channel(s), and its template archetype(s) — or explicitly document why the pattern does not apply (e.g., transient effect bundles use Modifiers per ad-0012; authoring policy decisions use ADR text without a runtime shape per ad-0011).

For post-Hardening waves (Wave M content authoring; specific lane content for the seven cross-act lanes; later autonomous Crown-AI emergence; per-act gate-spec authoring), the pattern remains binding for any new persistent primitive. The pattern does not apply to content rows authored as template instances against an existing archetype — those are template-data per the "Templates are data" tenet and use the existing SECS template primitive.

For the verifier, any new ADR that commits a fifth primitive shape without explicitly superseding this ADR is a tenet FAIL. Any doc that introduces a new gameplay primitive outside the four pattern components (scope, state channel, template archetype, optional Modifier attachments per ad-0012) is also a FAIL.

For ./ad-0012-character-conditions-and-injuries-as-modifiers.md and ./ad-0011-true-harm-placeholder-convention.md, the explicit "NOT instantiated by" callout above is the binding documentation that those two ADRs intentionally do not follow the pattern. The shape difference is by design, not by oversight.

References