Doctrine
ORA-2026-0036
Observation
Features in this fleet consistently ship in two halves. The LIBRARY half (DB table, helper module, storage path, scorer logic) lands clean with green tests and a legitimate DONE post. The ACTIVATION half (HTTP route wiring, cron trigger, timeline emission, client UI, INSERT site) is a different ticket class, crosses repo boundaries, and requires messy UX/infra decisions — so it never gets filed. The capability sits dormant until an operator question ("can the client see this yet?") triggers re-discovery weeks or months later.
The structural cause: the fleet rewards library work because it is hard, scoped, and testable. Activation work is messy and cross-cutting. The library author is genuinely done with their slice — the activation is nobody's ticket.
Evidence
Instance 1: heartwood-photo-attribution.js (10 days dormant)
- Library committed: 2026-04-12 (
4be1ab1— "Add Heartwood proof photo attribution pipeline"). 1,474 LOC. GPT-4.1-mini room scorer, proof-packet builder, review-queue logic, import function, test fixtures. - Activation gap: Zero HTTP routes called
importBuildertrendPhotoExportfor 10 days.vercel.jsonhad 0 entries pointing at it. - Discovery trigger: Chad's direction on 2026-04-22: "Photos. Photos. Photos." ORA-01's 18-agent discovery sprint found the library was 80% of the ship work.
- Activation in progress: CAMBER-02 wrote
buildertrend-photo-import.json 2026-04-22 (4afbf2f). As of this observation,vercel.jsonstill has 0 routes for it.
Instance 2: audit_log table (indefinitely dormant)
- Schema exists: Production-ready table definition with columns for event tracking.
- Zero INSERT sites:
grep -rn "INSERT.*audit_log"across both~/gh/heartwood/and~/gh/camber/returns nothing. - Zero writers in edge functions: No reference in any
.tsor.jsfile undersupabase/functions/in either repo. - Discovery context: Surfaced during ORA-01's 2026-04-20 financial pipeline unpack as "Gap 4: proof chain has the table, it's empty."
Instance 3: beside_direct_events media promotion (7 weeks dormant)
- Library committed:
beside_direct_eventstable + reader.py + NSURLCache subsystem live since 2026-02-27. Daemon writes events continuously. - Activation gap:
media_message/ voice-note promotion tosms_messagesnever wired.grep -rn "beside_direct_events"in camber mainline (excluding worktrees) returns zero consumer code. - Discovery trigger: ORA-02's 2026-04-20 Redline Mac disconnect trace. CMB-0095/0096/0097 filed 7 weeks after library landed.
Instance 4: v_beside_direct_read_parity_72h view (weeks dormant)
- View created: 2026-02-27 in camber DB.
- Activation gap: Monitor cron that consumes the view wired weeks later by CAMBER-10.
- Same shape: SQL view ships, consumer cron ships later with no ticket connecting them.
Live in-flight instance: FLT-0241 project_change_events
- Emitter committed: 2026-04-22 (
3c56228— "Emit project change event for imported Buildertrend photos") by CAMBER-02. - Current state:
project_change_eventstable has zerojobsite_photo_capturedrows because the importer trigger has not fired yet. Redline photo-thread merge is code-complete but visually dormant. - Significance: The pattern surfaces even on actively in-flight work, within hours of the library commit. The emitter is written but the trigger that calls it doesn't exist yet.
Structural analysis
The pattern has three properties that make it self-reinforcing:
1. The library author's DONE is legitimate. They built a scorer, it passes tests, the table has correct columns. No doctrine violation occurred. The gap is invisible at DONE-post time. 2. The activation is a different ticket class. It crosses repos (heartwood library → camber cron), requires infra decisions (Vercel routes, cron cadence), and often needs UX input. No one files it because the library author's scope didn't include it. 3. No fleet signal fires on dormancy. There is no "this table has zero rows after 7 days" alert, no "this function has zero callers" lint, no "this view has no consumer" check. Dormancy is invisible until an operator asks a product question.
Recommended countermeasure
Extend ORA-2026-0029 (dying-well / generative ticket transitions) with one new bullet:
LIBRARY DISCIPLINE: If your DONE lands a table, HTTP module, shared helper, or storage path without a same-PR consumer, the FOLLOW-ONS line MUST include one of:
- An explicit activation-ticket ID (e.g., activation: HWD-0290 — wire cron + Vercel route)
- A pointer to a documented consumer plan (e.g., activation: planned — see ARCHITECTURE_LLM_AT_JOINTS slices 1-6)
- An explicit exemption (e.g., activation: none-required because <reason>)
Sprint-window exemption: During a multi-day rapid-build sprint, Layer N landing before Layer N+1 is expected. But the sprint's final DONE post must file activation tickets for any layer that did not reach a consumer by sprint end.
This is a soft audit (FOLLOW-ONS check at DONE time), not a hard PR gate. Promote to hard gate after 3-month observation period if persistent skips are observed.
Secondary counter for data-pipeline libraries specifically: Shadow-mode consumers (per ARCHITECTURE_LLM_AT_JOINTS slice 1) exercise the library daily, making dormancy impossible. But the primary counter must be general enough to cover HTTP routes, iOS rendering, cron wiring, and non-pipeline activation paths.
Credential sub-class: negative blast radius (2026-04-22, Chad amendment)
Credentials shipped without a gate are themselves a Dormant Capability — but the blast radius is negative, not zero. A dormant library wastes cycles; a dormant credential is a live attack surface. If an API key is provisioned (env var set, secret stored, service-role key distributed) before the activation gate exists (route guard, send guard, consent check), the window between provisioning and gating is an unmonitored exposure window.
Instance 1: RESEND_API_KEY provisioned for photo digest email delivery before any send-guard or consent-gate existed. Caught by operator before any send fired.
Instance 2 (near-miss, 2026-04-24): RESEND_API_KEY was live in Vercel production env vars for 2+ days. Photo digest cron schedule ("5 16 5" — Fridays 16:05 UTC) and route handler (api/project-photo-digest-send.js) existed on branch codex/hwd-0348-client-send-test-mode but NOT on main — so production was safe only by accident of unmerged branch state. The client send gate (3-level: default-blocked → test-mode → enabled, controlled by HEARTWOOD_CLIENT_SEND_ENABLED and HEARTWOOD_CLIENT_SEND_TEST_MODE env vars) also existed only on the branch. If the branch had been merged wholesale (118 files, 23,624 lines), the cron would have fired on the next Friday and sent real photo digest emails to homeowners (Lou Winship, Zack Sittler, et al.) with no consent gate. Caught by operator on 2026-04-24 — a Friday — hours before the cron window. Filed HWD-0354 CRITICAL for cherry-picking gate commits before full branch merge. Blast radius if missed: unsolicited emails to real clients from a system they never opted into.
Rule extension (strengthened 2026-04-24): The LIBRARY DISCIPLINE bullet above applies with elevated urgency to credentials. If your DONE provisions a secret, API key, or service-role credential, the FOLLOW-ONS line MUST include the activation-gate ticket — and that ticket is CRITICAL priority, not normal. Credentials without gates do not get sprint-window exemptions.
Atomicity rule (2026-04-24, Chad directive): Credential provisioning and its activation gate MUST land in the same deployment. Never provision a credential (env var, secret, service-role key) to a production environment without the gate that controls its blast radius in the same merge/deploy. "Gate on branch, credential in prod" is the failure mode — the credential is live the moment the env var is set, regardless of whether the gate code has been merged. If the gate requires branch work that isn't ready to merge, the credential MUST NOT be provisioned until the gate commits are cherry-picked or merged first.
Parent-pattern hypothesis
"Dormant Capability" may be a child of a broader pattern: Invisible Existing Work — assets that exist in the codebase but propagate no signal about their existence or state. Two known children:
1. Dormant Capability (this observation): code exists, nobody knows to call it. 2. Specs Without Prior Art (ORA-2026-0066): spec is written, nobody knows the code already exists.
Both are visibility failures. If a third sibling surfaces within 2 weeks, elevate the parent to its own observation.
Counter-example audit (2026-04-22, ORA-02)
Scanned 90 days of git history across camber, heartwood, orbit, and ora. ~40 library/table/module commits examined for consumer pairing.
Counter-example 1 (VALID): CMB-0174 LLM primitive library
- Commit: c4599488 (2026-04-21). 25 files, 2,398 LOC, zero edge function consumers.
- Why CORRECT: Explicit 6-slice rollout plan in
ARCHITECTURE_LLM_AT_JOINTS.md. FLT-0241 scope packet already referencescompose()as a planned consumer. This is intentional infrastructure-first staging with a documented consumer plan. - Rule implication: The proposed activation-ticket rule should accept
activation: planned — see [doc/ticket]as an alternative to a concrete activation ticket ID. The intent is to make the "I know a consumer is needed" signal visible, not to block legitimate staged rollouts.
Counter-example 2 (PARTIAL): Heartwood reconciliation sprint bottom-up layering (2026-04-15/18)
- 12 libraries built over 4 days. Libraries at lower layers (ops-reconciliation-state, reconciliation-readback-html, reconciliation-scoreboard) were consumed by higher layers (invoicing, dashboard) within 1-3 days during the same sprint.
- Why PARTIALLY CORRECT: Bottom-up layering during a rapid multi-day sprint is valid engineering — Layer N must exist before Layer N+1 can import it.
- Why NOT FULLY CORRECT: 4 of 12 libraries (reconciliation-gap-alerts, bt-client, heartwood-finance-auth, receipt-review-html) remain dormant after the sprint ended. The sprint completed the middle layers but left the top-level activation paths unwired.
- Rule implication: The rule should acknowledge sprint windows — during a multi-day sprint, a library landing without a same-PR consumer is expected. But the sprint's final DONE must file activation tickets for any layer that didn't reach a consumer.
No counter-examples found for: A/B rollout gating, deprecation-in-progress
Zero instances of a library landing without a consumer due to A/B rollout gating or deprecation-in-progress replacement patterns. These theoretical justifications for no-consumer PRs did not appear in 90 days of fleet history.
Additional dormant instances discovered during audit
The audit surfaced 8+ additional dormant capability instances beyond the original 4, strengthening the pattern:
financial_bill_cover_request.ts— 0 edge function consumers (26 days, consumed only by CLI script)financial_project_cost_config.ts— consumed only by financial_bill_cover_request (which itself has 0 edge function consumers)synthetics_config.ts— created 2026-02-28, subsequently deleted, never consumed by any edge functionlearning_loop_kpitables (camber_metrics_pick_time, camber_metrics_write_actions, camber_metrics_undo_events) — 0 INSERT sites (49 days)reconciliation-gap-alerts— 0 consumers (post-sprint)bt-client.js— 0 consumers (post-sprint)heartwood-finance-auth.js— 0 consumers (post-sprint)receipt-review-html.js— 0 consumers (post-sprint)
Libraries that shipped WITH consumers (rule is compatible)
~12 commits shipped library + consumer in the same PR: lineage.ts (6 edge functions), time_resolver.ts, assistant_feedback, redline_repair_events, time_resolution_audit, edge_secret_contract, alias-system, evidence-assembler, plugin_loader + plugin_contract. The proposed rule would not have blocked any of these.
Audit verdict
1 valid counter-example, 1 partial. Rule is NOT over-broad. Refinement needed: accept activation: planned — see [doc] as an alternative to a concrete ticket ID, and acknowledge sprint-window layering as a temporary exemption with a final-DONE activation-ticket obligation.
Retroactive fleet audit (ORA-0035, 2026-04-23)
Full-fleet scan: ~880 surfaces across 4 repos. 10 new dormant instances found beyond the original 5, for 15 total known dormant capabilities. Breakdown: 2 dormant _lib helpers, 2 dormant API routes, 3 dormant edge functions, 3 dormant scripts. Orbit and ORA were clean.
Top 3 activation priorities: (1) photo review pipeline wiring (H4 apply-photo-review-decisions.js), (2) audit regression runner (C1 audit-regress-runner), (3) open-loop silence detection consumer (C4 open_loop_silence_candidates.sql).
Full report: /private/tmp/ora-0035-audit-report.md (ephemeral) — findings filed as activation tickets per ORA-2026-0036 doctrine.
See also
- ORA-2026-0029 — dying-well generative ticket transitions (this observation extends it)
- ORA-2026-0066 — synthesis dispatches propagate unverified schema assumptions (sibling pattern)
- ORA-2026-0021 — no scope creep on dispatches (complementary discipline)
- FLT-0241 — BT photo scrape (live instance of this pattern)
- FLT-0241 — BT photo scrape (live instance of this pattern)