feat(spec): retire the authorable AdvancedPluginLifecycleConfig surface, keep the host-driven lifecycle library (#11825, ADR-0049 route 2) - #12336
Conversation
…ce (#11825, ADR-0049 route 2) Whole-def retirement of the zero-reader authorable lifecycle-config surface: AdvancedPluginLifecycleConfigSchema (container), GracefulDegradationSchema, PluginUpdateStrategySchema — 3 defs, 9 exported names, 17 authorable-surface keys. The host-driven library classes in @objectstack/core and their input vocabularies (PluginHealthCheck/Status/Report, HotReloadConfig, DistributedStateConfig, PluginStateSnapshot) are KEPT per the ruling. Route 3 (no carrier key, no authored document): RETIRED_DEFS_BY_MAJOR[18] + D3 semantic entry advanced-plugin-lifecycle-config-retired ARE the declaration; no tombstone, no D2 conversion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV
…tire-advanced-lifecycle-config
📓 Docs Drift Check11 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 18361bedeea406d623c343a9f8dc4264a163ddc6 && git checkout 18361bedeea406d623c343a9f8dc4264a163ddc6
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin cf99875ea88a6a611353442e76c93de70727b74d cb59746d8709c6225566f36259b4b94a0e31c710 && git checkout -B drift-repro cf99875ea88a6a611353442e76c93de70727b74d && git merge --no-ff cb59746d8709c6225566f36259b4b94a0e31c710
node scripts/docs-audit/affected-docs.mjs --json cf99875ea88a6a611353442e76c93de70727b74d |
Fixes #11825
Maintainer ruling (2026-08-25, decision-box batch 4, route 2, not re-adjudicable): retire the declarative config surface of
AdvancedPluginLifecycleConfigunder ADR-0049 enforce-or-remove;PluginHealthMonitorand sibling classes stay as host-driven@objectstack/corelibrary (the #11811-correctedlifecycle.mdxexamples are the supported usage).Scope gate — per-group consumer audit (the ruling's mandated first step)
Measured at base
8cdd6965and re-verified at the merged headcb59746d, across objectstack + objectui (objectui atf53a8d0ae, control probe positive). Kernel-wiring measurement:new PluginHealthMonitor/new HotReloadManagerare constructed ONLY by their own unit tests andpackages/core/examples/phase2-integration.ts— no runtime path composes either, and both take their config directly, never through the container.healthPluginHealthCheckread bycore/src/health-monitor.ts(host-driven class, kernel never constructs it —kernel.tshas zeroHealthMonitorhits)checkMethod→ 10 hits in 4 files incl.health-monitor.ts:147-159(the scan sees real readers)hotReloadHotReloadConfigread bycore/src/hot-reload.ts(same host-driven shape;hot-reload.test.tscallers are test-side, ruled non-runtime)debounceDelay/stateStrategy→hot-reload.ts:61,386degradationoptionalDependencies= ADR-0116 plugin ordering;degradedFeatures= auth-manager's private MapfailureThresholdresolves tohealth-monitor.tsupdatescheckCompatibilitycollision =AppLifecycleServicemethod (different surface)resourcesmaxCpu/maxMemorycollisions =plugin-security-advancedresourceLimits, read bysandbox-runtime.ts:344(different def)maxCpureadersobservabilityenableMetrics/enableTracing/enableProfiling/metricsInterval)All six groups zero → container-level retirement (PM assumption 3 confirmed). No manifest, stack collection, or metadata-type binding embeds the container — no authored document could ever carry it (verified: zero structural references outside the module).
What this PR does
Removed (3 defs, 9 exported names):
AdvancedPluginLifecycleConfigSchema/AdvancedPluginLifecycleConfig/AdvancedPluginLifecycleConfigParsed,GracefulDegradationSchema/GracefulDegradation/GracefulDegradationParsed,PluginUpdateStrategySchema/PluginUpdateStrategy/PluginUpdateStrategyParsed— plus 17 authorable-surface rows and 3 json-schema.manifest keys, deleted deliberately per the gates' own instructions.Kept, deliberately:
PluginHealthStatusSchema,PluginHealthCheckSchema,PluginHealthReportSchema,HotReloadConfigSchema(+ embeddedDistributedStateConfigSchema),PluginStateSnapshotSchemaand their types — the input vocabularies of the kept host-driven classes.packages/coreis untouched.Route 3 (the #8715
identity/ApiKeyshape): nobody parses the container and nothing embeds it, so a tombstone would be a prescription nobody can receive and there is no seam for a D2 conversion. The declaration isRETIRED_DEFS_BY_MAJOR[18](kernel/AdvancedPluginLifecycleConfig,kernel/GracefulDegradation,kernel/PluginUpdateStrategy) + D3 semantic entryadvanced-plugin-lifecycle-config-retired(one file per entry;gen:migration-registryconcatenated — 120 semantic, 58 retired-key, 67 retired-def).Retirement kit: retirement record in the zod module · pin test
plugin-lifecycle-advanced-retirement.test.ts(zero holders for all 9 names on every public entry viaexport-origins/, survivors pinned) · trimmed unit tests · regenerated artifacts (authorable-surface, authorable-defaults, json-schema.manifest, api-surface −9, export-origins −9, reference docs, strictness ledger) · prose updates (PLUGIN_STANDARDS.md§5.1 + capability table,PROTOCOL_MAP.md,quick-reference.mdx) · changeset.Gate route evidence (verbatim, from the build at this head)
ℹ️ 3 schema(s) left the published set since 8cdd696592b0, each declared (#4725)— all threeRETIRED_DEFS_BY_MAJOR, major 18.ℹ️ 3 baseline deletion(s) since 8cdd696592b0 carry their own proof (#4650)— eachdef no longer emitted by this build; whole-schema removals are adjudicated by json-schema.manifest/ (#2978)(the authorable-surface 的 tombstone 门禁可被手编基线绕过 —— 删掉基线行就删掉了证据(#4638 / #4643 已两次这样过绿) #4650 path-3 verdict, i.e. the route's own self-identification).spec-changes.json/ upgrade guide: deliberately unchanged — they project released majors only (protocolVersion: 17.0.0); major-18 registrations enter at the 18 cut, identical to the [finding] TheApiKeyreference table documents better-auth's apiKey-plugin schema — a plugin this platform does not load and a shapesys_api_keydoes not have #8715 precedent (its semantic entry is likewise absent from both today).Changeset grade
@objectstack/spec: minorwith[BREAKING]+ ADR-0087 registration marker — the #12256 dual-green precedent, measured here:check-changeset-no-major:✓ This diff introduces no major bump.check-adr-0087-registration:✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.([BREAKING] registered advanced-plugin-lifecycle-config-retired)check-empty-changeset:✓ No empty-frontmatter changeset introduced by this diff (1 declaring changeset(s) added).Verification (all at merged head
cb59746dunless noted)pnpm --filter @objectstack/spec build— exit 0 (gate route evidence above printed by this run's pre-merge twin atef5632b; the merged-headcheck:generatedre-proves the artifacts)pnpm --filter @objectstack/spec run check:generated—✓ All 14 generated artifacts are up to date.pnpm --filter @objectstack/spec test—Test Files 429 passed (429)·Tests 11394 passed (11394)pnpm --filter @objectstack/spec typecheck— exit 0 (check:test-typecheck: OK)pnpm --filter '@objectstack/core^...' build+pnpm --filter @objectstack/core build— exit 0 (core has notypecheckscript; its dts-emitting build is the type gate)pnpm --filter @objectstack/core test—Test Files 38 passed (38)·Tests 955 passed (955)(health-monitor / hot-reload / kernel suites — classes kept, all green)@objectstack/spec/kernel→error TS2305×3 (expected red); positive control importing 5 kept names → exit 0.scripts/pm/dispatch-gates.mjs, no args, answer stampedobjectstack-ai/objectstackat this tree): 45 root/spec/lint gates exit 0, includingcheck:liveness,check:empty-state,check:variant-docs,check:skill-examples(256 prose examples),check:skill-refs,check:quick-reference-counts,check:merge-driver,check:objectui-changeset,check:published-files,check:spec-parsed-alias,check:test-source-alias,check:type-source-resolution,check:engine-double-contract,check-ci-filter-parity,check-plugin-teardown-shape, both docs-audit scripts,release-rehearsal-clone --self-test,check-docs-single-h1,check-nul-bytes.@objectstack/dogfoodtest/expression-conformance.test.ts— 1 file / 3 tests passed (playbook's default consumption radius).Declared narrowings (accepted-deviation form; CI runs the full farm regardless):
check:type-check-debtnot run locally — it refuses without the full 53-package built closure (its own error text namespnpm exec turbo run build --filter='./packages/*' ...as the CI prerequisite); lint.yml builds exactly that.check-test-completenessnot run locally — it is a CI-log parser (usage: check-test-completeness.mjs <turbo-test-log>), with no standalone mode.cloudnot scanned: unreachable from this seat's credential (add_repo: no access). objectstack + objectui measured directly; the docs/spec: PLUGIN_STANDARDS.md §5.1/§5.2/§5.4 把 Hot Reload 与 Plugin Isolation 标为 ✅,但 PluginHotReloadSchema / PluginSandboxingSchema 全仓零 runtime reader(ADR-0049) #4914 retirement of this module's neighbouring family recorded a three-repo zero (cloud measured 2026-08-09) for the same vocabulary neighbourhood.Out of scope, recorded for PM triage
HotReloadConfig.stateStrategy'disk'and'distributed'are silent memory fallbacks inside the KEPT class (hot-reload.tsstate manager), andhotReload.distributedConfig(DistributedStateConfigSchema) is read by nothing — declared-≠-enforced inside the kept library input. Left untouched here (the ruling keeps the classes as-is); finding draft in the dev report for PM to file.Generated by Claude Code
Generated by Claude Code