Repository navigation
content(blog): what os verify proves in two stages on ObjectStack 17.7.0 (slot 2026-10-24) - #281
Open
objectstack-fleet[bot] wants to merge 1 commit into
Open
objectstack-fleet[bot] wants to merge 1 commit into
objectstack-fleet[bot] wants to merge 1 commit into
Conversation
New post, slot Sat 2026-10-24, in en, zh-Hans, zh-Hant (generated), ja, ko, de, es and fr, with a cover and a stage diagram in the English and Chinese sets. Re-scoped to the published @objectstack/cli 17.7.0: two stages, one count, the --rls coverage rule; every transcript is a real run. Back-link from how-to-review-ai-generated-app-changes (en), its `updated` set to the slot date. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FeA1nwBz1ohH65dvffUGKr
This was referenced Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #271
Slot: Sat 2026-10-24, on the shared calendar on #267. Merge on the slot day only.
Seat review. The seat read the post and checked the pipeline diagram at 1366 and the zh-Hans fold at 1440.
os verifyProves in Two Stages on 17.7.0 #271. Nothing about 18.0 appears.how-to-review-ai-generated-app-changes. If both PRs write itsupdated:line, the later slot's date wins when the second one merges.ACCEPT.
Slate 1 post, slot Sat 2026-10-24. Staged on
lin/issue-271fromorigin/main(3c5b6c6), one commit,3e45b04. Not pushed by the dev; the seat pushes the branch and merges on the slot day.Re-scope: what the card asked for does not exist on 17.7.0
The card's title promised "the Six Invariants It Only Proves on Request", its ownable concept was the three verdicts proven / inconclusive / excluded, and proof artifact #3 was a deliberately failing
--delete-behaviorsrun. None of that is on the published@objectstack/cli17.7.0, whichnpm create objectstack@latestinstalls (npm dist-tags:latest17.7.0,next18.0.0-next.2). Evidence, all from the published binary in a fresh scaffold:Source-side: tag
@objectstack/cli@17.7.0packages/cli/src/commands/verify.ts:95-108declares exactlyapp,rls,multi-tenant,json. The five other probes (--reference-shapes,--delete-behaviors,--unique-scopes,--parent-write-reach,--dashboard-windows) sit inpackages/cli/CHANGELOG.mdatorigin/maininside the## 18.0.0-next.0section (entries at :937, :970, :1002, :1040, :1065; section bounds :871 and :2330). The word "inconclusive" appears 0 times in the 17.7.0content/docs/deployment/cli.mdxand 3 times atorigin/main. Seat decision: option A, re-scope to what 17.7.0 ships, keep the slot, no mention of unreleased material.What this PR adds
New post
content/blog/what-os-verify-proves-in-two-stages/in en, zh-Hans, zh-Hant (generated bypnpm gen:zh-hant), ja, ko, de, es and fr;date: 2026-10-24, noupdated,topic: app-building,audience: developer. Title: How Do You Test an AI-Written App Without Writing Tests? What os verify Proves in Two Stages on ObjectStack 17.7.0 (query-shaped, one number: two stages; the version named in the title, the lede and the footer).✓ verify passedat exit 0 while validate/build/lint refused it — named in the post as a false green. Second beat, not the title: the--rlscoverage rule, reported, never dropped (positionCoverage.notRunis a term ofhardFailures;member-visibleprobes stay in the report asunproven).scratchpad/issue-271/proof-a|b|c/):npm create objectstack@latest verify-demo(full command, skills installed;Create ObjectStack v17.7.0), thennpx os verify --json > report.json→ exit 0,crud.summaryobjects 1 / verified 1 /checked: 2,hardFailures: 0; 317 stderr lines, stdout exactly one JSON document (JSON.parseread it whole). Text face:Running author-time rules (49)… ✓ Author-time rules passed (49 rules).examples/app-crmat tag@objectstack/cli@17.7.0, run standalone against the published 17.7.0 packages (workspace:*pinned to17.7.0),npx os verify --rls --json→ exit 0,hardFailures: 0; crud: 4 verified, 1needs-fixture(crm_opportunity, the app's own validation rules refused the derived record: "Discount cannot exceed 40% …; Close Date must be today or a future date"), 1skipped(crm_opportunity_line_item, required relation); rls: base probe 6rls-consistent(GET 404/PATCH 404, row unchanged),positionCoveragedeclared = ran =[sales_rep, sales_manager, finance_approver],notRun: [],totalsobjects 24 / proven 6 / unproven 18 / memberVisible 18 / holes 0; text face says per position "this persona proved NOTHING — every object was member-visible".Field.lookup('verify_demo_project', …)added to the scaffold's one object →npx os verifyexit 1,✗ Author-time rules failed (1 issue) — the runtime stage did not run, ruleobject-reference-unknown;--json→ exit 1,{"error": …, "errors": [{"severity": "error", "rule": "object-reference-unknown", "where": …, "path": "objects[0].fields.project.reference", "message": …, "hint": …}]}; 0 stderr lines (nothing booted);os validateprints the same finding. Field restored byte-identical afterwards.os validate(the reference's own list),needs-fixture/skippedare not failures,--rlsproves one invariant where a scenario exists (18 of 24 probes proved nothing on the CRM, and the run is green), opt-in and single-tenant by default, not the human verify of the getting-started loop.T4_STANDALONEverbatim fromsrc/lib/positioning.ts, per locale. No pricing, signup URL or edition naming. No token figures. No competitor claims. CTA: point your agent at ObjectStack and let it run the done-bar; the README's ownos verifyline.how-to-point-your-agent-at-objectstack,how-to-review-ai-generated-app-changes(twice: the declared → enforceable → correct ladder, and pass 2),how-to-build-a-crm-with-an-ai-agent, glossarydeclared-vs-enforced(/zh-Hans/glossary/…in zh-Hans, rewritten to/zh-Hant/by the generator;/en/…elsewhere).cover-en.svg/cover.svg(1200×675),two-stages-en.svg/two-stages.svg(1200×700). The diagram adds what the cover lacks: the per-object and per-probe status lists, which statuses count and which are only reported, and the six-termhardFailuressum. ja/ko/de/es/fr use the English set, zh-Hans/zh-Hant the Chinese pair. Explicit light backgrounds and text fills, so the images read the same in dark mode.Updated post
content/blog/how-to-review-ai-generated-app-changes/index.mdx(en only; it has no other locale): one back-link paragraph after its "What this review still cannot catch" list, pointing the runtime half at the new post;updated: 2026-10-15T10:00:00+08:00→2026-10-24T10:00:00+08:00(the slot date, as the card rules).dateuntouched.Claims and their sources
os verifygreen means the author-time rules pass and the app behaves at runtime. It runs two stages, in order, and the second starts only when the first passes."@objectstack/cli@17.7.0,content/docs/deployment/cli.mdx:1876-1878os validateruns, over the stack prepared the wayos validateprepares it; advisories never fail it; "thedefineStackprovenance refusal …, the package-docs lint, the capability-provider check, the picklist-reference and view-container-name checks and--strictstayos validate's, so run it too"cli.mdx:1886-1898at the tag--rls, a second fresh boot proves the cross-owner invariant — a member must not write what it cannot read — for a probe persona and for one persona per declared position";--multi-tenantboots org-scopedcli.mdx:1899-1905at the tagcli.mdx:1916-1917at the tag--json: stdout carries exactly one JSON document; log lines go to stderr; the report carriesapp,config,multiTenant,crud,rls(with--rls) andhardFailures; refused →{ error, errors[] }cli.mdx:1919-1934at the taghardFailuressum (quoted as code)packages/cli/src/commands/verify.ts:279-285at the tag; emitted at:291notRuncountsverify.ts:251-262at the tag (declaredPositionNames(config),positionFailures);packages/verify/src/rls.ts:212-223("REPORTED, never dropped")RlsStatusvalues and their proven / not-proven readingpackages/verify/src/rls.ts:147-157at the tag✓ verify passedat exit 0, whileos validate,os buildandos lintall refused it. The documented done-bar … was green on a stack the build refuses to ship." (blockquote) and the two-stage fix f397608 / #21323packages/cli/CHANGELOG.mdat the tag,:29and:37packages/cli/CHANGELOG.mdat the tag,:250-254os verify # Boot the app in-process and verify it over real HTTPREADME.md:261at the tag (the card cites:302atorigin/main)verifyscript, hencenpx os verifypackages/create-objectstack/src/templates/blank/package.json:10-17at the tagcontent/docs/getting-started/build-with-claude-code.mdx:30at the tagcrm_sales_usergrants read on every CRM object; bound to the three positionsexamples/app-crm/src/security/sales-positions.ts:10-37, 45-66andbind-position-sets.ts:9, 27at the tag;objectstack.config.ts:100sharingModel: 'public_read_write', the line itemcontrolled_by_parentexamples/app-crm/src/objects/{account,activity,contact,lead,opportunity}.object.tsandopportunity-line-item.object.ts:21at the tagsrc/lib/positioning.ts(T4_STANDALONE, and each locale'st4)checked: 2, every number in the crud and rls blocks, theneeds-fixturerefusal text, the "proved NOTHING" linesscratchpad/issue-271/proof-a/{verify-text.out,report.json,report.stderr},proof-b/{report-rls.json,report-rls.stderr,verify-rls-text.out},proof-c/{verify-text.out,report.json,report.stderr,validate.out,note.object.ts.orig,note.object.ts.mutated},scaffold-full.log,version.txt,help.txt,delete-behaviors.stderr,reference-shapes.outThe runs, in order
npm create objectstack@latest verify-demo(full, with the skills bundle; an earlier scaffold made with--skip-skillswas kept as a second copy for the failing run — same packages, 17.7.0).npx os verifyandnpx os verify --json > report.json: exit 0 both.git archiveofexamples/app-crmat the tag into a standalone directory;workspace:*→17.7.0(andtypescript ^6.0.3→^5.9.3, unused byos verify);pnpm install(build scripts ignored by pnpm 10's default; the run boots onsqlite-wasm);npx os verify --rls --jsonand the text face: exit 0 both, 799 stderr lines.Field.lookup('verify_demo_project', …)added (anchor hit, lookup count 0 → 1, diff saved);npx os verifyexit 1,--jsonexit 1 with 0 stderr lines;npx os validateexit 1 with the same finding; file restored andcmpbyte-identical.Gates, on the tree committed as
3e45b04(check and build throughscripts/pm/os-verify-lock.sh, slotwww-271)pnpm content:lint✓ content lint passed (355 files, 46 glossary terms checked)pnpm content:lint --publishedpnpm svg:lintsvg-text-fit: OK — … (122 SVGs, 2643 text boxes, 183 filtered elements, tolerance 2px, 1 allowlisted)pnpm checkResult (160 files): 0 errors, 0 warnings, 0 hintspnpm build✓ zh-Hant: generated 48, kept 0 hand-maintained, 8 with body links pointed at /zh-Hant/·svg-text-fit: OK·[build] 920 page(s) built in 59.01s·✓ content lint --dist passed (494 built blog pages checked)· CJK line breaks (920 pages, 348 zh/ja, 0 breaks), quotation marks (12856 curly marks, 0 wrong) and links (99458 internal links) passed · tree clean afterwardspnpm seo:smokeSEO smoke test passed (910 HTML pages checked; 594 sitemap URLs against 316 noindexed pages; 5679 canonical/hreflang annotations; 17411 prose blocks language-checked; 99448 internal links redirect-checked)Lock:
VERDICT command-exit 0 · held the lock 94s · waited 42s(final run). One earlier build was red and fixed: the ko page rendered 4 literal**because two bold spans wrapping inline code sat against a Hangul particle; a space-separated noun was put after each.Advisories, verbatim and expected:
Date is in the future: Sat Oct 24 2026×8;Updated is in the future: 2026-10-24on the back-linked post; title widths (en 114 chars; zh-Hans 58 chars / 82 columns; ja 69 / 104; ko 74 / 105; de 129; es 119; fr 123) against the 60-column snippet note; descriptions all ≤ 230 chars (en 229, zh-Hans 113, ja 136, ko 168, de 227, es 229, fr 229).Browser check (final build served by
astro previewon 127.0.0.1:49141, Playwright Chromium at/opt/pw-browsers/chromium)scratchpad/issue-271/shots.mjs→scratchpad/www/shots-271/(101 files,results.json): 219 of 219 assertions pass. The article in en and zh-Hans at 1366×625, 1440×750, 1512×830, 1920×945, 390×844 and 360×800, light and dark (prefers-color-scheme), lazy images scrolled into view first: HTTP 200,scrollWidthequal to the viewport, no element past the viewport outside a scroll container, cover renders, every body image loads, no repeated image. The back-linked post in en at 1440 and 390, light and dark, carries the new link and renders "Updated Oct 24, 2026". The en and zh-Hans blog lists at 1440 and 390 link the new post (it is the first card under Latest). Element crops of the two tables, both images and four code blocks at 360 and 1366 in en and zh-Hans. The four served SVGs opened at native size in light and dark: lowest text contrast 5.06:1 on the covers ("THE COUNT THE EXIT CODE READS" / "退出码读的那个计数") and 4.73:1 on the diagrams (the amberneeds-fixturelabel on the pale status box); 0 text nodes on a dark fill.Looked at: the folds in en at 1366 light, 390 dark and 1920 dark; zh-Hans at 1440 light and 360 dark; the zh-Hans full page at 1366 dark; the phone table (horizontal scroll container, as the site gives every post) and the diagram at phone width; a code block at 1366; both covers and both diagrams at native size; the blog list; the updated post's header line.
Two visual defects the check found, both fixed before the commit: the grey small text (
#657872) read 4.24:1 inside the pink "refused" box and 4.29:1 on the green count bar, and by arithmetic 4.42:1 on the pale status boxes —.smalland.footare now#55685fin all four SVGs; and the two advisory lines at the bottom of the diagram's stage-1 box sat on its border and were lifted 8 px.Deviations and notes
--rlsposition personas proved nothing (every object member-visible); the post reports it as the second beat rather than hiding it, with the reason sourced to the permission set and the objects' sharing declarations.workspace:*pinned to17.7.0; nothing else in the example was edited.how-to-reviewis 93). Advisory only.Claude <noreply@anthropic.com>); the message ends with the two trailer lines the dispatch required. Not pushed; no GitHub comment, label or PR written by the dev.Acceptance notes (observations, not filed)
better-sqlite3's build script by default and warns about an unmet peer;os verifyboots onsqlite-wasmand is unaffected.needs-fixtureand counts as neither failure nor coverage. Documented behaviour at the tag, stated in the post.Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01FeA1nwBz1ohH65dvffUGKr