Skip to content

Commit ee0e115

Browse files
docs: default record page remedies name the other package's page, not the whole package (#23831)
Fixes #23553 Clause-②: no ## What changed The package registry's `DEFAULT_RECORD_PAGE_CONFLICT` remedy already says "compose the deployment without the other package's page". Three sibling texts still told the author (or an AI) to drop the whole package. They now say the same thing as the registry, with no option name, package name or tracker number: | Site | Before | After | |---|---|---| | `packages/metadata-protocol/src/protocol.ts`: the save door's refusal (remedy clause only) | "…stays the default unless the deployment is composed without that package." | "…stays the default unless the deployment is composed without that package's page." | | `packages/spec/src/ui/page.zod.ts`: `PageSchema.isDefault` TSDoc | "…or compose the deployment without the package that ships the other." | "…or compose the deployment without the other package's page." | | `packages/spec/src/api/error-code-ledger.zod.ts`: source comment | "…or composing the deployment without the other package." | "…or composing the deployment without the other package's page." | The save door's pin (`packages/objectql/src/default-record-page-save-door.test.ts`) moves to the new text in the same commit. It is changed, not deleted. **The coupling.** `AppPlugin`'s `private bundle: any` gets a doc comment naming its readers outside the class. I chose this over a public readonly accessor because it is smaller and adds no public surface. Measuring the readers turned up three of them, not the one the card names: `stackDeclaresOrganizationRecordPage` (`@objectstack/core`), the translations check in `@objectstack/cli`'s `serve.ts`, and `graft-runtime-hooks.ts`. The comment names all three. Changeset: one file, `patch` for `@objectstack/spec` (it ships `src/**/*.zod.ts`), `@objectstack/metadata-protocol` (the refusal string is in `dist/index.js`) and `@objectstack/runtime`. For runtime I measured the built `dist/index.d.ts` and `dist/index.d.cts`: both carry the new comment, so the shipped text changes. ## Verification (head `be4b60867`) - Build: `turbo run build` for spec, metadata-protocol and runtime plus their closure: 31/31 tasks, `VERDICT command-exit 0`. - `pnpm --filter @objectstack/objectql exec vitest run --maxWorkers=2 src/default-record-page-save-door.test.ts`: 34/34 passed, run against the rebuilt `metadata-protocol` dist. The old remedy text occurs 0 times in `dist/index.js`, so the moved pin is reading the new string. - Typecheck for `@objectstack/objectql`, `@objectstack/metadata-protocol` and `@objectstack/runtime`: exit 0. - `pnpm --filter @objectstack/spec check:generated`: all 14 generated artifacts are up to date, `check:docs` included. - Derived gate list (`dispatch-gates --commands`): 93 families. 92 exit 0. `check:dual-build-cjs-loads` exited 3 (PREREQUISITE NOT MET: it needs a full `pnpm build`), so it was NOT MEASURED locally and CI runs it. `check-engine-split-ratio` and `check-plugin-teardown-shape --self-test` first refused on the shallow clone; after deepening, both exit 0. `--ran` reconciliation: 92 run, 1 NOT-MEASURED, 0 UNRUN. ## Acceptance notes - The D3 entry `18.page-default-record-page-one-per-object-refused.ts` already says "compose the deployment without that package's page", which matches the new wording, so it is left as is. - Nothing about refusals changes: `code`, `status`, `object` and `holders` are the same, and no `.describe()` changed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01CN3bgHivgMGBHWTNUbYCDp --- _Generated by [Claude Code](https://claude.ai/code/session_01CN3bgHivgMGBHWTNUbYCDp)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3c080a6 commit ee0e115

6 files changed

Lines changed: 32 additions & 5 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
'@objectstack/spec': patch
3+
'@objectstack/metadata-protocol': patch
4+
'@objectstack/runtime': patch
5+
---
6+
7+
docs: the default-record-page remedies name the other package's page, not the whole package
8+
9+
Clause-②: no
10+
11+
A second `isDefault: true` record page for one object is refused with `DEFAULT_RECORD_PAGE_CONFLICT`. The package registry's refusal already told the author to keep one default or "compose the deployment without the other package's page". Three sibling texts still told them to drop the whole package, though a deployment can keep a package and leave out the one page it ships:
12+
13+
- `@objectstack/metadata-protocol`: the metadata save door's refusal now reads "a page a package ships stays the default unless the deployment is composed without that package's page." Only the remedy clause changed; `code`, `status`, `object` and `holders` are unchanged.
14+
- `@objectstack/spec`: `PageSchema.isDefault`'s TSDoc and the error-code ledger's comment on `DEFAULT_RECORD_PAGE_CONFLICT` say the same.
15+
- `@objectstack/runtime`: `AppPlugin`'s private `bundle` field now documents the three readers outside the class that read it structurally, so a rename is not made blind.
16+
17+
No behaviour changes; nothing to migrate.

‎packages/metadata-protocol/src/protocol.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21757,7 +21757,7 @@ export class ObjectStackProtocolImplementation implements
2175721757
const others = named.length === 1 ? `${named[0]} already is` : `${named.join(' and ')} already are`;
2175821758
const remedy = unique.some((h) => h.shipped)
2175921759
? `Save '${saveName}' with \`isDefault: false\`: a page a package ships stays the default unless the `
21760-
+ `deployment is composed without that package.`
21760+
+ `deployment is composed without that package's page.`
2176121761
: `Save '${saveName}' with \`isDefault: false\`, or first save ${unique.map((h) => `'${h.page}'`).join(' and ')} `
2176221762
+ `with \`isDefault: false\` to make '${saveName}' the default instead.`;
2176321763
const err = new Error(

‎packages/objectql/src/default-record-page-save-door.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ describe.each(TOPOLOGIES)('%s kernel — a page saved as a second default record
194194
expectRefusal(outcome, 'env_org_detail', 'acme_org', `page 'acme_org_detail' of package '${PKG}'`);
195195
expect(String((outcome as { error?: any }).error?.message)).toContain(
196196
"Save 'env_org_detail' with `isDefault: false`: a page a package ships stays the default unless the deployment "
197-
+ 'is composed without that package.',
197+
+ "is composed without that package's page.",
198198
);
199199
expect(storedPages()).toEqual([]);
200200
});

‎packages/runtime/src/app-plugin.ts‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,16 @@ export class AppPlugin implements Plugin {
150150
*/
151151
requiresServices: string[] = ['manifest'];
152152

153+
/**
154+
* Private to the type checker only: three readers outside this class read
155+
* `bundle` structurally off a plugin entry, with no type to break when it
156+
* changes. `stackDeclaresOrganizationRecordPage` (`@objectstack/core`,
157+
* `stack-organization-record-page.ts`) looks for an app's own
158+
* `sys_organization` record page; `@objectstack/cli`'s `serve.ts` looks for
159+
* declared translations, and its `graft-runtime-hooks.ts` finds an app's
160+
* bundle by manifest id to graft hooks onto. Renaming or reshaping this
161+
* field silently blinds all three; change them together.
162+
*/
153163
private bundle: any;
154164
/** Memoized backing store for {@link collections}. */
155165
private resolvedCollections?: any;

‎packages/spec/src/api/error-code-ledger.zod.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ export const ERROR_CODE_LEDGER = {
946946
// two HTTP install doors call `installPackage`. Its own code rather than
947947
// `NAMESPACE_CONFLICT`: no name is taken — an object's one default slot is
948948
// held — and renaming fixes nothing; the remedy is `isDefault: false` on
949-
// one page, or composing the deployment without the other package. Not a
949+
// one page, or composing the deployment without the other package's page. Not a
950950
// synonym of any standard member: the manifest is well-formed, and the
951951
// refusal comes from what the deployment already holds.
952952
'DEFAULT_RECORD_PAGE_CONFLICT',

‎packages/spec/src/ui/page.zod.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,8 +1871,8 @@ export const PageSchema = lazySchema(() => strictObject({
18711871
* objectstack#23015, record 6134056653.)
18721872
*
18731873
* To change which page opens: set `isDefault: false` on one of the two, or
1874-
* compose the deployment without the package that ships the other. Shipping
1875-
* a second default is not an override path.
1874+
* compose the deployment without the other package's page. Shipping a
1875+
* second default is not an override path.
18761876
*
18771877
* `isDefault: true` on a page that is not a record page bound to an object
18781878
* is REFUSED, at the same doors (maintainer ruling A on objectstack#23610,

0 commit comments

Comments
 (0)