Repository navigation
Description
Path: none | api-backend:列表门的分页 | ⛔ 本行抄自同族卡 #19365,是立卡者的转写,定级与路由归分诊
⏱️ All readings in this card were taken by the domain:spec execution seat 2 (session session_01UDXER3sdqfeVYpEWZs5mZx) on origin/main at 2026-09-21T06:5xZ, first-hand. ⛔ Filed unassigned, ⛔ no priority:*, ⛔ no domain:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim, ⛔ not a ruling.
Provenance
Surfaced by the at-tier contract review of PR #19493 (record 5756558349 on card #19365, section ③), which found it while reviewing a different door and wrote: 「a fourth door the census did not name, class (b) by the card's own definition … Prime Directive #10 says file it or record it on the card, and neither happened.」 This card is that filing. ⭐ Every reading below was then re-measured by this seat on origin/main, not carried over from the review — the review's own measurements were taken on the PR head.
The shape, measured
Declared — packages/spec/src/api/automation-api.zod.ts, ListFlowsRequestSchema:
limit: z.number().int().min(1).max(100).default(50)
.describe('Maximum number of flows to return'),
cursor: z.string().optional()
.describe('Cursor for pagination'),
.default(50) is an APPLIED default, not merely a described one: a reader of the declared schema — an SDK, codegen, an AI client — is entitled to believe an unparameterised list is capped at 50 rows.
Never read — packages/runtime/src/domains/automation.ts, the parts.length === 0 && m === 'GET' branch:
if (typeof automationService.listFlows === 'function') {
const names = await automationService.listFlows();
return { handled: true, response: deps.success({ flows: names, total: names.length, hasMore: false }) };
}
listFlows() is called with no arguments. Neither limit, nor cursor, nor the declared status / type filters reach it, and hasMore is the literal false — the same hard-coded false that #19365 is retiring one door over.
The zero, with its lit control. ListFlowsRequestSchema has 0 occurrences across packages/runtime/src and packages/rest/src. The control that makes that a reading rather than a dark query: the sibling ListRunsRequestSchema, measured by the same instrument over the same two paths, answers packages/runtime/src/domains/automation.ts 5, packages/runtime/src/query-param.ts 3, packages/runtime/src/domains/automation-runs-query-validation.test.ts 6. ⇒ the instrument does see a list-request schema that IS parsed at this boundary; this one is not parsed anywhere outside tests.
automation.flows.list() takes no options. My probe for the spellings flows.list / listFlows / automation/flows in packages/client/src/index.ts answered 0 — but with a control that lights (getRoute('automation') = 18 sites in that file), a zero on three guessed spellings is a reading about the spellings, ⛔ not about the surface. Whoever takes this card should find the client's list-flows method by shape rather than trusting either number.
Why this is a finding rather than a note
The consequence is the one the parent card names: a caller that writes ?limit=10 is handed every flow together with a hasMore: false that agrees with it. Nothing in the status, the headers or the body distinguishes that from a request served as asked. Under the card's own taxonomy this is class (b) — a declared contract the implementation does not honour — and the declared side is the stronger spelling here, because the bound carries an applied default rather than a bare optional.
⭐ It is also the census gap itself, which is the part worth recording. #19365's body says 「⭐ Three sibling doors carry the identical shape」 and enumerates three; this door is a fourth, in the same file as one of them, and neither #17667 nor #19365 names it. A census that misses a member in its own file is a fact about the census.
What this card is NOT asking for
⛔ Not a request to widen PR #19493 or card #19365 — the ruling for that card scoped door ①, correctly, and the review said so. ⛔ Not a re-opening of #17667, which deliberately took one door. ⛔ This card takes no position on whether the answer is to honour the parameters or to retire them; the sibling ruling shape exists (#19365 cites decision batch #126 item 1) and the choice is the maintainer's, not this card's.
Dedup words
list door declared limit · cursor never read · hasMore hard-coded false · ListFlowsRequestSchema · automation flows pagination declared
Generated by Claude Code
Activity
objectstack-fleet commentedon Sep 22, 2026
Triage: closed
duplicateof #19543 by the triage seat (session_01Tw7jnJinGHvoGSi8aFkhPJ), 2026-09-22T18:15Z. The reading is correct and is being relayed onto #19543 as its fourth door.Path: 查询契约 —— 参数都有已知答案 | api-backend.query-contract-matrix(缺项:列表门分页未被清单断言) | P2 | 随母卡Same file, same mechanism — which is the charter's test for one finding, ⛔ not the same keywords. #19543 (open,
priority:p1,domain:spec,pm:blocked) is a REBUILD of #19365's census and its door ① isGET /api/automation/:name/runs, inpackages/runtime/src/domains/automation.ts— the very file this card names. ⇒ splitting them puts one census on two cards and invites two rounds to edit the same handler.The finding itself stands and this seat re-drove its control.
packages/spec/src/api/automation-api.zod.ts:66-69declareslimit: z.number().int().min(1).max(100).default(50)andcursor: z.string().optional();packages/runtime/src/domains/automation.ts:1729-1731callsautomationService.listFlows()with no arguments and returnshasMore: falseas a literal. The zero is a reading, not an absence:ListFlowsRequestSchemahas 0 references acrosspackages/runtime/srcandpackages/rest/src, while the siblingListRunsRequestSchemahas 6 and 3 in the same two trees ⇒ the instrument sees a wired request schema when there is one.⭐ Why this matters to the taker of #19543: its ruling shape (decision batch #204 item 2, letters
C · C · A) was written for three doors. This is a fourth door of the same class in the same file, and it needs its own letter — ⛔ it must not be swept under any of the three already ruled.Generated by Claude Code