Skip to content

docs(readme): a 30-second demo GIF opens the README, rendered from a real showcase run - #22241

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-22232-readme-demo-gif
Oct 8, 2026
Merged

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-22232-readme-demo-gif

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #22232
Clause-②: no

Part A of the card: the README now opens on a thirty-second GIF recorded from a really running app, rendered by a committed script. Part B (repository topics and the About line) is the maintainer's click on the repository settings page and is not in this PR.

What changed

File Change
docs/screenshots/readme-demo.gif new: 1200 x 675, 43 frames, 29.88 s, loops forever, 497,614 bytes
docs/screenshots/render-readme-demo.mjs new: the generator (boots the app, makes the calls, screenshots the Console, renders the frames, assembles the GIF)
README.md top only: the GIF replaces the embedded cover image under the chip row, a one-line caption names the three beats, the "Watch: ObjectStack in 90 Seconds" link stays as text under it. docs/screenshots/hero-cover-dark.png is byte-untouched (the docs site's og:image). The architecture diagram and everything below it are unchanged.

No packages/**, apps/docs, content/**, CHANGELOG.md or package.json change; nothing publishes.

The recording

Example and object: examples/app-showcase, object showcase_team (three fields, so the whole typed definition fits one frame without scrolling).

  1. One definition, and the app runs. The Team object exactly as examples/app-showcase/src/data/objects/team.object.ts declares it (comment lines omitted; the frame says so), then pnpm dev:showcase -- --fresh -p PORT booting it on a throwaway database, then the Console's Team list (2 rows).
  2. An agent creates a record over MCP. A JSON-RPC tools/call of create_record against the running app's /api/v1/mcp, sent with the dev admin's API key; the real response; then the Console list with the new "Data Guild" row (3 rows) and its record page reading "Created by Dev Admin".
  3. A read-only identity is refused. The byte-identical call sent with the Auditor persona's API key; the real refusal; then the Console list, unchanged (3 rows).

Closing frame: "The ontology is the software." and the four chips Executable · AI-writable · Agent-operable · You own it.

Measured in the run that rendered the committed GIF (port 39497): showcase_team went 2 → 3 on the admin's call and stayed 3 on the refused call (read back over REST after each call).

  • Admin's call: 200, record QZu-Fcgx29Po-Sfn "Data Guild", created_by = the admin's user id.
  • Read-only call, the real response bytes:
{"result":{"content":[{"type":"text","text":"You do not have permission to perform this action. Contact your administrator if you need access."}],"isError":true},"jsonrpc":"2.0","id":1}

Keys and identities

  • Both keys are minted through the documented POST /api/v1/keys (content/docs/ai/connect-mcp.mdx, "Headless: API keys"), each from a session opened with POST /api/v1/auth/sign-in/email.
  • Writer: the dev admin that --fresh seeds (admin@objectos.ai).
  • Read-only identity: the showcase's own Auditor persona, auditor.demo@example.com ("Ada Auditor (demo)"), which examples/app-showcase/src/security/seed-approval-demo.ts provisions on every dev boot. It holds only the auditor position, bound to showcase_auditor (no Team grant), plus the member baseline showcase_member_default, which grants showcase_team read and no create. No code was changed to get a refusal. Before the GIF calls it "read-only", the script proves it can read: its query_records on showcase_team returned both rows.

Honesty rules, enforced by the script rather than trusted

  • Every browser frame is a screenshot of the real Console against the app that run booted; the only additions are an outline around the new row and around the record count.
  • The request panel shows the bytes sent: the body is sent pretty-printed, exactly as drawn; the API key is masked after its public prefix.
  • The response panel shows the bytes received, with one re-layout for legibility: the escapes inside result.content[0].text are drawn as the characters they encode.
  • Terminal lines are lines that run's dev server printed, picked by pattern in order, with a dim ellipsis at each gap. A pattern that stops matching is a refusal (exit 5), not a stand-in line.
  • No assistant chat transcript, no model identifier, no record the run did not create; the caller is "an agent" / "any MCP client".
  • The script also refuses (exit 5) when the admin's call does not create the row, when the read-only identity cannot read the object, when its create is NOT refused, or when the row count moves on the refusal; and (exit 6) when the GIF is not 1200 px wide, runs outside 20-35 s, or exceeds 4,000,000 bytes.

Re-render

node docs/screenshots/render-readme-demo.mjs                 # rewrite the committed GIF
node docs/screenshots/render-readme-demo.mjs --out /tmp/demo  # preview: GIF, every frame and story.json, nothing committed touched

Prerequisites are the ones pnpm dev checks itself: a built workspace (pnpm build) and a built Console (pnpm objectui:build), plus ffmpeg on PATH. Playwright's Chromium is resolved from examples/app-showcase (preinstalled binary under PLAYWRIGHT_BROWSERS_PATH, never playwright install), sharp from the docs app's Next dependency (it verifies screenshot and GIF dimensions and duration), and ffmpeg assembles the GIF in two passes (palettegen, then paletteuse with bayer dithering). Four end-to-end runs in this container produced the same beats; byte-identity is not a goal (ids, timestamps, port).

Fonts: the frames the script draws use Inter and IBM Plex Mono from Google Fonts, the hero cover's pair; all eight faces loaded in the committed render. Without them the script refuses to write the committed GIF (exit 3), as render-hero-cover.mjs does; --out previews the system fallback (Liberation Sans / DejaVu Sans Mono). The Console screenshots carry the Console's own fonts. No font file is committed.

Verification

Run on the final head 8336490e (change set: the three files above, 662 changed lines, the binary counted 0).

  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 13 families. All 13 exited 0: check-ci-filter-parity, check-closing-keyword-parity (and its --self-test), check-comment-mask-corpus, @objectstack/lint check:doc-formula-expressions, check:cross-package-test-inputs, check:doc-anchors, check:doc-authoring, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:refd-timer-probe, check:watch-hint-literal. --ran reconciliation: "13 derived, 13 run, 0 NOT-MEASURED, 0 UNRUN".
  • pnpm check:published-readme-links exited 0: "221 outbound link(s) across 101 published markdown file(s) ... 144/144 relative target(s) found in the tree."
  • Narrowed eslint, spelled as pnpm lint runs it (--no-inline-config), over the three changed paths:
    • population, read from the config: eslint --print-config answers a config object for render-readme-demo.mjs and undefined for README.md and the GIF;
    • count, read from --format json: 3 results, 1 file linted with 0 errors and 0 warnings, 2 "File ignored because no matching configuration was supplied";
    • invariance: that config's parserOptions is { ecmaVersion, sourceType } with no project or projectService (type-aware linting is off repo-wide), and nothing imports the new script, so this diff cannot move any untouched file's verdict.
  • Not run locally: the repo-wide pnpm lint and the rest of CI's farm, which CI owns.

Acceptance notes

  • Serial constraint: fix(cli): Console-dist warning names the remedy for where it runs; README states the Console step and command costs #22224 (the README contributor-path section, lower in the file) is still open; origin/main at 3ae59661 has no README change since this branch's base 7b926f76, so no merge was needed. Both PRs edit different hunks of README.md.
  • Observed in a fresh pnpm dev:showcase -- --fresh boot whose full output was read during this work, not investigated, not filed (outside this card): the boot-diagnostics block prints a sys_migration "UNIQUE constraint failed" insert warning, a pre-bind settings read warning, an analytics admitObjectRead warning and a sharing-rule "expands to NO recipients" warning. The terminal frame shows none of them because it shows a pattern-picked subset of lines; nothing in the GIF depends on them.
  • The MCP refusal is an isError: true tool result carrying prose only, with HTTP 200 and no machine-readable error code; the GIF shows it as received.

Generated by Claude Code

claude added 5 commits October 8, 2026 08:14
docs/screenshots/readme-demo.gif is 1200 x 675, 29.88 s, 497,614 B,
recorded by docs/screenshots/render-readme-demo.mjs: the Team object,
the dev server booting it, an MCP create_record as the dev admin, the
same call refused for the Auditor persona, and the Console around each.

Claude-Session: https://claude.ai/code/session_011hRnra93sK5Q2gTYYTbdJR
Co-authored-by: Claude <noreply@anthropic.com>
The cover image is no longer embedded (docs/screenshots/hero-cover-dark.png
stays, untouched: it is the docs site's og:image); the 90-second video
stays as a text link under the GIF's three-beat caption.

Claude-Session: https://claude.ai/code/session_011hRnra93sK5Q2gTYYTbdJR
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the size/l label Oct 8, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 8, 2026
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Oct 8, 2026
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 8, 2026 08:54
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 8, 2026
Merged via the queue into main with commit 31d24a5 Oct 8, 2026
37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-22232-readme-demo-gif branch October 8, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants