Repository navigation
feat(spec,runtime): a package export carries its namespace and dependencies, so a reinstalled .custom pair keeps both (#29617) - #29651
Conversation
…encies (#29617) PackageExportManifestSchema declares namespace and dependencies as optional fixed keys, each the install manifest's own shape; assemblePackageManifest writes both from the package's registry row, so a reinstalled .custom pair keeps its namespace and the edge to its base. Claude-Session: https://claude.ai/code/session_01JQwxbWPCwHb9Zxnf7ou79C Co-authored-by: Claude <noreply@anthropic.com>
…nd trip through install-local; changeset Claude-Session: https://claude.ai/code/session_01JQwxbWPCwHb9Zxnf7ou79C Co-authored-by: Claude <noreply@anthropic.com>
…'s namespace and dependencies Claude-Session: https://claude.ai/code/session_01JQwxbWPCwHb9Zxnf7ou79C Co-authored-by: Claude <noreply@anthropic.com>
…hheldMaps; regenerate Claude-Session: https://claude.ai/code/session_01JQwxbWPCwHb9Zxnf7ou79C Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check1 anchor(s) derived from 2 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 173 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 652f0ff54d3aabae099d4132b8a2af1b6c4dcfa9 && git checkout 652f0ff54d3aabae099d4132b8a2af1b6c4dcfa9
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 3482f3d8d2c48ec8d2e3306f1ce26c0364e800c2 3d93d712732f2ee47fc2566e072cc6fd2c1d3ce6 && git checkout -B drift-repro 3482f3d8d2c48ec8d2e3306f1ce26c0364e800c2 && git merge --no-ff 3d93d712732f2ee47fc2566e072cc6fd2c1d3ce6
node scripts/docs-audit/affected-docs.mjs --json 3482f3d8d2c48ec8d2e3306f1ce26c0364e800c2 |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract-review-claim: session_01AavokzJ5DndAwitDXvKy4U · head 3d93d71 · 2026-11-03T00:25Z Taken under (c): the spec lane's seats have stood down. There is no record yet. Generated by Claude Code |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract reviewServed-tier: Inputs read:
Taken by triage under (c): the ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgmentReading both keys off the registry row, with the install manifest's own schema as the contract, is the minimal true fix. The export now carries what an install decides by, under the same names the install door reads, with no translation layer. Writing nothing when the row declares nothing keeps old exports and non-pair packages byte-identical. Tried to break it:
Must-fix: none. Should-fix: none. Implemented-by: VERDICT: PASS Generated by Claude Code |
|
domain:spec#3 · os-support-ai · session_01WGufzfgvGexKn9vLHsy89K 维护者速读
席位意见:最小真修复,形状零新增(两键均为 席位核对 — ACCEPT · domain:spec#3 · head
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 41555880282 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
domain:spec#3 · os-support-ai · session_01WGufzfgvGexKn9vLHsy89K
Requested by Warren · project thread
Fixes #29617
Clause-②: yes (widening)
Metadata-protocol: added
Skills-docs: none — both keys are written by the export door from the registry row and read by the install door; no author writes them, and
skills/objectstack-platform/SKILL.mdalready sends the reader to the pair's export, which now reinstalls whole维护者速读
GET /packages/:id/export的导出清单新增两个可选固定键namespace与dependencies,从包的注册表行读取并写出;spec 的PackageExportManifestSchema同步声明这两个键(形状直接复用安装清单ManifestSchema的同名键)。.custom配对包丢了命名空间(落到custom)和对基础包的依赖;实测重装直接被 ADR-0146 D2 覆盖闸门拒绝403 NOT_OVERRIDABLE。packages/runtime/src/domains/packages.ts中assemblePackageManifest末尾新增的两行;packages/spec/src/api/package-lifecycle.zod.ts的两个新键;dogfood 新测试package-export-reinstall-custom-pair.dogfood.test.ts。pnpm --filter @objectstack/dogfood exec vitest run test/package-export-reinstall-custom-pair.dogfood.test.ts,预期 3 条全绿(源端导出带两键、目标端重装 200、重装后注册表行命名空间为showcase_custom且依赖指向 showcase)。What changes
PackageExportManifestSchema(packages/spec/src/api/package-lifecycle.zod.ts) declares two more optional fixed keys,namespaceanddependencies. Each is the install manifest's own declaration,ManifestSchema.shape.namespace/ManifestSchema.shape.dependencies, re-described for the export, so an export refuses exactly what an install would. The schema stays open for the per-type collections.assemblePackageManifest(packages/runtime/src/domains/packages.ts) writes both from the package's registry row (registry.getPackage(id).manifest), as the row declares them, and writes neither when the row declares none.dependenciesis a copy of the row's map.packages/spec/authorable-surface/api.json(two rows) andcontent/docs/references/api/package-lifecycle.mdx.@objectstack/specminor and@objectstack/runtimeminor (the kind isadded, on both packages the diff moves).Why
Measured by the filer through the real door on
81cd9eb0, and again here by ablation on this branch: the export answered the pair's items withid,name,version, and none of the two keys its registry row holds. Reinstalled throughPOST /api/v1/marketplace/install-local, the pair had no namespace (the door derivescustomfrom the id) and no edge to its base. The edge is what orders the pair after its base (ADR-0141 D5) and what admits itsoverridesdeclarations at the managed install (ADR-0146 D2). With the emission ablated, the round-trip pin's install answers:This also unblocks the server slice of #28914 (the whole-ontology export), which composes this per-package export.
Out of scope
type. The export still does not writetype. Adding it alone would not make the export aPOST /packagesbody.POST /api/v1/packages. That door still refuses an export (400: notype, flat collection keys). It is not a reinstall door; install-local is the door that reinstalls an export.Name approval
The maintainer approved the two key names
namespaceanddependenciesonPackageExportManifestSchemaas named: Warren chose 「全部批准」 on the decision card 「六个命名/措辞全部按推荐批准吗?」 (item 6), project thread "Decide pending spec name approvals", 2026-11-03T00:08Z. Seat pointer on #29617: comment 6591852561.Tests
packages/qa/dogfood/test/package-export-reinstall-custom-pair.dogfood.test.ts). Source boot: the ensure door createscom.example.showcase.custom, a dashboard override is saved into it and published, and the pair's export carries thenamespace(showcase_custom) anddependencies(com.example.showcase) its registry row declares (the row is the control). Target boot, a fresh showcase with install-local mounted: the export installs 200, and the reinstalled pair's registry row declares the same namespace and the same edge to the showcase.packages/runtime/src/domains/packages-export-registry-row-keys.test.ts): the real dispatcher over a registry double. The pair's export carries both keys (a copy of the row's map) and parses asPackageExportManifestSchema; a row declaring neither writes neither;typestays out.packages/spec/src/api/package-lifecycle.test.ts, a new block at the end of the file): a pair's export parses and keeps both keys; both are optional; each refuses what an install would (1crm,Crm, a non-string range, an array); each describe names its source and the ADRs and no tracker id.scripts/ablation-replace.mjs, runtime rebuilt,ablation-dist-preflight.mjs runtime 'manifest.namespace = namespace' --absentpassed): the dogfood file went 3 of 3 red (source export lacksnamespace; install403 NOT_OVERRIDABLEas quoted above; target row404), the door pin 2 of 3 red. Restore provedblob == HEAD,git diff HEADempty,git status --porcelainempty; runtime rebuilt, preflight found the marker in 2 built files, and the dogfood file was 3 of 3 green again.Acceptance notes
withheldMaps, same schema), which merged while this branch was open. The new keys sit betweenversionandlabel, apart from feat(spec): the package export manifest declares withheldMaps, classified door for the unmanaged import #29521's lines;mainwas merged in atd280265b, its two generated artifacts (authorable-surface/api.json,package-lifecycle.mdx) regenerated from the merged tree rather than text-merged, and the docblock now counts "the seven fixed keys below" (the existing spec test title follows). The new spec tests are a block at the end ofpackage-lifecycle.test.ts.protocol.tsfile is touched (freeze until 2026-11-03 06:00Z).UNMANAGED_INSTALL_KEY_DISPOSITIONSneeds no row:namespaceanddependenciesare already classified there asManifestSchemakeys.Verification
Head
3d93d712(main merged atd280265b, which carries #29521; the merge's two generated artifacts were regenerated from the merged tree and the docblock now counts seven fixed keys).test/package-export-reinstall-custom-pair.dogfood.test.tsTests 3 passed (3); runtime export pins (4 files)Tests 12 passed (12); lockVERDICT command-exit 0.pnpm --filter @objectstack/spec testat3d93d712:Test Files 801 passed (801),Tests 23734 passed | 1 todo.pnpm typecheckfor spec, runtime and dogfood at3d93d712: exit 0.pnpm --filter @objectstack/runtime test: before the merge (6d249e4f)Test Files 530 passed (530),Tests 8515 passed | 19 skipped; the re-run at3d93d712was still running at hand-back (the merge brought one runtime test file and a vitest config line, no source).pnpm --filter @objectstack/spec check:generatedat3d93d712: all 14 artifacts current.--no-inline-config) on the five changed.tsfiles: exit 0. Repo-widepnpm lintis CI's.dispatch-gates --commands and the ran list
Before the merge (
6d249e4f, 105 derived): 100 ran, 97 exit 0. NOT MEASURED, exit 3 (prerequisite not met):node scripts/check-plugin-teardown-shape.mjs --self-test(its fixture commit is outside the shallow clone),pnpm check:dual-build-cjs-loads(needs every package'sdist/), andcheck:skill-examples(client-react unbuilt; after building it, exit 0, 281 examples type-check). The last five (check:type-check-debtonward) were stopped by the merge.After the merge (
3d93d712, 104 derived): re-running at hand-back; 45 had run, 44 exit 0, the samecheck-plugin-teardown-shape --self-testexit 3. CI runs every family.Human Minimum
packages/specholds no runtime logic.pnpm lintin CI).main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code