Skip to content

Latest commit

 

History

History
378 lines (341 loc) · 184 KB

File metadata and controls

378 lines (341 loc) · 184 KB

bd HTTP mode — the divergence ledger

This is the shipped, human-readable rendering of divergence ledger v1: every place bd's HTTP client mode observably differs from local (embedded/served) mode, each with its reason and the test that pins it.

The discipline (design decision D9) is empty-by-default and test-asserted: every knowingly-degraded behavior is a ledger row with a pinned test, and a degradation not in this table is a bug. refuse rows fail rather than proceeding — a dropped filter widens a result set invisibly, the one failure class no server-side gate can observe — while degrade rows proceed with a difference argued to be unmisreadable as a narrower or wider answer than the caller asked for.

This file is generated from internal/httpclient/encode's Ledger(), the machine-readable source the client actually consults. Do not hand-edit it: change the ledger in Go and regenerate. Two gates keep it honest — the encoder's reflection bijection gate pins the ledger to the wire (a request field added upstream lands here or fails CI), and the golden test TestDivergenceLedgerDocMatchesLedger pins this doc to the ledger. The prose rationale and the decision numbers (D-rows) each entry cites trace back to the original (bd-enterprise-internal) design's decision log, which is not included in this repository; the full test-lane map lives alongside each row below.

A handful of rows still carry a TODO pin: these are the read-display and pre-run residuals (wisp-in-list, the pretty bd ready parent-epic map, the molecule/auto-import pre-run degradations). The client core is complete; a since-closed per-request project-id enforcement follow-up closed the read-display escalation, so pinning the remaining fixture corpus is deferred work (tracked as a read-display residual and a per-id D7 taxonomy follow-up). They are refusals or degradations already in force — the TODO is on the test that will hold each one, not on the behavior.

Kind

  • refuse — the operation fails; the wire cannot express what was asked and proceeding would silently widen or narrow the answer.
  • degrade — the operation proceeds with a knowingly different behavior that cannot be misread as a different answer to the question asked.
  • retired — a row a later council removed; kept so its L-number keeps resolving and a re-enumeration can tell "retired" from "never existed".

Summary

264 rows: 204 refuse, 34 degrade, 26 retired.

Whole-behavior divergences (D9 ledger)

The L-rows the design's D9 table names: whole behaviors that differ over HTTP, each degraded knowingly or refused outright. Retired rows stay so the L-numbers every citation uses keep resolving.

ID Kind Field / flag Divergence Why Spec Pinned test
L1 retired — RETIRED — bd list over http could not ask for the wisp plane retired by the upstream ask the design page filed for it: "include_ephemeral on listIssues (retires L1)". Upstream published the parameter, the server decodes it (internal/httpapi/reads.go handleListIssues), and the encoder emits it whenever ListRequest.IncludeEphemeral is set. THERE IS NO DIVERGENCE LEFT TO RECORD. bd list still shows no wisps, but it shows none LOCALLY either: the front door registers no --include-ephemeral (only bd ready does, ready.go), so the field is unset on both paths and both answer the durable plane. A degrade row describing behavior the local oracle shares is not a degradation, and keeping it as one would be the same falsified-premise problem the W- rows had — a ledger arguing from a document that moved D9 L1 (RETIRED), D8 row 1 TestEncodedParametersRoundTripThroughTheServerDecoder
L2 degrade — a non-created bd list sort, the flagless default included, costs page-to-exhaustion on the three legs that cannot push the order down: an unlimited read (--limit 0), a caller-supplied keyset position, and a server that does not advertise issues.list.sort NARROWED, not retired, by the upstream ask this row named: listIssues publishes sort and reverse, and the pager's pushdown leg (list_walk.go sortedPage) answers a bounded, position-free request against an advertising server in ONE request, with the server's own LIMIT deciding which rows survive the caller's order. What is left is the legs where that is unavailable or unsafe. An unlimited read has to cross every row whatever the order, and limit=0 pushed down would newly meet the server's unlimited-read refusal. A keyset position is defined in the created order, and the pager's prefix discard run against a page some other order truncated would drop rows whose replacements were never fetched — a wrong answer rather than a slow one. A down-level server is the fallback the capability probe exists to reach. On all three the client still fetches every page and applies the SQL order's own Go-side mirror plus a copy of the page epilogue's comparator. The weld itself is NOT a divergence and never was: a cursor is bound to the paged order it was minted in (created or priority) and the server refuses it under any other sort D9 L2, D8 row 1 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L3 degrade — a multi-page fetch has no snapshot isolation the keyset cursor pins a position, not a snapshot: rows created mid-walk are missed and row states mix instants, where local mode is one query D9 L3 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L4 retired — bd show dependents sections and comment bodies were degraded retired by council #1: the write-lifecycle wave landed include_dependents/include_comments on getIssue, and both the off-role text path and the on-role JSON path are wired D9 L4 (RETIRED), D4, D8 row 1 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L5 degrade — molecules are not auto-loaded pre-run the loader writes, the write refuses, and the call site swallows the refusal to debug.Logf D9 L5, D4 TODO(S3): a pre-run degradation, observable only through a cmd/bd invocation; the subprocess parity corpus pins it
L6 degrade — a pre-run auto-import ATTEMPT reaches an http workspace and fails as a best-effort stderr warning; nothing is imported THE MECHANISM THIS ROW USED TO NAME DOES NOT EXIST. It said the path was "force-disabled through an import.auto=false env override", and there is no such override anywhere: shouldRunAutoImportJSONL (cmd/bd/main.go) reads the config key, whose default is true (internal/config/config.go), and no http path sets it false. WHAT ACTUALLY HAPPENS is that maybeAutoImportJSONL runs — on any non-read-only, non-global, non-server-mode command — and is stopped by its own guards rather than by a switch: a missing or empty issues.jsonl, the attempt stamp, or the emptiness guard, which is a GetStatistics the server serves. Where all three pass (an empty server beside a non-empty local JSONL) the import is attempted and fails, because the client is not a jsonlImporter and the fallback importer's first write — SetConfig, or CreateIssuesWithFullOptions — is on the unsupported allowlist. The function is documented best-effort, so the failure is an stderr warning and the command proceeds. The DEGRADATION is therefore that nothing imports, which is the outcome the design wanted for the right reason — importing a local JSONL into a shared server is not a pre-run side effect — reached by refusal rather than by configuration. It stays a degrade because the command proceeds and the answer is not narrower or wider than the caller asked for. The retirement path is a real skip on the http backend, so the warning stops being the mechanism D9 L6, D4 TODO(S3): a pre-run degradation, observable only through a cmd/bd invocation; the subprocess parity corpus pins it
L7 degrade — the client-side status/type vocabulary is defaults plus the status.custom/types.custom/types.infra config keys; table-backed customs are invisible client-side the custom_statuses/custom_types tables have no wire operation; server-side role validation still uses the true vocabulary D9 L7, D4 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L8 degrade --deps bd list --deps and the policy decorator's compatibility fallback for its whole-workspace blocking state (design 3.6) both work, but by a client-side chunked scan rather than a single wire call GetAllDependencyRecords has no 1:1 wire mapping in v1 — listDependencies is anchored at <=100 ids per call (L12's maxEdgeCountAnchors) — so the client enumerates every issue id (fetchIssuePages) and issues it in chunks, grouping the results itself; this is slower and heavier than a local store's single query, not absent. --tree is NOT in this row: it defaults true and is bd list's default text rendering. The decorator takes that scan for its whole-workspace answers: ready work and its counts, the ready claim, and the single-issue close guard. Its per-issue roles (blocking annotation, the dependency tree, claim, and a batch close without a next claim) build on the client's served roles instead and read only the edges of the issues they name, through the served EdgeReader in chunks under the same cap (internal/storage/externaldeps/remote_roles.go) D9 L8, D4 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L9 degrade — credential-bearing settings are unreadable client-side the server redacts by omission and says so on the wire in Setting.redacted; the client answers absent-WITH-A-REASON rather than the empty string a caller would read as unset D9 L9 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L10 refuse --watch bd list --watch and bd show --watch refuse the loops poll every 2s, each bd list tick is a full cursor walk (L2), per-tick errors spam or vanish, and the decoration is refused anyway (L8); N watchers against one server is a request storm its semaphore answers with 503s the loop does not back off from D9 L10, D10 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L11 degrade — hooks fire client-side after the server's commit with no shared transaction, on connected workspaces only the seam sits below HookFiringStore in the client process; a --server-url ephemeral invocation has no hook directory and runs none D9 L11, D1 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L12 refuse — an inexpressible filter refuses, never drops — the class rule every E- row below is an instance of a dropped filter widens a result set invisibly, and the server can only reject parameters it receives D9 L12, D7 TestEncoderHonorsEveryTableDisposition
L13 degrade — pretty bd ready shows no parent-epic context buildParentEpicMap swallows the GetDependencyRecordsForIssues refusal into a nil map; the retirement path is an anchored listDependencies plus per-parent getIssue D9 L13, D4 TODO(S3): a pre-run degradation, observable only through a cmd/bd invocation; the subprocess parity corpus pins it
L14 degrade — against a server that does NOT advertise issues.claimNext, or on the CLI's chain while any issue in the workspace, closed ones included, holds an unsatisfied external ref, a composed ReadyClaimer leaves three residues: the ready-at-fetch/claim-at-dial window, a false empty under contention after the bounded refetch, and a claimed row whose CARDINALITIES are as of the listing rather than of the claiming transaction claimIssue validates claimability, not readiness, so a listing plus a claim is not the local role's one transaction and cannot be made into one. THE ROW IS NARROWER THAN IT WAS. Upstream published POST /v0/beads/issues:claimNext (#5510) and client wave ga-jpywb dials it, so on any server that advertises the token NONE of these three residues exists: selection, the compare-and-set and the hydration share the server's own transaction, an empty front is a 200 with claimed absent rather than a lost-races error, and the counts describe the state the claim produced. The whole ReadyClaimer contract tier runs against that leg with nothing parked, which is the measurement that says the residues were the COMPOSITION's rather than the wire's. WHAT KEEPS THE ROW ALIVE is the DOWN-LEVEL leg, which survives on purpose: bd ready --claim worked against pre-#5510 servers before this port, and refusing it now would be a regression dressed as progress. It is the posture BatchCloser takes toward issues.batchClose, and it is why this row describes shipped behavior rather than history. The third residue is stated in its IMPLEMENTED form, which is not the one the design anticipated: the design expected a follow-up getIssue to hydrate the counts, and therefore a read that could fail AFTER the claim was durable. The composition takes the counts from the ready page it already fetched instead, so that failure mode does not exist — a claim changes no dependency, dependent or comment count, and what is left is staleness bounded by the same fetch-to-dial window residue (a) already owns. A SECOND COMPOSED LEG exists on any server. On the CLI's chain the external-dependency decorator (design 3.6) hands the claim to this role only while no issue in the workspace holds an unsatisfied external ref, because claimNext has no parameter to exclude what that policy refuses. Otherwise it claims down its own filtered ready page through the served Claimer, so all three residues return, the second as a lost-races error (internal/storage/externaldeps/remote_roles.go). A closed holder counts, as it does in every backend's blocking state: it can never be a candidate, so the composed claim picks what the served one would, and leaving it out would cost a status read per holder. A server that advertises wire.CapExternalDependencies enforces the policy itself and never reaches that leg. bd close --claim-next takes no composed leg: the decorator refuses it rather than claim after the close commits (F-close). Retirement of the down-level leg is no longer an upstream ask but a fleet fact: it goes when no server this client may meet is older than #5510. The decorator's leg goes with an exclusion parameter on claimNext, or once every server enforces the policy itself D9 L14, D8 row 4 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L15 degrade — a --max-rows cap can fire over http on a query whose Limit is at or under the cap, on the bd list legs that still walk locally the effective SQL LIMIT is min(Limit, MaxRows+1), so a window at or under the cap can never exceed it; over http a walk to exhaustion fetches far more than the window and the cap deliberately bounds WIRE ROWS FETCHED — safety wins over exit-code parity on exactly the unbounded walk the cap exists to bound. NARROWED by the same pushdown that narrowed L2: the pushdown leg asks for min(limit, MaxRows+1) rows in one request, which IS the local expression, so a cap at or above the limit can no longer fire there and a request that used to exit 2 now answers. That is a convergence toward the contract, and it is observable — the same command changes from a refusal to a page. THE NARROWING IS SCOPED TO THE ORDERS SQL CAN EXPRESS, and that scope is a correctness bound rather than an optimization left on the table. For a GO-SIDE sort — sqlbuild.IsGoSideSort, today --sort id, which needs the natural-numeric comparison (bd-9 before bd-10) no ORDER BY renders — workapi.SQLLimit pushes 0 down instead of the limit, so LOCALLY the window is MaxRows+1 whatever the limit is and the cap fires on the overage even under a limit at or below it. min(limit, MaxRows+1) is therefore NOT the local expression there, and a request bounded by the limit cannot see the overage at all. walkIssues' gate keeps a capped Go-side sort on the walk, where fetching MaxRows+1 wire rows reproduces that unbounded local window exactly and raises the same refusal — so on this one shape the walk leg is the CONVERGENT one and pushing down would have been the divergence. What keeps the row live is the walk legs (unlimited reads, keyset positions, down-level servers), where the old accounting is unchanged and correct, and bd ready, which has no pushdown at all D9 L15, D12 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L16 refuse --file bd dep add --file carrying more than 100 edges refuses, naming the wire bound; it is never chunked maxAddDependencyEdges = 100 (internal/httpapi/dependency_edit.go); chunking is the one path that silently breaks the request's one-transaction/one-history-entry contract, where naive forwarding at least fails loudly D9 L16, D7, D8 row 18 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-close-cap refuse — a batch close naming more than 100 items refuses, naming the wire bound; it is never chunked maxBatchCloseItems = 100 (internal/httpapi/batch_close.go); the item cap bounds how long one request may hold a write transaction. Chunking is the one path that silently breaks the request's one-transaction/one-history-entry contract — the same reason L16 refuses a bulk dependency add rather than splitting it — so a larger list refuses and the caller splits it, each request atomic on its own D9 L-close-cap, D7 F-close, D8 row 17 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-dep-endpoint degrade — a dependency add whose source or target names no issue refuses as ErrValidation over http, not as *DependencyEndpointNotFoundError wrapping ErrDependencySourceNotFound or ErrDependencyTargetNotFound the wire spells that refusal as a 400 invalid_argument with reason invalid_value and the offending member in param (internal/httpapi/dependency_edit.go). Reason and code are the same ones a malformed id earns, so the two are indistinguishable without reading detail prose — which is exactly what the extension-member vocabulary exists to avoid. The refusal still FAILS the request and still writes nothing; only its classification is coarser. Upstream ask: a distinguishing code or reason for the endpoint-not-found refusal, which retires this row D8 row 18 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-claim-prose degrade — a claim refusal's MESSAGE does not carry the ClaimedBy/NotClaimableStatus fragments, so beads.ParseClaimConflict recovers nothing from it over http the fragments exist so that parser can recover the conflicting assignee and status from PROSE. Over the wire both arrive as typed extension members and *ClaimConflictError is reconstructed whole, so a caller reading the FIELDS loses nothing. Recomposing the copy client-side would mean re-implementing which copy each refusal shape gets — an open issue held by someone else deliberately omits the assignee tail, an in-progress one carries it — which is a second implementation of the very rule the fragments were introduced to keep single D8 row 3 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-delete-notfound degrade — issueops.Deleter.Delete over http refuses an absent id as issueops.ErrNotFound, not as *NotFoundError naming WHICH ids did not resolve the role's error is a typo report and names every missing id; the wire deliberately does not repeat them (internal/httpapi's NotFound() carries a FIXED detail, so a 404 body cannot echo caller input back). The refusal still FAILS the request and still deletes NOTHING — not even the ids beside the typo — so the all-or-nothing promise is intact and only the classification is coarser. It is stated at the ROLE rather than at a command because bd delete is not reachable against an http workspace at all (see httpUnconsumedCapabilities); the embedder holding the role is the audience. Upstream ask: an ids extension member on the not_found problem, which retires this row D8 row 13 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-delete-dependents degrade — the unforced dependents guard refuses as issueops.ErrValidation, not as *DependentsOutsideRequestError wrapping ErrDependentsOutsideRequest the wire spells that refusal as a 400 invalid_argument with no param (internal/httpapi's failDeleteErr) — the fix is to change the REQUEST, by sending cascade or force — so the blocked id and its dependents cannot be reconstructed without parsing detail prose, which is what the extension-member vocabulary exists to avoid. The guard itself is untouched: the request fails and the graph is whole. Upstream ask: a dependents_outside_request code carrying issue_id and dependents, which retires this row D8 row 13 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-delete-bound refuse — issueops.Deleter.Delete refuses a request naming more than 1000 ids, citing the wire bound; it is never split across requests maxDeleteIDs = 1000 (internal/httpapi/delete.go). Splitting is the one path that silently breaks the request's one-transaction, one-history-entry contract — and it would ask the dependents guard about half a request at a time, so a pair the caller deliberately listed together would be refused as an outside dependent. Naive forwarding at least fails loudly. Stated at the ROLE: bd delete cannot reach an http workspace, so the embedder is the audience D8 row 13, D9 L16 (the same argument, on the other bulk write) TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-batchcreate-bound refuse — bd create --file carrying more than 100 issues refuses, naming the wire bound; it is never split across requests maxBatchCreateItems = 100 (internal/httpapi/batch_create.go). The request IS the transaction, so two requests are two transactions and two history entries where the role promises one — and a failure in the second leaves half a plan created, which is the outcome all-or-nothing exists to make impossible D8 row 14, D9 L16 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-edgecount-bound refuse — issueops.GraphCounter.CountEdges refuses a request naming more than 100 DISTINCT anchors, citing the wire bound; it is never chunked across requests maxDependencyAnchors = 100 (internal/httpapi/edges.go), the same bound the stored-edge read on this collection carries — the role deliberately sets none of its own and says the bound belongs to the WIRE. Chunking is what a READ could get away with and this one cannot: CountEdges promises that an anchor's EXISTENCE and its edge count are read from one consistent view, so two requests would let an anchor be reported missing by a probe that raced a create the other chunk's count already saw — one answer contradicting itself, which is the exact failure AnchorEdgeCount.Missing exists to make impossible. Refusing at the bound fails loudly instead, and the caller splits the question knowing it asked twice. Upstream ask: a cursor or a higher bound on the anchor list, which retires this row D9 L16 (the same argument, on a read), D8 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-cycles-tracks refuse DetectCyclesRequest.IncludeTracks issueops.CycleDetector.DetectCycles refuses a request with IncludeTracks set, rather than silently answering the narrower (tracks-excluded) walk listDependencyCycles (wire.OpListDependencyCycles) publishes no include_tracks parameter at all — there is no wire member to widen the walk onto, not merely one this client chose not to send. Honoring the request field anyway (by just not sending it, the way a dropped filter would) would answer the DEFAULT walk to a caller who explicitly asked for the wider one that also follows tracks edges: a narrower answer with no error, exactly the failure mode ErrUnsupported exists to make loud instead of silent (see its own doc). Upstream ask: an include_tracks query parameter on listDependencyCycles, which retires this row D8 (refuse-not-drop), D9 L16 (the same argument, on a read) TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-batchcreate-target degrade — a batch create whose edge target names no issue refuses as issueops.ErrValidation alone, not as ErrValidation WRAPPING ErrNotFound the wire answers a dangling edge target with a 400 invalid_argument naming items (internal/httpapi's failBatchCreate), and deliberately does not quote the role's own message, which arrives as a driver error naming tables and constraints. The refusal still fails the whole batch and creates nothing — the promise the row is about — and only the second sentinel is lost. Upstream ask: a distinguishing code for the absent-target refusal D8 row 14 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-batchcreate-inbatch refuse — an edge onto an EARLIER ITEM OF THE SAME BATCH cannot be expressed at all over http the capability needs the earlier item to have named an id for itself, and apigen.BatchCreateItem publishes no id member — an explicit id is refused with the rest of W-BatchCreateItem.Issue. So the target of an in-batch edge can only be a row the workspace already holds. It is a REFUSE row rather than a degrade because the request that asks for it fails: the client refuses the explicit id before the dial, and there is no second spelling that would land the edge silently. The wire's own target_id description names this case, so the gap is in the SCHEMA rather than in the handler — the upstream ask is an item id member, which retires this row D8 row 14 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L18 degrade — DOWN-LEVEL ONLY: against a server that does not advertise issues.batchClose, a single-id bd close still composes onto closeIssue and records the SERVER's own close commit message rather than the batch's id-naming entry; the multi-id and --claim-next shapes refuse there the composed leg is one closeIssue call, so the history entry it leaves is the one that operation writes for itself — the batch's entry names the ids it closed and this one cannot, because no batch ran. Where issues.batchClose IS advertised the whole request is one call and one server-side transaction, so this divergence does not arise at all; the down-level leg survives on purpose, because bd close worked against pre-batchClose servers before this port and refusing it now would be a regression dressed as progress. It is the same posture L14 takes toward issues.claimNext. It is a degrade rather than a refuse because the close LANDS and the answer is neither narrower nor wider than the caller asked for — only the record of it is the operation's rather than the batch's. Retirement is a fleet fact rather than an upstream ask: the row goes when no server this client may meet is older than issues.batchClose D9 L18, D8 row 17 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-create-notfound degrade — a create whose dependency or waits-for target names no row refuses as issueops.ErrValidation ALONE — not as ErrValidation wrapping ErrNotFound — and does not name the target the wire answers a dangling target with a 400 invalid_argument naming dependencies and a FIXED detail (internal/httpapi's failCreateIssue), which deliberately does not quote the role's own message: that message arrives as a driver error naming tables and constraints, and 4xx details on this surface reflect the caller's own input back rather than server internals. The refusal still fails the whole request and creates NOTHING — the promise the row is about — and only the second sentinel and the target's name are lost. It is batchCreateIssues' L-batchcreate-notfound on the single create, and it retires the same way: an upstream code that distinguishes the absent-target refusal and carries the target. A missing --parent target stays on this row beside dependency and waits-for targets, not ahead of them: OpCreateIssue's problem-code table documents NO 404 for ANY edge target on purpose (internal/httpapi/problem.go) — there is no id in the path for parent_id to have missed any more than dependencies[i].target_id or waits_for.spawner_id has, so carving a parent-only not_found out of this row would contradict that design rather than follow it. A prior draft of this row and its pin (TestServedCreateRefusesAnAbsentParentAsNotFound) described that carve-out as already shipped; it never was, and the S3 review that found the drift retired the draft rather than the design D8 row 16 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-create-prefix degrade — an unforced explicit id outside the workspace's configured prefix refuses as issueops.ErrValidation rather than as storage.ErrPrefixMismatch the wire spells that refusal as a 400 invalid_argument with param: "id" and reason: invalid_value (internal/httpapi's failCreateIssue), which is the SAME pair a malformed or oversized id earns — so nothing on the wire tells the two apart, and reconstructing the typed sentinel from the pair would misclassify every other refusal of that member. The guard itself is untouched: the id is refused, nothing is created, and the detail names force_id_prefix as the bypass, which is the recovery a caller needs. What is lost is the errors.Is arm both local front doors use to decide whether to re-offer the create with --force. Upstream ask: a prefix_mismatch code, or a reason that distinguishes it, which retires this row D8 row 16 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-apply-snapshot degrade — every ItemResult of a batch apply comes back with Issue nil, where a local backend hydrates a post-item snapshot the WIRE result is lean by the document's own decision and the role's leaf says why: ApplyItemResult carries ids, changed and revision and no issue, because the Go contract carries the snapshot for its COMPLETION HOOKS — which hand a script the row they are telling it about — and hooks never fire on the http surface at all. A hundred hydrated issues with their labels and edges would be a response an order of magnitude larger than the request that produced it. What a caller loses is a read it can make: the ids ARE published, per item and through Keys, so the rows are one getIssue away and the plan's next step is composed from ids rather than from snapshots. It is a degradation rather than a refusal because nothing about the WRITE differs — every item landed exactly as asked — and refusing would make the whole operation unavailable over http to keep a member no consumer on this surface can use D8 refuse-not-drop (result half) TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-apply-ref degrade — an unresolvable metadata_refs key comes back as a *RefError naming the MEMBER rather than the key, and the reconstructed error replaces the server's problem envelope the wire's 400 names the offending member in param — items[3].create.metadata_refs — and carries the item index, the item's key and declared_later, but not WHICH entry of the refs map failed: the role's RefError.Member is diagnostic prose (metadata_ref <key>) rather than a vocabulary, so the server maps it onto the document's own member names instead of publishing it. The two ADDRESSING refs, target and source, are named exactly. The envelope is dropped because issueops.RefError has nowhere to put it: its Unwrap is hardcoded to ErrValidation and it carries no member for a cause, which is the role type's shape rather than a choice made here. The discriminator a caller ACTS on — an ordering mistake against a typo — survives whole, in both polarities. Upstream ask: a typed ref-key member on the problem document, which retires this row D8 refuse-not-drop (result half) TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-comment-author degrade — a comment's AUTHOR is subject to the server's own actor rule, which no local leg applies: it is stored TRIMMED where a local backend stores it verbatim, and one carrying a control character is refused (issueops.ErrValidation) where a local backend stores it the operation validates author with the actor rules whole (internal/httpapi's validateNameMember: trim, refuse empty, refuse past 256 bytes or 255 characters, refuse any control rune) and passes the TRIMMED value on to the role, while issueops.ValidateAddCommentRequest checks only that the field is non-empty and stores what it was given. So the same request produces a different STORED VALUE on the two legs, and a value one leg stores the other refuses. IT IS THE SERVER'S RULE AND THE DOCUMENT PUBLISHES IT, which is why this is a ledger row rather than a bug on either side: the schema states the trim and the character rule in as many words, and the reason is the column — author is 255 characters wide and every renderer of the thread prints it, where an unfiltered C1 introducer is an escape-sequence payload. The refusal half is a NARROWING the wire makes on purpose. THE CLIENT DOES NOT ANTICIPATE EITHER HALF, and that is the decision this row records. Trimming here would make the client agree with the server about the stored value and disagree with the role's own contract — and it would silently rewrite a caller's request, which is the one thing this seam never does. Refusing the control rune here would be a second copy of a server rule that is free to move. So the value travels as the caller wrote it and the server's answer is reported unchanged, which keeps the divergence visible instead of laundering it. IT IS A DEGRADE RATHER THAN A REFUSE because the ordinary path PROCEEDS: a well-formed author is stored, and the difference cannot be misread as a wider or narrower answer — a comment lands on the thread the caller named either way. The refusal half is the SERVER's, not this client's refuse-not-drop, which is what KindRefuse classifies. What a caller loses is an author whose surrounding space survives, and the recovery is the one the role's own contract already implies: compose the author from a value you would be willing to see printed. Upstream ask: either the role trimming its own author on every leg, or the operation storing it verbatim — the rows agree the day the two rules become one D8 row 19 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-release-notclaimed degrade — a release of a row that holds NO CLAIM answers issueops.ErrNotReleasable rather than issueops.ErrNotClaimed; a status that will not accept a release answers ErrNotReleasable as it does everywhere the role splits the two — ErrNotClaimed for a row nobody holds, ErrNotReleasable for a status the transition is not defined over — and the wire spells BOTH not_releasable under one code, with no member telling them apart. That is the server's deliberate choice (internal/httpapi's CodeNotReleasable) rather than an omission, and its detail names both conditions instead of guessing between them. So this client maps to the WIDER of the two, which is the only honest read: reconstructing ErrNotClaimed would assert a fact about the row that the wire never sent, and scraping the detail for it would bind a sentinel to prose. NOTHING ELSE ABOUT THE REFUSAL MOVES — nothing is written, the row and its version are untouched, and the conditional path is unaffected: a caller that named a holder gets ErrAssigneeMismatch on both sides, because that refusal has a code of its own. The caller who loses something is the one that told 'I already released this' from 'the row was never claimed', and the recovery is the one the server's own detail prescribes: READ THE ROW rather than retrying blind. Upstream ask: a code, or a member, that distinguishes the unheld row from the unreleasable status — which retires this row D8 (Releaser), D9 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-release-notowner degrade — an unforced, unconditional release by an actor that is NOT the holder answers issueops.ErrAlreadyClaimed — carrying *issueops.ClaimConflictError — rather than issueops.ErrNotOwner the wire answers the ownership fence with already_claimed, which is the code updateIssue already gives the same situation (a live foreign owner refusing a write, with a force bypass and a name-the-holder bypass), and this client maps that code to the sentinel every other operation means by it. The two sentinels are distinct values in issueops and neither wraps the other, so the arm a caller writes differs. REPORTING IT AS ErrNotOwner WOULD BE THE WORSE TRADE, not merely a different one: the code is shared with the claim refusals, so a client that special-cased it for this operation would be reading the OPERATION to decide the sentinel rather than the code — and would then answer ErrNotOwner for a genuine already_claimed the day the server reuses the code here for anything else. WHAT SURVIVES IS EVERYTHING A CALLER ACTS ON: the refusal is typed, it names the row (the request supplied the id the wire leaves out), nothing is written, and BOTH bypasses answer exactly as the role says — force releases the foreign claim, and naming the holder in expected_assignee releases it too, because a match replaces the fence. The wire deliberately sends no assignee member here, so the holder is not named: absence means 're-read the row', never 'nobody holds it'. Upstream ask: a code, or a member, that separates the release's fence from a claim conflict — which retires this row D8 (Releaser), D9 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-config-bounds degrade — a setting VALUE past types.MaxTextBytes bytes, and a setting KEY past types.MaxFieldLen characters on the WRITE, are refused with issueops.ErrValidation naming the member; on a local leg the same request reaches the column and fails with the engine's own too large for column error, which is no sentinel at all the bound belongs to the OPERATION rather than to the role: internal/httpapi's settingWriteKey and settingValue check both before the role is called, because a request the caller could have fixed should be a 400 naming the member rather than the 500 a column overflow would otherwise produce. workapi.ValidateSettingWrite — the rule every leg shares — applies no length bound at all, so below the wire the column is the only check there is. MEASURED, not inferred: a 65536-byte value answers 400 invalid_argument: \value` is 65536 bytes; storage holds at most 65535over http andError 1105: string ... is too large for column 'value'` on the embedded leg, and a 306-character key splits the same way. Exactly 65535 bytes is accepted on both. THIS CLIENT RESTATES NEITHER BOUND, and that is the decision this row records. They are the SERVER's policy on a value whose shape the role accepted, one release away from moving, so a second copy here would either drift or refuse a request a newer server would take — the same argument L-comment-author makes about the author rule, and the same posture. What travels back is the operation's own 400, which the problem mapper turns into ErrValidation. IT IS A DEGRADE RATHER THAN A REFUSE because the ordinary path PROCEEDS and because the divergence runs in the CALLER'S FAVOR: over http an oversized write is a typed, member-named refusal that wrote nothing, where a local leg hands back a driver error no caller can classify. What a caller loses is nothing; what a caller must not assume is that a value a local workspace stored will store here. THE TWO BOUNDS ARE NOT SYMMETRIC ACROSS THE VERBS, and the asymmetry is the operation's: DELETE checks only that the key names something, so removing a 306-character key succeeds over http exactly as it does locally. Upstream ask: the length rules moving onto the shared validator, which retires this row by making the two legs one D8 row 11, D9 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-update-fieldlen degrade — an updateIssue patch member past types.MaxFieldLen characters — a label on any of the three label members, title, external_ref — is refused with issueops.ErrValidation naming the member; on a local leg the same request answers types.ErrFieldTooLong the bound is applied TWICE and identically: internal/httpapi/update.go checks types.CheckFieldLen at the edge before the role is called, and internal/storage/issueops applies the same function below it. So this is a classification divergence and not a policy one — a value one leg stores the other stores, and a value one leg refuses the other refuses. WHAT COARSENS IT is the spelling: the operation refuses with invalid_argument and reason invalid_value (internal/httpapi's refuse on the patch member), which is the SAME pair a malformed status, an unparseable timestamp or any other bad value on the same member earns. Nothing on the wire tells them apart, so reconstructing ErrFieldTooLong from the pair would misclassify every other refusal of that member — the argument L-create-prefix makes about the id, on the patch. MEASURED, not inferred: a 256-character label answers 400 invalid_argument: \add_labels[0]` is 256 characters; storage holds at most 255over http and ErrFieldTooLong through the reference store's own Lifecycle role, and exactly 255 characters is accepted on both. THIS CLIENT RESTATES THE BOUND NOWHERE, and the reason differs from L-config-bounds': not that the rule is the server's to move, but that a second copy of a rule two layers already apply is a third place for it to drift. What travels back is the operation's own 400. IT IS A DEGRADE RATHER THAN A REFUSE because the path PROCEEDS and the outcome is identical on both legs — the request fails, the row is untouched, and no truncated value is stored — while the detail names the offending member and its length, which is the recovery a caller needs. What is lost is the errors.Is arm a caller writes to tell 'too long' from 'malformed'. Upstream ask: atoo_long` reason, or a code of its own, which retires this row D8 row 16, D9 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
L-events-paging degrade — an UNCAPPED journal read (limit 0) is served as a loop of handler-sized requests rather than one, so its rows and its head no longer come from a single instant; a bounded read is one request and is unaffected the role imposes no ceiling of its own — journalops.Journal says a limit of 0 means uncapped, because the caller that pages a hundred thousand records out to a file is as legitimate as the one polling for ten — and the OPERATION refuses limit=0 by value, capping a page at 10000 (internal/httpapi's maxEventsLimit). That cap is the handler's promise to its clients rather than a narrowing of the role, and this client is on the other side of it. SO THE LOOP IS THE ONLY HONEST READING. Refusing an uncapped read would refuse something the role permits; capping one silently at 10000 would answer a partial page beside a head saying there is more, which is a consumer stalling on a gap nobody told it about. Both are worse than N transactions. WHAT SURVIVES IS WHAT A CONSUMER ACTS ON: rows stay contiguous and seq-ascending, because each page continues exactly where the last ended; the head is the LAST page's, so it is the freshest and can only be at or ahead of the last row served; and a truncation on any page is the whole read's failure, never a shorter answer — a loop that returned the prefix it had already gathered would answer a gap with a plausible-looking suffix, which is the one failure a replay feed must never ship. WHAT DOES NOT SURVIVE is atomicity across the whole answer: a mutation committing mid-loop appears in a later page of the SAME call rather than in the next one. A consumer cannot observe that as a gap or a duplicate — it reads as records it would have received on its next poll, arriving early — which is why this is a degrade rather than a refusal. IT IS A DEGRADE RATHER THAN A REFUSE for the ordinary reason too: the path proceeds, and the answer cannot be misread as narrower or wider than the caller asked for. Upstream ask: an unlimited spelling on the operation, or a cursor the page can hand back — either retires this row D8 (Journal), D9 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline

Write-side refuse-not-drop (D8)

Role-request fields on the served writes that the v0 wire publishes no member for. Each refuses rather than forwarding a write shorn of the field — a silently dropped precondition or flag would widen what the write touches.

ID Kind Field / flag Divergence Why Spec Pinned test
W-UpdateRequest.Claim retired UpdateRequest.Claim a claim combined with a patch, a guard or a force override used to refuse RETIRED by the #7247 review port. The refusal stood on 'updateIssue cannot perform a claim, on this wire or on any other' — and upstream #6890, the capability the row itself named, had already published claim on updateIssue: the claim and the patch applied by the same role in one transaction, so PATCH claim was the server's shape and only this client's refusal. The body now sends claim as a pointer set true only on request, so a claim alone, a claim with a patch and a claim with a version guard are each ONE updateIssue call, answered with the post-write revision like every other update. The claimIssue route survives as the fallback for a claim ALONE against a server that predates the member, which refuses it as an unknown parameter before any database work; a combination against such a server returns that skew refusal rather than splitting into two calls D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-ClaimRequest.Wisp refuse — claiming a wisp is not supported by this bd serve the server predates claiming through its update operation, and its separate claim operation excludes the wisp plane; upgrade bd serve, or claim this issue from a local workspace D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-UpdateRequest.ForceAssigneeTransfer retired UpdateRequest.ForceAssigneeTransfer --force bypassing the anti-steal assignee fence used to refuse RETIRED by the #7247 review port, the two-member port ga-2ltro.15 named. The wire publishes force_assignee_transfer (upstream #5484) and the refusal was always this client's: client wave ga-7i6by had already narrowed it to the bypass alone by sending the assignee the fence guards, and issues:batchApply's update item already carried the same flag. The body now sends it as a pointer set true only on request. The fence itself is unchanged — a transfer away from a live foreign in-progress owner refuses with already_claimed unless one of the two bypasses rides with it, this one or a matched expected_assignee — and the server refuses the bypass without a patch.assignee or beside expected_assignee or claim D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-UpdateRequest.ForceClosePolicy retired UpdateRequest.ForceClosePolicy --force bypassing close policy on a status-crossing update used to refuse RETIRED with W-UpdateRequest.ForceAssigneeTransfer, the other half of ga-2ltro.15's port. The wire publishes force_close_policy (upstream #5484), client wave ga-7i6by sends the status whose crossing the policy gates, and issues:batchApply's update item already carried the flag. The body now sends it as a pointer set true only on request; unforced, a status crossing into the done category with open children or a live blocker still refuses with not_closable, typed, and writes nothing D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-UpdateRequest.ForceNotesOverwrite retired UpdateRequest.ForceNotesOverwrite bypassing the notes-overwrite fence on a single update used to refuse RETIRED by the S3 reconciliation that found it (2026-10). It was discovered refused on the single-patch updateIssue path while the identical flag was already carried on issues:batchApply's update item (W table entry applyBatch/item/update) — the same trio member, wired on one shape and not the other with no decision on record for the gap. Flipping it was a port, not a decision, same as W-UpdateRequest.ExpectedVersion's: the body now sends force_notes_overwrite as a pointer set true only on request, so a Patch.Notes that would replace existing non-empty notes with different non-empty content is bypassable here exactly as it already was on the batch path D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-UpdateRequest.ExpectedVersion retired — the compare-and-set row-version precondition used to refuse RETIRED by the client wave that sends it (ga-jbuyf). The refusal was always the CLIENT's rather than the document's — upstream #5484 published expected_version and this client had not been taught to emit it — and the row said so in as many words: 'flipping it is a port, not a decision: send the member, retire this row, and turn the refusal pin into a round-trip pin'. That is what happened. The member is now sent as a POINTER, so absent stays absent: 0 is a legal token (the migration-0054 backfill left rows holding it) and encoding 'no guard' as 0 would have armed a guard on every unguarded update. The pin below asserts the round trip in both directions D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-UpdateRequest.ExpectedAssignee retired — the compare-and-set assignee precondition used to refuse RETIRED with W-UpdateRequest.ExpectedVersion (ga-jbuyf). Its own trap is the mirror image of that one's: the EMPTY assignee is a real guard — it is how a caller says 'only if nobody holds it' — so this member cannot be omitted when it is empty either. A pointer expresses both, and the pin drives the empty-string guard as its own case D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-UpdateRequest.ExpectedStatus retired — the compare-and-set status precondition used to refuse RETIRED with W-UpdateRequest.ExpectedVersion (ga-jbuyf). The status guard is the readable one — Issue.status is on every read of this surface, so a caller can guard a transition with no token at all — and it is sent as the workspace's own status vocabulary, verbatim D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-UpdateRequest.IssuePlaneOnly refuse UpdateRequest.IssuePlaneOnly restricting an update to the issue plane refuses updateIssue publishes no plane restriction and the server's role auto-resolves both planes, so dropping the flag would EDIT the wisp the caller asked to be told did not exist — the widening refuse-not-drop exists to stop. Not in the design's own enumeration: the page lists the UpdateRequest members it had reviewed, and this one was found while wiring the role D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-UpdateRequest.Provenance refuse UpdateRequest.Provenance labeling an update's history entry refuses updateIssue publishes no provenance member and the server writes its own label, so a dropped Provenance would leave the history entry naming the SERVER's surface while the caller believed it named theirs. It is refused rather than degraded because the field's whole purpose is the label, so dropping it drops the request D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CloseRequest.ExpectedVersion retired — the compare-and-set row-version precondition on a close used to refuse RETIRED by the client wave that sends it (ga-jbuyf). CloseIssueRequest publishes expected_version (upstream #5506) and this client now emits it, so the guard reaches the server rather than refusing here — and the ordering the role promises, that the precondition is checked BEFORE the idempotent re-close, is the server's to keep and the served tier's to assert D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-ReopenRequest.ExpectedVersion retired — the compare-and-set row-version precondition on a reopen used to refuse RETIRED with W-CloseRequest.ExpectedVersion (ga-jbuyf). The design's enumeration named the close half only, and the reopen half is the same field on the same verb pair — it retires the same way D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-DeleteRequest.ExpectedVersion retired — the compare-and-delete row-version precondition used to refuse RETIRED with W-CloseRequest.ExpectedVersion (ga-jbuyf), and it is the one whose stakes made the refusal worth having: dropping this guard erases a row the caller had asked not to erase, with nothing left to compare afterwards. The multi-id refusal the wire attaches to it is deliberately NOT anticipated client-side: distinctness is measured after trimming and collapsing duplicates, which is the normalization this role sends its ids verbatim to avoid re-implementing D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-ReopenRequest.Provenance refuse ReopenRequest.Provenance labeling a reopen's history entry refuses reopenIssue publishes no provenance member and the server writes its own fixed label (bd serve: reopen issue); see W-UpdateRequest.Provenance D8 refuse-not-drop, D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-AddDependenciesRequest.SkipPerEdgeCycleCheck refuse AddDependenciesRequest.SkipPerEdgeCycleCheck --no-cycle-check bd dep add --no-cycle-check refuses on the bulk --file path the wire deliberately leaves SkipPerEdgeCycleCheck UNPUBLISHED and therefore false (internal/httpapi/dependency_edit.go). The single-edge spelling forwards false and only gates the post-hoc cycle warning, which the wire-backed CycleDetector serves, so it is served-with-note rather than refused D7, D8 row 18, D9 L16 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.Status retired — bd update -s used to refuse RETIRED with client wave ga-7i6by. IssuePatchBody published status with upstream #5484 and this client's encoder now emits it; close and reopen still carry the lifecycle semantics a status write has nowhere to put — the reason and session under first-close-wins, the done-status normalization, the already-closed idempotence flag — and stay the operations to reach for. What this member serves is the status moved ALONGSIDE other fields in one transaction, which is the thing two calls cannot do D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.Assignee retired — assignment and unassignment through update used to refuse RETIRED with W-IssuePatch.Status (ga-7i6by). The EMPTY STRING is the half that makes this member more than a rename: it UNASSIGNS, so a client that skipped an empty value would turn a real edit into no edit at all. The anti-steal fence around it is the server's and is unchanged — a transfer away from a live foreign in-progress owner still refuses with already_claimed, and the two bypasses (force_assignee_transfer and a matched expected_assignee) are both sent — the first since W-UpdateRequest.ForceAssigneeTransfer retired, the second since the guard wave D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.Metadata retired — a metadata patch used to refuse RETIRED with W-IssuePatch.Status (ga-7i6by). IssuePatchBody publishes the same replace/merge/set/unset algebra MetadataPatch carries, member for member, so the client projects it rather than translating it and the ordering rule — merge, then set in key order, then unset, with replace refusing beside the other three — stays the ROLE's, applied by the same body a local workspace runs. The CLEAR is the one state the wire's own struct cannot spell (omitempty omits it), which is why the document is built as a map and an empty replacement travels as the empty document. The compare-and-set door is a different question and is served by its own accessor (issues.casMetadata, ga-7i6by's other half) D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.SpecID refuse IssuePatch.SpecID a spec-id edit refuses neither IssuePatchBody nor ApplyPatchBody publishes spec_id (internal/httpapi/update.go issuePatchMembers) D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.AwaitID refuse IssuePatch.AwaitID an await-id edit refuses neither IssuePatchBody nor ApplyPatchBody publishes await_id (internal/httpapi/update.go issuePatchMembers) D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.Owner refuse IssuePatch.Owner an owner edit refuses ON updateIssue IssuePatchBody excludes owner — which the document itself calls an accident of order rather than a decision, since ApplyPatchBody DOES publish it and issues:batchApply's update item carries it (internal/httpapi/update.go issuePatchMembers) D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.ClosedBySession refuse IssuePatch.ClosedBySession a closed-by-session edit refuses neither IssuePatchBody nor ApplyPatchBody publishes closed_by_session (internal/httpapi/update.go issuePatchMembers) D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.Persistence refuse IssuePatch.Persistence a persistence-mode edit refuses neither body publishes persistence: moving a row between planes mid-plan is a different act from writing its fields (internal/httpapi/update.go issuePatchMembers) D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.ParentID retired — a parent re-hang through update used to refuse RETIRED with W-IssuePatch.Status (ga-7i6by). It is ONE call rather than a remove-then-add pair, which is the whole reason the member exists: the two-call spelling leaves the issue parentless if the second call fails, and dependencies:add/remove — still the general write side of the graph over this wire — cannot express the atomic replacement. The empty string removes every parent-child edge, so it travels like assignee's empty string rather than being skipped. The graph refusals it earns are the server's and arrive typed: a cycle through the issue's own descendant as the PLAIN dependency_cycle, and an existing edge of another type as dependency_exists D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CreateBatchRequest.Provenance refuse CreateBatchRequest.Provenance labeling a batch create's history entry refuses batchCreateIssues publishes actor and items only, and the server writes its own label; see W-UpdateRequest.Provenance. It is the one Provenance whose ABSENCE is visible in shipped history — the surface this role serves has always named its source file in the entry (bd: create 3 issue(s) from plan.md) D8 row 14 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CreateBatchRequest.ForceIDPrefix refuse CreateBatchRequest.ForceIDPrefix --force permitting explicit ids outside the workspace's configured prefix refuses the wire publishes no such member — and could not honor one, since it publishes no explicit id for the flag to permit (W-BatchCreateItem.Issue). Dropping it would answer a request about WHERE ids may be written with a batch whose ids the server chose D8 row 14 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-BatchCreateItem.Issue refuse BatchCreateItem.Issue an item whose Issue populates any member outside the wire's eight refuses, naming the member apigen.BatchCreateItem carries title, description, design, acceptance_criteria, priority, issue_type, assignee and labels and nothing else, while the role accepts far more of a types.Issue: an explicit id, the wisp flags, metadata, the storage class, every timestamp, the gate/molecule/event fields. ONE row rather than one per member because the reason is one reason — the wire's item vocabulary — and forty rows repeating it would say nothing a reader does not learn here. Exhaustiveness is held by REFLECTION instead: the client's carried and role-ignored tables are checked against types.Issue field by field, so a member added upstream is refused the day it lands rather than dropped until someone notices. The members the role ITSELF ignores on a create (ContentHash, RowVersion, lease, compaction, routing overrides, hydration flags) are not in this population and are not refused: a local create drops them too. Nor is a CreatedBy that names the request's actor: the server's create role defaults every item's created_by to the actor (W-CreateRequest.Issue), so that value arrives as written and only a CreatedBy naming someone else refuses D8 row 14 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CreateDependency.Reverse refuse CreateDependency.Reverse an edge written from the target back to the new issue refuses ON A BATCH CREATE BatchCreateDependency carries target_id and type only; dropping Reverse would write the edge in the OPPOSITE direction from the one asked for, which is a different graph. createIssue's CreateIssueDependency DOES publish it, and the single-create path sends it (internal/httpapi/spec BatchCreateDependency) D8 row 14 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CreateDependency.Metadata refuse CreateDependency.Metadata typed edge metadata refuses ON A BATCH CREATE BatchCreateDependency publishes no metadata member, and a waits-for gate whose metadata was dropped is a readiness rule that silently does not hold. createIssue's edge publishes it, and the single-create path sends it verbatim (internal/httpapi/spec BatchCreateDependency) D8 row 14 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CreateDependency.ThreadID refuse CreateDependency.ThreadID associating an edge with a discussion thread refuses neither BatchCreateDependency nor CreateIssueDependency publishes a thread member (internal/httpapi/spec BatchCreateDependency) D8 row 14 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CreateRequest.IDPrefix refuse CreateRequest.IDPrefix overriding the prefix an explicit, unforced id is checked against refuses createIssue publishes no id_prefix, and the omission is the SERVER's decision rather than a gap (internal/httpapi/create.go): the field exists because a workspace's own config.yaml prefix wins over the database's and only a local front door can read that file, so a remote caller's config.yaml describes a workspace this server does not serve. Publishing it would let a caller override the served workspace's prefix rule from outside it. Dropping it instead would check the id against the SERVER's prefix while the caller believed it was checked against theirs — the same request, two different answers to 'may this workspace mint this id'. It refuses only where it would ACT: the role reads the override for nothing but an explicit id it was not told to force, so a create that mints its id, or sets ForceIDPrefix, is the same request with or without it and is sent without it. That matters because bd create sends the workspace's prefix on EVERY create, so an unconditional refusal would refuse every create in a workspace whose config.yaml names one D8 row 16 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CreateRequest.Issue refuse CreateRequest.Issue a create whose Issue populates any member outside the wire's twenty refuses, naming the member createIssue publishes the whole create VOCABULARY — id, title, description, design, acceptance_criteria, notes, status, issue_type, priority, assignee, owner, estimated_minutes, external_ref, due_at, defer_until, sender, metadata, labels, ephemeral, no_history — and deliberately not the rest of a types.Issue: the creation time (created_at), because a caller-supplied creation time makes the row disagree with the journal entry that records it and re-dating history is what an import is for; and spec_id, await_, mol_type, wisp_type, work_type, storage_class, source_, pinned, is_template and the event quartet, which this surface publishes on no operation, read or write. ONE row rather than one per member for W-BatchCreateItem.Issue's reason — the reason is one reason — and exhaustiveness is held by the same REFLECTION over types.Issue, sharing the role-ignored table with the batch so the two operations cannot disagree about what the ROLE drops. Issue.Comments and Issue.Dependencies are not in this population: the role itself refuses them, so a local create fails too and this is validation rather than divergence. created_by is published on no create shape either, but the create role behind every one of them defaults an empty created_by to the request's actor (issueops.PreparePublicCreateRequest), the same rule a local create gets. So an empty CreatedBy and one that names the actor both arrive as the actor, and only one naming someone else refuses: the default would silently replace it. A server older than either stamp (handler or role) stores an empty created_by for that one member D8 row 16 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CreateItem.Issue refuse CreateItem.Issue a create ITEM whose Issue populates any member outside the wire's twenty refuses, naming the member ApplyCreateItem publishes exactly createIssue's create vocabulary — id, title, description, design, acceptance_criteria, notes, status, issue_type, priority, assignee, owner, estimated_minutes, external_ref, due_at, defer_until, sender, metadata, labels, ephemeral, no_history — and deliberately not the rest of a types.Issue, for the reasons W-CreateRequest.Issue gives in full. It is a row of its OWN rather than a citation of that one because the operations are different: a caller auditing why their PLAN refuses must not be sent to a row about a single create, and the two can diverge the day either vocabulary moves. The partition itself is SHARED — one carried table, one role-ignored table, held against types.Issue by the same reflection — so they cannot disagree about what the wire carries or about what the role drops. Issue.Comments and Issue.Dependencies are not in this population and are refused as validation on both sides: edges in this role are ITEMS, so a create item has nowhere to put one at all. Nor is a CreatedBy that names the request's actor: the server's create role defaults every create item's created_by to the actor (W-CreateRequest.Issue), so that value arrives as written and only a CreatedBy naming someone else refuses D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-ApplyPatch.ParentID refuse IssuePatch.ParentID a parent re-hang inside an update ITEM refuses, where the same member serves on updateIssue ApplyPatchBody deliberately publishes no parent_id, and the absence is this operation's ONE-EDGE-ONE-SPELLING rule rather than a gap: a parent is a dep_add item of type parent-child, so the ORDER of every edge in a plan stays total and there is exactly one place an edge is written. The single patch has no ordering to express and publishes the member directly (W-IssuePatch.ParentID, retired by client wave ga-7i6by), which is why the same Go field is carried by one document and refused by the other. Refusing is not a loss of capability, only of spelling: a plan re-hangs a parent with a dep_add item, which is the atomic replacement in the position the caller declared it D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-DepAddItem.HasSpawner retired DepAddItem.HasSpawner a waits-for edge ITEM that names its spawner used to refuse RETIRED by issues.batchApply.depAddLineage (S5). ApplyDepAddItem now publishes has_spawner — the write this row said only the role could make, metadata's spawner_id stamped from the resolved target — gated on the capability rather than dropped: a caller on a server that has not advertised the token refuses locally before the dial (BatchApplier.refuseUnservedDepAddLineage), and a caller on a server that has sends the member exactly as given. The flag is sent, and gated, on a waits-for edge only, the one type the role reads it on. Off a waits-for edge it is the role's no-op, so the client drops it there without loss — the stored row is the same either way — rather than refusing a request the flag cannot change, or sending an older server a member it answers with a 400 D8 refuse-not-drop (RETIRED) TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-DepAddItem.ThreadID retired DepAddItem.ThreadID associating an edge ITEM with a discussion thread used to refuse RETIRED with W-DepAddItem.HasSpawner (S5, issues.batchApply.depAddLineage). ApplyDepAddItem now publishes thread_id as a plain column on the stored edge, gated by the same capability and the same pre-dial refusal rather than dropped — a caller naming a thread on an unadvertising server is refused before the dial, never silently stored with no thread D8 refuse-not-drop (RETIRED) TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-IssuePatch.Labels retired IssuePatch.Labels RETIRED — the whole ordered label edit crosses: labels replaces, add_labels adds, remove_labels removes upstream #5510 published add_labels and remove_labels on IssuePatchBody and client wave ga-jpywb emits both, which is the retirement path this row named. The three travel as FLAT siblings where applyBatch nests them under one object, and the server assembles all three into ONE issueops.LabelPatch — so the algebra the role states (replace, then add, then remove; removal wins) is applied server-side and is never this client's to arrange. WHAT THE REFUSAL WAS PROTECTING is worth keeping after the refusal is gone: degrading an incremental edit onto the replace-only member would have meant reading the set, adding to it and writing it back, which silently drops any label another writer added in between. bd label add and every agent that tags work concurrently are exactly that caller, so the refusal was right for as long as the members did not exist — and it is the members that retire it, not a change of mind about the read-modify-write D8 refuse-not-drop, open questions (tracked-refusal roadmap) TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-CloseBatchRequest.ClaimNext refuse CloseBatchRequest.ClaimNext folding an atomic claim-after-close onto a batch close refuses batchCloseIssues publishes actor, force, items and session only — no claim_next member exists for this client to encode a ReadyRequest into, and none exists on the response for a claimed issue to decode back out of. Dropping the field silently would answer a caller's claim-after-close with a close that quietly never claimed anything; see W-CreateBatchRequest.Provenance for the same refuse-not-drop reasoning applied to an absent wire member. Deferred: S13 schedules ReadyLister (and with it, the ready-side plumbing a composed claim would need); no slice currently schedules claim_next itself D8 refuse-not-drop TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
W-SweepRequest.ProtectLiveDependents retired SweepRequest.ProtectLiveDependents protecting live structural dependents during a sweep used to refuse RETIRED by the S4 wire extension that sends it. The gap was always the DOCUMENT's rather than a decision: the local Sweeper role carries a structural-dependent protection alongside the referenced-citation one, and apigen.SweepRequest had no protect_live_dependents member for this client to narrow onto, so sending true and silently dropping it would have run an UNPROTECTED sweep while the caller believed the structural guard was active. The spec now publishes protect_live_dependents (and SweepSkips.live_dependent on the response) behind its own behavior-capability token, issues.sweep.liveDependents, because it is a parameter added to an operation that already shipped. The client sends it only once the handshake advertises the token and refuses locally, before the dial, when it does not — see refuseUnservedSweep (sweeper.go) and W-SweepRequest.Limit for the sibling member closed the same way D8 refuse-not-drop TestSweepSendsTheS4MembersOnceTheServerAdvertisesThem
W-SweepRequest.Limit retired SweepRequest.Limit bounding one sweep call and draining a backlog over several used to refuse RETIRED by the S4 wire extension that sends it (with W-SweepRequest.ProtectLiveDependents). The local Sweeper role bounds one sweep call and reports the remainder back; apigen.SweepRequest and SweepResult carried neither a limit member to send nor a remaining member to read one back from, so a dropped Limit would have run the UNBOUNDED sweep the caller asked to cap, in one transaction. The spec now publishes limit on the request and remaining on the response behind issues.sweep.limit. The client sends Limit only once the handshake advertises that token and refuses locally otherwise; issueops.SweepResult.Remaining now carries the server's count rather than always reading zero D8 refuse-not-drop TestSweepSendsTheS4MembersOnceTheServerAdvertisesThem

Command and flag refusals (D7)

Whole commands, and the flag modes of served commands, that dispatch onto methods the wire does not carry. They refuse early — before RunE — in the user's own command/flag vocabulary.

ID Kind Field / flag Divergence Why Spec Pinned test
F-ready-explain refuse --explain bd ready --explain refuses it dispatches onto raw GetBlockedIssues/GetIssuesByIDs/GetDependencyCounts/DetectCycles, three of which are on the unsupported allowlist D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-ready-mol refuse --mol bd ready --mol refuses its molecule subgraph load reaches findHierarchicalChildren, an IDPrefix SearchIssues shape the parent-walk bridge cannot express (E-IssueFilter.noShape). GetDependencyRecords and GetDependentsWithMetadata, which the same load also calls, stopped being the blocker once they flipped onto the wire D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-ready-gated refuse --gated bd ready --gated refuses it dispatches onto a filtered SearchIssues shape the bridge cannot express, plus GetDependents D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-show-thread refuse --thread bd show --thread refuses showMessageThread renders each reply's sender, recipient, body and timestamp off GetDependentsWithMetadata, but that read was flipped onto getIssue's include_dependents parameter, which carries the collectDependents SHALLOW projection (id/status/type/priority/title + edge type only, be-4d36f2). Those fields come back zeroed over http and zero-timestamp replies sort ahead of the root — a silent-wrong degrade the refuse-over-degrade doctrine forbids. Retires with a full-dependent wire shape, a server-side ask D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-show-refs refuse --refs bd show --refs refuses showIssueRefs's --json marshals the full GetDependentsWithMetadata rows, but the wire answers the same collectDependents shallow projection, so created_at/assignee/description come back zeroed and the JSON differs from a local workspace. The text render consumes only the shallow fields, but the flag cannot be split from its --json mode, so the whole flag refuses rather than serve a divergent JSON silently D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-show-children refuse --children bd show --children refuses showIssueChildren's --json marshals the full GetDependentsWithMetadata rows, the same collectDependents shallow projection as --refs, so created_at/assignee/description come back zeroed over http. bd children is NOT this flag: it is a bd list --parent listing, served through the reader role (S6c) D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-mol-ready refuse — bd mol ready refuses it is the same runMolReadyGatedCore body as bd ready --gated D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-blocked refuse — bd blocked refuses it is raw GetBlockedIssues, which is on the unsupported allowlist D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-count retired — RETIRED — bd count is SERVED whole it said the command refuses because "issueops.Counter has no wire operation; a counts operation is a filed upstream ask", and that ask was DELIVERED: upstream #5508 published countIssues, client wave ga-icks1 wired the Counter accessor, and count moved from httpRefusedCommands into httpServedCommands. D8 row 20 and docs/reference/http-workspaces.md have said so since; this row was the last place that did not. Every flag the command publishes reaches a wire member — the whole predicate, the six instant bounds, the three emptiness checks, --include-infra, and the five --by-* flags as the one group_by parameter — so there is no refused mode left to name either. HOW IT ROTTED IS THE PART WORTH KEEPING. Its pin was TestClassifiedRefusedCommandsRefuseBeforeTheOSSPreRun, which walks httpRefusedCommands and drives every entry. The moment count left that table the pin stopped covering this row — it stayed LIVE BY NAME, so the well-formedness gate that resolves PinnedBy to a real test kept passing, and DEAD BY COVERAGE, so nothing anywhere asserted the row's claim. A ledger row can be false for a whole wave under a green pin, which is what TestFRowsAgreeWithTheCommandClassification now makes impossible D7 (RETIRED), D8 row 20 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-serve refuse — bd serve refuses against an http workspace the OSS classifier would happily serve it from the opened store, and a bd serve re-serving a remote bd serve is a proxy chain nobody designed: run serve where the database is D7 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-close refuse — bd close is SERVED whole — single id and several ids — over issues:batchClose; it refuses against a DOWN-LEVEL server that does not advertise issues.batchClose, and --claim-next refuses against every server, before anything closes the CLI's close front door routes every id, single-id included, through BatchCloser.CloseBatch, and Lifecycle.Close has zero CLI callers at tip. The wire now carries issues:batchClose, so a CloseBatchRequest of any size is one wire call and one server-side transaction; nothing is composed or refused where the capability is present. THE NEXT CLAIM IS THE EXCEPTION. batchCloseIssues has no member to carry it, so the client refuses a ClaimNext on both legs, after the claim's own validation and before the dial (W-CloseBatchRequest.ClaimNext). Closing and then claiming would split the role's one transaction in two, and a claim that failed after the closes committed could not report them, because the role answers with an error or with outcomes, never both. On the CLI's chain the external-dependency decorator (design 3.6) refuses first unless the server advertises wire.CapExternalDependencies, and its refusal says nothing closed and names the commands that do the same work: close without --claim-next, then bd ready --claim (internal/storage/externaldeps/remote_roles.go). Against a server too old to advertise issues.batchClose, servesBatchClose() reads the handshake snapshot and routes around the batch dial entirely, so no Preflight runs and no wire.ErrCapabilityAbsent is raised: the down-level leg's refuseUnservedCloseShape raises the STORE's own *ErrHTTPUnsupported (batchcloser.go), which names the refused shape and the server, and cmd/bd prints it against each id the batch carried. The single-item, no-ClaimNext shape still composes onto closeIssue in that down-level leg (see L18); the shapes that cannot compose refuse there. The item cap is L-close-cap D8 row 17 (resolved, Wire), D9 L18, D9 L-close-cap TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline
F-partial-id refuse — partial-id resolution refuses with its own taxonomy text SearchIssueIDs has no wire operation, and the client cannot tell a partial id from a full id that does not exist — so the refusal text covers both outcomes rather than falling through to a raw search error, and it unwraps to ErrNotFound. The store also reports utils.ExactIDLookupStore, so the CLI's routed lookups (show, update, close, reopen, ...) stop at the exact getIssue and answer a plain not-found after that one round trip, never reaching the search (S6b) D11 TODO(S3): store/dial-seam and cmd/bd conformance this package's own gates do not reach; see the in-repo divergence ledger, engdocs/design/http-divergence-ledger.md, for the discipline

Ready-request fields

Members of the ready vocabulary the wire cannot express.

ID Kind Field / flag Divergence Why Spec Pinned test
E-ReadyRequest.MolType refuse ReadyRequest.MolType a molecule-type restriction on ready work refuses neither listReadyWork nor countReadyWork publishes a mol-type parameter, and the ready query applies molecule typing inside — so a dropped restriction would answer with the wider set of every molecule type D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ReadyRequest.Offset refuse ReadyRequest.Offset a non-zero Offset on ready work refuses the wire publishes no offset parameter, and the store-backed role refuses a non-zero Offset itself with a typed *ErrUnsupported. A ready request carries no keyset position, so there is no portable way to page ready work at all — a caller that must page pages a ListRequest instead D9 L12, D7, D8, D12 TestEncoderHonorsEveryTableDisposition
E-ReadyRequest.Brief retired — RETIRED — the ready listing SENDS the projection; only the count still drops it upstream #5586 published brief on GET /v0/beads/ready and GET /v0/beads/issues, which is the retirement path this row named. Both page encoders send the parameter now — readyTable, listTable and the ready bridge all map it — so the client asks for the projection it was handed and the server leaves the text columns unselected. The COUNT keeps the drop under E-ReadyRequest.Brief@countReadyWork, because countReadyWork publishes no such parameter and a cardinality has no rows to project. WHAT DID NOT RETIRE WITH IT IS THE WIRE HALF OF THE MARKER, and only that half: types.Issue.IsLitePartial is json:"-" and never crosses, so a projected page arrives on the transport byte-identical to a page of genuinely textless rows — the same absence getIssue's brief_deps carries, deferred upstream by #5549. THE CALLER-VISIBLE AMBIGUITY IS CLOSED, by client wave ga-f352s: brief is a parameter to the page decode rather than a field on anything, so httpReader hands it to wireRows (role_reader.go) and this client stamps IsLitePartial on every row of a page it ASKED to be projected — which is precisely what issueops.ListRequest.Brief's own leaf says a wire consumer distinguishes the two by — and never on a hydrated one. bd list --long --brief therefore prints "Description: (omitted by --brief)" over http exactly as it does locally, and TestHTTPCommentAndBriefRenderEndToEnd pins that line through the real binary D9 (a degradation not in this table is a bug) TestEncoderHonorsEveryTableDisposition
E-ReadyRequest.Brief@countReadyWork degrade ReadyRequest.Brief the free-form-text projection is DROPPED on the COUNT, not refused: a cardinality has no rows to project countReadyWork publishes no brief and answers a cardinality, so there is nothing to project: the parameter chooses what is HYDRATED and never which rows match, and a count reads neither. Dropping it is SkipLabels' and SkipCounts' argument exactly — the total is what it would have been — and refusing would make a performance flag a hard error on the one operation where it can cost nothing. The two page operations retired this drop and send the parameter; a caller that populates Brief for a count is asking a question a cardinality does not have D9 (a degradation not in this table is a bug) TestEncoderHonorsEveryTableDisposition
E-ReadyRequest.Limit@countReadyWork refuse ReadyRequest.Limit a Limit on a ready COUNT refuses countReadyWork publishes no limit parameter and ReadyCounter.CountReady refuses one itself: a cardinality has no page, and CountReady's identity with the listing it sizes stops being true the moment one is accepted. An explicit zero is refused with the rest — an unlimited count is the only kind there is D9 L12, D7, D8, D8 row 2 TestEncoderHonorsEveryTableDisposition

List-request fields

The listing publishes far more filters than the v0 wire does; every one the wire lacks refuses rather than dropping, because a dropped list filter widens the page invisibly. Two hydration opt-outs are dropped instead, with the argument for why that cannot be misread as a narrower or wider answer.

ID Kind Field / flag Divergence Why Spec Pinned test
E-ListRequest.TitleSearch refuse ListRequest.TitleSearch a title search refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.SpecPrefix refuse ListRequest.SpecPrefix a spec-id prefix restriction refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.IDFilter refuse ListRequest.IDFilter an explicit id set on the LISTING refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml); the exact-ids question is getIssue's, reached through the SearchIssues bridge's exact-ids shape (D11), not through a listing filter D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.LabelPattern refuse ListRequest.LabelPattern a glob label filter refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) — listReadyWork does publish label_pattern, which is exactly why the absence here has to refuse rather than fall through D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.LabelRegex refuse ListRequest.LabelRegex a regex label filter refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) — as for LabelPattern, listReadyWork publishes label_regex and the listing does not D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.TitleContains refuse ListRequest.TitleContains a title substring filter refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.DescContains refuse ListRequest.DescContains a description substring filter refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.NotesContains refuse ListRequest.NotesContains a notes substring filter refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.ExternalContains refuse ListRequest.ExternalContains an external-ref substring filter refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.ExternalRef refuse ListRequest.ExternalRef an exact external-ref filter refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.UpdatedAfter refuse ListRequest.UpdatedAfter an updated-after bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) — only the created bounds are published D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.UpdatedBefore refuse ListRequest.UpdatedBefore an updated-before bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) — only the created bounds are published D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.ClosedAfter refuse ListRequest.ClosedAfter a closed-after bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.ClosedBefore refuse ListRequest.ClosedBefore a closed-before bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.DeferAfter refuse ListRequest.DeferAfter a defer-after bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.DeferBefore refuse ListRequest.DeferBefore a defer-before bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.DueAfter refuse ListRequest.DueAfter a due-after bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.DueBefore refuse ListRequest.DueBefore a due-before bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.EmptyDesc refuse ListRequest.EmptyDesc the empty-description predicate refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.NoAssignee refuse ListRequest.NoAssignee the unassigned predicate refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) — listReadyWork publishes unassigned; the listing does not D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.NoLabels refuse ListRequest.NoLabels the no-labels predicate refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.Priority refuse ListRequest.Priority an exact priority filter refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) — listReadyWork publishes priority; the listing does not D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.PriorityMin refuse ListRequest.PriorityMin a minimum-priority bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.PriorityMax refuse ListRequest.PriorityMax a maximum-priority bound refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.PinnedFlag refuse ListRequest.PinnedFlag selecting the pinned-FLAG rows refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml). The pinned STATUS is reachable through status; the flag is a separate predicate at any status and has no parameter D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.NoPinnedFlag refuse ListRequest.NoPinnedFlag holding the unflagged predicate in place refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml). It changes nothing on a default listing and NARROWS under all or a pinned/hooked status — which is precisely when dropping it would widen the answer D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.ExcludeTypes refuse ListRequest.ExcludeTypes a type exclusion refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) — listReadyWork publishes exclude_type; the listing publishes only the four include_* toggles D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.NoParent refuse ListRequest.NoParent the top-level-only predicate refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.MolType refuse ListRequest.MolType a molecule-type restriction refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.WispType refuse ListRequest.WispType a wisp-type restriction refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml). The listing now ADMITS the wisp plane — include_ephemeral landed upstream and the encoder sends it (L1 retired) — so this refusal is no longer redundant with an invisible plane: it is the only thing standing between a caller and a listing that returns every wisp type when they named one D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.DeferredFlag refuse ListRequest.DeferredFlag the deferred predicate refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.OverdueFlag refuse ListRequest.OverdueFlag the overdue predicate refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml) D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.ReadyFlag refuse ListRequest.ReadyFlag switching a listing onto the ready set refuses ReadyFlag is not a filter but a change of QUESTION: it selects the blocker-aware ready query, which reads a narrower filter vocabulary than a ListRequest can describe. Over the wire that question is listReadyWork, a different operation with a different parameter table. Routing it there would have to decide, silently, which of this request's fields survive the crossing — so v1 refuses and the retirement path is an explicit route in the store, not a re-encode here D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.IncludeComments refuse ListRequest.IncludeComments hydrating every row's comment bodies refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml). listIssues documents comments as always absent on its rows; a caller that needs an issue's comments reads getIssue with include_comments, one issue at a time D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.Offset refuse ListRequest.Offset a non-zero Offset refuses listIssues publishes no such parameter (internal/httpapi/reads.go handleListIssues; internal/httpapi/spec/openapi.v0.yaml). The portable page is the keyset position, which the pager walks (D8 row 1); the store-backed role refuses a non-zero Offset itself D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.SkipLabels degrade ListRequest.SkipLabels the label-hydration opt-out is DROPPED, not refused: the wire hydrates labels either way the listing publishes no hydration parameter, so the client cannot ask the server to skip the labels JOIN. Dropping it hands the caller MORE data than it asked for and never fewer — the row set, its order, Parent and the has-more verdict are exactly what they would have been — so it cannot be misread as a narrower or wider answer. It is a degradation rather than a refusal because refusing would make bd list --skip-labels a hard error for a performance flag whose only observable effect over http is that the server pays for a join. The retirement path is a hydration parameter on the wire D9 (a degradation not in this table is a bug) TestEncoderHonorsEveryTableDisposition
E-ListRequest.Brief retired — RETIRED — bd list over http sends the projection upstream #5586 published brief on GET /v0/beads/ready and GET /v0/beads/issues, which is the retirement path this row named. Both page encoders send the parameter now — readyTable, listTable and the ready bridge all map it — so the client asks for the projection it was handed and the server leaves the text columns unselected. The COUNT keeps the drop under E-ReadyRequest.Brief@countReadyWork, because countReadyWork publishes no such parameter and a cardinality has no rows to project. WHAT DID NOT RETIRE WITH IT IS THE WIRE HALF OF THE MARKER, and only that half: types.Issue.IsLitePartial is json:"-" and never crosses, so a projected page arrives on the transport byte-identical to a page of genuinely textless rows — the same absence getIssue's brief_deps carries, deferred upstream by #5549. THE CALLER-VISIBLE AMBIGUITY IS CLOSED, by client wave ga-f352s: brief is a parameter to the page decode rather than a field on anything, so httpReader hands it to wireRows (role_reader.go) and this client stamps IsLitePartial on every row of a page it ASKED to be projected — which is precisely what issueops.ListRequest.Brief's own leaf says a wire consumer distinguishes the two by — and never on a hydrated one. bd list --long --brief therefore prints "Description: (omitted by --brief)" over http exactly as it does locally, and TestHTTPCommentAndBriefRenderEndToEnd pins that line through the real binary D9 (a degradation not in this table is a bug) TestEncoderHonorsEveryTableDisposition
E-ListRequest.IncludeAllTypes refuse ListRequest.IncludeAllTypes the never-hide-a-bead intent refuses it is the UNION of four intents the wire does publish — include_templates, include_gates, include_infra, include_ephemeral — and encoding it as those four would be a client-side restatement of a union whose whole point is that a FIFTH suppression added to workapi is lifted by it automatically. The day that fifth lands, the restatement silently stops lifting it and the listing hides beads from a caller whose contract is that it hides none. Dropping it narrows the answer for the same reason, so it refuses until the wire publishes the intent itself D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition
E-ListRequest.SkipCounts degrade ListRequest.SkipCounts the cardinality-hydration opt-out is DROPPED, not refused: the wire hydrates the three counts either way the same reasoning as SkipLabels, and here refusing would be actively wrong: EVERY text rendering of bd list sets SkipCounts (cmd/bd/list.go:284, and its proxied twin), so a refusal would kill the default listing over http. Dropping it means real counts arrive where zeros were expected, and a caller that must read a zero as UNKNOWN is safe reading a true count. The cost is the three aggregate joins — including the reverse-blocker one the embedded planner cannot index — paid on a page that prints none of them D9 (a degradation not in this table is a bug) TestEncoderHonorsEveryTableDisposition

Query-request fields

The boolean-query surface publishes almost its whole vocabulary; this is what is left over.

ID Kind Field / flag Divergence Why Spec Pinned test
E-QueryRequest.Offset refuse QueryRequest.Offset a non-zero Offset on a boolean query refuses queryIssues publishes no offset parameter — the document deliberately omits one, because the two database sources this server can be built on disagree about whether they can honor it — and the store-backed role refuses one uniformly D9 L12, D7, D8 TestEncoderHonorsEveryTableDisposition

Search bridge / IssueFilter (D4, D11)

The off-role SearchIssues bridge serves two shapes and no others: the exact-ids fast path and the parent descendant walk. Every other populated IssueFilter member is a filter the bridge would have to drop to answer, so it refuses.

ID Kind Field / flag Divergence Why Spec Pinned test
E-IssueFilter.Status refuse IssueFilter.Status a populated IssueFilter.Status refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Statuses refuse IssueFilter.Statuses a populated IssueFilter.Statuses refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Priority refuse IssueFilter.Priority a populated IssueFilter.Priority refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.IssueType refuse IssueFilter.IssueType a populated IssueFilter.IssueType refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Assignee refuse IssueFilter.Assignee a populated IssueFilter.Assignee refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Labels refuse IssueFilter.Labels a populated IssueFilter.Labels refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.LabelsAny refuse IssueFilter.LabelsAny a populated IssueFilter.LabelsAny refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.ExcludeLabels refuse IssueFilter.ExcludeLabels a populated IssueFilter.ExcludeLabels refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.LabelPattern refuse IssueFilter.LabelPattern a populated IssueFilter.LabelPattern refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.LabelRegex refuse IssueFilter.LabelRegex a populated IssueFilter.LabelRegex refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.TitleSearch refuse IssueFilter.TitleSearch a populated IssueFilter.TitleSearch refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.IDPrefix refuse IssueFilter.IDPrefix a populated IssueFilter.IDPrefix refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.SpecIDPrefix refuse IssueFilter.SpecIDPrefix a populated IssueFilter.SpecIDPrefix refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.TitleContains refuse IssueFilter.TitleContains a populated IssueFilter.TitleContains refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.DescriptionContains refuse IssueFilter.DescriptionContains a populated IssueFilter.DescriptionContains refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.NotesContains refuse IssueFilter.NotesContains a populated IssueFilter.NotesContains refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.ExternalRefContains refuse IssueFilter.ExternalRefContains a populated IssueFilter.ExternalRefContains refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.ExternalRef refuse IssueFilter.ExternalRef a populated IssueFilter.ExternalRef refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.CreatedAfter refuse IssueFilter.CreatedAfter a populated IssueFilter.CreatedAfter refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.CreatedBefore refuse IssueFilter.CreatedBefore a populated IssueFilter.CreatedBefore refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.UpdatedAfter refuse IssueFilter.UpdatedAfter a populated IssueFilter.UpdatedAfter refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.UpdatedBefore refuse IssueFilter.UpdatedBefore a populated IssueFilter.UpdatedBefore refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.ClosedAfter refuse IssueFilter.ClosedAfter a populated IssueFilter.ClosedAfter refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.ClosedBefore refuse IssueFilter.ClosedBefore a populated IssueFilter.ClosedBefore refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.StartedAfter refuse IssueFilter.StartedAfter a populated IssueFilter.StartedAfter refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.StartedBefore refuse IssueFilter.StartedBefore a populated IssueFilter.StartedBefore refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.AfterCreatedAt refuse IssueFilter.AfterCreatedAt a populated IssueFilter.AfterCreatedAt refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.AfterID refuse IssueFilter.AfterID a populated IssueFilter.AfterID refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.AfterPriority refuse IssueFilter.AfterPriority a populated IssueFilter.AfterPriority refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.EmptyDescription refuse IssueFilter.EmptyDescription a populated IssueFilter.EmptyDescription refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.NoAssignee refuse IssueFilter.NoAssignee a populated IssueFilter.NoAssignee refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.NoLabels refuse IssueFilter.NoLabels a populated IssueFilter.NoLabels refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.PriorityMin refuse IssueFilter.PriorityMin a populated IssueFilter.PriorityMin refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.PriorityMax refuse IssueFilter.PriorityMax a populated IssueFilter.PriorityMax refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.SourceRepo refuse IssueFilter.SourceRepo a populated IssueFilter.SourceRepo refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Ephemeral refuse IssueFilter.Ephemeral a populated IssueFilter.Ephemeral refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.EphemeralTier refuse IssueFilter.EphemeralTier a populated IssueFilter.EphemeralTier refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Pinned refuse IssueFilter.Pinned a populated IssueFilter.Pinned refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.IsBlocked refuse IssueFilter.IsBlocked a populated IssueFilter.IsBlocked refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.IsTemplate refuse IssueFilter.IsTemplate a populated IssueFilter.IsTemplate refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.NoParent refuse IssueFilter.NoParent a populated IssueFilter.NoParent refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.MolType refuse IssueFilter.MolType a populated IssueFilter.MolType refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.WispType refuse IssueFilter.WispType a populated IssueFilter.WispType refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.ExcludeStatus refuse IssueFilter.ExcludeStatus a populated IssueFilter.ExcludeStatus refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.ExcludeTypes refuse IssueFilter.ExcludeTypes a populated IssueFilter.ExcludeTypes refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Deferred refuse IssueFilter.Deferred a populated IssueFilter.Deferred refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.DeferAfter refuse IssueFilter.DeferAfter a populated IssueFilter.DeferAfter refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.DeferBefore refuse IssueFilter.DeferBefore a populated IssueFilter.DeferBefore refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.DueAfter refuse IssueFilter.DueAfter a populated IssueFilter.DueAfter refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.DueBefore refuse IssueFilter.DueBefore a populated IssueFilter.DueBefore refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Overdue refuse IssueFilter.Overdue a populated IssueFilter.Overdue refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.MetadataFields refuse IssueFilter.MetadataFields a populated IssueFilter.MetadataFields refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.HasMetadataKey refuse IssueFilter.HasMetadataKey a populated IssueFilter.HasMetadataKey refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.IncludeDependencies refuse IssueFilter.IncludeDependencies a populated IssueFilter.IncludeDependencies refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.SkipLabels refuse IssueFilter.SkipLabels a populated IssueFilter.SkipLabels refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.SkipCounts refuse IssueFilter.SkipCounts a populated IssueFilter.SkipCounts refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.SkipWisps refuse IssueFilter.SkipWisps a populated IssueFilter.SkipWisps refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.NoIDShrink refuse IssueFilter.NoIDShrink a populated IssueFilter.NoIDShrink refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Offset refuse IssueFilter.Offset a populated IssueFilter.Offset refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.SortBy refuse IssueFilter.SortBy a populated IssueFilter.SortBy refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.SortDesc refuse IssueFilter.SortDesc a populated IssueFilter.SortDesc refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.MaxRows refuse IssueFilter.MaxRows a populated IssueFilter.MaxRows refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.MaxRowsSource refuse IssueFilter.MaxRowsSource a populated IssueFilter.MaxRowsSource refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.Lite refuse IssueFilter.Lite a populated IssueFilter.Lite refuses on the SearchIssues bridge the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses D8 (off-role raw methods), D4, D11, D9 L12 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.shapeConflict refuse — an id set and a ParentID together refuse — the pair is NEITHER expressible shape the exact-ids shape dials getIssue per id and applies no filter at all, so honoring the parent restriction would mean discarding answers client-side; the descendant walk dials listIssues?parent=, which publishes no id filter, so honoring the ids would mean intersecting two answers no single wire call asked for. Both readings are drops wearing a filter's clothes, so the combination refuses before a shape is chosen D4, D11, D9 L12 TestASearchFilterMatchingNeitherShapeRefuses
E-IssueFilter.Limit@exactIDs refuse IssueFilter.Limit a Limit alongside an id set refuses getIssue answers one row per call, so a Limit could only be applied by discarding answers the caller named explicitly D11 TestEncoderHonorsEveryTableDisposition
E-IssueFilter.IDs@bound refuse IssueFilter.IDs an id set larger than MaxExactIDs refuses the exact-ids shape costs one getIssue per id, so an unbounded set is an unbounded burst at one shared server. The bound is 100 and is a GUESS: open question 6 asks for the real call-site fan-out to be measured before GA D11, open question 6 TestTheExactIDsFanOutIsBounded
E-IssueFilter.noShape refuse — a raw SearchIssues call matching neither expressible shape refuses the off-role SearchIssues bridge serves TWO shapes and no others: the exact-ids fast path D11 special-cases to getIssue, and the ParentID-only descendant walk D4 maps to paged listIssues?parent=. Any other populated field is a filter the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly — so it refuses. A filter naming no ids and no parent — the unbounded everything shape included — is not one of them D8 (off-role raw methods), D4, D11, D9 L12 TestASearchFilterMatchingNeitherShapeRefuses
E-bridge-parent-shape retired — RETIRED — the ParentID-only shape was unreachable from bd list --parent as the CLI builds it, and the walk refused over http the escalation this row raised (ga-2ieek) was resolved by spec revision 6b428bf63 as semantic inversion: the wire publishes INTENTS (all, include_templates, include_gates, include_infra) rather than materialized exclusions, and the server's role re-derives the exclusions from the same builder against its own authoritative vocabulary. The bridge therefore inverts the derived members back to intents instead of encoding them, and the objection recorded here — that recognizing the baseline would be an unsanctioned second encoder — is answered by VERIFYING each candidate through workapi.BuildListFilter itself rather than reimplementing it. The live rules are the P-IssueFilter.* population D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults

Parent-walk derived defaults (D4)

The descendant walk reads the same IssueFilter as the exact-ids shape and reads it differently. The wire publishes intents (all, include_templates, include_gates, include_infra) and the server re-derives the exclusions; the bridge inverts the derived defaults back to intents and refuses anything the inversion cannot account for.

ID Kind Field / flag Divergence Why Spec Pinned test
P-IssueFilter.ExcludeStatus refuse IssueFilter.ExcludeStatus a status exclusion that is not the derived default refuses listIssues publishes no exclude_status: the wire publishes the INTENT (all) and the server re-derives the exclusions from the same builder against its own authoritative vocabulary, which additionally heals L7's degraded client-side set for the walk. An exclusion list no intent reproduces is therefore unstatable, and dropping it would widen the listing to closed work D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.Pinned refuse IssueFilter.Pinned a pinned predicate that is not the derived default refuses the pinned default is the FOURTH derived member and has no parameter of its own: --pinned selects the flagged rows and --no-pinned holds the unflagged predicate in place under --all, and the wire can express neither. Its derived value is a function of the all intent alone — upstream #5333 stopped an every-status selector from forcing it, so --status all and --all are now one filter and one wire question — and a value that intent does not reproduce is a user's own predicate, which NARROWS, and that is precisely when dropping it would answer a different question D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.IsTemplate refuse IssueFilter.IsTemplate a template predicate that is not the derived default refuses listIssues publishes include_templates, an intent, not an is_template predicate. &false is what the absent flag derives and sends nothing; nil is what --include-templates derives and sends the flag; &true selects templates ONLY, which no intent on this operation can say D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.ExcludeTypes refuse IssueFilter.ExcludeTypes a type exclusion beyond the derived gate and infra members refuses listIssues publishes include_gates and include_infra — intents — and no exclude_type. The gate member and the whole infra vocabulary are what their absent flags derive; a leftover member is a user's --exclude-type, and dropping it would return the type they asked to hide D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.Ephemeral refuse IssueFilter.Ephemeral an ephemeral predicate that is not the derived default refuses BuildListFilter sets it only for an infra --type, from the same flag the walk already encodes; the wire publishes no ephemeral PREDICATE on the listing — include_ephemeral is an intent that ADMITS the plane, not a selector that restricts to it — so any other value is unstatable D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.SkipWisps refuse IssueFilter.SkipWisps a wisp-merge opt-out that is not the derived default refuses NARROWED by client wave ga-mijra, which closed the client-side gap this row used to record. The walk now encodes include_ephemeral — SkipWisps going false IS that intent, and it is read back off the member the way every other derived default is — so a wisp-inclusive descendant listing crosses instead of refusing, which is the shape gc's TierBoth reads take. What still refuses is a SkipWisps no set of intents reproduces: holding the plane out while include_infra or an infra --type admits it. BuildListFilter never builds that pair, so it is a hand-made filter rather than a flag combination, and dropping the opt-out would merge a plane the caller asked to skip D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.SortBy degrade IssueFilter.SortBy the walk's sort key is DROPPED findAllDescendants accumulates every level into a map keyed by id, so no per-level order reaches the answer: the walk's own assembly discards it before the caller sees it. This is a drop with nothing to drop, and the rendering order is the tree renderer's D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek, D9 TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.SortDesc degrade IssueFilter.SortDesc the walk's sort direction is DROPPED the other half of the order findAllDescendants discards; see P-IssueFilter.SortBy D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek, D9 TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.SkipLabels degrade IssueFilter.SkipLabels the label-hydration opt-out is DROPPED the listing publishes no hydration parameter, so the client cannot ask the server to skip the labels join. Dropping it hands the caller MORE data and never fewer rows, so it cannot be misread as a narrower or wider answer D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek, D9 TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.SkipCounts degrade IssueFilter.SkipCounts the cardinality-hydration opt-out is DROPPED the same absence as SkipLabels, and here refusing would be actively wrong: every text rendering of bd list sets it, so a refusal would kill the walk's DEFAULT rendering — the one behavior D4 classifies the walk as served in order to keep D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek, D9 TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.Priority refuse IssueFilter.Priority a populated IssueFilter.Priority refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.LabelPattern refuse IssueFilter.LabelPattern a populated IssueFilter.LabelPattern refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.LabelRegex refuse IssueFilter.LabelRegex a populated IssueFilter.LabelRegex refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.TitleSearch refuse IssueFilter.TitleSearch a populated IssueFilter.TitleSearch refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.IDPrefix refuse IssueFilter.IDPrefix a populated IssueFilter.IDPrefix refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.SpecIDPrefix refuse IssueFilter.SpecIDPrefix a populated IssueFilter.SpecIDPrefix refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.TitleContains refuse IssueFilter.TitleContains a populated IssueFilter.TitleContains refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.DescriptionContains refuse IssueFilter.DescriptionContains a populated IssueFilter.DescriptionContains refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.NotesContains refuse IssueFilter.NotesContains a populated IssueFilter.NotesContains refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.ExternalRefContains refuse IssueFilter.ExternalRefContains a populated IssueFilter.ExternalRefContains refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.ExternalRef refuse IssueFilter.ExternalRef a populated IssueFilter.ExternalRef refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.UpdatedAfter refuse IssueFilter.UpdatedAfter a populated IssueFilter.UpdatedAfter refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.UpdatedBefore refuse IssueFilter.UpdatedBefore a populated IssueFilter.UpdatedBefore refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.ClosedAfter refuse IssueFilter.ClosedAfter a populated IssueFilter.ClosedAfter refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.ClosedBefore refuse IssueFilter.ClosedBefore a populated IssueFilter.ClosedBefore refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.StartedAfter refuse IssueFilter.StartedAfter a populated IssueFilter.StartedAfter refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.StartedBefore refuse IssueFilter.StartedBefore a populated IssueFilter.StartedBefore refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.AfterCreatedAt refuse IssueFilter.AfterCreatedAt a populated IssueFilter.AfterCreatedAt refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.AfterID refuse IssueFilter.AfterID a populated IssueFilter.AfterID refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.AfterPriority refuse IssueFilter.AfterPriority a populated IssueFilter.AfterPriority refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.EmptyDescription refuse IssueFilter.EmptyDescription a populated IssueFilter.EmptyDescription refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.NoAssignee refuse IssueFilter.NoAssignee a populated IssueFilter.NoAssignee refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.NoLabels refuse IssueFilter.NoLabels a populated IssueFilter.NoLabels refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.PriorityMin refuse IssueFilter.PriorityMin a populated IssueFilter.PriorityMin refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.PriorityMax refuse IssueFilter.PriorityMax a populated IssueFilter.PriorityMax refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.SourceRepo refuse IssueFilter.SourceRepo a populated IssueFilter.SourceRepo refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.EphemeralTier refuse IssueFilter.EphemeralTier a populated IssueFilter.EphemeralTier refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.IsBlocked refuse IssueFilter.IsBlocked a populated IssueFilter.IsBlocked refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.NoParent refuse IssueFilter.NoParent a populated IssueFilter.NoParent refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.MolType refuse IssueFilter.MolType a populated IssueFilter.MolType refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.WispType refuse IssueFilter.WispType a populated IssueFilter.WispType refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.Deferred refuse IssueFilter.Deferred a populated IssueFilter.Deferred refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.DeferAfter refuse IssueFilter.DeferAfter a populated IssueFilter.DeferAfter refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.DeferBefore refuse IssueFilter.DeferBefore a populated IssueFilter.DeferBefore refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.DueAfter refuse IssueFilter.DueAfter a populated IssueFilter.DueAfter refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.DueBefore refuse IssueFilter.DueBefore a populated IssueFilter.DueBefore refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.Overdue refuse IssueFilter.Overdue a populated IssueFilter.Overdue refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.IncludeDependencies refuse IssueFilter.IncludeDependencies a populated IssueFilter.IncludeDependencies refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.NoIDShrink refuse IssueFilter.NoIDShrink a populated IssueFilter.NoIDShrink refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.Offset refuse IssueFilter.Offset a populated IssueFilter.Offset refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.Lite refuse IssueFilter.Lite a populated IssueFilter.Lite refuses on the descendant walk listIssues publishes no parameter for it, and the walk's inversion accounts only for the members BuildListFilter DERIVES plus the explicit filters the operation does publish. Anything left over is a restriction the bridge would have to drop to answer at all, and a dropped filter widens the set invisibly D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek TestTheParentWalkInvertsTheDerivedDefaults
P-IssueFilter.unrecognized refuse — a descendant-walk filter whose intents this client cannot reproduce at all refuses the inversion proves a candidate by RE-RUNNING workapi.BuildListFilter and comparing the derived members, so a candidate the builder itself rejects — an unknown status, a vocabulary the client's degraded copy does not carry (L7) — is never compared. When every candidate is rejected that way there is no member to blame, and refusing on the recognition is the only honest answer D4 (bd list --parent hierarchical walk), D9 L12, escalation ga-2ieek, D9 L7 TestTheParentWalkInvertsTheDerivedDefaults

Ready bridge / WorkFilter (D8)

The throwaway bridge that maps a WorkFilter back onto ready parameters until the front door moves onto issueops.Reader. It refuses every field it cannot express.

ID Kind Field / flag Divergence Why Spec Pinned test
E-WorkFilter.Lite retired — RETIRED — the ready bridge maps Lite onto brief, the same parameter ReadyRequest.Brief now sends upstream #5586 published brief on GET /v0/beads/ready and GET /v0/beads/issues, which is the retirement path this row named. Both page encoders send the parameter now — readyTable, listTable and the ready bridge all map it — so the client asks for the projection it was handed and the server leaves the text columns unselected. The COUNT keeps the drop under E-ReadyRequest.Brief@countReadyWork, because countReadyWork publishes no such parameter and a cardinality has no rows to project. WHAT DID NOT RETIRE WITH IT IS THE WIRE HALF OF THE MARKER, and only that half: types.Issue.IsLitePartial is json:"-" and never crosses, so a projected page arrives on the transport byte-identical to a page of genuinely textless rows — the same absence getIssue's brief_deps carries, deferred upstream by #5549. THE CALLER-VISIBLE AMBIGUITY IS CLOSED, by client wave ga-f352s: brief is a parameter to the page decode rather than a field on anything, so httpReader hands it to wireRows (role_reader.go) and this client stamps IsLitePartial on every row of a page it ASKED to be projected — which is precisely what issueops.ListRequest.Brief's own leaf says a wire consumer distinguishes the two by — and never on a hydrated one. bd list --long --brief therefore prints "Description: (omitted by --brief)" over http exactly as it does locally, and TestHTTPCommentAndBriefRenderEndToEnd pins that line through the real binary D9 (a degradation not in this table is a bug) TestEncoderHonorsEveryTableDisposition
E-WorkFilter.Status refuse WorkFilter.Status a ready-work status that is not the derived default refuses; the default (open only) is DERIVED server-side and drops listReadyWork publishes no status parameter: handleReady decodes a status-LESS request and the server re-derives ready work's status through workapi.BuildReadyFilter, which is unconditionally StatusOpen — open work only, the set bd list --ready shows. The client sends that one derived value as the absence the server reads it back from, so every real bd ready and bd ready --json (whose filter BuildReadyFilter always stamps StatusOpen) round-trips to the identical rows. Any other status is unstatable and refuses: a named status would answer over the query's open-only default rather than the set named, and the empty status is the storage layer's own open+in_progress default, which this operation cannot express either D8 (off-role ready bridge), D9 L12, D4 (derived-default inversion, escalation ga-2ieek) TestEncoderHonorsEveryTableDisposition
E-WorkFilter.Statuses refuse WorkFilter.Statuses a multi-status OR set on ready work refuses listReadyWork publishes no status parameter, and an OR-set is neither the server's derived default (open only) nor anything the wire can carry — dropping it would widen the answer to statuses the caller did not ask for, so it refuses alongside a non-default Status (L12) D8 (off-role ready bridge), D9 L12 TestEncoderHonorsEveryTableDisposition
E-WorkFilter.MoleculeID refuse WorkFilter.MoleculeID restricting ready work to one molecule's direct children refuses listReadyWork publishes parent for the RECURSIVE descendant restriction and nothing for direct membership; the two are different sets, so parent is not a substitute D8 (off-role ready bridge), D9 L12 TestEncoderHonorsEveryTableDisposition
E-WorkFilter.MolType refuse WorkFilter.MolType a molecule-type restriction on ready work refuses no wire parameter — the same absence E-ReadyRequest.MolType records, reached from the other source shape D8 (off-role ready bridge), D9 L12 TestEncoderHonorsEveryTableDisposition
E-WorkFilter.WispType refuse WorkFilter.WispType a wisp-type restriction on ready work refuses listReadyWork publishes include_ephemeral, which admits the wisp plane wholesale, and nothing that selects a wisp TYPE within it D8 (off-role ready bridge), D9 L12 TestEncoderHonorsEveryTableDisposition
E-WorkFilter.ExcludeIDs refuse WorkFilter.ExcludeIDs an id exclusion set on ready work refuses listReadyWork publishes no id-exclusion parameter; the set is what the external-dependency policy decorator (upstream #4753) injects to hide sources behind unsatisfied external blockers, and dropping it would widen the answer to exactly the issues the caller's policy excluded (L12). A server that advertises policy.external_dependencies applies the policy itself, so the client never builds the set for it D8 (off-role ready bridge), D9 L12 TestEncoderHonorsEveryTableDisposition
E-WorkFilter.Offset refuse WorkFilter.Offset a non-zero Offset on ready work refuses no wire parameter, and ready work carries no keyset position to page by; see E-ReadyRequest.Offset D8 (off-role ready bridge), D9 L12 TestEncoderHonorsEveryTableDisposition