Repository navigation
feat(cloud-connection,metadata-core): an install the protocol handshake admitted unchecked says so in its answer - #30409
Conversation
…ke admitted unchecked says so in its answer
POST /api/v1/marketplace/install-local answers data.protocolCheckSkipped
({ reason, packageId, protocolVersion, message }, plus requiredRange and
rangeSource for unparsed-range) when the ADR-0087 handshake admitted the
package without checking it, on the managed, unmanaged and paired
customization success answers; omitted when the range was checked. The
reason is the handshake's own verdict: assertProtocolCompat now returns the
verdict it admitted the package under, and the no-range / unparsed-range
verdicts carry the protocolVersion they were judged against. The warn log
line stays.
Claude-Session: https://claude.ai/code/session_01Utp6CZ35sjTKgyrvdkytCz
Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CZ35sjTKgyrvdkytCz Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 11 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 4 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 10 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 779fd05b4856fb96e11734090c7af8cdd63d2cd1 && git checkout 779fd05b4856fb96e11734090c7af8cdd63d2cd1
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin fe835b49aadbe5ef51dd1b7d4a4922b4c9b97d8a 6c1d2ef227fc2a495b50947229606a7184c2ddae && git checkout -B drift-repro fe835b49aadbe5ef51dd1b7d4a4922b4c9b97d8a && git merge --no-ff 6c1d2ef227fc2a495b50947229606a7184c2ddae
node scripts/docs-audit/affected-docs.mjs --json fe835b49aadbe5ef51dd1b7d4a4922b4c9b97d8a
|
|
domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb 席位核对 · ACCEPT · 2026-11-05T10:08Z · head
|
Requested by Bill · project thread
domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb
维护者速读
engines.protocol)的应用时,安装成功的应答里多了protocolCheckSkipped:说明没做兼容性检查、按哪个协议版本装的,并带一句给管理员看的话;声明了版本范围、检查通过的包,应答和以前一字不差。assertProtocolCompat从无返回值改为返回它本来就算出的判决,旧调用方不受影响。回滚即撤本 PR,无数据迁移。packages/cloud-connection/src/marketplace-install-local-plugin.ts的protocolCheckSkippedOf和步骤 1c 里接住判决的那几行;packages/metadata-core/src/protocol-handshake.ts的assertProtocolCompat返回值。pnpm --filter @objectstack/cloud-connection exec vitest run src/marketplace-install-local-protocol-handshake.test.ts -t 30326,预期 5 条全绿;在 main 的代码上其中 4 条是红的(对照那条本来就绿)。Part of #30326
Clause-②: yes (widening) — the three success answers of
POST /api/v1/marketplace/install-localgain the optionaldata.protocolCheckSkipped;@objectstack/metadata-core'sassertProtocolCompatreturnsProtocolCompatAdmitted(new exported type) where it returnedvoid, and theno-range/unparsed-rangemembers of the exportedProtocolCompatResultgainprotocolVersion. Nothing accepted or answered is taken away.Metadata-protocol: none — an install answer and a runtime helper's return value, not anything a metadata author writes
Skills-docs: none —
git grep -n -i "install-local\|declares no engines\|without a compatibility check\|protocolCheck\|engines.protocol" -- skills(evals excluded) hits four lines:objectstack-platform/SKILL.md:118(a declared range is checked and an out-of-range app refused, still true),objectstack-platform/references/operations.md:106and:111(whatos package installand the plugin are),objectstack-upgrade/SKILL.md:87(where the declared range is read). None describes what an install answers for a package with no range.What changes
The card: "The install answer carries this, and the page shows it in plain words". The triage (6652014530) puts the server half in
marketplace-install-local-plugin.ts; the UI half is a laterdomain:uicard, so #30326 stays open after this PR (the seat releases it at landing).The handshake hands its verdict back.
assertProtocolCompat(ADR-0087 D1) already computed a verdict and threw onincompatible; forok,no-rangeandunparsed-rangeit returned nothing, so a door that answers a caller could only log. It now returns the verdictcheckProtocolCompatgave (ProtocolCompatAdmitted= every member butincompatible), and theno-range/unparsed-rangemembers carryprotocolVersion, the version they were judged against (theincompatiblemember and its diagnostic already did). No new judgement: the range is read once, by the handshake.The install answer carries the skipped check. Step 1c of
handleInstallkeeps the verdict, andprotocolCheckSkippedOfturns ano-rangeorunparsed-rangeverdict intoreasonis the handshake's ownstatusvalue, the stable machine code;packageIdis the id the door's id gate parsed;protocolVersionis the protocol the package was installed under unchecked;messagesays it in plain words for the person who pressed Install. It rides all three success answers: managed,unmanaged(installUnmanaged) and a paired customization package (installCustomizationPair), passed down the waywithheldMapsis. It is omitted, not nulled, when the range was checked, so that answer's key set is unchanged. Thewarnline[MarketplaceInstallLocal] [protocol] package '…' declares no engines.protocol range; …is unchanged.Why the code is in
reason, notcode. Acode:literal in the answer would be read bycheck:dispatcher-error-vocabularyas an ADR-0112 error code and would need a row in the spec ledger. This is a notice on a200, not an error code (the D6c familycheck:error-code-casingdescribes), and the handshake's own status value is the code the ruling asks for.Contract stop: measured, not reached
The order: stop if carrying the notice needs a
packages/specchange. Measured onfdad1786and again on870ebce3: no schema inpackages/spec/srcdescribes the install-local success answer. The spec'swithheldMaps(PackageExportManifestSchema) is the export manifest's, not the answer's;git grep -n "hotLoaded\|upgradedFrom\|credentialNote" -- packages/spec/src(three keys only this answer carries) hits nothing. The answer is a cloud-connection-internal REST shape, so the field is added there.Tests
marketplace-install-local-protocol-handshake.test.ts, new top-leveldescribe('[#30326] …'): an inline manifest with no range answersprotocolCheckSkipped{ reason: 'no-range', packageId, protocolVersion }with the plain-words message, is registered, and logs exactly one[protocol]warn line; the compiled artifactos package install FILEsends answers the same; a range the handshake cannot read (workspace:*) answersunparsed-rangewithrequiredRangeandrangeSource; anunmanagedinstall of the same package carries it; control: under^CURRENT_MAJORthe answer has noprotocolCheckSkippedkey. The harness'smountgained an optional protocolimportUnmanagedPackagestub for the unmanaged case.marketplace-install-local-customization-pair-install.test.ts, new top-leveldescribe: a pair export with no range answersno-range; with^CURRENT_MAJORno key.protocol-handshake.test.ts, new top-leveldescribe:assertProtocolCompatreturns theno-rangeandunparsed-rangeverdicts withprotocolVersion, and theokverdict equal tocheckProtocolCompat's.fdad1786with the fix reverted and the pins in: the 5 notice cases red (200with noprotocolCheckSkipped), the 2 controls green. With the fix: 43/43 in the two files.marketplace-install-local-jobs.test.ts: its fixture now declaresengines.protocol: ^CURRENT_MAJOR, as a scaffolded app does. Its jobs-free case pins the answer's exact key set, and the fixture declared no range, so with this change the set gainedprotocolCheckSkipped; with a declared range the pin keeps meaning "the jobs gate adds nothing".Suites and typecheck on 4d926a7
os-verify-lockVERDICT command-exit 0:@objectstack/metadata-coretypecheck exit 0,@objectstack/cloud-connectiontypecheck exit 0;@objectstack/metadata-coretest Test Files 23/23, Tests 911/911;@objectstack/cloud-connectiontest Test Files 70/70, Tests 877/877.Ablation
One leg, through
scripts/ablation-replace.mjson4d926a74: deletingprotocolCheckSkipped = protocolCheckSkippedOf(admitted, manifestId);(anchor 1 → 0, blob8e7fdb92→5f6c1432) turns the 5 notice cases red, 38 green; restored to blob == HEAD8e7fdb92,git diff HEADempty. The cloud-connection suite resolves@objectstack/metadata-coretosrc/(vitest alias), and the plugin is imported fromsrc/, so nodist/leg applies.Acceptance notes
POST /api/v1/packages(packages/runtime/src/domains/packages.ts,assertProtocolCompat(manifest)), still answers success with no notice for a package with no range. It is outside this order's surface; withassertProtocolCompatnow returning the verdict, the same spread there is a small follow-up. carrier: seat 5.os package installprints the answer'snote; whether the CLI also printsprotocolCheckSkippedis the CLI's call. carrier: seat 5.Verification
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon the final head6c1d2ef22(after mergingorigin/mainat8fad7b193): 60 families, the same list as on4d926a749. All 60 run, exit codes captured before any pipe, allexit 0;--ranreconciliation: 60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN. On4d926a749the same 60 were allexit 0aftergit fetch origin 621a4876gavecheck-plugin-teardown-shape --self-testits pinned fixture (it exits 3 on a shallow clone).pnpm lintexit 0 on4d926a749; the merge brought no file of this diff's packages.origin/main(fix(metadata-protocol,cli): os migrate packageless-overlays lists a package-less view container cannot_declare, and --apply never attempts it #30380, fix(spec): repoint the query.searchFields liveness row at engine-find.ts#expandSearchOnAst #30368) touchedmetadata-protocol,cliandspec, none of this diff's packages, so the suites and typechecks above were not re-run on6c1d2ef22.!in the title and no(narrowing)arm: no full dogfood run owed.Generated by Claude Code