Repository navigation
Convert the accepted cross-request caching design (#11633) into an ADR — governed surface: draft PR, human merge #11969
Description
Activity
os-support-ai commented
on Aug 26, 2026 CollaboratorAuthorMore actionsBlocker expired —
Blocked-by: #10348is satisfied; one shorthand still needs resolving before dispatchdomain:servicesseat, sessionsession_0157mMVAq9fjGe2kaSD2aJC8, round 1.The machine-readable gate has cleared
The body carries
Blocked-by: #10348. #10348 closed 2026-08-24T13:49:00Z, completed by PR #11686 ("fix(auth): resolve the id-shaped platform-admin question in one place"). The card's parenthetical already recorded the other premise as met ("The #11663 condition is met — ruled 2026-08-25, #11663 comment 5404675670").⇒ Both named premises now read as landed, and the card has been sitting in
pm:queuewith a staleBlocked-by:line rather than being unblocked deliberately.⚠️ One thing I could not resolve, recorded rather than assumed awayThe parenthetical names the surviving gate as "#10348-C", not "#10348". That shorthand does not resolve cleanly against anything I can read:
- [finding] Three spellings of the ADR-0068 platform-admin read now live in plugin-auth, and one of them skips the system read context #10348 itself is a single finding (three spellings of the id-shaped platform-admin read) with no A/B/C legs on it;
- "leg C" in this design's vocabulary means the caching leg C, which is authz caching leg C: cache successful localization reads (
sys_setting) — settings-bus invalidation, engine-seam backstop, TTL bound #11966 — a different card, still open, and now carrying a routing objection from this seat (its fix lands inpackages/core, not this lane).
Two readings, and they differ in consequence:
reading consequence "#10348, leg C" — some sub-part of the consolidation #10348 is closed as completed, so the leg is presumptively landed ⇒ dispatchable now "#10348 and leg C (#11966)" — two premises collapsed into one token leg C is unbuilt ⇒ ⛔ not dispatchable yet ⭐ I lean to the first, and would still dispatch on it, for a reason independent of the token: an ADR records a decision, not an implementation. This card's own acceptance criterion is "a draft PR exists converting comment 5394942824 into
docs/adr/**" — the durable rule it captures (no authorization answer is cached without a declared invalidation contract and a TTL bound) is true whether or not leg C has shipped, and writing it down before the implementation is the normal and better order.⛔ But I am not resolving another seat's shorthand by preference. Resolvable in one read by anyone who opens the design comment (#11633 comment 5394942824, §10.1) and sees which premise list "-C" belongs to.
State: staying
pm:queue, ⛔ not dispatched this roundNot for lack of capacity — the batch (#12446, #11959, #12128) is disjoint from
docs/adr/**and this would have fit. Held for one round to resolve the token above, because the cost of being wrong is asymmetric: an ADR written on an unlanded premise records a rule the code does not yet obey, and it lands on a governed surface where the maintainer's merge is the review record.⚠️ Governed-surface discipline for whoever dispatches it — the card already states it, keeping it louddocs/adr/**⇒ draft PR only. ⛔ Never flipped ready, ⛔ never enqueued, ⛔ never auto-merged by a seat. Human merge is the review record. The seat's remaining duties are: write the review conclusion on this issue, request review fromos-zhuangon the draft PR, and list it under "awaiting a human merge" in the round report.
Generated by Claude Code
os-support-ai commented
on Aug 26, 2026 CollaboratorAuthorMore actionsClaim: PM loop round 2 (services seat)
Session:session_0157mMVAq9fjGe2kaSD2aJC8
Branch:claude/issue-11969-cross-request-caching-adr
Worktree:objectstack-issue-11969
Domain:domain:services
File surface:docs/adr/**— one new ADR file, and nothing else. ⛔ Zero code, zeropackages/spec, zerocontent/docs/releases/**. Stop on breach and explain in the report.
Container & model: M,mode:subagent,model: claude-opus-5. Transcribing an accepted design into a durable rule is judgement about what was actually ruled — the failure mode is an ADR that records a rule slightly wider or narrower than the one accepted, which then gets cited as if it were the ruling.
Clause-②: no — an ADR is a record of a decision. It changes no contract accept/reject behaviour and widens no public surface. ⛔ Do not hangneeds:contract-review.
Serial constraints cleared:docs/adr/**is free — no open PR in this lane touches it. Sibling in flight this round: #11520 (plugin-security) — disjoint. Landed this round: #12505, #12506.
⚠️ GOVERNED SURFACE — this PR is never yours to landdocs/adr/**is a governed surface. The discipline, and it is absolute:- Draft PR only. ⛔ Never flip it ready, ⛔ never enqueue it, ⛔ never enable auto-merge.
- Human merge is the review record. The maintainer merges it; that act is the approval.
- Your job ends at a draft PR with a body that links both rulings. The PM then writes the review conclusion, requests review from
os-zhuang, and lists it under "awaiting a human merge".
⇒ Do not be surprised that nothing lands. A correctly finished run here leaves an open draft.
⭐ Premise step zero — resolve a shorthand nobody has resolved, and stop if it resolves the wrong way
The card's
Blocked-by: #10348is cleared: #10348 closed 2026-08-24, completed by PR #11686. Verified.⚠️ But the card's parenthetical names the surviving gate as "#10348-C", not "#10348", and that token does not resolve cleanly from outside:- [finding] Three spellings of the ADR-0068 platform-admin read now live in plugin-auth, and one of them skips the system read context #10348 is a single finding (three spellings of the id-shaped platform-admin read) with no A/B/C legs;
- "leg C" in this design's vocabulary means the caching leg C, which is authz caching leg C: cache successful localization reads (
sys_setting) — settings-bus invalidation, engine-seam backstop, TTL bound #11966 — a different card, still open, and now carrying a routing objection (its fix measures topackages/core, the engine lane).
Your first task: open the design document — #11633 comment 5394942824, §10.1 — and read which premises it actually lists.
what you find what to do "#10348" alone, or a sub-part of it it is landed ⇒ proceed, and say so in the report "#10348" and leg C (#11966) as two premises leg C is unbuilt ⇒ ⭐ stop and report. ⛔ Do not write an ADR whose premise has not landed ⭐ My reading, offered as a mechanism assumption you should try to falsify, not as a ruling: an ADR records a decision, not an implementation, and the rule this one captures — no authorization answer is cached without a declared invalidation contract and a TTL bound — is true whether or not leg C has shipped. Writing it before the implementation is the normal and better order. But I am not resolving another seat's shorthand by preference, and if §10.1 says otherwise, §10.1 wins.
What the ADR must record — from the design, ⛔ not from this comment
Transcribe from #11633 comment 5394942824, quoting the design rather than paraphrasing from the card's summary:
- the durable rule: no authorization answer is cached without a declared invalidation contract and a TTL bound;
- the staleness posture: leg B off by default, TTL = 0, supported low-seconds range;
- the fork rulings: coarse invalidation; TTL +
authz.invalidatedwith TTL as the contract; session-of-record stays uncached per decision(plugin-auth): 会话的「记录之处」到底在哪 —— better-auth secondaryStorage 一旦接上 cache,ADR-0069 D4 的会话管控就静默失效 #4785; - the expiry-boundary rule:
min(ttl, nextBoundary)— validity windows see no write at their boundary.
⚠️ Where the card's summary and the design comment differ, the design comment is authoritative and the difference is worth naming in your report — a card summarising a design is exactly where a rule quietly widens.Provenance the PR body must carry
Both rulings, linked, because an ADR without its provenance is an opinion:
- maintainer acceptance: Design: cross-request caching for the authenticated request path (tranche 2 of #10757) — write-invalidation-first, short-TTL fallback, configurable staleness window #11633 comment 5404681591 (2026-08-25, verbatim 「接受你的建议,继续」)
- the [Design] Re-anchor platform-admin:
admin_full_accessbecomes a kernel metadata declaration; WHO holds it comes from env-configured verified emails — retiring the org-less row anchor #11663 condition, ruled met: [Design] Re-anchor platform-admin:admin_full_accessbecomes a kernel metadata declaration; WHO holds it comes from env-configured verified emails — retiring the org-less row anchor #11663 comment 5404675670 (2026-08-25)
House style
Read two or three recent
docs/adr/**files first and match their structure, numbering and front-matter conventions. ⛔ Do not invent a new ADR shape. Take the next ADR number from the tree at the moment you write, not from any number quoted elsewhere.Verification
- Derived gate union from
node scripts/pm/dispatch-gates.mjson your actual changed set, exit codes captured before any pipe.⚠️ Re-derive on a current tree — a stale derivation cost a sibling card a missed gate this round. - Expect the docs/ADR families to have an opinion (
check-adr-0087-registration, doc-frontmatter, doc-anchors, single-h1). Run them rather than assuming a new markdown file is inert. - Changeset: an ADR ships nothing executable. Argue
skip-changesetexplicitly; ⛔ never an empty changeset. - ⛔ No model names in any pushed artifact.
⚠️ The harness's default commit trailer carries one — a sibling card this round used the model-freeCo-authored-by: Claudespelling, already present in this repo's history.
Report
Post your terminal JSON report as a comment on this issue first, then return it as your message. Leave your own claim comment (your session id + branch) before you start — ⛔ the assignee here is the PM session, not you.
A
premise_still_valid: falsestop at step zero is a good run, not a failure.
Generated by Claude Code
os-support-ai commented
on Aug 26, 2026 CollaboratorAuthorMore actionsClaim (os-dev): starting work on this card.
- Session:
session_0157mMVAq9fjGe2kaSD2aJC8(dev subagente708cda6-4eec-5369-9cc9-9958b8e9c774; the dispatching PM seat shares this session id, so the subagent id is the disambiguator) - Branch:
claude/issue-11969-cross-request-caching-adr - Worktree:
../objectstack-issue-11969offorigin/main - File surface:
docs/adr/**— one new ADR file and nothing else. Zero code, zeropackages/spec, zerocontent/docs/releases/**. - Governed surface: draft PR only. Never flipped ready, never enqueued, never auto-merged. Human merge is the review record.
First action is premise step zero — reading #11633 comment 5394942824 §10.1 to resolve the "#10348-C" token — before any file is written. If §10.1 lists leg C (#11966) as a separate unlanded premise, this run stops and reports rather than writing the ADR.
Assignee untouched (it is the PM seat, per the dispatch brief).
Generated by Claude Code
Generated by Claude Code
- Session:
os-dev-report
{ "issue": 11969, "status": "done", "branch": "claude/issue-11969-cross-request-caching-adr", "pr": "https://github.com/objectstack-ai/objectstack/pull/12519", "premise_still_valid": true, "summary": "PREMISE RESOLVED -> PROCEED. The dispatch pointed at design comment 5394942824 SS10.1; there is no SS10.1 (SS10 is 'Proposed implementation split', a flat list of six items). The premise list is SS6 'Dependency disclosure', restated in SS9, and it names exactly two: #10348-C and #11663. The design defines the token itself in SS4 (leg A/A1): '#10348-C deletes it. Option C (ruled 2026-08-24) removes the id-shaped judges from auth-manager.ts and sends both call sites to resolve-authz-context.ts.' So '-C' is Option C OF #10348, a sub-part of that card -- NOT caching leg C (#11966), which appears only as item 1 of the implementation split, i.e. a thing the design proposes to BUILD, never a thing it depends on. That is the dispatch table's row 1. The maintainer acceptance says the same independently: 'the ADR conversion is the follow-up card, blocked on #10348'. Confirmed the landed shape matches the premise rather than trusting the card: auth-manager.ts now carries zero platform-admin judges and the derivation sits at packages/core/src/security/resolve-authz-context.ts, with admin-standing-surface.ts / last-admin-guard.ts / explain-engine.ts consuming it -- SS6's 'if it lands' branch. #11663 ruled 2026-08-25. DELIVERED: docs/adr/0127-authorization-cache-invalidation-contract-and-ttl-bound.md, one file, zero code, zero packages/spec, zero content/docs/releases. Nine decisions D1-D9 transcribed from the design comment: both-halves rule; seam-not-call-site-list; coarse invalidation baseline; TTL is the correctness contract with authz.invalidated narrowing the typical window only plus the non-optional boot posture statement; min(ttl, nextBoundary); grants off by default with 0 a real path and knobs in deployment config; session of record stays uncached per #4785; explainer + runAs automation bypass and sys_session never watched; pins assert cached == uncached. CARD-vs-DESIGN DIFFERENCE WORTH REPORTING: the card's shorthand 'declared invalidation contract' is WIDER than the design's SS0, which requires that 'every write that can change it passes a seam this process observes'. The shorthand admits the call-site-list reading that SS2.1 explicitly rejects (a forgotten call site fails as silent over-permission). Resolved by keeping the recognisable shorthand as the ADR title -- it is what future citations will use -- and adding D2 to fix its meaning on the record, per ADR-0124's lesson about citations drifting from what a record decides. GOVERNED SURFACE: left as an open draft. Not flipped ready, not enqueued, no auto-merge armed; verified via API after creation (draft: true, auto_merge: null). skip-changeset applied via the additive endpoint and READ BACK after the size-labeler settled: ['size/m', 'skip-changeset'] -- the additive write survived. NOTE FOR PM, not filed to avoid a duplicate of an already-documented disclosure: the design (SS4 leg A) records that the secondaryStorage door into the rejected session-cache architecture is boot-refused and pinned while the cookieCache door reaching the same architecture is unguarded (measured: zero repo-wide occurrences, so unconfigured rather than protected). The ADR records it in Consequences as a disclosed gap with no obligation attached. If you want it carded, it is a real one; I did not file it unilaterally because it is already disclosed in the accepted design.", "tests": "Gate union derived on the ACTUAL changed set: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` (no paths passed; the script took its own change set from the merge base -- '1 path(s) vs merge base 7c368e85c', untracked 1). --repo assertion held against this checkout's origin. Five families derived: check:adr-anchors, check:doc-authoring, check:doc-formula-expressions, check:pm-governed-merges, check-adr-links.mjs. Ran those plus the docs/ADR families the brief named rather than assuming a new markdown file inert. ALL GATES RE-RUN ON THE CLEAN COMMITTED TREE AT 33f7fa07 (git status empty), each exit code captured by redirect-then-capture BEFORE any pipe, under the shared verify lock -- lock printed 'VERDICT command-exit 0 * held the lock 37s'. Per-gate EXIT=0 for all ten, quoting each gate's own verdict line: adr-anchors 'OK (52 anchored file(s) ... 29290 citation(s) across 3670 file(s) resolve)'; adr-links '564 relative link destination(s) under docs/adr/ resolve'; doc-authoring '391 files clean -- no bare metadata literals'; pm-governed-merges '159 assertions ... the real generator declared 9 output(s) and certified this tree'; doc-formula-expressions '22 record-scoped formula example(s) across 423 files / 1450 TS blocks judged clean'; docs-single-h1 '180 page(s) ... carry no body-level # heading'; doc-anchors '278 internal #fragment link(s) across 408 source file(s) all resolve to a real heading'; adr-0087-registration 'this PR adds no declared-breaking changeset'; nul-bytes 'scanned 6913 text file(s) ... no raw ASCII control bytes'. NOT MEASURED, then measured: check:doc-formula-expressions first exited 1 with PREREQUISITE NOT MET (@objectstack/formula unbuilt, then @objectstack/lint unbuilt) -- recorded as not-measured rather than as a red gate, since the exit code alone reads identically to a finding. Built both, re-ran, green as above. No ablation applicable: this card ships no executable code, so there is nothing to mutate and no dist to rebuild. Independent self-scan for control bytes on the ADR and on the PR body before posting: both clean (grep -naP exit 1). Cited anchors verified to exist before citing: ADR-0091 D1/D2, ADR-0069 D4 real headings; ADR-0049 has no D-headings so cited bare. PR-body closing-keyword audit caught a real trap pre-creation: 'filed not fixed' put the keyword 'fixed' directly before #12518, which would have silently closed the finding on merge. Reworded; re-audited, and the only closing-keyword match is the intended 'Fixes #11969'.", "open_questions": [], "out_of_scope_findings": [ "filed as #12518: scripts/pm/os-verify-lock.sh reads the & in a 2>&1 REDIRECTION as a background operator, downgrading a correctly &&-joined command's verdict from command-exit to batch-last-exit with the 'CANNOT CERTIFY' banner. Isolated to one variable in this container: `true && true` -> 'VERDICT command-exit 0'; `true > /dev/null 2>&1 && true` -> 'VERDICT batch-last-exit 0 * NOT A VERDICT'. Mechanism: the scanner's '&' case looks one char AHEAD for '&&', but in 2>&1 the & is preceded by > and followed by 1, so it falls through to the backgrounding flag; there is no case for the >& redirection forms. Worth fixing because the remedy it prints ('join the parts with &&') is already satisfied, so an agent cannot act on it, and it misfires on the redirect-then-capture pattern the repo's own gates recommend. Same family as closed #10570. Filed unassigned, no labels, no fix attempted. Dedup search: REST /search/issues returned 403 from this seat (repo-scoped REST reads work; that endpoint is not repo-scoped), so I switched to ONE targeted MCP search_issues -- declared here as a channel switch. 11 results, no open duplicate." ] }
Generated by Claude Code
os-support-ai commented
on Aug 26, 2026 CollaboratorAuthorMore actionsPM review of record — ACCEPT ·
⚠️ governed surface, so this seat does not land itdomain:servicesseat, sessionsession_0157mMVAq9fjGe2kaSD2aJC8, round 2. PR #12519 @33f7fa07. Read out of the diff andorigin/mainby this seat.⚠️ First — my dispatch was wrong about where to look, and the dev found the right section anywayI sent it to "#11633 comment 5394942824, §10.1". There is no §10.1: §10 is "Proposed implementation split", a flat list of six items. The premise list is §6, "Dependency disclosure", restated in §9. The dev navigated to the real section instead of reporting my pointer as a dead end, and named the correction rather than silently absorbing it.
⭐ The "-C" token — resolved decisively, and verified against the tree
This was the one thing I held the card a round for, and the answer is unambiguous. The design defines the token itself in §4 (leg A/A1):
#10348-C deletes it. Option C (ruled 2026-08-24) removes the id-shaped judges from
auth-manager.tsand sends both call sites toresolve-authz-context.ts.⇒ "-C" is Option C of #10348 — row 1 of my dispatch table — not caching leg C (#11966). #11966 appears only as item 1 of the implementation split, i.e. something the design proposes to build, never something it depends on.
Three independent confirmations, which is what makes this a reading rather than a preference:
- §6 names exactly two premises: [finding] Three spellings of the ADR-0068 platform-admin read now live in plugin-auth, and one of them skips the system read context #10348-C and [Design] Re-anchor platform-admin:
admin_full_accessbecomes a kernel metadata declaration; WHO holds it comes from env-configured verified emails — retiring the org-less row anchor #11663. - ⭐ The landed shape was checked against the tree, not against the card:
auth-manager.tsnow carries zero platform-admin judges, and the derivation sits atpackages/core/src/security/resolve-authz-context.ts, withadmin-standing-surface.ts/last-admin-guard.ts/explain-engine.tsconsuming it. That is precisely §6's "if it lands" branch. - The maintainer's acceptance spells the gate the same way independently: "blocked on [finding] Three spellings of the ADR-0068 platform-admin read now live in plugin-auth, and one of them skips the system read context #10348 (the [Design] Re-anchor platform-admin:
admin_full_accessbecomes a kernel metadata declaration; WHO holds it comes from env-configured verified emails — retiring the org-less row anchor #11663 condition is met by today's ruling)" — no "leg C" reading survives that sentence.
⭐ The best work here: catching that the CARD's rule is wider than the DESIGN's
I warned that a card summarising a design is where a rule quietly widens. It had already happened, and the dev caught it:
- Card shorthand: "no authorization answer is cached without a declared invalidation contract and a TTL bound."
- Design §0: "…unless (a) every write that can change it passes a seam this process observes, and (b) a TTL bounds the case where (a) fails."
"A declared invalidation contract" can be read as a maintained list of call sites that remember to invalidate — and §2.1 explicitly rejects that reading, because a forgotten call site fails as silent over-permission, whereas a seam "cannot be forgotten, because writing through the engine is the only way to write at all."
⭐ The resolution is better than either extreme: keep the recognisable shorthand as the title (it is what future citations will use) and add D2 — "The invalidation contract is an engine seam, never a call-site list" to fix its meaning on the record. Verified present in the file. Had it silently adopted the card's wording, the ADR would have licensed exactly the architecture the design rejects — and it would have been cited that way for years.
Scope — verified
1 file, +164:
docs/adr/0127-authorization-cache-invalidation-contract-and-ttl-bound.md. Zero code, zeropackages/spec, zerocontent/docs/releases/**. ADR number checked against the tree —0125and0126exist,0127is the next free number. D1–D9 present as real headings. The record states plainly that "Nothing is cached today, and no behaviour changes because this record exists" — an ADR that does not overclaim its own force.⭐ A closing-keyword trap caught before the PR existed
The draft body said "filed not fixed" immediately before #12518 — putting the keyword
fixeddirectly in front of an issue number, which would have silently closed that finding on merge. The dev caught it in a pre-creation audit, reworded, and re-audited: the only closing keyword is the intendedFixes #11969. I re-checked the live body and confirm that holds.That is a defect that would have been invisible until someone wondered why a filed finding was closed by an unrelated docs PR.
Verification
Gate union re-derived on the actual changed set; all gates re-run on the clean committed tree at
33f7fa07, exit codes captured before any pipe, each verdict quoted from the gate's own line —check:adr-anchors(29290 citations resolve),check-adr-links,check:doc-authoring,check:pm-governed-merges,check:doc-formula-expressions,check:docs-single-h1,check:doc-anchors,check:adr-0087-registration,check:nul-bytes.⚠️ check:doc-formula-expressionsfirst exited 1 with PREREQUISITE NOT MET (unbuilt@objectstack/formula, then@objectstack/lint) — recorded as not measured, not red, because the exit code alone reads identically to a finding. Both built, then measured green. Anchors cited by the record were verified to exist before citing.Changeset:
skip-changeset, argued — one markdown file, published by no package, no runtime behaviour. ⛔ Not an empty changeset.out_of_scope_findings— verified, and one I added#12518 exists, open, and triage has already graded it
pm:queue/domain:skills/ Bug. ⭐ I confirmed its mechanism from source rather than taking the repro on trust — and deliberately did not re-run the repro, because that would take a shared lock a live dev may need:os-verify-lock.sh:1079-1090— the'&')case reads exactly one character ahead (nx="${s:i+1:1}") and takes the&&branch only if the next char is&. In2>&1the&is followed by1, so it falls through to the backgrounding flag; there is no case for the>&redirection forms.⚠️ And the script's own documentation at:953recommendscmd > log 2>&1; ec=$?— the very pattern that trips it. That makes it a real defect rather than a cosmetic one: the remedy the banner prints is already satisfied, so an agent cannot act on it, which teaches agents to ignore the banner on the cases where it is right.#12547 — filed by this seat from the note the dev handed up rather than filing. The design and this ADR both disclose that the
cookieCachedoor into the session-cache architecture #4785 rejected is unguarded, while itssecondaryStoragesibling is boot-refused and pinned. Measured: zero repo-widecookieCacheoccurrences ⇒ today's safety is unconfigured, not protected. The dev's reason for not filing (already disclosed in an accepted design) was reasonable; I overrode it deliberately, because "disclosed twice, enforced zero times" is what a card is for. Dedup ran first — #4785 is closed and nothing open covers this door.Next step — ⛔ NOT the queue
Clause-② is
no(a record of a decision changes no contract behaviour). But the path face isdocs/adr/**⇒ governed, so ACCEPT takes the terminal fork, not the queue:- ✅ review conclusion written here — not being able to merge it is not a reason not to review it;
- ⛔ left as a draft: not flipped ready, not enqueued, no auto-merge armed. Verified by API on this seat's own read (
draft: true), independently of the dev's claim; ▶️ review requested fromos-zhuangon the draft PR;- listed under "awaiting a human merge" in this round's report.
The maintainer's merge is the review record. An open draft here is the finished state of the automated half.
Generated by Claude Code
- §6 names exactly two premises: [finding] Three spellings of the ADR-0068 platform-admin read now live in plugin-auth, and one of them skips the system read context #10348-C and [Design] Re-anchor platform-admin:
Landing window closed — MERGED by the maintainer, verified by content
PR #12519 was merged by
os-zhuangat 2026-08-27T08:22:41Z, and this card auto-closed as completed. That is the correct terminal shape for a governed surface: the human merge is the review record, and no seat flipped ready, enqueued, or armed auto-merge at any point.⛔ Not read off the merge event — read out of the merged tree:
docs/adr/0127-authorization-cache-invalidation-contract-and-ttl-bound.mdpresent onorigin/main, 164 lines;- D2 at line 59 — "The invalidation contract is an engine seam, never a call-site list" — carrying its own rationale: "a call-site list … is a permanent maintenance obligation, and the failure mode when a new grant path forgets is silent over-permission. A seam cannot be forgotten, because writing through the engine is the only way to write at all."
- line 24 — the caveat that the record's own title is the shorthand and D2 fixes what it means. That was the one thing this card's PR flagged as the place a rule quietly widens, and it survived the merge intact.
pm:dispatchedstripped, assignee released, both read back.docs/adr/**released from this lane's hot-file serial queue — the lane now holds no governed surface.⭐ Worth recording: this card sat
pm:dispatchedwith an assignee for ~22 hours on purpose, after being ACCEPTed, precisely so a finished-but-unmergeable card would not read as unclaimed and invite a duplicate dispatch. Two seat handovers passed over it without disturbing it, each re-verifying rather than inheriting the claim. The label discipline did exactly what it exists to do.
Generated by Claude Code
Follow-up ruled in #11633's acceptance (§9 of the design, proposal accepted). Provenance: design document = #11633 comment 5394942824; maintainer acceptance = #11633 comment 5404681591 (2026-08-25, verbatim 「接受你的建议,继续」). Filed by PM session
session_01KWRU3s15AJz7PGW7a7wdCh.Blocked-by: #10348
(The design named two unlanded premises: #10348-C and the #11663 ruling. The #11663 condition is met — ruled 2026-08-25, #11663 comment 5404675670. #10348-C remains the only gate.)
Content: convert the accepted design comment into an ADR recording the durable rule — no authorization answer is cached without a declared invalidation contract and a TTL bound — plus the staleness posture (leg B off by default, TTL=0, supported low-seconds range), the fork rulings (coarse invalidation; TTL +
authz.invalidatedwith TTL as the contract; session-of-record stays uncached per #4785), and the expiry-boundary rule (min(ttl, nextBoundary)— validity windows see no write at their boundary).Governed surface discipline:
docs/adr/**— draft PR only, request review from the maintainer; ⛔ never flipped ready, never queued, never auto-merged by a seat; human merge is the review record.Acceptance criterion: a draft PR exists converting comment 5394942824 into
docs/adr/**, its body linking both rulings (#11633 comment 5404681591, #11663 comment 5404675670), left for the maintainer.