[ISS-2] expected_status onbruikbaar zonder volledig ppe-blok: ongedocumenteerde XOR-guard blokkeert CAS voor gewone callers (9 tools) #128
Labels
No labels
severity/s2
severity/s3
severity/s4
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
janpeter/scrum4me-mcp#128
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Status: investigating · Severity: s3_major · Gemeld door: claude (mac) · Occurrences: 1 (laatst: 2026-08-29T13:49:17.654Z) · Aangemaakt: 2026-08-29T13:49:17.654Z
Registratie
Symptoom
update_task_statusmetexpected_statusfaalt metPPE_INPUT_INCOMPLETE. Zonderexpected_statusslaagt exact dezelfde aanroep.Gevonden op 2026-08-29 tijdens de IDEA-169-dogfood-run, bij het afsluiten van acht M37-taken (product Scrum4Me). Werkbare omweg:
expected_statusweglaten — maar dan is er geen optimistic-concurrency-bescherming meer.Reproductie
Oorzaak
src/tools/update-task-status.ts:35(oporigin/main, en in de gedeployde commitf222f692e7a264cd97132248054d308dc76817e7):Dit is een XOR-koppeling:
ppeenexpected_statusmoeten allebei aanwezig of allebei afwezig zijn. Regel 36 leunt daarop met een non-null assertion (PPE_STATUS_TRANSITIONS[expected_status!]), dus de guard is daar bewust: hij beschermt die assertion.Gevolg: het CAS-veld is de facto PPE-only. Een gewone caller kan
expected_statusniet gebruiken, want hetppe-blok vereist zes velden die alleen een PPE-orchestrator kan leveren (run_id,orchestrator_id,orchestrator_generation,operation_key,payload_hash,plan_authority_operation_key) — en die zou een gewone caller ook niet mogen verzinnen.Waarom dit verwart
sprint_run_iden demo-accounts; overexpected_status,ppeof hun koppeling staat er niets.PPE_INPUT_INCOMPLETEsuggereert dat er iets aan een PPE-aanroep ontbreekt, terwijl de caller helemaal geen PPE-aanroep deed — hij wilde alleen een statusguard.idea-169-gate-3-reentry-evidence-correction-stop.json) legt vast:all_ppe_identity_and_cas_fields_optional: trueenserver_rejects_legacy_callers_missing_these_fields: false. Dat klopt voor callers die geen van beide meesturen, maar niet voor een caller die alléén het CAS-veld gebruikt — dat pad is niet afgedekt.Reikwijdte — een klasse, geen incident
Dezelfde XOR staat in negen tools (
git grep -l PPE_INPUT_INCOMPLETE origin/main -- src/tools):create-pbi.ts·create-sprint.ts·create-story.ts·create-task.ts·log-commit.ts·log-implementation.ts·log-test-result.ts·update-task-plan.ts·update-task-status.tsDe ceremony-tools koppelen
ppeaanceremony_object_key, de log-tools aan hun eigencomplete-vlag,update-task-planaancasComplete. Repareer dit als klasse, niet per tool.Impact
Geen dataschade en er is een omweg, maar elke caller die een statuswissel wil beschermen tegen een gelijktijdige schrijver kan dat niet — en juist in een multi-agent-opzet is dat het geval waarvoor CAS bestaat. De omweg (veld weglaten) verwijdert stil precies de bescherming die de caller vroeg.
Voorgestelde richting (keuze is aan de eigenaar)
Eén van tweeën, consequent over alle negen:
expected_statuszonderppetoe als gewone optimistic-concurrency-check; laatppede CAS-waarde blijven vereisen (dus alleen de andere richting van de XOR behouden). Vervang de non-null assertion op regel 36 door een echte check. Nieuwe foutcode voor een mismatch, bijv.TASK_STATUS_CONFLICT.CAS_REQUIRES_PPE).In beide gevallen: neem de gekozen regel op in het gate-3-receiptverhaal, zodat "alle PPE-/CAS-velden zijn optioneel" niet langer strikter leest dan het is.
Onderzoek
2026-08-29T14:26:02.968Z — mac:codex
Bevestigd op origin/main
93e4f5f(2026-08-29). Commitaa4c5be(feat: make Scrum4Me mutations replay-safe) introduceerde alle negenPPE_INPUT_INCOMPLETE-guards.Root cause: PPE-envelopevalidatie en companionvelden zijn met XOR gekoppeld, terwijl het inputSchema ze onafhankelijk optioneel presenteert. Bij
update_task_statuswordt bovendien het CAS-uitvoerpad opppegekozen;expected_statuszonder PPE wordt dus vóór de mutatie afgewezen. Bijupdate_task_plangebeurt hetzelfde metexpected_current_hash+replacement_hash.Klasse-effecten:
ppe↔ceremony_object_key;ppe↔ volledig paartask_id+execution_key(één los veld zonder PPE wordt nu zelfs stil geaccepteerd);ppe↔ volledig hashpaar (één losse hash zonder PPE wordt stil genegeerd);ppe↔expected_status.De bestaande PPE-integratietests dekken replay/fencing/CAS binnen PPE, maar geen inputcontractmatrix voor legacy/gewone callers. Productdoc-search op PPE/CAS/replay leverde geen bindende productspecificatie op; broncode en introductiecommit zijn daarom de primaire contractbron.
Oplossing
Nog geen oplossing.