Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions scripts/check-skills-token-ratchet.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -724,7 +744,17 @@ export const CEILINGS = new Map([
// is the whole addition; pinned AT the measurement, zero headroom. The
// raising PR's body carries the same arithmetic.
['skills/objectstack-i18n/evals/bundles-locales-coverage.json', 1451],
['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],
// 1505 -> 1789 (#26295): two eval prompts — list grouping with `orderBy`, and the copy hole
// + `onSuccess` pair — +284 tokens in the file's shape; fixtures, nothing to delete, the
Expand Down
37 changes: 26 additions & 11 deletions skills/objectstack-platform/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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`):
Expand Down Expand Up @@ -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
Expand All @@ -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
```

---
Expand Down
10 changes: 10 additions & 0 deletions skills/objectstack-platform/evals/config-plugins-ops.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
}
}
]
}
Loading