Skip to content

Commit 45de8c6

Browse files
fix(skills): objectstack-platform — a seeded sys_user row lands as an account-less directory row, it is not refused (#26302 follow-up) (#26448)
<!-- claude-projects-attribution: {"github_login":"os-warren"} --> _Requested by **Warren** · [project thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ81ut4uJxWyaaick9b2LrTc1)_ Fixes #26302 Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么**:把 PR #26420 刚合并进 objectstack-platform 技能包的那一小节里写错的一句改对:种子里写的 `sys_user` 行不是「被拒(ADR-0092)」,而是落成一条没有账号、谁也登不进的目录行;eval 7 的括号同改。两行天花板按实测重钉(5981→5997、1458→1469,headroom 0),注释写成相对 main 的增量。 - **为什么改**:席位对 #26420 的合同复核(PR 评论 6433051864)判 FAIL 就在这一句——种子写入走系统上下文,绕过 ADR-0092 的身份写保护,运行时测试钉住了这行会落库;队列在复核贴出前已把 #26420 合进 main,所以这是同一张卡的补丁轮。 - **风险与回滚**:只改一句教学、一处 eval 措辞和两行天花板数字;不发版、无运行时改动,回滚 = revert 本 PR。 - **先看**:① `skills/objectstack-platform/SKILL.md` 第 445–447 行那一句;② `scripts/check-skills-token-ratchet.mjs` 两行(5997 / 1469)及其增量注释;③ eval 7 的 `expected_output`。 - **两分钟验证**:`node scripts/check-skills-token-ratchet.mjs` —— 全绿,objectstack-platform 的 SKILL.md 与 eval 文件 headroom 都是 0。 - **需要你做的**:Approve(Tier H,`skills/**` 是发布面)或「Merge when ready」。 ## What changes The patch round the contract review of PR #26420 ordered (PR comment 6433051864, VERDICT FAIL, ①(a) item 1). That PR landed on `main` as `75afeffd` with the sentence in it, so this is a follow-up on the same card: - `skills/objectstack-platform/SKILL.md` — the opening reason of *Demo accounts — `demoStaff` vs `devLogins`* now says what the platform does: "a `sys_user` row written through `data` lands as a directory row with no account, so nobody can sign in as it". The former "is refused (ADR-0092)" was copied from the `demo-staff.zod.ts` TSDoc and is false against the runtime: seed inserts run under `SEED_WRITE_EXECUTION_CONTEXT` (`isSystem: true`), the ADR-0092 identity write guard bypasses system-context writes (`identity-write-guard.ts` `isUserContextWrite`, pinned by its test), and `app-plugin.seed.test.ts` pins a `data: [{ object: 'sys_user' }]` row being inserted; `dev-admin-seed-gate.ts` measured the result as "a directory row with no account". The ADR citation is dropped. - `skills/objectstack-platform/evals/config-plugins-ops.json` — eval 7's expected output says "(it lands as a directory row nobody can sign in as)" instead of "(refused)". Assertions unchanged. - `scripts/check-skills-token-ratchet.mjs` — the two `objectstack-platform` rows re-pinned at the new measurement, each with a delta comment under the record that landed in #26420. The spec prose that misled the section (`demo-staff.zod.ts` lines 14–16, and the `dev-login.zod.ts` guidance that tells an author to seed the user in `data`) is card #26424, filed by the seat; not touched here. ## Why A published teaching that states a refusal the platform does not perform sends an AI author to expect a load-time failure where the row silently lands dead — the worse outcome, and exactly the "who pays" card #26302 names. ### Line budget (`skills/**` is a published surface) Whole-file, before → after, lines (before = `main` at `75afeffd`): | File | Before | After | |:--|--:|--:| | `skills/objectstack-platform/SKILL.md` | 503 | 504 | | `skills/objectstack-platform/evals/config-plugins-ops.json` | 75 | 75 | Whole-package (`SKILL.md` + `references/**/*.md` + `rules/**/*.md`): **2107 → 2108** (+1; the seven other `.md` files are untouched; `references/_index.md` generator-owned, 41). ### Token ratchet — maintainer ruling A, delta from `main` Same ruling as #26420 (the maintainer's tap on the seat thread's decision card 「skills 修复卡的教学和 eval 都撞 token 天花板,怎么付?」, 2026-10-27T01:21Z, verbatim and untranslated: 「A:先削重复,余额按实测提高」). Nothing duplicated was added, so there is nothing to cut; the remainder is the rewording itself: | Row | `main` | Added | After | Ceiling | |:--|--:|--:|--:|:--| | `SKILL.md` (priced text, minus the 20-byte stamp line) | 23924 B = 5981 tok | +61 B | 23985 B = 5997 tok | 5981 → **5997** (+16) | | `evals/config-plugins-ops.json` | 5831 B = 1458 tok | +42 B | 5873 B = 1469 tok | 1458 → **1469** (+11) | Both rows pinned AT the measurement (headroom 0). No other row is touched; the diff against `main` is these three files only. ## Tests No TypeScript changed; the reworded sentence is prose. The six-shape `defineStack` probe from #26420 still describes the schema (unchanged); the reworded reason is read off `identity-write-guard.ts`, `execution-context.zod.ts`, `app-plugin.seed.test.ts` and `dev-admin-seed-gate.ts` as above. Dogfood battery: n/a — no `!` in the title and no `(narrowing)` arm. ## Acceptance notes - `Fixes #26302` because the seat reopened the card for this patch round; the rest of #26420's review passed and is not re-done here. - Branch restarted from `main` at `75afeffd` (GitHub deleted the merged head branch), so the history is `main` + two commits; no force-push. - Commit author on both commits is the clone's configured identity. ## Verification Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` on the branch tree at head `198e492d` (54 families, the same set as #26420), each command run locally with its exit code captured before any pipe, then reconciled. `dispatch-gates --ran` at head `198e492d`: **54 derived families accounted for — 53 run (exit 0), 1 NOT-MEASURED, 0 UNRUN.** The one NOT-MEASURED is `pnpm check:dual-build-cjs-loads`, recorded exit 3 (PREREQUISITE NOT MET: it needs every package's `dist`), so CI's `Build Core` is its reading. <details><summary>Readings</summary> - Ratchet family: `node scripts/check-skills-token-ratchet.mjs` exit 0 — "81 authored bundle file(s) within their ceilings"; `objectstack-platform/SKILL.md` 5997 / 5997 (headroom 0), `evals/config-plugins-ops.json` 1469 / 1469 (headroom 0); `--self-test` exit 0 (79 cases). - The card's three acceptance gates: `pnpm --filter @objectstack/spec check:skill-docs` exit 0 ("Skill docs in sync"); `check:skill-refs` exit 0 ("9 generated files in sync with packages/spec"); `check:skill-examples` exit 0 ("264 prose examples type-check across 3 surface(s)"); the client closure built under `scripts/pm/os-verify-lock.sh` (slot `issue-26302`), VERDICT command-exit 0 (246 s held). - Every other derived command exit 0 at `198e492d`, including `pnpm check:pm-dispatch-gates` (run detached), `pnpm --filter @objectstack/lint run check:doc-formula-expressions` and `pnpm check:lean-entry-closure`. - Not owed locally: no package `test` / `typecheck` (no TypeScript changed); `test:repo`, `pnpm lint` and the whole-tree scans are CI's. - CI on the PR: not waited for (the order forbids it); the seat reads the check-runs. </details> ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (no schema touched) - [x] 2. Every name I added uses the casing for its kind. - [x] 3. No formatter ran; `pnpm lint` is CI's whole-tree run. - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. Publishes nothing (`skills/**` has no `package.json`; `skip-changeset`); both declaration lines are above. - [x] 6. `packages/spec` not touched. - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English (the 维护者速读 block and the quoted ruling are Chinese by the repo's own rule). - [x] The *Before Submitting* list in CONTRIBUTING.md is done. --- _Generated by [Claude Code](https://claude.ai/code/session_01JQwxbX1XjSzpntF9n85TgB)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent b53322d commit 45de8c6

3 files changed

Lines changed: 19 additions & 7 deletions

File tree

‎scripts/check-skills-token-ratchet.mjs‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,13 @@ export const CEILINGS = new Map([
467467
// text is 23924 bytes -> 5981 tokens: the 4 tokens of headroom are absorbed
468468
// and the ceiling moves 5828 -> 5981 (+153). Pinned AT the measurement.
469469
// ceil(($(wc -c < skills/objectstack-platform/SKILL.md) - 20) / 4) == ceil(23924 / 4)
470-
['skills/objectstack-platform/SKILL.md', 5981],
470+
// 5981 -> 5997 (card #26302, the follow-up its contract review ordered): the
471+
// section's opening reason reworded — a `sys_user` row written through
472+
// `data` is not refused, it lands as a directory row with no account — +61
473+
// bytes, so the priced text is 23924 -> 23985 bytes -> 5997 tokens, ceiling
474+
// +16, pinned AT the measurement. Same ruling, same arithmetic rule as above.
475+
// ceil(($(wc -c < skills/objectstack-platform/SKILL.md) - 20) / 4) == ceil(23985 / 4)
476+
['skills/objectstack-platform/SKILL.md', 5997],
471477
// `skills/objectstack-pm-dispatch/SKILL.md` (9708) and its
472478
// `rules/dev-template.md` (1838) left this table on 2026-09-10 with the files:
473479
// the maintainer deleted the published PM skill whole (verbatim:
@@ -837,7 +843,12 @@ export const CEILINGS = new Map([
837843
// fixture adds +989 bytes, so the LANDED file is 5831 bytes -> 1458 tokens,
838844
// ceiling +247, pinned AT the measurement.
839845
// ceil($(wc -c < skills/objectstack-platform/evals/config-plugins-ops.json) / 4) == ceil(5831 / 4)
840-
['skills/objectstack-platform/evals/config-plugins-ops.json', 1458],
846+
// 1458 -> 1469 (card #26302 follow-up): eval 7's expected output says what a
847+
// seeded `sys_user` row becomes instead of "(refused)" — +42 bytes, so the
848+
// file is 5831 -> 5873 bytes -> 1469 tokens, ceiling +11, pinned AT the
849+
// measurement.
850+
// ceil($(wc -c < skills/objectstack-platform/evals/config-plugins-ops.json) / 4) == ceil(5873 / 4)
851+
['skills/objectstack-platform/evals/config-plugins-ops.json', 1469],
841852
// 955 -> 1175: one regression case for the now-anchored comparand (the
842853
// overdue-by-grace-days prompt) — expected `{ $now: true, addDays: { $field:
843854
// 'grace_days_offset' } }` as the whole comparand of `$lt`, and NO stored

‎skills/objectstack-platform/SKILL.md‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -443,10 +443,11 @@ definition: never write it by hand, and never hand-write a raw
443443
### Demo accounts — `demoStaff` vs `devLogins`
444444

445445
A seed deals records to people (`owner_id: 'Legal Counsel 1'`) but cannot
446-
create one: a `sys_user` row in `data` is refused (ADR-0092). Declare the
447-
people in `demoStaff`; `os dev` creates each account after the development
448-
admin, signing in with the seed password (`--admin-password`, default
449-
`admin123`) — an entry carries no `password`:
446+
create one: a `sys_user` row written through `data` lands as a directory row
447+
with no account, so nobody can sign in as it. Declare the people in
448+
`demoStaff`; `os dev` creates each account after the development admin,
449+
signing in with the seed password (`--admin-password`, default `admin123`) —
450+
an entry carries no `password`:
450451

451452
```typescript
452453
demoStaff: [{ name: 'Legal Counsel 1', email: 'counsel1@example.com',

‎skills/objectstack-platform/evals/config-plugins-ops.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
{
6565
"id": 7,
6666
"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.",
67-
"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.",
67+
"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 (it lands as a directory row nobody can sign in as). `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.",
6868
"files": [],
6969
"assertions": {
7070
"must_contain": ["demoStaff", "position", "permissionSets", "os dev"],

0 commit comments

Comments
 (0)