docs: plan issue #2066 — embargo invite RSVP deadlines - #2210
Conversation
- ADR-0059 (accepted-provisional): carry the RSVP-by deadline on `Invite.end_time`, not `Offer.end_time` — the embargo invitation is an `as_Invite`, not an `as_Offer` - specs/case-management.yaml: add CM-27 (RSVP semantics, CaseActor lazy enforcement, lapse recorded as DECLINED, ledger provenance, UTC normalisation); amend CM-18-002 so the pocket veto and the explicit deadline stay one mechanism - specs/embargo-policy.yaml: add EP-07 (fallback window, 72h minimum, clamp-on-receipt) - specs/em-behavior.yaml: add EMB-17 (late Accept is never refused — honour / re-invite / ack-no-op) - notes/participant-embargo-consent.md: reconcile the pocket-veto section, document the two-`end_time` hazard, resolve three open questions - glossary, draft protocol spec, ADR index, mkdocs nav updated Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nvite.end_time Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- phase5-ledger-snapshot-core-shaped: the canonical ledger snapshot for a partially accepted status was core-shaped (nested rm/vfd, no @context, emConsentState or cvdRole), which the fcvcv invariant harness rejects and every replica misreads. Core must not import the wire layer to rebuild the object (ADR-0009/0017), so the override is now a field *patch* keyed by wire alias, merged onto the snapshot's existing object by _merge_snapshot_object_fields. Shape preservation is structural: the override and non-override paths produce identical shapes. New spec RSH-05-009 states the requirement. - phase8-ratchet-result-discarded: ApplyParticipantStatusFromLedgerNode saved the ratcheted status only when the object was absent locally. Since the node appends what it reads *back*, an already-stored object silently discarded the ratchet and regressed the replica's RM while the ratchet's own warning claimed the opposite. Saved unconditionally now. - phase8-absent-case-status-erases-pxa-em: an inbound status with no caseStatus asserts nothing about pxa/em; it now carries the receiver's own case_status forward instead of blanking both. - phase8-noop-path-leaves-stale-bb-keys: update() clears both blackboard keys unconditionally, before the datalayer guard, so no no-op path inherits a previous execution's override (BT-17-003/004). - phase8-closed-to-closed-mislabeled-refused: addressed in part. The operator-facing WARNING now distinguishes "rewrote dimension(s) X" from "blocked dimension(s) X with no change to the asserted value". The reviewer's proposed reorder of _rm_is_acceptable was NOT applied: making CLOSED->CLOSED acceptable empties `refused`, which makes ValidateRMTransitionNode re-reject the transition (reintroducing #2235) and lets a pure no-op status be appended and ledger-committed. - phase10-no-snapshot-schema-assertion: assert the committed snapshot keeps the sender's wire shape (rmState/vfdState/emConsentState/cvdRole/@context, nested caseStatus, no core dimension dicts, no stale snake_case twins), plus omitted-caseStatus and already-stored-object coverage. - phase10-no-blackboard-leak-test: back-to-back executions, the commit node's ID match in both directions, resolve_dimension_filter's mismatch branch, and the datalayer-missing clear. - phase10-monotonic-helpers-untested: exhaustive table-driven coverage of is_monotonic_vfd_forward / is_monotonic_pxa_forward over every ordered pair, with a bitmask subset oracle independent of the implementation. - phase6-adr-number-collision: renumbered ADR-0060 -> ADR-0061; open PR #2275 (older) keeps 0060. Note that PR #2210 claims 0059, which is already taken on main and will need its own renumber. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sei-ahouseholder
left a comment
There was a problem hiding this comment.
PR Triage — #2210
Branch: plan/2066-offer-expiry-end-time → main
Label: specs-notes (docs-only)
CI: ✅ All checks passing (CodeQL, docs-build-check, lint, spec-lint — 2026-08-12)
Merge state:
Issue Linkage
Closes #2066. All six acceptance criteria are satisfied:
- AC-1: ADR-0059 documents
Invite.end_timeas the RSVP deadline, captures all required rationale ✓ - AC-2: CM-27-002 + EP-07-001 — absent
end_timefalls back to CM-18-002 policy window ✓ - AC-3: CM-27-004 — lapse records
DECLINED, identical to explicit refusal ✓ - AC-4: EMB-17-002 / EMB-17-003 — late Accept with active embargo: honour (same terms) or re-invite (stale terms) ✓
- AC-5: EMB-17-004 — late Accept with no embargo: ack as no-op, retain case participation ✓
- AC-6: Rescind mechanism deferred to its own Idea, with rationale in ADR-0059 §More Information ✓
Three deliberate refinements to the issue's framing are documented in the PR body (Invite not Offer; two-end_time collision is sharper; late-Accept rule is liberal). All confirmed.
Findings
| ID | Severity | File | Description |
|---|---|---|---|
| phase12-merge-conflicts-0 | FAIL | — | Branch is CONFLICTING with main; must be resolved before merge |
| phase5-circular-spec-relationship-0 | IMPROVE | specs/case-management.yaml |
CM-18-002 and CM-27-002 mutually refines each other — circular. CM-18-002's relationships block should be removed (the prose note already captures the relationship). |
| phase9-notes-related-specs-stale-0 | IMPROVE | notes/participant-embargo-consent.md |
Frontmatter related_specs lists only case-management.yaml; the new RSVP section also covers EP-07 and EMB-17 — add specs/embargo-policy.yaml and specs/em-behavior.yaml. |
All three findings are fix-now (trivial inline fixes).
Summary
This is a well-constructed planning PR. The spec groups (CM-27, EP-07, EMB-17) are internally consistent and cover the protocol design space correctly. The ADR follows project conventions (MADR template, accepted-provisional status with explicit rationale, consequences and options documented). Notes and docs are current. The only structural issue is a circular spec relationship; the other two findings are minor frontmatter and relationship-direction cleanups.
🤖 pr-triage
- phase5-circular-spec-relationship-0 — remove backward relationships block from CM-18-002 that created a mutual refines loop with CM-27-002; the prose note already captures the relationship clearly - phase9-notes-related-specs-stale-0 — add specs/embargo-policy.yaml and specs/em-behavior.yaml to related_specs frontmatter in notes/participant-embargo-consent.md (new RSVP section references both) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
ADR-0059 and CM-27 were taken on main by the task/2096 merge. Rename docs/adr/0059-embargo-invite-rsvp-deadline.md to 0065 and update the spec group id from CM-27 to CM-28 throughout. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
ADR-0059 through ADR-0064 and CM-27 landed on main via task/2096-resolve-todo-fixme-markers. Resolved conflicts by keeping main's entries in order and appending this branch's ADR-0065 (renamed from 0059) and CM-28 (renamed from CM-27) after. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
sei-ahouseholder
left a comment
There was a problem hiding this comment.
PR Execute: #2210 — docs: plan issue #2066 — embargo invite RSVP deadlines
Fixes applied: 3 commits
Issues filed: 0
Deferred: 0
Tests run: unit only (docs-only PR)
CI status after push: ⏳ pending (pushed to origin; CI re-running)
Fixed
| Finding | Commit |
|---|---|
| phase5-circular-spec-relationship-0: Remove circular refines from CM-18-002 | 84ed17b8 |
| phase9-notes-related-specs-stale-0: Add EP/EMB specs to notes frontmatter | 84ed17b8 |
| phase12-merge-conflicts-0: Resolve ADR/spec number collisions with main | 29e33806 + 0212d1eb |
Conflict resolution detail
ADR-0059–0064 and CM-27 (Case Collection Mutation Discipline) landed on main via
task/2096. This branch originally added its own ADR-0059 and CM-27 (Embargo Invite
RSVP Deadlines). Resolved by:
- Renumbering:
docs/adr/0059-embargo-invite-rsvp-deadline.md→0065; spec group CM-27 → CM-28; all cross-references updated throughout (29e33806) - Merging origin/main with the three conflicting files resolved in order — main's ADR-0059–0064 and CM-27 first, then our ADR-0065 and CM-28 appended (
0212d1eb)
All pre-commit hooks passed (spec registry linter, ADR index and nav in sync, markdownlint).
Test suite
6996 passed · 370 skipped · 5 xfailed · 0 failed (92s)
All 5 xfails reference live open issues (#2288, #2289, #1992, #2293, #2294).
Execute artifact: .claude/pr-2210-execute.json
Next step: wait for CI, then /pr-verify or /pr-ship will continue automatically.
🤖 pr-execute
sei-ahouseholder
left a comment
There was a problem hiding this comment.
PR Verify: #2210 — docs: plan issue #2066 — embargo invite RSVP deadlines
Overall verdict: ✅ READY-TO-MERGE
CI status: ✅ passing (CodeQL, docs-build-check, lint, Spec Lint — all 6 checks)
Merge state: ✅ MERGEABLE (CLEAN) — base main
Base sync in execute: ✅ merged @ 0212d1eb (3 conflicts resolved — docs/adr/index.md, mkdocs.yml, specs/case-management.yaml)
Integrity check: ✅ all 3 findings accounted for
Finding Verdicts
| Finding | Severity | Outcome | Verdict |
|---|---|---|---|
| phase12-merge-conflicts-0: Branch conflicting with main | ❌ FAIL | fixed @ 0212d1eb |
✅ CONFIRMED |
| phase5-circular-spec-relationship-0: Circular refines on CM-18-002 | fixed @ 84ed17b8 |
✅ CONFIRMED | |
| phase9-notes-related-specs-stale-0: Notes frontmatter missing EP/EMB specs | fixed @ 84ed17b8 |
✅ CONFIRMED |
Spot-check detail
- phase12: Live merge-state check returns
mergeable: MERGEABLE, merge_state_status: CLEAN. No conflict markers at HEAD (git grepclean). - phase5: CM-18-002 in
specs/case-management.yamlhas norelationships:block at HEAD — circular refines removed; CM-28-002→refines→CM-18-002 is the sole (correct) direction. - phase9:
notes/participant-embargo-consent.mdfrontmatterrelated_specslists all three specs (case-management, embargo-policy, em-behavior) at HEAD.
Renumbering note
ADR-0059 (embargo invite RSVP deadline) was renumbered to ADR-0065 and spec group CM-27 to CM-28 to avoid collisions with ADR-0059–0064 and CM-27 (Case Collection Mutation Discipline) that landed on main via #2111. All cross-references updated; ADR index / nav sync hook passed.
Artifacts cleaned up.
🤖 pr-verify
Summary
Plans IDEA-2066 (embargo invite expiration deadlines) into an ADR plus three spec groups. Three of the issue's premises changed during planning: the embargo invitation is an
as_Invite, not anas_Offer; the twoend_timemeanings collide inside a single invitation payload; and a deadline mechanism (the CM-18-002 pocket veto) was already specified but entirely unimplemented. The plan reconciles the pocket veto with an explicit wire deadline rather than adding a second timeout notion.Changes
docs/adr/0059-embargo-invite-rsvp-deadline.md(new): carry the RSVP-by deadline onInvite.end_time. Records the five-part decision (field/meaning, authority, CaseActor lazy enforcement, liberal late-Accept, no new PEC state) and the four options weighed.status: accepted-provisional— ratified but unimplemented, so marking itacceptedwould trip the MS-14 status/prose rule.specs/case-management.yaml: new group CM-27 (6 entries) — RSVP semantics and the two-end_timehazard, wire value authoritative over local policy, CaseActor (CVDRole.CASE_MANAGER) lazy enforcement with no scheduler required, lapse recorded asDECLINED, ledger-based provenance, inbound UTC normalisation. Amends CM-18-002 with anote+refinesrelationship so the pocket veto and the explicit deadline remain one mechanism.specs/embargo-policy.yaml: new group EP-07 (3 entries) — fallback window (7 days, matching CM-18-002), 72h minimum, and clamp-on-receipt for sub-floor deadlines.specs/em-behavior.yaml: new group EMB-17 (4 entries) — a lateAcceptis never refused on deadline grounds: honour it when terms are current, re-invite with current terms when stale, acknowledge as a no-op (retaining case participation) when no embargo remains. Closes the gap where anAcceptarrives after EMEXITEDbut CS is not yet P/X/A, which EMB-13-002 did not cover.notes/participant-embargo-consent.md: reconciles the pocket-veto section, adds a "RSVP Deadlines on Embargo Invites" section documenting the two-end_timehazard and theInvite-not-Offercorrection, and resolves three open questions. Also flags that the section's cited provenance (archived_notes/demo-review-26042001.md) never mentions "pocket veto".docs/reference/glossary.md: revised Pocket Veto; new RSVP Deadline term.docs/reference/draft-vultron-spec.md: §6.4.4 updated so the draft protocol spec does not go stale.docs/adr/index.md,mkdocs.yml: ADR-0059 registered.Notes for reviewers
Invite.end_time(AC-1 saidOffer.end_time); the late-Acceptrule is liberal rather than fail-closed; and the rescind mechanism (Undo(Invite)) is deferred to its own Idea, which AC-6 explicitly permits.mkdocs build --strictreports 2 warnings, both pre-existing onmainand unrelated to this branch — theprint-siteplugin ordering notice (already whitelisted bymkdocs-build-strict.sh) and an autorefs failure on[SUPERSEDED]text inspecs/multi-actor-demo.yaml/specs/architecture.yaml. This branch adds no new warnings..github/scripts/mkdocs-build-strict.shcomputes its warning counts withgrep -c ... || echo 0, which emits"0\n0"when a count is zero and breaks the arithmetic on lines 31/34/37 (syntax error in expression), making the script report failure even when only whitelisted false positives are present. This does not affect CI —docs-build-check.ymlrunsuv run mkdocs build --verbose --cleandirectly, without--strictand without this wrapper, and it passes on this branch. The script only misleads anyone running it locally. Not touched here (CI is out of agent scope perAGENTS.md); flagged for a maintainer.Implementation Issues
size:M)DECLINED+ ledger provenance (size:L)Accept: honour / re-invite / ack-no-op, EMB-17 (size:M)Deferred with rationale, filed separately:
Undo(Invite(EmbargoEvent))(the issue's AC-6)FORBIDDENonorganization.projectV2). #2211–#2214 are sub-issues of epic #2088 and should inherit its Schedule tier; #2215 has no parent epic and needs routing.