Skip to content

test(platform-objects): sweep code-shipped managed objects through the apiMethods affordance rule (#7934) - #8314

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-7934-managed-api-methods-registry-sweep
Aug 13, 2026
Merged

test(platform-objects): sweep code-shipped managed objects through the apiMethods affordance rule (#7934)#8314
os-zhuang merged 2 commits into
mainfrom
claude/issue-7934-managed-api-methods-registry-sweep

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes#7934

os lint walks an authored stack. This repo's own object definitions ship as code (packages/**/*.object.ts), so they were never walked by object/managed-api-method-unaffordable — the rule #7521 wrote. This adds the sweep that closes that gap, by importing the exported predicate rather than re-deriving it.

The measurement came first, and it is green

The card was explicit that it is unknown whether this repo has any live divergence, and that the fix must not be scoped before the measurement says there is one. Measured on origin/main:

object files swept76
objects loaded76
in scope (managed + non-empty apiMethods)51
findings0

So there is nothing to fix. This lands as regression insurance: the divergence class does not exist here today, and this is what stops it arriving unannounced. No object definition is modified by this PR.

The rule is reused, never copied

validateManagedApiMethods is imported from @objectstack/lint (a new devDependency of platform-objects), which delegates to checkManagedApiMethodAffordances in @objectstack/spec/data — the same predicate objectql's registry calls when it strips the verb. This PR adds no affordance table and no verb list; packages/lint is not touched.

Why the sweep is repo-wide

#7934 names platform-objects and metadata-core. Measured, those hold 30 of the 51 in-scope objects; the other 21 live in plugin-security, plugin-approvals, plugin-audit, plugin-sharing, service-messaging, service-realtime and service-automation — same class of object, same registry, equally unwalked by os lint.

Scoping the sweep to the package it lives in would repeat a failure this repo has already paid for twice: the #3391 bulk audit was scoped to platform-objects and missed eight objects elsewhere (#3745), and #7802 records it as "an audit whose SCOPE was a package name while the gap lived in packages nobody thought to open".

The objects are imported rather than regex-matched, unlike the two existing repo-wide object walkers, because this verdict resolves affordances through resolveCrudAffordances — a regex would have to re-derive that layering, and a second copy of the table is exactly the drift the rule detects. That is affordable because every one of these files imports from @objectstack/spec and nothing else.

Anti-vacuity

A sweep over an empty or wrongly-filtered set passes triumphantly and proves nothing, so:

Reverse verification (direction predicted before running): adding update to sys_audit_log's apiMethods — in plugin-audit, deliberately outside the card's named surface — turned the verdict red naming that exact file, export and rule, and took the red arm from 1 finding to 2; the two population cases stayed green. Restored from the commit, git status clean.

The two non-test changes, and why they are here

  • scripts/check-cross-package-test-inputs.mjs + turbo.json — a test whose real inputs are wider than its package is invisible to both turbo's affected-set and its task cache, so it goes red on main while every PR reports green (main is red for every PR that touches packages/spec: #7769 gave sys_api_keyupdate without bulk, and the conformance scan that catches it lives in a package #7769 never touched #7802). The declaration is what check:cross-package-test-inputs requires; without it the gate fails.
  • platform-objects/tsconfig.json gains types: ["node"] — so the new file contributes 0 errors to the package's TEST_DEBT (which stays at its recorded 3) instead of raising a shrink-only ledger. The sweep also seeds its root from __dirname rather than import.meta.url: the latter is a TS1470 under this package's config, and those are the only two seeds the cross-package gate recognises as escaping — deriving the root any other way makes the radius invisible to the gate, which then asks for the declaration to be deleted. Measured both ways.

No object definition, no runtime code and no published behaviour changes, so this carries the skip-changeset label rather than a changeset.

Verification

pnpm --filter @objectstack/platform-objects test 17 files, 351 tests passed
pnpm --filter @objectstack/platform-objects typecheck clean
pnpm --filter '...@objectstack/platform-objects' typecheck 51 projects in scope, 43 ran, all Done (downstream)
pnpm check:nul-bytes OK (7524 files)
pnpm check:cross-package-test-inputs OK (9 packages, all declared, turbo.json hashes every glob)
pnpm check:type-check-coverage OK
pnpm check:type-check-debt OK (33 entries re-measured, none above its recorded number)
pnpm check:query-options-erasure OK

check:query-options-erasure was not in the dispatch list; re-deriving the gates against the actual diff surfaced it, and it passes.


Generated by Claude Code

…e apiMethods affordance rule (#7934)
`os lint` walks an authored stack, so this repo's own `.object.ts` definitions
were never covered by `object/managed-api-method-unaffordable` (#7521). Import
the exported `validateManagedApiMethods` and run it over every code-shipped
object in the monorepo — the predicate is reused, never re-derived.
Measured: 76 object files, 51 in-scope managed objects, ZERO findings. The
divergence class does not currently exist in this repo, so this lands as
regression insurance rather than a fix.
Repo-wide rather than scoped to the two packages the card names: those hold
30 of the 51 in-scope objects, and an audit scoped to a package name is the
failure already recorded in #3745 and #7802.
- declares the cross-package input radius (gate + turbo.json), without which
turbo replays a stale green for a diff touching another package's objects
- platform-objects tsconfig gains `types: ["node"]` so the test layer stays at
its TEST_DEBT number (3) instead of drifting up
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012WMpuAfA2KSdDjGF6tm1bH
@vercel

vercelBot commented Aug 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 13, 2026 5:26am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/platform-objects.

2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/plugins/packages.mdx(via @objectstack/platform-objects)
  • content/docs/ui/setup-app.mdx(via @objectstack/platform-objects)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file tests tooling labels Aug 13, 2026
@os-zhuangos-zhuang added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 13, 2026 — with Claude
…fordance sweep (#7934)
`check:test-source-alias` went red on this branch: adding `@objectstack/lint`
as a devDependency made it a NEW unaliased artifact import for this package.
Unaliased, `validateManagedApiMethods` resolved through `exports` to
`lint/dist`, so the sweep was a verdict about build state rather than about
the rule in the checkout — acutely wrong here, since the sweep's whole purpose
is to run the CURRENT rule over the CURRENT objects, and a stale rule narrows
the population silently while the sweep keeps reporting zero findings.
This package had no `vitest.config.*` at all, so the fix is the package's
first one. It carries the alias and nothing else: no `test` block, so suite
discovery stays on the vitest defaults it ran on before (17 files / 351 tests,
unchanged) and this file's only effect is the resolution.
Array form with an anchored `/^@objectstack\/lint$/`, which is load-bearing
rather than stylistic: `@objectstack/lint` exports a second subpath
(`./runtime`), and the object form matches by PREFIX, so a bare key with a
FILE replacement would swallow it and resolve to `…/src/index.ts/runtime`
(ENOTDIR at run time). Same shape as `packages/rest` (#7955) and
`service-storage` (#7778).
The registry in `scripts/check-test-source-alias.mjs` is untouched — it is
shrink-only, and its own message says widening it is not the fix.
Verified: sweep census unchanged at 76 files / 51 in-scope / 9 packages, zero
findings, now measured against lint's source.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012WMpuAfA2KSdDjGF6tm1bH
@os-zhuang
os-zhuang marked this pull request as ready for review August 13, 2026 05:41
@os-zhuang
os-zhuang added this pull request to the merge queueAug 13, 2026
Merged via the queue into main with commit 9d74614Aug 13, 2026
27 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-7934-managed-api-methods-registry-sweep branch August 13, 2026 05:55
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gateteststooling

Projects

None yet

2 participants

@os-zhuang@claude