docs(content,spec): search-ready page descriptions — 52 authored rewrites and derived reference descriptions - #20258
Merged
Merged
Conversation
build-docs.ts wrote every generated module page as "<Title> protocol schemas" and every category overview as "Complete reference for all <title> schemas" — 210 of 211 generated pages under the 70 characters a search result keeps. The new lib/page-description.ts reads the same module doc block the page body opens with and condenses its lead into 70-160 characters; a thin lead is completed with the page's schema names, and a module with no doc block gets a sentence naming them. The value is emitted double-quoted so prose punctuation cannot change the YAML. content/docs/references regenerated with gen:docs. Claude-Session: https://claude.ai/code/session_01RCEEP3Z95jrpXCeF3it3Y2 Co-authored-by: Claude <noreply@anthropic.com>
…aracters 15 descriptions were under 70 characters and 37 over 160. Each is rewritten to 120-155 characters as a sentence: what the page lets a reader do, in the words they would search. Only the description line changes; title and navTitle lines are untouched, as are the 129 in-range pages and releases/. Claude-Session: https://claude.ai/code/session_01RCEEP3Z95jrpXCeF3it3Y2 Co-authored-by: Claude <noreply@anthropic.com>
builtin-node-config.mdx changed on both sides (main's #20205 edited the module; this branch changed its description emission) and os-regen deferred it; regenerated with gen:docs from the merged tree. Claude-Session: https://claude.ai/code/session_01RCEEP3Z95jrpXCeF3it3Y2 Co-authored-by: Claude <noreply@anthropic.com>
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
3 tasks
Contributor
Author
维护者速读 · 需要你过目 description 文案,并定一处小取舍 · 2026-09-27T16:52Z本 PR 交付 #12238(p1,devx 车道最后一张开着的 p1)。席位复核结论 ACCEPT(#12238 评论 改了什么
举几行作者页的例子(完整对照表在 PR 正文里)
为什么改:搜索结果里的摘要只有这一行是我们能控制的。太短时 Google 会弃用、自己从正文里截一段;太长会被截断。 风险与代价(含回滚)
席位意见: 建议通过。另有一处小取舍请你定:
你要做的(一个动作): 在本 PR 回复「同意,选 A」或「同意,选 B」。如果某行文案要改,直接点名那一行。 Generated by Claude Code |
This was referenced Sep 27, 2026
hotlong
approved these changes
Sep 28, 2026
hotlong
marked this pull request as ready for review
September 28, 2026 02:11
hotlong
enabled auto-merge
September 28, 2026 02:11
This was referenced Sep 28, 2026
This was referenced Sep 28, 2026
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Sep 28, 2026
…el, so `os g` scaffolds reach the stack (objectstack-ai#20333) (objectstack-ai#20363) Fixes objectstack-ai#20333 Clause-②: no ## Summary `npm create objectstack`'s blank starter imported `./src/objects` alone, so everything `os g view|action|flow|dashboard|app|skill` wrote was never loaded and `os validate` counted 0 of it. The starter now wires the seven generator barrels `os init` wires since PR objectstack-ai#20329, in the lines `os init` renders: `exportsOf` over `export {};` barrels, and `requires: ['automation', 'triggers']`. The copy is bound to the CLI's single source (`SCAFFOLD_WIRED_BARRELS` / `SCAFFOLD_WIRED_REQUIRES`, derived from `GENERATOR_SCAFFOLD_TARGETS`) by a parity pin, so it is not a second wiring rule. A per-PR pin drives `npm create objectstack` → `os g object` (control) → `os g flow` → `os validate` and reads `Logic: 1 Flows`. ## What changed - `packages/create-objectstack/src/templates/blank/objectstack.config.ts`: imports every wired barrel, declares the `exportsOf` helper, and hands each barrel to its stack key. The objects import changes from `'./src/objects/index.js'` to `'./src/objects'`, the extensionless form `os init` renders, which the parity pin compares verbatim; the template's `moduleResolution: bundler` resolves the directory index, and a fresh scaffold type-checks. It carries `requires: ['automation', 'triggers']`. `automation` was already there for the three connector plugins, and its comment keeps that reason. - Six new `src/{views,actions,flows,dashboards,apps,skills}/index.ts` barrels, byte-identical to what `os init` writes. - Two pins in `packages/cli/test/` (below). The CLI is the only package that can call the renderer, and it already depends on `create-objectstack`. - `packages/cli/package.json` gains `@objectstack/connector-{rest,openapi,mcp}` as devDependencies (lockfile +9 lines, one importer block). They exist only so the scaffolded project the chain pin builds under the CLI's `node_modules` can resolve the blank config's connector imports, and so CI builds them in `@objectstack/cli#test`'s closure. - `scripts/cross-package-test-inputs.mjs` and `turbo.json` declare the blank config and `src/**` as inputs of `@objectstack/cli#test`, with a witness for the barrel glob the scan cannot name. - Docs this change made false (see below), and a `create-objectstack` patch changeset. ## Why a static copy, and what binds it `create-objectstack` cannot import the roster. The dependency edge runs the other way, and the npx entry must not pull the CLI's closure: the boundary `scripts/sync-scaffold-emission-policy.mjs` already documents. Measured options: - **Generate at build time.** The roster is computed from the `GENERATORS` literal in `generate.ts`. Reading it at `create-objectstack`'s build would need either text-parsing that literal, or evaluating the CLI's source before the CLI's own dependencies are built, which is a build-order cycle. - **Parity pin over a static copy.** Chosen as the least machinery. `create-objectstack-wiring-parity.test.ts` reads every expected line off the CLI: the barrel import lines, the `exportsOf` line and the stack-key lines of `TEMPLATES.app.configContent`, the `requires` tokens as a superset of `SCAFFOLD_WIRED_REQUIRES`, and each empty barrel byte for byte from `TEMPLATES.app.srcFiles`. A generator added to the roster, a renderer change or a hand edit of the template reddens it (ablations A1 to A3). ## Measured before and after, through the real commands The on-ramp's real `bin/` scaffolded `my-app --skip-install --skip-skills` into a directory where the config's imports resolve, then this repo's CLI ran. | step | `origin/main` `c74de10a9` | this branch | |:---|:---|:---| | `os g object order_line` (control) | exit 0, reaches the stack | exit 0, reaches the stack | | `os g flow order_line` | exit 0, **Not wired** | exit 0, reaches the stack | | `os validate` | exit 0, `Data: 2 Objects`, `Logic: 0 Flows` | exit 0, `Data: 2 Objects`, `Logic: 1 Flows` | - **`exportsOf` is required here too.** A fresh starter type-checks (`tsc --noEmit`, 6.0.3, exit 0). The same starter with `Object.values` on the empty barrels fails with 4 x TS2322 (actions, flows, dashboards, apps). After generating the object and the flow it still type-checks. - **`requires` boots.** `os dev --fresh` on a random port: the flow-less fresh starter was healthy after about 22s, `/api/v1/ready` answered 200, and `AutomationServicePlugin` and the record-change, schedule, time-relative and api trigger plugins loaded, resolved through the CLI's own dependencies. With the generated flow it was healthy after about 24s and reported `Flows: 1 flow(s) 1 bound to triggers`. Neither boot printed "not enabled" or "NOT installed". - **Census.** `src/templates/` holds one starter, `blank`, which is also the registry's only entry. ## Pins - `packages/cli/test/create-objectstack-wiring-parity.test.ts` (unit, per-PR): 20 cases, described above. - `packages/cli/test/create-objectstack-stack-reach.test.ts` (integration, per-PR, not `.e2e`): the chain above, with item names read off the generator roster. It asserts the exit codes, the named subjects, the absence of the wiring lines and of a `requires` line from `os g flow`, and the `Data: 2 Objects` / `Logic: 1 Flows` counts. No prose is pinned. ## Ablations Each ran after the fix was committed. Mutations went through `scripts/ablation-replace.mjs` in wrap mode, which verified the anchor count and the blob change and restored with blob equal to HEAD and an empty `git diff HEAD`. - **A1, the wiring reverted** (the `flows: exportsOf(flows),` line deleted, then `create-objectstack` rebuilt). `ablation-dist-preflight --absent` confirmed the line was gone from `dist/`. Chain pin: 2 failed, 2 passed. The control and the scaffold stayed green, and `os g flow` printed the wiring lines while validate read no `Logic: 1 Flows`. Parity pin: 1 failed, 19 passed, on the stack-key comparison. Direction: red. - **A1 restore.** Rebuilt; `ablation-dist-preflight` found the marker present in `dist/templates/blank/objectstack.config.ts`, and the whole tree was clean. Chain pin 4/4, parity pin 20/20. - **A2, a barrel dropped from the template** (the `skills` key deleted): parity 1 failed, 19 passed. Red. - **A3, one barrel's bytes drifted from what `os init` writes** (`views/index.ts` reworded): parity 1 failed, 19 passed. Red. - After A2 and A3 the whole tree was clean, and parity was 20/20. ## Verification Patch round 1, at HEAD `702a27775` (origin/main `a88a1bb39` merged at `df0c0c846`): the 124 derived gates, `check-issue-citations --base origin/main` and `check:scaffold-emission-policy` all exited 0 on the first pass (`--ran`: 124 derived, 124 run, 0 NOT-MEASURED, 0 UNRUN), including `check:doc-anchors`, `check:docs-audit-scope` and `check-affected-docs`; `pnpm lint` exited 0; the parity pin 20/20, the chain pin 4/4, and `create-objectstack` 16 files, 232 passed. Round 0: all of the following ran at HEAD `d50d46fe0` (origin/main `26daf0b03` merged). - `pnpm --filter create-objectstack test`: 16 files, 232 passed. `typecheck`: exit 0. - `pnpm --filter @objectstack/cli typecheck`: exit 0, including `check:test-typecheck`, whose ledger is unchanged. - CLI `unit` project: 231 files, 3316 passed. - CLI `integration`: this chain pin plus `generate-stack-reach.test.ts`, 2 files, 11 passed. - `pnpm lint`: exit 0 over the whole repo, not narrowed. - `node scripts/check-issue-citations.mjs --base origin/main`: exit 0. - `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran`: 124 derived, 124 run, 0 NOT-MEASURED, 0 UNRUN. Three gates first exited 3 with PREREQUISITE NOT MET (`check:skill-examples`, `check:dual-build-cjs-loads`, `check:i18n-coverage`) and exited 0 after a full build. - `pnpm check:scaffold-emission-policy`: exit 0. ## Docs this change made false, and a surface note These published lines described an objects-only starter and are corrected in place: - the blank starter's `README.md` Layout, plus its app remedy, which now says to export the file from `src/apps/index.ts`; - the shipped `AGENTS.md` rule 3, which prescribed `Object.values()` (measured TS2322 on the now-empty barrels); - the package `README.md` tree; - `content/docs/getting-started/your-first-project.mdx`: its section-2 tree and config block; - `content/docs/getting-started/build-with-claude-code.mdx` (patch round 1): step 3 said the agent wires the action, view and app through `actions:` / `views:` / `apps:` keys in `defineStack()`. It now says each file is exported from its directory's barrel (`src/actions/index.ts`, `src/views/index.ts`, `src/apps/index.ts`), which the starter's config already hands to `defineStack()`, matching the shipped `AGENTS.md` rule 3. A sweep of `content/docs/` found no other sentence telling a starter author to add a collection key; - `content/docs/deployment/cli.mdx`. In `cli.mdx`, the `os generate` section's "Not wired" example named "the `npm create objectstack` starter", and its first-app walkthrough ran `os generate action approve`. On the wired starter that action is refused with exit 1: "Action 'approve' references object 'my_app_approve' which is not defined in objects". The walkthrough now runs `object customer`, then `flow customer`, then `action customer`, measured `UI: 1 Actions` and `Logic: 1 Flows`. Its fixture callout now names the extra action. `content/docs/**` and `packages/create-objectstack/README.md` were outside the claim's first file surface; the seat amended the claim in place to name them. They are edited under the agent contract's rule that a published line this change makes false is repaired in the same PR. PR objectstack-ai#20341 edits `cli.mdx` around lines 1619 to 1690, disjoint from these hunks; PR objectstack-ai#20258 edited lines 1 to 7 of `your-first-project.mdx` and `build-with-claude-code.mdx`, has since landed, and merged into this branch without conflict. `skills/objectstack-platform/SKILL.md` line 192 says the template declares `requires: ['automation']`. That is now stale, but `skills/**` is a governed Tier H surface, so it is **not** edited here; the seat files it for the skills lane once this PR lands. ## Acceptance notes - Byte-identical barrels inherit the article slip in `init.ts`'s `renderEmptyWiredBarrel` ("a action", "a app"). `init.ts` is read-only here. Whoever next edits that renderer carries it, and the parity pin will then require the starter to follow. - The old walkthrough's `os generate flow onboarding` also bound its flow to an undeclared object. That was not silent: `os dev` warned "the flow will never fire". The new walkthrough binds to the object it creates. - Measured in patch round 1, on a scaffolded starter holding the Build with Claude Code step-3 files: exporting each from its barrel, with the config untouched, gives `os validate` exit 0 with `Data: 2 Objects 6 Fields` and `UI: 1 Apps 1 Views 1 Actions`, the page's step-4 counts. Adding `actions:` / `views:` / `apps:` keys beside the wired ones instead still validates (the later key wins), but the starter's `tsc --noEmit` fails with 3 x TS1117, and a later `os g view customer` then reports Not wired, while the barrel-wired project reports it reaches the stack. - The `requires` pair is PR objectstack-ai#20329's shape. The standing family cards for the rest of that seam are objectstack-ai#20331 and objectstack-ai#20332, both named on objectstack-ai#20215. --- _Generated by [Claude Code](https://claude.ai/code/session_01UYBdGBzWSrAMzpW8ah3GbP)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
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 #12238
Clause-②: no
Draft for the maintainer's voice review — do not merge or ready it. One card, both halves, per the rulings recorded on the card (comment
5856895911): 「一张卡全做」 (authored pages AND the generator), 「只改超范围的 52 页」 (only the out-of-range authored pages), 「不加门禁」 (no newcheck:*gate).The rule
A page's frontmatter
descriptionis the one line a search result shows under its title.Population, before → after
Measured on this branch's tree (
4b7d63cc) against its basee0f17a3;releases/**is release-owned and out of scope.content/docs/**minusreferences/**,releases/**)references/**Every one of the 392 pages' frontmatter parses as YAML (js-yaml) with a string
descriptionin range. No exceptions remain.Authored half — 52 rows
Only the
description:line changes (git diffover the 52 files: 52 insertions, 52 deletions, zero other lines).title:/navTitle:lines, the 129 in-range pages,releases/**,apps/docs/**andmeta.jsonare untouched. Over-long lines were trimmed toward their original meaning rather than rewritten. Rows 1–15 were under 70; rows 16–52 were over 160.concepts/north-star.mdxdata-modeling/drivers.mdxgetting-started/quick-reference.mdxindex.mdxkernel/architecture.mdxkernel/events.mdxkernel/runtime-services/email-service.mdxkernel/runtime-services/queue-service.mdxkernel/runtime-services/sharing-service.mdxkernel/services.mdxprotocol/index.mdxprotocol/objectui/actions.mdxprotocol/objectui/concept.mdxprotocol/objectui/index.mdxprotocol/objectui/widget-contract.mdxapi/declarative-endpoints.mdxapi/plugin-endpoints.mdxautomation/approvals.mdxautomation/connectors.mdxcapabilities/index.mdxconcepts/metadata-lifecycle.mdxdeployment/index.mdxdeployment/publish-and-preview.mdxdeployment/seed-tenancy-repair.mdxdeployment/self-hosting.mdxdeployment/tenancy-modes.mdxgetting-started/build-with-claude-code.mdxgetting-started/how-ai-development-works.mdxgetting-started/your-first-project.mdxpermissions/access-recipes.mdxpermissions/administrator-guide.mdxpermissions/attachments-access.mdxpermissions/authorization.mdxpermissions/capabilities.mdxpermissions/delegated-administration.mdxpermissions/index.mdxpermissions/permission-sets.mdxpermissions/permissions-matrix.mdxpermissions/positions.mdxpermissions/profiles.mdxpermissions/record-view-auditing.mdxreadaction in sys_audit_log: its per-object opt-in, the four edges of its scope, and what a view row deliberately does not carry.permissions/sharing-rules.mdxpermissions/system-context.mdxExecutionContext.isSystem— what an elevated write gets, what it loses, and what the flag deliberately does NOT do. Built by census over the whole repo, not by recall.permissions/tenant-audit-census.mdxui/actions.mdxui/audience-based-interfaces.mdxui/create-vs-edit-form.mdxui/field-grouping-and-order.mdxui/forms.mdxui/public-data-collection.mdxui/react-pages.mdxupgrading.mdxGenerator half —
packages/spec/scripts/build-docs.tsBefore: every module page was written
description: TITLE protocol schemas, every category overviewdescription: Complete reference for all TITLE schemas— 210 of 211 generated pages under 70.Derivation (new
packages/spec/scripts/lib/page-description.ts, pinned byscripts/page-description.test.ts, 18 cases). Nopackages/spec/src/**file is edited: the rule reads the module's leading doc block through the existingfindModuleDocBlock— the same blockrenderFileDescriptionalready renders as the page's opening.{@link}are flattened to text; citation-only parentheticals ((#NNN),[ADR-NNNN …]), bare URLs, one-word run-in labels and theImplements P0 requirement …boilerplate are dropped; a sentence that only introduced a list keeps its clause before the last comma or dash.… Reference for A, B and N more: every property with its type and default.TITLE schemas of the ObjectStack CATEGORY: A, B and N more — each property with its type, default and a TypeScript example.Names are listed while they fit, the rest counted.The ObjectStack CATEGORY in N reference pages: every schema in @objectstack/spec with its properties, types, defaults and a TypeScript example.The value is emitted double-quoted (
JSON.stringify, a subset of YAML's double-quoted style), because doc-block prose carries:and quotes. Everything is a pure function of the source, socheck:docsstays a plain regenerate-and-compare. Eachgen:docsrun prints one tally line.Which rule wrote the 196 module pages: 115 from the doc block alone, 19 doc block + schema names, 62 on the schema-name fallback (their module has no module-level doc block — e.g.
data/object,api/contract,kernel/plugin). Plus 14 category overviews from rule 5. Two doc-block pages end on the word-boundary ellipsis (data/validation,marketplace/package): their opening sentence has no clause boundary that keeps ≥ 70 characters. They are in range.Sample — 10 regenerated pages
references/data/object.mdxreferences/ui/view.mdxreferences/api/dispatcher.mdxreferences/automation/control-flow.mdxreferences/kernel/cluster.mdxreferences/security/rls.mdxreferences/api/error-code-ledger.mdxreferences/system/object-storage.mdxreferences/kernel/plugin.mdxreferences/data/index.mdxExact hunks in
build-docs.ts(for #15403's rebase)#15403 remains open; it will edit the title emission. This PR does not touch the title line (
md += \title: ${zodTitle}\n``, base line 478) or anything else in the title path. Hunks, in base-file line numbers:@@ -64,0 +65,6— import oflib/page-description.@@ -457,0 +464,3— thedescriptionSourcestally, afterPAGE_SECTION_LEVEL.@@ -465 +474,2,@@ -470 +480— the module source is read once intosourceand handed torenderFileDescription(behaviour unchanged).@@ -476,0 +487,9— themodulePageDescription(...)call, just above the frontmatter.@@ -479 +498— the one description line of module pages.@@ -912 +931— the one description line of category overviews.@@ -1102,0 +1122,8— the tally'sconsole.log, beforeflush.content/docs/references/**is regenerated bygen:docs, never hand-edited: againstorigin/main, the only changed lines under it are 210description:lines (the rootreferences/index.mdxwas already in range and is unchanged).Acceptance
content/docs/**description outsidereleases/**is 70–160 characters — 392 of 392, no exceptionsa— dropped by the ruling 「不加门禁」check:*gate enforces the rangeChangeset
skip-changeset: nothing here ships.packages/specpublishesfiles: [dist, json-schema, liveness, prompts, llms.txt, README.md, src/**/*.zod.ts, CHANGELOG.md, api-surface, spec-changes.json];scripts/**is not in it. Measured after a real build:modulePageDescription/categoryIndexDescriptionhave 0 hits across every shipped path, while the positive controlObjectSchemahas 56 hits indist.content/docs/**belongs to no package.Verification (on
4b7d63cc, after mergingorigin/mainviaos-regen-merge.sh)pnpm --filter @objectstack/spec build, thencheck:generated— every gate ✓, includingcheck:docs("226 generated files in sync").dispatch-gates --commandsderived 94 families.--ranwith recorded exit codes: 94 derived, 92 run, 2 NOT-MEASURED, 0 UNRUN. All 92 exit 0.check:dual-build-cjs-loadsandcheck:type-check-debt's--re-measure. Both exit 3 because they need the fullpackages/*build closure. This diff changes no package source they read; CI builds that closure.pnpm --filter @objectstack/spec typecheck(tsc +check:scripts-typecheck+check:test-typecheck) — exit 0.scripts/page-description.test.ts18/18; neighboursfile-description,references-banner,category-title,root-index,category-index,schema-section— 3 files (local) + 4 files (repo), 68 + 146 tests pass.main's feat(spec,automation): create_record / update_record fields.* accept the CEL value envelope — declared and evaluated together #20205 changedautomation/builtin-node-configon both sides. It was regenerated from the merged tree in its own commit (4b7d63cc); its body is byte-identical toorigin/mainapart from the description line.Acceptance notes
packages/spec/src/**edit and was out of this card's surface on purpose (clause-② path limb). The tally line printed bygen:docsis the running count.kernel/metadata-protection: "Phase 1 introduces the item-level lock …"). The rule reproduces the source's own first sentence faithfully; improving those needs asrcdocblock edit, not a generator change.Size: 265 files, +801 / −266 = 1,067 changed lines, generated files included — under the 5,000-line threshold.
Seat
domain:devx#2, dispatched bysession_018mA64scZ8fmpiPkrHVAwXj; implemented insession_01RCEEP3Z95jrpXCeF3it3Y2.🤖 Generated with Claude Code
Generated by Claude Code