From 01d2b0f87e76ac4e9383b746eb9b419af7130524 Mon Sep 17 00:00:00 2001 From: os-warren Date: Tue, 27 Oct 2026 02:56:00 +0000 Subject: [PATCH] docs(skills): objectstack-platform teaches demoStaff and when to pick it over devLogins The platform skill named `demoStaff` only in its top-level key list, so an author preparing a demo declared banner logins and hand-wrote user seed rows. The Seed Data section now says what each key does and which to pick, with one example and the refusals an author meets, and the package's eval file gains one prompt for it. Paid under the token ratchet's ruling A: four restatements cut from SKILL.md first, then the two touched CEILINGS rows raised by exactly the measured remainder, each row comment carrying the arithmetic. Claude-Session: https://claude.ai/code/session_01JQwxbX1XjSzpntF9n85TgB Co-authored-by: Claude --- scripts/check-skills-token-ratchet.mjs | 34 ++++++++++++++++- skills/objectstack-platform/SKILL.md | 37 +++++++++++++------ .../evals/config-plugins-ops.json | 10 +++++ 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/scripts/check-skills-token-ratchet.mjs b/scripts/check-skills-token-ratchet.mjs index 4ff52d219eb..840a19522f3 100644 --- a/scripts/check-skills-token-ratchet.mjs +++ b/scripts/check-skills-token-ratchet.mjs @@ -421,7 +421,27 @@ export const CEILINGS = new Map([ // decision tables at 487 lines. // 5833 -> 5828: A2′ — the release-stamp line left the count (see // STAMP_LINE_REPIN); the file's count fell by the same 5, headroom unchanged. - ['skills/objectstack-platform/SKILL.md', 5828], + // 5828 -> 5981 (card #26302, the objectstack-platform row of the skills gap + // audit): the Seed Data section gains `demoStaff` against `devLogins` — a + // seed deals records to people and cannot create one, so the people are + // declared in `demoStaff` and `os dev` creates the accounts (position and + // permission sets from the stack's own declarations, the seed password, never + // in the built artifact), while `devLogins` is banner text that creates and + // grants nothing. Maintainer ruling 2026-10-27 on the seat's decision card + // 「skills 修复卡的教学和 eval 都撞 token 天花板,怎么付?」, his tap verbatim + // and untranslated: 「A:先削重复,余额按实测提高」. Paid down first, as the + // ruling asks — four restatements cut, each with a surviving home in the + // file: the `defineStack()` intro (the opening paragraph and the project + // tree say it), the "read the source for the exact shape" paragraph (the + // References section keeps the rule; one pointer line stays), the boot + // sequence's "(see Ports & networking)" aside and the two cheat-sheet port + // comments (the Port resolution paragraph says both). Arithmetic in bytes: + // on `origin/main` the priced text was 23294 bytes (5824 tokens, headroom 4); + // the cuts remove 309 bytes and the section adds 939, so the LANDED priced + // text is 23924 bytes -> 5981 tokens: the 4 tokens of headroom are absorbed + // and the ceiling moves 5828 -> 5981 (+153). Pinned AT the measurement. + // ceil(($(wc -c < skills/objectstack-platform/SKILL.md) - 20) / 4) == ceil(23924 / 4) + ['skills/objectstack-platform/SKILL.md', 5981], // `skills/objectstack-pm-dispatch/SKILL.md` (9708) and its // `rules/dev-template.md` (1838) left this table on 2026-09-10 with the files: // the maintainer deleted the published PM skill whole (verbatim: @@ -689,7 +709,17 @@ export const CEILINGS = new Map([ ['skills/objectstack-data/evals/objects-fields-relationships.json', 946], ['skills/objectstack-formula/evals/cel-predicates-formulas.json', 1046], ['skills/objectstack-i18n/evals/bundles-locales-coverage.json', 1004], - ['skills/objectstack-platform/evals/config-plugins-ops.json', 1211], + // 1211 -> 1458 (card #26302): one eval for a demo whose seed names people — + // expected: both in `demoStaff` with a declared `position` / + // `permissionSets`, created by `os dev`; NO `role:` alias and NO platform + // set such as `admin_full_access`. Same ruling as the `SKILL.md` row above + // (2026-10-27, tap A: 「A:先削重复,余额按实测提高」); the file's six fixtures + // share no sentence, so there was no duplicate to cut (0 bytes). On + // `origin/main` the file was 4842 bytes (1211 tokens, headroom 0); the + // fixture adds +989 bytes, so the LANDED file is 5831 bytes -> 1458 tokens, + // ceiling +247, pinned AT the measurement. + // ceil($(wc -c < skills/objectstack-platform/evals/config-plugins-ops.json) / 4) == ceil(5831 / 4) + ['skills/objectstack-platform/evals/config-plugins-ops.json', 1458], ['skills/objectstack-query/evals/filters-pagination-search.json', 955], ['skills/objectstack-ui/evals/views-apps-actions-pages.json', 1505], ['skills/objectstack-upgrade/evals/protocol-major-upgrade.json', 1033], diff --git a/skills/objectstack-platform/SKILL.md b/skills/objectstack-platform/SKILL.md index 4979af2ac36..4a212db40b3 100644 --- a/skills/objectstack-platform/SKILL.md +++ b/skills/objectstack-platform/SKILL.md @@ -33,9 +33,6 @@ development** (plugins, services, kernel hook / event handlers, ## `defineStack()` — The Core Configuration -`objectstack.config.ts` is the single entry point for every project. -It calls `defineStack()` to declare all metadata. - → Moved verbatim to [references/bootstrap.md](./references/bootstrap.md) § Minimal Example. ### Full Configuration Reference @@ -78,11 +75,9 @@ keeping straight: scheduled migration, so a key that only warns today is expected to be refused later. -For the exact Zod shape — including which keys are optional and what types -the collection items take — read -`node_modules/@objectstack/spec/src/stack.zod.ts` -(`ObjectStackDefinitionSchema`). Each collection's item shape lives in -its own domain folder (`data/object.zod.ts`, `ui/view.zod.ts`, …). +Exact shape: `ObjectStackDefinitionSchema` in +`node_modules/@objectstack/spec/src/stack.zod.ts`; each collection's item +schema sits in its domain folder (`data/object.zod.ts`, `ui/view.zod.ts`, …). → Moved verbatim to [references/bootstrap.md](./references/bootstrap.md) § Map Format (Key → Name) · § Barrel Import Pattern. @@ -348,7 +343,7 @@ CLI: `os serve` / `os dev` ├── DispatcherPlugin └── AIServicePlugin (cloud / EE only — reverse-mounted by a cloud host; absent in the open framework per cloud ADR-0025) 5. Runtime.start() → init + start all plugins - 6. Server listens on the resolved port (see "Ports & networking" in Part 3) + 6. Server listens on the resolved port ``` **Port resolution** (both `os dev` and `os start` → `os serve`): @@ -445,6 +440,26 @@ definition: never write it by hand, and never hand-write a raw | `ignore` | Insert if not exists, skip otherwise | | `replace` | ⚠️ **Data loss** — drops and re-inserts all records | +### Demo accounts — `demoStaff` vs `devLogins` + +A seed deals records to people (`owner_id: 'Legal Counsel 1'`) but cannot +create one: a `sys_user` row in `data` is refused (ADR-0092). Declare the +people in `demoStaff`; `os dev` creates each account after the development +admin, signing in with the seed password (`--admin-password`, default +`admin123`) — an entry carries no `password`: + +```typescript +demoStaff: [{ name: 'Legal Counsel 1', email: 'counsel1@example.com', + position: 'legal_counsel', permissionSets: ['contracts_editor'] }], +``` + +`name` is what a seed reference resolves by; `position` / `permissionSets` +name only what this stack declares (a platform set such as +`admin_full_access` is refused); `os build` drops the key and a non-dev boot +creates nothing. `devLogins` creates and grants nothing — it only prints an +existing account on the boot banner. Pick `demoStaff` whenever the demo +needs an account to exist. + --- ## CLI Commands @@ -455,12 +470,12 @@ Cheat sheet for the bootstrap loop: ```bash npx create-objectstack my-app cd my-app && npm install -os dev --ui # dev server + Console at /_console/ (auto-hops port if taken) +os dev --ui # dev server + Console at /_console/ os validate # metadata cross-reference checks os compile # produce dist/ artifact os migrate plan # preview metadata↔DB schema drift (additive sync never alters existing columns) os migrate apply # reconcile DB to metadata (loosening only; --allow-destructive for drops/tightenings) -PORT=8080 os start # production — pin the port explicitly (see Ports & networking) +PORT=8080 os start # production — pin the port explicitly ``` --- diff --git a/skills/objectstack-platform/evals/config-plugins-ops.json b/skills/objectstack-platform/evals/config-plugins-ops.json index a114aa80a0e..b5c9dca96cd 100644 --- a/skills/objectstack-platform/evals/config-plugins-ops.json +++ b/skills/objectstack-platform/evals/config-plugins-ops.json @@ -60,6 +60,16 @@ "must_contain": ["os start", "PORT", "OS_TRUSTED_ORIGINS", "driver-sql"], "must_not_contain": ["new DriverPlugin", "@objectstack/plugin-prometheus"] } + }, + { + "id": 7, + "prompt": "Prepare a demo of our contracts app: the seed data assigns matters to 'Legal Counsel 1' and 'Paralegal 1', and the demo should open signed in as Legal Counsel 1.", + "expected_output": "Both people go in `demoStaff` — `name` exactly as the seed references them, `email`, and a `position` / `permissionSets` the stack itself declares — and `os dev` creates the accounts with the seed password (`admin123` by default): no `password` key, no `role:` alias, no platform set such as `admin_full_access`, and no hand-written `sys_user` seed row (refused). `devLogins` creates nothing: at most one entry naming Legal Counsel 1's address so the boot banner prints it. Notes that `os build` drops `demoStaff` and a production boot creates no demo account.", + "files": [], + "assertions": { + "must_contain": ["demoStaff", "position", "permissionSets", "os dev"], + "must_not_contain": ["role:", "admin_full_access"] + } } ] }