Repository navigation
Upgrade the @objectstack/* dependencies from 17.3.0 to 17.4.0 #35
Description
Maintainer directive, 2026-09-09, verbatim: 「object stack 可以升级到 17.4 了」.
@objectstack/* 17.4.0 was published today and is now latest on every package this repo
consumes. This card moves the app onto it and proves the app still works, on a real boot in a real
browser — not by the version string changing.
Where the repo actually is (readings, 2026-09-09T13:50Z)
| Reading | Value | How |
|---|---|---|
| Declared range | ^17.0.0 on @objectstack/spec, runtime, plugin-hono-server, cli |
package.json |
| Resolved pin | 17.3.0, every package | pnpm-lock.yaml ('@objectstack/cli@17.3.0', spec@17.3.0, runtime@17.3.0, plugin-hono-server@17.3.0) |
latest on npm |
17.4.0 | npm view @objectstack/<pkg> dist-tags — all four agree |
| Protocol range | engines: { protocol: '^17' } (objectstack.config.ts:35) |
17.4 is inside it; ⛔ do not widen it |
The caret already admits 17.4.0 — the lockfile is what is holding the app at 17.3.0. So this is
not only a package.json edit; the lockfile has to move and be committed.
What is coming with it
17.4.0 is 396 changesets across 61 packages: 35 carrying a breaking marker, 140 other minor,
221 patch (content/docs/releases/v17/17-4.mdx on objectstack-ai/objectstack@origin/main). That
page is a machine draft and says so — its breaking list is "a floor, never a clearance", so an
unmarked breaking change would not appear on it. Treat it as a starting point for the sweep, not the
sweep.
Exposure the PM measured — front-load this one
b398ad2 — BREAKING (behaviour), the one most likely to break this app:
a static
readonlyfield is now stripped from a non-system caller's INSERT payload inside
engine.insert, exactly as it already was onengine.update. […] Seeding a read-only column at
create time is a system act — usecontext.isSystem, a flow'srunAs: 'system', a system hook
or a seed.
src/objects/contract.object.ts declares ~20 readonly: true fields — owner_id, the four
route_* booleans, and the nine lifecycle timestamps (submitted_at, review_started_at,
approved_at, signed_at, activated_at, archived_at, …). The file's own comment at line 26 says
"which is why readonly: true does not lock the engine out" — that sentence was written against
17.3 and is exactly the kind of claim this release re-opens.
The changeset's own text says a seed is a system act, so the seeder should be unaffected — ⛔ that
is a PM mechanism assumption, not a finding. Falsify it first, because if it is wrong the failure
mode is the one this repo already shipped once: #26, owner_id NULL on all 120 seeded contracts
and 我的合同 blank for every audience. A silent column drop reports through onFieldsDropped /
droppedFields and a warn log — so read the boot log, do not just count rows.
Exposure the PM measured as absent (do not spend time re-deriving)
grep -rnE "\btimeout\b|\bttl\b|idleTimeout|sessionTimeout" --include=*.ts . → zero hits outside
node_modules. The same grep style returns 20+ hits for readonly: true, so the zero is real and not
a broken pattern. That clears:
e9fcd6b(duration-unit key renameshook.timeout/job.timeout→timeoutMs,ttl→ttlMs)ed5d557/5071310/bc0ac1d/0145680(driver-tursotimeoutrefusals — this app has no turso driver)7629f4d(MetadataManagerConfig.cacheretirement)
Also measured absent in src/: record_picker (clears 414c1fc), 'tree' fields (clears
fb77aa5), any ESignatureConfig / deadline key (clears the ESignatureConfig half of c463d03).
Re-verify these yourself before relying on them — they are one PM grep at one moment, and the
release list is a floor.
Exposure that needs a measurement, not a guess
- Flows (
src/flows/:contract-intake,contract-approval,signature-record) —21aabbc,
52804cd,53cf263makeFlowSchemarefuse duplicate node ids, duplicate edge ids, and a region
node id colliding with the top-level id space.pnpm validateis the instrument. - Dashboards / datasets —
233222eclosestimeDimensions[].dateRange's string arm to the
date-range preset vocabulary, refusing anything else with400 ANALYTICS_DATE_RANGE_UNRECOGNIZED.
src/dashboards/legal.dashboard.ts:193describes "thetimeDimensionsentry the executor
shifts". All three dashboards must be opened in a browser, not just validated. - Positions / security —
8e0b297makespositions[]on the session payload the security axis.
This app binds position sets insrc/security/bind-position-sets.tsand has seven positions. - i18n —
cf9bda4makes the kernel's in-memory fallback learn the declaredi18n.fallbackLocale
(this app declaresfallbackLocale: 'en').pnpm lint:i18n-gatemust still exit 0 and the
zh-CNconsole must still be Chinese; Card 11 — translations:en(default) andzh-CN, with a gate that fails on a missing key #32 landed that surface yesterday and it is the newest,
least-settled thing in the repo. 65846bc— a batch row now reports a unique-constraint refusal asUNIQUE_VIOLATION. This app
declares unique indexes; the seeder inserts in batches.
Rider: closes #34 (declared, not smuggled)
#34 asks for two prose numbers to be corrected and says in its own body that the fix should "ride
the next card that touches these files". This is that card: it re-boots the app and re-measures both
quantities as a matter of course.
src/data/index.ts:81says the demo installs 780 rows; it installs 820. One word.scripts/demo.mjs:16-17(0.813s) andsrc/data/plan-contracts.ts:28(~1.8s, annotated
(measured)) give two answers for the same interval. Two numbers in the repo's own prose are wrong or contradict each other (780 vs 820 rows; 0.8s vs ~1.8s) #34 is explicit: ⛔ do not swap one
unverified number for another. Re-measure on your 17.4 boot, make the two sites agree — or delete
the number fromplan-contracts.tsand have it citedemo.mjs, so there is one place to be wrong.- Report the row count you actually observe. If 17.4 changes it, 820 is not automatically the
answer — say what you measured and why it differs.
Put Fixes #34 in the PR body only if you actually re-measured both. If you did not, leave #34
open and say so.
Acceptance
pnpm validate && pnpm lint && pnpm typecheck && pnpm lint:i18n-gate— all four exit 0, exit codes
captured before any pipe.pnpm-lock.yamlshows 17.4.0 for all four direct dependencies and is committed.- A boot-log diff against
main— same seed, clean.objectstack/data, both read at seeder
quiescence (row count stable and log stable), not at the ready banner. Card 11 — translations:en(default) andzh-CN, with a gate that fails on a missing key #32's report shows why:
its first baseline read 135 lines / 0 errors and the seeder then wrote 142 more. Report new
warnings,onFieldsDropped/droppedFields, and anySystem started with degraded capabilities. - Browser (
pnpm dev --seed-admin, Chromium at/opt/pw-browsers/, ⛔ noplaywright install):
sign in, open 我的合同 (the The demo opens on an empty screen:owner_idis NULL on all 120 seeded contracts, so 我的合同 › Launched by Me is blank for every audience #26 surface — confirmowner_idis populated), the contract detail
page's seven tabs, and all three dashboards (thetimeDimensionsrisk). Do one pass inzh-CN
to confirm Card 11 — translations:en(default) andzh-CN, with a gate that fails on a missing key #32's bundle still resolves. Report what the console logged, not what you expect. - A changeset, or the
skip-changesetlabel —changeset-check.ymlgates every PR. - ⛔ Bump and migrate only. If 17.4 ships a capability that makes an existing workaround in this
repo obsolete — the seedlocaleaxis inc1d8f98vs this repo's ownOS_SEED_LOCALEswitch is
the known example — report it, do not adopt it here. That is a separate showcase card. - If a breaking change needs a product decision rather than a mechanical migration, stop and return
needs_decisionwith options and a recommendation. ⛔ Do not decide it in the diff.
Activity
zhuangjianguo commentedon Sep 9, 2026
Claim: PM loop round 1 (seat
repo:hotclm, taken this fire). Dispatched by the PM seat for its dev; the dev inherits this claim and posts no second one.Session:
session_01R3n3GGzobdegM4HUzah1iRBranch:
claude/issue-35-objectstack-17-4Worktree:
hotclm-issue-35(dedicated, offorigin/main@b9a2524)Domain:
repo:hotclm(single-lane repo — nodomain:*axis)File surface:
package.json·pnpm-lock.yaml· whatever the 17.4 migration provably forces undersrc/— plus, as the declared rider for #34,src/data/index.ts·src/data/plan-contracts.ts·scripts/demo.mjs(stop on breach; explain in the report)Container & model:
L,mode:subagent,model: default judgement tier—scripts/pm/dispatch-gates.mjsis objectstack-side tooling keyed to that repo's file surface and has no reading to give here, so the tier is the PM's explicit decision under the "M/L and any card carrying design judgement" rule, not a quoted--tierline.Clause-②: no — a dependency bump in a consumer app neither relaxes an acceptance set nor widens a published surface. This repo produces no
@objectstack/*contract; it consumes one.Thread-read: none (no comments on this card at claim time, 2026-09-09T13:5xZ)
Serial constraints cleared: none to clear. Zero open PRs in this repo, zero other
pm:dispatchedcards, and everyclaude/issue-*branch on the remote is merged intomain@b9a2524(git ls-remote --heads origin, 2026-09-09T13:50Z).fold-or-serial, answered explicitly: #34 and this card share the hot files
src/data/andscripts/demo.mjs. They are not folded — folding gate ① (same defect shape, same fix) fails: adependency migration and a prose-number correction are different work. #34 rides this card instead,
which is what #34's own body asks for ("ride the next card that touches these files"), and it is
carried as a declared increment in the file surface above rather than as an unannounced extra.
The reason it is the right moment and not merely a convenient one: #34's second half requires a
re-measurement on a current boot, and this card has to take that boot anyway.
Generated by Claude Code
claude commentedon Sep 9, 2026
os-dev-report
{ "issue": 35, "status": "done", "branch": "claude/issue-35-objectstack-17-4", "pr": "https://github.com/objectstack-ai/hotclm/pull/37", "premise_still_valid": true, "base": "b9a2524b2f5b3bc6a837c6ec26d6773f5cd5ee7a", "head": "ba4eb43", "summary": "Lockfile moved from 17.3.0 to 17.4.0 for all 57 resolved @objectstack packages; package.json byte-identical to main (the ^17.0.0 caret already admitted 17.4) and engines.protocol '^17' untouched. Zone 2 assumption 1 CONFIRMED, not falsified: a clean-database pnpm demo boot on 17.4 installs the same 820 rows with every readonly:true stamp present, field for field identical to the 17.3.0 baseline taken in the same worktree; b398ad2's strip is live for a non-system REST caller (a forged contract_number was dropped and the hook's ORD-2026-0017 stored) and the FLS-locked readonly families refuse with 403 PERMISSION_DENIED before the strip could be silent. Zone 2 assumption 2 re-verified and left alone: contract.object.ts:26 is still true on 17.4 (a non-system child insert moved the parent's readonly planned_amount 0 -> 12345). Browser-verified in Chromium after performing the README operator setup: 我的合同 shows rows for Business Requester 1, owner_id 120/120 populated at 43/43/34, all three dashboards render real numbers, all seven contract-detail tabs open, one zh-CN pass fully Chinese, zero HTTP 400-or-worse from any app endpoint. #34's two prose numbers were both re-measured on this run, so the PR carries Fixes #34.", "gates": [ { "command": "pnpm install --frozen-lockfile", "exit": 0, "evidence": "Lockfile is up to date, resolution step is skipped" }, { "command": "pnpm validate", "exit": 0, "evidence": "Validation passed (876ms); 26 author-time warnings (5 pre-existing + 21 new-in-17.4 field-no-consumers)" }, { "command": "pnpm lint", "exit": 0, "evidence": "21 warning(s), 5 suggestion(s) (844ms)" }, { "command": "pnpm typecheck", "exit": 0, "evidence": "tsc --noEmit, no diagnostics" }, { "command": "pnpm lint:i18n-gate", "exit": 0, "evidence": "COVERAGE: 0 missing keys across 2 locale(s); 1525 keys expected" } ], "gate_capture_method": "each command redirected to its own log file, $? read on the next line; no pipe between the command and the exit code. All four run through /home/user/objectstack/scripts/pm/os-verify-lock.sh (ACQUIRED after 0s, held 18s).", "boot_diff": { "method": "same worktree, clean .objectstack/data, pnpm demo, both read at seeder quiescence (3 consecutive stable row-count reads AND 20s of log silence), not at the ready banner", "rows_installed": { "main_17_3_0": 820, "branch_17_4_0": 820 }, "seed_result_line": { "main": "inserted:820 errored:120 referencesDropped:0", "branch": "inserted:820 errored:120 referencesDropped:0" }, "readonly_stamp_nulls_over_120_contracts": { "main": "contract_number 0, category 0, direction 0, route_legal_head 0, execution_formalities 0, submitted_at 60, signed_at 48, activated_at 48", "branch": "identical" }, "rollups": { "main": "planned_amount sum 47700500, 0 nulls", "branch": "identical" }, "degraded_capabilities": { "main": "absent", "branch": "absent" }, "no_such_table": { "main": "absent", "branch": "absent" }, "plugins_loaded": { "main": 38, "branch": 38 }, "onFieldsDropped_droppedFields_on_app_objects": { "main": "none", "branch": "none" }, "author_time_rules": { "main": "42 rules / 5 warnings", "branch": "44 rules / 26 warnings" }, "warnings_removed_by_17_4": "5 x [sql-driver] declared field 'id' asks for storage the platform's own 'id' column does not provide (5 -> 0)", "errors_added_by_17_4": "2, both on platform sys_* tables: [sql-driver] DATABASE_ERROR no such table _objectstack_sequences; ERROR Insert operation failed sys_oauth_resource UNIQUE constraint failed" }, "browser": { "engine": "/opt/pw-browsers/chromium-1194/chrome-linux/chrome (pre-installed, no playwright install)", "http_400_or_worse_from_app_endpoints": 0, "page_errors": 0, "my_contracts_as_requester": "rows present; grouped Status Active 16; AMD-2026-0004, ICA-2026-0001, LSE-2026-0005, SUP-2026-0017 visible", "owner_id": "120/120 populated, 3 distinct owners, 43/43/34 split (matches README)", "dashboards": "legal_workbench 6/12/10/1 + Approved This Month 2 with compareTo; executive_overview value-by-currency bars + 12/19 + routes 11/41/23/4; finance_overview overdue 2176250 + 12 instalments + top-10 table", "contract_detail_tabs": "7 of 7 clicked and rendered: Overview, Versions, Review & Deviations, Approvals, Obligations & Payments (6), Signing & Archive, Discussion", "zh_CN": "full Chinese console via Accept-Language zh-CN (预览版/合同/我发起的/法务工作台/管理层看板/财务看板), widget titles and descriptions included", "recurring_console_lines_not_caused_by_this_diff": [ "GET /favicon.ico -> 404 (/_console/favicon.ico and .svg both 200)", "GET /api/v1/auth/organization/list -> net::ERR_ABORTED with [AuthProvider] Failed to load organizations; the same route answers 200 to a direct call with the same cookie, so it is a Console startup race, and the route is new in plugin-auth 17.4" ] }, "files_changed": [ "pnpm-lock.yaml (+441 -440) — the whole bump", "scripts/demo.mjs (+7 -3) — #34 rider: the interval re-measured on 17.4, stated once", "src/data/index.ts (+1 -1) — #34 rider: 780 -> 820", "src/data/plan-contracts.ts (+8 -3) — #34 rider: second answer for the same interval deleted; the ordering claim the re-measurement falsified corrected without changing its conclusion" ], "files_not_touched": "package.json (byte-identical to main), objectstack.config.ts, pnpm-workspace.yaml, DESIGN.md, AGENTS.md, CLAUDE.md, LICENSE, CHANGELOG.md, docs/**, src/objects/**", "line_budget": "n/a — no skills/** or published-package surface in the diff. Hand-written diff is 16 added / 7 removed lines across 3 files; the remaining 441/440 is the generated lockfile.", "deviations": [ "No changeset and no skip-changeset label. The card's acceptance names changeset-check.yml; this repo has no such workflow (.github/workflows holds only ci.yml), no .changeset/ directory, no @changesets/cli dependency, and get_label reports 'skip-changeset' does not exist in objectstack-ai/hotclm. AGENTS.md is consistent: 'Release notes: None per PR. CHANGELOG.md is written at release time by the maintainer.' Creating the label would install a gate nothing reads.", "package.json ranges deliberately left at ^17.0.0. pnpm update rewrote them to ^17.4.0 and re-sorted the dependency keys; that was reverted and pnpm install re-run, so the lockfile records specifier ^17.0.0 / version 17.4.0 and pnpm install --frozen-lockfile exits 0.", "Browser verification required the README's operator setup first, which is more than 'pnpm dev --seed-admin': self-registration is closed on this environment (SELF_REGISTRATION_CLOSED, posture invite_only), so the three Business Requester accounts were created through the admin create-user endpoint, granted clm_requester via sys_user_permission_set, and pnpm demo re-run so its upserts hand owner_id over. The dev admin was put in the clm_admin position (sys_user_position.position, spelled by NAME) because without it GET /api/v1/meta/app/clm serves it navigation: []. Without that step 我的合同 is empty on 17.3 and 17.4 alike, which is documented product behaviour and not a regression.", "Two probe rows (one clm_contract, one clm_payment_plan) were written into the local scratch database by the b398ad2 measurement. Local .objectstack/data only; nothing committed." ], "assumptions_tested": { "zone2_1_readonly_insert_strip_breaks_the_seed": "FALSIFIED as a risk / PM assumption CONFIRMED — 820 rows and every stamp present on 17.4, identical to baseline", "zone2_2_contract_object_ts_26_may_now_be_false": "still TRUE on 17.4 (planned_amount 0 -> 12345 from a non-system child insert), so the comment was NOT edited", "zone2_3_absence_greps": "re-verified: 0 hits for timeout|ttl|idleTimeout|sessionTimeout in any .ts outside node_modules (control: 35 hits for 'readonly: true' under src/), 0 for record_picker, 'tree', ESignatureConfig, deadline", "zone2_4_820_rows": "measured 820 on both sides", "card_233222e_timeDimensions_dateRange": "no dateRange string is authored anywhere in this app; the only timeDimensions surface is legal.dashboard.ts:193's { $gte, $lte } + compareTo, which the executor lowers itself. That tile rendered its number and comparison; ANALYTICS_DATE_RANGE_UNRECOGNIZED appears in no boot log or browser session.", "card_8e0b297_positions_axis": "session payload now carries positions: [platform_admin, org_owner, clm_admin, everyone] and the app's permission model resolves off it correctly", "card_65846bc_unique_violation": "no app-object unique refusal occurred; the one that surfaced is a platform sys_oauth_resource row (see findings)" }, "mcp_calls": "5 — issue_read get #35, issue_read get_comments #35, issue_read get #34, issue_read get #26, get_label skip-changeset. The branch push, the PR creation and this comment went through git and repo-scoped REST, not MCP.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: 17.4 RETIRES a boot-noise workaround-adjacent condition — the five [sql-driver] \"declared field 'id' asks for storage the platform's own 'id' column does not provide\" warnings present on every 17.3.0 boot are gone on 17.4.0. Nothing to adopt; recorded so the next reader does not hunt for them. Carrier: this PR body.", "noted, not filed: the pnpm-workspace.yaml better-auth 1.7.2 override fixture is NOT retired by 17.4 — sign-in still passes with the pins in place and the block still names objectstack-ai/objectstack#16186 as its removal condition. Left untouched. Carrier: this PR body.", "noted, not filed: OS_SEED_LOCALE vs c1d8f98's seed locale axis — the card named this as the known 17.4 capability that obsoletes a workaround here. Not adopted (Zone 1 rule 3). No measurement was taken of the new axis, because taking one means authoring against it; the PM's showcase card is the right carrier.", "PLATFORM (objectstack), needs PM to file — new author-time rule field-no-consumers fires 21 times on this app (17.4 runs 44 author-time rules where 17.3 ran 42). Every verdict is 'carrier-only': clm_clause.standard_text/fallback_text, clm_contract_type.description/template_placeholders, clm_contract_version.notes, clm_deviation.deviation_text/justification, clm_obligation.evidence/notes, clm_party.legal_representative/address/contact_phone/bank_name/bank_account/risk_note/screened_at, clm_review.comments/internal_note, clm_signature.envelope_id/signers/notes. Gates stay green (warnings). Deciding per field between 'give it a consumer' and 'remove the declaration plus its translation carriers' is product work on 21 fields — a hotclm card of its own, not a rider on a dependency bump. I did not file it: it needs a product decision on 21 surfaces and the PM owns that queue.", "PLATFORM (objectstack), needs PM to file — 17.4 logs two new ERROR lines on platform sys_* tables on any boot after the first, on a clean single-tenant sqlite dev database: (1) [sql-driver] DATABASE_ERROR ... SELECT \"tenant_id\" FROM \"_objectstack_sequences\" WHERE 1 = 0 - no such table: _objectstack_sequences (a column-existence probe against a table that does not exist yet, logged at error level); (2) ERROR Insert operation failed {\"object\":\"sys_oauth_resource\", \"UNIQUE constraint failed: sys_oauth_resource.identifier\"} raised from createWithAutonumberResync (a platform bootstrap row re-inserted on a database that already has it; 17.3 logged nothing here, consistent with 65846bc surfacing refusals that used to be swallowed). Neither touches app data. AGENTS.md's rule for platform gaps is report, never patch, and filing them belongs in objectstack-ai/objectstack with its PLATFORM_GAPS append, which is outside this card's repo and file surface.", "PLATFORM (objectstack), needs PM to file — the single-boot seed path diverges from its own log. CLM_DEMO_SEED=1 objectstack dev --compile --ui --seed-admin on a clean database (NOT pnpm demo) installs 760 rows, not 820: all 60 clm_review rows are refused with 'Reviewer is required', which is exactly the failure scripts/demo.mjs's two-boot handover exists to prevent. The loader then logs 'Deferred reference UNRESOLVED after pass 2 - clm_contract.owner_id stays NULL' for all 120 contracts while the database ends up holding the dev admin's id in owner_id on all 120. pnpm demo never takes that path so the product is unaffected, but a log that says NULL over a column that is not NULL is the kind of claim this repo's discipline exists to catch. Side effect worth recording: this resolves #26's open contradiction 2 - 'the runtime claims ownerless seeded rows for the dev admin once that account is minted (measured)' is true on the single-boot ordering and false on the two-boot one, so the original annotation was measured on a path #21's handover removed.", "noted, not filed: src/data/keys.ts says an unresolvable owner_id name 'lands NULL, silently'. It is not silent on either version - 17.3.0 and 17.4.0 both log 120 SeedLoader ERROR lines plus 20 Seeder WARN lines for it. One word, in a file this PR already touches, but it is outside #34's declared two numbers and outside what the bump forced, so it was left alone rather than smuggled in." ] }Generated by Claude Code
zhuangjianguo commentedon Sep 9, 2026
Review: ACCEPT — PR #37, head
ba4eb43, CI green (2/2Validatecompleted/success). Merging under theAGENTS.mdmerge delegation. Readings below are mine, taken against GitHub and the tree, not read off the report.⛔ First: a premise in my own dispatch order was wrong, and the PR was right to refuse it
I put
changeset-check.ymland theskip-changesetlabel into #35's acceptance. No such gate exists in this repository. Verified myself onorigin/main:I imported that criterion from the PM lane charter at
references/lanes/hotcrm.md— which is the charter for hotcrm, a different repository. This is precisely the naming trap I recorded in the seat register (#36) about 40 minutes before writing the dispatch, and it caught me in the same fire.AGENTS.mdhere is the consistent authority: "Release notes: None per PR.CHANGELOG.mdis written at release time by the maintainer."⇒ The PR carries no changeset and no label, deliberately and correctly. Creating the label would have installed a gate nothing reads. Recorded as my error, not as the PR's deviation.
Verification I performed independently
git diff --name-only origin/main...FETCH_HEAD(⛔ notget_files, which exceeded the token cap on the lockfile, and ⛔ not the report's own list)pnpm-lock.yaml·scripts/demo.mjs·src/data/index.ts·src/data/plan-contracts.tsDESIGN.md/AGENTS.md/CLAUDE.md/LICENSE/CHANGELOG.md/docs/design/package.jsonuntouchedpackage.json+ whatever the migration forces undersrc/+ the three rider filesget_check_runs, after re-reading the PR object for its headValidate, bothcompleted/success, both onba4eb43a8ff…= the PR object's headThe front-loaded risk was answered better than I asked
I asked whether
b398ad2would strip the ~20readonly: truestamps out of the seed and reproduce #26. The PR did not answer it by counting 820 rows — it answered it three ways, and the third is the one I did not think to ask for:contract_number: 'FORGED-0001'got201with the hook'sORD-2026-0017stored instead, read back out of SQLite rather than from the response body.submitted_at/approved_at/route_*answers403 PERMISSION_DENIED, and so does aPATCH. §04's field-level security sits in front of the strip for every family whose forging would matter.(2) and (3) together are the real finding: the mechanism is armed, and this app's own FLS is what makes it non-silent. "820 rows, therefore fine" would have been a weaker answer to the same question.
contract.object.ts:26re-verified and left alone — a non-system child insert moved the parent'sreadonlyplanned_amount0 → 12345, so the sentence is still true on 17.4. Not editing a comment that turned out to be correct is the right call; I had flagged it as suspect and it was not.Rider #34 — spot-checked by reading the diff, not the summary
src/data/index.ts:780→820. One word, as specified.scripts/demo.mjs: re-measured on 17.4 with both timestamps stated (14:26:53.833Z→14:26:57.396Z, 3.563s) and the sentence "it is measured here and nowhere else, so there is one place to be wrong" — which is the shape Two numbers in the repo's own prose are wrong or contradict each other (780 vs 820 rows; 0.8s vs ~1.8s) #34 asked for.src/data/plan-contracts.ts: the second answer is gone, and this is the part worth calling out. Two numbers in the repo's own prose are wrong or contradict each other (780 vs 820 rows; 0.8s vs ~1.8s) #34 warned "the interval may no longer mean what it did — re-measure the thing the comment is actually claiming, not just the two timestamps." The old comment's premise ("the seed loader runs BEFORE the first user account exists") is false on the pathpnpm demoactually takes, because Seed data:demo-en(default) anddemo-zh(card 08, M2) #21's handover mints the admin first. The rewrite keeps the conclusion, replaces the argument with the one that is actually true (no owner exists because §10 leaves the three requesters to the operator), and citesdemo.mjsfor the ordering instead of restating it. That is the failure mode this repo has been bitten by four times, corrected rather than reproduced.Fixes #34is therefore earned under the card's own condition.Accepted with findings, not silently
AGENTS.mdthe maintainer should see, which I am not deciding.AGENTS.mdsays a boot loggingno such tableis "not a passing boot", and 17.4 adds exactly that at ERROR level —no such table: _objectstack_sequences, a column-existence probe against a table that does not exist yet. It is platform-internal, touches no app data, andAGENTS.md's own rule for platform gaps is report, never patch, so the app cannot fix it. Net boot-noise change on 17.4: −5 warnings (the[sql-driver] declared field 'id'family is gone), +2 platform ERROR lines, +21 author-time warnings. Capability is not degraded —degraded capabilitiesabsent, plugins 38 = 38, every app surface verified in the browser. I am accepting on that basis and routing the two ERROR lines upstream, but the judgement about sitting on a platform version that logs errors on boot is the maintainer's, not mine.field-no-consumerswarnings are a real finding about this showcase, not noise. 17.4 runs 44 author-time rules where 17.3 ran 42, and one of them reports 21 fields declared here that nothing reads or displays —clm_party.address/bank_account/contact_phone,clm_signature.envelope_id/signers,clm_review.internal_note, and more. In an exhibit, declared-equals-enforced matters double: a field a translation bundle names and nothing renders teaches every AI that copies this repo to declare inert metadata. Correctly refused as a rider on a dependency bump — deciding 21 fields between "give it a consumer" and "remove the declaration and its translation carriers" is product work. Filing it as its own card.The four
out_of_scope_findingsmarked needs PM to file are mine now; filed below and linked from here.Landing
AGENTS.mdmerge delegation (maintainer 2026-09-07, verbatim: 「你自己派发自己合并」): CI green on the head ✓ · ACCEPT recorded on the issue ✓ (this comment) · diff touches no governed surface ✓ (verified above, not asserted) · not a second REWORK round ✓. All four hold ⇒ ready, then squash-merge. This repo runs no merge queue (ci.ymlonly), so the direct squashAGENTS.mdspecifies is the sanctioned path here.Generated by Claude Code