T-HTN8-lease-gate-memo-fields
Status: closed/superseded · Impact: high · Complexity: small
D-S30G-task-state-plane-split (task state planes) moves the readiness gate
memos off task frontmatter and onto the lease payload — the expand stage, the
home that must exist before the writers stop stamping frontmatter (T-5LP4).
This task adds the two memo fields to the task-lifecycle lease payload and a
way to set them through the existing transition op. Settles the ADR’s open
question in favor of dedicated typed fields over the freeform notes.
| Location | Role today |
|---|---|
apps/sdlc/lib/services/lease/schemas.ts#TaskLifecycleLeaseSchema | The task-lifecycle payload: phase, pr_number (nullable, default null), notes (default ""); no gate-memo fields |
apps/sdlc/lib/services/lease/schemas.test.ts | Payload schema round-trip tests |
apps/sdlc/lib/services/lease/ops/task/transition.ts | CAS-replace transition op (sdlc lease task transition <task-id> --phase <phase>); updates phase, pr_number, ttl/expires_at, rotates lease_token, composes handoff on awaiting-review; no memo pass-through |
Proposed
Section titled “Proposed”TaskLifecycleLeaseSchema carries readiness_verified_at and
touchpoints_verified_at — ISO 8601 UTC datetime strings, nullable,
defaulting to null so every existing serialized payload still parses. The
transition op accepts optional flags to set them. No consumer changes here:
writing the memos from ensure-ready is T-5LP4’s wiring.
Approach
Section titled “Approach”- In
schemas.ts, addreadiness_verified_atandtouchpoints_verified_attoTaskLifecycleLeaseSchema, adjacent topr_number: nullable string,.default(null), ISO-datetime-shaped (reuse the file’s regex-anchor style for the shape check). While in the file, note that the “schemas.py” mirror comments are historical — noschemas.pyexists in the repo; reword the header comment so it no longer implies a live mirror obligation. - In
transition.ts, add optional--readiness-verified-at <iso>and--touchpoints-verified-at <iso>flags that write through to the replaced payload; absent flags preserve the current payload’s values (memos survive unrelated phase transitions). - Extend
schemas.test.ts: a payload without the new fields parses with nulls (backward compat); a payload with them round-trips; a malformed datetime is rejected.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
apps/sdlc/lib/services/lease/schemas.ts | modify | Two nullable datetime memo fields on TaskLifecycleLeaseSchema; historical-mirror comment reworded |
apps/sdlc/lib/services/lease/schemas.test.ts | modify | Backward-compat, round-trip, and rejection cases for the memo fields |
apps/sdlc/lib/services/lease/ops/task/transition.ts | modify | Optional memo pass-through flags; absent = preserve current values |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: a serialized payload predating the change (no memo keys) parses
via
TaskLifecycleLeaseSchemawith both memos null — asserted inapps/sdlc/lib/services/lease/schemas.test.ts. - AC-2: a payload carrying both memos round-trips unchanged; a non-datetime value is rejected — asserted in the same suite.
- AC-3:
sdlc lease task transitionwith--readiness-verified-atwrites the value into the replaced payload; a subsequent transition without the flag preserves it. - AC-4: the schemas suite
apps/sdlc/lib/services/lease/schemas.test.tspasses when bun-run as a test file.
Out of scope
Section titled “Out of scope”- Writing the memos from ensure-ready / task-work (T-5LP4).
- Any frontmatter change to the task entity (retirement is D-S30G-task-state-plane-split’s later migration stages).
- The operation-lease payload and other lease kinds.
Dependencies
Section titled “Dependencies”- D-S30G-task-state-plane-split expects acceptance before writer changes land — this task only adds the home, so it can proceed, but T-5LP4 should wait for the flip.
Discovery context
Section titled “Discovery context”Dedup search (spawn-from-post-mortem)
Section titled “Dedup search (spawn-from-post-mortem)”Bullet: A conflicting in-flight task specifies the same two stamps in a
contradictory shape — T-HTN8-lease-gate-memo-fields (from D-EQGC, since
deleted, open/ready, autonomy: autonomous/pr) adds readiness_verified_at /
touchpoints_verified_at as FLAT .default(null) payload fields plus
--readiness-verified-at flags on transition, against this task’s nested
gates object plus sibling op. Two decisions claim one migration and they
collide on schemas.ts and transition.ts — readiness gating is per-task
and saw neither. A cross-task touchpoint-overlap check at pickup (same
## Files to touch rows on another open/in-progress task) would have caught
it before implementation.
Keywords searched: t-htn8-lease-gate-memo-fields, touchpoints_verified_at,
readiness_verified_at, readiness-verified-at, touchpoint-overlap,
contradictory, conflicting, in-progress
Excluded: T-5G81-lease-payload-gates
Top candidates (score / status / headline):
- 44 / closed/done / T-ZQ4H-task-ensure-ready-accepts-in-progress — task-ensure-ready accepts in-progress when readiness_verified_at is set
- 30 / closed/done / T-N2X3-start-task-preserves-readiness-stamp — start_task.py should preserve readiness_verified_at across rebase
- 23 / closed/done / T-4Q0T-restructure-task-touchpoints-as-a-table-with-symbol-dir-glob — Restructure task touchpoints as a table with symbol/dir/glob citation grammar
- 22 / closed/superseded / T-2QXZ-start-task-handles-frontmatter-rebase-cleanly — start_task.py auto-merges frontmatter on stamp/start rebase conflict
- 15 / closed/done / T-OHT5-resolve-ensure-ready-in-progress-contract — Resolve task-ensure-ready contract conflict with task-work in-progress contract
Decision: LINKED-EXISTING T-HTN8-lease-gate-memo-fields
Rationale: Override of the script’s SPAWNED. The keyword scorer ranked only
closed tasks (this task scored below the top-5 cut because the shared terms
appear just a handful of times in its body), but the bullet names this task
explicitly: T-5G81-lease-payload-gates and this task specify the SAME two
gate stamps in contradictory shapes — a nested gates object plus a sibling
op (from D-S30G-task-state-plane-split) versus flat .default(null)
payload fields plus --readiness-verified-at transition flags (from
D-EQGC, since deleted) — and collide on
apps/sdlc/lib/services/lease/schemas.ts and
apps/sdlc/lib/services/lease/ops/task/transition.ts. The resolution is a
human decision between two decision records, not a new automation task, so
the link is recorded here instead of minting a third artifact.
Post-mortem
Section titled “Post-mortem”Captured by /sdlc:task-work on 2026-08-03. PR: pending.
Acceptance criteria coverage
Section titled “Acceptance criteria coverage”TBD — filled at Step 8.
What worked
Section titled “What worked”TBD — filled at Step 8.
Friction and automation gaps
Section titled “Friction and automation gaps”TBD — filled at Step 8.