Skip to content

runtime-services/index.mdx's chapter list omits services.sms and its Source-of-Truth list carries a Security entry the chapter has no page for #9604

Description

@os-steve

Found while sweeping every pointer on content/docs/kernel/runtime-services/index.mdx for #9588 (which fixes a different line on the same page — the Audit canonical source). Reported rather than ridden along: #9588's dispatch pinned the fix to the audit pointer, and both drifts below reach past this file.

What is wrong

The page carries two lists that disagree with each other, with meta.json, and with the pages on disk.

1. The chapter list omits services.sms. Lines 19-25 enumerate seven slots:

- `services.data`
- `services.sharing`
- `services.audit`
- `services.queue`
- `services.email`
- `services.settings`
- `services.storage`

services.sms is absent — yet content/docs/kernel/runtime-services/sms-service.mdx exists, meta.json lists sms-service in pages, the same page's own Source-of-Truth list (line 43) has SMS: packages/spec/src/contracts/sms-service.ts, and the slot is really registered: packages/services/service-sms/src/sms-plugin.ts:181 runs ctx.registerService('sms', this.service), with SmsService implements ISmsService (sms-service.ts:95). So the one list on the page that reads as "what this chapter documents" is the only place the service is missing.

content/docs/kernel/index.mdx:17-21 omits it too, which is why this is filed rather than patched into #9588: fixing only the runtime-services index would leave the two index pages newly disagreeing where they currently agree.

2. The Source-of-Truth list has a Security row the chapter does not document. Line 39 reads Security: packages/spec/src/contracts/security-service.ts, but services.security appears in neither the chapter list nor meta.json, and no security-service.mdx exists under runtime-services/. The slot itself is real (packages/plugins/plugin-security/src/security-plugin.ts:1157), and the contract file is the right one — it names its own registration in its header. The row simply points at a service this chapter never introduces, so the list's stated purpose ("Each page links the canonical TypeScript source used to derive signatures") does not hold for it: there is no page.

Why it is worth a card

Both are small, but they are the index — the one page whose job is to be a trustworthy map of the chapter. A reader looking for SMS concludes the chapter has no SMS page and goes hunting; a reader following the Security row lands on a contract with no page explaining the accessor. Nothing checks either direction: check:docs-audit-scope confirms which pages are in audit scope, not that an index enumerates them.

Directions, not a recommendation

  • Add services.sms to both index pages' lists in one change, so they stay in step.
  • For Security: either give it a page in this chapter, or move the row to wherever services.security is actually documented, or drop it. Which one depends on whether services.security is meant to be a documented runtime accessor at all — worth a maintainer read rather than a guess.

Refs: #9588 · #9534 · PR #9587

Activity

  1. os-steve commented on Aug 18, 2026

    @os-steve
    CollaboratorAuthor

    Claiming this card.

    • Session: session_01XqDQYVU5smx29ts9pAErja
    • Branch: claude/issue-9604-runtime-services-index
    • Repo: objectstack-ai/objectstack

    Scope per dispatch: SMS half only (both index pages, one change). The Security row is measured and reported, not edited — it is a maintainer product-surface call. Also running a full registerService sweep and reading check:docs-audit-scope to answer whether any gate could have caught this.

    Files I expect to touch: content/docs/kernel/runtime-services/index.mdx, content/docs/kernel/index.mdx, .changeset/*.md (plus possibly a new patrol script under scripts/, to be confirmed after sizing).

    Generated by Claude Code


    Generated by Claude Code

  2. os-steve commented on Aug 18, 2026

    @os-steve
    CollaboratorAuthor
    {
      "issue": 9604,
      "status": "done",
      "branch": "claude/issue-9604-runtime-services-index",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/9634",
      "premise_still_valid": true,
      "summary": "SMS half implemented as directed: `services.sms` added to BOTH index lists in one change (runtime-services/index.mdx chapter list and kernel/index.mdx table), placed by the derived convention rather than appended -- the chapter list is exactly meta.json's `pages` order minus sms, so the bullet belongs between email and settings. Every card claim re-verified against main at e8dba8a8a; all still hold, including the three line-precise citations (sms-plugin.ts:181, sms-service.ts:95, security-plugin.ts:1157) which are exact and unchanged. Second commit builds the H1 gate: `pnpm check:runtime-services-index` holds meta.json `pages`, the chapter list, the kernel/index.mdx table and the chapter list's ORDER to the pages on disk, wired into lint.yml beside its closest sibling check:quick-reference-counts. The Security row was measured and NOT edited; PR body carries both findings. Note: the platform appended a second signature footer to the PR body on creation -- platform behavior, not another actor.",
      "tests": "All at final commit 88a3e3659 (clean tree), gate family re-derived from actual changed paths with `node scripts/pm/dispatch-gates.mjs` -- which discovers the new gate from lint.yml on its own, confirming the CI wiring is real. Union all green (13): check:runtime-services-index, check:nul-bytes, check:docs-audit-scope, check:docs-redirects, check:role-word, check:node-version, check:required-contexts, check:workflow-status-functions, check:shard-attestation, and spec check:empty-state / check:variant-docs / check:liveness / check:strictness-ledger. REVERSE VERIFICATION, predicted direction RED and observed RED: reverting only the two doc files to origin/main (fix already committed, so restore was `git checkout HEAD -- ...`) gives exit=1 with exactly the two drifts the card names -- 'chapter list omits `services.sms`' and '`services.*` table has no row for `services.sms`' -- and exit=0 after restore. New gate's --self-test: 11 assertions on a synthetic tree, every limb (chapter list, kernel table, meta.json, order, href, title premise, empty tree) observed FAILING and observed silent. No build/test needed (docs + node scripts); pnpm install run under flock /tmp/os-heavy-verify.lock. skip-changeset label applied and CONFIRMED BY READ-BACK as the union ['size/m','skip-changeset'] -- nothing publishable is touched (@objectstack/docs and @objectstack/spec-monorepo are both private).",
      "open_questions": [
        {
          "question": "H2 VERDICT -- the Security row is outcome 2, 'documented nowhere', which the card itself calls a bigger gap than #9604 states. Measured: `services.security` has ZERO hits in all of content/docs/; the contract path appears in docs exactly once, in the row itself; no security-service.mdx exists anywhere. The two near-misses do not close it -- kernel/contracts/index.mdx:44 documents the INTERFACE ISecurityService (contracts chapter, not the accessor surface), and permissions/explain.mdx:53 shows kernel.getService('security') for one task in another chapter. The slot is real (security-plugin.ts:1157). Filed as #9629. Not edited, per ruling 1.",
          "options": [
            "A -- give it a page in this chapter (plus meta.json, both index lists); correct if services.security is meant to be a public runtime accessor. Largest option; the contract surface is wide.",
            "B -- move the row to where services.security is documented; cheapest in principle, but the measurement says there is NO destination page, so it only works together with deciding which chapter should own it (permissions/ is the nearest neighbour).",
            "C -- drop the row; right if the accessor is internal and callers are meant to reach security via permissions/ docs and kernel.getService rather than a documented services.* slot."
          ],
          "recommendation": "Maintainer decision, deliberately not made here. I did NOT encode any of the three in the new gate either -- the Source-of-Truth list is explicitly out of the gate's scope, because an allowlist entry for Security would be answer C in gate form. Once decided, extending the gate to that list is a small follow-up."
        }
      ],
      "out_of_scope_findings": [
        "filed as #9629: `services.security` is documented nowhere under content/docs/ while the chapter advertises a canonical source for it -- the H2 verdict, needs a maintainer product-surface decision (unlabeled, left for PM triage)",
        "filed as #9630: `services.storage` is the only documented accessor whose registry slot has a different name (`file-storage`, canonical in CoreServiceName; no registerService('storage') exists anywhere), and the page never says so -- a reader following the chapter's own ctx.getService(...) instruction gets nothing back. Judgment attached re which namespace is authoritative, so recorded not patched (label: finding)",
        "H3 MATRIX (no card needed -- this is the sweep result): every production registerService name matched against the chapter. SMS was the ONLY omission of its shape; after this PR all four enumerations (disk / meta.json / chapter list / kernel table) agree exactly on all 8 accessors. 7 of 8 map 1:1 to a same-named slot -- data (objectql/plugin.ts:312), sharing (sharing-plugin.ts:494), audit (audit-plugin.ts:117, multiline call), queue (queue-service-plugin.ts:82), email (email-plugin.ts:370), sms (sms-plugin.ts:181), settings (settings-service-plugin.ts:130); storage is the lone exception, see #9630. The other 43 registered slots are internal plumbing with no page and no claim to one.",
        "H1 ANSWER (built, not filed): NO existing gate could have caught this. check:docs-audit-scope derives WHICH pages the docs-accuracy audit covers by shelling out to affected-docs.mjs --all and never reads an index page -- the card's claim is exactly right. Nothing else in the repo reads runtime-services/meta.json either (only the release-notes collectors touch any meta.json). Cost judged contained: the precedent check-quick-reference-counts.mjs guards the identical defect class (hand-written docs index vs the real directory) and CI wiring is one run: line in lint.yml. So it was built rather than filed."
      ]
    }

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions