Repository navigation
export: PDF / print document generation — re-planned for v18, superseding the #1301 NOT_PLANNED closure #8346
Description
Blocked-by: #24283 (the console pin move that carries the print fixes into an installable build — recorded by domain:spec seat 2 at the close-out reading)
Ruled: 6051470224 · letter B′ · 2026-10-08T03:19Z
Earlier blockers, each read closed at the close-out reading (2026-10-18): objectstack-ai/objectui#12915, objectstack-ai/objectui#12924, objectstack-ai/objectui#12906, objectstack-ai/objectui#11958, #22269, #22270, #22271.
Status
Maintainer decision (2026-08-13): PDF document generation is re-planned and scheduled for v18. This supersedes the #1301 NOT_PLANNED closure (2026-06-27).
Ruling history (what this issue reverses)
- [P1] export: no print / PDF export — procurement orders & audit reports cannot be delivered #1301 — "[P1] export: no print / PDF export" was closed
NOT_PLANNED. - spec:
ListView.exportOptionsis typed as a bare array, but the only renderer readsexportOptions.formats#8010 —'pdf'was subsequently removed fromview.exportOptionsformats in@objectstack/spec17.0.0; the enum's error map now carries a retirement prescription andos migrate meta --from 16rewrites existing sources (packages/spec/src/ui/view.zod.ts:1239-1264). Surviving formats:csv/xlsx/json.
Re-introducing the capability therefore has a spec-side unwind cost, not just a renderer cost: the retired enum value, its error-map prescription, and the corresponding removal-registry entry all need to be walked back deliberately (and the migration story for metadata authored against 17 decided).
Why it came back
Solution scoping for an overseas port/terminal customer (2026-08) — and previously the template gap audit (docs/PLATFORM_GAPS_FROM_TEMPLATES.md gap #9, the origin of #1301) — keeps hitting the same wall: statutory / paper deliverables are non-negotiable for billing- and government-adjacent customers. Concrete artifacts in the port scenario alone: invoices, weighbridge tickets, delivery orders, official correspondence, monthly operation reports. Browser Ctrl+P (Console chrome, no pagination) and per-project Puppeteer side-services are the only workarounds today, and every implementation reinvents the latter.
Suggested scope (starting point: the M1–M4 sketch from #1301)
- M1 — declarative print templates in spec (header/footer, pagination, tables, related-record blocks).
- M2 — render engine (headless Chromium HTML→PDF), output downloadable or committed to storage (
sys_file). - M3 — row/detail action integration ("Export PDF", template picker).
- M4 — bulk export (merged PDF / zip) — note the aggregate bulk-action dispatch (
execution: 'aggregate', objectui#3139) already anticipates "merged PDF, batch print" as its example payload, so the action surface is partly in place. - Spec unwind: restore a
'pdf'(or successor) export format value and retire the spec:ListView.exportOptionsis typed as a bare array, but the only renderer readsexportOptions.formats#8010 retirement prescription cleanly.
Related
- [P1] export: no print / PDF export — procurement orders & audit reports cannot be delivered #1301 (superseded), spec:
ListView.exportOptionsis typed as a bare array, but the only renderer readsexportOptions.formats#8010 (enum removal to unwind) - currency: no exchange-rate / home-currency conversion — dynamic multi-currency amounts cannot be reconciled or aggregated across currencies #8345 (FX conversion — same customer scoping batch, also v18)
Activity
objectstack-fleet commentedon Oct 7, 2026
Claim: PM loop round 1 · 2026-10-07T15:26Z
Session:
session_01RPo7FUd6bSnAfkWMAKi848Account:
os-justin(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-8346-pdf-generation-design-roundWorktree:
objectstack-issue-8346Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface: ⛔ none written. Design round only, per triage's release
6039014631: the dev measures and reports; the branch stays empty at its base and no PR is opened (the shape of #22046's measurement round). Read and measured onorigin/main3d9188502e:packages/spec/src/ui/view.zod.ts(exportOptions, the retired'pdf'value and its error-map prescription), the removal / conversion registry entry #8010 left, theos migrate metarewrite for it, the action surface for a document action (execution: 'aggregate'),sys_filestorage, and any existing print / HTML-render path in this repo. Any probe is a local scratch file, deleted after the run. Stop on breach and explain in the report.Container & model:
M,mode:subagent,model: opus(--tier: no path-derived mandate; the tier is the PM's per-card call, default tier for a design round with judgment)Clause-②: no
Responsibility:
n/a — not a defect cardThread-read: 6039014631
Serial constraints cleared: none. The round writes no file. No open PR touches
view.zod.ts(13 open PRs' file lists read at this stamp).What the round delivers (triage
6039014631): a measured design note in theos-dev-report, then this seat writes theneeds-user-decisionanalysis on this card (维护者速读, the four-facet block,Prior rulings read:) for the director to present. ⛔ No production change.objectstack-fleet commentedon Oct 7, 2026
os-dev-report
{ "issue": 8346, "status": "needs_decision", "branch": "claude/issue-8346-pdf-generation-design-round", "pr": null, "session": "session_01RPo7FUd6bSnAfkWMAKi848 — the PM's id (mode:subagent); this run's identity is the branch", "premise_still_valid": true, "summary": "DESIGN NOTE (measurement only; no production change, no PR; branch pushed empty at its base). Anchors: objectstack origin/main 3d9188502e (BASE, spec 17.7.0, no .changeset/pre.json); objectui main 9990f9e122 (equal to the remote main head at read time). [1] H1 CONFIRMED, and wider than three places. The card's cite view.zod.ts:1239-1264 is stale: the block moved to packages/spec/src/ui/list-view-export-options.ts (the shared-block change, #21229) and now has TWO carriers, the list view's exportOptions and the object-grid page component's properties.exportOptions (component.zod.ts:4901, the same object by identity). Every place a restore-'pdf' route walks back, at BASE: (a) enum + error map, list-view-export-options.ts:36-59 (LIST_VIEW_EXPORT_PDF_RETIRED, ListViewExportFormatSchema), formats describe :80-81; (b) union-level refusal view.zod.ts:2357-2366 (exportOptionsPdfUnionError) wired at :2875-2878, plus doc cross-refs at view.zod.ts:90, :2283, :2398, :2436, :4168, :6455, :6486 and component.zod.ts:1787, :4893; (c) conversion view-export-options-pdf-removed, conversions/registry.ts:2296-2385 (toMajor 17, retiredFromLoadPath true, retiredAfter 16.1.0), registered at :14878; (d) step-17 prose migrations/registry.ts:1076-1095; (e) step-18 semantic entry 18.ui-object-grid-export-options-closed.ts:18-24 and :34. Correction to H1's wording: the entry is prose; the refusal on the object-grid row is the shared enum itself; (f) pins: view.test.ts:3909-3975 (3 cases), component-object-grid-export-options-members.pin.test.ts:94-97, view-spelling-walk.test.ts (5 sites), the conversion's own fixture; (g) generated: spec-changes.json:127 and :1019, docs/protocol-upgrade-guide.md:146 and :171, liveness/view.json:200 note, content/docs/references (auto-gen); (h) hand-written: content/docs/ui/views.mdx:112; (i) objectui: packages/types/src/objectql.ts:747-760 (ListViewExportFormat), packages/types/src/zod/objectql.zod.ts:215 (mirror), plugin-grid ObjectGrid.tsx:4084-4106 (supported-format filter csv/xlsx/json). A real 'pdf' then needs a producer on BOTH export paths, the server stream (objectstack packages/rest/src/rest-server.ts:9944-10125 branches csv/xlsx/json) and the client fallback (csv/json). Without one, the filter drops it again: the pre-17 dead state; (j) release-owned history, never walked back: spec CHANGELOG 17.0.0 entry, console CHANGELOG. DECISIVE COST, measured by probe P2: applyConversionsToStoredItem replays the FULL chain including retired entries with no version gate (conversions/stored.ts:17-30, apply.ts:148). A stored view row declaring formats ['csv','pdf'] comes back as ['csv']. Re-admitting 'pdf' while the entry stays therefore silently strips a legal value at every rehydration. Deleting the entry contradicts ADR-0087 ('never deleted', the D2 window paragraph; the chain is a 'forever artifact'), so it needs an ADR amendment (Prime Directive 13). A per-seam excludeConversionIds is the 'filter of convenience' apply.ts forbids. And `os migrate meta --from 16` would keep stripping 'pdf' for a 16-to-18 upgrader. Any shape: the shipped refusal text says 'PDF export itself was declined as NOT PLANNED', which has been false since the 2026-08-13 re-plan. Whichever shape lands rewords it in the same landing: A deletes it, B or C point it at the new surface. [2] H2 CONFIRMED for objectstack, radius widened. The PM grep over packages/ exits 1. The widened pattern (puppeteer, headless chrom, html-to-pdf, pdfkit, pdf-lib, jspdf, pdfmake, wkhtmltopdf, gotenberg, weasyprint, @react-pdf), run over the whole repo minus changelogs, gets 2 hits, both prose (PLATFORM_GAPS doc, a dogfood audit). The only browser dependency is @playwright/test, an e2e devDependency of examples/app-showcase. The runtime image docker/Dockerfile is FROM node:22-slim: no browser, no CJK fonts. What the radius misses: objectui (measured below); cloud is NOT MEASURED (no checkout here, and the search API answers 403 'sessions are bound to their configured repositories'); the templates repo and customer side-services are NOT MEASURED. objectui at 9990f9e: zero PDF libraries in any package.json (control: 43 package.json files name react or lucide-react). The print and PDF paths that do exist: (1) app-shell/src/styles.css:67-260, an @media print sheet (objectui#4462) that hides console chrome, releases viewport clipping, repeats thead, avoids splitting rows and sets an @page 12mm margin; (2) bare window.print() controls in ListView.tsx:4977 (behind schema.allowPrinting, spec view.zod.ts:2932, liveness 'live'), DashboardView.tsx:136 and ReportViewer.tsx:141. Record pages have none; (3) ReportViewer's 'PDF' button, ReportExportEngine.exportAsPDF :118-173: it opens a popup, writes an HTML table with @page size and orientation, and calls print(). If the popup is blocked, it downloads .html; (4) GanttView.tsx:3359-3367 exportPdf with a hand-rolled single-image JPEG-in-PDF writer at :789-805, the ONLY PDF byte producer in either repo (objectstack has zero). So the card's 'Ctrl+P (Console chrome, no pagination)' has been stale since objectui#4462. [3] H3 CONFIRMED, narrower than 'partly in place'. BulkActionExecutionSchema is declared at packages/spec/src/ui/bulk-action.zod.ts:123 ('perRecord' | 'aggregate'). It is used by bulkActionDefs (view.zod.ts:2831-2839) and ActionSchema.execution (action.zod.ts:1156-1208), and lint's validateActionDispatchContract enforces the wiring. Consumers: objectui plugin-grid ObjectGrid.tsx:5098-5123 runBulkActionAggregate (one executeAction carrying params._selectedIds, resultDialog kept), useBulkExecutor.ts:212 and BulkActionDialog.tsx. The specimen is the showcase recalc endpoint, mounted imperatively on http.server ('there is no declarative endpoint surface in a bundle', recalc-endpoint.ts:12). What is in place is the DISPATCH; the PRODUCER is not. Every PDF behind it today is a per-project imperative route with its own browser dependency, which is the card's workaround. The published skill skills/objectstack-ui/rules/actions.md:177-185 already teaches newTabUrl '/api/v1/invoice/{recordId}/pdf' pointing at such a per-project endpoint. [4] H4 PARTLY FALSIFIED. The kernel 'storage' / 'file-storage' service (IStorageService, contracts/storage-service.ts:229-395) writes bytes by key only. A sys_file row is minted only by service-storage's HTTP routes (storage-routes.ts:385 presigned, :453 complete, :502 and :681 chunked), via StorageMetadataStore.createFile (metadata-store.ts:415), which is not a kernel service. No in-process door turns server-produced bytes into a committed sys_file: a search for commitFile, storeFile, putFile, uploadBuffer, createFileFromBuffer and saveFile finds 0 (control: createFile has 4 hits in storage-routes.ts). plugin-email's out-of-row attachments use raw IStorageService with no sys_file row (attachment-storage.ts). A committed row with no sys_attachment or field claim is 'immortal' (stranded-orphan-inventory.ts:11-25), so a generator must also attach its output. Server-side generation therefore needs ONE new service-storage seam (one owner), not a reuse. [5] H5 CONFIRMED external; the in-tree pull is shape-only. docs/PLATFORM_GAPS_FROM_TEMPLATES.md exists at BASE: gap #9 is the row at :21 (P1) and the section at :177-189 (document template engine with data binding; server render by headless Chrome or wkhtmltopdf; download or email). Its origin is the templates repo (contracts, procurement, compliance), not this tree. The port customer has zero in-tree mentions (weighbridge, delivery order, terminal: 0 hits). In-tree models with the shape of a printable document: showcase_invoice plus invoice_line (master-detail, inline line grid), and CRM opportunity plus opportunity_line_item ('a single product line on an opportunity quote'). Neither carries any print or PDF declaration. allowPrinting authorings: 0. exportOptions authorings: 4 (CRM opportunity.view x2, showcase task.view, docs views.mdx), all csv/xlsx/json. Declared-but-dead neighbour: packages/spec/src/data/document.zod.ts DocumentTemplateSchema and DocumentSchema (a docx fileUrl plus placeholders) have zero readers outside packages/spec and are not a metadata type (the file's own header says so), yet they are published (api-surface/data.json, authorable-surface). docs/NEXT_STEP.md:55 still plans ui/document-template.zod.ts. Live precedent of a template kind: email_template, whose engine plugin-email/src/template-engine.ts is mustache-only ('no loops / conditionals / partials'), so as it stands it cannot render invoice lines. [6] SHAPES. A, 'pdf' back in view.exportOptions. Spec: enum +1; delete the error map and the union refusal. Runtime: a PDF table writer on the server stream (a 4th branch in rest-server) and on the client fallback. Where: server stream or browser. Migration: the full list in [1], plus an ADR-0087 amendment for the D3 entry. AI error: asked for an 'invoice PDF', an AI writes formats ['pdf'] and believes it delivered, but gets a table of list rows; the history then reads 'removed in 17, restored in 18'. Resembles a grid's export-to-PDF or printable list view (Airtable, Salesforce Classic), none of the document-generation products. B, a document-template metadata kind + render service + action producing a sys_file. Spec: a new closed metadata type with a DEFAULT_METADATA_TYPE_REGISTRY row (28 types in MetadataTypeSchema today). It declares an object binding, page setup, header and footer, field blocks and related-list table blocks, and every field path is validated against the object at publish. Action wiring reuses ActionSchema locations and the aggregate bulk dispatch. Runtime: a render service with one engine driver (absence loud at boot; the action is refused with a prescription when no engine is configured), the new service-storage commit door, a sys_attachment link, and a download response. Where: server. Migration: additive. exportOptions stays closed, with its prescription re-pointed. The dead data/DocumentTemplate is retired or replaced in the same landing. Footprint reference: email_template spans 17 non-test spec files and 47 non-test files outside spec and plugin-email. AI error: a closed schema with publish-time path validation makes a wrong hole loud; free HTML templates would reproduce email's never-throw-on-render empty holes. Resembles Odoo QWeb reports (a template record + a Print binding on form and list + wkhtmltopdf + save as attachment) nearly 1:1, and Salesforce Quote Templates / Document Generation; Dynamics 365 Word templates are the docx variant. C, browser print only. Spec: at most one key (print on record pages). Runtime: an objectui print layout for record pages on the existing objectui#4462 sheet. Where: browser. Migration: none. AI error: a print button accepted as a 'PDF export', which is exactly the objectui#4462 lesson. It cannot produce a stored file, a batch run, a scheduled monthly report, an email attachment or deterministic statutory output. Resembles Salesforce Classic Printable View and Airtable's print view. Most of C already exists (point [2]). [7] RECOMMENDATION: B, with a block-model template rendered server-side through one engine driver and output as a sys_file attached to the record plus a download; exportOptions stays closed and its prescription is reworded; C is not a separate deliverable; A is rejected. By axis: BUSINESS NEED: every named artifact (invoice, weighbridge ticket, delivery order, official correspondence, monthly report) and gap #9's three (PO, contract, audit report) is a record-bound document with line blocks, or a report, that must be archived, emailed or batched. Only B serves non-interactive generation. A serves list tables, which are already printable via allowPrinting plus objectui#4462. C serves on-screen print. LONG-TERM SOUNDNESS: B is additive and contract-first (the declaration lands with its runtime). A reverses a ruled retirement and collides with ADR-0087 permanence (probe P2). C leaves the decided v18 scope unmet and invites a second template dialect later. AI-ERROR RESISTANCE: B's closed, publish-validated block model is the hardest to write wrong. A gives an AI a one-token way to claim invoice PDFs. C gives an AI a button it can mistake for an export. STARTUP FOCUS: B is the largest. Hold it to M1-M3 (one record to one PDF to a sys_file plus a download). Bulk goes through the existing aggregate dispatch only if the port pull names batch print. Defer DOCX, e-signature, email or flow-node attachment and scheduling. Ship one engine driver, not a matrix. No new gate is proposed.", "tests": "Read-only round; one scratch probe (scratchpad issue-8346/probe.mts, deleted after the run), run with tsx against the worktree's spec SOURCE at BASE 3d9188502e. EXIT=0, output verbatim: P1 parse success: false | P1 first issue: 'pdf' was removed from `view.exportOptions` formats in @objectstack/spec 17.0.0 (PDF export itself was declined as NOT P[...] | P1c control parse success: true | P2 stored formats before: [\"csv\",\"pdf\"] | P2 stored formats after replay: [\"csv\"] | P2c control same reference: true | P3 conversion present: true | P3 toMajor / retiredFromLoadPath / retiredAfter: [17,true,\"16.1.0\"] | P3 total conversions: 129. Greps (counts at BASE unless named): PM's H2 grep over packages/ exit 1; widened PDF/headless pattern over the whole repo minus changelogs: 2 hits, both prose; objectui at 9990f9e: PDF libraries in package.json 0 (control: react or lucide-react 43); objectui and objectstack PDF byte producers: 1 (GanttView.tsx:789) and 0; in-process sys_file commit door 0 (control createFile in storage-routes.ts 4); DocumentTemplate readers outside packages/spec 0; allowPrinting authorings in examples and skills 0; exportOptions authorings 4; 'pdf' authored as an exportOptions format 0; port-customer terms 0. cloud: NOT MEASURED (no checkout; GitHub search API 403, session bound to its configured repositories). Build, typecheck and tests: none run. Nothing was changed, so nothing owed (pnpm install only, per worktree-first). No gate run: no file changed.", "files_changed": "none (branch claude/issue-8346-pdf-generation-design-round pushed empty at 3d9188502e)", "mcp_calls": "0", "api_writes": "1 — POST /repos/objectstack-ai/objectstack/issues/8346/comments (this os-dev-report, via scripts/pm/post-stamped.mjs)", "deviations": [ "Premise refinements, not falsifications: the card's view.zod.ts:1239-1264 cite is stale (the block now lives in list-view-export-options.ts, with a second carrier on object-grid); the card's 'Ctrl+P prints Console chrome with no pagination' is stale since objectui#4462; H4 (a sys_file write door for a server generator) is partly falsified: only the HTTP upload routes mint sys_file rows; H3's 'action surface partly in place' holds for the dispatch only, not the producer.", "cloud repo NOT MEASURED: no local checkout, and GitHub code search answered 403 ('sessions are bound to their configured repositories'); no add_repo was attempted, since the dispatch asked only what the grep radius misses.", "Reads: REST GETs of issues 8346, 1301 and 8010 and their comments (gh api), plus 6 code-search GETs that answered 403. No other GitHub traffic.", "Empty branch pushed at BASE as the write-route probe (git push, not a REST write); no commit, no PR, no label, no assignee write. The branch stays on origin at its base; the local worktree is removed after this report (clean tree, nothing unpushed).", "pnpm install was run in the worktree per worktree-first, though no build was needed; the scratch probe and its output were deleted after the run." ], "open_questions": [ { "question": "Q1. Does 'pdf' return to view.exportOptions?", "options": [ "A. No. 'pdf' stays retired. The refusal text LIST_VIEW_EXPORT_PDF_RETIRED is reworded in the same landing to point at the document-generation surface (its 'declined as NOT PLANNED' clause is false since 2026-08-13). Cost: one string, its pins, and the objectui comment and hint sentences that cite the decline.", "B. Yes, restored as a list-table format. Cost: every site in summary [1](a)-(i), a PDF table writer on both export paths (rest-server stream branch + objectui client fallback), and an ADR-0087 amendment, because the stored-row replay strips 'pdf' with no version gate (probe P2). The alternative is a silent strip of a v18-legal value at every rehydration.", "C. Yes, as a successor value that dispatches to a default document template. That is a second spelling of one capability on a list-export pipe, with the same D3 conflict as B." ], "recommendation": "A. Business: none of the named artifacts is a list table, and list tables already print via allowPrinting plus objectui#4462. Long-term: no ADR-0087 reversal; the storage list() precedent was likewise 'restored correctly shaped', with the old shape staying gone. AI error: no one-token way to claim invoice PDFs. Startup: cheapest path." }, { "question": "Q2. The template model: what does a document template declare?", "options": [ "A. A declarative, closed block model bound to one object: page setup (size, orientation, margins), header and footer (logo, text, page X of Y), field blocks, related-list table blocks (child object, columns, totals) and a signature or footer block. Every field and relationship path is validated against the object at publish. An optional theme CSS. Resembles Salesforce Quote Templates.", "B. An HTML/CSS template string with data holes, loops and conditionals, Odoo QWeb or Visualforce style. Most flexible; holes are validated only if a parser is built. The existing email engine is mustache-only and renders an unknown path as empty, never throwing.", "C. Word/DOCX templates with placeholders (Dynamics 365 Word templates, Salesforce Document Generation), reviving or replacing the dead data/DocumentTemplate (fileUrl + placeholders). Needs a docx merge plus docx-to-PDF conversion (LibreOffice-class engine).", "D. Reuse the page metadata with a print kind, rendered by objectui's React renderer (the #1301 M2 sketch, 'isomorphic with Console'). Server render then means a headless browser loading the console, plus a session for it." ], "recommendation": "A. AI error: a closed, publish-validated schema makes a wrong path loud, while free HTML (B) recreates silent empty holes. Business: invoices, tickets, delivery orders and reports are header + line tables + footer, which A covers. Long-term: one declarative dialect. B can later become an escape hatch inside A only on a named pull. Startup: A is the smallest validator surface. The maintainer also names the kind: 'document_template' collides with the published but dead data/DocumentTemplate export (see Q5)." }, { "question": "Q3. The rendering engine, and where it runs.", "options": [ "A. Headless Chromium inside the runtime (Puppeteer or Playwright-core). Best HTML/CSS fidelity, with native header and footer templates and page numbers. Cost: the runtime image (node:22-slim today, no browser) grows by the browser, its system libraries and CJK fonts; per-render memory and cold start; it cannot run on serverless or edge.", "B. An external render service behind a driver contract (a Gotenberg-style Chromium HTTP sidecar; cloud can host it). The runtime image stays slim and the engine is swappable, following the storage adapter pattern. Cost: self-hosters run a second container; the driver must refuse loudly when unconfigured.", "C. A pure-JS PDF writer in-process (pdfmake or pdfkit class), from the block model directly, with no browser. Runs anywhere and is deterministic. Cost: lower CSS fidelity (a layout DSL, not HTML), and a CJK font subset must be embedded.", "D. Browser-side only (window.print over the objectui#4462 print sheet), i.e. shape C. No stored file, no batch or scheduled output." ], "recommendation": "B as the contract, with exactly one reference driver in v18, keeping boot-time absence loud. Long-term: the engine is a deployment choice behind a contract, not baked into the kernel. Business: statutory output must be deterministic and server-side. Startup: one driver, not a matrix. wkhtmltopdf (Odoo's engine) is not recommended because upstream is unmaintained. If the maintainer weights zero-dependency deployability over CSS fidelity, C is the trade, and it pairs naturally with block model A. This is a genuine trade-off for the maintainer." }, { "question": "Q4. Where does the output land?", "options": [ "A. A committed sys_file attached to the source record (sys_attachment), plus a download response. Needs ONE new in-process service-storage door that commits server bytes as a sys_file row: today only the HTTP upload routes mint rows (H4), and an unattached committed row is never reaped.", "B. A download stream only, with no storage. Simplest, but nothing is archived, so no email attachment, batch or audit trail.", "C. A file field named by the template. Field-reference claim semantics apply; one file per field slot." ], "recommendation": "A. Business: the named artifacts are statutory and must be archived and re-sent. Long-term: one owner (service-storage) gains the door instead of each generator hand-rolling bytes-plus-row. AI error: an attached file is visible on the record, so a failed generation is not silent. Startup: one seam." }, { "question": "Q5. The v18 scope cut, and the dead data/DocumentTemplate.", "options": [ "A. v18 = M1-M3: the template kind, one render driver, and a record/row action producing a sys_file plus a download. The dead data/DocumentTemplate, DocumentSchema and ESignatureConfig are retired in the same landing under ADR-0049 (zero readers outside packages/spec; a published export, so it is breaking in 18 with its D3 entry). M4 bulk (merged PDF or zip via the existing execution 'aggregate' dispatch) only if the port pull names batch print. Deferred: DOCX, e-signature, email or flow-node attachments, scheduled reports.", "B. v18 = M1-M4 including bulk merged PDF and zip.", "C. Keep data/DocumentTemplate and name the new kind print_template, avoiding the collision: two 'template' dialects coexist." ], "recommendation": "A. Startup focus: capability grows only on named pull. The port customer names single documents and monthly reports; batch print appears only as the aggregate example payload. Long-term: one 'document template' meaning, not two. AI error: an AI importing DocumentTemplateSchema today gets a schema no runtime reads. The bulk call is the maintainer's, on the customer evidence." } ], "out_of_scope_findings": [ "carrier: whichever PR lands #8346 (in this card's own scope, not a separate card) · noted, not filed — the shipped refusal text LIST_VIEW_EXPORT_PDF_RETIRED (list-view-export-options.ts:36-42) says 'PDF export itself was declined as NOT PLANNED', false since the 2026-08-13 re-plan; the same sentence recurs in objectui types/src/objectql.ts:750, ListView.tsx:4970-4975, ReportViewer.tsx:131-134, app-shell styles.css:79 and content/docs/ui/views.mdx:112 · dedupe words: NOT PLANNED, LIST_VIEW_EXPORT_PDF_RETIRED, pdf retirement text, exportOptions pdf", "carrier: the shape-B implementation PR (none if B is not chosen; then an enforce-or-remove card is the seat's call) · noted, not filed — packages/spec/src/data/document.zod.ts DocumentTemplateSchema / DocumentSchema / ESignatureConfigSchema: published, zero readers outside packages/spec at 3d9188502e, not a metadata type; dead declaration, no producer stores it, so not class c · dedupe words: DocumentTemplateSchema, document.zod.ts, dead declaration, enforce-or-remove", "carrier: the objectui PR that lands the print/PDF surface · noted, not filed — objectui ReportViewer's 'PDF' button runs exportAsPDF (ReportExportEngine.ts:118-173): a print popup, an .html download when the popup is blocked; its own comment (ReportViewer.tsx:131-134) calls it a PDF export. Read only, not reproduced in a browser this round, so no reach measured · dedupe words: ReportViewer PDF button, exportAsPDF, print popup, html fallback", "carrier: the shape-B implementation PR (docs and skill update) · noted, not filed — skills/objectstack-ui/rules/actions.md:177-185 teaches newTabUrl '/api/v1/invoice/{recordId}/pdf' to a per-project endpoint, and docs/NEXT_STEP.md:55 plans ui/document-template.zod.ts; both become stale or anti-pattern once a platform surface lands · dedupe words: open_invoice_pdf, newTabUrl pdf, document-template.zod.ts, NEXT_STEP 13.2" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 7, 2026
Seat verdict: ACCEPT the measurement round (
6041346785); the contract shape goes to the maintainer ·domain:specseat 3 (#18883) ·session_01RPo7FUd6bSnAfkWMAKi848· 2026-10-07T15:45ZChecked on GitHub and
origin/main3d9188502e, not from the report:claude/issue-8346-pdf-generation-design-roundsits at its base3d9188502e, no commit and no PR; the report comment is intact (25,152 bytes, tail present).LIST_VIEW_EXPORT_PDF_RETIREDlives inpackages/spec/src/ui/list-view-export-options.ts:36and still says "PDF export itself was declined as NOT PLANNED" (:38), false since the 2026-08-13 re-plan.conversions/stored.tsstates "The full chain replays, includingretiredFromLoadPathentries" (:17), and ADR-0087 says a retired conversion is "never deleted" (:145) and the chain is "a forever artifact" (:306). So re-admitting'pdf'while the protocol-17 conversion stays would strip it from stored rows at every rehydration (the report's probe P2:['csv','pdf']→['csv']).DocumentTemplateSchema/DocumentSchema: no code reader outsidepackages/spec(hits are docs only, two of them generated references).sys_filerows are minted only by the HTTP upload routes (storage-routes.ts:404,:520→metadata-store.ts:415); no in-process door commits server-produced bytes.Release:
session_01RPo7FUd6bSnAfkWMAKi848· why: the measurement round is delivered and the shape is the maintainer's to rule · to:needs-user-decision, unassigned. Whoever implements the ruled shape claims afresh.待裁(
needs-user-decision):v18 的 PDF / 打印文档,用哪种契约形状交付?维护者速读
'pdf'拿回来;另一条是新增"文档模板"这一种元数据。allowPrinting)。两个仓库里都没有任何能在服务端生成 PDF 的东西。'pdf'。一句话问题
客户要从一条业务记录(比如一张发票)生成一份能存档、能再发出去的正式 PDF 文件,平台应该用什么方式让应用作者声明它?
背景
6041346785(只读,未改码)。'pdf'从列表导出格式里退役了(spec:ListView.exportOptionsis typed as a bare array, but the only renderer readsexportOptions.formats#8010),并且写进了协议转换链和升级迁移。8 月 13 日你改为 v18 要做,分诊6039014631释放本卡时明确"形状待裁"。Governing text
docs/adr/0087-metadata-protocol-upgrade-contract.md:145):已退役的转换条目"never deleted";:306转换链是"a forever artifact"。存量行重放全链、含已退役条目(packages/spec/src/conversions/stored.ts:17)。packages/spec/src/ui/list-view-export-options.ts:36-42:现行退役文案说"PDF export itself was declined as NOT PLANNED",8 月 13 日起已不成立。前提(各带复核命令与阳性对照)
git grep -n "declined as NOT PLANNED" origin/main -- packages/spec/src/ui/list-view-export-options.ts(对照:同文件git grep -c "ListViewExportFormatSchema"应 >0)。'pdf'转换。git grep -n "including \retiredFromLoadPath` entries" origin/main -- packages/spec/src/conversions/stored.ts(对照:同文件git grep -c "applyConversionsToStoredItem"` 应 >0)。git grep -l -i -E "puppeteer|pdfkit|pdf-lib|pdfmake|gotenberg|wkhtmltopdf" origin/main -- packages/(应为空;对照:git grep -l "@playwright/test" origin/main -- examples/应命中)。sys_file的门。git grep -n "createFile(" origin/main -- packages/services/service-storage/src/storage-routes.ts(只在 HTTP 路由里;对照:metadata-store.ts里有async createFile定义)。DocumentTemplateSchema无代码读者。git grep -l "DocumentTemplateSchema" origin/main -- . ':!packages/spec' ':!content'(应为空;对照:packages/spec/src/data/document.zod.ts内计数 >0)。选项 × 真实代价
'pdf'恢复为列表导出格式,服务端和前端各加一个"表格转 PDF"'pdf'剥离(实测会被静默剥掉),并回退约 9 处退役痕迹sys_file挂到记录上并给下载;列表导出保持关闭,退役文案改指新能力service-storage一个新的存档入口业务含义直译
os-decision-facets
DocumentTemplateSchema,不留两套"模板"含义。Prior rulings read: pdf,exportoptions,print,document template → 0 hits; none; thread: none; repo: objectstack-ai/objectstack;另读 ADR-0087 D2/D3(
:145、:306)与 #8010 / #1301 的退役记录。推荐
B。 两年后的样子:平台有一个"文档生成"能力,单据格式以元数据声明,生成引擎躲在驱动契约后面可替换,产物作为附件归档;主流对照是 Odoo QWeb 报表(模板记录 + 打印入口 + 存为附件)和 Salesforce 报价单模板 / Document Generation。
execution: 'aggregate'批量分发以后能直接接上)。DocumentTemplateSchema/DocumentSchema/ESignatureConfigSchema。 推荐在同一次落地按 ADR-0049 退役(已发布、零读者,v18 内属于破坏性变更,带迁移条目),新类型沿用"文档模板"这个名字。裁后执行
DocumentTemplateSchema;②service-storage:进程内存档入口(存为sys_file并挂附件);③ 渲染服务加一个引擎驱动,未配置时启动即响亮报出;④ 记录页 / 行操作的"生成 PDF"动作(objectui 侧另立卡)。每张卡带拒收用例与契约复核。objectstack-fleet commentedon Oct 7, 2026
Box intake (triage): the face is complete and ready for the director. The decision is the
domain:specseat's6041425322. Its recommendation is B (fallback C, the minimum delivery), with the sub-questions answered by default if the maintainer replies with a letter only. The labels stand (needs-user-decision·domain:spec·target:v18).Read for intake:
Governing text:;os-decision-facetsblock;Prior rulings read:.None is missing.
Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-07T20:55Z. ⛔ Not a claim.objectstack-fleet commentedon Oct 8, 2026
Ruling: batch #288 item 3 · letter B′ · maintainer 「8346 B′」 2026-10-08T03:18Z
Director seat, summon #35,
session_01VYToj6PQehTEKNrjGM9akg(GitHubos-zhuang; written asobjectstack-fleet[bot]via the relay). Batch #288 presented thedomain:specseat's decision request (6041425322: A restore the list export, B a new document-template metadata type, C browser printing only; the seat recommending B) in the detailed form. The maintainer asked how the mainstream platforms model document templates, whether AI writes the template, how it is previewed and whether a visual designer is needed, and then proposed the simpler shape: an AI-authored metadata page that declares paper, header and footer. The seat read the proposal against the platforms (Odoo's QWeb report plusreport.paperformat; Salesforce's VisualforcerenderAs="pdf"), named the two hard parts it does not remove (the render engine; print-safe blocks) and reframed it as B′; the maintainer answered 「8346 B′」. Freshness gate: the body and all thirteen comments (newest 6046696492, triage's box intake) were re-read before this record; nothing newer exists. Thread-read: 6046696492.The ruling
B′. A document is a page with a print declaration; no new template type.
page. The body vocabulary is the page's own blocks (field blocks, static tables of all rows, text, images), which AI already authors through the Studio author's metadata-authoring skill and the console already renders and previews. The page gains an optionalprintdeclaration: paper size and orientation, margins, header and footer blocks, page numbering, page-break hints, mapped to print CSS (@page, repeated table heads,break-inside). A printable block subset is defined and linted: a block that virtualises rows or lays out responsively is refused inside a print page, with pins.sys_fileattached to the record, downloadable and usable as an email or flow attachment; a deployment without the driver configured reports it loudly at startup, it does not fail silently at the first request. ⛔ No in-process layout driver: a page model needs a browser to render.'pdf'; the retirement sentence inpackages/spec/src/ui/list-view-export-options.ts("PDF export itself was declined as NOT PLANNED") is rewritten to point at the print page, because it is no longer true. The zero-readerDocumentTemplateSchema,DocumentSchemaandESignatureConfigSchemaretire in v18 under ADR-0049 with ADR-0087 entries, so that "template" means one thing.'pdf'on list export: it prints lists, not documents, and reverses a recorded retirement against ADR-0087's forever-chain), B (a second authoring vocabulary beside pages; withdrawn by the seat on the maintainer's proposal), C as the end state (browser printing alone yields no archive), a Word-upload template kind, batch merging or packaged downloads (not in v18 unless a customer names them), and the in-processpdfmake-class driver.Why B′ on the first axis: one authoring vocabulary for every rendered surface, screen and paper alike; the two platforms whose model this follows (Odoo, Salesforce) have kept it for a decade. The second axis holds: the port customer's five document kinds (invoice, weighbridge ticket, delivery order, official letter, monthly report) are record-plus-lines documents a print page expresses. The third: the page's blocks are validated at publish today and the declaration adds a few checked fields. The fourth: M1 adds almost no parts; M2 adds one driver.
State
needs-user-decision→pm:queuein this act;enhancement·priority:p2·domain:spec·target:v18unchanged, no assignee. Thedomain:specseat claims this card as the design parent and splits it, spec first: ① spec, theprintdeclaration onPageSchema, the printable subset and its lint, the export-options text, the three retirements; ② objectui, the print CSS mapping, the printable blocks, the record page's print action (domain:ui); ③ the render service, the Chromium driver and theservice-storagein-process archive entry (domain:services); ④ the record-page "generate PDF" action and the attachment on the record. Each card carries its refusal cases and the contract review; the Studio author's skill learns the print page when ① lands. Body:Ruled:line added in the same act.Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
Claim: PM loop round 1 (the design parent, per the ruling
6051470224: "Thedomain:specseat claims this card as the design parent and splits it, spec first") · 2026-10-08T03:22ZSession:
session_01RPo7FUd6bSnAfkWMAKi848Account:
os-justin(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-8346-pdf-generation-design-round(the measurement round's empty branch; no code lands on the parent)Worktree: none (the parent carries no code)
Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface: none on the parent. Each split card declares its own at its claim.
Container & model:
n/a — a design parent; each split card is dispatched on its own claimClause-②: no
Responsibility:
n/a — not a defect cardThread-read: 6051470224
Serial constraints cleared: n/a for the parent. The split follows the ruling's order:
printdeclaration onPageSchema, the printable block subset and its lint, thelist-view-export-options.tsretirement sentence, and the three zero-reader retirements (DocumentTemplateSchema,DocumentSchema,ESignatureConfigSchema) under ADR-0049 with ADR-0087 entries.domain:ui), ③ the render service (domain:services) and ④ the record-page "generate PDF" action and attachment: each is filed once ①'s contract shape is on a PR, so their cards cite the declared shape rather than predict it.The parent stays
pm:dispatchedwith this seat until ①–④ close. Each split card carriesPart of #8346and its own refusal cases and contract review.feat(spec,lint): a page gains an optional print declaration and the p…
feat(spec): the list-export pdf prescription points at the print page…
feat(spec)!: retire the zero-reader document family whole (DocumentTe…
objectstack-fleet commentedon Oct 8, 2026
The split is filed.
pm:dispatched→pm:blockedon the remaining cards, and this seat's claim is releaseddomain:specseat 3 (#18883) ·os-justin· sessionsession_01RPo7FUd6bSnAfkWMAKi848· 2026-10-08T10:52Z · holder of claim6051507786(the design parent), which this act releases.The ruling of record
6051470224(letter B′) ordered this seat to claim the card as the design parent and split it, spec first. The split is complete:PageSchema.print, the printable subset and its lint, the export-options sentence, the four document schemas retireddomain:spec326a90a4a3(6058198073)record:line_itemscap underprint), the record page's "print" action, objectui's leftover "NOT PLANNED" sentencedomain:uipm:on-hold,Restart-when:an installable@objectstack/specexportsPagePrintSchemasys_filearchive, loud at startupdomain:servicespm:queuedomain:spec, inherited; triage routes it when it unblockspm:blocked,Blocked-by: #22269actions.md's per-project/pdfendpoint goesdomain:skills(Tier H)pm:queueThis card:
pm:dispatched→pm:blocked, unassigned. The body gains oneBlocked-by:line per open card. When all of them have closed, the unlock scan brings the card back so it can be closed as delivered.Release:
session_01RPo7FUd6bSnAfkWMAKi848· why: the design parent's split is filed and its spec half has landed · to:pm:blocked, unassigned.feat(spec)!: a page gains an optional print declaration and a linted …
skills(ui): the page skill learns the print page — `print`, the print…
objectstack-fleet commentedon Oct 15, 2026
Grade p2 → p1: the maintainer names PDF for 18.0 GA · triage seat ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-15T23:14ZSource. The maintainer said 「PDF 要赶 18.0 正式版」 in this session's live chat on 2026-10-15. Their standing rule is 「发版本优先的都p1」, so this parent and its open children move to p1:
pm:queue;pm:blockedon print page ③ of #8346: a render service with one headless-Chromium driver renders a print page under the requesting user's principal and archives the PDF as a sys_file (M2) #22269;page.printandtranslation.flows.successMessage/errorMessagereadplannedwhile the shipped console applies them (family card; theparentDataSourceleg is #23585) #23710, the print ledger flip. Every compile still tells authors that printing a page prints the screen layout, which has been false since PR chore(objectui): move the console pin to 1f23d5b070fa, carrying objectstack-ai/objectui#12475 and objectstack-ai/objectui#12493 #23709.Unchanged: the ruling B′ (
6051470224), the lane (domain:spec, the design parent) andtarget:v18.The critical path to GA is serial. #22269's build runs in stages: S1 the archive entry, S2 the credential mint (with its spec part), then S3 + S4, the print service with both placements (
6204149204). #22270 follows it. Cloud's adoption card for the remote placement follows the option's name.⛔ Not a claim.
objectstack-fleet commentedon Oct 17, 2026
Re-blocked on the chain's new child objectui#12906 · stays p1 ·
target:v18· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-17T19:00ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
page.print, the printable block subset, its lint) now that #22158 has landed — #8346 ruling B′ #22271 closed 2026-10-08.printshows none of its header actions — no Edit / Share / Delete, no declared record_header action (the showcase invoice hides "Submit for Sign-off" and "Generate PDF") objectui#12906 (p1,target:v18,pm:queue), found by print page ④ of #8346: a record-page "generate PDF" action that calls the render service and attaches the archived PDF to the record #22270's dev, shows that a record whose default record page declaresprintdraws none of its header actions. On the showcase invoice that includes ④'s "Generate PDF". Since the print service prints only the default record page, every app that wants a server PDF hits it.pm:blocked. ABlocked-by: objectstack-ai/objectui#12906line is added to the body, and the unlock scan releases the parent when that closes.domain:specseat, as design parent, reads ruling B′'s list (6051470224) againstmainand the pin, and closes this card or names what remains.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Re-blocked: objectui#12906 closed; two print-path p1s found since · stays p1 ·
target:v18· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-17T22:55ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
printshows none of its header actions — no Edit / Share / Delete, no declared record_header action (the showcase invoice hides "Submit for Sign-off" and "Generate PDF") objectui#12906 closedcompleted. A print record page now draws its header actions, including ④'s "Generate PDF".pm:dispatched): a read-only line-items table printed raw numbers and stored values.pm:queue): boolean and multi-file line cells print English.pm:blocked. TwoBlocked-by:lines name them in the body, under the same rule as before: the unlock scan releases the parent when both close. Then thedomain:specseat reads ruling B′ (6051470224) againstmainand the pin, and closes this card or names what remains..objectui-shacarries these merges. That pin is still5e15928b46.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Unlock:
pm:blocked→pm:queuefor close-out · p1 ·target:v18· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-18T07:47ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
Blocked-by:target on this card is closed.page.print, the printable block subset, its lint) now that #22158 has landed — #8346 ruling B′ #22271 were closed before.domain:specseat, as design parent, reads ruling B′ (6051470224) againstmainand closes this card or names what remains..objectui-shacarries those three merges. It is still5e15928b46, which carries none of them, so the PDF chain is complete on objectuimainbut not yet in a build. That pin move is the release step this card's close-out should name.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Claim: PM loop round 1 · 2026-10-18T07:58Z · the design parent's close-out, per triage
6247300226: read ruling B′ (6051470224) againstmainand the console pin, then close this card or name what remainsSession:
session_019oFY6Hi35J7atvgVFnmoaKAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch: none (a seat reading; no code lands on the parent)
Worktree: none
Domain:
domain:specSeat:
domain:spec#2(seat post #18549)File surface: none on the parent. A reading of
origin/mainand of objectui at the.objectui-shapin.Container & model:
n/a — a seat reading by this session, no dev is dispatchedClause-②: no
Responsibility:
n/a — not a defect cardThread-read: 6247300226
Serial constraints cleared: n/a for a reading. No open PR or in-flight claim names this card.
Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Close-out reading: ruling B′ against
mainand the console pin · stays open,pm:dispatched→pm:blockedon #24283 ·domain:specseat 2 ·zhuangjianguo· sessionsession_019oFY6Hi35J7atvgVFnmoaK· 2026-10-18T08:03Z⛔ Not a dispatch. This is the design parent's close-out that triage's unlock
6247300226asked for, under claim6247391043.Readings: objectstack
origin/main93b4acb57e; objectuiorigin/main, deepened 400 commits. Every negative ancestry reading has a control leg: the pin's own~3answers exit 0.main/ at the pinprintdeclaration onPageSchema, the printable subset and its lintPagePrintSchemainpackages/spec/src/ui/page.zod.ts(5 hits); ruleprint-page-block-unprintableinpackages/lint/src/validate-print-page-blocks.ts(#22158, PR #22193)mainpackages/spec/src/ui/list-view-export-options.ts:40–:43names the print page andallowPrintingmainDocumentTemplateSchema,DocumentSchema,ESignatureConfigSchemaretirepackages/spec/src/data/index.ts:244–:255remains underpackages/spec/srcoutside tests and conversions (control:PageSchemain 61 files)mainsys_filearchive, loud at startuppackages/services/service-print/src/chromium-driver.ts,print-service.ts,print-service-plugin.ts(#22269, closed 2026-10-17)maind9a749bae0main2312bd9a6(objectui PR #12356) and263e9ddcc(objectui PR #12729) are in the pind637be321(objectui PR #12921)8523e81db(objectui PR #12923)32b492b67(objectui PR #12937).objectui-shais5e15928b4631, set by PR chore(objectui): move the console pin from f8267df93aba to 5e15928b4631 before 18.0.0-next.3 #24144, and objectuimainis 62 commits past it. By the cross-repo rule the test is "the consumer can install it", not "the upstream merged". So the chain is complete on bothmains but not in an objectstack build, and ④'s "Generate PDF" is unreachable on a print record page there.maincommit at or after32b492b67. It also carries objectui#12854's fix (54e79f989), which spec(stack): defineStack's hydrated inline-column check (collectHydratedInlineColumnErrors) does not walkrecord:line_items, so once its columns hydrate, a currency column withscalepublishes there and is refused on the master-detail carriers #24190 waits on.d637be321,8523e81dband32b492b67, then closes this card as delivered. Nothing else of B′ is open.Release: session
session_019oFY6Hi35J7atvgVFnmoaK· claim6247391043· why: the close-out reading is done, and the remainder is #24283 · to:pm:blockedonBlocked-by: #24283(body rewritten in this act; the seven closed targets move to a prose line), assignee cleared.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Unlock:
pm:blocked→pm:queue· p1 ·target:v18·domain:spec(the close-out) · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-18T13:02ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
f5e98a35d1(11:34Z).origin/main.objectui-shais now0707b4ae3712.git merge-base --is-ancestoragainst0707b4ae37(objectui) → ancestor for all three print fixes:d637be321(objectui#12906),8523e81db(objectui#12915) and32b492b67(objectui#12924).domain:specseat 2's close-out reading (claim6247391043, reading6247425715): read ruling B′ againstmainand this pin, then close the parent or name what remains.nextis still18.0.0-next.3. The chain is onmainand in the vendored console. It reaches an installed build only withnext.4(chore: version packages (next) #24168, the maintainer's). Whether "done" waits on that publish is the close-out's call, against B′'s own words.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Close-out reading 2: ruling B′ against
mainand the console pin · closedcompleted·domain:specseat 2 ·zhuangjianguo· sessionsession_019oFY6Hi35J7atvgVFnmoaK· 2026-10-18T13:40Z⛔ Not a dispatch. This is the second close-out reading that triage's unlock (
6250236268, 2026-10-18T13:02Z) asked for. The first reading (6247425715) left one row open: the console pin.Readings, taken in this act: objectstack
origin/main.objectui-sha=0707b4ae37120d45d6401170666a0b76cb7a3546, moved by PR #24311 (#24283, closedcompleted). In an objectui clone fetched in this act,git merge-base --is-ancestor COMMIT 0707b4ae37returns exit 0 for each fix below. The control leg, the pin's own~3, also returns exit 0.printdeclaration, the printable subset and its lintPagePrintSchemainpackages/spec/src/ui/page.zod.ts(5 hits onmain); #22158 closedcompletedmain6247425715)mainpackages/services/service-print/src/chromium-driver.tsonmain; #22269 closedcompletedmaincompletedmaincompleted2312bd9a6and263e9ddccare ancestors of the pind637be321is an ancestor of the pin; the issue is closedcompleted8523e81dbis an ancestor of the pin; the issue is closedcompleted32b492b67is an ancestor of the pin; the issue is closedcompletedWhy this closes now, and does not wait for a publish. Ruling B′ (
6051470224) names the parts (①–④, M1, M2) and their split. It sets no condition on a release. This repository consumes objectui by pin, and for a pin-consumed repo the pin move is the installable point. npmnextreads18.0.0-next.3in this act (npm view @objectstack/spec dist-tags). An installednextbuild carries the chain fromnext.4on. That publish is the maintainer's act (#24168), and this card does not track it.State: closed
completed;pm:queueis removed in the same act.domain:spec,target:v18and the type labels stay. The earlier claim (6247391043) ended with reading 1's release topm:blocked. This reading needed no new claim: it closes the card in one write.Generated by Claude Code