feat(cli): preflight installable provider for required capabilities (#3366)#3385
Merged
Merged
Conversation
…3366) A capability in `requires: [...]` was only checked at serve time, and a missing provider printed a generic "not installed — add it to your dependencies" even when the provider has no installable version in the current edition (e.g. `ai` -> @objectstack/service-ai, cloud-only since ADR-0025). `os validate` (token vocabulary only) and `os build` (never resolved providers) both passed, so a validate && build && test CI script never caught it — it surfaced only as an opaque `os start` crash. - spec: add `PLATFORM_CAPABILITY_PROVIDERS` (token -> package + edition) and a pure `classifyRequiredCapability()` — one machine-readable source of truth for the provider/edition knowledge the serve resolver encoded informally. A drift test keeps it 1:1 with the vocabulary and in agreement with serve's CAPABILITY_PROVIDERS packages. - cli: `capability-preflight.ts` resolves each declared capability's provider the way serve loads it (host dir, then CLI deps) and renders an edition-aware message. `os build` and `os validate` fail fast on a `requires` entry with no installable provider in the active edition; an absent-but-installable provider is an advisory `pnpm add` hint; a satisfied list passes unchanged. - cli: the `os serve` boot error now renders the same classification, so preflight and boot read identically. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013CQ5vX12KRiZ7mn1U4bSwQ
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 110 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…ports `check:api-surface` gates the @objectstack/spec public API. The #3366 additions (PLATFORM_CAPABILITY_PROVIDERS, classifyRequiredCapability, and their types) are additive (0 breaking, 12 added) — regenerate the committed snapshot so the gate passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013CQ5vX12KRiZ7mn1U4bSwQ
os-zhuang
marked this pull request as ready for review
July 21, 2026 14:25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3366.
Problem
A capability listed in
requires: [...]is fail-fast atserve/starttime when its provider package is missing — but when the provider has no installable version in the current edition, the generic "not installed, add it to your dependencies" advice is un-followable. Nothing shifted this left:os validateonly checks the token against the vocabulary (ADR-0066), andos buildnever resolves providers or boots the runtime, so avalidate && build && testCI script never caught it. It surfaced only as an opaqueos startcrash — seen upgrading an open-edition app from14.7to16after@objectstack/service-aiwent cloud-only (ADR-0025).Change
One machine-readable source of truth (spec).
@objectstack/spec/kernelnow exportsPLATFORM_CAPABILITY_PROVIDERS(every vocabulary token → provider package + edition:open/enterprise/cloud) and a pureclassifyRequiredCapability(token, isInstalled). This lifts the provider/edition knowledge the serve resolver encoded informally (itsCAPABILITY_PROVIDERSmap + tier gating) into data a preflight can read before boot.Shift-left gate (cli). A new
capability-preflight.tsutil resolves each declared capability's provider the same wayserveloads it (host app dir, then the CLI's own deps where the framework@objectstack/*providers live) and renders an edition-aware message. Wired intoos buildandos validate:ai→@objectstack/service-ai, cloud-only) → fails fast with the edition-aware message.pnpm addhint, not a hard error.requires→ passes unchanged.Identical boot message (cli). The two
os servefail-fast sites (the AI block and theCAPABILITY_PROVIDERSloop) now render the same classification, so preflight and boot read identically.Example, from
os validate/os buildon arequires: ['ai']app under the open edition:Tests
packages/spec/.../platform-capabilities.test.ts— registry shape + classifier (ok / installable / unavailable / unknown; injected resolution, no I/O).packages/cli/test/capability-preflight.test.ts— preflight aggregation, message rendering,missingProviderMessageproving serve and build render identically, and real on-disk resolution.packages/cli/test/serve-capability-vocabulary.test.ts— extended drift guard: the registry stays 1:1 with the vocabulary and agrees with serve'sCAPABILITY_PROVIDERSpackages;ai/ai-studioare cloud-only.aifails bothvalidateandbuild; a satisfied list and an absent-but-installable (enterprise) provider behave as specified.Notes
@objectstack/spec+@objectstack/cli, minor).🤖 Generated with Claude Code
https://claude.ai/code/session_013CQ5vX12KRiZ7mn1U4bSwQ
Generated by Claude Code