Repository navigation
Add sys_presence system object to service-realtime package - #1020
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
- Add PRESENCE constant to SystemObjectName in @objectstack/spec - Create sys-presence.object.ts with fields matching PresenceStateSchema - Register sys_presence in RealtimeServicePlugin via app convention - Export SysPresence from @objectstack/service-realtime - Add tests for object definition and SystemObjectName constant - Update ROADMAP.md system object naming table - Update CHANGELOG.md with architecture change Agent-Logs-Url: https://github.com/objectstack-ai/spec/sessions/8eb9f944-6c43-4378-b0a8-b84aaf261524 Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Agent-Logs-Url: https://github.com/objectstack-ai/spec/sessions/8eb9f944-6c43-4378-b0a8-b84aaf261524 Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add sys_presence system object to service-realtime package
Add sys_presence system object to service-realtime package
Mar 31, 2026
hotlong
marked this pull request as ready for review
March 31, 2026 09:51
Contributor
There was a problem hiding this comment.
Pull request overview
Adds the missing sys_presence system object to the realtime domain so the runtime can discover/register it and avoid no such table: sys_presence errors, while also exposing a protocol constant for consistent references.
Changes:
- Added
SystemObjectName.PRESENCE = 'sys_presence'(plus tests) in@objectstack/spec/system. - Introduced
SysPresenceObjectSchema(and tests) in@objectstack/service-realtime. - Registered
SysPresencefor ObjectQL auto-discovery via theapp.com.objectstack.service.realtimeconvention and exported it from the package root; updated ROADMAP/CHANGELOG entries.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| ROADMAP.md | Adds SystemObjectName.PRESENCE → sys_presence to the system object naming table. |
| packages/spec/src/system/constants/system-names.ts | Introduces the PRESENCE system object name constant. |
| packages/spec/src/system/constants/system-names.test.ts | Extends constant coverage to include PRESENCE. |
| packages/services/service-realtime/src/realtime-service-plugin.ts | Registers realtime system objects under the app.* service convention for ObjectQL discovery. |
| packages/services/service-realtime/src/objects/sys-presence.object.ts | Defines the SysPresence object schema, fields, and indexes. |
| packages/services/service-realtime/src/objects/sys-presence.object.test.ts | Adds unit tests validating the SysPresence schema shape and defaults. |
| packages/services/service-realtime/src/objects/index.ts | Barrel export for realtime-owned system objects. |
| packages/services/service-realtime/src/index.ts | Exposes SysPresence from @objectstack/service-realtime root. |
| CHANGELOG.md | Documents the addition of sys_presence and the new spec constant. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Oct 7, 2026
…ugins/plugin-dev/src to the commits that decided them (objectstack-ai#20767) Part of objectstack-ai#20594 Clause-②: no ## What changed This is stage 12 of the `domain:cli` lane of the dead-citation sweep: `packages/plugins/plugin-dev/src`. Every comment site there that cited a tracker number answering 404 now cites, in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123), the commit in this repository's history that decided what the line describes, and keeps saying in its own words what that commit decided. PR objectstack-ai#20533 is the method, and stages 1 to 11 of this card (PR objectstack-ai#20624, PR objectstack-ai#20632, PR objectstack-ai#20656, PR objectstack-ai#20673, PR objectstack-ai#20689, PR objectstack-ai#20703, PR objectstack-ai#20713, PR objectstack-ai#20723, PR objectstack-ai#20735, PR objectstack-ai#20741, PR objectstack-ai#20748) are the precedents. The card stays open for the lane's remaining packages, so this PR says `Part of`. That is **6 sites on 6 lines in 3 files, covering 2 numbers**, rewritten to **2 distinct commits**: - the census's **3 sites**, all in `src/dev-plugin.ts` (`:1063`, `:1078`, `:1097`); - **3 test-file comment sites** (the census defers `*.test.ts`; stages 1 to 11 took test comments too): `dev-plugin.test.ts:90` and `:127`, `dev-plugin-security-enforcement-warning.test.ts:53`. Only comments changed: **6 lines out, 6 in**, every one of them a site (no companion line), and every touched file keeps its line count (1159 / 317 / 199), so no line citation into these files moves. **No citation number is added**: the only tracker number on an added line is `objectstack-ai#3900` at `dev-plugin.ts:1063`, which the removed line already carried and which answers 200; no PR number stands on an added line. No ADR or ruling-record file in `docs/adr/` or `scripts/adr-anchors/` records either decision (a grep there for the 2 numbers, their PR number objectstack-ai#10092 and the 2 shas reads 0 hits; the control number `7329` reads 1 file in the same tree), so both anchors are commits. ADR-0115 records the older decision the warning comes from (an empty security slot gets one loud boot-log line), not the move these lines describe. **A `patch` changeset** for `@objectstack/plugin-dev` rides along (`.changeset/plugin-dev-provenance-anchors.md`, in PR objectstack-ai#20632's form), because the two rewritten docblock lines reach the published `dist` (measured below), as stage 6 (PR objectstack-ai#20703) measured for its package. ## Census: `packages/plugins/plugin-dev`, before and after **Instrument.** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged, run under `with-fleet.sh --read` for the token. The count is its `allocated-but-absent` findings under `packages/plugins/plugin-dev/`. Both runs enumerated the whole board. | reading | tree | board | whole-repo `allocated-but-absent` | package sites | lines | numbers | files | |---|---|---|---|---|---|---|---| | before | base `33e4a5609c`, run 2026-09-30T02:45:30Z to 02:51:51Z | enumerated, 186 pages, frontier objectstack-ai#20757, 18,584 numbers | 1,061 | **3** | 3 | 2 | 1 | | after | head `a237b10ee7`, run 03:07:39Z to 03:14:14Z | enumerated, 186 pages, frontier objectstack-ai#20765, 18,592 numbers | 1,058 | **0** | 0 | 0 | 0 | The whole-repo drop of 3 is exactly these sites: a site-by-site diff of the two JSON outputs has 3 findings gone (`dev-plugin.ts:1063`, `:1078`, `:1097`) and none added. The other three tallies (`resolves` 33,038, `resolves-as-pull-request` 1,984, `cross-repo-unjudged` 995) are equal in both runs. **Supplementary scan (test files, strings and files outside `src/` included).** Every `#N` token (two to six digits) in the package's 19 tracked files, `CHANGELOG.md` excluded, was probed by REST: 39 distinct numbers at base, of which 2 answer 404 in `src/` (`objectstack-ai#10035`, `objectstack-ai#10036`) and 1 outside it (`objectstack-ai#13176`, in `tsconfig.test.json`); `objectstack-ai#1020` is `cloud#1020`, cross-repo. Dead occurrences at base: 6 in `src/` comments (3 source, 3 test), 1 in a test string, 2 in `tsconfig.test.json`. After: 0 in comments, the test string and the two `tsconfig.test.json` lines unchanged (see Acceptance notes). A grep for the two numbers with no word-boundary operator, beside a control of the same shape (`objectstack-ai#3900` reads 6 lines of `dev-plugin.ts`), finds only those three lines left. ## Per-number table `git blame` at the base ties every one of the 6 lines to `7552e0337`, the commit that wrote them, and each anchor was read in its message and its diff, not only its subject. | number | sites (base line) | anchor: what it decided | |---|---|---| | `objectstack-ai#10036` | `dev-plugin.ts:1063`, `:1078`; `dev-plugin.test.ts:90`, `:127`; `dev-plugin-security-enforcement-warning.test.ts:53` | `7552e0337`: the "RBAC/RLS/masking are NOT enforced" warning stops probing the three `SecurityPlugin.init()` internals (`security.permissions`, `security.rls`, `security.fieldMasker`, which the spec contract names implementation internals) and asks the published `security` service instead, and asks it from `DevPlugin.start()`, after the child-start loop and beside the boot banner, since asking from `init()` would find it absent on every stack; the internal handles keep one use, telling "never loaded" apart from "loaded, then failed to start". Both halves of its squash message carry this number. Its own PR number (objectstack-ai#10092) answers 404 as well. | | `objectstack-ai#10035` | `dev-plugin.ts:1097` | `c1731d023`: `plugin-hono-server`'s `/auth/me/permissions` and `/me/apps` delegate permission-set resolution to the `security` service, and their degraded branches key on the published `security` service instead of `security.permissions` (its docblock "What absent now means, precisely"). The site's sentence says the same presence signal misled that endpoint and was cured "by this same move"; `objectstack-ai#10035` is that commit's own PR number, carried in its subject. | **How the lines read now.** `:1063` keeps `objectstack-ai#3900` and says `commit 7552e03 moved this check here from init()`; the `:1078` heading and the test-comment brackets name `commit 7552e03` where the number stood, with the decision spelled out in the surrounding prose they already carried; `:127` reads `(the two told apart since commit 7552e03)`; `:1097` reads `commit c1731d0 by this same move`. **Anchor checks.** Both cited shas match exactly one object (`git rev-parse --disambiguate`, count 1 each), are commits, have one parent, and are ancestors of `main` (`merge-base --is-ancestor` against `33e4a5609c`, exit 0 for both). The checkout is not shallow. Control legs: `44738f7af6` (the parent of `c1731d023`) exits 0 against the base; the negative control (the base as an ancestor of `7552e0337`) exits 1. **Numbers.** `objectstack-ai#10035`, `objectstack-ai#10036` and `objectstack-ai#10092` answer 404 by REST (probed 2026-09-30T02:43:04Z and again at 03:14:40Z). `objectstack-ai#3900`, kept on `:1063`, answers 200. ## Mechanical guard: no code token moves **H2 holds on the token reading; the emitted `dist` is NOT byte-identical, and the difference is exactly the two docblock lines.** **Token guard.** It compares the TypeScript parser's leaf tokens (TypeScript 6.0.3, `getChildren` walk, JSDoc nodes excluded) of the 3 touched files at base `33e4a5609c` and at `37eaf1647f` (the comment commit). Controls mutate the head text in memory only. - Real run: 6,653 base tokens, 0 files differing. - Comment-insertion control: 0 differing. - Code-insertion control: all 3 files differ. - String control (the first character of the first import specifier flipped in each file): all 3 files differ, first differing kind `StringLiteral`. - The script's own verdict: exit 0 (real 0 and every control as expected). All 12 changed lines in `src/` (6 out, 6 in) are `//` or `*` comment lines. **Emitted `dist`.** `pnpm --filter @objectstack/plugin-dev build` at base (before any edit, after its dependency closure) and at `37eaf1647f`. Of the 6 `dist` files, `index.js.map` and `index.mjs.map` have equal sha256; `index.js`, `index.mjs`, `index.d.ts` and `index.d.mts` differ, and `diff -r` shows exactly two changed lines in each: the `:1078` heading and the `:1097` line of the `warnIfNothingIsEnforcingSecurity` docblock. The `//` comment at `:1063` does not ship. So the published tarball carried both dead numbers, and now carries the commits. - Code-mutation control (`scripts/ablation-replace.mjs`, wrap mode, anchor `ctx.logger.info(' Discovery: /.well-known/objectstack');` hit 1 to 0, planted marker 0 to 1, blob `708af69f9b2a` to `b0b387f53d6a`; `scripts/ablation-dist-preflight.mjs` found the marker in `dist/index.js` and `dist/index.mjs`): `index.js`, `index.mjs` and both source maps differ from the head build. The blob was restored to HEAD `708af69f9b2a` with `git diff HEAD` empty, `dist` was rebuilt, the preflight in `--absent` mode reads the marker absent from all 6 files with a clean tree, and the 6 sha256 values equal the head build. - The whole-workspace build (below) left `plugin-dev`'s `dist` equal to the same 6 values. A raw scan of the 4 changed files for ASCII control bytes finds none (a positive probe on a scratch file with one such byte reads 1), and `check:nul-bytes` exits 0. ## Changeset **`patch` for `@objectstack/plugin-dev`.** The package publishes (`files` is `dist`, `README.md`, `CHANGELOG.md`), and the measurement above shows the rewritten docblock reaching four `dist` files. The changeset states comments only, with no behaviour change. `check-empty-changeset`, `check-changeset-no-major`, `check-adr-0087-registration` (1 non-breaking changeset seen) and `check-changeset-fixed` all exit 0. ## Gates (head `a237b10ee7`) This host has no `flock`, so `os-verify-lock.sh` ran in its declared unlocked mode. Its official wording, verbatim (printed by every run; the command line differs per run and is listed in the verdicts below): > **Declared narrowing — verification ran UNLOCKED.** `scripts/pm/os-verify-lock.sh` > could not take the shared verify lock on this host: no usable `flock`. The shared > verify lock is declared Linux-only (`flock` is util-linux, and a stock macOS does > not ship it), so the command below was run directly, without the lock — > a declared narrowing, not a silent one. No serialization guarantee held for this > run, nor for any sibling agent in this container while it ran. Its verdict line from each run (the closure build at base `33e4a5609c`; the head build at `37eaf1647f`; the whole-workspace build, the tests and the typecheck at this head): ```text os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 65s (1m05s) · declare it in the PR body · pnpm --workspace-concurrency=2 --filter '@objectstack/plugin-dev...' build os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 3s · declare it in the PR body · pnpm --filter @objectstack/plugin-dev build os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 97s (1m37s) · declare it in the PR body · pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*' --concurrency=2 os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 7s · declare it in the PR body · pnpm --filter @objectstack/plugin-dev exec vitest run --maxWorkers=2 os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 6s · declare it in the PR body · pnpm --filter @objectstack/plugin-dev typecheck ``` - **Build:** `plugin-dev` with its dependency closure (36 packages, the filter spelled with the package included), then the package, then the whole workspace, `turbo run build --filter=./packages/* --filter=./packages/*/* --concurrency=2`, 71 of 71 tasks. The tree was clean after each. - **Tests:** `vitest run --maxWorkers=2`: 9 files, 86 tests, all passed. - **Typecheck:** `pnpm --filter @objectstack/plugin-dev typecheck` (`tsc --noEmit`, then `check:test-typecheck` over `tsconfig.test.json`) exits 0. `--listFiles` under both configs reaches all 12 `src/` files, including the 9 tests and the 3 touched files. - **Spec artifacts:** not run. `origin/main` did not move while this branch was open (still `33e4a5609c`; the merge was a no-op), and this diff does not touch `packages/spec`. - **Lint:** the repo-wide `pnpm lint` (`eslint . --no-inline-config`) exits 0 at this head (2026-09-30T03:07:02Z to 03:07:32Z). - **Citation judging:** after merging `origin/main` (already up to date at `33e4a5609c`), `node scripts/check-issue-citations.mjs --base origin/main` judges 1 added citation (`objectstack-ai#3900`), which resolves (exit 0). - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derived 62 families from the 4 changed paths. All 62 exit 0 in one pass at this head, and `--ran` with the exit-coded record reads "62 derived, 62 run, 0 NOT-MEASURED, 0 UNRUN" (a derived zero). Among them: `check:issue-citations`, `check:doc-authoring`, `check:nul-bytes`, `check:published-files`, `check:cross-package-test-inputs`, `check:dts-closure`, `check:dual-build-cjs-loads`, `check:type-check-debt`, `check-empty-changeset`, `check-adr-0087-registration`. - **Artifact rosters:** 36 of the 39 non-self-test roster rows exit 0 at this head, among them `check-changeset-fixed` and the three others the derivation marks as keeping their roster under one of this diff's paths (`check:authz-resolver`, `check:error-code-casing`, `check:filter-alias-parity`). The other three need a pull request's context; they are run against this PR once it exists and reported on the card. The 18 self-test-only rows grade their checkers' fixtures and cannot judge this diff. ## Hypotheses (measured first) - **H0 holds.** At base `33e4a5609c` the filtered census answers 3 sites on 3 lines, 2 numbers, 1 file, as on the seat's `0be898499f`. The whole-repo count is 1,061. - **H1 holds.** After the rewrite, the filtered census answers 0 for `packages/plugins/plugin-dev`. No site was left for an open PR (the file lists of all 8 open PRs were read at 2026-09-30T02:45:10Z: only the Version Packages PR objectstack-ai#20639 touches the package, in `CHANGELOG.md` and `package.json`) or for an unfound anchor. - **H2 holds, by the token reading, not the `dist` reading.** The parser leaf-token diff of all 3 touched files is empty with its controls firing. The emitted `dist` is not byte-identical, and it is not meant to be: its only difference is the two docblock lines, which is why the changeset ships. ## Acceptance notes - **Strings, the form-D stage.** One dead number remains in a string literal: the `describe` title at `dev-plugin-security-enforcement-warning.test.ts:121` (`objectstack-ai#10036`). It stays on the card for its form-D stage; no string moved here. It is not assertion text. The same title is quoted in three recorded CI-log fixtures under `scripts/fixtures/merge-queue-triage/`; those are captured logs read by `check-merge-queue-triage-outcome.mjs`, so a later rename of the title does not need them edited. - **Outside `src/**`:** `tsconfig.test.json:3` and `:56` cite `objectstack-ai#13176`, which answers 404. The same number sits in the `tsconfig.test.json` of 13 `packages/plugins/*` packages (17 `tsconfig*.json` files under `packages/` in all), outside the census's declared surface; stage 10 (PR objectstack-ai#20741) recorded its own copy for a later stage of this card. Every other citation in the package outside `src/` answers 200 (`vitest.config.ts`, `README.md`, `tsconfig.json`, `package.json`); `CHANGELOG.md` is release-owned and was not read as a site. - **`origin/main` did not move.** It read `33e4a5609c` at worktree creation and at every later fetch, so every run above is against the same base and nothing needed rerunning after the merge. ## Deviations - **The two builds inside the code-mutation control** (the mutate leg and the restore leg) ran directly, not through `os-verify-lock.sh`. On this host that wrapper runs unlocked anyway, so nothing was serialized either way. - **The dependency-closure build** used the filter `'@objectstack/plugin-dev...'` (package plus its dependencies) rather than the closure-only `^...` spelling; it built the same closure and the package in one run. - **Commit trailers** are AGENTS.md's model-free pair (`Claude-Session` plus `Co-authored-by: Claude`), and the pre-push trailer check passed on every push. The harness's attribution reminder asked for a model-named trailer and a different PR footer, and AGENTS.md overrides it. --- _Generated by [Claude Code](https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289)_ --------- Co-authored-by: Jack Zhuang <50353452+hotlong@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
This branch was successfully deployed
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.
Runtime hits
no such table: sys_presencebecause the object was never defined or registered. Per system architecture,sys_-prefixed objects belong to their domain package — presence belongs toservice-realtime.Changes
SystemObjectName.PRESENCE— New'sys_presence'constant in@objectstack/spec/systemSysPresenceobject definition —packages/services/service-realtime/src/objects/sys-presence.object.tswith fields aligned toPresenceStateSchemaprotocol (user_id,session_id,status,last_seen,current_location,device,custom_status,metadata)RealtimeServicePlugin.init()registers viaapp.com.objectstack.service.realtimeconvention (same pattern asMetadataPlugin,AIServicePlugin)SysPresenceexported from@objectstack/service-realtimeroot