Skip to content

feat(plugin-security): delete the curated capability seeder — the boot writes no sys_capability row for the platform's capabilities (ADR-0131 D3, #15204 stage 6b-1b) - #22709

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-15204-s6b1b-system-capability-seeder
Oct 11, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-15204-s6b1b-system-capability-seeder

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #15204
Clause-②: no

Stage 6b-1b of the cutover plan only (claim amendment 6098440046): the curated and derived-default capability seeder bootstrapSystemCapabilities (packages/plugins/plugin-security/src/bootstrap-system-capabilities.ts) is deleted, with its test, its import and its one call in security-plugin.ts. This is a deletion only (batch #310 item 4). The rest of #15204 stays open. bootstrapDeclaredCapabilities, capability-name-collision and 6b-1a's transitional engine view are 6b-1c's and are kept as they are. No sys_capability row is deleted, sys-capability.object.ts is unchanged, and who may author a capability is unchanged (#22621 → A).

Landing: after stage 5 (C9), per stage-0 order correction 3. This PR stays a draft until the PM schedules it.

Premise, re-verified on origin/main 96469912

  • The seeder is still on main: 995 lines, plus a 1,376-line test. Its only production caller is security-plugin.ts (import :88, call :5015). index.ts does not export it.
  • No branch or open PR deletes it. The other claude/issue-15204-* heads are s1, s3 and s6c-prep. Of these, only s6c-prep touches the module, and only to repoint one import (per-organization-catalog to organization-scope, 2 lines). Whichever of the two PRs lands second gets a modify/delete conflict on this file, and the fix is to keep the deletion.
  • After 6b-1a (feat(plugin-security): the curated platform capabilities are declared capability metadata (ADR-0131 D3, #15204 stage 6b-1a) #22669), the nine curated names resolve in the registry. This was measured on a booted showcase (below), and builtin-capabilities.boot.test.ts asserts it.

Who reads sys_capability rows (re-measured on this tree)

reader what it is fresh database after this PR
Setup nav nav_capabilities (security-plugin.ts:1612) and the object's list page a UI listing of rows lists only the package rows (showcase: 2, was 11). Correction 3 holds this PR behind C9, whose picker reads the registry
sys-capability.object.ts lookup providers (:122, :132, :142) the picker data source same rows as above
the curated-name row gate (security-plugin.ts :7652–:7710, stage 8-pre) refuses a Setup row claiming a curated name unchanged. It reads PLATFORM_CAPABILITY_NAMES, not the seeded rows; it reads a row only to detect a rename
cli/src/utils/organization-ownership-inventory.ts:349 an ownership census of the table counts fewer platform rows; no decision rides on it
lint/src/validate-capability-references.ts:97 reads a stack's data seed declarations, not rows unchanged

No runtime authorization path reads a row: grants resolve by the name in systemPermissions (core/src/security, rest, objectql, services grep: zero sys_capability reads).

Measured fresh-database effect (showcase, pnpm dev -- --fresh, this branch, all three reads as admin@objectos.ai)

reading before (main, from the 6b-1a report 6096357309 and the boot pin's old census) after (this branch, measured)
GET /api/v1/data/sys_capability (the Setup capability list) 11 rows: 9 curated platform + 2 package 2 rows: showcase.export_data, showcase.restricted_ops, both managed_by: package
GET /api/v1/meta/capability 11 11 (the nine curated names plus the two package names)
GET /api/v1/meta/capability/manage_users 200 200
capability refusal or failure lines in the boot log 0 0

The derived half adds nothing: the 6b-1a report measured that every systemPermissions entry of the platform's default sets is curated, and the showcase's one non-curated grant (showcase.export_data) is its own declared capability.

Changes

  • Deleted: bootstrap-system-capabilities.ts (995) and bootstrap-system-capabilities.test.ts (1,376).
  • security-plugin.ts: removed the import, the bootstrapSystemCapabilities try block, and the materializedCapabilityNames handoff. That variable existed only to feed the deleted call, and under noUnusedLocals it cannot stay. The bootstrapDeclaredCapabilities call, its arguments and the withoutPlatformCapabilityDeclarations view are unchanged; only its const capOutcome = binding goes. Two comments that would now be false are reworded: the seeding block and the curated-name gate's doc.
  • Tests, each one classified:
    • bootstrap-seed-round-trips.test.ts: the #11451/#11520 describe asserts the seeder's own round trips, so its eight seeder cases go. One case (the existing callers still emit their exact key set) only calls bootstrapDeclaredPermissions and fences buildExistingByName. It is kept, in a describe of its own.
    • bootstrap-declared-capabilities.test.ts (measured here; not in the amendment's list): CLAIMS a derived … placeholder used the seeder only to set up a platform row, so it now inserts that row directly. declared name suppresses the implicit derived placeholder, and eight #4967 Part 1 cases, assert how the two seeders combine, so they go. materializedNames reconciles with the outcome counters stays. The whole file goes in 6b-1c.
    • builtin-capabilities.boot.test.ts (measured here; 6b-1a's pin): its census expected the nine curated rows. It now expects only the stack's package row, on a fresh database and on a re-opened one, with zero writes on the second boot. This is the stage's acceptance pin.
    • seed-name-lookup-degradation-audible.test.ts, bootstrap-platform-admin-seeded-provenance.test.ts, sys-capability.organization-unique.test.ts, driver-sql/…/sql-driver-declared-index-organization-respelling.test.ts: each named the seeder in a comment only. The sentence that would now be false is reworded or dropped. No assertion changes.
  • Comments in surviving modules that would now be false: builtin-capabilities.ts (item 2 of its header), spec/src/security/capabilities.ts (its consumer list; doc comment only, no schema or export change), lint/src/validate-capability-references.ts (the "mirrors bootstrapSystemCapabilities" clause).
  • Censuses, each regenerated by its own tool: scripts/engine-double-contract.baseline.json loses the deleted test's row. node scripts/tenant-audit-census.mjs --write re-counted the write call sites (241 → 239, two erased-receiver sites gone). The hand-written prose counts on content/docs/permissions/tenant-audit-census.mdx are corrected to match, as the gate requires.
  • Changeset: .changeset/15204-s6b1b-system-capability-seeder.md, @objectstack/plugin-security minor.

Verification

  • Build: --filter '@objectstack/plugin-security...', lint..., driver-sql..., dogfood^..., runtime..., plus the packages dual-build-cjs-loads needed: all exit 0.
  • plugin-security: typecheck exit 0 (tsc, scripts, and check:test-typecheck, which covers the tests); vitest run: 197 files, 4055 passed / 45 skipped, at b88b3567. The later commit 264e056d touched only the two census docs.
  • lint: 135 files, 6231 passed; typecheck exit 0. driver-sql: the edited file passed 26 tests; typecheck exit 0. runtime: standalone-stack-seeder-declaration-copy passed 13 tests.
  • Dogfood pins that read capabilities: security-catalog-showcase, audit-log-audit-capability, showcase-d3-d4-capabilities, me-apps-and-everyone-baseline and org-admin-affordance-reach: 5 files, 69 passed.
  • dispatch-gates --commands derived 121 commands. --ran reconciles 121 derived, 121 run, 0 NOT-MEASURED, 0 UNRUN. The first pass of four commands needed work before they passed:
    • check-tenant-audit-census and its self-test went red on this diff's real count change, and were fixed above.
    • check-plugin-teardown-shape --self-test needed an unshallowed clone.
    • check:dual-build-cjs-loads needed 8 packages built outside the closure.
  • Line budget: 2,930 changed lines (+83 / −2,847, 17 files), under 3,000.

Acceptance notes

  • sys-capability.object.ts:87 still says "The two production readers of the table are both seeders (bootstrap-system-capabilities.ts, bootstrap-declared-capabilities.ts)". The amendment excludes any change to that file, so it waits for stage 8, which retires the object. Carrier: stage 8.
  • The 6b-1a ACCEPT (6096401008) records the transitional view's deletion as owed by "6b-1b … together with the seeders". The later amendment 6098440046 moves it to 6b-1c, and the dispatch says not to touch it. This PR follows the amendment.
  • On a database that was already seeded, the curated platform rows stay (no row is deleted). They are no longer refreshed at boot, and stage 8 / C7b retire them.

Generated by Claude Code

…p-system-capabilities)

The boot no longer writes sys_capability rows for the platform's curated
capabilities or for undeclared systemPermissions names; the curated ones are
served by the registry since 6b-1a. The seeder's own test goes, the cases in
other suites that asserted its behaviour go, the one that only used it to set
up a platform row inserts that row directly, and comments that would now be
false are reworded.

Claude-Session: https://claude.ai/code/session_0113mDBBZPBFzvZqbJqfaFMv
Co-authored-by: Claude <noreply@anthropic.com>
… seeder's write sites

Claude-Session: https://claude.ai/code/session_0113mDBBZPBFzvZqbJqfaFMv
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/xl documentation Improvements or additions to documentation tests tooling labels Oct 10, 2026
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/lint, @objectstack/plugin-security, @objectstack/spec, touching 23 documentable anchor(s). ⚠️ 3 changed file(s) yielded no anchor (packages/lint/src/validate-capability-references.ts, packages/plugins/plugin-security/src/builtin-capabilities.ts, packages/spec/src/security/capabilities.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

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

  • content/docs/permissions/authorization.mdx (via sys_capability (literal, a string literal in bootstrapSystemCapabilities), /api/v1/meta/capability (route, a path literal in a comment in start))
  • content/docs/permissions/capabilities.mdx (via sys_capability (literal, a string literal in bootstrapSystemCapabilities), /api/v1/meta/capability (route, a path literal in a comment in start))
  • content/docs/permissions/field-level-security.mdx (via SecurityPlugin (symbol, a top-level class))
  • content/docs/permissions/index.mdx (via SecurityPlugin (symbol, a top-level class))
  • content/docs/permissions/permission-sets.mdx (via sys_capability (literal, a string literal in bootstrapSystemCapabilities), /api/v1/meta/capability (route, a path literal in a comment in start))
  • content/docs/permissions/tenant-audit-census.mdx (via SYSTEM_CTX (symbol, a top-level const object))
  • content/docs/plugins/packages.mdx (via SecurityPlugin (symbol, a top-level class))
  • content/docs/ui/forms.mdx (via SecurityPlugin (symbol, a top-level class))

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

  • content/docs/releases/implementation-status.mdx (via SecurityPlugin (symbol, a top-level class))
  • content/docs/releases/v15.mdx (via sys_capability (literal, a string literal in bootstrapSystemCapabilities))
  • content/docs/releases/v17/17-0.mdx (via SYSTEM_CTX (symbol, a top-level const object))
  • content/docs/releases/v17/17-3.mdx (via tryFind (symbol, a top-level function))

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/lint/src/validate-capability-references.ts, packages/plugins/plugin-security/src/builtin-capabilities.ts, packages/spec/src/security/capabilities.ts) — pages documenting those are invisible to this run
  • 8 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • 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 — 142 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 d7b26df5b50f323dd42d693eea5d7de55922bdd1 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from f473bb721047813018e12cfbc68ca6ee66fdf7f0 — the merge of head b8df7fda7b8fc0205bae7d45995fac7c600cfc95 into base d7b26df5b50f323dd42d693eea5d7de55922bdd1, 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 f473bb721047813018e12cfbc68ca6ee66fdf7f0 && git checkout f473bb721047813018e12cfbc68ca6ee66fdf7f0
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d7b26df5b50f323dd42d693eea5d7de55922bdd1 b8df7fda7b8fc0205bae7d45995fac7c600cfc95 && git checkout -B drift-repro d7b26df5b50f323dd42d693eea5d7de55922bdd1 && git merge --no-ff b8df7fda7b8fc0205bae7d45995fac7c600cfc95

node scripts/docs-audit/affected-docs.mjs --json d7b26df5b50f323dd42d693eea5d7de55922bdd1

⚠️ 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 d7b26df5b50f323dd42d693eea5d7de55922bdd1 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

…h no sys_capability row

Claude-Session: https://claude.ai/code/session_0113mDBBZPBFzvZqbJqfaFMv
Co-authored-by: Claude <noreply@anthropic.com>
…b1b-system-capability-seeder

# Conflicts:
#	packages/plugins/plugin-security/src/bootstrap-system-capabilities.ts
#	packages/plugins/plugin-security/src/security-plugin.ts
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

os-dev-report addendum: landing patch round (6b-1b, ruling 6104498446)

Merge head b8df7fda7b (origin/main d7b26df5b5 merged in; no rebase, no force-push). Size against merge base d7b26df5b: 2,964 changed lines (+105 / −2,859, 20 files), under 3,000. GitHub reads the same 105 / 2,859 / 20, and mergeable: true.

Conflict resolutions

  • bootstrap-system-capabilities.ts: a modify/delete conflict, because main repointed one import (refactor(plugin-security): move the organization-scope helpers and the seed write-refusal accumulator out of per-organization-catalog.ts #22696). Kept the deletion.
  • security-plugin.ts import block: main changed per-organization-catalog.js to organization-scope.js (6c-prep) and still had the seeder import. Took main's organization-scope.js import and dropped the seeder import. No other hunk conflicted, and no live reference to bootstrapSystemCapabilities or materializedCapabilityNames remains. The only remaining mentions are comments in retired modules (batch Release version 0.4.0 #310 item 4) and the historical prose in measure-durability-swallow-family.mjs.
  • No path in this PR is merge=os-regen, so a plain git merge applied. The tenant-audit census and the double-contract baseline were re-checked on the merged tree by their own gates; both exit 0 with no regeneration needed.

Gate and suite exits (all at b8df7fda7b, every exit captured before any pipe)

  • Full build (turbo run build, all packages except docs): 72 of 72 tasks, exit 0.
  • Typecheck: plugin-security, lint and spec each exit 0, including check:test-typecheck.
  • Suites:
    • plugin-security: 197 files, 4053 passed / 45 skipped.
    • lint: 135 files, 6321 passed.
    • spec: 697 files, 20175 passed / 1 todo.
  • dispatch-gates --commands derives 121 commands; all 121 exit 0. --ran: 121 run, 0 NOT-MEASURED (a derived zero).
  • Nothing is still running.

Each sentence re-verified against main after stage 1 (stage 1 edited authorization.mdx, capabilities.mdx, permission-sets.mdx and validate-capability-references.ts; nothing it changed falsifies a sentence of this PR, and no fix was needed):

  • permission-sets.mdx:150: curated capabilities are registry declarations with no row; package-declared ones are seeded as a row. Holds. No non-test sys_capability read in core, objectql, rest, services, plugin-auth or plugin-sharing; the only writer is bootstrap-declared-capabilities.ts.
  • permission-sets.mdx:43: "matched by capability name". Holds.
  • capabilities.mdx:223: the only production reader of the table is the declared-capability boot seeder. Holds. The other plugin-security readers are the Setup nav, the object's lookup providers and the curated-name write gate; they are UI and door code, not production readers in the callout's sense, unchanged from before.
  • authorization.mdx:207: the derivation is retired. Holds.
  • authorization.mdx:546: the registry bullet. Holds (registerBuiltinCapabilities is on main).
  • spec/src/security/capabilities.ts:14 and :21. Hold.
  • lint/src/validate-capability-references.ts:22: stage 1's +62 lines do not touch it. Holds.
  • builtin-capabilities.ts:22. Holds.
  • Changeset (plugin-security minor, spec and lint patch): every sentence holds. No authorization decision changes; a declared capability is still seeded as a package row until 6b-1c.

The PR stays a draft.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 11, 2026 02:49
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 11, 2026 02:49
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 11, 2026
Merged via the queue into main with commit 7aa8d51 Oct 11, 2026
37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-15204-s6b1b-system-capability-seeder branch October 11, 2026 03:16
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: b8df7fda7b8fc0205bae7d45995fac7c600cfc95
Local-runs: none

Post-hoc audit after merge. PR #22709 (stage 6b-1b of #15204) was queued on Clause-②: no without a contract-tier record although its diff touches packages/spec/src/security/capabilities.ts and packages/lint/src/validate-capability-references.ts (non-test), so the path limb of the contract gate fired and a PASS was owed before the queue. The queue merged it as 7aa8d51c0ffb at 2026-10-11T03:16:16Z. This record judges, after the fact, whether the declaration was true and whether the changesets match what was published. Inputs: the PR body and file list, its net diff (20 files, +105/−2,859), the check-runs on the head, card #15204 (ACCEPT 6101036695, amendment 6098440046, ruling 6104498446, landing note 6104756315, Landed 6104947165) and the dev report 6100594613 with addenda 6100651013, 6100820807, 6104745893. Nothing was built, run or re-run; the merged tree was read with git show / git grep against 7aa8d51c and the PR base d7b26df5b5.

① Derived judgments

  1. packages/spec/src/security/capabilities.ts (+3/−3) changes no published contract. The hunk is lines 11–24 of the module's leading /** [ADR-0066 D1] … */ block, above the first export (PlatformCapability at :25). It touches no .describe() (:169–:184), no export (:25, :40, :85, :135, :197, :199, :217), no schema shape and no value in PLATFORM_CAPABILITIES / PLATFORM_CAPABILITY_NAMES. Consumers of that block on main at the merge commit: the reference-docs generator (packages/spec/scripts/build-docs.ts) collects .zod.ts files only (collectZodFiles) and renders schema sections from json-schema/, i.e. the .describe() strings; capabilities.ts is not a .zod.ts, and its CapabilityDeclarationSchema lands in the security/misc catch-all page, which carries no source pointer and no module description from this file. The api-surface snapshot (packages/spec/api-surface/security.json:55–:61) records names and kinds only. packages/spec/liveness/capability.json anchors symbols in other files. json-schema.manifest/security.json is unchanged. Measured on the merged tree: neither the old sentences ("which seeds these into sys_capability records at boot", "keeps the seeder and the lint") nor the new ones ("registers these as capability metadata items at boot", "keeps the registry and the lint") occur anywhere outside the source file itself — no generated artifact, ledger or reference page carries either. The four gates that red on a consumed comment all ran success on b8df7fda7b: "Check generated reference docs are in sync with the spec", "Check the authorable key surface is recorded and nothing vanished", "Check @objectstack/spec public API surface", "Check spec liveness". Judgment: correct — not a contract change.

  2. packages/lint/src/validate-capability-references.ts (+1/−2) changes no published contract. The hunk drops the parenthetical "mirrors the runtime bootstrapSystemCapabilities derived-defaults rule" from item 3 of the module header's known-set list. CAPABILITY_REFERENCE_UNKNOWN, CapabilityRefSeverity, CapabilityRefFinding, validateCapabilityReferences, the rule's severity and the known-set computation are untouched. The two anchors into this file on main are symbol anchors, not line anchors (packages/spec/liveness/capability.json:8 names #validateCapabilityReferences; docs/qa/platform-checklist/areas/access-security.json:2209 names #known), so the one-line shrink moves nothing; @objectstack/lint has no generator reading module headers (exports: ., ./runtime, ./rule-explanations). Judgment: correct — not a contract change.

  3. The deletion widens nothing and removes no public surface. bootstrapSystemCapabilities was not exported from packages/plugins/plugin-security/src/index.ts on the PR base d7b26df5b5 (0 mentions) nor on the merge commit; its only caller was security-plugin.ts. The observable runtime change — a fresh boot writes no sys_capability row for the nine curated capabilities and none for an undeclared systemPermissions name; on a fresh showcase GET /api/v1/data/sys_capability goes 11 → 2 rows while GET /api/v1/meta/capability stays at 11 — is seeded data and runtime security behaviour, which the Clause-② criterion excludes (负边界:运行时权限/安全行为变更不是条款②). No route, no spec key, no error code and no accept set changes; sys-capability.object.ts is untouched. Judgment: Clause-②: no holds on the declaration limb as well as on the path limb.

  4. Docs edits (content/docs/permissions/authorization.mdx, capabilities.mdx, permission-sets.mdx, tenant-audit-census.mdx) are hand-written prose outside the three contract faces; the ACCEPT 6101036695 read them sentence by sentence. scripts/engine-double-contract.baseline.json loses only the deleted test's row; the tenant-audit census pair was regenerated by its own tool (241 → 239). Not contract surfaces; noted, not re-judged here.

  5. Head and merge agree. The two contract-path files and the changeset are byte-identical between the PR head b8df7fda7b and the merge commit 7aa8d51c (git diff --stat empty), so the Landed record's 18-of-20 reading holds for them.

② Semver level

.changeset/15204-s6b1b-system-capability-seeder.md: @objectstack/plugin-security minor, @objectstack/spec patch, @objectstack/lint patch, with the body line Clause-②: no matching the PR body's line. Consistent with ①: no yes (so no at-least-minor obligation is triggered), no (narrowing) arm (so no BREAKING migration text or ADR-0087 marker is owed), nothing exported removed. minor for plugin-security is defensible — the boot's observable behaviour changes with no removal of a public export — and sits at or above any floor. patch for spec and lint is the honest floor: both packages' shipped bytes change (the comment ships in source and declaration output), so skip-changeset would be wrong and no higher level is earned. Check Changeset is success on the head, and the dev's addendum 6100651013 records check-changeset-no-major, check-empty-changeset and check-adr-0087-registration green on the changeset's head. Judgment: the changesets match what was published.

③ Boundary flags

  • Dev open_questions: none. Deviations, each answered: (a) const capOutcome = and materializedCapabilityNames dropped in security-plugin.ts — internal locals, not exported, forced by noUnusedLocals; no contract reach. (b) Files outside the dispatched landing zone (the spec and lint comments, the double-contract baseline, the census pair) — judged in ①.1, ①.2 and ①.4. (c) The minor bump — judged in ②.
  • Out-of-scope findings the dev carried: sys-capability.object.ts:87 still names the deleted seeder (the amendment forbids editing that file; carrier stage 8), and the transitional view's deletion was moved to 6b-1c by amendment 6098440046. Neither is a contract surface.
  • Check-runs on b8df7fda7b: 35 success, 2 skipped (Console Pin Gate, Packed-tarball smoke — roster skips), commit status success; Governed Surface Queue Guard success (0 of 20 paths governed). No red to excuse.
  • Process flag, for the seat: the contract-surface path limb fired on this diff and the PR was queued (landing note 6104756315: "Clause-②: no, so no contract review is owed") without a ## Contract review record on its head. The path limb is judged on the file list, independently of the declaration, so that was a landing-operations miss — not a contract defect. This record is the compensating control; no follow-up is owed for the diff itself.

Implemented-by: session_0113mDBBZPBFzvZqbJqfaFMv
Reviewed-by: session_01Rerax7QTjKMPCUZxQUtPFR

VERDICT: PASS


Generated by Claude Code

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/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants