- Status: approved (2026-08-15)
- Priority: EXT — non-blocking for the core, blocking for YSD-19107/19108
- Decision owner: @GreyChimp
- Drafted: 2026-08-15 by Claude Code (Opus 5)
- Approval: ruled by @GreyChimp on 2026-08-15; outcome recorded in decision-log.json; review by 2027-08-15
Question#
Phase 5 defers two capabilities behind one condition: build them only if learner research shows they solve a demonstrated need, and only then go beyond the policy-safe core. Does the need exist, and are they to be built for the first release?
What the gate says today#
capabilityNeedVerdict over the recorded research
(src/product/deferred-capability-research.ts) returns, for both:
| capability | verdict | gate standing | construction |
|---|---|---|---|
| mobile-review-companion | unproven |
decided-after-build |
partially-built |
| offline-note-queue | unproven |
decided-after-build |
built |
Three facts in that table matter more than the ruling.
unproven is not not-justified. The gate's vocabulary separates "the
evidence shows the core does the job" from "nothing demonstrates it yet, which
is an absence rather than a refusal". The programme holds no learner research
about either capability, so only the second is available, and this decision was
recorded against the verdict the evidence earns rather than the stronger one it
would be convenient to write. The distinction is asserted in
deferred-capability-research.spec.ts, in both directions.
The absence is structural, not a backlog item.
planesThatCanDemonstrateAwayFromWorkspaceNeed returns exactly one plane —
consented-research. The need at issue is for work done away from the
workspace, and every other observation plane can only see somebody who is in
it: a learner who wanted to review on the train and therefore did not review
emits no session, files no ticket and appears in no funnel. Product analytics
cannot close the gap either, because YSD-17072 permits metrics to carry
interaction-shape and record-shape and nothing else, so analytics can
establish that work stopped and never why. Consented research needs a panel,
and YSD-18002's recruitment has not happened.
Both gates fired after the build. The offline note queue shipped under
YSD-15094 and YSD-17034; mobile-companion is one of the four rendering
surfaces of the deep-link contract shipped under YSD-15092. The decision this
gate exists to make was, for both, partly made by construction. That is recorded
rather than smoothed over: gatesDecidedAfterBuild names them and
assertGateStillOpen refuses to pretend the gate can authorize what has already
shipped.
Recommendation#
Do not build beyond the policy-safe core in the first release, for both
capabilities, and record the verdict as unproven rather than not-justified.
Ruling#
Approved as recommended by @GreyChimp on 2026-08-15: do not build beyond the policy-safe core in the first release, for both capabilities.
For the companion, the core already opens the web workspace in a phone browser under the same rights enforcement, and a companion would move rights-restricted material and a learner's private notes onto a personal device to serve a need nobody has observed. For the queue, the ruling governs what comes next; it does not retroactively authorize what is already here.
Recorded in code as DEFERRED_CAPABILITY_RULINGS, with the verdict and the
construction state as they stood on the day of the ruling, so
rulingStanding reports superseded-by-evidence the moment research justifies
either one and construction-moved if the tree is built past the ruling. A
ruling that cannot go stale is a sentence; this one reports its own
supersession.
Options considered#
- Ship the companion anyway — rejected: it crosses four policy surfaces to serve a need with no observation behind it, and "we already mint deep links for it" is a fact about a link contract, not about a learner.
- Record
not-justified— rejected: that verdict asserts the core does the job, and no evidence says so. Writing it would launder an absence into a finding, which is the specific failure this gate is built to catch. - Recruit for consented research first — deferred, not rejected: it is the only plane that could settle the question, and it waits on YSD-18002. The ruling's review date is what brings it back.
Consequences#
- YSD-19107's obligation does not arise. It is conditional on a
justifiedverdict;companionObligationArisesreturnsfalsewith the verdict and the reason attached, so the absence is a computed answer rather than an assumed one. - Two crossings on a shipped capability remain unresolved and are now
visible. The offline note queue crosses
learner-notes-on-personal-deviceandlost-device-revocation, and neither has a decision from the owner of those surfaces. The tree holds controls that bear on them — an offline bundle expires locally, a covering grant lapses, accepted records are lease-gated — and they are recorded inNEAREST_CONTROLSas controls, each with the sentence saying why it is not a permission. A time bound limits how long a lost device stays useful; it does not revoke anything on demand. These are rights and device-privacy decisions that no amount of demonstrated need would settle, and they are owed regardless of this ruling. - The first release ships the policy-safe core: the web workspace in a phone browser, portable study packages, and deep links.
Machine-enforced outcome#
The gate is asked about the programme rather than about a fixture: its inputs come from a recorded register instead of an array literal at each call site, and the owner's ruling is held against the live verdict and the live construction state every time it is read.
Control in force#
assertGateStillOpen throws for both capabilities, and that stays true after
this ruling — approval decides what to build next, not that the gate was
consulted in time. assertDeferredCapabilitiesJustified still throws, because
neither verdict is justified and this decision does not make one so.