Sitelet https://github.com/objectstack-ai/objectstack/pull/12336
Skip to content

feat(spec): retire the authorable AdvancedPluginLifecycleConfig surface, keep the host-driven lifecycle library (#11825, ADR-0049 route 2) - #12336

Open
os-litant wants to merge 2 commits into
mainfrom
claude/issue-11825-retire-advanced-lifecycle-config
Open

feat(spec): retire the authorable AdvancedPluginLifecycleConfig surface, keep the host-driven lifecycle library (#11825, ADR-0049 route 2)#12336
os-litant wants to merge 2 commits into
mainfrom
claude/issue-11825-retire-advanced-lifecycle-config

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes #11825

Maintainer ruling (2026-08-25, decision-box batch 4, route 2, not re-adjudicable): retire the declarative config surface of AdvancedPluginLifecycleConfig under ADR-0049 enforce-or-remove; PluginHealthMonitor and sibling classes stay as host-driven @objectstack/core library (the #11811-corrected lifecycle.mdx examples are the supported usage).

Scope gate — per-group consumer audit (the ruling's mandated first step)

Measured at base 8cdd6965 and re-verified at the merged head cb59746d, across objectstack + objectui (objectui at f53a8d0ae, control probe positive). Kernel-wiring measurement: new PluginHealthMonitor / new HotReloadManager are constructed ONLY by their own unit tests and packages/core/examples/phase2-integration.ts — no runtime path composes either, and both take their config directly, never through the container.

Group Reference points found Positive control Verdict
health spec declaration + own test; PluginHealthCheck read by core/src/health-monitor.ts (host-driven class, kernel never constructs it — kernel.ts has zero HealthMonitor hits) checkMethod → 10 hits in 4 files incl. health-monitor.ts:147-159 (the scan sees real readers) zero runtime readers → retire from authorable surface; vocabulary KEPT as library input
hotReload spec declaration + own test; HotReloadConfig read by core/src/hot-reload.ts (same host-driven shape; hot-reload.test.ts callers are test-side, ruled non-runtime) debounceDelay/stateStrategyhot-reload.ts:61,386 zero runtime readers → retire from authorable surface; vocabulary KEPT as library input
degradation spec declaration + own test ONLY. Bare-name collisions verified structurally different: optionalDependencies = ADR-0116 plugin ordering; degradedFeatures = auth-manager's private Map same-scan failureThreshold resolves to health-monitor.ts zero readers, no implementation body → retire whole def
updates spec declaration + own test ONLY. checkCompatibility collision = AppLifecycleService method (different surface) same scan configuration zero readers, no implementation body → retire whole def
resources spec declaration + own test ONLY. maxCpu/maxMemory collisions = plugin-security-advanced resourceLimits, read by sandbox-runtime.ts:344 (different def) that very collision proves the scan finds real maxCpu readers zero readers → dies with container
observability spec declaration + own test ONLY (enableMetrics/enableTracing/enableProfiling/metricsInterval) same scan configuration zero readers → dies with container

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 (+ embedded DistributedStateConfigSchema), PluginStateSnapshotSchema and their types — the input vocabularies of the kept host-driven classes. packages/core is untouched.

Route 3 (the #8715 identity/ApiKey shape): 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 is RETIRED_DEFS_BY_MAJOR[18] (kernel/AdvancedPluginLifecycleConfig, kernel/GracefulDegradation, kernel/PluginUpdateStrategy) + D3 semantic entry advanced-plugin-lifecycle-config-retired (one file per entry; gen:migration-registry concatenated — 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 via export-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)

Changeset grade

@objectstack/spec: minor with [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 cb59746d unless noted)

  • pnpm --filter @objectstack/spec build — exit 0 (gate route evidence above printed by this run's pre-merge twin at ef5632b; the merged-head check:generated re-proves the artifacts)
  • pnpm --filter @objectstack/spec run check:generated✓ All 14 generated artifacts are up to date.
  • pnpm --filter @objectstack/spec testTest 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 no typecheck script; its dts-emitting build is the type gate)
  • pnpm --filter @objectstack/core testTest Files 38 passed (38) · Tests 955 passed (955) (health-monitor / hot-reload / kernel suites — classes kept, all green)
  • Reverse type verification against the rebuilt dist (consumer side, downstream direction): importing the 3 removed names from @objectstack/spec/kernelerror TS2305 ×3 (expected red); positive control importing 5 kept names → exit 0.
  • Gate battery (union re-derived by scripts/pm/dispatch-gates.mjs, no args, answer stamped objectstack-ai/objectstack at this tree): 45 root/spec/lint gates exit 0, including check: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/dogfood test/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):

Out of scope, recorded for PM triage

HotReloadConfig.stateStrategy 'disk' and 'distributed' are silent memory fallbacks inside the KEPT class (hot-reload.ts state manager), and hotReload.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

claude added 2 commits August 25, 2026 17:46
…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
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

11 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️ 10 changed file(s) yielded no anchor (packages/spec/PLUGIN_STANDARDS.md, packages/spec/PROTOCOL_MAP.md, packages/spec/api-surface/kernel.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 10 changed file(s) yielded no anchor (packages/spec/PLUGIN_STANDARDS.md, packages/spec/PROTOCOL_MAP.md, packages/spec/api-surface/kernel.json, …) — pages documenting those are invisible to this run
  • 4 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 45 of 222 client-bound route-ledger rows — the other 177 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 177: 14 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 56 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 107 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.

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 cf99875ea88a6a611353442e76c93de70727b74dpackageMentionDocs.

Which tree this was computed on

This run read content/docs from 18361bedeea406d623c343a9f8dc4264a163ddc6 — the merge of head cb59746d8709c6225566f36259b4b94a0e31c710 into base cf99875ea88a6a611353442e76c93de70727b74d, 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 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

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

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Aug 25, 2026
@os-litant
os-litant marked this pull request as ready for review August 25, 2026 19:49
@os-litant
os-litant added this pull request to the merge queue Aug 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Aug 25, 2026
@os-litant
os-litant enabled auto-merge August 25, 2026 20:37
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

2 participants