Repository navigation
fix(cli): os build carries a package-relative OpenAPI connector spec into the artifact - #28533
Conversation
…into the artifact Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U
… install pin Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U
…rtifact; changeset Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U
…p-package-file-install
📓 Docs Drift CheckThis PR changes 1 package(s): 21 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 6 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 35 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 9a77ea3ed31a58755d68bda5dba16c9b9afb1563 && git checkout 9a77ea3ed31a58755d68bda5dba16c9b9afb1563
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 37184244b82b9e4234581b653cdc7554e74e6136 842ba0f7cb1392adc5de5d98af4f2cef1902864d && git checkout -B drift-repro 37184244b82b9e4234581b653cdc7554e74e6136 && git merge --no-ff 842ba0f7cb1392adc5de5d98af4f2cef1902864d
node scripts/docs-audit/affected-docs.mjs --json 37184244b82b9e4234581b653cdc7554e74e6136
|
|
epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U 席位核对ACCEPT at head
Out of scope, filed: #28534 is the runtime half of the defect: the materializer resolves an installed package's file ref against the host's root, and the dev measured it binding the host's own document. It is a child of #27293 and carries the dev's options A/B/C. #28535 is a separate defect: Landing: not governed. The seat lands it ( |
…h new sites in the parity ledgers Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U
|
epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U 席位核对ACCEPT at head
Landing: not governed. The seat lands it now ( |
Fixes #28505
Clause-②: no
Metadata-protocol: none
维护者速读
os build现在把provider: 'openapi'连接器以包内相对路径引用的 OpenAPI 文档读出来,直接内联写进dist/objectstack.json;路径无效时构建失败。os package install或市场安装)只带过去那份 JSON,路径会按宿主自己的目录解析,找不到文件,连接器静默不出现;Stripe 应用装上即用不了。providerConfig.spec由路径变成对象,体积随文档增大(Stripe 由约 4.7 KB 到 59.8 KB);读产物的云端流水线需接受内联形态(spec 本就允许)。回滚即还原本 PR,源码不需要改。packages/cli/src/utils/bundle-connector-spec-files.ts(只识别 openapi 的spec字符串且非 http(s) 的那一种);packages/cli/src/commands/compile.ts新增的 4a-bis 段;packages/qa/dogfood/test/install-local-connector-spec-file.dogfood.test.ts。pnpm --filter @objectstack/connector-app-stripe build,预期输出一行Bundling connector spec files... 1 document (46.0 KB),且dist/objectstack.json里connectors[0].providerConfig.spec.openapi为3.0.0。What changes
os buildcarries a package-relative OpenAPI spec into the artifact. Newpackages/cli/src/utils/bundle-connector-spec-files.ts, wired incompile.tsright after the seed-file bundling, split the same way (collect= the gate,place= the assembly). For every connector entry (top level,manifest, and eachpackages[i].manifestbody) withprovider: 'openapi'whoseproviderConfig.specis a non-empty string that is not an http(s) URL, the file is read relative to the directory holdingobjectstack.config.ts, confined to it by the runtime loader's own rule, parsed as JSON, and written in place of the path. Every other provider, key and form is written as before.connectors[0].providerConfig.spec), in the text face and in--json.content/docs/automation/connectors.mdx(theprovider: 'openapi'section) says the build carries the file.@objectstack/clipatch.What this changes for readers of the artifact (the cloud ingestion pipeline among them): an artifact built by this CLI carries
providerConfig.specas the inline document object, never the path, and is larger by the document's size. The inline form is one the spec schema (providerConfig: z.record(z.string(), z.unknown())) and theopenapiprovider already accept; nopackages/specchange.The measurement (before any code), at
23d1303dScratch app,
provider: 'openapi',providerConfig.spec: './openapi/fixture.openapi.json',auth: bearerwith the credential set:os buildwrotedist/objectstack.json(0.7 KB) withproviderConfig: { spec: './openapi/fixture.openapi.json' }, no document.POST /api/v1/marketplace/install-local, body exactly aspackages/cli/src/commands/package/install.tsbuilds it for an artifact file:200,hotLoaded: true,credentialRefs[0].status: set.GET /api/v1/automation/connectorsdid not list the instance at all (not even degraded):The install door caches the artifact JSON alone (
STORAGE_DIR/SAFE_ID.json,marketplace-install-local-plugin.tsheader), andservice-automationhands every instancecreatePackageFileLoader(this.options.packageRoot), the host's root. An installed package has no directory on disk, so "resolve against the installed package's own root" (route b) has nothing to resolve against without the artifact carrying the file anyway; route (a) needs no contract change, so it is the route taken. ADR-0097 (§ Deliberate scope boundaries) describes the file form as resolved against "the declaring stack/package root (packageRoot, CLI default: theobjectstack.config.tsdirectory)" and does not anticipate an installed package having a root of its own.After the fix, the real Stripe app (
packages/apps/connector-stripe, now onmain) builds to 59.8 KB with the 46.0 KB document inline, and installed into the showcase the same way it materializesreadywith its eight actions.Tests
packages/cli/src/utils/bundle-connector-spec-files.test.ts(unit tier): carried with its other keys kept; manifest andpackages[]bodies; inline document, http(s) URL, another provider and a descriptor left as written; five refusals, each located and naming the reference, nothing changed.packages/qa/dogfood/test/install-local-connector-spec-file.dogfood.test.ts: spawns the BUILTos buildon a one-connector app, asserts the artifact carries the document, installs it into the showcase through install-local and assertsGET /automation/connectorslists the instancereadywith the document's operation. Declares a measuredtest-budget: 20(class: spawns the real producer once per single-cause fixture).Red before, green after, one ablation (dogfood file, reads the CLI's dist)
main:Tests 2 failed (2)—expected './openapi/fixture.openapi.json' to deeply equal { openapi: '3.0.3', …(3) }; the listing held only the showcase's five connectors.pnpm --filter @objectstack/cli build:Tests 2 passed (2).9b81f435:node scripts/ablation-replace.mjs --file packages/cli/src/commands/compile.ts --anchor 'placeConnectorSpecFiles(connectorSpecs);' --replacement 'void placeConnectorSpecFiles; /* ABLATED_SPEC_PLACE */' -- …→anchor 1 -> 0, blob daba252de551 -> 0994c37b6d13; rebuild;ablation-dist-preflight @objectstack/cli ABLATED_SPEC_PLACE→marker present in 1 built file;Tests 2 failed (2); restoredblob == HEAD (daba252de551) and git diff HEAD is empty. Restore leg: rebuild; preflight--absent→marker absent from all 772 built files,working tree clean against HEAD;Tests 2 passed (2).Final head f6ca481 (after merging origin/main)
pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 src/utils/bundle-connector-spec-files.test.ts src/utils/bundle-seed-files.test.ts→Tests 16 passed (16).pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/install-local-connector-spec-file.dogfood.test.ts→Tests 2 passed (2).pnpm --filter @objectstack/connector-app-stripe test→Tests 16 passed (16).pnpm --filter @objectstack/cli typecheckandpnpm --filter @objectstack/dogfood typecheck→ exit 0 (tsc --listFiles: the dogfood program holds the new test; the CLI'stsconfig.jsonprogram coverssrc/**tests).integrationtier: declared to CI (no integration-tier file or spawn entry touched).Acceptance notes
os validatedoes not run this gate; onlyos builddoes (seed files run in both). A missing spec file is therefore refused at build, not at validate.os dev's watcher watchesobjectstack.config.tsandsrc/; a spec file outsidesrc/(the Stripe app's./openapi/) edited duringos devreaches the running artifact at the next recompile, not on its own.loadPackageFile/resolvePackagePathstill resolve an installed package's file ref against the host root. Measured: an installed package naming./src/system/connectors/status-openapi.jsonmaterializedreadywith the showcase host's own document. Reported for a separate card, not fixed here.skills/objectstack-automation/references/integration-recipes.mdrecipe 1 stays correct ("ships in the package").Verification
Derived gate families, local, head f6ca481
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack→ 90 commands; all 90 run, exit 0 each (two first exited 3, PREREQUISITE NOT MET for unbuilt packages outside this diff —check:skill-examplesneeded@objectstack/client-reactdist,check:dual-build-cjs-loadsseven package dists; built, re-run:278 prose examples type-check across 3 surface(s)and113 published require entry point(s) across 70 package(s) load).--ranreconciliation:90 derived famil(ies) accounted for — 90 run, 0 NOT-MEASURED. Repo-wide scans (pnpm lint) andtest:repoare CI's.Generated by Claude Code