Repository navigation
docs(adr): ratify the claim expiry contract (ADR-011, S5/APA-26) - #181
Merged
Merged
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
21 of 36 tasks
EXPIRED has been implemented, wired, tested and deployed for a long time, but no document in this repository ever ratified it. Its semantics were attested only by code comments citing a Linear id the repo does not record, while the file calling itself the specification of this lifecycle did not contain the status at all. ADR-011 records the approved semantics: EXPIRED is terminal-for-round (no out-edges; terminality by absence from claims.Transitions), reachable only as HITL -> EXPIRED or ACTION_PENDING -> EXPIRED (HITL-wait timeout). Timeout expiry can never approve, reject, close, escalate or otherwise decide a claim; post-expiry APPROVE/REJECT/ESCALATE/HOLD are illegal and APPROVE from HITL was already illegal. Re-drive after expiry requires an explicit new decision/round, never an implicit edge. Reconciled documentation: - statemachine.go's header no longer claims the file is 'the Go port of the Python specification' - packages/domain/state_machine.py is a demoted artifact, not a mirror, and does not define EXPIRED. Comment-only change. - AGENT_OPERATING_CONTRACT.md item 5 now lists EXPIRED in the chain. - packages/domain/state_machine.py's docstring states it is superseded for lifecycle semantics and is not a mirror. Docstring-only change. - 09_DECISION_LOG.md and 06_PROGRESS.md carry the decision. - KNOWN_LIMITATIONS.md gains KL-18 registering the narrower Python graph rather than reconciling it silently. No lifecycle behaviour changed. The implementation already behaved this way and the existing tests already pin it: claims/expiry_red_test.go, handlers/decision_expiry_test.go (4 PG-gated), repository/postgres/hitl_expiry_test.go. The statemachine.go comment about golden case 08 is also inaccurate but is deliberately left alone: that correction is a separate focused change. Co-Authored-By: opencode <no-reply@opencode.ai>
Aparnap2
force-pushed
the
docs/adr-011-claim-expiry-contract
branch
from
October 21, 2026 06:53
bb6421a to
876d9e9
Compare
The rebase onto main@7ad446c (which merged #180 and #179) made three statements in this change false as written: - The ADR, the decision-log entry and KL-18 all said the cross-language fixture 'contains nine cases'. After #179 it contains nineteen. None of the nineteen covers EXPIRED, so the substantive claim is unchanged; only the count was stale. - The ADR's Base line still named main@254c4b9; it is now written against main@7ad446c. - The Context said 'no document in this repository ever ratified it'. This ADR ratifies it, so the claim needs its temporal qualifier. The statemachine.go reference is likewise now stated as 'before this ADR', since this change corrects that header. Also fixes KL-18's position: it was inserted between KL-16 and KL-17 instead of after KL-17, so the register's rows were out of order. Co-Authored-By: opencode <no-reply@opencode.ai>
Aparnap2
marked this pull request as ready for review
October 21, 2026 07:03
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Documentation-only, plus two comment-only source edits. No lifecycle behaviour changed.
docs/adr/011-claim-expiry-contract.mddocs/specs/09_DECISION_LOG.mddocs/specs/06_PROGRESS.mdLast updated→ 2026-10-21; liveCurrent basepointer →main@254c4b9docs/AGENT_OPERATING_CONTRACT.mdEXPIREDin the transition chaindocs/KNOWN_LIMITATIONS.mdapps/api/internal/claims/statemachine.gopackages/domain/state_machine.pyBase
main@254c4b92dddf59a758a133c1edbf7618dcc011b2· commitbb6421a· branchdocs/adr-011-claim-expiry-contract. ADR-011 avoids the pendingADR-010in PR #161.The gap this closes
EXPIREDwas implemented, wired, tested and deployed — but no document ever ratified it. Its semantics were attested only by code comments citing a Linear id this repo does not record, while two things made that dangerous:statemachine.go:3-7described itself as "the Go port of the Python specification inpackages/domain/state_machine.py" — a specification with 13 statuses and noEXPIRED. The file claimed parity it did not have.fixtures/golden_cases.json— the cross-language contract designated by ADR-001 — has nine cases and none coversEXPIRED. The one status on which the two implementations disagree was exactly the status the contract did not cover.What ADR-011 records
EXPIREDis an approved state of the authoritative Go lifecycle (S5/APA-26):claims.Transitions.HITL → EXPIREDandACTION_PENDING → EXPIRED(HITL-wait timeout).APPROVE/REJECT/ESCALATE/HOLDare illegal, andAPPROVEfromHITLwas already illegal becauseHITLhas noVERIFIEDedge.Alternatives considered and rejected in the ADR: resyncing the Python graph to a true 14-status mirror (contradicts ADR-001's demotion and keeps a second lifecycle alive); removing the Go edges (the deployed GCW workflow posts
EXPIREon the HITL-timeout path — that branch would have no business-state outcome); leaving it undocumented (the status quo that caused this).Evidence the implementation already behaves this way
Nothing in the implementation changed; these already existed and still pass:
apps/api/internal/claims/claim.go:117-121— the status and its stated intent.apps/api/internal/claims/statemachine.go:53-60— the only two inbound edges.apps/api/internal/handlers/decision.go:95-100—EXPIREwired into the HMAC decision endpoint with the same HMAC, version and idempotency controls as every other decision.workflows/claim-investigation.yaml— the deployed workflow already postsEXPIRE(expire/expire_escalated).apps/api/internal/claims/expiry_red_test.go— the S5/APA-26 contract.apps/api/internal/handlers/decision_expiry_test.go— 4 PostgreSQL-gated tests.apps/api/internal/repository/postgres/hitl_expiry_test.go—TestHITL_ExpiredExcludedFromPending.Verification
The expiry behaviour was re-asserted unchanged after the edit:
TestExpiry_HITLToExpired_Legal,TestExpiry_ActionPendingToExpired_Legal,TestExpiry_NoOutEdges,TestExpiry_ApproveFromHITL_Illegal,TestDecision_PostExpiryDecisions_Rejected_Live,TestHITL_ExpiredExcludedFromPending— all PASS.Diff shape proof:
git diffonstatemachine.gocontains only//comment lines;git diffonpackages/domain/state_machine.pyis a single hunk at line 1 (the docstring). No executable line changed in either file.Scope notes and deliberate omissions
06_PROGRESS.md'sCurrent base:was a live pointer tomain@dffa160; because the file now carries a fact true as of254c4b9, I updated it rather than leave the file internally inconsistent. This incidentally resolves one of the three W17 pointers;09_DECISION_LOG.md:490and10_PHASE3_E2E_QUALIFICATION.md:5remain for that separate pass. (2)packages/domain/state_machine.pyis touched — docstring only — because its silence is precisely what caused the misattribution this ADR resolves.statemachine.gocomment describing golden case 08 as witnessing "stale-version wins over legality" is also inaccurate (case 08's edge is legal, so the case witnesses only that a stale version is rejected). That is a separate focused change.EXPIREDcase; the canonical audit-action vocabulary (Go emitsclaim.transitioned, the fixture saysclaim.status.transition); and the Go-vs-Python malformed-claim rule. These are tracked separately and are not resolved by this ADR.docs/KNOWN_LIMITATIONS.mdgains KL-18 registering the narrower Python graph rather than silently reconciling it.Status
Documentation and comments only. Not authorized to merge — opened as a draft for review. No branch-protection change, no deployment. Release status NOT QUALIFIED; this closes no release gate.