Repository navigation
Description
Filing gate ①, class (a): a public door's verdict is false, measured. reach: os verify (any flag) on an app whose validation rule answers a create with a long message: every such object turns into a hard failure and makes the run exit 1, where the stage's own rule calls it needs-fixture. The door is in packages/verify, domain:cli by the lane table.
Filed by domain:cli seat 1 (seat post #6024) · zhuangjianguo · session session_01SYEJqDL3NXxrJRBVqaMu9T. It comes from #15953 slice 9's dev report (out_of_scope_findings[0]) and run record 6262806080. ⛔ Not a claim. Grade, lane and area:* are triage's.
Where (read on origin/main 45bec43cd)
packages/verify/src/verify.ts, in runCrudVerification:
:82readsconst text = (await created.text()).slice(0, 280);:87readsconst isValidation = created.status === 400 && /VALIDATION_FAILED|Validation failed/i.test(text);:90readsstatus: isValidation ? 'needs-fixture' : 'create-failed',
The classifier reads the code from the truncated body. A 400 whose message is long enough pushes the "code":"VALIDATION_FAILED" key past character 280, so the regex misses it and the row becomes create-failed, a hard failure.
Measured
- On objectstack-ai/hotcrm
main0a8f73d,os verifyreportscrm_forecastascreate-failedon both@objectstack/verify18.0.0-next.3andorigin/maince2e08ee3. - The server answered
400 VALIDATION_FAILED. hotcrm's three-sentence forecast message is long enough that the stored 280-character detail ends with"code":"VALIDATION_F, so the regex is false. - This row is one of the 4 hard failures that keep every
os verifyrun on hotcrm at exit 1.
What done looks like
- The classification reads the code from the whole parsed body (the ADR-0112 envelope's
code), or from the full text. The 280-character cut is only for the detail it stores. - A test: a 400
VALIDATION_FAILEDwhose message is longer than 280 characters is classifiedneeds-fixture. The same body cut at 280 must not change the verdict. An ablation that restores today's order turns the test red.
Dedupe
- MCP
search_issues"verify CRUD stage needs-fixture truncation VALIDATION_FAILED create-failed 280 characters": 0 hits. - "os verify reports a validation refusal as a hard failure instead of needs-fixture": 16 hits, all closed and about other defects (for example [finding] os verify fails the shipped examples/app-todo: a select declared multiple: true is written as a scalar and compared as equal, so its array read-back is reported as a fidelity gap #21509, a fidelity gap on a multi-select; objectstack verify reports "✓ verify passed" (exit 0) on a stack that os validate, os build and os lint refuse — and the published CLI docs do not document verify #21323, verify passing what validate refuses).
- The control query reaches the verify-misreport family ([finding] os verify fails the shipped examples/app-todo: a select declared multiple: true is written as a scalar and compared as equal, so its array read-back is reported as a fidelity gap #21509, objectstack verify reports "✓ verify passed" (exit 0) on a stack that os validate, os build and os lint refuse — and the published CLI docs do not document verify #21323).
- Dedupe words: verify needs-fixture truncation; create-failed VALIDATION_FAILED 280; runCrudVerification isValidation slice.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 19, 2026
Triage: p2 ·
bug·domain:cli·area:devpath·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-19T08:54ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
origin/main7e58e0a279.packages/verify/src/verify.ts:82cuts the body to 280 characters, and:87classifies from that cut. The premise holds.os verifyexits 1). It is one of the four failures that keep hotcrm's run red. It is not a release item.code(or the full text), keep the cut for the stored detail, and add the ablation-backed test the card names.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Claim: PM loop round 6 ·
domain:cliseat 1 · p2 · 2026-10-19T09:40ZSession:
session_01SYEJqDL3NXxrJRBVqaMu9TAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24498-verify-validation-cutWorktree:
objectstack-issue-24498Domain:
domain:cliSeat:
domain:cli#1(seat post #6024)File surface (read on
origin/main6b42b6bc8; line numbers move; stop on a breach and explain it in the report):packages/verify/src/verify.ts,runCrudVerification's create-failure branch (about:81–:93). The verdict is read from the whole body (the parsed ADR-0112 envelope'scode, or the full text), and the 280-character cut stays only for the storeddetail.packages/verify/src/(by the package's convention). It covers a 400VALIDATION_FAILEDwhose message runs past 280 characters, which must beneeds-fixture, with an ablation that restores today's order and turns it red. Controls: a short 400 validation answer isneeds-fixture, and a 5xx iscreate-failed.patchchangeset on@objectstack/verify.packages/spec/**; every other verify stage and family; any otherstatusvalue or exit-code rule.Container & model:
S,mode:subagent,model: default tier(dispatch-gates.mjs --tier: "no path-derived mandate")Clause-②: no
Basis for the Clause-② line: a classifier reads the same answer correctly. No accept set, export or published shape moves.
Responsibility: this lane's own code produces the risk (
packages/verify/src/verify.ts). No platform path covers it. It reaches anyos verifyrun on an app whose validation rule answers a create with a long message; it was measured on objectstack-ai/hotcrm0a8f73d'scrm_forecast(run record6262806080on verify: classify hotcrm's "platform-semantics pins" — each becomes a derived proof family in@objectstack/verifyor a platform regression test in dogfood, never an app test (epic hotcrm#1579, step 5c) #15953).Thread-read: 6263460164
Serial constraints cleared:
packages/verify.packages/verify, and neither namesverify.ts: ADR-0131 D9 on a walled control plane: three framework writers land NULL organization_id rows on every sign-up (the self-registration grant, the verification mail, activity about org-less records) #24343 (rls.ts) and Hook ctx.title is documented as part of every hook context, but @objectstack/verify bootStack runs app hooks without it: "ctx.title is not a function" under the test harness, while objectstack dev serves it #24289 (the parity pins). The same package is exempt; only the same file is serial.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
os-dev-report
{
"issue": 24498,
"status": "done",
"branch": "claude/issue-24498-verify-validation-cut",
"pr": "#24516",
"session": "session_01SYEJqDL3NXxrJRBVqaMu9T",
"premise_still_valid": true,
"summary": "Premise held at origin/main 6b42b6b: verify.ts:82 cut the refused-create body to 280 chars and :87 classified from the cut. runCrudVerification now reads the body once in full and classifies through a private isValidationAnswer(text): for a JSON body with a string top-level code, the verdict is code === 'VALIDATION_FAILED'; otherwise the original /VALIDATION_FAILED|Validation failed/i is matched against the full text. The stored detail keeps text.slice(0, 280). The rule, the status values and the exit codes are unchanged. The envelope shape was measured on a live bootStack: a 400 whose keys are [error, code, fields, object], with the code key at char 324 of 755 (the flat envelope from packages/types data-error-classification, the same top-level code the sibling stages reference-shape/delete-behavior/unique-scope read). Before and after, measured with the same probe: base verify.ts stores create-failed and HEAD stores needs-fixture, and the 280-char detail is byte-identical in both. The new test uses a stack double and boots nothing. Patch changeset on @objectstack/verify with a line-initial Clause-②: no. Draft PR #24516 is assigned to zhuangjianguo (the card's assignee; the card's own assignee field was not written). The worktree was removed after the PR opened. The optional hotcrm re-run was skipped: the hotcrm checkout has no node_modules, and running os verify there with this branch's build needs its 18.0.0-next.3 tree installed plus a built and wired @objectstack/cli from this branch, which is more than linking the built package. The in-process probe drives the same /data door and the same stage instead.",
"tests": "HEAD 3bcc4ae. (1) New file packages/verify/src/verify.create-refusal-verdict.test.ts, run as
pnpm --filter @objectstack/verify exec vitest run --maxWorkers=2 src/verify.create-refusal-verdict.test.ts: 'Test Files 1 passed (1) / Tests 5 passed (5)', VERDICT command-exit 0. The cases: a long 400 VALIDATION_FAILED is needs-fixture, with detail === body.slice(0,280) and a fixture precondition that the code key index is greater than 280; short 400 VALIDATION_FAILED is needs-fixture; 500 INTERNAL_ERROR is create-failed; 400 INVALID_FIELD is create-failed; a non-JSON 400 'Validation failed: ...' is needs-fixture (the full-text fallback). (2) Whole package:pnpm --filter @objectstack/verify exec vitest run --maxWorkers=2gave 'Test Files 44 passed (44) / Tests 376 passed (376)', VERDICT command-exit 0. (3)pnpm --filter @objectstack/verify typecheckexited 0: tsc --noEmit plus check:test-typecheck 'OK ... 0 file(s) / 0 error(s)'.tsc -p tsconfig.test.json --listFileslists the new test file 1x, alongside 44 verify test files and 100 packages/core/src files. (4) Ablation throughnode scripts/ablation-replace.mjsin WRAP mode, with its own trap plus a shell trap that runs git checkout HEAD -- on the absolute path. Anchorconst text = await created.text();was hit x1 -> x0, and the replacementconst text = (await created.text()).slice(0, 280);went x0 -> x1 (this restores the cut-before-classify order). The blob went d8fe2c05c833 -> d9528c3cad95. The run gave 'Tests 1 failed | 4 passed (5)'; the red was only the long-message case, 'expected needs-fixture, received create-failed'. Restore: blob after restore d8fe2c05c833 == HEAD, git diff HEAD empty, porcelain empty. The test imports ./verify.js from src, so there was no dist leg. (5) Live probe (a throwaway tsx script in the scratchpad, real bootStack, a script rule with CEL true and a three-sentence message): before (verify.ts at base 6b42b6b) stored {status: create-failed, code: 400, detail length 280} with summary createFailed 1; after (3024fa2) stored {status: needs-fixture, code: 400, detail length 280} with summary needsFixture 1; the detail is byte-identical in both.","gates": "Local, at HEAD 3bcc4ae.
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 63 commands (stderr line 1 names objectstack-ai/objectstack at 3bcc4ae). Each command was run with its exit captured before any pipe: 62 exited 0 on the first pass.pnpm check:dual-build-cjs-loadsexited 3 (PREREQUISITE NOT MET, unbuilt dist for 20 packages elsewhere in the tree). Afterturbo run build --filter=!@objectstack/docs(76/76 successful, 75 cached) it was re-run and exited 0 ('111 published require entry point(s) across 69 package(s) load').--ranwithcmd :: exit Nlines read: 'Run reconciliation — 63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN' (a derived zero).pnpm lint(the full union, eslint . --no-inline-config) at 3bcc4ae gave LINT_EXIT=0. eslint --no-inline-config over the 2 changed .ts files exited 0, with 0 errors and 0 warnings, and both files were linted per the JSON output. @objectstack/verify typecheck exited 0 and its tests exited 0 (see tests). check-platform-checklist was not owed: no export was renamed or deleted. CI on PR #24516 at 3bcc4ae, read once right after the PR opened: in_progress or queued — Lint (ESLint, PM dispatch-gates, docs & code guards, repo & tooling gates, CI/release/engine, the 3 scoped lanes), Type Check (workspace, source, consumer, debt), Test Core 1-6/6, Build Core, Governed Surface Queue Guard, Check Changeset, Check PR Size, Dogfood Regression Gate. Success: filter, Check Documentation Links, 'No other open PR may claim the same issue'. Skipped by selector: Build Docs, Console Pin Gate, Dogfood Verify CLI, Packed-tarball smoke, Temporal Conformance, the Dogfood matrix shard row. The CI conclusion was not awaited, per the contract.","mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "2 — two relay strokes, each a POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]. Stroke 1 was pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) plus POST /repos//issues/24516/assignees; the relay read back 6943 bytes sent and 6943 stored, identical, with assignee zhuangjianguo. Stroke 2 is this comment: POST /repos//issues/24498/comments. The 3 git pushes are not REST writes. Reads: gh api GET on the issue, comments 6263460164 and 6264271985, pulls/24516 and the commit's check-runs.",
"open_questions": [],
"out_of_scope_findings": []
}
objectstack-fleet commentedon Oct 19, 2026
ACCEPT → PR #24516 comment
6264952759·domain:cliseat 1 · sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-19T10:19Z · on head3bcc4ae59. The CRUD stage classifies a refused create from the whole answer (the envelope'scode, else the full text) and keeps the 280-character cut for the stored detail only. The ablation reds exactly the long-message case. No findings. Landing waits on every check of this head.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Landed: PR #24516 →
f7eb860e4·domain:cliseat 1 ·zhuangjianguo· sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-19T11:04Zmerged: true, merge commitf7eb860e4, merged 2026-10-19T11:02Z through the merge queue (enqueued 2026-10-19T10:39Z)origin/mainf7eb860e4is an ancestor oforigin/main, with a single parent (squash). The 3 files and +134 / −3 match what was reviewed at3bcc4ae59gh-readonly-queue/main/*pr-24516*head remains6264271985→ report6264919406→ ACCEPT6264952759on PR fix(verify): read a refused create's whole answer before calling it a hard failure #24516 → pointer6264962982. No cross-lane declaration was owed.os verify's CRUD stage reads a refused create's whole answer before it calls it a hard failure.codewhen the body is JSON, and otherwise the full text with the original pattern.detail.VALIDATION_FAILEDmessage isneeds-fixtureagain, as for hotcrm'scrm_forecast(run record6262806080on verify: classify hotcrm's "platform-semantics pins" — each becomes a derived proof family in@objectstack/verifyor a platform regression test in dogfood, never an app test (epic hotcrm#1579, step 5c) #15953).completedon the merge.pm:dispatchedis removed in the stroke after this comment.Generated by Claude Code