Skip to content

docs(spec): manifest.runtime trust-tier text states publish-gate-only enforcement truthfully - #13479

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-11330-runtime-tier-truthful-text
Aug 30, 2026
Merged

docs(spec): manifest.runtime trust-tier text states publish-gate-only enforcement truthfully#13479
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-11330-runtime-tier-truthful-text

Conversation

@claude

@claude claude Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #11330

Executes the maintainer ruling of 2026-08-30 (verbatim「同意」): option B now — make the text true. Option A (enforce the tier at load) is a v18 direction and is deliberately not built here; option C (retire the key) was ruled out, because the cloud marketplace publish gate is a real consumer.

The defect

manifest.loading's tombstone redirected every upgrading author, verbatim:

⚠️ loading.sandboxing in particular never isolated anything … If you were relying on it for isolation, you had none — use the plugin trust tier (manifest.runtime) and the permission declarations, which are enforced.

Measured, that redirection pointed at a key this repo does not enforce at all. An author who followed the prescription got the same nothing they were being warned about, one key over — ADR-0049 false compliance with a shipped migration message attached.

Premise re-check (all three hold, re-measured on origin/main this run)

# Check Result
1 git grep -n "which are enforced" origin/main -- packages/spec/src/kernel/manifest.zod.ts HITmanifest.zod.ts:569
2 git grep -nE "runtime === '(sandbox|node|worker)'" origin/main -- packages/ | grep -v test ZERO code hits. The two raw hits are prose only (liveness/README.md, liveness/manifest.json quoting the pattern); restricted to packages/**/*.ts(x)/js the count is 0. Control: the sibling key packaging does dispatch (cli/src/commands/plugin/build.ts:158,202), so the probe is not blind to this file.
3 cloud publish gate Cited from the in-record 2026-08-29 reading on the card (plugin-permission-audit.ts — 422 + requiresManualReview). ⛔ No new cloud read taken; this board has no cloud access.

The only reads of the tier remain two CLI progress lines that echo the value (plugin/build.ts:127, plugin/publish.ts:94).

What changed — text only

The truthful statement is a split, and both halves ship together everywhere the claim appears:

  • Enforced at the cloud marketplace publish gate — an unverified publisher requesting the node tier is hard-rejected (HTTP 422) and forced to manual review.
  • Not enforced at load — load-side enforcement is not implemented, so a locally installed plugin is not isolated by the tier it declares.

Corrected in all four places the claim is published:

  1. packages/spec/src/kernel/manifest.zod.ts — the loading tombstone prescription
  2. packages/spec/src/kernel/manifest.zod.ts — the PluginRuntime enum describe + TSDoc
  3. packages/spec/src/kernel/manifest.zod.ts — the manifest.runtime field describe + TSDoc
  4. packages/spec/src/migrations/entries/semantic/17.plugin-manifest-loading-retired.ts — the ADR-0087 D3 entry

Plus the packages/spec/liveness/ ledger row and README narrative, brought to the same reading (the row's "READ TWICE, ENFORCED NOWHERE" headline and its SCOPE LIMIT — cloud unmeasured clause are both falsified by the #12400 cloud reading).

⭐ Coordination pin with #11333 — the permissions half is untouched

The ruling splits that one tombstone sentence: the trust-tier half is this card, the permission declarations half rides with #11333. This PR corrects only its own half and preserves the permissions clause verbatimthe permission declarations, which are enforced. A dedicated pin test asserts it is still there, so when #11333 corrects it the handoff shows up as a red pin rather than a silent overwrite.

Declared scope extension (bounded in-place fix)

Item 4 and the liveness files are outside the ruling's named landing point (manifest.zod.ts) and are declared here rather than done quietly. They are the same claim shipped a second time: the D3 entry renders into docs/protocol-upgrade-guide.md, so fixing only the schema would have left the upgrade guide still calling the tier a surface "the platform actually enforces" — a half-fix that leaves the repo self-contradictory on a security-shaped claim. Boundary scan: git grep -rln "which are enforced" → the remaining hits are packages/spec/CHANGELOG.md (a different subject — skill.active, unrelated) and the regenerated content/docs/references/**. No open PR touches any file in this diff (checked against the full open-PR file set).

Verification

Full log excerpts are in the report comment on #11330. Union re-run on the final commit 15963192:

  • pnpm --filter @objectstack/spec check:generated✓ All 14 generated artifacts are up to date. (exit 0)
  • pnpm --filter @objectstack/spec testTest Files 443 passed | 1 skipped, Tests 11815 passed | 1 skipped (exit 0)
  • pnpm --filter @objectstack/spec typecheck → exit 0, including check:test-typecheck: OK — @objectstack/spec's test layer compiles (so the new test file is genuinely covered, not silently excluded)
  • Derived gate families (scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, from the real change set): check:doc-authoring, check:doc-anchors, check:docs-single-h1, check:doc-security-posture, check:changeset-gate-self-tests, check:pm-half-states, check:objectui-changeset, check:test-source-alias, check:spec-parsed-alias, check:empty-state, check:llms-txt, check:skill-examples, check:role-word, check:docs-audit-scope, check:quick-reference-counts, check:docs-redirects — all exit 0.
  • node scripts/check-nul-bytes.mjs → OK, plus a control-byte self-scan over the diff.

⚠️ Two gates first returned PREREQUISITE NOT MET (unbuilt @objectstack/lint / @objectstack/client-react) — recorded as NOT MEASURED, not as failures; both were rebuilt and re-run to a real green.

Byte-invariance

This is a text change and the accepted key set is byte-identical: check:authorable-surface is green and packages/spec/authorable-surface/** is absent from the diff. A pin test asserts the behaviour directly — node / sandbox / worker all still parse, unset still parses, 'isolated' is still refused.

Reverse verification (predicted direction: RED)

Restored the retracted claim into the tombstone on top of the commit, with the mutation proven on disk before reading any result — HEAD blob 88c8f73d vs mutated cf9c6e38, injected-marker count 1 → 0, restored-claim count 0 → 1. The tombstone pin went red (Tests 1 failed | 5 passed); the five describe/behaviour pins correctly stayed green, since the ablation reverted only the tombstone. Restore verified by stategit diff HEAD empty — not by an exit code. The pins resolve through relative source imports (./manifest.zod), so this ablation acts on src/ directly and has no dist/ leg to rebuild.

Review posture

Clause ② path limb fires (packages/spec/src/**), so this PR parks as DRAFT with needs:contract-review on both carriers; the review chain owns enqueue. The content limb reads as not firing — no accept/reject behaviour moves — but that is the reviewer's call, not mine, and the evidence for it is the byte-invariance section above.

One question I could not settle inside a text card, flagged for the review chain: the liveness row still carries "status": "dead". That is now only true of load-side dispatch in objectstack+objectui — the key has a real cross-repo consumer. I left the verdict alone and corrected the prose to say so explicitly, because live requires an evidence pointer the scan resolves to a local file and cloud's gate is not local. The ledger may want a vocabulary for "enforced in a sibling repo"; that is its own decision, not this one.


Generated by Claude Code

… enforcement truthfully

The `manifest.loading` tombstone redirected upgrading authors to the plugin
trust tier as something "which are enforced". Measured, nothing in this repo
dispatches on the tier — its only reads are two CLI progress lines that echo
the value — so the redirection pointed at a key with no local enforcement:
ADR-0049 false compliance with a shipped migration message attached.

The truthful statement is a split, now carried in all four places the claim
ships (tombstone prescription, PluginRuntime enum describe, manifest.runtime
field describe, ADR-0087 D3 entry -> protocol-upgrade-guide):

- enforced at the cloud marketplace publish gate (unverified publisher
  requesting the `node` tier -> HTTP 422 + forced manual review), which is why
  the key is not retired;
- not enforced at load, so a locally installed plugin is not isolated by the
  tier it declares.

Text only: no schema shape and no accept/reject change (check:authorable-surface
green, accept-set pinned). The permissions half of the tombstone sentence is
preserved verbatim and rides with the permissions card.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Aug 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 2 documentable anchor(s). ⚠️ 3 changed file(s) yielded no anchor (packages/spec/liveness/README.md, packages/spec/liveness/manifest.json, packages/spec/spec-changes.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

3 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/getting-started/quick-reference.mdx (via ManifestSchema (symbol))
  • content/docs/plugins/development.mdx (via ManifestSchema (symbol))
  • content/docs/protocol/kernel/plugin-spec.mdx (via ManifestSchema (symbol))

1 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v15.mdx (via ManifestSchema (symbol))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/spec/liveness/README.md, packages/spec/liveness/manifest.json, packages/spec/spec-changes.json) — pages documenting those are invisible to this run
  • 4 name(s) were too generic to anchor anything (single lowercase words)
  • 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.

Coarse fallback — 126 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 8fcd0816dadc10c66aa7a5d2fa5d8b57e7844344packageMentionDocs.

Which tree this was computed on

This run read content/docs from 760e15935f8320bdb09a1589b7a0a3232acb881c — the merge of head 15963192715b505a2b2a82c9430e683ee0a80a47 into base 8fcd0816dadc10c66aa7a5d2fa5d8b57e7844344, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 760e15935f8320bdb09a1589b7a0a3232acb881c && git checkout 760e15935f8320bdb09a1589b7a0a3232acb881c
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 8fcd0816dadc10c66aa7a5d2fa5d8b57e7844344 15963192715b505a2b2a82c9430e683ee0a80a47 && git checkout -B drift-repro 8fcd0816dadc10c66aa7a5d2fa5d8b57e7844344 && git merge --no-ff 15963192715b505a2b2a82c9430e683ee0a80a47

node scripts/docs-audit/affected-docs.mjs --json 8fcd0816dadc10c66aa7a5d2fa5d8b57e7844344

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 8fcd0816dadc10c66aa7a5d2fa5d8b57e7844344 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@zhuangjianguo
zhuangjianguo marked this pull request as ready for review August 30, 2026 14:26
@zhuangjianguo
zhuangjianguo added this pull request to the merge queue Aug 30, 2026
Merged via the queue into main with commit a9ee989 Aug 30, 2026
41 checks passed
@zhuangjianguo
zhuangjianguo deleted the claude/issue-11330-runtime-tier-truthful-text branch August 30, 2026 15:09
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 tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[text correction · ruled B] manifest.runtime tombstone/describe reads truthfully: publish-gate enforced (cloud), load-side NOT enforced

2 participants