Skip to content

docs(releases): amend the released "absent security admits analytics reads" sentences to the measured deny - #22296

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-22279-released-text-correction
Oct 8, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-22279-released-text-correction

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #22279

Clause-②: no

This is the docs-only half of #22279. It amends release-owned text and nothing else. The four service-analytics source comments are in a separate PR, on branch claude/issue-22279-analytics-source-comments. The card stays open until both PRs have merged.

Route: amend each entry in place and add a dated erratum inside it

AGENTS.md, Documentation Guardrails, the packages/*/CHANGELOG.md row: "Factual error in a released entry → amend that entry in a dedicated docs-only PR, ⛔ never an erratum in a later entry and never a rider on code changes". The content/docs/releases/ row: "Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on code changes."

Triage asked this PR to say which route it took: "⛔ No silent rewrite of a published CHANGELOG line, if that process forbids one; the PR states which route it took."

The route: each false passage is corrected inside the entry that published it. Each amended entry also gets one dated line at its own end, in the form *Erratum, 2026-10-08 — this entry said "…". … (Corrected after publication, #22279.)*. That line quotes the wording that shipped. Earlier in-place amendments in these files use the same shape, for example 5b481e2 and 576afc1 in packages/spec/CHANGELOG.md, and the bulk-callers bullet on the 17.0 release page. So nothing is rewritten silently. The shipped wording is quoted in the entry, kept in the published tarballs and kept in git history. No later entry is written, and no changeset is added (see below).

Why: maintainer ruling B on #22235

Ruling 6056824332 (「同意」, 2026-10-08), verbatim: "B — deny, as measured, becomes the declaration. On a deployment with no security service the analytics read bridges deny, fail-closed, as they do today; the bridge comments and the header of admission-bridge-resolution.test.ts say so; the "absent admits" sentence in the released text is corrected by a docs card, since that text is release-owned."

The sentences were false when they were published, not only now. Measured on the published tarballs (npm pack, unpacked into a scratch directory):

  • @objectstack/core 17.5.0 and 17.6.0: the context getService of both ObjectKernel and LiteKernel throws [Kernel] Service 'NAME' not found for a name that was never registered.
  • @objectstack/service-analytics 17.5.0 and 17.6.0: the object-level bridge catches that throw as unusable and denies. Its if (resolved.kind === "absent") return true; line is reached only when the lookup returns nothing. The row-scope bridge does the same and throws readScopeUnresolvedError. In 17.6.0 the field-level bridge throws as well. In both releases assertReadAdmitted runs before resolveReadScopes.

The new text states what was ruled: on a deployment with no security service the bridges deny, fail-closed. ⛔ It does not say that the ABSENT branch denies. ABSENT is described as a state reached only by a context that answers the lookup with nothing, and no in-repo kernel does that. This matches the bridge comments that PR #22276 landed on main (58707166f).

What changed

Line positions are at base 58707166f. These files have not changed since 3513ac77, where the card read its positions.

File Entry Passage Listed on the card?
service-analytics/CHANGELOG.md 17.6.0 1571aed :583-584 "applies no field-level check, as on the data API" yes
same 17.6.0 5f6b63a :645-647 "applies no object-level check, as on the data API" yes
same 17.6.0 ce4e205 :821 "the field-level read gate, which stands down with no security service" added
same 17.6.0 ae1e950 :1211-1213 "A deployment with no security service, and an object …, apply no field-level check" yes
same, and the three lockstep copies 17.5.0 041d9fd :1917-1919 BREAKING banner, "Nothing that was already admitted becomes refused except the requests GET /data/OBJECT refuses" added
same, and the three lockstep copies 17.5.0 041d9fd :1926 "keeps its previous analytics behaviour by design" yes
same, and the three lockstep copies 17.5.0 041d9fd :1930 "an ABSENT security service admits (… keeps a deployment shipping no plugin-security working as before)" yes
same 17.5.0 5d12b16 :1936 "ABSENT admits, THROWING and METHOD-LESS deny" yes
same 17.5.0 5d12b16 :1952 ABSENT row, "a legitimate configuration … ⛔ Deliberately not tightened" yes
same 17.5.0 5d12b16 :1955 "and no deployment with none, changes behaviour by so much as a byte" added
same 17.5.0 54b3d1d :2773 "a deployment with NO security service still runs unscoped exactly as before" yes
content/docs/releases/v17/17-5.mdx object read grant bullet :482-486 "keeps its old behaviour and warns at init" yes (:482-484)

The lockstep copies are plugin-security/CHANGELOG.md (:1666-1668, :1675, :1679), spec/CHANGELOG.md (:13365-13367, :13374, :13378) and verify/CHANGELOG.md (:562-564, :571, :575). After the edit the 041d9fd entry is still byte-identical in all four files: 27 lines each, sha256 prefix a7ff1b99f2de9992. The four copies were also identical before the edit.

Each amended entry gets one erratum line: seven in service-analytics/CHANGELOG.md, one in each lockstep copy and one in the release-page bullet. On the release page, the migration line also gains the remedy for a deployment with no security service: register one, or supply admitObjectRead.

The three added passages (bounded in-place fix, declared here)

The card did not list these. Each makes the same claim and sits inside an entry this PR amends, or in the same file:

  • :1917-1919 (all four copies): on a kernel with no security service, analytics reads that 17.4 served became refused, while /data still serves them. Left alone, the banner would contradict the amended :1926 three paragraphs below it in the same entry. One clause is added.
  • :1955: the same entry as :1936 and :1952, with the same claim.
  • :821: the claim :1211 makes, in another 17.6.0 entry of the same file.

All three meet the four conditions: the same defect class as the card, a mechanical rewording to a shape the ruling already fixed, a file this card already holds, and the same gates. Reviewer: if you want any of them out, say which and it comes back in a patch round.

Not changed, on purpose

  • The ADR-0087 disposition marker of the 041d9fd entry (:1912) is an HTML-comment line that does not render. Its prose also says the narrowing is "the same verdict GET /data/OBJECT already returns". It is the machine-read disposition record, its category (not-required) does not change, and it is left as published.
  • :1930 still says the plugin "warns loudly at init when no security service is registered". That stays because 17.5.0 and 17.6.0 did print that warning at init (measured in both tarballs). Only what the bridge then does is corrected.
  • :1244 says the 17.6.0 member gate refuses "in every tier — including a deployment with no security service". That is true, so it stays. :1948 describes the value the pre-fix code produced for an absent service. That is history, so it stays too.
  • Not here, per the card: the runtime UNUSABLE log text in plugin.ts and read-admission.ts, and any change in behaviour.

Changeset: none, labelled skip-changeset

This follows 5b481e2 and 576afc1. CHANGELOG.md is in each package's files[], so the next tarball ships the amended text. A changeset is still the wrong tool here. It would compile the correction into a new entry under a later version. That is the "erratum in a later entry" the guardrail rules out, and this PR changes no package code. changeset version prepends to these files and keeps the amended entries. All four packages are in the single fixed group of .changeset/config.json, and 101 changesets are pending on main, so the next release carries the corrected entries.

Verification (head 2bd53e98a)

  • Gates: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derives 85 commands for this diff. Each was run with its exit code captured before any pipe. 79 exit 0. 6 are NOT MEASURED: each exited 3, PREREQUISITE NOT MET, because it reads build output this docs-only worktree does not hold.
    • pnpm --filter @objectstack/spec run check:skill-examples: its client-SDK half needs a 36-package build of the @objectstack/client and @objectstack/client-react closure.
    • pnpm check:i18n: needs the CLI closure, 61 packages.
    • pnpm check:dts-closure, pnpm check:dual-build-cjs-loads, pnpm check:lean-entry-closure and pnpm check:sourcemap-no-sources-content: need a full workspace build.
    • This narrowing is declared. The diff changes no source byte. A build compiles src/ and never reads CHANGELOG.md or .mdx. CI's Lint & Repo Gates runs these gates after its own closure build.
  • node scripts/pm/dispatch-gates.mjs --ran gives: "85 derived, 79 run, 6 NOT-MEASURED, 0 UNRUN."
  • The @objectstack/lint closure (lint, formula, spec, sdui-parser) was built under the verify lock first, so these gates were measured rather than refused: check:docs ("225 generated files in sync"), check:doc-formula-expressions, check:doc-security-posture and check:docs-transcript-drift, all exit 0. The build left the working tree clean.
  • Named results: check:nul-bytes scanned 10245 tracked files and found no raw control bytes. check:release-notes, check:release-page-status, check:doc-authoring and check:issue-citations all exit 0. A separate control-byte grep over the five files matches nothing.
  • Lint: eslint --no-inline-config --format json over the 5 files reports 5 files, each "File ignored because no matching configuration was supplied". No config object matches .md or .mdx, so pnpm lint has nothing to judge here.

Acceptance notes

  • Two test titles say "no security service" where they mean a test double that answers the lookup with nothing. admission-absence-report.test.ts:199 names its describe "no security service ever registered (the ABSENT resolution)". caller-member-column-reference-gate.test.ts:109 labels a tier "no security service (no field reader wired)". Test names are outside a docs-only PR and outside a comments-only PR. Noted, not filed. Carrier: none.

Generated by Claude Code

claude added 2 commits October 8, 2026 12:39
…reads" sentences to the measured deny

Amends, in place, the released CHANGELOG entries (service-analytics 17.5.0 and
17.6.0, and the 041d9fd lockstep entry in plugin-security, spec and verify)
and the v17.5 release page. Each said a deployment with no security service
keeps its analytics behaviour, applies no object- or field-level check, or
runs unscoped. On the published 17.5.0 and 17.6.0 tarballs, ObjectKernel and
LiteKernel throw on a never-registered `security` service, so the analytics
bridges take the UNUSABLE branch and refuse the query, fail-closed.

Docs-only. No code, changeset, or other entry moves.

Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q
Co-authored-by: Claude <noreply@anthropic.com>
… in-place amendment shape

Each amended CHANGELOG entry, and the v17.5 release-page bullet, gains one
dated erratum line at its own end. It quotes what the entry said and says
the sentence was false when published. This is the shape the earlier
in-place amendments in these files use, so the correction is not a silent
rewrite and stays inside the entry it corrects.

Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the size/m label Oct 8, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 8, 2026
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Oct 8, 2026
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 4 changed file(s) yielded no anchor (packages/plugins/plugin-security/CHANGELOG.md, packages/services/service-analytics/CHANGELOG.md, packages/spec/CHANGELOG.md, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 4 changed package(s)).

What this run could not see
  • 4 changed file(s) yielded no anchor (packages/plugins/plugin-security/CHANGELOG.md, packages/services/service-analytics/CHANGELOG.md, packages/spec/CHANGELOG.md, …) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 143 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 4578c56e65c1f50f04da9259579091272d319558 → packageMentionDocs.

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 37787288895 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

分类:failure —— 按下面的日志分诊。

失败的 job(日志抽取,best effort):

  • Test Core (6/6) — 失败步骤: Check this shard's timing drift(日志不可读,点进 job 看)

↳ 失败原因 是判读的关键:超时(Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言(AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

⚠️ 断言这一侧有一类例外,判据是断言在测什么,不是它是不是 AssertionError。 断言的对象是产品行为(一个值、一个形状、一次拒收)⇒ 照上面读:真实的行为改变,去查,⛔ 不要重排掉;
断言的对象是这次实验自身的有效性前提(跑完的耗时、负载下的先后、任何只在时间预算内才成立的条件)⇒ 它跟超时是同一类,同样对负载敏感,重排一次是合法的判别手段。
识别是机械的:断言的消息或它比较的值本身点名了一段时长、一个时间戳、一个耗时计数。实测过的一对 —— AssertionError: SecurityPlugin.init() ran: expected false to be true 测的是产品行为(真回归);
AssertionError: this run took over a second, so second-precision stamps could have differed too: expected 1006 to be less than 1000 测的是实验前提:它守护的那条不变式当时是绿的,同一个 head 原样重排一次即成功。
穿着 AssertionError 外衣的时间测量,仍然是时间测量。(⛔ 这只改「怎么读一次红」,不改「哪些测试可以重排」——后者由别处管。)

跨 PR 相同签名(24h,按失败测试文件聚合):

  • ⚠️ 本次没有可用的聚合签名(日志里没有能解析出测试文件名的 FAIL 行)—— 这不是「没有同签名的其他 PR」,是这一轮没测到。跨 PR 聚合本次不可用,请手工比对其他 PR 的同类评论。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 7 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

Merged via the queue into main with commit 98cce87 Oct 8, 2026
41 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-22279-released-text-correction branch October 8, 2026 14:40
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 9, 2026
… a deployment with no security service (objectstack-ai#22299)

Part of objectstack-ai#22279

Clause-②: no

This is the source-comment half of objectstack-ai#22279: comments only, plus the patch
changeset their published text needs. The release-owned text is in the
docs-only PR objectstack-ai#22296. The card stays open until both PRs have merged.

## Why

Maintainer ruling B on objectstack-ai#22235 (`6056824332`, 「同意」, 2026-10-08),
verbatim: "**B — deny, as measured, becomes the declaration.** On a
deployment with no security service the analytics read bridges deny,
fail-closed, as they do today; the bridge comments and the header of
`admission-bridge-resolution.test.ts` say so; the "absent admits"
sentence in the released text is corrected by a docs card, since that
text is release-owned."

PR objectstack-ai#22276 (`58707166f`) rewrote the bridge comments in `plugin.ts` and
the test header to that ruling. The comments here are the ones its
acceptance notes listed outside its fence. Each one equated "no provider
wired" with "a deployment with no security service" and said such a
deployment keeps its analytics behaviour. Through
`AnalyticsServicePlugin` a provider is always wired, either the host's
own or the bridge. On `ObjectKernel` and `LiteKernel` the lookup of a
`security` service that was never registered throws, so the bridges take
UNUSABLE and refuse the query, fail-closed.

The new text follows the `plugin.ts` wording on `main`. ⛔ It does not
say the ABSENT branch denies. ABSENT is described as reached only by a
context that answers the lookup with nothing (the package's test doubles
do, and no in-repo kernel does). Whether ABSENT itself should deny is
not ruled.

## What changed (comments only)

Line positions are at base `58707166f`.

| File | Site | Listed on the card? |
|---|---|---|
| `read-admission.ts` | module header, *Fail direction*, `:51-65`. The
ABSENT bullet is replaced by three bullets: the declared deny on a
deployment with no security service, the ABSENT context, and a host that
constructs `AnalyticsService` with no provider. The lead-in "but closed
is a claim about a WIRED provider" goes. | yes (`:59-65`) |
| `analytics-service.ts` | `AnalyticsServiceConfig.admitObjectRead` doc,
`:842-845` | yes |
| `analytics-service.ts` | `AnalyticsServiceConfig.getReadableFields`
doc, `:862-866` | yes |
| `analytics-service.ts` | `assertReadAdmitted` doc, `:1899-1901` (the
card's `:1897-1899`) | yes |
| `field-read-admission.ts` | `assertCallerMembersJudgeable` header,
`:338-341` | yes (`:339-341`) |
| `analytics-service.ts` | the `[objectstack-ai#20917]` field-level read gate doc,
`:1922` "A no-op when no provider is wired (no security service)". It
documents `assertFieldsReadable` but sits detached, directly above the
member-shape gate's doc. | **added** |
| `analytics-service.ts` | `assertCallerMembersResolvable` doc, `:1935`
"that gate is a no-op with no security service" | **added** |
| `analytics-service.ts` | `assertDatasetFieldsJudgeable` doc, `:2061`
"which stands down with no security service" | **added** |
| `read-scope-refusal.ts` | `readScopeUnresolvedError` doc, `:96-99`: "a
deployment with no security service … is reported loudly at init, and it
must keep running unscoped exactly as before" | **added** |

### The four added sites (bounded in-place fix, declared here)

The card listed four sites, taken from PR objectstack-ai#22276's acceptance notes. A
census of the package's `src/` for the same claim, `git grep -n -i 'no
.?security.? service'` outside `__tests__`, found four more. Three are
in `analytics-service.ts`, a file this card already holds. The fourth is
the row-scope sibling of the read-admission header. All four meet the
four conditions: the same defect class as the card, a mechanical
rewording to a shape the ruling already fixed, the same gates, and no
other claim on the file (`read-scope-refusal.ts` is in none of the 12
open PRs' file lists, which were read during this run before the edit).
Leaving them would keep the claim alive twenty lines below the doc this
PR corrects. Reviewer: if you want any of them out, say which and it
comes back in a patch round.

## Proof that only comments moved

For each of the four files, `ts.transpileModule` with `removeComments:
true` gives byte-identical output for the base file and for this head:

```
read-admission.ts        base=8a4829c31e94d58c/1351   head=8a4829c31e94d58c/1351
analytics-service.ts     base=8dd74af6788b7660/65291  head=8dd74af6788b7660/65291
field-read-admission.ts  base=9be45d2722f380cd/5145   head=9be45d2722f380cd/5145
read-scope-refusal.ts    base=badef6b1c177459d/233    head=badef6b1c177459d/233
```

(sha256 prefix / bytes.) Positive control: the same comparison over
`read-scope-refusal.ts` with `err.status = 500` changed in memory to
`501` reports the stripped outputs as different.

## Changeset: `patch` for `@objectstack/service-analytics`, not
`skip-changeset`

AGENTS.md: published means what `files[]` ships, and this package ships
`["dist","README.md","CHANGELOG.md"]`. After a rebuild of the package
(under the verify lock), the edited JSDoc is in the published output:

- "That is not a deployment with no security service" (the two
`AnalyticsServiceConfig` docs) is in `dist/index.d.ts` and
`dist/index.d.cts`.
- "without `admitObjectRead`. `AnalyticsServicePlugin` always wires one"
and "no-op with no field reader wired" (class-member docs) are in all
four of `dist/index.{js,cjs,d.ts,d.cts}`.
- "a deployment that registers NO security service denies" (the module
header) is in `dist/index.d.ts` and `dist/index.d.cts`.
- Control for that reading: the `read-scope-refusal.ts` phrase "their
lookup throws on the never-registered name" is in 0 files, because a
non-exported function's doc is not emitted. A runtime string from
`plugin.ts` is in 2 files.

The published `@objectstack/service-analytics@17.6.0` tarball carries
the old sentences in the same files. "the deployment has no security
service, which" and "keeps its pre-existing analytics behaviour" are in
its `index.d.ts` and `index.d.cts`. "A no-op when no provider is wired:
that is a deployment with no security" is in all four. So this diff
changes published bytes and takes a `patch`:
`.changeset/22279-analytics-absent-security-comments.md`.

This differs from PR objectstack-ai#22276, which carried `skip-changeset`. Its
`plugin.ts` comments sit inside a function body, measured at 0 files
under `dist/`. Here the comments are on an exported interface and on
class members, which the build keeps.

## Verification (head `7fb9cee98`)

- `@objectstack/service-analytics` was built under the verify lock: its
dependency closure, then the package itself. `check-dts-emitted` found
"2/2 declared declaration file(s) present".
- `pnpm --filter @objectstack/service-analytics typecheck` exits 0.
- `pnpm --filter @objectstack/service-analytics exec vitest run
--maxWorkers=2`: "Test Files 180 passed (180)", "Tests 4443 passed | 262
skipped (4705)". These are the same counts PR objectstack-ai#22276 recorded.
- Gates: `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derives **58** commands. Each was run with
its exit code captured before any pipe. **57 exit 0.** **1 is NOT
MEASURED**: `pnpm check:dual-build-cjs-loads` exited 3, `PREREQUISITE
NOT MET`, because 65 workspace packages have no `dist/` in this
worktree. A targeted substitute reading: `require('./dist/index.cjs')`
of this package loads, with 17 exports and `AnalyticsServicePlugin` a
function. `dispatch-gates --ran` gives: "58 derived, 57 run, 1
NOT-MEASURED, 0 UNRUN."
- Named results: `check:dts-closure` reports 75/75 declaration files
across 15 built packages. `check:sourcemap-no-sources-content` reports
105 maps across 15 packages, none embedding source.
`check:published-files`, `check:nul-bytes` (10246 tracked files, no raw
control bytes), `check:doc-authoring`, `check-empty-changeset` ("1
declaring changeset(s) added") and `check:lean-entry-closure` all exit
0. Locally, `check-changeset-no-major` reads its clause-② level axis as
not applicable, because there is no `pull_request` payload. CI reads
this body's `Clause-②: no`.
- Lint, narrowed: `eslint --no-inline-config --format json` over the 4
touched source files reports 4 files, 0 errors and 0 warnings. The
config's only global ignores are `node_modules`, `dist`, `build`,
`.next` and `.turbo`, so all 4 files are in scope. The config never
enables type-aware linting (no `parserOptions.project` in
`eslint.config.mjs`), so this diff cannot change the verdict on a file
it does not touch. The repo-wide `pnpm lint` is left to CI.

## Acceptance notes

- Not here, per the card: the runtime UNUSABLE log text ("A security
service is wired on this deployment") in `plugin.ts` and
`read-admission.ts`, and any change in behaviour.
- Two test titles still say "no security service" for a double that
answers the lookup with nothing. One is the describe at
`admission-absence-report.test.ts:199`, the other the tier label at
`caller-member-column-reference-gate.test.ts:109`. Test names are
outside this comments-only fence. Noted, not filed. Carrier: none.

---
_Generated by [Claude
Code](https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants