You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tracking card for the upstream half of hotcrm's ADR-0130 package split. The downstream epic is objectstack-ai/hotcrm#1904; the blocked packaging card is objectstack-ai/hotcrm#1907, whose branch is built, runtime-proven and waiting.
This card exists because the dependency is a set plus a release, and until now no single carrier named the sequence. Filed at the maintainer's prompt (「objectstack 是否也应该开一个专题卡跟踪」).
The one sentence
hotcrm cannot land two packages in one artifact until a released@objectstack/* line carries the #18202 spec fix alongside the already-merged #17066 lint/cli change. Everything else on this list is authoring ergonomics, not a gate.
packages/spec/src/stack.zod.ts:2021, if (objectNames.size === 0) return errors; — present on origin/main, identical in the published dist; that validator has no dependency awareness anywhere. Fix PR #18212 delivered and ACCEPTed by the PM 2026-09-14 (draft, final head b0072379, 4 commits / 4 files, RED 0, CI still running). DefineStackOptions.artifactObjects widens the two ARTIFACT-SCOPED classes to resolve against the artifact, and composeStacks gained an ARTIFACT pass — measured necessary, since composeStacks ran no cross-reference validation at all before this PR. hooks[].object and app navigation objectName stay refused (ADR-0130 §1.5). This WAS the only upstream code gate, and it is now closed. Four rounds of at-tier contract review (two FAIL, then PASS, then a fourth on the merged-forward tree after the PM cleared the gate 19 seconds before moving the head); landed through the queue, squash, single parent. artifactObjects is on main.
#18204 — per-package author-time rules refuse an action param's record-picker reference to a dependency's object
✅ CLOSED 2026-09-15 — premise falsified; never a code gate
Fixed on origin/main by f89dd33cc … (#17066): artifactProvidedObjectNames is defined at packages/lint/src/validate-object-references.ts:162 and called at :209. Absent from the published @objectstack/lint@17.4.0 hotcrm pins. PR #18213 added two-tier regression pins plus an ablation; no behaviour change. Contract review PASS (rendered by an at-tier isolated reviewer, adopted verbatim), merged through the queue 2026-09-15T01:18:19Z as fb3c6b4f6 (squash, single parent). The card closed on its Fixes keyword; pm:dispatched and the assignee came off in the same stroke.
The release itself
🔴 the ONLY remaining link
packages/{spec,lint,cli} are all at 17.4.0 on main with a large unreleased changeset backlog. Merged upstream is not available in a pin (hotcrm AGENTS.md, Platform Upgrades). ⇒ the release is the last link, and it has no carrier other than this card.
Not blocking — filed from the same work, awaiting triage
translation-target-unknown reads apps[].navigation only, so every locale key for a navigationContributions item looks unknown — 15 warnings on hotcrm's branch. Warnings only.
The ADR-0046 package-docs collector reads <config dir>/src/docs only. Moving a docs directory under a package layout exits 0 and silently drops docs[]. Forced hotcrm's plan item 6 (src/docs/ stays at the top of src/).
A shared picklist (global value set) metadata kind.
The open design question this set sits on
#14488 (closed) proposed the mirror of navigationContributions for authorization: a module contributes its own objects' permission grants into app-owned roles. That is exactly the shape #18202's refusal is about, approached from the other side.
Route A is in force and #18212 implements it. Recorded here so route B is not re-derived from scratch later.
⚠️ One PM framing was falsified in the course of route A and is corrected here so it is not repeated: the original #18202 title said the refused object was owned by a declared dependency. Measured on the repro branch (hotcrm be11c07), the failing stack is the type: app package, which declares no dependencies at all; the module declares the edge, and ADR-0116's topological order admits only module → app. So the resolution scope is the artifact, never the declaring package's dependency closure — a closure-scoped rule would refuse the very shape the addendum makes mandatory. The card title has been corrected.
Deliberately left open by #18212 — so nobody rediscovers it
composeStacks preserves one leniency verbatim, pinned in both directions by the new tests: an input stack that declares no objects at all can still contribute a permission grant or a seed reference that nothing anywhere refuses. Closing it would newly refuse compositions that pass today — references served by a plugin outside the composition — so the fix does not touch it, and the reason is now written at the ARTIFACT pass rather than left to be rediscovered.
Two reference classes also stay stack-scoped on purpose: view data.object / mappings[].targetObject, and actions[].objectName. PM ruling: leave them, and do not open a speculative card. Nothing in ADR-0130 or ADR-0086 rules on a view over, or an action bound to, a sibling package's object, and this round measured no consumer that needs it — hotcrm's branch has no sales-side view crossing into a service object. The argument for widening them is recorded in PR #18212's body; whoever first meets a real shape files the card with that shape attached.
The release step — what is actually available, measured
The epic's last link is a release, and it has two shapes. Both are the maintainer's to pull; neither is something a PM seat can trigger.
Full release.pnpm release off the standing "Version Packages" PR. Slow here by design — that PR is force-refreshed on every push to main, and main moves roughly 18 merges a working day.
RC cut — the fast path..github/workflows/cut-rc.yml exists precisely because the full lane cannot converge on a busy main: it snapshots one main sha and does every downstream step against that frozen value. It is workflow_dispatch-only, environment: release-gated, and a human types the exact version — the file states this is deliberate, under the 2026-08-07 ruling 「版本发布必须是人工的」. So it is available today, and it is a maintainer action.
What an rc would mean downstream, measured rather than assumed:
hotcrm pins 21@objectstack/* packages, all at 17.4.0, and its AGENTS.md Platform Upgrades requires they be bumped together (version-locked) with specVersion in objectstack.manifest.json updated in the same stroke.
hotcrm has pinned an rc zero times in its history (git log -S'-rc.' -- package.json → 0 commits). This would be new practice for that repo.
Nothing in hotcrm's upgrade policy forbids it. The gate is practice, not a rule.
objectstack already carries check:prerelease-pins and a prerelease-pin-watch workflow, so a prerelease pin is a supported state upstream.
⇒ If the maintainer wants #1907 unblocked before the next full release, the RC cut is the lever, and the only new thing it asks of hotcrm is its first rc pin.
hotcrm bumps all 21 pins together (plus specVersion) and pnpm validate on claude/issue-1907-sales-app-service-module reports zero cross-reference issues.
Tracking card for the upstream half of hotcrm's ADR-0130 package split. The downstream epic is objectstack-ai/hotcrm#1904; the blocked packaging card is objectstack-ai/hotcrm#1907, whose branch is built, runtime-proven and waiting.
This card exists because the dependency is a set plus a release, and until now no single carrier named the sequence. Filed at the maintainer's prompt (「objectstack 是否也应该开一个专题卡跟踪」).
The one sentence
hotcrm cannot land two packages in one artifact until a released
@objectstack/*line carries the #18202 spec fix alongside the already-merged #17066 lint/cli change. Everything else on this list is authoring ergonomics, not a gate.Blocking — the release path
defineStack's per-stack cross-reference validation refusespermissions[].objects/data[].objectnaming a dependency's objectb8ec127b4packages/spec/src/stack.zod.ts:2021,if (objectNames.size === 0) return errors;— present onorigin/main, identical in the published dist; that validator has no dependency awareness anywhere. Fix PR #18212 delivered and ACCEPTed by the PM 2026-09-14 (draft, final headb0072379, 4 commits / 4 files, RED 0, CI still running).DefineStackOptions.artifactObjectswidens the two ARTIFACT-SCOPED classes to resolve against the artifact, andcomposeStacksgained an ARTIFACT pass — measured necessary, sincecomposeStacksran no cross-reference validation at all before this PR.hooks[].objectand appnavigationobjectName stay refused (ADR-0130 §1.5). This WAS the only upstream code gate, and it is now closed. Four rounds of at-tier contract review (two FAIL, then PASS, then a fourth on the merged-forward tree after the PM cleared the gate 19 seconds before moving the head); landed through the queue, squash, single parent.artifactObjectsis onmain.referenceto a dependency's objectorigin/mainbyf89dd33cc … (#17066):artifactProvidedObjectNamesis defined atpackages/lint/src/validate-object-references.ts:162and called at:209. Absent from the published@objectstack/lint@17.4.0hotcrm pins. PR #18213 added two-tier regression pins plus an ablation; no behaviour change. Contract review PASS (rendered by an at-tier isolated reviewer, adopted verbatim), merged through the queue 2026-09-15T01:18:19Z asfb3c6b4f6(squash, single parent). The card closed on itsFixeskeyword;pm:dispatchedand the assignee came off in the same stroke.packages/{spec,lint,cli}are all at17.4.0onmainwith a large unreleased changeset backlog. Merged upstream is not available in a pin (hotcrm AGENTS.md, Platform Upgrades). ⇒ the release is the last link, and it has no carrier other than this card.Not blocking — filed from the same work, awaiting triage
translation-target-unknownreadsapps[].navigationonly, so every locale key for anavigationContributionsitem looks unknown — 15 warnings on hotcrm's branch. Warnings only.<config dir>/src/docsonly. Moving a docs directory under a package layout exits 0 and silently dropsdocs[]. Forced hotcrm's plan item 6 (src/docs/stays at the top ofsrc/).objectstack.config.tsmay carry no named export — the build parses the whole config module against the strict stack schema, undocumented.ctx.api(HookApi/HookObjectApi/HookQuery) — hand-declared in every metadata app today.The open design question this set sits on
#14488 (closed) proposed the mirror of
navigationContributionsfor authorization: a module contributes its own objects' permission grants into app-owned roles. That is exactly the shape #18202's refusal is about, approached from the other side.Two routes, and the choice is the maintainer's:
defineStack's per-stack cross-reference validation refusespermissions[].objectsanddata[].objectthat name an object owned by ANOTHER PACKAGE OF THE SAME ARTIFACT — so ADR-0130's co-owned artifact and the "permission sets stay whole in the app package" addendum cannot both hold once the app package owns objects #18202 is fixed so a stack may grant on a dependency's object. hotcrm's branch lands unchanged.navigationContributions)—— ADR-0130 分拆第二阶段,不挡发版 #14488 reopened and decided. hotcrm's branch would be reshaped.Route A is in force and #18212 implements it. Recorded here so route B is not re-derived from scratch later.
be11c07), the failing stack is thetype: apppackage, which declares no dependencies at all; the module declares the edge, and ADR-0116's topological order admits only module → app. So the resolution scope is the artifact, never the declaring package's dependency closure — a closure-scoped rule would refuse the very shape the addendum makes mandatory. The card title has been corrected.Deliberately left open by #18212 — so nobody rediscovers it
composeStackspreserves one leniency verbatim, pinned in both directions by the new tests: an input stack that declares no objects at all can still contribute a permission grant or a seed reference that nothing anywhere refuses. Closing it would newly refuse compositions that pass today — references served by a plugin outside the composition — so the fix does not touch it, and the reason is now written at the ARTIFACT pass rather than left to be rediscovered.Two reference classes also stay stack-scoped on purpose: view
data.object/mappings[].targetObject, andactions[].objectName. PM ruling: leave them, and do not open a speculative card. Nothing in ADR-0130 or ADR-0086 rules on a view over, or an action bound to, a sibling package's object, and this round measured no consumer that needs it — hotcrm's branch has no sales-side view crossing into a service object. The argument for widening them is recorded in PR #18212's body; whoever first meets a real shape files the card with that shape attached.The release step — what is actually available, measured
The epic's last link is a release, and it has two shapes. Both are the maintainer's to pull; neither is something a PM seat can trigger.
Full release.
pnpm releaseoff the standing "Version Packages" PR. Slow here by design — that PR is force-refreshed on every push tomain, andmainmoves roughly 18 merges a working day.RC cut — the fast path.
.github/workflows/cut-rc.ymlexists precisely because the full lane cannot converge on a busymain: it snapshots onemainsha and does every downstream step against that frozen value. It isworkflow_dispatch-only,environment: release-gated, and a human types the exact version — the file states this is deliberate, under the 2026-08-07 ruling 「版本发布必须是人工的」. So it is available today, and it is a maintainer action.What an rc would mean downstream, measured rather than assumed:
@objectstack/*packages, all at17.4.0, and its AGENTS.md Platform Upgrades requires they be bumped together (version-locked) withspecVersioninobjectstack.manifest.jsonupdated in the same stroke.git log -S'-rc.' -- package.json→ 0 commits). This would be new practice for that repo.check:prerelease-pinsand aprerelease-pin-watchworkflow, so a prerelease pin is a supported state upstream.⇒ If the maintainer wants #1907 unblocked before the next full release, the RC cut is the lever, and the only new thing it asks of hotcrm is its first rc pin.
Done when
defineStack's per-stack cross-reference validation refusespermissions[].objectsanddata[].objectthat name an object owned by ANOTHER PACKAGE OF THE SAME ARTIFACT — so ADR-0130's co-owned artifact and the "permission sets stay whole in the app package" addendum cannot both hold once the app package owns objects #18202 merged.@objectstack/*line — a full release or an rc — carries it and fix(cli, lint): gate a dangling lookup/master_detail reference, and resolve one across the artifact packages[] #17066.specVersion) andpnpm validateonclaude/issue-1907-sales-app-service-modulereports zero cross-reference issues.Steps 1 and 2 are this card's; step 3 is objectstack-ai/hotcrm#1907's.
Generated by Claude Code