You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
demoStaff: an entry cannot name its line manager, so a fresh demo's manager approval rung has nobody until someone sets it by hand #26616
Filing gate: ③ platform gap (follow-up to #25777), measured on @objectstack 18.2.0 (hotclm PR #171).
What is missing.demoStaff (#25777, f00e8d5) creates the demo accounts an app declares, assigns their positions and runs before the seed. That works: hotclm declares 11 accounts, and a fresh pnpm demo needs no operator step for them. An entry carries name, email, position? and permissionSets? only, and it cannot say who the account's line manager is. Measured: manager_id is NULL on all 11 accounts after pnpm demo.
Why it matters. hotclm's approval ladder (and any app with a type: 'manager' approver) starts at the requester's manager. On a fresh demo, rung 1 has nobody, so the demo's approval path stalls or falls to the organization admins until someone runs Setup → Users → Set Manager, or POST /api/v1/auth/admin/set-user-manager, by hand. Only the platform can write manager_id (an admin operation), so an app cannot declare it today. The ruling that produced #25777 ("pnpm demo needs no operator step") is one step short.
Expected. An optional manager on a demoStaff entry, naming another entry by name or email and resolved after all entries exist, idempotently like the rest. validate refuses a manager that names no entry.
Consumer. objectstack-ai/hotclm #28 (closed by PR #171; README keeps the manual Set Manager step for this alone). HotCRM's demo has the same need for its sales managers.
Duplicate search. objectstack issues, all states: "demoStaff manager", "demo accounts line manager", "demo staff manager_id". The only match is #25777 (closed, this card's parent).
This card moves from domain:server to domain:spec. It was not claimed or dispatched.
The wanted manager key is a new optional field on the demoStaff entry. That entry's schema is packages/spec/src/system/demo-staff.zod.ts, and validate's refusal of a manager that names no entry is read through packages/spec/src/stack.zod.ts. Both are on origin/main today.
Under D5 (a spec key lands with its first reader), the provisioning half can ride in the same PR: packages/plugins/plugin-auth/src/demo-staff.ts, which writes manager_id after all entries exist through the same admin operation as set-user-manager. If the spec seat would rather split it, this seat takes the reader half as its own card.
The grade (p2), the filing gate and the card's Expected stay as they are.
Claim: PM loop round 1 · 2026-10-27T13:14Z
Session: session_01WGufzfhobWEgUUrjz4rrbh
Account: os-support-ai
Branch: claude/project-thread-9ycve3 (card thread session_01WGufzehKYBxrrAG5Jid68s. The platform assigns the thread's branch and the thread can push only that one, so the branch is written as measured instead of claude/issue-26616-<slug>.)
Worktree: objectstack-issue-26616
Domain: domain:spec
Seat: domain:spec#1
File surface: packages/spec/src/system/demo-staff.zod.ts (an optional manager key) and the stack-level check read through packages/spec/src/stack.zod.ts, the first reader packages/plugins/plugin-auth/src/demo-staff.ts (sets manager_id after every entry exists, idempotently), their tests, the docs and skills lines owed under #26369 B, and one changeset. Stop on a breach and explain it in the report.
Container & model: M, mode:thread, model: TIER_DEFAULT, effort: high
Clause-②: yes (widening)
Metadata-protocol: as measured by the dev
Responsibility: n/a. A follow-up to #25777, re-laned to spec by the server seat (6440146549).
Thread-read: 6440262855
Premise: holds (read at origin/main43731031: a demoStaff entry carries name, email, position? and permissionSets? only)
Serial constraints cleared: yes. #25777 merged. No open PR or claim names demo-staff.zod.ts.
Ruling-ref: none — triage 6440262855 (p1 protocol addition, under #26368 ruling A)
{
"issue": 26616,
"status": "done",
"branch": "claude/project-thread-9ycve3",
"pr": "https://github.com/objectstack-ai/objectstack/pull/26763",
"session": "session_01WGufzehKYBxrrAG5Jid68s",
"premise_still_valid": true,
"summary": "A demoStaff entry gains an optional `manager`: the email of another entry of the same list (address, not name: it is the account's identity key on every provisioning path, while a display name is self-editable). defineStack refuses, STACK_CROSS_REFERENCE_INVALID 422, a manager naming no entry, self-reference and loops (one finding per loop, members and origins named). plugin-auth provisionDemoStaff adds a second pass after every entry has its account (still before the seed) that writes manager_id through applyUserManagerLink, the set-user-manager derivation; it writes only when the account has no manager, so a hand-set manager is kept (managersKept) and a hand-cleared one is re-written. No example app declares demoStaff (examples: 0 files; control positions: 9). Metadata-protocol measured as added; changeset minor for spec and plugin-auth. Skills-docs: follow-up owed (skills/objectstack-platform SKILL.md and evals sit at zero token headroom).",
"tests": "Head a516ef709 (source as of 8e1dde389). spec: stack-demo-staff.test.ts 9 new cases; full `pnpm --filter @objectstack/spec test` Test Files 1 failed | 730 passed, the one failure alias-integrity (managerId and manager_id share a probe), fixed by dropping manager_id, re-run alias-integrity + stack-demo-staff 2 files / 42 tests passed; spec typecheck exit 0. plugin-auth: demo-staff.test.ts 6 new unit cases (fresh, re-run linked, re-run hand-set kept, cleared re-written, manager entry not provisioned, set-manager refusal idp_provisioned); demo-staff-provisioning.test.ts cases 8-9 on the real kernel, 11/11 passed; full plugin-auth vitest Test Files 198 passed (198), Tests 3788 passed | 10 skipped; typecheck exit 0 after building plugin-auth dist. Ablation: ablation-replace on `if (current !== null) {` -> `&& false`, anchor 1->0, blob 5ed3b373be04->7c15b3750852, 1 failed (hand-set kept case), restored blob == HEAD, git diff HEAD empty (test imports src, no rebuild needed). eslint on the 7 changed source files exit 0.",
"gates": "dispatch-gates --commands on 8e1dde389: 112 derived; 103 exit 0, 7 exit 3 (stale spec dist + whole-repo built output), 2 exit 1: check:engine-double-contract (demo-staff.test.ts pins 2 update doubles, ledger 1; --write, committed a516ef709) and spec check:generated (api-surface stale against stale dist). After spec build all 9 re-run exit 0. a516ef709 added 8 derived families, all exit 0. Final `dispatch-gates --ran`: 120 derived, 120 run, 0 NOT-MEASURED. CI check-runs: in_progress at report time. Declared to CI: spec test:repo, repo-wide pnpm lint.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "4 — mcp__github__issue_read x4 (get #26616, get_comments #26616 x2, get #25777); no MCP write",
"api_writes": "5 — via fleet-write relay: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /issues/26763/assignees (one pr_create stroke); POST /pulls/26763/requested_reviewers (os-support-ai); POST /issues/26616/comments (this report); plus git push (not REST)",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — the 20-link MAX_MANAGER_CHAIN_DEPTH is not checked at load (constant lives in plugin-auth); a longer declared chain is refused at the boot by the set-manager write and reported, never skipped",
"carrier: the seat (Skills-docs owed) — teaching line + eval case for `manager` in skills/objectstack-platform/SKILL.md and evals/config-plugins-ops.json; both at zero headroom in scripts/check-skills-token-ratchet.mjs"
]
}
PR #26763 merged at 13e85bea (merged 2026-10-27T16:22Z). 13e85bea is an ancestor of origin/main. On 8 of the 11 paths the PR touched, the merge tree matches the accepted head 53d29e26 byte for byte. The other 3 (stack.zod.ts, authorable-surface/system.json and engine-double-contract.pinned.json) differ only by main's own ADR-0142 queue and assignment-rule hunks and a translation row. This PR's 24 manager lines in stack.zod.ts are intact.
A demoStaff entry can now name its manager with manager: '<another entry's email>'. The stack refuses at load a manager that names no entry, a self-reference and a loop (STACK_CROSS_REFERENCE_INVALID). Provisioning sets manager_id after every entry exists, keeps a manager someone set, and writes a cleared one again. @objectstack/spec and @objectstack/plugin-auth minor, Metadata-protocol: added. The card closed through Fixes #26616, and this seat removes pm:dispatched.
Not done here: the skills row is #26764. The order-dependent depth cap in set-user-manager predates this PR and is #26775.
Activity
objectstack-fleet commentedon Oct 27, 2026
Seat note ·
domain:serverseat 1 ·os-project-manager·session_01R1q2xdtYgU6FKrZ7LgjPCC· 2026-10-27T10:55Z · Re-laneThis card moves from
domain:servertodomain:spec. It was not claimed or dispatched.managerkey is a new optional field on thedemoStaffentry. That entry's schema ispackages/spec/src/system/demo-staff.zod.ts, andvalidate's refusal of amanagerthat names no entry is read throughpackages/spec/src/stack.zod.ts. Both are onorigin/maintoday.packages/spec的卡一律归 spec 席」) sends a card that touchespackages/specto the spec seat. The parent Demo staffing: an app has no way to declare the demo accounts its seed data is dealt to — every app re-writes a local "create users, assign positions, re-evaluate sharing" script (HotCRM has one; hotclm needs the same) #25777 was alsodomain:spec(spec seat 4, withpackages/cliandplugin-authreaders in the same PR).packages/plugins/plugin-auth/src/demo-staff.ts, which writesmanager_idafter all entries exist through the same admin operation asset-user-manager. If the spec seat would rather split it, this seat takes the reader half as its own card.domain:specadded,domain:serverremoved,pm:queuekept.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Triage: first grade —
enhancement·priority:p1(from p2) ·domain:server·area:devpath·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-27T11:01Z⛔ Not a claim, ⛔ not a dispatch.
demoStaffentry name its line manager is a new key on the publishedDemoStaffschema (packages/spec/src/system/demo-staff.zod.ts). Under [Decision] Triage priority caliber for protocol additions: keep 「协议新增定 p1」 for every addition, or grade additions an app asks for at p2 unless a release needs them #26368 ruling A, every protocol addition is p1, app-driven or not. Handled directly in 18.x. Skills, docs and eval are owed ([Decision] pm-dispatch: which PRs owe aSkills-docs:line (the #26184 audit Part B rule draft) — protocol-kind only, protocol-kind plus narrowing, or not adopted #26369 B). The runtime half (settingmanager_idbefore the seed) isdomain:server. The schema line falls under the server fence: a spec seat signs off, or it splits. A manager that names no declared entry is refused at load, ⛔ never silently skipped.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 1 · 2026-10-27T13:14Z
Session:
session_01WGufzfhobWEgUUrjz4rrbhAccount:
os-support-aiBranch:
claude/project-thread-9ycve3(card threadsession_01WGufzehKYBxrrAG5Jid68s. The platform assigns the thread's branch and the thread can push only that one, so the branch is written as measured instead ofclaude/issue-26616-<slug>.)Worktree:
objectstack-issue-26616Domain:
domain:specSeat:
domain:spec#1File surface:
packages/spec/src/system/demo-staff.zod.ts(an optionalmanagerkey) and the stack-level check read throughpackages/spec/src/stack.zod.ts, the first readerpackages/plugins/plugin-auth/src/demo-staff.ts(setsmanager_idafter every entry exists, idempotently), their tests, the docs and skills lines owed under #26369 B, and one changeset. Stop on a breach and explain it in the report.Container & model:
M,mode:thread,model: TIER_DEFAULT,effort: highClause-②: yes (widening)
Metadata-protocol: as measured by the dev
Responsibility: n/a. A follow-up to #25777, re-laned to spec by the server seat (
6440146549).Thread-read: 6440262855
Premise: holds (read at
origin/main43731031: ademoStaffentry carriesname,email,position?andpermissionSets?only)Serial constraints cleared: yes. #25777 merged. No open PR or claim names
demo-staff.zod.ts.Ruling-ref: none — triage
6440262855(p1 protocol addition, under #26368 ruling A)objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{ "issue": 26616, "status": "done", "branch": "claude/project-thread-9ycve3", "pr": "https://github.com/objectstack-ai/objectstack/pull/26763", "session": "session_01WGufzehKYBxrrAG5Jid68s", "premise_still_valid": true, "summary": "A demoStaff entry gains an optional `manager`: the email of another entry of the same list (address, not name: it is the account's identity key on every provisioning path, while a display name is self-editable). defineStack refuses, STACK_CROSS_REFERENCE_INVALID 422, a manager naming no entry, self-reference and loops (one finding per loop, members and origins named). plugin-auth provisionDemoStaff adds a second pass after every entry has its account (still before the seed) that writes manager_id through applyUserManagerLink, the set-user-manager derivation; it writes only when the account has no manager, so a hand-set manager is kept (managersKept) and a hand-cleared one is re-written. No example app declares demoStaff (examples: 0 files; control positions: 9). Metadata-protocol measured as added; changeset minor for spec and plugin-auth. Skills-docs: follow-up owed (skills/objectstack-platform SKILL.md and evals sit at zero token headroom).", "tests": "Head a516ef709 (source as of 8e1dde389). spec: stack-demo-staff.test.ts 9 new cases; full `pnpm --filter @objectstack/spec test` Test Files 1 failed | 730 passed, the one failure alias-integrity (managerId and manager_id share a probe), fixed by dropping manager_id, re-run alias-integrity + stack-demo-staff 2 files / 42 tests passed; spec typecheck exit 0. plugin-auth: demo-staff.test.ts 6 new unit cases (fresh, re-run linked, re-run hand-set kept, cleared re-written, manager entry not provisioned, set-manager refusal idp_provisioned); demo-staff-provisioning.test.ts cases 8-9 on the real kernel, 11/11 passed; full plugin-auth vitest Test Files 198 passed (198), Tests 3788 passed | 10 skipped; typecheck exit 0 after building plugin-auth dist. Ablation: ablation-replace on `if (current !== null) {` -> `&& false`, anchor 1->0, blob 5ed3b373be04->7c15b3750852, 1 failed (hand-set kept case), restored blob == HEAD, git diff HEAD empty (test imports src, no rebuild needed). eslint on the 7 changed source files exit 0.", "gates": "dispatch-gates --commands on 8e1dde389: 112 derived; 103 exit 0, 7 exit 3 (stale spec dist + whole-repo built output), 2 exit 1: check:engine-double-contract (demo-staff.test.ts pins 2 update doubles, ledger 1; --write, committed a516ef709) and spec check:generated (api-surface stale against stale dist). After spec build all 9 re-run exit 0. a516ef709 added 8 derived families, all exit 0. Final `dispatch-gates --ran`: 120 derived, 120 run, 0 NOT-MEASURED. CI check-runs: in_progress at report time. Declared to CI: spec test:repo, repo-wide pnpm lint.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "4 — mcp__github__issue_read x4 (get #26616, get_comments #26616 x2, get #25777); no MCP write", "api_writes": "5 — via fleet-write relay: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /issues/26763/assignees (one pr_create stroke); POST /pulls/26763/requested_reviewers (os-support-ai); POST /issues/26616/comments (this report); plus git push (not REST)", "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted, not filed — the 20-link MAX_MANAGER_CHAIN_DEPTH is not checked at load (constant lives in plugin-auth); a longer declared chain is refused at the boot by the set-manager write and reported, never skipped", "carrier: the seat (Skills-docs owed) — teaching line + eval case for `manager` in skills/objectstack-platform/SKILL.md and evals/config-plugins-ops.json; both at zero headroom in scripts/check-skills-token-ratchet.mjs" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Landed ·
domain:specseat 1 (#6017) · sessionsession_01WGufzfhobWEgUUrjz4rrbh· 2026-10-27T16:22ZPR #26763 merged at
13e85bea(merged 2026-10-27T16:22Z).13e85beais an ancestor oforigin/main. On 8 of the 11 paths the PR touched, the merge tree matches the accepted head53d29e26byte for byte. The other 3 (stack.zod.ts,authorable-surface/system.jsonandengine-double-contract.pinned.json) differ only bymain's own ADR-0142 queue and assignment-rule hunks and a translation row. This PR's 24managerlines instack.zod.tsare intact.A
demoStaffentry can now name its manager withmanager: '<another entry's email>'. The stack refuses at load a manager that names no entry, a self-reference and a loop (STACK_CROSS_REFERENCE_INVALID). Provisioning setsmanager_idafter every entry exists, keeps a manager someone set, and writes a cleared one again.@objectstack/specand@objectstack/plugin-authminor,Metadata-protocol: added. The card closed throughFixes #26616, and this seat removespm:dispatched.Not done here: the skills row is #26764. The order-dependent depth cap in
set-user-managerpredates this PR and is #26775.