Skip to content

T-1VF3-lease-token-rotation-full-policy

Status: closed/superseded · Impact: medium · Complexity: medium

Auto-generated from a /sdlc:task-work post-mortem. Review and promote to open/ready before picking up.

Slice 1’s CLI implements a deliberately approximate token-rotation rule (“transitions to claimed or working rotate; other phases preserve”) that handles single-host operation but not the ADR’s full owner-rotation matrix — in particular, explicit rotation on cross-host successor takeover. Slice 2’s /sdlc:task-work integration will exercise the cross-host path (different runner = different owner), so the approximation needs to be replaced with the full matrix before slice 2 lands. Cite T-QC31-add-sdlc-lease-cli-commands’s post-mortem for the slice-1 limitation note.

LocationRole today
plugin/scripts/lease_cli/transition.py (best guess)Implements the directional rule: rotate token on transition to claimed or working, preserve otherwise. README documents this as a slice-1 limitation.
plugin/lib/lease/primitives.py (best guess)The library’s cas_replace primitive accepts a new token but doesn’t itself enforce a rotation policy — the policy lives in the caller (the CLI today).
docs/planning/decisions/github-ref-leases/protocol.mdThe ADR’s authoritative owner-rotation matrix lives here (Token rotation section).

Move the rotation policy out of the CLI and into the library so all callers (CLI today, /sdlc:task-work tomorrow, headless workers later) get the same behavior:

  • A should_rotate_token(old_payload, new_payload) -> bool helper in the lease library that consults the ADR’s matrix on (old.phase, new.phase, old.owner, new.owner).
  • Cover the full matrix: claim/working rotations as today, plus cross-host successor takeover (different owner.kind or owner.id = rotate), plus explicit “release-and-reclaim” sequences if the ADR calls them out.
  • The CLI’s transition handler stops embedding the rule and just calls the helper.

The matrix details come from the ADR section — implementer reads it during planning and translates each row into a test case.

  1. Re-read the ADR’s Token rotation section (or equivalent) and enumerate every row of the matrix as a (old.phase, new.phase, old.owner, new.owner) → rotate? tuple.
  2. Implement should_rotate_token(...) in the library; one parametrized test per matrix row.
  3. Replace the CLI’s inline rotation rule with a call to the helper.
  4. Update the CLI README to describe the rule as “consults the library’s should_rotate_token helper” and drop the slice-1 limitation note.
  5. Re-run the existing CLI rotation tests (test_task_transition_rotates_token_to_working, …_keeps_token_on_awaiting_review) — they should still pass unchanged because the matrix’s single-host rows match the directional rule.
LocationKindChange
plugin/lib/lease/primitives.pymodifyAdd should_rotate_token(old, new) -> bool implementing the ADR’s full matrix.
plugin/lib/lease/tests/test_token_rotation.pynewParametrized test, one case per matrix row.
plugin/scripts/lease_cli/transition.pymodifyReplace inline rotation rule with a call to the library helper.
plugin/scripts/lease_cli/README.mdmodifyDrop the “slice-1 limitation” note from the token-rotation section.
  • AC-1: should_rotate_token is callable from the lease library and its return value matches the ADR’s matrix for every row.
  • AC-2: A cross-host successor takeover (transition where new.owner.id != old.owner.id and new.owner.kind matches a successor scenario from the ADR) rotates the token, asserted by a parametrized test.
  • AC-3: All existing CLI rotation tests (the single-host claim / working / awaiting-review cases from slice 1) continue to pass without modification.
  • AC-4: grep -n "rotate" plugin/scripts/lease_cli/transition.py shows zero policy logic — the CLI delegates entirely to the library helper.
  • AC-5: The lease-CLI README no longer describes the rotation rule as a slice-1 limitation.
  • Wiring the helper into /sdlc:task-work’s phase transitions. That’s slice 2.
  • Heartbeat / release token semantics. This task is only about transition-driven rotation.

Spawned by /sdlc:task-work post-mortem of T-QC31-add-sdlc-lease-cli-commands on 2026-05-23.

Bullet: Token-rotation policy is approximate. Implemented the directional rule ‘transitions to claimed or working rotate; other phases preserve’ which matches AC-3’s stated intent. The ADR’s full owner-rotation matrix is richer (e.g., explicit rotation on cross-host successor takeover). The CLI’s rule is correct for single-host operation and gets the slice-1 cases right; slice 2’s task-work integration will need the fuller policy. Documented as a slice-1 limitation in the README. Keywords searched: token-rotation, owner-rotation, approximate, implemented, directional, transitions, single-host, integration Excluded: 2026-05-23-add-sdlc-lease-cli-commands Top candidates (score / status / headline):

  • 6 / closed/done / 2026-05-19-add-epic-entity-task-depends-on-dependencies — Add epic entity + task depends_on dependencies
  • 6 / closed/done / 2026-05-19-implement-entities-migrate — Implement /sdlc:entities-migrate to apply mechanical schema-drift fixes
  • 4 / in-progress / 2026-05-20-orchestrator-tick-race-fixture — Integration fixture for concurrent orchestrator tick race on task-close-out
  • 2 / closed/done / 2026-05-19-add-update-skill-doc-skill — Add /update-skill-doc skill that refreshes a skill’s markdown doc from its SKILL.md
  • 2 / closed/done / 2026-05-19-extract-task-close-out-skill — Extract task-work Step 11 into /sdlc:task-close-out skill Decision: SPAWNED

← Back to Tasks