From f67bf856bbbc453d1ade99141a2c131ec091a710 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 29 Sep 2026 03:31:42 +0000 Subject: [PATCH 1/5] fix(core,app-shell): the two runtime strings that cite an objectstack card name its repository `RETIRED_ACTION_KEYS.execute` (the dev warning for an action that still carries the retired `execute` key) cited the card that retired the alias by a bare number, which in this repository resolves to an unrelated docs card. It now names objectstack-ai/objectstack#3855; the rest of the message is unchanged. The Studio skill form's `triggerConditions` help text gets the same treatment: objectstack-ai/objectstack#1878 and objectstack-ai/objectstack#1895. Changeset: patch for @object-ui/core and @object-ui/app-shell. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude --- .changeset/11016-cross-repo-bare-citations.md | 34 +++++++++++++++++++ .../views/metadata-admin/default-schemas.ts | 2 +- packages/core/src/actions/actionKeys.ts | 2 +- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 .changeset/11016-cross-repo-bare-citations.md diff --git a/.changeset/11016-cross-repo-bare-citations.md b/.changeset/11016-cross-repo-bare-citations.md new file mode 100644 index 0000000000..828095e1e9 --- /dev/null +++ b/.changeset/11016-cross-repo-bare-citations.md @@ -0,0 +1,34 @@ +--- +'@object-ui/core': patch +'@object-ui/app-shell': patch +--- + +Citations of objectstack cards now name their repository (objectui#11016). + +A bare `#N` in this repository resolves to an objectui item. Where the sentence +meant an objectstack card, a reader who followed the number landed on an +unrelated objectui card or pull request, and nothing flagged it: both +repositories answer for the number, so an earlier sweep that looked for dead +numbers could not see this class. + +Two of those citations are runtime text, and they now name the card they mean: + +- `@object-ui/core`: the dev warning for an action that still carries the + retired `execute` key (`RETIRED_ACTION_KEYS.execute`) points at + objectstack-ai/objectstack#3855, the card that retired the alias. The rest of + the message, including "rename the key to `target`", is unchanged. +- `@object-ui/app-shell`: the Studio skill form's help text for + `triggerConditions` points at objectstack-ai/objectstack#1878 and + objectstack-ai/objectstack#1895. + +The other sites are code comments and doc comments in the non-test sources, +requalified the same way: a bare number whose sentence meant +an objectstack card now reads `objectstack-ai/objectstack#N`. Numbers that mean +an objectui card stay bare. Where a comment quotes objectstack's own text, the +quote keeps its words and the card name sits in square brackets, the editorial +mark for a substituted word. + +Pending entries in this release that carry such a number get a dated note +naming the card, and their frontmatter is unchanged. + +Nothing else moves: no key, accept set, refusal decision or code path. diff --git a/packages/app-shell/src/views/metadata-admin/default-schemas.ts b/packages/app-shell/src/views/metadata-admin/default-schemas.ts index 569c8ea8a0..f847facb23 100644 --- a/packages/app-shell/src/views/metadata-admin/default-schemas.ts +++ b/packages/app-shell/src/views/metadata-admin/default-schemas.ts @@ -174,7 +174,7 @@ const SCHEMAS: Record> = { triggerConditions: { type: 'array', title: 'Trigger Conditions', - description: 'Programmatic activation conditions (context field / operator / value). The activation-critical field — previously only hand-editable (#1878/#1895).', + description: 'Programmatic activation conditions (context field / operator / value). The activation-critical field — previously only hand-editable (objectstack-ai/objectstack#1878 / objectstack-ai/objectstack#1895).', items: { type: 'object', properties: { diff --git a/packages/core/src/actions/actionKeys.ts b/packages/core/src/actions/actionKeys.ts index 37d5e0480c..bdab186c1d 100644 --- a/packages/core/src/actions/actionKeys.ts +++ b/packages/core/src/actions/actionKeys.ts @@ -368,7 +368,7 @@ export const HOST_DISPATCH_ACTION_KEYS = ['overrideNotice'] as const; * a tombstone the spec keeps only in order to reject it by name. */ export const RETIRED_ACTION_KEYS: Readonly> = { - execute: '`execute` was removed in @objectstack/spec 17 (#3855) — rename the key to `target`. ' + + execute: '`execute` was removed in @objectstack/spec 17 (objectstack-ai/objectstack#3855) — rename the key to `target`. ' + 'The value (a script name or expression) is unchanged. ' + 'Run `os migrate meta --from 16` to rewrite it automatically.', }; From d47acaf117008aa4c14ef833b49b3a95c3177de1 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 29 Sep 2026 03:31:58 +0000 Subject: [PATCH 2/5] docs(src): a comment that cites an objectstack card by a bare number names its repository A bare number in this repository resolves to an objectui item. The census of bare numbers in non-test package sources (each sentence read against both repositories' titles, not only the numbers that answer 404) found comments whose sentence means an objectstack card while the number resolves here to an unrelated objectui card or pull request. Each now reads objectstack-ai/objectstack#N. Numbers that mean an objectui card stay bare. Where a comment quotes objectstack's own text, the quote keeps its words and the card name sits in square brackets. The quoted generic-substitution sentence in apiErrorEnvelope.ts also says which card it is: the sharing-rule dialog card, whose objectui fix (objectui#2920) introduced that substitution. Comment-only: no code token moves. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude --- .../app-shell/src/chrome/CommandPalette.tsx | 4 +- packages/app-shell/src/console/AppContent.tsx | 22 ++++---- .../app-shell/src/console/ConsoleShell.tsx | 2 +- .../manage/InviteMemberDialog.tsx | 2 +- .../organizations/manage/MembersPage.tsx | 2 +- .../src/console/organizations/orgRoleLabel.ts | 2 +- .../app-shell/src/hooks/useActionModal.tsx | 2 +- .../src/hooks/useConsoleActionRuntime.tsx | 2 +- .../app-shell/src/hooks/useRecordApprovals.ts | 2 +- packages/app-shell/src/layout/AppSwitcher.tsx | 2 +- .../app-shell/src/layout/InboxPopover.tsx | 2 +- .../src/preview/DraftChangesPanel.tsx | 2 +- .../app-shell/src/preview/commitHistory.ts | 4 +- .../src/providers/AdapterProvider.tsx | 2 +- .../src/providers/writeWarningToast.ts | 4 +- packages/app-shell/src/urlParams.ts | 4 +- .../app-shell/src/utils/apiErrorEnvelope.ts | 6 ++- packages/app-shell/src/utils/appRoute.ts | 2 +- .../app-shell/src/utils/deriveRelatedLists.ts | 2 +- packages/app-shell/src/utils/flowResponse.ts | 2 +- .../src/utils/pageSchemaIntrospect.ts | 2 +- packages/app-shell/src/utils/paramToField.ts | 6 +-- .../src/utils/recordFormNavigation.ts | 4 +- .../src/utils/resolveActionParams.ts | 8 +-- .../app-shell/src/views/ActionParamDialog.tsx | 2 +- .../src/views/DeclaredActionsBar.tsx | 6 +-- packages/app-shell/src/views/FlowRunner.tsx | 2 +- .../app-shell/src/views/ObjectDataPage.tsx | 4 +- packages/app-shell/src/views/ObjectView.tsx | 10 ++-- .../src/views/RecordAttachmentsPanel.tsx | 12 ++--- .../app-shell/src/views/RecordDetailView.tsx | 12 ++--- .../app-shell/src/views/RecordFormPage.tsx | 6 +-- .../src/views/RelatedRecordActionsBridge.tsx | 4 +- packages/app-shell/src/views/ScreenView.tsx | 4 +- .../app-shell/src/views/SearchResultsPage.tsx | 2 +- .../app-shell/src/views/drillUrlFilters.ts | 4 +- .../metadata-admin/MetadataTypeActions.tsx | 4 +- .../metadata-admin/PackageFormDialog.tsx | 4 +- .../views/metadata-admin/ResourceEditPage.tsx | 2 +- .../src/views/metadata-admin/anchors.ts | 2 +- .../views/metadata-admin/clientValidation.ts | 12 ++--- .../datasource/DatasourceResourcePage.tsx | 2 +- .../src/views/metadata-admin/form-spec.ts | 2 +- .../inspectors/FlowNodeConfigField.tsx | 2 +- .../inspectors/FlowObjectListField.tsx | 4 +- .../inspectors/FlowReferenceField.tsx | 18 +++---- .../inspectors/flow-node-config.ts | 24 ++++----- .../metadata-admin/inspectors/flow-scope.ts | 4 +- .../inspectors/json-schema-to-fields.ts | 4 +- .../metadata-admin/inspectors/useFlowScope.ts | 6 +-- .../metadata-admin/previews/ActionPreview.tsx | 4 +- .../metadata-admin/previews/AgentPreview.tsx | 2 +- .../metadata-admin/previews/AppPreview.tsx | 2 +- .../metadata-admin/previews/FlowRunsPanel.tsx | 18 +++---- .../metadata-admin/previews/ToolPreview.tsx | 2 +- .../app-shell/src/views/useOpenRecordList.ts | 6 +-- .../app-shell/src/views/viewFilterFold.ts | 2 +- packages/auth/src/createAuthenticatedFetch.ts | 2 +- packages/auth/src/types.ts | 2 +- .../src/renderers/action/action-bar.tsx | 2 +- .../src/renderers/action/action-button.tsx | 2 +- .../src/renderers/action/action-group.tsx | 4 +- .../src/renderers/action/action-icon.tsx | 2 +- .../src/renderers/action/action-menu.tsx | 2 +- .../src/renderers/basic/metadata-viewer.tsx | 2 +- .../components/src/renderers/form/form.tsx | 8 +-- .../src/renderers/layout/containers.tsx | 2 +- packages/core/src/actions/ActionEngine.ts | 2 +- packages/core/src/actions/ActionRunner.ts | 30 +++++------ packages/core/src/actions/actionKeys.ts | 4 +- packages/core/src/actions/actionResponse.ts | 4 +- packages/core/src/adapters/ValueDataSource.ts | 2 +- .../core/src/adapters/batchTransaction.ts | 2 +- .../core/src/data-scope/ViewDataProvider.ts | 2 +- .../src/data-scope/element-data-source.ts | 2 +- .../core/src/evaluator/ExpressionEvaluator.ts | 2 +- packages/core/src/evaluator/fieldRules.ts | 2 +- .../core/src/evaluator/listConditional.ts | 4 +- packages/core/src/index.ts | 2 +- packages/core/src/theme/ThemeEngine.ts | 2 +- packages/core/src/utils/dashboard-filters.ts | 2 +- packages/core/src/utils/dataset-format.ts | 6 +-- packages/core/src/utils/filter-converter.ts | 12 ++--- packages/core/src/utils/filter-tokens.ts | 4 +- packages/core/src/utils/sort-query.ts | 2 +- .../validators/object-validation-engine.ts | 2 +- packages/data-objectstack/src/index.ts | 50 +++++++++---------- .../data-objectstack/src/metadata-client.ts | 8 +-- packages/data-objectstack/src/userState.ts | 6 +-- packages/fields/src/index.tsx | 4 +- .../src/widgets/FilterConditionField.tsx | 2 +- packages/fields/src/widgets/LookupField.tsx | 2 +- .../fields/src/widgets/RecordPickerDialog.tsx | 2 +- packages/i18n/src/locales/en.ts | 2 +- packages/i18n/src/provider.tsx | 2 +- packages/layout/src/PageHeader.tsx | 2 +- packages/layout/src/index.ts | 2 +- .../permissions/src/MePermissionsProvider.tsx | 6 +-- .../plugin-calendar/src/ObjectCalendar.tsx | 4 +- packages/plugin-charts/src/ObjectChart.tsx | 4 +- .../plugin-dashboard/src/DatasetWidget.tsx | 6 +-- .../src/ObjectMetricWidget.tsx | 2 +- packages/plugin-dashboard/src/index.tsx | 2 +- packages/plugin-dashboard/src/utils.ts | 2 +- packages/plugin-detail/src/RelatedList.tsx | 2 +- packages/plugin-detail/src/index.tsx | 4 +- .../src/renderers/record-related-list.tsx | 2 +- .../src/synth/buildDefaultPageSchema.ts | 6 +-- packages/plugin-form/src/ModalForm.tsx | 8 +-- packages/plugin-form/src/ObjectForm.tsx | 8 +-- packages/plugin-form/src/SplitForm.tsx | 2 +- packages/plugin-form/src/autoLayout.ts | 6 +-- packages/plugin-form/src/schemaDefaults.ts | 2 +- packages/plugin-gantt/src/ObjectGantt.tsx | 2 +- packages/plugin-grid/src/ImportWizard.tsx | 10 ++-- packages/plugin-grid/src/ObjectGrid.tsx | 6 +-- .../src/components/RowActionMenu.tsx | 2 +- .../plugin-grid/src/hooks/multiValueFields.ts | 2 +- .../plugin-grid/src/resolveBulkActions.ts | 2 +- packages/plugin-grid/src/savedMapping.ts | 2 +- packages/plugin-kanban/src/ObjectKanban.tsx | 4 +- packages/plugin-list/src/ListView.tsx | 10 ++-- .../src/DatasetReportRenderer.tsx | 8 +-- packages/plugin-timeline/src/index.tsx | 4 +- packages/plugin-view/src/ObjectView.tsx | 6 +-- packages/plugin-view/src/recordSurface.ts | 4 +- packages/react/src/context/ThemeContext.tsx | 2 +- packages/react/src/hooks/useExpression.ts | 2 +- packages/react/src/hooks/useFilterScope.ts | 4 +- .../react/src/hooks/useNavigationOverlay.ts | 4 +- packages/react/src/hooks/useRecordSearch.ts | 2 +- packages/test-support/src/spec-tombstones.ts | 2 +- packages/types/src/base.ts | 2 +- packages/types/src/complex.ts | 2 +- packages/types/src/data-protocol.ts | 2 +- packages/types/src/data.ts | 8 +-- packages/types/src/field-types.ts | 2 +- packages/types/src/form.ts | 2 +- packages/types/src/index.ts | 6 +-- packages/types/src/objectql.ts | 6 +-- packages/types/src/ui-action.ts | 16 +++--- packages/types/src/widget.ts | 2 +- packages/types/src/zod/objectql.zod.ts | 4 +- 143 files changed, 342 insertions(+), 338 deletions(-) diff --git a/packages/app-shell/src/chrome/CommandPalette.tsx b/packages/app-shell/src/chrome/CommandPalette.tsx index 5fefbe03e5..e32303f05b 100644 --- a/packages/app-shell/src/chrome/CommandPalette.tsx +++ b/packages/app-shell/src/chrome/CommandPalette.tsx @@ -133,7 +133,7 @@ export function CommandPalette({ apps, activeApp, objects, onAppChange, dataSour }, [objects]); // Group the (server-ranked) record hits by object so the palette lists them - // under per-object headings — issue #3371 asks for record hits "grouped by + // under per-object headings — issue objectstack-ai/objectstack#3371 asks for record hits "grouped by // object". The object with the top-ranked hit leads (first-seen order), and // within each group the server's relevance order is preserved. const recordGroups = useMemo(() => { @@ -216,7 +216,7 @@ export function CommandPalette({ apps, activeApp, objects, onAppChange, dataSour )} {/* Record search hits from the platform's global search - (/api/v1/search), grouped by object (issue #3371). The searching + (/api/v1/search), grouped by object (issue objectstack-ai/objectstack#3371). The searching pulse rides the first group's heading so it stays visible while a refined query is in flight over an existing result set. */} {recordGroups.map((group, groupIndex) => { diff --git a/packages/app-shell/src/console/AppContent.tsx b/packages/app-shell/src/console/AppContent.tsx index 7c41a615fa..77abe2e80e 100644 --- a/packages/app-shell/src/console/AppContent.tsx +++ b/packages/app-shell/src/console/AppContent.tsx @@ -210,7 +210,7 @@ export function AppContent({ extraRoutes, extraRoutesNoApp }: AppContentProps = // skips hidden apps to avoid landing the user on a personal-settings // app by default. // - // ⛔ `hidden` only — never `_unpublished` (objectstack#6955 / #4829 A1). The + // ⛔ `hidden` only — never `_unpublished` (objectstack#6955 / objectstack-ai/objectstack#4829 A1). The // publish gate is enforced server-side; duplicating it here would strand a // builder on their own unpublished app. const activeApps = apps.filter((a: any) => a.active !== false); @@ -395,7 +395,7 @@ export function AppContent({ extraRoutes, extraRoutesNoApp }: AppContentProps = } }, [activeApp?.name, appName, location.pathname, navigate]); - // #2604 — the create/edit overlay is URL-driven (`?form=new` / `?form=`), + // objectstack-ai/objectstack#2604 — the create/edit overlay is URL-driven (`?form=new` / `?form=`), // not component state: the record form is a TASK overlay over the origin // route, and putting its open-state in the URL makes browser Back close the // overlay (returning to the intact origin) instead of abandoning the route @@ -405,7 +405,7 @@ export function AppContent({ extraRoutes, extraRoutesNoApp }: AppContentProps = // ahead in history. const [searchParams, setSearchParams] = useSearchParams(); const recordFormParam = searchParams.get(RECORD_FORM_PARAM); - // #2604 D3 — child-task extension of the record-form URL contract: + // objectstack-ai/objectstack#2604 D3 — child-task extension of the record-form URL contract: // `formObject` names the object the form edits when it is NOT the route's // object (a subtable child opened over its parent's detail); `formLink` // ("field:id") pre-links the parent on create. Keeping the whole task in @@ -563,7 +563,7 @@ export function AppContent({ extraRoutes, extraRoutesNoApp }: AppContentProps = const currentObjectDef = allObjects.find((o: any) => o.name === objectNameFromPath); // The object the record-form overlay edits: the route's object by default, - // or the `formObject` child override (#2604 D3 — subtable child task opened + // or the `formObject` child override (objectstack-ai/objectstack#2604 D3 — subtable child task opened // over its parent's detail). const formObjectDef = formObjectParam ? allObjects.find((o: any) => o.name === formObjectParam) @@ -586,7 +586,7 @@ export function AppContent({ extraRoutes, extraRoutesNoApp }: AppContentProps = executeAction({ type: 'dialog_cancel' }); }, [executeAction]); - // #2604 save invariant — *edit never moves you; create takes you to the + // objectstack-ai/objectstack#2604 save invariant — *edit never moves you; create takes you to the // record you made.* Edit save: the origin route is untouched (crud_success // bumps refreshKey → origin refetches in place). Create save: land on the // new record's detail, on ITS derived surface — a light object's detail is @@ -594,7 +594,7 @@ export function AppContent({ extraRoutes, extraRoutesNoApp }: AppContentProps = // `replace: true` swaps out the transient `?form=…` entry so Back returns // to the pre-create origin. const handleRecordFormSuccess = useCallback(async (saved: any) => { - // Child task (#2604 D3): the parent detail must stay EXACTLY as it was — + // Child task (objectstack-ai/objectstack#2604 D3): the parent detail must stay EXACTLY as it was — // active tab, scroll, everything. So do NOT go through crud_success; // the child's open related lists refetch on their own via the // invalidation bus (#2269): the dataSource write already emitted a @@ -1025,7 +1025,7 @@ export function AppContent({ extraRoutes, extraRoutesNoApp }: AppContentProps = no organization), and widening it for filter resolution would couple two unrelated contracts. Renderer packages deliberately do not depend on @object-ui/auth, so the shell supplies the values (framework - #3574). */} + objectstack-ai/objectstack#3574). */} {members.map((member) => { - /* [framework #3697] Roles this actor may SET on THIS member — see the + /* [objectstack-ai/objectstack#3697] Roles this actor may SET on THIS member — see the menu below for what the list mirrors. Hoisted out of the JSX because objectui#4475 needs its emptiness twice: an actor with no assignable role AND no remove permission gets no menu at all, rather than a diff --git a/packages/app-shell/src/console/organizations/orgRoleLabel.ts b/packages/app-shell/src/console/organizations/orgRoleLabel.ts index 679e9b8e27..d3f621798b 100644 --- a/packages/app-shell/src/console/organizations/orgRoleLabel.ts +++ b/packages/app-shell/src/console/organizations/orgRoleLabel.ts @@ -38,7 +38,7 @@ * * ## Unknown roles degrade, they never blank * - * The membership vocabulary is closed and framework-owned (ADR-0108 / #3723), so + * The membership vocabulary is closed and framework-owned (ADR-0108 / objectstack-ai/objectstack#3723), so * a role outside the four is not supposed to exist. `member.role` is still a * server string, and the console's job when it does not recognize one is to show * what the server said — the same "prefer mapped, degrade to verbatim" rule the diff --git a/packages/app-shell/src/hooks/useActionModal.tsx b/packages/app-shell/src/hooks/useActionModal.tsx index fa49da3058..aa5ed0c38d 100644 --- a/packages/app-shell/src/hooks/useActionModal.tsx +++ b/packages/app-shell/src/hooks/useActionModal.tsx @@ -183,7 +183,7 @@ export function useActionModal(dataSource?: any) { * `headlessActionTypeError` rejects `type: 'modal'` over REST with a 400), so * objectstack#3959 removed that fallthrough from the console runtimes and * objectui#3320 removed the copy in `RecordDetailView`. This TSDoc still - * described the pre-#3959 behaviour; corrected here. + * described the pre-objectstack-ai/objectstack#3959 behaviour; corrected here. */ const resolveModalTarget = useCallback( async (schema: any): Promise => { diff --git a/packages/app-shell/src/hooks/useConsoleActionRuntime.tsx b/packages/app-shell/src/hooks/useConsoleActionRuntime.tsx index 6c6c54715c..073979b624 100644 --- a/packages/app-shell/src/hooks/useConsoleActionRuntime.tsx +++ b/packages/app-shell/src/hooks/useConsoleActionRuntime.tsx @@ -401,7 +401,7 @@ export function useConsoleActionRuntime(opts: ConsoleActionRuntimeOptions): Cons : undefined; const body: Record = wrap ? { [wrap]: resolvedParams } : { ...resolvedParams }; - // #3447: decision outputs. DeclaredActionsBar synthesizes one param per + // objectstack-ai/objectstack#3447: decision outputs. DeclaredActionsBar synthesizes one param per // author-declared output key, named `outputs.` (the key set is // per-request, so it can't be a static action param). Fold the dotted // params into the nested `outputs` object the approvals decide route diff --git a/packages/app-shell/src/hooks/useRecordApprovals.ts b/packages/app-shell/src/hooks/useRecordApprovals.ts index 9acb280581..b2b83669f7 100644 --- a/packages/app-shell/src/hooks/useRecordApprovals.ts +++ b/packages/app-shell/src/hooks/useRecordApprovals.ts @@ -349,7 +349,7 @@ export async function remindApprovalRequest( * ⛔ No `currentUserId` parameter (objectui#3055). It existed only to feed the * retired client-side `canDecide`; every remaining question about the viewer — * may they act, are they the submitter, may they override — is answered by the - * server on the row itself (`viewer`, framework#3310 / #3424). A surface that + * server on the row itself (`viewer`, framework#3310 / objectstack-ai/objectstack#3424). A surface that * still needs the signed-in id for a pre-`viewer` fallback (the panel's remind) * reads it from `useAuth()` where it renders. */ diff --git a/packages/app-shell/src/layout/AppSwitcher.tsx b/packages/app-shell/src/layout/AppSwitcher.tsx index 9feb689622..2c55327452 100644 --- a/packages/app-shell/src/layout/AppSwitcher.tsx +++ b/packages/app-shell/src/layout/AppSwitcher.tsx @@ -36,7 +36,7 @@ export function AppSwitcher({ activeAppName, onAppChange }: AppSwitcherProps) { // (personal-settings-style surfaces like the Account app), not the // top-level App Switcher. // - // ⛔ Do NOT add `_unpublished` here (objectstack#6955 / #4829 A1). That key is + // ⛔ Do NOT add `_unpublished` here (objectstack#6955 / objectstack-ai/objectstack#4829 A1). That key is // the ADR-0045 publish gate and is enforced server-side — the REST metadata // gate withholds unpublished apps from non-builders, so anything that reaches // this list is already permitted. Filtering it here would hide a builder's own diff --git a/packages/app-shell/src/layout/InboxPopover.tsx b/packages/app-shell/src/layout/InboxPopover.tsx index 325439a914..d6040125a2 100644 --- a/packages/app-shell/src/layout/InboxPopover.tsx +++ b/packages/app-shell/src/layout/InboxPopover.tsx @@ -277,7 +277,7 @@ export function InboxPopover({ )} - {/* Badge breakdown (#7233). The bell badge is `unreadTopics + + {/* Badge breakdown (objectstack-ai/objectstack#7233). The bell badge is `unreadTopics + pendingApprovalsCount` and clamps at "9+", so the number on its own is unexplainable — and the two tab pills clamp at "9+" too, which means a loaded inbox can show three "9+"s that reconcile to nothing. diff --git a/packages/app-shell/src/preview/DraftChangesPanel.tsx b/packages/app-shell/src/preview/DraftChangesPanel.tsx index d2e594bedd..2eeeb4a051 100644 --- a/packages/app-shell/src/preview/DraftChangesPanel.tsx +++ b/packages/app-shell/src/preview/DraftChangesPanel.tsx @@ -34,7 +34,7 @@ import { SheetTitle, } from '@object-ui/components'; import { useObjectTranslation } from '@object-ui/i18n'; -// The `/meta` URL-spelling fold (objectstack#7894, #8424), applied once in +// The `/meta` URL-spelling fold (objectstack#7894, objectstack-ai/objectstack#8424), applied once in // `listPendingDrafts` below. // // CORRECTED, and the correction matters more than the number. An earlier diff --git a/packages/app-shell/src/preview/commitHistory.ts b/packages/app-shell/src/preview/commitHistory.ts index 12de691b13..fd83479cb0 100644 --- a/packages/app-shell/src/preview/commitHistory.ts +++ b/packages/app-shell/src/preview/commitHistory.ts @@ -43,7 +43,7 @@ * objectui#3529's body points at `details.code`. Verified against the producer, * that is the SERVER-INTERNAL carrier only: `HttpDispatcher.errorFromThrown` * builds `details: { code: e.code }`, and `buildApiError`/`splitSemanticCode` - * (objectstack `packages/runtime/src/error-envelope.ts`, #3842) then LIFT that + * (objectstack `packages/runtime/src/error-envelope.ts`, objectstack-ai/objectstack#3842) then LIFT that * code into `error.code` and drop `details` entirely when it held nothing else. * So `details.code` never reaches the browser from this producer, and a consumer * reading it would be running a check that can only ever pass vacuously. We read @@ -55,7 +55,7 @@ * * The card also expects the 503's prose to say "unknown". It does not reach the * browser: `declaresServerFault` (objectstack `packages/types/src/error-leak.ts`, - * #5811) is true for exactly this error — `status >= 500` WITH a string `code` — + * objectstack-ai/objectstack#5811) is true for exactly this error — `status >= 500` WITH a string `code` — * so the dispatcher replaces the sentence with the generic * `INTERNAL_ERROR_MESSAGE` ("Internal server error") while `error.code` survives. * Rendering the envelope message here would therefore show an operator a generic diff --git a/packages/app-shell/src/providers/AdapterProvider.tsx b/packages/app-shell/src/providers/AdapterProvider.tsx index 539c77e42c..d79c37c0dd 100644 --- a/packages/app-shell/src/providers/AdapterProvider.tsx +++ b/packages/app-shell/src/providers/AdapterProvider.tsx @@ -73,7 +73,7 @@ export function AdapterProvider({ children, adapter: externalAdapter }: AdapterP cache: { maxSize: 50, ttl: 300_000 }, }); - // Surface silently-stripped write fields (#3431/#3455) as a toast so a + // Surface silently-stripped write fields (objectstack-ai/objectstack#3431 / objectstack-ai/objectstack#3455) as a toast so a // read-only value the user typed doesn't just vanish on save. The sink // is passed in rather than imported by the message builder — see // `WriteWarningSink`. diff --git a/packages/app-shell/src/providers/writeWarningToast.ts b/packages/app-shell/src/providers/writeWarningToast.ts index 8553b706b3..89541bbac9 100644 --- a/packages/app-shell/src/providers/writeWarningToast.ts +++ b/packages/app-shell/src/providers/writeWarningToast.ts @@ -7,7 +7,7 @@ */ /** - * Turning a write-warning (framework #3431/#3455) into the message the user + * Turning a write-warning (objectstack-ai/objectstack#3431 / objectstack-ai/objectstack#3455) into the message the user * reads. Lives apart from `AdapterProvider` — and, deliberately, imports NOTHING * that renders — so the wording, the label resolution and the reason-branching * can be exercised directly. @@ -177,7 +177,7 @@ function lineFor(reason: DroppedFieldsNotice['reason']): StrippedLine { * Announce a write-warning. The write SUCCEEDED — some caller-supplied fields * were legally stripped, so we tell the user rather than let it pass silently. * - * The REASON decides the wording (#3794), via the exhaustive {@link STRIPPED_LINE} + * The REASON decides the wording (objectstack-ai/objectstack#3794), via the exhaustive {@link STRIPPED_LINE} * table. `readonly_when` is not "this field is read-only" — the field is editable * in other states and the form rendered it as an ordinary input; what happened is * that THIS record's current state locks it. Saying "read-only" there sends the diff --git a/packages/app-shell/src/urlParams.ts b/packages/app-shell/src/urlParams.ts index 7fe4a47e52..38da8fd8ba 100644 --- a/packages/app-shell/src/urlParams.ts +++ b/packages/app-shell/src/urlParams.ts @@ -88,10 +88,10 @@ export const RECORD_DRAWER_PARAM = 'recordId'; /** Global record-form overlay: `new` | `` (framework#2604). */ export const RECORD_FORM_PARAM = 'form'; -/** Child-task object override for the record-form overlay (#2604 D3). */ +/** Child-task object override for the record-form overlay (objectstack-ai/objectstack#2604 D3). */ export const RECORD_FORM_OBJECT_PARAM = 'formObject'; -/** Child-task parent pre-link `":"` (#2604 D3). */ +/** Child-task parent pre-link `":"` (objectstack-ai/objectstack#2604 D3). */ export const RECORD_FORM_LINK_PARAM = 'formLink'; /** Active record-detail tab (objectui#2257; stable semantic values). */ diff --git a/packages/app-shell/src/utils/apiErrorEnvelope.ts b/packages/app-shell/src/utils/apiErrorEnvelope.ts index 9333852101..c1dbd09581 100644 --- a/packages/app-shell/src/utils/apiErrorEnvelope.ts +++ b/packages/app-shell/src/utils/apiErrorEnvelope.ts @@ -22,7 +22,11 @@ * the END USER (objectstack `79c46da90`). Its presence IS the marking, and the envelope * writer's own words are the rule this module implements: "a consumer that * sees the field renders it verbatim and keeps its generic substitution - * (#3821) for everything unmarked". + * ([objectstack-ai/objectstack#3821]) for everything unmarked". The bracketed + * card name is the one substituted word: the writer's bare number names it only + * inside objectstack. It is the sharing-rule dialog card, and its objectui fix + * (objectui#2920) is where a refused write's raw server text first became + * localized copy, the generic substitution itself. * * So the mark OUTRANKS the diagnostic. That order is the contract's, not a * preference — a reader that ignores `userMessage` is not degrading gracefully, diff --git a/packages/app-shell/src/utils/appRoute.ts b/packages/app-shell/src/utils/appRoute.ts index 76d1a48cdb..63217d82d1 100644 --- a/packages/app-shell/src/utils/appRoute.ts +++ b/packages/app-shell/src/utils/appRoute.ts @@ -72,7 +72,7 @@ const SETUP_APP_SEGMENT = 'setup'; * One definition, because "an app the user can open" has to mean the same thing * to Home's launcher and to every producer that builds a link into an app. * - * ⛔ Do NOT add `_unpublished` to this predicate (objectstack#6955 / #4829 A1). + * ⛔ Do NOT add `_unpublished` to this predicate (objectstack#6955 / objectstack-ai/objectstack#4829 A1). * It is the machine-managed ADR-0045 publish gate, and it is enforced * SERVER-SIDE — the REST metadata gate withholds unpublished apps from * non-builders, so any that reach this function belong to a builder entitled to diff --git a/packages/app-shell/src/utils/deriveRelatedLists.ts b/packages/app-shell/src/utils/deriveRelatedLists.ts index d60c0ef1f5..73e6bdccf8 100644 --- a/packages/app-shell/src/utils/deriveRelatedLists.ts +++ b/packages/app-shell/src/utils/deriveRelatedLists.ts @@ -26,7 +26,7 @@ * columns when omitted — resolved by the renderer). * - `relatedListFilter` on the FK field is the list's own declared SCOPE * (objectui#4664; the spec key landed upstream as objectstack#8704 / PR - * #8955 and ships from `@objectstack/spec` 17.1.0). It is carried through + * objectstack-ai/objectstack#8955 and ships from `@objectstack/spec` 17.1.0). It is carried through * to the `record:related_list` node's existing `filter` prop, where * `RelatedList` AND-composes it with `{ [referenceField]: parentId }` * (objectstack#7118) — the parent condition is never negotiable, so the diff --git a/packages/app-shell/src/utils/flowResponse.ts b/packages/app-shell/src/utils/flowResponse.ts index 8c2717cf6f..a8de1d0952 100644 --- a/packages/app-shell/src/utils/flowResponse.ts +++ b/packages/app-shell/src/utils/flowResponse.ts @@ -46,7 +46,7 @@ * ## A failed run does NOT always arrive as HTTP 200 (`833c90047`) * * The three shapes above describe the route as it answers today. objectstack#8684 - * unifies the resume route onto real status codes — inheriting the #3962 ruling + * unifies the resume route onto real status codes — inheriting the objectstack-ai/objectstack#3962 ruling * that business failures must not ride HTTP 200 inside a double envelope — so the * SAME terminal node failure that answers `200 {data:{success:false}}` today will * answer `400` + `FLOW_FAILED` once that lands, in the ADR-0112 error envelope: diff --git a/packages/app-shell/src/utils/pageSchemaIntrospect.ts b/packages/app-shell/src/utils/pageSchemaIntrospect.ts index d8ba48d08b..4bef661d3d 100644 --- a/packages/app-shell/src/utils/pageSchemaIntrospect.ts +++ b/packages/app-shell/src/utils/pageSchemaIntrospect.ts @@ -65,7 +65,7 @@ function hasNodeOfType(root: unknown, types: ReadonlySet): boolean { * Return `root` with every `record:discussion` / `record:chatter` node removed * from the containers this module walks. * - * This is the object-level `enable.feeds: false` gate (#2707) applied to a + * This is the object-level `enable.feeds: false` gate (objectstack-ai/objectstack#2707) applied to a * COMPOSED page (objectui#7298). The maintainer ruling of 2026-09-12 makes the * declared node the only way a discussion panel reaches a record page, and * keeps `enable.feeds` as the object's switch *over* the page: an object with diff --git a/packages/app-shell/src/utils/paramToField.ts b/packages/app-shell/src/utils/paramToField.ts index 7464d02d03..8a2649964b 100644 --- a/packages/app-shell/src/utils/paramToField.ts +++ b/packages/app-shell/src/utils/paramToField.ts @@ -59,14 +59,14 @@ const LOOKUP_WIDGET_TYPES = new Set(['lookup', 'master_detail']); * The ONE answer to that question, exported so every surface that REACTS to the * degradation reads the same table that PERFORMS it. `ActionParamDialog` is the * caller that made exporting it necessary (objectui#5654): it decides whether to - * show the #3405 "paste a record id" placeholder and help text, and it used to + * show the objectstack-ai/objectstack#3405 "paste a record id" placeholder and help text, and it used to * answer with its own literal over RAW param spellings * (`param.type === 'lookup' || param.type === 'reference'`). That copy disagreed * with this one in BOTH directions, so neither set contained the other: * * - `master_detail` degrades here but got no hints there — a targetless * `master_detail` param really did render as an unexplained empty box asking - * for a bare UUID, which is exactly the state #3405 added the hints for. + * for a bare UUID, which is exactly the state objectstack-ai/objectstack#3405 added the hints for. * - `reference` was hand-copied out of `PARAM_TYPE_ALIASES`, a spelling this * side never sees: it is folded to `lookup` before the membership test. * @@ -95,7 +95,7 @@ export function paramDegradesWithoutTarget(param: ActionParamDef): boolean { * without a target object) — preserving the dialog's long-standing behavior * for partially-resolved metadata. * - * That fallback is now a last resort, not an expected path (#3405): inline + * That fallback is now a last resort, not an expected path (objectstack-ai/objectstack#3405): inline * params declare `reference` and field-backed ones inherit it, and the spec * rejects a targetless inline picker at parse time. Reaching it means the * metadata is broken or partial, so say so in dev instead of silently handing diff --git a/packages/app-shell/src/utils/recordFormNavigation.ts b/packages/app-shell/src/utils/recordFormNavigation.ts index b935b2de61..1fd5d4f1fb 100644 --- a/packages/app-shell/src/utils/recordFormNavigation.ts +++ b/packages/app-shell/src/utils/recordFormNavigation.ts @@ -153,7 +153,7 @@ export function resolveFormViewLayout( } /** - * Result of the post-create-save navigation decision (#2604 save invariant: + * Result of the post-create-save navigation decision (objectstack-ai/objectstack#2604 save invariant: * *create takes you to the record you made*). `kind: 'none'` means stay put * (no usable record id came back from the save). */ @@ -162,7 +162,7 @@ export type PostCreateTarget = | { kind: 'detail-page' | 'detail-drawer'; url: string }; /** - * Decide where a CREATE save lands (#2604): the new record's detail, on the + * Decide where a CREATE save lands (objectstack-ai/objectstack#2604): the new record's detail, on the * record's own derived surface. * * - `surface: 'page'` (field-heavy) → the detail ROUTE diff --git a/packages/app-shell/src/utils/resolveActionParams.ts b/packages/app-shell/src/utils/resolveActionParams.ts index bae6ae85fa..ab27a056a8 100644 --- a/packages/app-shell/src/utils/resolveActionParams.ts +++ b/packages/app-shell/src/utils/resolveActionParams.ts @@ -133,7 +133,7 @@ export interface RawActionParam { /** Max upload size in bytes for `file`/`image` params. */ maxSize?: number; /** - * Reference target for an INLINE `lookup`/`master_detail` param (#3405) — + * Reference target for an INLINE `lookup`/`master_detail` param (objectstack-ai/objectstack#3405) — * the object whose records the picker searches. Field-backed params inherit * it from the referenced field instead (see `lookupExtras` below). Spelled * `reference` to match `FieldSchema.reference` / `ActionParamSchema.reference`. @@ -499,7 +499,7 @@ export function resolveActionParam( multiple: param.multiple, accept: param.accept, maxSize: param.maxSize, - // Inline picker target (#3405). Without this an inline `lookup` param + // Inline picker target (objectstack-ai/objectstack#3405). Without this an inline `lookup` param // could never reach `` — `paramToField()` degrades a // targetless picker to a raw record-id text input. referenceTo: param.reference, @@ -525,7 +525,7 @@ export function resolveActionParam( // offering a box no human can fill. Without this key the degradation is // undetectable downstream: by the time `paramToField()` sees the param it // is a `text` param, so `paramDegradesWithoutTarget()` answers false and - // even the #3405 "paste a record id" hints do not fire. + // even the objectstack-ai/objectstack#3405 "paste a record id" hints do not fire. // // ⛔ The warning is NOT gated on the param's type. "Which widget did this // want?" is exactly the question that cannot be answered here, so gating on @@ -609,7 +609,7 @@ export function resolveActionParam( const lookupExtras: Partial = isLookupResolvedType ? { // Inline `reference` wins, matching how every other inline value - // overrides the resolved field (#3405). + // overrides the resolved field (objectstack-ai/objectstack#3405). // ⚠️ objectui#6837 half 2: the READ narrows to `reference` (the only // spelling the protocol declares — `FieldSchema` refuses `reference_to` // by name). The EMITTED key is unchanged: it is what this emit's TARGET diff --git a/packages/app-shell/src/views/ActionParamDialog.tsx b/packages/app-shell/src/views/ActionParamDialog.tsx index 90f0939055..e26daf4766 100644 --- a/packages/app-shell/src/views/ActionParamDialog.tsx +++ b/packages/app-shell/src/views/ActionParamDialog.tsx @@ -606,7 +606,7 @@ export function ActionParamDialog({ state, onOpenChange }: ActionParamDialogProp ? { dependentValues: values } : {}; // A picker param that fell back to text for want of a declared - // target keeps the "paste an ID" placeholder/help hints (#3405). + // target keeps the "paste an ID" placeholder/help hints (objectstack-ai/objectstack#3405). // // WHICH params fell back is asked of the adapter that performs the // fallback — never restated here (objectui#5654). This line used to diff --git a/packages/app-shell/src/views/DeclaredActionsBar.tsx b/packages/app-shell/src/views/DeclaredActionsBar.tsx index 9d2aedc7b7..6564ca0a4e 100644 --- a/packages/app-shell/src/views/DeclaredActionsBar.tsx +++ b/packages/app-shell/src/views/DeclaredActionsBar.tsx @@ -153,7 +153,7 @@ const DeclaredActionButton: React.FC<{ * * What is specific to this bar is the cost of getting it wrong: EVERY * declared action on `sys_approval_request` gates on `record.viewer.*` - * (framework#3310 / #3424), so under a root-only bag the whole + * (framework#3310 / objectstack-ai/objectstack#3424), so under a root-only bag the whole * server-declared decision set was invisible on every surface this bar * renders — `record.viewer.can_act` does not read as false there, it throws * `record is not defined` and `throwOnError` turns that into "hidden". @@ -168,7 +168,7 @@ const DeclaredActionButton: React.FC<{ }); // Spec `disabled` — the same three arms as `visible` (`boolean | CEL string | // { dialect, source }`, disabled when TRUE), evaluated against the same record - // context. #1885 wired it in action-button only; this bar ignored it, so a + // context. objectstack-ai/objectstack#1885 wired it in action-button only; this bar ignored it, so a // spec-authored `disabled` guard on a declared action did nothing here. (No // legacy `enabled` fallback: server-declared actions are spec-shaped and never // carried the non-spec key.) @@ -255,7 +255,7 @@ const DeclaredActionButton: React.FC<{ // input), and reserve `params` for the `_rowRecord` stash the api handler // reads for `{id}` interpolation + record-id injection. const { params: rawParams, ...rest } = action as ActionDef & { params?: unknown }; - // #3447: an approval decision may carry author-declared structured + // objectstack-ai/objectstack#3447: an approval decision may carry author-declared structured // outputs. The key set is PER-REQUEST (each approval node declares its // own `decisionOutputs`, surfaced on the row as `decision_output_defs`), // so it cannot be a static action param — synthesize one param per key diff --git a/packages/app-shell/src/views/FlowRunner.tsx b/packages/app-shell/src/views/FlowRunner.tsx index 83752d5270..e03f5d9fe0 100644 --- a/packages/app-shell/src/views/FlowRunner.tsx +++ b/packages/app-shell/src/views/FlowRunner.tsx @@ -397,7 +397,7 @@ export function FlowRunner({ state, authFetch, baseUrl, onClose, onComplete, dat // declared list. A `visibleWhen` field that is required *when shown* is not // required while hidden — the user was never asked for it, and the flow is // not waiting on it. Validating the full list here is what dead-ended - // #3528: HotCRM's lead conversion declares `opportunityName` required with + // objectstack-ai/objectstack#3528: HotCRM's lead conversion declares `opportunityName` required with // `visibleWhen: createOpportunity == true`, so leaving the checkbox // unticked blocked Submit on an input that was not on screen, and the run // sat paused with no resume request ever issued. diff --git a/packages/app-shell/src/views/ObjectDataPage.tsx b/packages/app-shell/src/views/ObjectDataPage.tsx index 41edad4f30..b97852afe2 100644 --- a/packages/app-shell/src/views/ObjectDataPage.tsx +++ b/packages/app-shell/src/views/ObjectDataPage.tsx @@ -240,7 +240,7 @@ export function ObjectDataPage({ dataSource, objects }: any) { // Template variables mirror nav `recordId` substitution so shared links // can carry `{current_user_id}`. Routed through the shared resolver so a // link also gets `{current_org_id}` and date macros, instead of the single - // hard-coded token this used to compare against (framework #3574). + // hard-coded token this used to compare against (objectstack-ai/objectstack#3574). return resolveFilterPlaceholders(readable, { currentUserId: user?.id ?? null, currentOrgId: activeOrganization?.id ?? null, @@ -248,7 +248,7 @@ export function ObjectDataPage({ dataSource, objects }: any) { }, [filterParamsKey, canRead, user?.id, activeOrganization?.id]); // One display chip per field — a date-bucket drill's two range triples - // (>= start, < end) collapse into a single "start → end" chip (#1752). + // (>= start, < end) collapse into a single "start → end" chip (objectstack-ai/objectstack#1752). const filterChips = React.useMemo(() => groupFilterChips(urlFilters), [urlFilters]); const removeUrlFilter = React.useCallback( diff --git a/packages/app-shell/src/views/ObjectView.tsx b/packages/app-shell/src/views/ObjectView.tsx index fe60b6d70f..9191705a8d 100644 --- a/packages/app-shell/src/views/ObjectView.tsx +++ b/packages/app-shell/src/views/ObjectView.tsx @@ -111,7 +111,7 @@ const FALLBACK_USER = { id: 'current-user', name: 'Demo User' }; * (`if (!Array.isArray(filter)) return filter`) and knew exactly one token. * That narrowness is why it could not be reused by dashboard widgets, whose * filters are MongoDB-style objects — so widgets went without any resolution - * at all and silently rendered 0 (framework #3574). Every surface now routes + * at all and silently rendered 0 (objectstack-ai/objectstack#3574). Every surface now routes * through one shape-agnostic resolver. */ function substituteFilterTokens(filter: any, scope: FilterTokenScope): any { @@ -2328,7 +2328,7 @@ function ObjectViewInner({ dataSource, objects, onEdit, externalRefreshKey }: Co if (authored) { // Authored config wins. For an overlay, resolve the `size` // bucket (or 'auto') to a viewport-clamped width when no explicit - // width was given — #2578: a pixel width can't be authored blind. + // width was given — objectstack-ai/objectstack#2578: a pixel width can't be authored blind. if (authored.mode === 'page') return authored; return { ...authored, @@ -2338,7 +2338,7 @@ function ObjectViewInner({ dataSource, objects, onEdit, externalRefreshKey }: Co ), }; } - // #2578: derive surface + width from FIELD COUNT. Field-heavy → full + // objectstack-ai/objectstack#2578: derive surface + width from FIELD COUNT. Field-heavy → full // page (cramped in a drawer); light → a drawer sized to the content // and clamped to the viewport. Mobile always pages (in deriveRecordSurface). return deriveRecordSurface(objectDef) === 'page' @@ -2609,7 +2609,7 @@ function ObjectViewInner({ dataSource, objects, onEdit, externalRefreshKey }: Co // (objectui#10035): `ObjectChart` runs its own query and refetches // in place on the data-invalidation bus (see `refreshData`). // - // ADR-0021 (#1890): dataset-bound chart — the single author-facing + // ADR-0021 (objectstack-ai/objectstack#1890): dataset-bound chart — the single author-facing // shape. Selects dimensions/measures BY NAME and runs through the // governed queryDataset path (numbers consistent across surfaces). if (chartConfig.dataset) { @@ -3050,7 +3050,7 @@ function ObjectViewInner({ dataSource, objects, onEdit, externalRefreshKey }: Co // This was a hand-listed projection of six keys (`chartType` / // `xAxisField` / `yAxisFields` / `aggregation` / `series` / // `config`): the PRE-ADR-0021 set, frozen. The whole ADR-0021 - // (#1890) authoring shape (`dataset` / `dimensions` / `values`) + // (objectstack-ai/objectstack#1890) authoring shape (`dataset` / `dimensions` / `values`) // and the legacy `categoryField` / `valueField` spelling had no // rung here, so an author who declared them reached `ListView` // with the binding stripped. Once objectui#7544 gave diff --git a/packages/app-shell/src/views/RecordAttachmentsPanel.tsx b/packages/app-shell/src/views/RecordAttachmentsPanel.tsx index 2d6499c879..0961fc5d50 100644 --- a/packages/app-shell/src/views/RecordAttachmentsPanel.tsx +++ b/packages/app-shell/src/views/RecordAttachmentsPanel.tsx @@ -24,7 +24,7 @@ import { createAuthenticatedFetch } from '@object-ui/auth'; import { useObjectTranslation, isPermissionError, classifyLoadError } from '@object-ui/react'; /** - * RecordAttachmentsPanel — generic record Attachments surface (#2727, + * RecordAttachmentsPanel — generic record Attachments surface (objectstack-ai/objectstack#2727, * Salesforce "Notes & Attachments" parity). * * Rendered by RecordDetailView ONLY when the object declares @@ -37,7 +37,7 @@ import { useObjectTranslation, isPermissionError, classifyLoadError } from '@obj * `sys_attachment` join row linking it to `(parent_object, parent_id)`. * Downloads fetch a short-lived signed URL from `/storage/files/:fileId/url` * with the console's Bearer token (the endpoint requires an authenticated - * session for attachments-scope files, #2970), then open it. + * session for attachments-scope files, objectstack-ai/objectstack#2970), then open it. */ interface AttachmentRow { @@ -171,7 +171,7 @@ export const RecordAttachmentsPanel: React.FC = ({ [baseUrl, authFetch], ); - /** Map the server's fail-closed 40x codes (#2755, #2970) to friendly copy. */ + /** Map the server's fail-closed 40x codes (objectstack-ai/objectstack#2755, objectstack-ai/objectstack#2970) to friendly copy. */ const friendlyError = React.useCallback( (err: unknown): string => { const anyErr = err as { code?: string; message?: unknown } | null; @@ -308,7 +308,7 @@ export const RecordAttachmentsPanel: React.FC = ({ file_name: uploaded.name ?? file.name, mime_type: uploaded.mimeType ?? file.type, size: uploaded.size ?? file.size, - // Back-compat with pre-#2755 servers; a current server stamps + // Back-compat with pre-objectstack-ai/objectstack#2755 servers; a current server stamps // `uploaded_by` from the session and ignores this value. ...(currentUserId ? { uploaded_by: currentUserId } : {}), }); @@ -333,7 +333,7 @@ export const RecordAttachmentsPanel: React.FC = ({ setRows((prev) => prev.filter((r) => r.id !== row.id)); } catch (err: any) { // The delete button deliberately renders for every row: the server - // is the gate (uploader-or-parent-editor, #2755) and the client + // is the gate (uploader-or-parent-editor, objectstack-ai/objectstack#2755) and the client // lacks the parent-edit data to pre-compute it — a denial surfaces // here as friendly copy instead. setError(friendlyError(err)); @@ -347,7 +347,7 @@ export const RecordAttachmentsPanel: React.FC = ({ setError(null); try { // The stable `/files/:fileId` endpoint now requires an authenticated - // session for attachments-scope files (#2970) — an can't + // session for attachments-scope files (objectstack-ai/objectstack#2970) — an can't // carry the Bearer token. Fetch a short-lived signed URL with auth, // then open it (the signed URL itself needs no credentials). const res = await authFetch( diff --git a/packages/app-shell/src/views/RecordDetailView.tsx b/packages/app-shell/src/views/RecordDetailView.tsx index 7b4f29ba0d..205181189a 100644 --- a/packages/app-shell/src/views/RecordDetailView.tsx +++ b/packages/app-shell/src/views/RecordDetailView.tsx @@ -1107,7 +1107,7 @@ export function RecordDetailView({ dataSource, objects, onEdit, objectNameOverri * because a modal has no server dispatch — the fallthrough only converted an * authoring mistake (a target naming no page) into a confusing round-trip. * objectstack#3959 removed it from the shared runtime; this copy kept the - * pre-#3959 shape until objectui#3320. An unresolvable target is now + * pre-objectstack-ai/objectstack#3959 shape until objectui#3320. An unresolvable target is now * reported as what it is. To collect input and then run server-side, declare * `type: 'script'` with `params`: the runner collects the same dialog and * the handler runs with those values. @@ -1402,7 +1402,7 @@ export function RecordDetailView({ dataSource, objects, onEdit, objectNameOverri return objects.some((o: any) => o.name === 'sys_audit_log'); }, [objectDef, objects]); - // ── Capability gates: enable.feeds / enable.activities (#2707) ───── + // ── Capability gates: enable.feeds / enable.activities (objectstack-ai/objectstack#2707) ───── // Both are opt-OUT capabilities (spec default `true`): absent enable // block/flag = on; only an explicit `false` disables. `feeds:false` // hides the discussion panel and skips the sys_comment fetch (the @@ -1412,7 +1412,7 @@ export function RecordDetailView({ dataSource, objects, onEdit, objectNameOverri // empty anyway — skipping keeps the network quiet). const feedsEnabled = objectDef?.enable?.feeds !== false; const activitiesEnabled = objectDef?.enable?.activities !== false; - // `enable.files` (#2727) is opt-IN (spec default `false`): the generic + // `enable.files` (objectstack-ai/objectstack#2727) is opt-IN (spec default `false`): the generic // Attachments panel is a new surface, so it only renders when the object // explicitly declares it. The server enforces the same gate on // sys_attachment creation (403 FILES_DISABLED). @@ -1751,7 +1751,7 @@ export function RecordDetailView({ dataSource, objects, onEdit, objectNameOverri // M10.11: Fetch sys_activity rows for this record and merge into the // timeline. plugin-audit's writers populate sys_activity on every // create/update/delete unless the object opts OUT via an explicit - // `enable.activities: false` (#2707 — opt-out contract, spec default + // `enable.activities: false` (objectstack-ai/objectstack#2707 — opt-out contract, spec default // true), so this surface gives us a Salesforce-style "what happened // on this record" feed without any per-app glue. // @@ -2549,7 +2549,7 @@ export function RecordDetailView({ dataSource, objects, onEdit, objectNameOverri // composes `record:discussion` itself — out-of-the-box record pages are // unchanged; AUTHORED pages that relied on the append add one node. // - // `enable.feeds` (#2707) stays the OBJECT's switch and OUTRANKS the page: an + // `enable.feeds` (objectstack-ai/objectstack#2707) stays the OBJECT's switch and OUTRANKS the page: an // object with feeds off shows no panel, declared or not. That is the one half // of the ruling this tree did not already do — the old `feedsEnabled` gate // sat on the append alone, so a declared (or synthesized) node rendered a @@ -2744,7 +2744,7 @@ export function RecordDetailView({ dataSource, objects, onEdit, objectNameOverri )} - {/* Generic Attachments panel (#2727) — opt-in via + {/* Generic Attachments panel (objectstack-ai/objectstack#2727) — opt-in via `enable.files: true`; the server rejects attachments targeting any other object (403 FILES_DISABLED). Fallback only: synthesized pages already place a diff --git a/packages/app-shell/src/views/RecordFormPage.tsx b/packages/app-shell/src/views/RecordFormPage.tsx index a510f487b2..b49b2b52d2 100644 --- a/packages/app-shell/src/views/RecordFormPage.tsx +++ b/packages/app-shell/src/views/RecordFormPage.tsx @@ -274,11 +274,11 @@ export function RecordFormPage({ mode }: RecordFormPageProps) { ); } - // Honour the object's form view layout (#1890): wire the declared `type` + // Honour the object's form view layout (objectstack-ai/objectstack#1890): wire the declared `type` // (simple/tabbed/wizard/split) + `sections` through to ObjectForm, which // already renders each variant. Page-level layouts only — `drawer`/`modal` // are presentation/open-modes, not record-page layouts, so they fall back to - // `simple` here (see the form-layout-vs-presentation modelling note in #1890). + // `simple` here (see the form-layout-vs-presentation modelling note in objectstack-ai/objectstack#1890). const formDef: any = (objectDef as any).form ?? (objectDef as any).formViews?.default ?? {}; const pageFormType: 'simple' | 'tabbed' | 'wizard' | 'split' = ['tabbed', 'wizard', 'split'].includes(formDef.type) ? formDef.type : 'simple'; @@ -368,7 +368,7 @@ export function RecordFormPage({ mode }: RecordFormPageProps) { mode, recordId: mode === 'edit' ? recordId : undefined, ...(prefillValues && { initialValues: prefillValues }), - // framework#1894 / #2998: honor the spec-aligned structured + // framework#1894 / objectstack-ai/objectstack#2998: honor the spec-aligned structured // `buttons`/`defaults` from the object's form view. ObjectForm // folds them onto its flat props; an explicit `initialValues` // (URL prefill above) still wins over `defaults`. diff --git a/packages/app-shell/src/views/RelatedRecordActionsBridge.tsx b/packages/app-shell/src/views/RelatedRecordActionsBridge.tsx index c7410605f2..ced6df5bc9 100644 --- a/packages/app-shell/src/views/RelatedRecordActionsBridge.tsx +++ b/packages/app-shell/src/views/RelatedRecordActionsBridge.tsx @@ -17,7 +17,7 @@ * * - 查看详情 → navigate to the child record's detail route * - 增 / 改 → open the child form as an OVERLAY on the parent detail - * (#2604 D3: a child task's return target is ALWAYS the parent + * (objectstack-ai/objectstack#2604 D3: a child task's return target is ALWAYS the parent * detail with the subtable refreshed — never a route, which * would drop the parent's scroll/tab context and refetch it). * Implemented by pushing the console's record-form URL params @@ -281,7 +281,7 @@ export function RelatedRecordActionsBridge({ [recordHref, navigate], ); - // #2604 D3 — open a child create/edit task as the console's global record + // objectstack-ai/objectstack#2604 D3 — open a child create/edit task as the console's global record // form overlay, by URL params. Pushes ONE history entry (Back = close, the // parent detail stays mounted underneath). The read side lives in // `AppContent` (see its record-form URL contract). diff --git a/packages/app-shell/src/views/ScreenView.tsx b/packages/app-shell/src/views/ScreenView.tsx index 5c59fe9733..9a98f91ede 100644 --- a/packages/app-shell/src/views/ScreenView.tsx +++ b/packages/app-shell/src/views/ScreenView.tsx @@ -55,7 +55,7 @@ import type { * third-party node executor, legitimately carries no `fields` array, and an * absent `fields` used to throw the moment the dialog opened. Every read goes * through {@link screenFields} rather than touching the array directly, so the - * widening cannot leak into rendering or `required` enforcement (#3528). + * widening cannot leak into rendering or `required` enforcement (objectstack-ai/objectstack#3528). * * If the spec ever makes `fields` optional itself, this alias collapses to a * plain re-export — `__tests__/spec-symbol-parity.test.ts` fails on that day and says so. @@ -77,7 +77,7 @@ export function screenFields(screen: ScreenSpec): ScreenFieldSpec[] { * field whose `visibleWhen` predicate holds (or that declares none). * * This is the list callers must use for BOTH rendering and `required` - * enforcement. Splitting them is the #3528 dead-end: validate the full list + * enforcement. Splitting them is the objectstack-ai/objectstack#3528 dead-end: validate the full list * while rendering a subset and Submit blocks on a field the user was never * shown, with no resume request ever issued. * diff --git a/packages/app-shell/src/views/SearchResultsPage.tsx b/packages/app-shell/src/views/SearchResultsPage.tsx index 552b451711..7232523b8b 100644 --- a/packages/app-shell/src/views/SearchResultsPage.tsx +++ b/packages/app-shell/src/views/SearchResultsPage.tsx @@ -134,7 +134,7 @@ export function SearchResultsPage() { // (`/api/v1/search` via `useRecordSearch`/`searchAll`), scoped to the app's // searchable nav objects so record links resolve within this app. This is // what makes the full-page search actually surface records, not just the - // metadata nav items above (issue #3371 follow-up). + // metadata nav items above (issue objectstack-ai/objectstack#3371 follow-up). const searchableObjectNames = useMemo(() => { if (!activeApp) return [] as string[]; return flattenNavigation(activeApp.navigation || []) diff --git a/packages/app-shell/src/views/drillUrlFilters.ts b/packages/app-shell/src/views/drillUrlFilters.ts index 9b0fd8273a..28520ac5d3 100644 --- a/packages/app-shell/src/views/drillUrlFilters.ts +++ b/packages/app-shell/src/views/drillUrlFilters.ts @@ -10,7 +10,7 @@ * URL filter (de)serialization shared by the drill "escape hatch" * (`useOpenRecordList`, the WRITE side) and the ADR-0055 bare data surface * (`ObjectDataPage`, the READ side). Keeping both sides in ONE module keeps the - * `filter[][]` operator contract (#1752) from drifting between the + * `filter[][]` operator contract (objectstack-ai/objectstack#1752) from drifting between the * code that emits a URL and the code that parses it back. * * Contract: @@ -353,7 +353,7 @@ function collectFilterParams(filter: Record, params: URLSearchP /** * Delete the equality param AND every operator param (both range bounds, and the * emptiness param in either direction) for a field, so removing a date-range - * chip drops the whole range together (#1752) and removing an emptiness chip + * chip drops the whole range together (objectstack-ai/objectstack#1752) and removing an emptiness chip * drops its param (objectui#9159, objectui#9508). Prefix-based, so it covers a suffix by construction rather * than by listing one — a new operator is removable the day it is writable. * Mutates and returns `params`. diff --git a/packages/app-shell/src/views/metadata-admin/MetadataTypeActions.tsx b/packages/app-shell/src/views/metadata-admin/MetadataTypeActions.tsx index 8d6f21f9fa..d5b69a68c1 100644 --- a/packages/app-shell/src/views/metadata-admin/MetadataTypeActions.tsx +++ b/packages/app-shell/src/views/metadata-admin/MetadataTypeActions.tsx @@ -175,8 +175,8 @@ export function MetadataTypeActions({ entry, location, recordId, onAfter }: Meta // one place every `type: 'api'` action passes through. // // Deliberately tolerant of an already-unwrapped body: endpoints an action - // may target are converted module by module (framework#3675 → #3689 → - // #3843), so this repo must not be coupled to the merge order of that + // may target are converted module by module (framework#3675 → objectstack-ai/objectstack#3689 → + // objectstack-ai/objectstack#3843), so this repo must not be coupled to the merge order of that // sequence. Same reason the two attachment openers read // `body?.url ?? body?.data?.url` for framework#3689. const data = diff --git a/packages/app-shell/src/views/metadata-admin/PackageFormDialog.tsx b/packages/app-shell/src/views/metadata-admin/PackageFormDialog.tsx index 01ed9b0117..4ea6d7de6d 100644 --- a/packages/app-shell/src/views/metadata-admin/PackageFormDialog.tsx +++ b/packages/app-shell/src/views/metadata-admin/PackageFormDialog.tsx @@ -312,7 +312,7 @@ export function PackageFormDialog({ setError(marked ? msg : t('engine.packages.create.exists', locale)); } else if (e?.status === 403 || /manage_metadata/i.test(msg)) { // objectstack#8270 — for an UNMARKED body this arm still answers - // exactly as it did, and that is the whole of what #8270 measured. The + // exactly as it did, and that is the whole of what objectstack-ai/objectstack#8270 measured. The // sentence it was ruled about, "Managing packages requires the // `manage_metadata` capability.", is the door's DIAGNOSTIC: // `sendError(res, 403, 'FORBIDDEN', …)` in `@objectstack/rest` @@ -321,7 +321,7 @@ export function PackageFormDialog({ // byte as the 2026-08-13 maintainer ruling requires. A deployment that // withholds the capability does so deliberately, so this is a settled // posture to state in the user's language, not a transient failure to - // retry. What changes is only the case #8270 never saw: a body a + // retry. What changes is only the case objectstack-ai/objectstack#8270 never saw: a body a // producer deliberately marked for the end user. // // Probed the same way as the 409 arm above — the status when the diff --git a/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx b/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx index 2ea9e12ae3..f877de14c1 100644 --- a/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx +++ b/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx @@ -222,7 +222,7 @@ const CANVAS_OWNED_KEYS: Record = { * * Both steps of the loop send this value — `doSave` binds the draft row to the * package (`PUT ?package=`), and since objectstack `9e04c3e35`, `doPublish` states the - * same package on the promotion (`POST .../publish?package=`) so #9612's + * same package on the promotion (`POST .../publish?package=`) so objectstack-ai/objectstack#9612's * package-closure narrowing at the runtime publish gate is reachable from an * HTTP-driven promotion at all. One value, one spelling, both steps — which * means one derivation too. A second inline copy in the publish path would be diff --git a/packages/app-shell/src/views/metadata-admin/anchors.ts b/packages/app-shell/src/views/metadata-admin/anchors.ts index ff3c68826a..742d1a10c5 100644 --- a/packages/app-shell/src/views/metadata-admin/anchors.ts +++ b/packages/app-shell/src/views/metadata-admin/anchors.ts @@ -441,7 +441,7 @@ export function registerBuiltinAnchors(): void { // A new action defaults to `type: 'script'` (ActionType.default), which the // spec requires to carry an executable `body` or `target` — otherwise the // draft fails validation on save (422) and AppPlugin registers no engine - // handler (the #2169 "Mark Done" runtime miss). Seed a no-op L2 body so + // handler (the objectstack-ai/objectstack#2169 "Mark Done" runtime miss). Seed a no-op L2 body so // "New action -> name -> Save" round-trips; the author edits the source after. createDefaults: { type: 'script', diff --git a/packages/app-shell/src/views/metadata-admin/clientValidation.ts b/packages/app-shell/src/views/metadata-admin/clientValidation.ts index 68fa2b9afe..e5eca2a6ac 100644 --- a/packages/app-shell/src/views/metadata-admin/clientValidation.ts +++ b/packages/app-shell/src/views/metadata-admin/clientValidation.ts @@ -164,7 +164,7 @@ function viewSchemaForDraft(item: ZodLikeSchema, container: ZodLikeSchema): ZodL * that root issue literally is what collapsed every field-level diagnostic on * the edit path into one un-addressable "Invalid input": `SchemaForm` highlights * by `path` and Monaco locates by `path`, so an empty path points at nothing, - * and the guided messages the spec wrote for these rejections (#4001) never + * and the guided messages the spec wrote for these rejections (objectstack-ai/objectstack#4001) never * reached the user. * * Selection is by the draft's OWN discriminant — the same `isViewItemDraft` the @@ -362,7 +362,7 @@ function arrayVariantMemberIndex(groups: ZodLikeIssue[][], value: unknown): numb * `sort: [{field: 'n', order: 'bogus'}]` the plain-`string` member rejects the * array outright and the `ColumnSort[]` member reports * `[0].order` / `Invalid option: expected one of "asc"|"desc"` — the spec's own - * guided message (#4001), which until now was thrown away and rendered as + * guided message (objectstack-ai/objectstack#4001), which until now was thrown away and rendered as * `config.sort` / `Invalid input`. * * This rule does NOT index members positionally: the index is derived from the @@ -624,7 +624,7 @@ const LOADERS: Record = { // // CREATE — the authoring gate, unchanged: `viewSchemaForDraft` dispatches on // the record's own `viewKind` discriminant to `ViewItemSchema` (what - // `createBuildBody` emits) or `ViewSchema` (the container). #5074 made these + // `createBuildBody` emits) or `ViewSchema` (the container). objectstack-ai/objectstack#5074 made these // strict on purpose and this admin's create path passes them cleanly. // // EDIT — the WIRE gate. The editor opens a body that came back out of @@ -636,7 +636,7 @@ const LOADERS: Record = { // the accepted body verbatim (ADR-0005 §Validation). So the server ACCEPTS // this body — it validates against `ViewMetadataSchema` — while the authoring // gate rejects it. Judging a stored body by the authoring schema made the - // client strictly stricter than the server; that is the inversion #5316 fixes. + // client strictly stricter than the server; that is the inversion objectstack-ai/objectstack#5316 fixes. // // Why `ViewMetadataSchema` and not the narrower `ViewItemWireSchema`, which // also declares `isPinned`/`sortOrder`: two measured reasons. @@ -699,7 +699,7 @@ const LOADERS: Record = { // since spec 7.1.0 (`BUILTIN_METADATA_TYPE_SCHEMAS` in // `kernel/metadata-type-schemas.ts` is the authority); `EmailTemplateSchema` // survived only as an inline sub-shape of the old `Notification` holder and - // was deleted with it in objectstack#4610 / #4616. So this validator was + // was deleted with it in objectstack#4610 / objectstack-ai/objectstack#4616. So this validator was // checking authored templates against the WRONG contract — `name` + `locale` // and `bodyHtml` / `bodyText`, not `id` and `body` + `bodyType`. email_template: async () => (await import('@objectstack/spec/system')).EmailTemplateDefinitionSchema as unknown as ZodLikeSchema, @@ -870,7 +870,7 @@ async function validateObjectFieldRules(draft: unknown): Promise 100` authored here does not * merely fail to match — it rejects EVERY write to the object, and the spec's * Zod accepts it (`ExpressionInputSchema` checks the SHAPE only, exactly as it diff --git a/packages/app-shell/src/views/metadata-admin/datasource/DatasourceResourcePage.tsx b/packages/app-shell/src/views/metadata-admin/datasource/DatasourceResourcePage.tsx index 250431c9b3..02201b9463 100644 --- a/packages/app-shell/src/views/metadata-admin/datasource/DatasourceResourcePage.tsx +++ b/packages/app-shell/src/views/metadata-admin/datasource/DatasourceResourcePage.tsx @@ -213,7 +213,7 @@ export function DatasourceResourcePage(_props: { type?: string }): React.ReactEl let body: any = text; try { body = JSON.parse(text); } catch { /* keep text */ } if (!res.ok) { - // `error` is `{ code, message }` post-#3843 and was a bare string + // `error` is `{ code, message }` post-objectstack-ai/objectstack#3843 and was a bare string // before it; without the first read this threw "[object Object]". const detail = (body && typeof body.error === 'object' && body.error?.message) || diff --git a/packages/app-shell/src/views/metadata-admin/form-spec.ts b/packages/app-shell/src/views/metadata-admin/form-spec.ts index e163f8b90d..5f05696d11 100644 --- a/packages/app-shell/src/views/metadata-admin/form-spec.ts +++ b/packages/app-shell/src/views/metadata-admin/form-spec.ts @@ -145,7 +145,7 @@ export interface FormFieldSpec { * engine honours on the insert path (`applyFieldDefaults` falls back to * the option marked `default: true` when the field declares no * `defaultValue`; `defaultValue` wins when both are declared — - * objectstack#7246, ruled `enforce`, PR #7388). That is why + * objectstack#7246, ruled `enforce`, PR objectstack-ai/objectstack#7388). That is why * `SelectOptionSchema` still carries the key and only this reference site * narrows it: one surface honours it, this one deliberately does not, and * a second default contract here is what the 2026-08-10 ruling's objectui diff --git a/packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeConfigField.tsx b/packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeConfigField.tsx index b95126329f..64a0543d6d 100644 --- a/packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeConfigField.tsx +++ b/packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeConfigField.tsx @@ -58,7 +58,7 @@ export interface FlowNodeConfigFieldProps { context?: FlowReferenceContext; /** In-scope variable references for the data-picker (#1934). */ scopeGroups?: ScopeGroup[]; - /** #3447: approval-expression picker groups (current/trigger/vars roots). */ + /** objectstack-ai/objectstack#3447: approval-expression picker groups (current/trigger/vars roots). */ approvalScopeGroups?: ScopeGroup[]; /** * The trigger record's declared subject vocabulary at this node, when one is diff --git a/packages/app-shell/src/views/metadata-admin/inspectors/FlowObjectListField.tsx b/packages/app-shell/src/views/metadata-admin/inspectors/FlowObjectListField.tsx index b0c406544a..29c7f4231d 100644 --- a/packages/app-shell/src/views/metadata-admin/inspectors/FlowObjectListField.tsx +++ b/packages/app-shell/src/views/metadata-admin/inspectors/FlowObjectListField.tsx @@ -145,7 +145,7 @@ export interface FlowObjectListFieldProps { /** In-scope variable references for `expression` columns (#1934). */ scopeGroups?: ScopeGroup[]; /** - * #3447: picker groups for approval `expression` approver cells — the + * objectstack-ai/objectstack#3447: picker groups for approval `expression` approver cells — the * closed current/trigger/vars root set. Regular flow scopeGroups must NOT * be offered there (record.* / bare-field spellings are rejected at * runtime), which is why this rides as its own prop. @@ -349,7 +349,7 @@ export function FlowObjectListField({ const disc = col.ref?.kindFrom ? String(row.values[col.ref.kindFrom] ?? '') : ''; - // #3447: `expression` is a discriminator value, not a + // objectstack-ai/objectstack#3447: `expression` is a discriminator value, not a // reference kind — an approver whose sibling `type` is // 'expression' authors a CEL expression over the approval // roots (current/trigger/vars). Render the expression diff --git a/packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx b/packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx index ef95d10984..d5e42d909c 100644 --- a/packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx +++ b/packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx @@ -14,7 +14,7 @@ * extra dependencies, and built-in accessibility. * * Four kinds carry a stronger contract than suggest-and-allow-anything - * (framework #3508): the directory-backed kinds (`user`/`team`/`department`/ + * (objectstack-ai/objectstack#3508): the directory-backed kinds (`user`/`team`/`department`/ * `position`) render a record lookup against the data API (with a manual-entry * escape hatch, so the never-trap rule still holds), `org-membership-level` is * a strict select over a closed enum, `manager` is auto-resolved (disabled @@ -70,7 +70,7 @@ interface Option { * backed by DATA records, not the metadata registry: they used to map here, * so the picker queried `GET /api/v1/meta/user` (which lists no `sys_user` * rows), came back empty, and silently degraded to a free-text id box - * (framework #3508). They live in {@link KIND_TO_RECORD_LOOKUP} instead. + * (objectstack-ai/objectstack#3508). They live in {@link KIND_TO_RECORD_LOOKUP} instead. */ const KIND_TO_META_TYPE: Partial> = { object: 'object', @@ -82,7 +82,7 @@ const KIND_TO_META_TYPE: Partial> = { /** * Reference kinds backed by DATA records in the system directory objects — * mirrors `APPROVER_VALUE_BINDINGS` in `@objectstack/spec` (automation/ - * approval.zod.ts, framework #3508; import it once a published ^16 release + * approval.zod.ts, objectstack-ai/objectstack#3508; import it once a published ^16 release * carries the export). The approval engine resolves these against records, * so the designer offers a record lookup through the DataSource adapter. * @@ -135,7 +135,7 @@ const RECORD_LOOKUP_PRESENTATION = { * registry, which holds no `sys_user` / `sys_team` / `sys_business_unit` / * `sys_position` ROWS, so candidates came back empty, the control degraded to * free text, and `sales_manager` got typed into a field that accepts three - * values (framework #3508). Spec answered by publishing the binding with a + * values (objectstack-ai/objectstack#3508). Spec answered by publishing the binding with a * `satisfies` that makes an undeclared `ApproverType` a compile error; reading * it here is what finally carries that guarantee across the repo boundary. * @@ -167,7 +167,7 @@ export const KIND_TO_RECORD_LOOKUP: Partial; /** * Where each discriminator value's candidates actually live, keyed like - * {@link map} — published by the spec as `xRef.sources` (framework #3508 + * {@link map} — published by the spec as `xRef.sources` (objectstack-ai/objectstack#3508 * follow-up) and carried through by `json-schema-to-fields`. * * {@link map} only ever named a picker KIND. It never said what backs that @@ -416,7 +416,7 @@ const FLOW_NODE_CONFIG: Record = { help: 'Cron expression — when the flow runs. A time-relative sweep defaults to daily if left empty.', showWhen: { field: 'triggerType', equals: ['schedule', 'time_relative'] }, }, - // Time-relative trigger (#1874) — a `config.timeRelative` descriptor sweeps an + // Time-relative trigger (objectstack-ai/objectstack#1874) — a `config.timeRelative` descriptor sweeps an // object on a schedule (daily by default) and launches the flow once per record // whose date field falls in the window. All fields live under the nested // `config.timeRelative` block (which the whole group "owns", so it never leaks @@ -812,7 +812,7 @@ const FLOW_NODE_CONFIG: Record = { { value: 'department', label: 'Department' }, { value: 'team', label: 'Team' }, { value: 'field', label: 'Field' }, - // #3447: CEL over current.* / trigger.* / vars.*, resolved at node + // objectstack-ai/objectstack#3447: CEL over current.* / trigger.* / vars.*, resolved at node // entry — the value cell switches to the expression input. { value: 'expression', label: 'Expression (CEL)' }, { value: 'org_membership_level', label: 'Organization membership tier' }, @@ -823,8 +823,8 @@ const FLOW_NODE_CONFIG: Record = { // Polymorphic: the picker follows the row's `type` — record lookups // for the directory kinds, a strict select for the membership tier, // an auto-resolved cell for `manager`, an object-field picker for - // `field` (framework #3508). Unmapped/empty types fall back to free - // text — except `expression` (#3447), which the cell special-cases + // `field` (objectstack-ai/objectstack#3508). Unmapped/empty types fall back to free + // text — except `expression` (objectstack-ai/objectstack#3447), which the cell special-cases // into the CEL expression input (it is a discriminator value, not a // reference kind, so it deliberately has no `map` entry). key: 'value', @@ -852,7 +852,7 @@ const FLOW_NODE_CONFIG: Record = { }, }, { - // #3447: expression-only — how the expression's resolved ids expand + // objectstack-ai/objectstack#3447: expression-only — how the expression's resolved ids expand // into people. Dead config on other types (linted server-side). key: 'resolveAs', label: 'Resolve as', @@ -865,7 +865,7 @@ const FLOW_NODE_CONFIG: Record = { ], }, { - // Group label for `per_group` sign-off (#3266): approvers sharing a + // Group label for `per_group` sign-off (objectstack-ai/objectstack#3266): approvers sharing a // label form one group; the node advances when EACH group reaches // `minApprovals`. Ignored by other behaviors. key: 'group', @@ -907,7 +907,7 @@ const FLOW_NODE_CONFIG: Record = { placeholder: 'approval_status', help: 'Business-object field to mirror request status onto (pending/approved/rejected). Should be readonly.', }), - // #3447: empty-slate policy — load-bearing for expression approvers, whose + // objectstack-ai/objectstack#3447: empty-slate policy — load-bearing for expression approvers, whose // slate is runtime data and may legitimately resolve to nobody. cfg('onEmptyApprovers', 'If no approver resolves', 'select', { options: [ @@ -1033,7 +1033,7 @@ const FLOW_NODE_CONFIG: Record = { ], help: 'Notification severity.', }), - // Click-through target (#2675): deep-link the notification to a record. + // Click-through target (objectstack-ai/objectstack#2675): deep-link the notification to a record. cfg('sourceObject', 'Link object', 'text', { placeholder: 'sys_approval_request', help: 'Object of the record the notification links to (requires Link record id).' }), cfg('sourceId', 'Link record id', 'text', { help: 'Record id the notification links to (requires Link object).' }), cfg('url', 'Click-through URL', 'text', { help: 'Explicit link; overrides the one synthesized from Link object/record.' }), diff --git a/packages/app-shell/src/views/metadata-admin/inspectors/flow-scope.ts b/packages/app-shell/src/views/metadata-admin/inspectors/flow-scope.ts index b63690b94c..aafdc3e546 100644 --- a/packages/app-shell/src/views/metadata-admin/inspectors/flow-scope.ts +++ b/packages/app-shell/src/views/metadata-admin/inspectors/flow-scope.ts @@ -38,7 +38,7 @@ import { t, tFormat } from '../i18n.js'; /** Which group a reference belongs to (drives the picker's section headers). */ export type ScopeGroupId = | 'variables' | 'outputs' | 'loop' | 'trigger' - // #3447: approval `expression` approvers see a DIFFERENT root set than flow + // objectstack-ai/objectstack#3447: approval `expression` approvers see a DIFFERENT root set than flow // conditions (current/trigger/vars — never `record`/bare fields). Their // picker groups carry their own ids so they can never leak into the regular // condition picker. @@ -109,7 +109,7 @@ interface FlowEdgeLike { const RECORD_TRIGGER_TYPES = new Set([ 'record-after-create', 'record-after-update', - 'record-after-write', // create OR update (#3427) + 'record-after-write', // create OR update (objectstack-ai/objectstack#3427) 'record-before-write', 'record-before-update', 'record-after-delete', diff --git a/packages/app-shell/src/views/metadata-admin/inspectors/json-schema-to-fields.ts b/packages/app-shell/src/views/metadata-admin/inspectors/json-schema-to-fields.ts index 273f68f09d..27326c265f 100644 --- a/packages/app-shell/src/views/metadata-admin/inspectors/json-schema-to-fields.ts +++ b/packages/app-shell/src/views/metadata-admin/inspectors/json-schema-to-fields.ts @@ -84,7 +84,7 @@ interface JsonSchemaNode { kindFrom?: string; map?: Record; /** - * Per-discriminator data contract (framework #3508 follow-up): where each + * Per-discriminator data contract (objectstack-ai/objectstack#3508 follow-up): where each * kind's candidates live and which column the picker commits. `map` names * only a picker KIND, which is how this package came to query the metadata * REGISTRY for data records; with `sources` the designer reads the answer @@ -116,7 +116,7 @@ const REFERENCE_KINDS: ReadonlySet = new Set([ 'queue', 'department', // Auto-resolved approver (submitter's manager) — renders as a disabled - // cell, not a picker (framework #3508). Listed so the spec's xRef map entry + // cell, not a picker (objectstack-ai/objectstack#3508). Listed so the spec's xRef map entry // survives validation; an older designer without it just degraded to text. 'manager', 'connector', diff --git a/packages/app-shell/src/views/metadata-admin/inspectors/useFlowScope.ts b/packages/app-shell/src/views/metadata-admin/inspectors/useFlowScope.ts index 30290c397e..b8cfc13e28 100644 --- a/packages/app-shell/src/views/metadata-admin/inspectors/useFlowScope.ts +++ b/packages/app-shell/src/views/metadata-admin/inspectors/useFlowScope.ts @@ -34,7 +34,7 @@ export interface UseFlowScopeResult { /** Flat, de-duplicated ref list (all groups). */ refs: ScopeRef[]; /** - * #3447: the picker groups for an approval node's `expression` APPROVER, + * objectstack-ai/objectstack#3447: the picker groups for an approval node's `expression` APPROVER, * whose closed root set differs from a flow condition's — `current.` * (live record at node entry), `trigger.` (submit-time snapshot) and * `vars.*` (flow variables / upstream outputs, prefix-mapped). `record.*` @@ -61,7 +61,7 @@ export interface UseFlowScopeResult { isEmpty: boolean; } -// The REGULAR picker's sections — the approval_* group ids (#3447) never +// The REGULAR picker's sections — the approval_* group ids (objectstack-ai/objectstack#3447) never // appear here; they ride the separately-emitted approvalExpressionGroups. // Each heading is a catalogue key, resolved in the designer locale // (objectui#10748). @@ -109,7 +109,7 @@ export function useFlowScope( refs: refs.filter((r) => r.group === id), })).filter((g) => g.refs.length > 0); - // #3447: approval-expression picker groups, built from the same materials. + // objectstack-ai/objectstack#3447: approval-expression picker groups, built from the same materials. // Trigger-object fields expand under BOTH times (current/trigger); the // graph-walk refs (variables / upstream outputs / loop items) re-home // under the `vars.` prefix. Trigger-group refs (record., previous., diff --git a/packages/app-shell/src/views/metadata-admin/previews/ActionPreview.tsx b/packages/app-shell/src/views/metadata-admin/previews/ActionPreview.tsx index 678077a348..606a44f39f 100644 --- a/packages/app-shell/src/views/metadata-admin/previews/ActionPreview.tsx +++ b/packages/app-shell/src/views/metadata-admin/previews/ActionPreview.tsx @@ -174,7 +174,7 @@ export function ActionPreview({ name, draft, locale }: MetadataPreviewProps) { const icon = (d.icon as string | undefined) || undefined; const type = String(d.type ?? 'script'); // `target` only: the `execute` alias was removed in @objectstack/spec 17 - // (#3855, #3856). Reading it here would preview a draft as bound when the + // (objectstack-ai/objectstack#3855, objectstack-ai/objectstack#3856). Reading it here would preview a draft as bound when the // spec rejects it at save, which is the opposite of what a preview is for. const target = d.target as string | undefined; const variant = (d.variant as string | undefined) || undefined; @@ -580,7 +580,7 @@ function renderFieldMock(p: ActionParam, fieldLabel: string, locale?: string): R if (widget === undefined) return options.length > 0 ? selectMock : inputMock('text'); // A targetless picker collapses to a record-id text box in the dialog, with - // its own placeholder and help text (#3405). The box alone would be honest + // its own placeholder and help text (objectstack-ai/objectstack#3405). The box alone would be honest // about the control and silent about the reason, which is the state that // help text was added for. if (degraded) { diff --git a/packages/app-shell/src/views/metadata-admin/previews/AgentPreview.tsx b/packages/app-shell/src/views/metadata-admin/previews/AgentPreview.tsx index a91e951520..e4f07a3e46 100644 --- a/packages/app-shell/src/views/metadata-admin/previews/AgentPreview.tsx +++ b/packages/app-shell/src/views/metadata-admin/previews/AgentPreview.tsx @@ -13,7 +13,7 @@ * * NOT shown — `agent.tools` and `agent.knowledge` (objectui#3275). * Both are `retiredKey()` tombstones in `@objectstack/spec` 17 - * (objectstack#3894 / #3896): `AgentSchema` rejects them BY NAME, so a + * (objectstack#3894 / objectstack-ai/objectstack#3896): `AgentSchema` rejects them BY NAME, so a * draft carrying either cannot be saved. This preview used to read both * and paint a TOOLS chip strip plus a `KNOWLEDGE (RAG)` block, which told * the author their draft was fine right up until publish refused it — diff --git a/packages/app-shell/src/views/metadata-admin/previews/AppPreview.tsx b/packages/app-shell/src/views/metadata-admin/previews/AppPreview.tsx index 81818698a9..f6c3d52706 100644 --- a/packages/app-shell/src/views/metadata-admin/previews/AppPreview.tsx +++ b/packages/app-shell/src/views/metadata-admin/previews/AppPreview.tsx @@ -201,7 +201,7 @@ export function AppPreview({ name, draft, editing, selection, onSelectionChange, // The landing page is DERIVED, never authored: it is the first navigation // item that actually addresses something. The app used to be able to pin it // with `homePageId`, but spec 17.0.0 retired that key (objectstack#4667 / - // #4709) — an ID cross-reference with no referential integrity, which fell + // objectstack-ai/objectstack#4709) — an ID cross-reference with no referential integrity, which fell // back to the first item silently when it dangled. Before that it was // `landing`, removed in objectstack#4001. Reading either one back here would // show the author a landing page the runtime will not honour. diff --git a/packages/app-shell/src/views/metadata-admin/previews/FlowRunsPanel.tsx b/packages/app-shell/src/views/metadata-admin/previews/FlowRunsPanel.tsx index 9ef9458f1e..583a90be1b 100644 --- a/packages/app-shell/src/views/metadata-admin/previews/FlowRunsPanel.tsx +++ b/packages/app-shell/src/views/metadata-admin/previews/FlowRunsPanel.tsx @@ -4,12 +4,12 @@ * FlowRunsPanel — run history for a flow, fetched from the automation engine * (`GET /api/v1/automation/{name}/runs`, the observability surface next to * resume/screen). Renders each run's status / start time / duration with an - * expandable step log (the `ExecutionLog.steps` ADR-0019/#1479 shape). Body + * expandable step log (the `ExecutionLog.steps` ADR-0019 / objectstack-ai/objectstack#1479 shape). Body * steps that ran inside a structured control-flow region — a `loop` iteration, * a `parallel` branch, or a `try`/`catch` handler — are nested under their - * container node and grouped by iteration / branch (#1505), so authors can see + * container node and grouped by iteration / branch (objectstack-ai/objectstack#1505), so authors can see * where a run paused or failed *and which iteration did it*, without leaving the - * Studio. A step may also carry advisory `warnings` (#3407) — e.g. a write to a + * Studio. A step may also carry advisory `warnings` (objectstack-ai/objectstack#3407) — e.g. a write to a * `readonly` field the data layer legally stripped — rendered amber beneath the * step without demoting its `success` status. * @@ -37,7 +37,7 @@ interface RunStep { status: 'success' | 'failure' | 'skipped' | string; durationMs?: number; error?: RunError; - // #1505: structured-region grouping. A step that ran inside a `loop` / + // objectstack-ai/objectstack#1505: structured-region grouping. A step that ran inside a `loop` / // `parallel` / `try_catch` body region is tagged by the engine with its // immediate container so the panel can nest it, instead of showing the // container as one opaque step. Absent on top-level (main-graph) steps. @@ -48,7 +48,7 @@ interface RunStep { branch?: number; /** Region kind the step ran in: `loop-body` | `parallel-branch` | `try` | `catch`. */ regionKind?: string; - // #3407: advisory warnings the engine attaches to an otherwise-successful step + // objectstack-ai/objectstack#3407: advisory warnings the engine attaches to an otherwise-successful step // — e.g. an `update_record` whose write to a `readonly` / `readonlyWhen` field // was legally stripped by the data layer. The step still `success`es (the strip // is legitimate semantics); the warning is the only signal the intended write @@ -91,7 +91,7 @@ export function errorText(e: RunError | undefined | null): string | undefined { /** * Reconstruct the execution tree from the engine's flat, pre-order step log - * (#1505). Each step carries its **immediate** structured-region container in + * (objectstack-ai/objectstack#1505). Each step carries its **immediate** structured-region container in * `parentNodeId`; the container's own step always precedes its body steps in the * array, and a whole region's steps are contiguous (the engine appends * `NodeExecutionResult.childSteps` in one shot). A stack walk therefore rebuilds @@ -169,7 +169,7 @@ export function parallelBranchIndex(step: RunStep): ParallelBranchIndex { } /** - * Human label for a body step's enclosing region (#1505). `loop-body` carries a + * Human label for a body step's enclosing region (objectstack-ai/objectstack#1505). `loop-body` carries a * zero-based `iteration`, `parallel-branch` a zero-based `branch` plus the * enclosing loop's `iteration` when it has one (read by * {@link parallelBranchIndex}), each surfaced 1-based; `try`/`catch` carry only @@ -289,7 +289,7 @@ function StepRow({ step, depth = 0 }: { step: RunStep; depth?: number }) { ? 'text-rose-600 dark:text-rose-400' : 'text-muted-foreground'; const stepErr = errorText(step.error); - // #3407: advisory warnings are amber and never recolor the status — a step + // objectstack-ai/objectstack#3407: advisory warnings are amber and never recolor the status — a step // that legally stripped a write is still a `success`, just not silent. The // status badge keeps its tone; the ⚠ marker and the amber sub-lines below // carry the "your write didn't fully land" signal. @@ -346,7 +346,7 @@ function RegionHeader({ label, depth }: { label: string; depth: number }) { } /** Render a step and, nested beneath it, its structured-region body steps — - * grouped by iteration / branch / handler (#1505). Recurses for nested regions. */ + * grouped by iteration / branch / handler (objectstack-ai/objectstack#1505). Recurses for nested regions. */ function StepNode({ node, depth, locale }: { node: StepTreeNode; depth: number; locale?: string }) { const groups = node.children.length > 0 ? groupChildren(node.children, locale) : []; return ( diff --git a/packages/app-shell/src/views/metadata-admin/previews/ToolPreview.tsx b/packages/app-shell/src/views/metadata-admin/previews/ToolPreview.tsx index 6ec5a47839..e58fac284a 100644 --- a/packages/app-shell/src/views/metadata-admin/previews/ToolPreview.tsx +++ b/packages/app-shell/src/views/metadata-admin/previews/ToolPreview.tsx @@ -22,7 +22,7 @@ * for end-to-end testing — see `ApiConsoleLink` below for where it points * and what it carries (objectui#10591). * - * NO FLAG PILLS — deliberate (objectstack#3715 / #3896, objectui#3236). + * NO FLAG PILLS — deliberate (objectstack#3715 / objectstack-ai/objectstack#3896, objectui#3236). * The header strip used to render `requiresConfirmation`, `active`, * `builtIn` and `category`. All four were removed from the spec's * `ToolSchema`, which is now `.strict()` and rejects them by name with an diff --git a/packages/app-shell/src/views/useOpenRecordList.ts b/packages/app-shell/src/views/useOpenRecordList.ts index 20a7fa10e5..05afe839ee 100644 --- a/packages/app-shell/src/views/useOpenRecordList.ts +++ b/packages/app-shell/src/views/useOpenRecordList.ts @@ -19,7 +19,7 @@ import { serializeDrillFilterParams } from './drillUrlFilters.js'; * Navigates to the object's ADR-0055 bare data surface, scoped by a record * filter, using the console's `/apps/:appName/:object/data?filter[...]` route * shape. Equality dims serialize to `filter[field]=value`; a date-bucket drill's - * range serializes to `filter[field][gte]=…&filter[field][lt]=…` (#1752). Wire it + * range serializes to `filter[field][gte]=…&filter[field][lt]=…` (objectstack-ai/objectstack#1752). Wire it * into a `DrillNavigationProvider` so the dashboard/report drill drawers can offer * "Open in list →" and honor `drillDown.target: 'navigate'`. * @@ -73,12 +73,12 @@ export function useOpenRecordList(): (objectName: string, filter?: Record) => { // Expand EVERY placeholder vocabulary in one call — date macros and // session tokens. Calling only one of the two is the defect this helper - // exists to prevent (framework #3574): `{today}` would work and + // exists to prevent (objectstack-ai/objectstack#3574): `{today}` would work and // `{current_user_id}` would silently not. const runtimeFilter = resolveFilterPlaceholders(filter, filterScope); // A date-bucket drill carries an ObjectQL range operator object // (`{ $gte, $lt }`); the shared serializer emits it as `filter[field][gte|lt]` - // (never "[object Object]"). Equality dims stay `filter[field]=value` (#1752). + // (never "[object Object]"). Equality dims stay `filter[field]=value` (objectstack-ai/objectstack#1752). const qs = serializeDrillFilterParams(runtimeFilter).toString(); const base = appName ? `/apps/${appName}` : ''; // ADR-0055 bare data surface (`/:object/data`): "the URL is the view" — no diff --git a/packages/app-shell/src/views/viewFilterFold.ts b/packages/app-shell/src/views/viewFilterFold.ts index ed9c0ee58b..0f278c8c9b 100644 --- a/packages/app-shell/src/views/viewFilterFold.ts +++ b/packages/app-shell/src/views/viewFilterFold.ts @@ -161,7 +161,7 @@ function isGroupLike(value: unknown): value is FilterGroupLike { * value}` — the spec version this repo pins REJECTS a rule carrying `id` * with `unrecognized_keys` on `filter.0`. (The issue's replay matrix saw * variant ② accepted against a server running framework `main`, where - * #5154 tolerates the extra key; objectui's own pin does not. Keeping the + * objectstack-ai/objectstack#5154 tolerates the extra key; objectui's own pin does not. Keeping the * id would only trade one 422 for another.) * 2. Nothing downstream needs it persisted: the read path regenerates it — * `parseSpecFilter`'s `parseTriplet` always mints `crypto.randomUUID()`, diff --git a/packages/auth/src/createAuthenticatedFetch.ts b/packages/auth/src/createAuthenticatedFetch.ts index 6de192b8c4..bf273649b8 100644 --- a/packages/auth/src/createAuthenticatedFetch.ts +++ b/packages/auth/src/createAuthenticatedFetch.ts @@ -139,7 +139,7 @@ export function createAuthenticatedFetch( // switcher, so reading it here means a language switch carries the new // `Accept-Language` on every subsequent request — closing the gap where // server-resolved labels stayed in the old language until a page refresh - // (issue #1319). We only fold it in for our own API calls, and never + // (issue objectstack-ai/objectstack#1319). We only fold it in for our own API calls, and never // clobber an `Accept-Language` the caller set explicitly. if (isApiCall && !headers.has('Accept-Language') && typeof document !== 'undefined') { const lang = document.documentElement.lang; diff --git a/packages/auth/src/types.ts b/packages/auth/src/types.ts index 9c39e968bd..5c7c36360d 100644 --- a/packages/auth/src/types.ts +++ b/packages/auth/src/types.ts @@ -272,7 +272,7 @@ export interface AuthPublicConfig { * better-auth admin plugin mounted server-side (`auth.plugins.admin`; * SCIM forces it on). Gates the admin user-management surfaces — the * sys_user create/set-password actions and the identity import wizard - * entry (framework#2766 / #2782). + * entry (framework#2766 / objectstack-ai/objectstack#2782). */ admin?: boolean; /** diff --git a/packages/components/src/renderers/action/action-bar.tsx b/packages/components/src/renderers/action/action-bar.tsx index ba45c2bba2..17432863b5 100644 --- a/packages/components/src/renderers/action/action-bar.tsx +++ b/packages/components/src/renderers/action/action-bar.tsx @@ -202,7 +202,7 @@ const ActionBarRenderer = forwardRef = ({ action, onExecute, record }) => { const { recordData, isVisible } = useMenuActionVisible(action, record); // Spec `disabled` (boolean | CEL — disabled when TRUE) primary, legacy - // non-spec `enabled` fallback (#1885 follow-through — only action-button + // non-spec `enabled` fallback (objectstack-ai/objectstack#1885 follow-through — only action-button // was wired; this renderer ignored a spec-authored `disabled`). const isDisabledPred = useCondition(toPredicateInput((action as any).disabled), recordData); const isEnabled = useCondition(toPredicateInput(action.enabled), recordData); diff --git a/packages/components/src/renderers/basic/metadata-viewer.tsx b/packages/components/src/renderers/basic/metadata-viewer.tsx index 9a9eb056dd..167289de97 100644 --- a/packages/components/src/renderers/basic/metadata-viewer.tsx +++ b/packages/components/src/renderers/basic/metadata-viewer.tsx @@ -133,7 +133,7 @@ function Placeholder({ tone = 'muted', children }: { tone?: 'muted' | 'warn'; ch * - `default` is KEPT, and is read at `initial` below. That is deliberate and * is the whole reason this is a spec derivation rather than a narrower * local shape: `default` on the OBJECT-field face is ruled `enforce` - * (objectstack#7246, implemented by PR #7388) — the engine seeds the insert + * (objectstack#7246, implemented by PR objectstack-ai/objectstack#7388) — the engine seeds the insert * path from the option marked `default: true` — so the state this view * calls "initial" is the same one the platform actually writes. * diff --git a/packages/components/src/renderers/form/form.tsx b/packages/components/src/renderers/form/form.tsx index 805d147387..0c1a1bb147 100644 --- a/packages/components/src/renderers/form/form.tsx +++ b/packages/components/src/renderers/form/form.tsx @@ -1463,7 +1463,7 @@ ComponentRegistry.register('form', }, previousRecord, predicateScope, - // Same locator as the render path (#5149). A failure here reports the + // Same locator as the render path (objectstack-ai/objectstack#5149). A failure here reports the // field, not a bare rule kind; `warnPredicateFailure` dedupes by // predicate source, so re-evaluating a rule the renderer already // evaluated cannot double-warn. @@ -1514,7 +1514,7 @@ ComponentRegistry.register('form', }, previousRecord, predicateScope, - // Same locator the render path uses (#5149), so a faulted + // Same locator the render path uses (objectstack-ai/objectstack#5149), so a faulted // predicate is reported once, against the field. `field '${name}'`, ); @@ -2455,7 +2455,7 @@ ComponentRegistry.register('form', // producer-side marking: a hook sets it at throw time to // say "this text is for the end user". It is a separate field from // `message`, so nothing unmarked can reach here — the substitution above - // still governs every platform diagnostic, and #3821 holds by + // still governs every platform diagnostic, and objectstack-ai/objectstack#3821 holds by // construction rather than by us guessing what a 403 body contains. // Status-agnostic on purpose: 403 is where this was reported // (objectui#5210), not a fence the contract draws. @@ -2631,7 +2631,7 @@ ComponentRegistry.register('form', // canonical CEL engine and record scope as visibleWhen; both // the bare-string and `{ dialect, source }` wire shapes are // accepted, and a broken predicate fails open — loudly since - // #5149 (#2212). + // objectstack-ai/objectstack#5149 (#2212). if ( visibleOn != null && !evalFieldPredicate(visibleOn, ruleRecord, true, previousRecord, predicateScope, { diff --git a/packages/components/src/renderers/layout/containers.tsx b/packages/components/src/renderers/layout/containers.tsx index e61d6ea211..7f1980f161 100644 --- a/packages/components/src/renderers/layout/containers.tsx +++ b/packages/components/src/renderers/layout/containers.tsx @@ -1257,7 +1257,7 @@ ComponentRegistry.register('section', PageSectionRenderer, { /** * One-time diagnostics for header-action `visible` / `hidden` predicates * (#2358). Warn-once per (action, predicate) pair so re-renders don't spam the - * console, mirroring ActionEngine's `warnHiddenPredicate` (#2183). + * console, mirroring ActionEngine's `warnHiddenPredicate` (objectstack-ai/objectstack#2183). * * The *fault* half of these diagnostics is no longer written here: since * objectui#3521 the predicates run through `evalRowPredicate`, whose own diff --git a/packages/core/src/actions/ActionEngine.ts b/packages/core/src/actions/ActionEngine.ts index b47355c53a..45288a8c1a 100644 --- a/packages/core/src/actions/ActionEngine.ts +++ b/packages/core/src/actions/ActionEngine.ts @@ -286,7 +286,7 @@ export class ActionEngine { // BARE field reference (`done` instead of `record.done`), which is // an undeclared variable in the `{ record, recordId, objectName, // user }` eval scope. Silently hiding it makes that bug invisible - // (the #2183 hunt). Warn once per predicate so it is diagnosable + // (the objectstack-ai/objectstack#2183 hunt). Warn once per predicate so it is diagnosable // without spamming re-renders. warnHiddenPredicate(ra.action.name, raw, err); return false; diff --git a/packages/core/src/actions/ActionRunner.ts b/packages/core/src/actions/ActionRunner.ts index ef3be97ce3..51f12663a2 100644 --- a/packages/core/src/actions/ActionRunner.ts +++ b/packages/core/src/actions/ActionRunner.ts @@ -285,9 +285,9 @@ export interface ActionDef { * `'url'`, flow name for `'flow'`, modal/page for `'modal'`, endpoint for * `'api'`, FormView name for `'form'`. * - * The `execute` alias was REMOVED in @objectstack/spec 17 (#3855) and is not - * read here (#3856) — don't re-add it. Two handler slots is how one action ran - * one script server-side and a different one client-side (#3713). + * The `execute` alias was REMOVED in @objectstack/spec 17 (objectstack-ai/objectstack#3855) and is not + * read here (objectstack-ai/objectstack#3856) — don't re-add it. Two handler slots is how one action ran + * one script server-side and a different one client-side (objectstack-ai/objectstack#3713). */ target?: string; /** @@ -350,7 +350,7 @@ export interface ActionDef { // rather than stylistic. `ActionSchema` is a `ZodPipe` whose transforms narrow // the authored shape — `visible` is authored as `string | { dialect, source }` // but INFERS to the object form alone. This runner consumes authored/stored - // rows, which #3903 established are rehydrated UNPARSED, so it sees the input + // rows, which objectstack-ai/objectstack#3903 established are rehydrated UNPARSED, so it sees the input // shape. Deriving from the `z.infer` side would type-error the raw-string // predicate that `ActionEngine` explicitly supports and that // `ActionEngine.visibility.test.ts` pins. @@ -763,7 +763,7 @@ export interface ActionParamDef { * hands back `type: param.type ?? 'text'`, and every downstream reader of the * degradation is blind to it: the param is a `text` param by then, so * `paramDegradesWithoutTarget()` answers false, `paramToField()` emits no - * "no reference target" warning, and the #3405 "paste a record id" hints do + * "no reference target" warning, and the objectstack-ai/objectstack#3405 "paste a record id" hints do * not apply either. A lookup param that should have rendered a record picker * renders an unannotated empty box instead — no options, no dropdown, and no * request for the referenced object on the wire, because no picker was ever @@ -1132,11 +1132,11 @@ export class ActionRunner { try { // `ActionDef` accepts any key of any type, so a typo (`targt`) and a // retired key (`execute`) both reach here having type-checked. Neither - // binds a handler, and binding no handler silently is the #2169 "Mark Done - // does nothing" shape. Dev-only, warn-once, changes nothing (#4075 step 1). + // binds a handler, and binding no handler silently is the objectstack-ai/objectstack#2169 "Mark Done + // does nothing" shape. Dev-only, warn-once, changes nothing (objectstack-ai/objectstack#4075 step 1). warnOnUnknownActionKeys(action); - // The compat window for the object-form `params` payload (#5777, maintainer + // The compat window for the object-form `params` payload (objectstack-ai/objectstack#5777, maintainer // ruling 2026-08-06 direction A). Checked HERE, before the param-collection // block below rewrites `action.params` into a values map — after that point // an action that authored a legitimate ActionParam[] DEFINITION array also @@ -1466,7 +1466,7 @@ export class ActionRunner { // found zero producers outside the channel's own pins. // // `readOnSuccessNavigation` stays as the shape guard, not as a - // discriminator: stored rows are rehydrated UNPARSED (#3903), so the value + // discriminator: stored rows are rehydrated UNPARSED (objectstack-ai/objectstack#3903), so the value // is still read as data, and a shape the spec refuses gets no reading — // no navigation, no callback dispatch, no lenient fallback. if (result.success && action.onSuccess) { @@ -1661,9 +1661,9 @@ export class ActionRunner { */ private async executeScript(action: ActionDef): Promise { // `target` is the only handler slot. The `execute` alias was removed in - // @objectstack/spec 17 (#3855), which rejects an authored `execute` at parse + // @objectstack/spec 17 (objectstack-ai/objectstack#3855), which rejects an authored `execute` at parse // with the rename prescription — so parsed metadata cannot carry it and a - // `target || execute` fallback could only ever evaluate to `target` (#3856). + // `target || execute` fallback could only ever evaluate to `target` (objectstack-ai/objectstack#3856). const script = action.target; if (!script) { // A spec `body` IS a script — this runner just cannot run one (see the @@ -1687,11 +1687,11 @@ export class ActionRunner { // `ActionDef` no longer declares `execute` — nor any open index signature // — so `tsc` now catches the retired key at every site that AUTHORS an // action literal in code. That is the half of the problem the type can - // reach. It is not this half: #3903 established that stored + // reach. It is not this half: objectstack-ai/objectstack#3903 established that stored // `sys_metadata` rows are rehydrated UNPARSED, so metadata written before // spec 17 arrives here as a plain object the compiler never saw, still // carrying `execute`. Declaring the key to make this read compile would - // re-legitimize a tombstone (#3855 removed it; the spec keeps it only to + // re-legitimize a tombstone (objectstack-ai/objectstack#3855 removed it; the spec keeps it only to // reject it BY NAME), and deleting the branch would send those rows back // to a bare "no script provided" — which reads as "you forgot a field" to // an author who did write one, the objectstack#2169 shape. @@ -2047,7 +2047,7 @@ export class ActionRunner { * old object-form `params` page — POSTed an empty body here. * * `params` contributes only in its DEPRECATED non-array form (the compat window - * #5777 opened; see `warnOnDeprecatedObjectParams`). An ARRAY `params` is a + * objectstack-ai/objectstack#5777 opened; see `warnOnDeprecatedObjectParams`). An ARRAY `params` is a * parameter DEFINITION list, not a payload: it reaches this method unconsumed * only when no `paramCollectionHandler` is mounted, and POSTing the definitions * as the request body was never a payload any endpoint wanted. It now falls @@ -2342,7 +2342,7 @@ export interface OnSuccessNavigation { * Is this `onSuccess` the spec's navigation block? * * The test IS the spec's declaration: a non-array object carrying a STRING - * `navigate`. Stored rows are rehydrated UNPARSED (#3903), so the runner reads + * `navigate`. Stored rows are rehydrated UNPARSED (objectstack-ai/objectstack#3903), so the runner reads * the value as data and anything else gets NO reading — since objectui#5934 * retired the legacy chained-callback channel (`ActionDef | ActionDef[]`), * there is no other channel for an off-contract shape to fall into. This is a diff --git a/packages/core/src/actions/actionKeys.ts b/packages/core/src/actions/actionKeys.ts index bdab186c1d..fd7cab57ce 100644 --- a/packages/core/src/actions/actionKeys.ts +++ b/packages/core/src/actions/actionKeys.ts @@ -19,7 +19,7 @@ * * That asymmetry was the issue. An open key set on a DECLARED METADATA CONTRACT * is what lets a typo (`targt`, `exectue`) and a tombstoned key (`execute`) both - * sail through to a runner that then silently does nothing — the #2169 "Mark + * sail through to a runner that then silently does nothing — the objectstack-ai/objectstack#2169 "Mark * Done does nothing" shape. * * This module was step 1 of the staged narrowing: make the key set VISIBLE and @@ -428,7 +428,7 @@ const isDev = (): boolean => * Dev-mode only: name the keys an action carries that no reader will ever look * at. Non-breaking by construction — it changes no types and rejects nothing. * - * Silently binding no handler is the #2169 "Mark Done does nothing" shape. The + * Silently binding no handler is the objectstack-ai/objectstack#2169 "Mark Done does nothing" shape. The * compiler now catches it in action literals AUTHORED IN CODE — objectstack#4075 * step 3 closed `ActionDef` — but not in the actions that arrive as DATA, which * reach the runner unparsed and which no compiler ever looked at. This is the diff --git a/packages/core/src/actions/actionResponse.ts b/packages/core/src/actions/actionResponse.ts index 7df738f0f0..5b491fc9cb 100644 --- a/packages/core/src/actions/actionResponse.ts +++ b/packages/core/src/actions/actionResponse.ts @@ -77,7 +77,7 @@ export interface ActionResponseOutcome { export function readActionPayload(envelope: unknown): unknown { // objectstack#3962 servers single-wrap: `body.data` IS the handler value, // so most of the time this is the identity function. Only the exact LEGACY - // action envelope (pre-#3962: a boolean `success` and no keys beyond the + // action envelope (pre-objectstack-ai/objectstack#3962: a boolean `success` and no keys beyond the // envelope's own) is unwrapped one more level — a handler value that // merely contains a `success` key passes through untouched. if (isLegacyActionEnvelope(envelope)) { @@ -107,7 +107,7 @@ export function interpretActionResponse( label: string, ): ActionResponseOutcome { const envelope = json?.data; - // Pre-#3962 servers reported a rejection as HTTP 200 with the inner + // Pre-objectstack-ai/objectstack#3962 servers reported a rejection as HTTP 200 with the inner // `{success:false, error}`; current servers answer a real status, which // `res.ok` catches first. Detected narrowly so a handler value that merely // contains `success: false` is not misread as a failure. diff --git a/packages/core/src/adapters/ValueDataSource.ts b/packages/core/src/adapters/ValueDataSource.ts index 2c5e46f4ae..0b8eef295c 100644 --- a/packages/core/src/adapters/ValueDataSource.ts +++ b/packages/core/src/adapters/ValueDataSource.ts @@ -189,7 +189,7 @@ function refuseArrayComparand( * * > *an empty `$icontains` comparand is REFUSED* — "Every row contains the * > empty substring, so evaluating it is a predicate that constrains nothing — - * > the widening #5240 refused `{ field: {} }` over, one level in." + * > the widening [objectstack-ai/objectstack#5240] refused `{ field: {} }` over, one level in." * * > *a non-string `$icontains` comparand is REFUSED* — "Coercing 42 to `"42"` * > would answer a query nobody wrote; the declared comparand type is string." diff --git a/packages/core/src/adapters/batchTransaction.ts b/packages/core/src/adapters/batchTransaction.ts index 073f56fcfd..122ad7079e 100644 --- a/packages/core/src/adapters/batchTransaction.ts +++ b/packages/core/src/adapters/batchTransaction.ts @@ -8,7 +8,7 @@ * Client-side emulation of {@link DataSource.batchTransaction} for adapters * that lack a server-side transactional batch endpoint. This is the single, * tested home for the non-atomic fallback (ObjectStack objectui #2679 / - * framework #1604 / ADR-0034 item 4): components call `runBatchTransaction` + * objectstack-ai/objectstack#1604 / ADR-0034 item 4): components call `runBatchTransaction` * unconditionally and never orchestrate cross-object writes themselves. * * The emulation runs operations sequentially — NOT the old `bulk('create')` diff --git a/packages/core/src/data-scope/ViewDataProvider.ts b/packages/core/src/data-scope/ViewDataProvider.ts index 8c0dd872ea..72f7d6889e 100644 --- a/packages/core/src/data-scope/ViewDataProvider.ts +++ b/packages/core/src/data-scope/ViewDataProvider.ts @@ -89,7 +89,7 @@ export interface DataFetcher { * * Optional because most fetchers only read records. A fetcher WITHOUT it * cannot honour a named view, and {@link ViewDataProvider.resolveElementDataSource} - * says so in `error` rather than dropping the key — the whole point of #5576 + * says so in `error` rather than dropping the key — the whole point of objectstack-ai/objectstack#5576 * is that a `view` the runtime cannot apply must never look applied. * * Either shape stored views come in is accepted: a map keyed by view id, or diff --git a/packages/core/src/data-scope/element-data-source.ts b/packages/core/src/data-scope/element-data-source.ts index 46d37ef443..ddfcaaeba3 100644 --- a/packages/core/src/data-scope/element-data-source.ts +++ b/packages/core/src/data-scope/element-data-source.ts @@ -443,7 +443,7 @@ function savedViewColumns(view: ElementSavedView | null | undefined): unknown { * * Pure — the caller resolves the view (see {@link resolveSavedView}) and owns * the "named a view that does not exist" decision. Passing `undefined` /`null` - * for `view` composes a binding with no view, which is exactly the pre-#5576 + * for `view` composes a binding with no view, which is exactly the pre-objectstack-ai/objectstack#5576 * behaviour for the other four keys. * * See the module doc for the per-key rule table; `filter` is the only key that diff --git a/packages/core/src/evaluator/ExpressionEvaluator.ts b/packages/core/src/evaluator/ExpressionEvaluator.ts index 678d9b85de..4a6737fddd 100644 --- a/packages/core/src/evaluator/ExpressionEvaluator.ts +++ b/packages/core/src/evaluator/ExpressionEvaluator.ts @@ -448,7 +448,7 @@ export class ExpressionEvaluator { // canonical helper fails soft to the fallback, so a value that tracks the // fallback in BOTH runs means the predicate faulted — then we throw. // `warn: false`: the throw below IS this path's diagnostic; without it one - // broken predicate would log AND throw (#5149). + // broken predicate would log AND throw (objectstack-ai/objectstack#5149). const asTrue = evalFieldPredicate(source, record, true, undefined, bag, { warn: false }); const asFalse = evalFieldPredicate(source, record, false, undefined, bag, { warn: false }); if (asTrue !== asFalse) { diff --git a/packages/core/src/evaluator/fieldRules.ts b/packages/core/src/evaluator/fieldRules.ts index d24a45f62f..83605f713b 100644 --- a/packages/core/src/evaluator/fieldRules.ts +++ b/packages/core/src/evaluator/fieldRules.ts @@ -263,7 +263,7 @@ export function evalFieldPredicate( ...(scope ? { extra: scope } : {}), }); // Parse error, type error, unbound identifier, engine fault … — every - // not-ok verdict resolves to the fallback, but never silently (#5149). + // not-ok verdict resolves to the fallback, but never silently (objectstack-ai/objectstack#5149). if (!res.ok) reason = `[${res.error.kind}] ${res.error.message}`; else value = res.value === true; } catch (err) { diff --git a/packages/core/src/evaluator/listConditional.ts b/packages/core/src/evaluator/listConditional.ts index cc42dd9d0c..60bae30492 100644 --- a/packages/core/src/evaluator/listConditional.ts +++ b/packages/core/src/evaluator/listConditional.ts @@ -140,7 +140,7 @@ function evalCel( // verbatim — no second engine — so CEL semantics never drift from B2. // `warn: false`: this caller reports the fault itself (the labelled // `warnEvalError` in `evalRowPredicate`) — one warning per broken predicate, - // not two (#5149). `onFault` carries the engine's reason across that silence + // not two (objectstack-ai/objectstack#5149). `onFault` carries the engine's reason across that silence // so the labelled report can still name it (objectui#3792); both probes fault // identically, so the first reason is the reason. let reason: string | undefined; @@ -325,7 +325,7 @@ export function evalRowPredicate( // The fault-aware `evalCel` costs two evaluations (to tell a fault // from a genuine `false`), so only pay it when a caller wants the labelled // fail-closed warning — the formatting hot path takes the single-eval fast - // route. Since #5149 the fast route is no longer silent either: the + // route. Since objectstack-ai/objectstack#5149 the fast route is no longer silent either: the // canonical helper itself warns once per broken predicate (with `opts.label` // as the locator when given). if (!opts.warnOnError) { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index a1aba3a58f..0a56ef2869 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -78,7 +78,7 @@ export * from './utils/drill-down.js'; export * from './utils/date-macros.js'; // Session-scoped filter placeholders ({current_user_id} / {current_org_id}) // plus `resolveFilterPlaceholders`, the single entry point every surface -// should call so no vocabulary is silently skipped (framework #3574). +// should call so no vocabulary is silently skipped (objectstack-ai/objectstack#3574). export * from './utils/filter-tokens.js'; export * from './utils/dashboard-filters.js'; export * from './utils/merge-filters.js'; diff --git a/packages/core/src/theme/ThemeEngine.ts b/packages/core/src/theme/ThemeEngine.ts index 7261ec0c67..074447d365 100644 --- a/packages/core/src/theme/ThemeEngine.ts +++ b/packages/core/src/theme/ThemeEngine.ts @@ -143,7 +143,7 @@ export function generateColorVars(colors: ColorPalette): Record // (`fontSize` / `fontWeight` / `lineHeight` / `letterSpacing`, plus // `fontFamily.heading` / `fontFamily.mono`) became TOMBSTONES: the schema now // rejects them by name and their prescription points at `theme.customVars`, the -// declared — and since #5021 the only — door for a custom property. A +// declared — and since objectstack-ai/objectstack#5021 the only — door for a custom property. A // `--z-modal` or a `--duration-fast` is authored there now, emitted verbatim as // `--: `. // diff --git a/packages/core/src/utils/dashboard-filters.ts b/packages/core/src/utils/dashboard-filters.ts index 2d3a0f24f2..f1e76f2a81 100644 --- a/packages/core/src/utils/dashboard-filters.ts +++ b/packages/core/src/utils/dashboard-filters.ts @@ -206,7 +206,7 @@ function presetBounds(preset: string): { from?: string; to?: string } | undefine * protect. * * What stays local is the BOUNDS table above, which is the other half of - * #4614's design ("the two vocabularies live one import apart and neither + * objectstack-ai/objectstack#4614's design ("the two vocabularies live one import apart and neither * restates the other's grammar"): the spec owns which presets exist, this * module owns what each one resolves to in date-macro tokens. */ diff --git a/packages/core/src/utils/dataset-format.ts b/packages/core/src/utils/dataset-format.ts index b758bf07ca..50bdf8bd21 100644 --- a/packages/core/src/utils/dataset-format.ts +++ b/packages/core/src/utils/dataset-format.ts @@ -526,7 +526,7 @@ export function buildDatasetFieldHelpers( } /** - * A half-open date-range drill scope for one time-bucketed dimension (#1752): + * A half-open date-range drill scope for one time-bucketed dimension (objectstack-ai/objectstack#1752): * the object FIELD to filter and its inclusive `gte` / exclusive `lt` bounds * (the server's `drillRanges` sidecar entry). */ @@ -586,7 +586,7 @@ export interface DatasetDrillRange { * URL-dialect operator on both the write and the read side, which is its own * card. * - * A time-bucketed date dimension (#1752) drills by RANGE, not equality — a + * A time-bucketed date dimension (objectstack-ai/objectstack#1752) drills by RANGE, not equality — a * humanized bucket ("2026-Q2") can't be exact-matched, so the server sends a * half-open `[gte, lt)` per date dim in `rawRanges` instead of a raw value. * Each becomes an ObjectQL range operator object (`{ $gte, $lt }`) so the drill @@ -657,7 +657,7 @@ export interface DatasetDrillRange { * $lt }` range is two conditions on its own, so even a single date bucket * re-spells. Sending the identity leg through the sink therefore re-shaped * every multi-condition dataset drill — including the controls objectui#9085, - * objectui#4056, objectstack#5473 and #1752 pin on paths this card does not + * objectui#4056, objectstack#5473 and objectstack-ai/objectstack#1752 pin on paths this card does not * touch — for ZERO change in the rows selected or the `filter[...]` params * emitted. ⛔ Do not "simplify" this to an unconditional call without redoing * that measurement. diff --git a/packages/core/src/utils/filter-converter.ts b/packages/core/src/utils/filter-converter.ts index 488d6b229d..5d04847cc4 100644 --- a/packages/core/src/utils/filter-converter.ts +++ b/packages/core/src/utils/filter-converter.ts @@ -209,7 +209,7 @@ const AST_LOGIC_KEYWORD: Record = { * would widen the result set, which is the one failure direction this file * exists to avoid. * - * `#5322` (maintainer ruling 2026-08-04, recorded on `FilterConditionSchema`) + * `objectstack-ai/objectstack#5322` (maintainer ruling 2026-08-04, recorded on `FilterConditionSchema`) * fixes the identities: `{ $and: [] }` is TRUE, `{ $or: [] }` is FALSE, and a * `{}` disjunct is TRUE and ABSORBS its `$or`. TRUE is expressible here — it is * the absence of a constraint. FALSE is not: the AST has no contradiction @@ -263,7 +263,7 @@ function lowerLogicalGroup( // and the refusal propagates out of the whole filter (objectui#9164). // Both spellings mean the same thing here, which is // why the test is `Array.isArray` and not a comparison against either - // spelling: that child is the TRUE identity (#5322), so it absorbs an + // spelling: that child is the TRUE identity (objectstack-ai/objectstack#5322), so it absorbs an // `$or` outright and drops out of an `$and`. It must not be pushed as a // child either way: an object in AST child position makes `isFilterAST` // false (measured), and the wire face answers `400 INVALID_FILTER` for @@ -274,7 +274,7 @@ function lowerLogicalGroup( children.push(lowered as FilterNode); } - // A TRUE disjunct absorbs its `$or` (#5322) — now that every member was read. + // A TRUE disjunct absorbs its `$or` (objectstack-ai/objectstack#5322) — now that every member was read. if (absorbed) return undefined; // Every conjunct reduced to TRUE, so the `$and` constrains nothing. @@ -288,7 +288,7 @@ function lowerLogicalGroup( } /** - * `{ $or: [] }` — FALSE, the OR identity (#5322) — as the leaf this file has + * `{ $or: [] }` — FALSE, the OR identity (objectstack-ai/objectstack#5322) — as the leaf this file has * always emitted for it. * * Deliberately unchanged, and deliberately not a group node. Three measurements @@ -302,7 +302,7 @@ function lowerLogicalGroup( * - `['or']` — the "obvious" empty group — is `isFilterAST` FALSE and * `parseFilterAST` `undefined`: no filter at all, i.e. EVERY row. That is * the widening direction, on a filter whose whole purpose is to hide rows - * (#5134), so it is the one shape that must not be emitted. + * (objectstack-ai/objectstack#5134), so it is the one shape that must not be emitted. * * A leaf naming `$or` as a field is not a shape to be proud of; it is the shape * that answers FALSE at both consumers, which the alternatives do not. @@ -393,7 +393,7 @@ function describeExoticComparand(value: object): string { * * > *an empty `$icontains` comparand is REFUSED* — "Every row contains the * > empty substring, so evaluating it is a predicate that constrains nothing — - * > the widening #5240 refused `{ field: {} }` over, one level in." + * > the widening [objectstack-ai/objectstack#5240] refused `{ field: {} }` over, one level in." * * > *a non-string `$icontains` comparand is REFUSED* — "Coercing 42 to `"42"` * > would answer a query nobody wrote; the declared comparand type is string." diff --git a/packages/core/src/utils/filter-tokens.ts b/packages/core/src/utils/filter-tokens.ts index ac7bdac708..5c3f2e5bc4 100644 --- a/packages/core/src/utils/filter-tokens.ts +++ b/packages/core/src/utils/filter-tokens.ts @@ -24,7 +24,7 @@ import { resolveDateMacros } from './date-macros.js'; * * { owner_id: '{current_user_id}' } * - * ## Why this module exists (framework #3574) + * ## Why this module exists (objectstack-ai/objectstack#3574) * * There used to be no shared resolver. Three ad-hoc implementations had grown * up independently — one in `ObjectView` for list views, one in @@ -231,7 +231,7 @@ export function resolveContextTokens(filter: T, scope: FilterTokenScope * macros and context tokens — in one call. * * This is the function surfaces should call. Calling only one of the two - * resolvers is the defect behind framework #3574: dashboard widgets called + * resolvers is the defect behind objectstack-ai/objectstack#3574: dashboard widgets called * `resolveDateMacros` alone, so `{today}` worked and `{current_user_id}` * silently did not. * diff --git a/packages/core/src/utils/sort-query.ts b/packages/core/src/utils/sort-query.ts index ea88c7b574..d63f42636f 100644 --- a/packages/core/src/utils/sort-query.ts +++ b/packages/core/src/utils/sort-query.ts @@ -31,7 +31,7 @@ * `record:line_items`) next to three sibling blocks that each inlined a * byte-identical private copy (`ObjectGantt` / `ObjectMap` / `ObjectCalendar`), * and a fifth and sixth copy is how the conversions start disagreeing. Those - * three copies were deliberately left alone by #7137 and collapsed onto this + * three copies were deliberately left alone by objectstack-ai/objectstack#7137 and collapsed onto this * function by objectui#4022; every block now imports it from here. * * Two deliberate differences from those retired private copies, both of which diff --git a/packages/core/src/validation/validators/object-validation-engine.ts b/packages/core/src/validation/validators/object-validation-engine.ts index 09a944f47f..31a1199259 100644 --- a/packages/core/src/validation/validators/object-validation-engine.ts +++ b/packages/core/src/validation/validators/object-validation-engine.ts @@ -608,7 +608,7 @@ export class ObjectValidationEngine { * - no `initialStates` declared → allow (legacy no-op) * - field absent from the write → allow (requiredness is not our job) * - value empty → allow (ditto) - * - value ∉ initialStates → reject (the FSM entry point, #3165) + * - value ∉ initialStates → reject (the FSM entry point, objectstack-ai/objectstack#3165) * * UPDATE * - field absent from the write → allow (no transition to police) diff --git a/packages/data-objectstack/src/index.ts b/packages/data-objectstack/src/index.ts index 17c52bc94b..2f15432600 100644 --- a/packages/data-objectstack/src/index.ts +++ b/packages/data-objectstack/src/index.ts @@ -819,7 +819,7 @@ export function clearSharedDiscoveryCache(): void { /** * Read the cross-object atomic-batch capability from a `discovery` document - * (framework #3298 / objectui #2693). The server advertises it hierarchically + * (objectstack-ai/objectstack#3298 / objectui #2693). The server advertises it hierarchically * under `capabilities.transactionalBatch.enabled`; the published * `@objectstack/client` also accepts the flat `capabilities.transactionalBatch: * boolean` form and normalizes the two — mirror that here so the adapter reads @@ -832,7 +832,7 @@ export function clearSharedDiscoveryCache(): void { * real error. * - `false` — the backend explicitly does NOT (route absent, or a runtime that * can't open a transaction). - * - `undefined` — the capability is absent, i.e. the backend predates #3298; + * - `undefined` — the capability is absent, i.e. the backend predates objectstack-ai/objectstack#3298; * the caller must keep the legacy runtime-probe fallback (we can't tell * whether `/batch` exists without trying it). */ @@ -1118,7 +1118,7 @@ export function isViewConfigPermissionDeniedError( /** * Thrown when the deployment has no analytics capability installed - * (framework#3891 / #4019). + * (framework#3891 / objectstack-ai/objectstack#4019). * * The framework retired its degraded in-kernel analytics fallback — it dropped * the caller's RLS/tenant scope and ignored the contract filter, so it answered @@ -2205,7 +2205,7 @@ const UNATTRIBUTED_STRIP_OBJECT = ''; /** * Emitted after a create/update whose response carried `droppedFields` - * (framework #3431/#3455). The write SUCCEEDED — this is a warning that some + * (objectstack-ai/objectstack#3431 / objectstack-ai/objectstack#3455). The write SUCCEEDED — this is a warning that some * supplied fields never landed, so the UI can tell the user rather than let it * pass silently. Subscribe via {@link ObjectStackAdapter.onWriteWarning}. * @@ -2880,7 +2880,7 @@ export const VIEW_OVERLAY_OWNED_KEYS = Object.freeze([ * still says what KIND of row it is. * * `label` is deliberately NOT here even though the platform stamps it onto - * these rows: `viewIdentityPatch` (`@objectstack/metadata-protocol`, #2555) + * these rows: `viewIdentityPatch` (`@objectstack/metadata-protocol`, objectstack-ai/objectstack#2555) * inherits `viewKind`/`object`/`label` from the registry entry an overlay * shadows, so a stored `label` is a snapshot of the source view's label at * write time — content, and exactly the class of frozen key this narrowing @@ -3109,10 +3109,10 @@ export class ObjectStackAdapter implements DataSource { // one adapter that has to cope with a backend lacking server atomicity (#2679). private batchUnsupported = false; // The server's declared cross-object atomic-batch capability, read from - // discovery at connect() (framework #3298 / objectui #2693). `true` → the + // discovery at connect() (objectstack-ai/objectstack#3298 / objectui #2693). `true` → the // backend GUARANTEES an atomic `/batch`, so batchTransaction trusts it and // never degrades to the non-atomic emulation (any failure surfaces as a real - // error). `false` or `undefined` (capability absent → backend predates #3298) + // error). `false` or `undefined` (capability absent → backend predates objectstack-ai/objectstack#3298) // → keep the legacy runtime-probe + emulation fallback so a save is still // possible; dropping it there would turn "saves, less safe" into "no save // path" on older backends (#2679 compatibility constraint). @@ -3124,7 +3124,7 @@ export class ObjectStackAdapter implements DataSource { private mutationListeners = new Set<(event: DataSourceMutationEvent) => void>(); // Subscribers registered via onWriteWarning(). Emitted after a create/update - // whose response carried `droppedFields` (framework #3431/#3455) so the app + // whose response carried `droppedFields` (objectstack-ai/objectstack#3431 / objectstack-ai/objectstack#3455) so the app // shell can surface a toast instead of the strip passing silently. private writeWarningListeners = new Set(); @@ -3229,7 +3229,7 @@ export class ObjectStackAdapter implements DataSource { // helpers continue to work without a redundant fetch. (this.client as unknown as { discoveryInfo?: unknown }).discoveryInfo = data; - // Record the declared cross-object atomic-batch capability (#3298) so + // Record the declared cross-object atomic-batch capability (objectstack-ai/objectstack#3298) so // batchTransaction can decide declaratively at call time whether it may // trust server atomicity instead of runtime-probing 404/405/501. this.atomicBatchCapability = readTransactionalBatchCapability(data); @@ -3434,7 +3434,7 @@ export class ObjectStackAdapter implements DataSource { * — a per-object metadata-driven search (ADR-0061) — this consults the search * index and ranks hits across objects, so it surfaces records the per-object * fanout misses. Global affordances (⌘K command palette, search page) prefer - * this path (framework #3371). + * this path (objectstack-ai/objectstack#3371). * * Returns `{ query, hits }`. A backend without the search plugin installed * answers `404`; we treat that as "no global search here" and return an empty @@ -3616,7 +3616,7 @@ export class ObjectStackAdapter implements DataSource { } /** - * Read `droppedFields` off a create/update response (framework #3431/#3455) + * Read `droppedFields` off a create/update response (objectstack-ai/objectstack#3431 / objectstack-ai/objectstack#3455) * and, when present, notify write-warning subscribers. Tolerant of a client * whose response type predates `droppedFields`: the field is read structurally * and validated, so an older client (or a backend that never drops) is a no-op. @@ -3647,7 +3647,7 @@ export class ObjectStackAdapter implements DataSource { } /** - * Same, for the cross-object transactional batch (framework #3794). Its + * Same, for the cross-object transactional batch (objectstack-ai/objectstack#3794). Its * response hangs the events off a top-level `droppedFields` list, each tagged * with the `index` of the operation it came from — `results` entries are bare * record echoes with nowhere to hang a per-row list. @@ -3731,7 +3731,7 @@ export class ObjectStackAdapter implements DataSource { /** * Subscribe to write-warning events (a create/update dropped caller-supplied - * fields — #3431/#3455). Returns an unsubscribe function. The app shell uses + * fields — objectstack-ai/objectstack#3431 / objectstack-ai/objectstack#3455). Returns an unsubscribe function. The app shell uses * this to toast the user; the write itself already succeeded. */ onWriteWarning(callback: WriteWarningListener): () => void { @@ -3746,7 +3746,7 @@ export class ObjectStackAdapter implements DataSource { * advisory findings on a save that SUCCEEDED (#4237; backend * objectstack#7435). Returns an unsubscribe function. * - * Deliberately the same seam as {@link onWriteWarning} (#3431/#3455), which + * Deliberately the same seam as {@link onWriteWarning} (objectstack-ai/objectstack#3431 / objectstack-ai/objectstack#3455), which * is what {@link MetadataSaveAdvisoryEvent}'s own declaration already said it * was modelled on. It is a SIBLING of that channel rather than a second * payload pushed down it: `WriteWarningEvent` is a closed shape whose @@ -4121,25 +4121,25 @@ export class ObjectStackAdapter implements DataSource { * @returns Promise resolving to array of results */ /** - * Cross-object transactional batch (ObjectStack #1604 / ADR-0034 item 4). + * Cross-object transactional batch (objectstack-ai/objectstack#1604 / ADR-0034 item 4). * Runs the operations in ONE server transaction — commit all or roll back * all. A field value of `{ $ref: }` resolves to that op's * created id, so a child can reference its parent created earlier in the same * batch (master-detail). * * Transport: the published `@objectstack/client` SDK method - * `data.batchTransaction` (framework #3271; shipped since client v16, our + * `data.batchTransaction` (objectstack-ai/objectstack#3271; shipped since client v16, our * dependency floor). Per AGENTS.md §7 data always flows through the client — * never a hand-rolled `fetch('/api/v1/batch')`. * - * Fallback decision — declarative capability negotiation (framework #3298 / + * Fallback decision — declarative capability negotiation (objectstack-ai/objectstack#3298 / * objectui #2693). At connect() we read `capabilities.transactionalBatch` * from discovery: * - Declared `true` → the backend GUARANTEES atomicity (declared === * enforced). We TRUST it: any batch failure — including 404/405/501 — * surfaces as a real error. No non-atomic client-side compensation. This * is the path modern backends take. - * - Declared `false`, or ABSENT (backend predates #3298) → we can't rely on + * - Declared `false`, or ABSENT (backend predates objectstack-ai/objectstack#3298) → we can't rely on * server atomicity, so we keep the legacy behaviour: on 404/405 (no * endpoint) or 501 (runtime without transactions) degrade to the * client-side, NON-atomic {@link emulateBatchTransaction} so a save is @@ -4150,13 +4150,13 @@ export class ObjectStackAdapter implements DataSource { async batchTransaction( operations: BatchTransactionOperation[], ): Promise<{ results: any[] }> { - // Ensure discovery (and thus the #3298 capability) is loaded so the + // Ensure discovery (and thus the objectstack-ai/objectstack#3298 capability) is loaded so the // decision below is declarative, not "fire a batch and read the status". await this.connect(); // When the backend declares atomic batch support we never degrade: a // failure is a real error, not a cue to fall back. Otherwise (declared - // false, or capability absent on a pre-#3298 backend) the emulation + // false, or capability absent on a pre-objectstack-ai/objectstack#3298 backend) the emulation // fallback below stays active. const guaranteed = this.atomicBatchCapability === true; @@ -4168,7 +4168,7 @@ export class ObjectStackAdapter implements DataSource { try { // Typed SDK method — guaranteed present by the `@objectstack/client@^16` - // dependency floor (framework #3271). No hand-rolled POST /api/v1/batch. + // dependency floor (objectstack-ai/objectstack#3271). No hand-rolled POST /api/v1/batch. const payload = await this.client.data.batchTransaction(operations); this.emitBatchMutations(operations, payload?.results); this.notifyBatchDroppedFields(operations, payload); @@ -4612,7 +4612,7 @@ export class ObjectStackAdapter implements DataSource { const records = resultObj.records || resultObj.value || []; const total = resultObj.total ?? resultObj.count ?? records.length; // Prefer the server's `hasMore` (real server-side pagination, framework - // issue #2212). Fall back to the page-local estimate (a full page implies + // issue objectstack-ai/objectstack#2212). Fall back to the page-local estimate (a full page implies // there may be more) only when the server doesn't report it. const hasMore = typeof resultObj.hasMore === 'boolean' ? resultObj.hasMore @@ -4888,7 +4888,7 @@ export class ObjectStackAdapter implements DataSource { // Use cache with automatic fetching. The cache is keyed by object name // only (locale-independent); a language switch wipes it wholesale via // `clearCache()` so the next read re-fetches in the new locale — see the - // shell's locale remount (issue #1319). Keeping the key locale-free here + // shell's locale remount (issue objectstack-ai/objectstack#1319). Keeping the key locale-free here // means a metadata *write* still invalidates the single entry it knows // about, without having to fan out across every cached locale. // Read through a cache-revalidating fetch (see fetchObjectSchemaFresh): @@ -5552,7 +5552,7 @@ export class ObjectStackAdapter implements DataSource { /** * List registered import `mapping` artifacts targeting a given object - * (framework #2611). Reads the `mapping` metadata kind via the overlay API + * (objectstack-ai/objectstack#2611). Reads the `mapping` metadata kind via the overlay API * and filters by `targetObject` client-side (the metadata index is * name-only). Feeds the import wizard's "saved mapping" selector. * @@ -5911,7 +5911,7 @@ export class ObjectStackAdapter implements DataSource { * * The maintainer ruling (2026-08-12) put the answer on the BY-NAME route * rather than in the list, so the enumeration surface is not widened past what - * a by-name probe already implies (objectstack#8013 / PR #8135): an app that + * a by-name probe already implies (objectstack#8013 / PR objectstack-ai/objectstack#8135): an app that * exists and whose `requiredPermissions` the session lacks answers `403` with * `PERMISSION_DENIED` in the declared envelope, and absence — a nonexistent * name, an unpublished app, an app gated by an absent optional service — is diff --git a/packages/data-objectstack/src/metadata-client.ts b/packages/data-objectstack/src/metadata-client.ts index 76b67ad9cc..05548066d5 100644 --- a/packages/data-objectstack/src/metadata-client.ts +++ b/packages/data-objectstack/src/metadata-client.ts @@ -69,17 +69,17 @@ export type { RuntimeAuthoringIssue }; * returned 200 — so this is advisory, never a failure. * * Deliberately the same shape of seam as `ObjectStackAdapter.onWriteWarning` - * (#3431/#3455): a successful write whose response carries something the author + * (objectstack-ai/objectstack#3431 / objectstack-ai/objectstack#3455): a successful write whose response carries something the author * needs to be told, surfaced to the shell as an event so the data layer never * imports a toaster. The difference is only which door produced it — that one * is record CRUD, these are the metadata write doors. * * ## Both write doors report (#5026) * - * The #4463 runtime authoring gate runs on BOTH metadata write doors by its D1 + * The objectstack-ai/objectstack#4463 runtime authoring gate runs on BOTH metadata write doors by its D1 * ruling — a draft→active promotion is gated exactly as a direct active save — * and its non-blocking findings ride the 2xx of whichever door earned them. - * `SaveMetaItemResponseSchema` has carried the key since #4717 and + * `SaveMetaItemResponseSchema` has carried the key since objectstack-ai/objectstack#4717 and * `PublishMetaItemResponseSchema` since objectstack#9176; both declare it at * the response's TOP level, under the same name and with the same * `RuntimeAuthoringIssueSchema` element type, which is what lets one reader and @@ -1486,7 +1486,7 @@ export class MetadataClient { ): Promise { // objectstack `9e04c3e35` (`@objectstack/rest` 17.2.0) — this door accepts // `?package=` and forwards it as the promotion's package binding, so - // #9612's package-closure narrowing at the runtime publish gate is + // objectstack-ai/objectstack#9612's package-closure narrowing at the runtime publish gate is // reachable from an HTTP-driven promotion at all. Deliberately the SAME // wire spelling and the same conditional as `save()` a few hundred lines // up: ONE value, ONE spelling, both steps of the save->publish loop. diff --git a/packages/data-objectstack/src/userState.ts b/packages/data-objectstack/src/userState.ts index 6ec15fe388..a5697c52c6 100644 --- a/packages/data-objectstack/src/userState.ts +++ b/packages/data-objectstack/src/userState.ts @@ -167,11 +167,11 @@ export function createObjectStackUserStateAdapter( // failed insert. // // Deliberately does NOT stamp `updated_at`: the column is server-managed, and - // a non-system caller's write to it is stripped (framework #2948) and reported + // a non-system caller's write to it is stripped (objectstack-ai/objectstack#2948) and reported // back as a dropped field — which the console surfaces as a "Some fields were - // not saved" toast (#3431). Sending it made every recents/favorites write pop + // not saved" toast (objectstack-ai/objectstack#3431). Sending it made every recents/favorites write pop // a scary warning about a field the user never touched, drowning the real - // signal the toast exists for (#3794). The server stamps it either way. + // signal the toast exists for (objectstack-ai/objectstack#3794). The server stamps it either way. const upsert = async (items: T[]): Promise => { // Fast path: we already know the row id from a previous load/save. if (cachedRowId !== null) { diff --git a/packages/fields/src/index.tsx b/packages/fields/src/index.tsx index 8d81f60c89..2f52d7c60d 100644 --- a/packages/fields/src/index.tsx +++ b/packages/fields/src/index.tsx @@ -263,7 +263,7 @@ function useLookupName( typeof dataSource.find === 'function' && (typeof value === 'string' || typeof value === 'number') && value !== ''; - // The preferred display field is part of the cache identity (#2926 ⑧). The + // The preferred display field is part of the cache identity (objectstack-ai/objectstack#2926 ⑧). The // entry now holds the record, not a name, so two columns with different // `displayField`s could share one; the key is left as it was so that this // change does not alter how many reads a screen makes. @@ -2485,7 +2485,7 @@ export function LookupCellRenderer({ value, field }: CellRendererProps): React.R // Explicit author-chosen display field on the lookup — beats every resolver. // ObjectGrid forwards `displayField` on the column meta (RELATIONAL_META_KEYS) - // the same way it forwards `reference` (#2926 ⑧). + // the same way it forwards `reference` (objectstack-ai/objectstack#2926 ⑧). const displayField = (field as { displayField?: string }).displayField || (field as { reference_field?: string }).reference_field || diff --git a/packages/fields/src/widgets/FilterConditionField.tsx b/packages/fields/src/widgets/FilterConditionField.tsx index fa87fd2451..d81fa3370e 100644 --- a/packages/fields/src/widgets/FilterConditionField.tsx +++ b/packages/fields/src/widgets/FilterConditionField.tsx @@ -531,7 +531,7 @@ function mongoToFilterGroup(mongo: any): BuilderGroup | null { * Would this criteria select EVERY record of the object? * * Mirrors the server's `isMatchAllCriteria` (objectstack `plugin-sharing`, - * #3896) closely enough to warn before the round-trip: blank, `{}`, `[]`, and + * objectstack-ai/objectstack#3896) closely enough to warn before the round-trip: blank, `{}`, `[]`, and * the vacuous combinators. Deliberately conservative in the same direction — * the cost of a false positive is one extra hint, the cost of a false negative * is a save that fails with a toast. The server stays authoritative. diff --git a/packages/fields/src/widgets/LookupField.tsx b/packages/fields/src/widgets/LookupField.tsx index e062a97595..6c6da89ea1 100644 --- a/packages/fields/src/widgets/LookupField.tsx +++ b/packages/fields/src/widgets/LookupField.tsx @@ -775,7 +775,7 @@ export function LookupField({ value, onChange, field, readonly, error: fieldErro // Single id: the pre-existing cheap paths — a primary-id `findOne` // GET, or an equality filter when the field commits a different // column (`idField: 'name'` — e.g. position machine names, - // objectstack #3508). + // objectstack-ai/objectstack#3508). if (unresolved.length === 1) { const id = unresolved[0]; if (typeof (dataSource as any).findOne === 'function' && idField === 'id') { diff --git a/packages/fields/src/widgets/RecordPickerDialog.tsx b/packages/fields/src/widgets/RecordPickerDialog.tsx index 6ce5768b4a..c40ea61f1e 100644 --- a/packages/fields/src/widgets/RecordPickerDialog.tsx +++ b/packages/fields/src/widgets/RecordPickerDialog.tsx @@ -361,7 +361,7 @@ export interface RecordPickerDialogProps { * (`before`, `after`, `is_empty`, `is_not_empty`) the record form has no * `$op` for. No second operator vocabulary is introduced here: two already * exist (the spec's `AST_OPERATOR_MAP`, data-objectstack's - * `FILTER_OPERATOR_ALIASES`) and #3948 is what a third costs. + * `FILTER_OPERATOR_ALIASES`) and objectstack-ai/objectstack#3948 is what a third costs. * * The discriminator is exact rather than heuristic — every AST node is an * ARRAY and a rule is a plain OBJECT, the same predicate `toFilterNode` uses. diff --git a/packages/i18n/src/locales/en.ts b/packages/i18n/src/locales/en.ts index 66e3947118..15724f46f6 100644 --- a/packages/i18n/src/locales/en.ts +++ b/packages/i18n/src/locales/en.ts @@ -3304,7 +3304,7 @@ const en = { viewApprovals: 'View approvals', noPendingApprovals: 'No pending approvals', openApprovalsInbox: 'Open Approvals Inbox', - // Bell-badge breakdown (#7233): the badge sums unread notification topics + // Bell-badge breakdown (objectstack-ai/objectstack#7233): the badge sums unread notification topics // and pending approvals, then clamps at "9+". These three spell the sum // out inside the popover so the number is explainable. badgeTotal: '{{total}} total', diff --git a/packages/i18n/src/provider.tsx b/packages/i18n/src/provider.tsx index 50e8b764f9..760bf93a15 100644 --- a/packages/i18n/src/provider.tsx +++ b/packages/i18n/src/provider.tsx @@ -301,7 +301,7 @@ function resolveSeedLanguage(seed: string, config?: I18nConfig): string | null { * Applied at instance creation rather than through a post-mount * `changeLanguage`, because the very first render must already be in the right * locale: `` seeds the `Accept-Language` header on every API call - * (`createAuthenticatedFetch`, issue #1319), so a late switch would fetch the + * (`createAuthenticatedFetch`, issue objectstack-ai/objectstack#1319), so a late switch would fetch the * first wave of server-resolved metadata labels in the wrong language and then * have to remount to fix it. * diff --git a/packages/layout/src/PageHeader.tsx b/packages/layout/src/PageHeader.tsx index 1e7f086b8f..d3147e3de1 100644 --- a/packages/layout/src/PageHeader.tsx +++ b/packages/layout/src/PageHeader.tsx @@ -36,7 +36,7 @@ export interface PageHeaderComponentProps extends React.HTMLAttributes = ({ // When the local navigation mode is an overlay (drawer/modal), ignore the // inherited onRowClick so the local overlay wins over parent page-nav. // No width is spelled here on purpose (objectui#6303, converging the calendar - // on the shape #6305 gave ObjectGantt). `width` is `@deprecated [#2578 -> + // on the shape #6305 gave ObjectGantt). `width` is `@deprecated [objectstack-ai/objectstack#2578 -> // size]` in the spec that owns this shape, and `resolveOverlayWidth` gives an // explicit `width` priority OVER `size` — so spelling it kept the deprecated // branch load-bearing on the path most calendars take (no declared @@ -1139,7 +1139,7 @@ export const ObjectCalendar: React.FC = ({ // producer-side marking: a field set at throw time to say "this text is // for the end user". It is a SEPARATE field from `message`, so nothing // unmarked can reach here — the substitution below still governs every - // platform diagnostic and #3821 holds by construction rather than by us + // platform diagnostic and objectstack-ai/objectstack#3821 holds by construction rather than by us // guessing what a body contains. Status-agnostic on purpose: 403 is // where this was reported (objectui#5210/#5902), not a fence the // contract draws — a marked 409 or 400 renders identically. diff --git a/packages/plugin-charts/src/ObjectChart.tsx b/packages/plugin-charts/src/ObjectChart.tsx index 91c08298d3..4610507d4d 100644 --- a/packages/plugin-charts/src/ObjectChart.tsx +++ b/packages/plugin-charts/src/ObjectChart.tsx @@ -575,7 +575,7 @@ export const ObjectChart = (props: ObjectChartProps) => { () => (schema.compareTo ? JSON.stringify(schema.compareTo) : ''), [schema.compareTo], ); - // ADR-0021 (#1890): a chart can bind to a semantic-layer `dataset` instead of + // ADR-0021 (objectstack-ai/objectstack#1890): a chart can bind to a semantic-layer `dataset` instead of // the legacy inline `objectName` + `aggregate` query. Stable key over the // dataset selection so a fresh object literal each render doesn't refetch-loop. const datasetKey = useMemo( @@ -777,7 +777,7 @@ export const ObjectChart = (props: ObjectChartProps) => { setError(null); } try { - // ── Dataset-bound path (ADR-0021, #1890) ────────────── + // ── Dataset-bound path (ADR-0021, objectstack-ai/objectstack#1890) ────────────── // When the chart binds to a semantic-layer `dataset`, run the same // governed `queryDataset` path the dashboard DatasetWidget and // dataset-bound reports use, so the numbers match everywhere. The diff --git a/packages/plugin-dashboard/src/DatasetWidget.tsx b/packages/plugin-dashboard/src/DatasetWidget.tsx index 43e1177f09..083152f15a 100644 --- a/packages/plugin-dashboard/src/DatasetWidget.tsx +++ b/packages/plugin-dashboard/src/DatasetWidget.tsx @@ -513,7 +513,7 @@ export function DatasetWidget({ widget, dataSource, subCaption }: { widget: any; // ONE extra statement, `SELECT SUM(…), AVG(…) FROM t` — the same WHERE, no // GROUP BY — at 9.6ms beside the primary's 48.8ms, i.e. +20% on the widget's // query, holding at +19%/1M rows and +28%/10k. The cross-tab has shipped - // THREE such groupings, ungated, since #1753; one is strictly less. + // THREE such groupings, ungated, since objectstack-ai/objectstack#1753; one is strictly less. // // NOT requested when `options.limit` truncates the table. The executor drops // `limit` for a totals query by design (a total covers the whole selection), @@ -555,7 +555,7 @@ export function DatasetWidget({ widget, dataSource, subCaption }: { widget: any; // // Resolve BOTH vocabularies. This used to call `resolveDateMacros` alone, so // a user-scoped widget sent `{current_user_id}` to SQL as a literal, matched - // no row, and rendered 0 with no error anywhere (framework #3574). + // no row, and rendered 0 with no error anywhere (objectstack-ai/objectstack#3574). const filterScope = useFilterScope(); // The object-schema probe's host-authenticated fetch (objectui#4121) is no // longer read here: it moved INTO `useDatasetDimensionMeta` along with the @@ -947,7 +947,7 @@ export function DatasetWidget({ widget, dataSource, subCaption }: { widget: any; // charts map a clicked segment back to its dataset row (see handleChartDrill). const { object: drillObject, dimensionFields, drillRawRows, drillRanges } = state; const drillDims = dimensionFields ? dimensions.filter((d) => d in dimensionFields) : []; - // #1752: a date-only widget has no equality drill dim but still drills by the + // objectstack-ai/objectstack#1752: a date-only widget has no equality drill dim but still drills by the // server's per-row date RANGE, so the presence of ranges makes it drillable too. const canDrill = !!drillObject && (drillDims.length > 0 || !!drillRanges?.length); const openDrill = (index: number, title: string) => { diff --git a/packages/plugin-dashboard/src/ObjectMetricWidget.tsx b/packages/plugin-dashboard/src/ObjectMetricWidget.tsx index eda3be85f7..4b4bad0863 100644 --- a/packages/plugin-dashboard/src/ObjectMetricWidget.tsx +++ b/packages/plugin-dashboard/src/ObjectMetricWidget.tsx @@ -318,7 +318,7 @@ export const ObjectMetricWidget: React.FC = ({ // "{current_quarter_start}") AND session tokens ("{current_user_id}") — so // the server sees real values and the drill-down `find()` later sees the // exact same filter as the aggregate query. Resolving only date macros here - // left user-scoped metrics silently rendering 0 (framework #3574). + // left user-scoped metrics silently rendering 0 (objectstack-ai/objectstack#3574). const filterScope = useFilterScope(); const resolvedFilter = useMemo( () => resolveFilterPlaceholders(filter, filterScope), diff --git a/packages/plugin-dashboard/src/index.tsx b/packages/plugin-dashboard/src/index.tsx index 06e5b1cf7c..0dba5dc648 100644 --- a/packages/plugin-dashboard/src/index.tsx +++ b/packages/plugin-dashboard/src/index.tsx @@ -70,7 +70,7 @@ export { // `__tests__/dashboardAuthoredInputs.test.tsx`: // - `title` — legacy spelling of `label`; the spec rejects it by name. // The `schema.title || schema.label` read STAYS (documents in the wild). -// - `aria` — spec tombstone (#3896 audit close-out): no dashboard +// - `aria` — spec tombstone (objectstack-ai/objectstack#3896 audit close-out): no dashboard // renderer ever applied it, and this package has no read site either. // // `name` is honoured too (the `schema.name` read keys the diff --git a/packages/plugin-dashboard/src/utils.ts b/packages/plugin-dashboard/src/utils.ts index d3552a78d5..831fa3a709 100644 --- a/packages/plugin-dashboard/src/utils.ts +++ b/packages/plugin-dashboard/src/utils.ts @@ -126,7 +126,7 @@ export function deriveStaticTableColumns(rows: unknown): Array<{ header: string; // vocabularies (date macros AND `{current_user_id}` / `{current_org_id}`). // Calling `resolveDateMacros` alone is exactly what left every dashboard // widget unable to resolve user-scoped filters — they silently rendered 0 -// (framework #3574). +// (objectstack-ai/objectstack#3574). export { resolveDateMacros, resolveFilterPlaceholders } from '@object-ui/core'; // Re-export compareTo helpers from core for convenience. diff --git a/packages/plugin-detail/src/RelatedList.tsx b/packages/plugin-detail/src/RelatedList.tsx index c66e8af70d..8b6ef5421e 100644 --- a/packages/plugin-detail/src/RelatedList.tsx +++ b/packages/plugin-detail/src/RelatedList.tsx @@ -1104,7 +1104,7 @@ export const RelatedList: React.FC = ({ // all (objectui#7299). // // Measured, not assumed. The repo's one operator contract for this - // spelling is `drillUrlFilters`' `URL_FILTER_OPS` (#1752) — `gte`, + // spelling is `drillUrlFilters`' `URL_FILTER_OPS` (objectstack-ai/objectstack#1752) — `gte`, // `lte`, `gt`, `lt` and nothing else — and its parser DROPS an // unrecognised suffix rather than downgrading it, so a hopeful // `filter[][contains]=` would arrive as no condition whatsoever: diff --git a/packages/plugin-detail/src/index.tsx b/packages/plugin-detail/src/index.tsx index 1d1dd6fd7f..afa85eba06 100644 --- a/packages/plugin-detail/src/index.tsx +++ b/packages/plugin-detail/src/index.tsx @@ -503,7 +503,7 @@ ComponentRegistry.register('details', RecordDetailsRenderer, { // validate, not one the contract quietly throws away — the same trap as // declaring a top-level `readonly` on `record:highlights` below. The // renderer tolerating it is not a licence to teach it. (This said "STRIPS" - // until objectui#7127: that was the pre-#4001-batch-A behaviour the spec's + // until objectui#7127: that was the pre-objectstack-ai/objectstack#4001-batch-A behaviour the spec's // own refusal message still recounts, and the `layout` paragraph above // already said `rejects`.) // @@ -658,7 +658,7 @@ ComponentRegistry.register('highlights', RecordHighlightsRenderer, { // trusted that surface would be left with the machine-owned column still // hand-editable and their page refused by the contract wherever it is // parsed. (This said "strips the unknown key on parse without error" until - // objectui#7127: the pre-#4001-batch-A behaviour, the same stale claim the + // objectui#7127: the pre-objectstack-ai/objectstack#4001-batch-A behaviour, the same stale claim the // `record:details` block above carried.) `ComponentInput.of` carries a member // KIND and nothing finer (objectui#8067), so an array input publishes its // member KEYS in prose, the same way `record:path.stages` and diff --git a/packages/plugin-detail/src/renderers/record-related-list.tsx b/packages/plugin-detail/src/renderers/record-related-list.tsx index b97d2f7c26..b3e73d1e1b 100644 --- a/packages/plugin-detail/src/renderers/record-related-list.tsx +++ b/packages/plugin-detail/src/renderers/record-related-list.tsx @@ -71,7 +71,7 @@ export interface RecordRelatedListRendererProps { * sides — one describes what an author writes, the other what the block reads. * * Spelling it `RecordRelatedListComponentProps` flat said the opposite, and - * said it about the wrapper: the exact authoring shape #6953 added did not + * said it about the wrapper: the exact authoring shape objectstack-ai/objectstack#6953 added did not * type-check against the component that exists to accept it. The body already * reads the key defensively (`objectName && …`, `objectName || ''`) precisely * because it can arrive unbound; this declaration now agrees with that code. diff --git a/packages/plugin-detail/src/synth/buildDefaultPageSchema.ts b/packages/plugin-detail/src/synth/buildDefaultPageSchema.ts index d4e515f229..bf2c0b1215 100644 --- a/packages/plugin-detail/src/synth/buildDefaultPageSchema.ts +++ b/packages/plugin-detail/src/synth/buildDefaultPageSchema.ts @@ -98,7 +98,7 @@ export interface ObjectDefLike { fieldGroups?: Array[number]>>; /** * Spec `enable` capability toggles. Only `files` is read here: - * `enable.files === true` (opt-in, #2727) makes the synthesizer emit an + * `enable.files === true` (opt-in, objectstack-ai/objectstack#2727) makes the synthesizer emit an * Attachments tab beside Details/Related (objectstack#4358). */ enable?: { files?: boolean; [key: string]: any }; @@ -221,7 +221,7 @@ export interface BuildPageOptions { * * The host supplies it; this synthesizer neither derives nor merges it. * `RecordDetailView` fills it from the FK field's `relatedListFilter` - * (objectui#4664 — the spec key from objectstack#8704 / PR #8955), already + * (objectui#4664 — the spec key from objectstack#8704 / PR objectstack-ai/objectstack#8955), already * in the canonical Query-DSL `FilterCondition` shape that key declares. The * component-level authored `filter` and this derived one are therefore the * same vocabulary arriving at the same prop, which is the point: one read @@ -888,7 +888,7 @@ export function buildDefaultDiscussion(): any { } /** - * Sub-builder: the `record:attachments` panel (#2727). Emitted only when the + * Sub-builder: the `record:attachments` panel (objectstack-ai/objectstack#2727). Emitted only when the * object opts in via `enable.files: true` — the same gate the server enforces * on `sys_attachment` rows (403 FILES_DISABLED otherwise). */ diff --git a/packages/plugin-form/src/ModalForm.tsx b/packages/plugin-form/src/ModalForm.tsx index 1dd7131a2e..560af4c968 100644 --- a/packages/plugin-form/src/ModalForm.tsx +++ b/packages/plugin-form/src/ModalForm.tsx @@ -135,7 +135,7 @@ export interface ModalFormSchema { title?: string; description?: string; sections?: ModalFormSectionConfig[]; - /** Internal content layout (ADR-0050, #1890): 'tabbed' renders sections as + /** Internal content layout (ADR-0050, objectstack-ai/objectstack#1890): 'tabbed' renders sections as * tabs inside the modal, so "modal + tabbed" composes. Default stacks them. */ contentLayout?: 'simple' | 'tabbed'; fields?: string[]; @@ -770,7 +770,7 @@ export const ModalForm: React.FC = ({ // The form is ONE grid. Its width is the explicit form `columns`, else the // widest section; each section then lays ITS fields out at its own - // declared density within that grid via colSpan (#2578), exactly like the + // declared density within that grid via colSpan (objectstack-ai/objectstack#2578), exactly like the // full-page sectioned form. const clampCol = (n: unknown): number | undefined => typeof n === 'number' && n > 0 ? Math.min(Math.floor(n), 4) : undefined; @@ -822,7 +822,7 @@ export const ModalForm: React.FC = ({ ...(containerFieldClass ? { fieldContainerClass: containerFieldClass } : {}), }; - // ADR-0050 (#1890): a modal can host a tabbed layout — sections render as + // ADR-0050 (objectstack-ai/objectstack#1890): a modal can host a tabbed layout — sections render as // tabs (label on the trigger) instead of a vertical stack, so a modal // create/edit form composes with `tabbed`. The renderer owns the tab strip // and panels (`fieldTabs`) so all tabs stay mounted inside the one form. @@ -1003,7 +1003,7 @@ export const ModalForm: React.FC = ({ fields: schema.fields as any, sections: schema.sections as any, // Forward create-mode prefills (e.g. a subtable child's parent - // pre-link, #2604) — MasterDetailForm consumes them the same + // pre-link, objectstack-ai/objectstack#2604) — MasterDetailForm consumes them the same // way the flat form path does. initialValues: schema.initialValues, initialData: schema.initialData, diff --git a/packages/plugin-form/src/ObjectForm.tsx b/packages/plugin-form/src/ObjectForm.tsx index 1ed1739cc0..f2d45a4459 100644 --- a/packages/plugin-form/src/ObjectForm.tsx +++ b/packages/plugin-form/src/ObjectForm.tsx @@ -111,7 +111,7 @@ export interface ObjectFormComponentProps { /** * Fold the structured, spec-aligned `buttons`/`defaults` surface - * (`@objectstack/spec` FormViewSchema; framework#1894 / #2998) down onto the + * (`@objectstack/spec` FormViewSchema; framework#1894 / objectstack-ai/objectstack#2998) down onto the * flat renderer props ObjectForm and its variants read * (`showSubmit`/`submitText`/`showCancel`/`cancelText`/`showReset`/ * `initialValues`). This is the objectui-side consumer of those spec keys — it @@ -202,7 +202,7 @@ export const ObjectForm: React.FC = ({ // (Tabbed/Wizard/Split/Drawer/Modal/Simple) transparently honour FLS. // Fail-open when no provider mounted (perms.isLoaded false). const schema = useMemo(() => { - // framework#1894 / #2998 (ADR-0078): the authored @objectstack/spec + // framework#1894 / objectstack-ai/objectstack#2998 (ADR-0078): the authored @objectstack/spec // FormViewSchema carries the structured `buttons.{submit,cancel,reset}. // {show,label}` + `defaults` surface, but this renderer historically read // only the flat `showSubmit`/`submitText`/…/`initialValues`. Fold the @@ -1499,7 +1499,7 @@ const SimpleObjectForm: React.FC = ({ // Derived (fieldGroup) sections were computed from the filtered field list; // explicit sections keep the authored field selection as-is. const sourceFields = fieldGroupSections ? groupableFields : formFields; - // #2578: honour per-section `columns`. The form renders as ONE grid (one + // objectstack-ai/objectstack#2578: honour per-section `columns`. The form renders as ONE grid (one // react-hook-form instance); each section lays its OWN fields out at its // declared density within that grid. Grid width = explicit form `columns`, // else the widest section, else inferred from field count (the @@ -1633,7 +1633,7 @@ const SimpleObjectForm: React.FC = ({ }), ); - // #2578: lay THIS section's fields out at its declared column density + // objectstack-ai/objectstack#2578: lay THIS section's fields out at its declared column density // within the shared form grid (span-aware; wide fields still full-row). const secCols = clampCol((section as any).columns); const laid = formColumns > 1 ? applyAutoColSpan(sectionFields, formColumns, secCols) : sectionFields; diff --git a/packages/plugin-form/src/SplitForm.tsx b/packages/plugin-form/src/SplitForm.tsx index 53276ef764..20eca0b61f 100644 --- a/packages/plugin-form/src/SplitForm.tsx +++ b/packages/plugin-form/src/SplitForm.tsx @@ -471,7 +471,7 @@ export const SplitForm: React.FC = ({ } // The form is ONE grid; each section then lays ITS fields out at its own - // declared density within that grid via colSpan (#2578) — the same arrangement + // declared density within that grid via colSpan (objectstack-ai/objectstack#2578) — the same arrangement // the stacked/tabbed sectioned forms use. The grid lives on the FIELD // container inside the form, never wrapped around the form (that leaves the // extra columns permanently empty, #2128). diff --git a/packages/plugin-form/src/autoLayout.ts b/packages/plugin-form/src/autoLayout.ts index 7e99a05668..f97afabe20 100644 --- a/packages/plugin-form/src/autoLayout.ts +++ b/packages/plugin-form/src/autoLayout.ts @@ -101,7 +101,7 @@ export function isAutoGeneratedFieldType(type: string): boolean { } /** - * Infer the MAX column count from the field count (#2578). This is an UPPER + * Infer the MAX column count from the field count (objectstack-ai/objectstack#2578). This is an UPPER * BOUND — the actual column count at render time is decided by the CSS * container queries in {@link CONTAINER_GRID_COLS} against the form's REAL * width, so a narrow drawer stays 1–2 columns while the SAME form on a wide @@ -129,7 +129,7 @@ function clampGrid(n: number | undefined): number { /** * Resolve the effective colSpan (grid cells) a field occupies, given the form's - * grid width and the section's desired column count (#2578). + * grid width and the section's desired column count (objectstack-ai/objectstack#2578). * * The column count is derived per surface (mobile 1 / modal 2 / page 3-4), so * the robust field-width primitive is the relative `span`, NOT an absolute @@ -178,7 +178,7 @@ export function resolveColSpan( /** * Apply the resolved colSpan to each field so the form's CSS grid lays them out - * at the intended density. Span-aware and clamping (#2578); wide fields still + * at the intended density. Span-aware and clamping (objectstack-ai/objectstack#2578); wide fields still * span the full row (the `span: 'auto'` default). `section-divider` rows are * left untouched (they carry their own full-row span). * diff --git a/packages/plugin-form/src/schemaDefaults.ts b/packages/plugin-form/src/schemaDefaults.ts index 602f5ae460..99ac7e85c1 100644 --- a/packages/plugin-form/src/schemaDefaults.ts +++ b/packages/plugin-form/src/schemaDefaults.ts @@ -252,7 +252,7 @@ export function schemaDefaultValues( * Is this field one the `current_user` token may legally default — and does it * declare that token? * - * The type gate mirrors the spec's own authoring rule (`field.zod` #7127: + * The type gate mirrors the spec's own authoring rule (`field.zod` objectstack-ai/objectstack#7127: * `current_user` is legal "on `user` or `lookup` with `reference: 'sys_user'` * only"), so a token that somehow reached an illegal field type is left alone * here exactly as the engine's validator would refuse it. `reference` is the diff --git a/packages/plugin-gantt/src/ObjectGantt.tsx b/packages/plugin-gantt/src/ObjectGantt.tsx index a29fd783b2..af40a353b9 100644 --- a/packages/plugin-gantt/src/ObjectGantt.tsx +++ b/packages/plugin-gantt/src/ObjectGantt.tsx @@ -1835,7 +1835,7 @@ export const ObjectGantt: React.FC = ({ // detail panel inline (no full-page navigation). Schema can override by // providing its own `navigation` config (e.g., page mode). // - // No width is spelled here on purpose. `width` is `@deprecated [#2578 -> + // No width is spelled here on purpose. `width` is `@deprecated [objectstack-ai/objectstack#2578 -> // size]` in the spec that owns this shape, and `resolveOverlayWidth` gives // an explicit `width` priority OVER `size` — so spelling it kept the // deprecated branch load-bearing on the path most gantts take (no declared diff --git a/packages/plugin-grid/src/ImportWizard.tsx b/packages/plugin-grid/src/ImportWizard.tsx index 6618e8ed21..394be530f1 100644 --- a/packages/plugin-grid/src/ImportWizard.tsx +++ b/packages/plugin-grid/src/ImportWizard.tsx @@ -326,7 +326,7 @@ export interface ImportWizardProps { /** Override the storage backend (defaults to window.localStorage). Use this * to disable persistence (`null`) or to inject an in-memory store in tests. */ templateStorage?: ImportTemplateStorage | null; - /** Registered server-side import mappings for this object (framework #2611). + /** Registered server-side import mappings for this object (objectstack-ai/objectstack#2611). * When omitted, the wizard fetches them via `dataSource.listImportMappings` * (feature-detected). Pass explicitly to override / for tests. */ savedMappings?: SavedMapping[]; @@ -591,7 +591,7 @@ function assembleImportRequest( skipBlankMatchKey: boolean; dryRun?: boolean; /** When set, the server resolves this registered mapping and owns the - * rename + transform + write semantics (framework #2611). `rows` must + * rename + transform + write semantics (objectstack-ai/objectstack#2611). `rows` must * then carry SOURCE headers (see buildSourceRows), and the inline * column mapping / write-mode are omitted — mutually exclusive per the * server contract. `runAutomations` is still honored. */ @@ -975,7 +975,7 @@ const TemplateBar: React.FC<{ ); }; -/** Selector for a registered server-side import mapping (framework #2611). +/** Selector for a registered server-side import mapping (objectstack-ai/objectstack#2611). * Picking one hands rename + transforms to the server; the manual column * table is replaced by a read-only summary of the artifact. */ const SavedMappingBar: React.FC<{ @@ -1637,7 +1637,7 @@ export const ImportWizard: React.FC = ({ const [runAutomations, setRunAutomations] = useState(true); // Default OFF (opt-in): a normal import must still walk the state machine — // only an explicit "historical" import skips it so mid-lifecycle rows aren't - // rejected by initialStates (framework #3479). The strict behavior is the default. + // rejected by initialStates (objectstack-ai/objectstack#3479). The strict behavior is the default. const [treatAsHistorical, setTreatAsHistorical] = useState(false); const [skipBlankMatchKey, setSkipBlankMatchKey] = useState(false); // Opt-in: route this import through a background job even when the row count @@ -1704,7 +1704,7 @@ export const ImportWizard: React.FC = ({ // Re-hydrate templates if the storage backend or key changes. useEffect(() => { setTemplates(loadTemplates(storage, storageKey)); }, [storage, storageKey]); - // ── Server-registered import mappings (framework #2611) ───────────── + // ── Server-registered import mappings (objectstack-ai/objectstack#2611) ───────────── // The reusable, governed alternative to hand-building the column mapping. // Supplied via prop, or fetched from the adapter (feature-detected; a data // source without the method simply yields none, hiding the selector). diff --git a/packages/plugin-grid/src/ObjectGrid.tsx b/packages/plugin-grid/src/ObjectGrid.tsx index b51be6017f..f001173883 100644 --- a/packages/plugin-grid/src/ObjectGrid.tsx +++ b/packages/plugin-grid/src/ObjectGrid.tsx @@ -1624,7 +1624,7 @@ export const ObjectGrid: React.FC = ({ // real match total + page controls. We must forward those straight to DataTable // instead of client-slicing the window — otherwise the footer would report // "pages = window / pageSize" and records beyond the window stay unreachable - // (framework #2212). `data` is a prop, and so are these — all declared on + // (objectstack-ai/objectstack#2212). `data` is a prop, and so are these — all declared on // `ObjectGridExternalPaginationProps` since #4277. const externalManualPagination = hostManualPagination === true && @@ -1952,7 +1952,7 @@ export const ObjectGrid: React.FC = ({ // ($top/$skip) and the DataTable's display page size are the SAME number here // — the records we hold ARE one page, so paging means refetching the next // slice from the server instead of slicing an in-memory batch. This is what - // makes records beyond the first batch reachable at all (framework #2212). + // makes records beyond the first batch reachable at all (objectstack-ai/objectstack#2212). const [serverPage, setServerPage] = useState(1); const [serverPageSize, setServerPageSize] = useState( resolvePageSize(schema, DEFAULT_SERVER_WINDOW_SIZE), @@ -5075,7 +5075,7 @@ export const ObjectGrid: React.FC = ({ * sort state as, and what it EMITS back to whoever persists it. A stale * entry is inert on arrival and is dropped the first time anything writes * the sort back. Only under a served projection — with no signal there is no - * verdict to filter by, and the pre-#10235 behaviour stands unchanged. + * verdict to filter by, and the pre-objectstack-ai/objectstack#10235 behaviour stands unchanged. */ const rawManualSort: TableSortItem[] = externalManualPagination ? (hostSort ?? []) diff --git a/packages/plugin-grid/src/components/RowActionMenu.tsx b/packages/plugin-grid/src/components/RowActionMenu.tsx index 39213a3086..7b1704d427 100644 --- a/packages/plugin-grid/src/components/RowActionMenu.tsx +++ b/packages/plugin-grid/src/components/RowActionMenu.tsx @@ -575,7 +575,7 @@ export const RowActionMenu: React.FC = ({ // children on `sys_approval_request`, whose `list_item` actions (approve / // reject / recall) are gated for approvers and fail for an admin browsing the // "全部" view. The capability gate above was already folded in for exactly - // this reason (#3923); the per-record predicates were not. + // this reason (objectstack-ai/objectstack#3923); the per-record predicates were not. const scope = usePredicateScope(); const plan = React.useMemo( () => diff --git a/packages/plugin-grid/src/hooks/multiValueFields.ts b/packages/plugin-grid/src/hooks/multiValueFields.ts index 6ce74fc359..c261ef1141 100644 --- a/packages/plugin-grid/src/hooks/multiValueFields.ts +++ b/packages/plugin-grid/src/hooks/multiValueFields.ts @@ -44,7 +44,7 @@ export function hasMultiValueShape(def: MultiValueFieldDef | undefined | null): * Return a copy of `patch` where any lone scalar aimed at a multi-value * field (per the object schema) is wrapped into a single-element array. * A scalar written verbatim silently corrupts the column shape for every - * array-consumer (#2204); the server normalizes too (framework #2552), but + * array-consumer (#2204); the server normalizes too (objectstack-ai/objectstack#2552), but * the client should never emit the wrong shape in the first place. * * Only unambiguous scalars (string/number/boolean) are wrapped — arrays diff --git a/packages/plugin-grid/src/resolveBulkActions.ts b/packages/plugin-grid/src/resolveBulkActions.ts index c094482097..a566032c5d 100644 --- a/packages/plugin-grid/src/resolveBulkActions.ts +++ b/packages/plugin-grid/src/resolveBulkActions.ts @@ -22,7 +22,7 @@ * **In the VIEW's `bulkActions`, naming an action the object declares.** That * is the whole vocabulary. `ActionSchema.bulkEnabled` looked like an * object-level alternative and this module briefly derived from it, but spec - * 17.0.0 retired the key (#3896 close-out / framework#4054) — it is now a + * 17.0.0 retired the key (objectstack-ai/objectstack#3896 close-out / framework#4054) — it is now a * `retiredKey()` tombstone, so authoring it is a HARD parse rejection whose * own prescription is: *"the multi-select toolbar is driven by the LIST VIEW's * `bulkActions` / `bulkActionDefs`, never by this flag … declare the action in diff --git a/packages/plugin-grid/src/savedMapping.ts b/packages/plugin-grid/src/savedMapping.ts index 22dd39755d..2b3ae0ed4f 100644 --- a/packages/plugin-grid/src/savedMapping.ts +++ b/packages/plugin-grid/src/savedMapping.ts @@ -1,4 +1,4 @@ -// A registered server-side import `mapping` artifact (framework #2611), fetched +// A registered server-side import `mapping` artifact (objectstack-ai/objectstack#2611), fetched // via the data source and offered in the import wizard as a reusable, governed // alternative to hand-building the column mapping. The server owns the rename + // transform pipeline; the wizard only picks a mapping by name and previews it. diff --git a/packages/plugin-kanban/src/ObjectKanban.tsx b/packages/plugin-kanban/src/ObjectKanban.tsx index af7639f655..8121ea0ee9 100644 --- a/packages/plugin-kanban/src/ObjectKanban.tsx +++ b/packages/plugin-kanban/src/ObjectKanban.tsx @@ -1223,7 +1223,7 @@ export const ObjectKanban: React.FC = ({ // panel inline. A schema can override this with its own `navigation` config. // // No width is spelled here on purpose (objectui#6303, converging kanban on - // the shape #6305 gave ObjectGantt). `width` is `@deprecated [#2578 -> size]` + // the shape #6305 gave ObjectGantt). `width` is `@deprecated [objectstack-ai/objectstack#2578 -> size]` // in the spec that owns this shape, and `resolveOverlayWidth` gives an // explicit `width` priority OVER `size` — so spelling it kept the deprecated // branch load-bearing on the path most boards take (no declared @@ -1368,7 +1368,7 @@ export const ObjectKanban: React.FC = ({ // producer-side marking: a field set at throw time to say "this text is // for the end user". It is a SEPARATE field from `message`, so nothing // unmarked can reach here — the substitution below still governs every - // platform diagnostic and #3821 holds by construction rather than by us + // platform diagnostic and objectstack-ai/objectstack#3821 holds by construction rather than by us // guessing what a body contains. Status-agnostic on purpose: 403 is // where this was reported (objectui#5210/#5902), not a fence the // contract draws — a marked 409 or 400 renders identically. diff --git a/packages/plugin-list/src/ListView.tsx b/packages/plugin-list/src/ListView.tsx index 7681e474a9..41776b50e0 100644 --- a/packages/plugin-list/src/ListView.tsx +++ b/packages/plugin-list/src/ListView.tsx @@ -174,7 +174,7 @@ function resolveListMapConfig(schema: { map?: unknown; options?: { map?: unknown * * `resolves` is the "renders from names the AUTHOR wrote" question, one leg per * shape: - * - ADR-0021 (#1890): a `dataset` with at least one measure in `values`. The + * - ADR-0021 (objectstack-ai/objectstack#1890): a `dataset` with at least one measure in `values`. The * dimensions are what it plots BY, and a block may legitimately declare * none (a single aggregate), so they are not required here. * - legacy: a declared category (`xAxisField` / `categoryField`) AND a @@ -1416,7 +1416,7 @@ export const ListView = React.forwardRef(({ if (message) console.warn(message); }, [dynamicPageSize, authoredPageSize, schema.objectName]); - // --- Server-side pagination (#2212) --- + // --- Server-side pagination (objectstack-ai/objectstack#2212) --- // ListView owns the fetch, so it owns paging too: it requests one window at a // time ($skip = (page-1)*size) and reads the real match `total` from the // result. That total + page controls are handed DOWN to the flat grid view so @@ -2663,7 +2663,7 @@ export const ListView = React.forwardRef(({ setData(items); - // Capture the real match total (framework #2212: findData now returns it). + // Capture the real match total (objectstack-ai/objectstack#2212: findData now returns it). // With a known total the grid pages server-side, so the "showing first N" // cap warning no longer applies; without one we fall back to the old // single-window behaviour and keep the warning. @@ -3695,7 +3695,7 @@ export const ListView = React.forwardRef(({ // block. const chartBinding = resolveListChartBinding(schema); const chartCfg = chartBinding.config; - // ADR-0021 (#1890): the single author-facing shape binds to a semantic + // ADR-0021 (objectstack-ai/objectstack#1890): the single author-facing shape binds to a semantic // `dataset` and selects dimensions/measures BY NAME, so the chart runs // through the governed queryDataset path (numbers consistent everywhere). // @@ -5169,7 +5169,7 @@ export const ListView = React.forwardRef(({ // Drive the flat grid's single (DataTable) pager from the // server: it renders THIS window as the current page, the real // total sets the page count, and turning the page asks ListView - // to refetch the next window. One pager, server-backed (#2212). + // to refetch the next window. One pager, server-backed (objectstack-ai/objectstack#2212). manualPagination: true, rowCount: serverTotal, page: serverPage, diff --git a/packages/plugin-report/src/DatasetReportRenderer.tsx b/packages/plugin-report/src/DatasetReportRenderer.tsx index c362912eba..c0598fd1cc 100644 --- a/packages/plugin-report/src/DatasetReportRenderer.tsx +++ b/packages/plugin-report/src/DatasetReportRenderer.tsx @@ -618,7 +618,7 @@ function DatasetReportTable({ // emit an exact field→raw filter (correct for select/lookup dims, which a // display-label groupKey would mis-filter); the host then filters with no // extra metadata round-trip. Older server → groupKey-only fallback. - // #1752: a time-bucketed date dim contributes a RANGE (not an equality dim), + // objectstack-ai/objectstack#1752: a time-bucketed date dim contributes a RANGE (not an equality dim), // so the fast path also fires when the server sent a range for this row — // covering a date-ONLY report that has no equality drill dim at all. const rowRanges = state.drillRanges?.[index]; @@ -1284,7 +1284,7 @@ function DatasetMatrixTable({ }) { // Row subtotals, column subtotals, and the grand total ([]), in that order. // - // #3916: the ordering rides on the PRIMARY query only — the server drops it + // objectstack-ai/objectstack#3916: the ordering rides on the PRIMARY query only — the server drops it // for the totals sub-queries by design (a total covers the whole selection, // and an order key may name a dimension the totals grouping doesn't have). // The across-axis header sequence follows from it: `pivot` below collects @@ -1386,7 +1386,7 @@ function DatasetMatrixTable({ ? [...rows, ...columnsAcross].filter((d) => d in state.dimensionFields!) : []; const drillCell = (rowKey: Row, colKey: Row, index: number) => { - // #1752: include the date-bucket range sidecar so an "X by time" cell scopes + // objectstack-ai/objectstack#1752: include the date-bucket range sidecar so an "X by time" cell scopes // to the clicked time bucket, not every bucket in that row/column. const cellRanges = state.drillRanges?.[index]; const hasRange = !!cellRanges && Object.keys(cellRanges).length > 0; @@ -1555,7 +1555,7 @@ export const DatasetReportRenderer: React.FC = ({ warnOnRejectedFilterAlias(block, `${reportSite} block \`${block.name ?? index}\``); const blockFilter = mergeFilters(outerFilter, block.runtimeFilter); const blockAcross = readNames(block.columns); - // #3916 — each block orders ITSELF. A joined container selects nothing + // objectstack-ai/objectstack#3916 — each block orders ITSELF. A joined container selects nothing // of its own (the schema rejects `order` on it), and every block is an // independent query over its own dataset, so there is no report-level // ordering to inherit here. diff --git a/packages/plugin-timeline/src/index.tsx b/packages/plugin-timeline/src/index.tsx index 16ab87b4db..d9ceb2058b 100644 --- a/packages/plugin-timeline/src/index.tsx +++ b/packages/plugin-timeline/src/index.tsx @@ -315,12 +315,12 @@ import { * `object-timeline` maps `object` + `filter` + `sort` + `limit` — every key its * fetch now reads (objectstack#7137). * - * Until #7137 the fetch was `dataSource.find(schema.objectName, { options: { $top: + * Until objectstack-ai/objectstack#7137 the fetch was `dataSource.find(schema.objectName, { options: { $top: * 100 } })`: no `$filter`, no `$orderby`, and a cap nested under a key no adapter * reads. objectstack#7121 therefore mapped `object` alone and said so, rather than * writing the composed filter/sort/limit onto keys nobody read — which would have * looked like the binding was honoured while changing nothing about the rows. - * #7137 added the read sites (`$filter` / `$orderby` / `$top: schema.limit ?? 100`), + * objectstack-ai/objectstack#7137 added the read sites (`$filter` / `$orderby` / `$top: schema.limit ?? 100`), * so the flags come with them and a named `view` now actually narrows the rail. * * `columns` stays unmapped for the same reason a calendar's does: a timeline diff --git a/packages/plugin-view/src/ObjectView.tsx b/packages/plugin-view/src/ObjectView.tsx index db64424727..6143e534e4 100644 --- a/packages/plugin-view/src/ObjectView.tsx +++ b/packages/plugin-view/src/ObjectView.tsx @@ -1421,7 +1421,7 @@ export const ObjectView: React.FC = ({ invalidationNonce, ]); - // Determine layout mode. #2578: default the record surface from how heavy the + // Determine layout mode. objectstack-ai/objectstack#2578: default the record surface from how heavy the // object is — a field-heavy object opens create/edit/detail as a full page, a // light one as a drawer. Mobile always pages. An explicit `schema.layout` (or // a per-view navigation config, handled in handleRowClick) still wins. @@ -2185,7 +2185,7 @@ export const ObjectView: React.FC = ({ // Aggregated chart of the object's records, delegating to the same // object-chart component the dashboard uses. const chartCfg = viewOptions.chart || {}; - // ADR-0021 (#1890): dataset-bound chart — the single author-facing shape. + // ADR-0021 (objectstack-ai/objectstack#1890): dataset-bound chart — the single author-facing shape. if (chartCfg.dataset) { const dims: string[] = Array.isArray(chartCfg.dimensions) ? chartCfg.dimensions : []; const vals: string[] = Array.isArray(chartCfg.values) ? chartCfg.values : []; @@ -2429,7 +2429,7 @@ export const ObjectView: React.FC = ({ cancelText: schema.form?.cancelText, showReset: schema.form?.showReset, initialValues: schema.form?.initialValues, - // framework#1894 / #2998: forward the spec-aligned structured + // framework#1894 / objectstack-ai/objectstack#2998: forward the spec-aligned structured // `buttons`/`defaults`; ObjectForm folds them onto the flat props above // (an explicitly-set flat key still wins). buttons: schema.form?.buttons, diff --git a/packages/plugin-view/src/recordSurface.ts b/packages/plugin-view/src/recordSurface.ts index 4b27197146..46e276843a 100644 --- a/packages/plugin-view/src/recordSurface.ts +++ b/packages/plugin-view/src/recordSurface.ts @@ -8,7 +8,7 @@ /** * Record-surface derivation — now sourced from `@objectstack/spec/data` - * (framework #2578 / #2604). The local mirror this file used to carry existed + * (objectstack-ai/objectstack#2578 / objectstack-ai/objectstack#2604). The local mirror this file used to carry existed * only because objectui pinned a spec that predated the export; with the spec * bump to `^12.2.0` the real derivation is available, so we re-export it and * delete the copy (restoring the single-source guarantee the mirror stood in @@ -40,7 +40,7 @@ import { countAuthorableFields } from '@objectstack/spec/data'; /** * Overlay size bucket for a drawer/modal (mirrors spec `NavigationConfig.size` - * / `FormView.modalSize`). #2578: width is a runtime concern — the author can't + * / `FormView.modalSize`). objectstack-ai/objectstack#2578: width is a runtime concern — the author can't * know the client viewport — so buckets map to a pixel CAP that the renderer * always clamps to the viewport (`min(cap, 92vw)`). */ diff --git a/packages/react/src/context/ThemeContext.tsx b/packages/react/src/context/ThemeContext.tsx index aa5bbabd47..1d6cdb734e 100644 --- a/packages/react/src/context/ThemeContext.tsx +++ b/packages/react/src/context/ThemeContext.tsx @@ -227,7 +227,7 @@ export function ThemeProvider({ el.classList.remove('light', 'dark'); el.classList.add(resolvedMode); - // No favicon here: spec v17 (#3494) pruned `Theme.logo`, so the key is + // No favicon here: spec v17 (objectstack-ai/objectstack#3494) pruned `Theme.logo`, so the key is // stripped at parse and could never arrive. The live favicon comes from // operator branding (`getFaviconUrl()`), applied in the console's // index.html, main.tsx, and on route change. diff --git a/packages/react/src/hooks/useExpression.ts b/packages/react/src/hooks/useExpression.ts index 2ad634e106..c93fffd8d7 100644 --- a/packages/react/src/hooks/useExpression.ts +++ b/packages/react/src/hooks/useExpression.ts @@ -120,7 +120,7 @@ export { toPredicateInput } from '@object-ui/core'; * Because the rule has two halves and every predicate face has to get both: * the SHAPE — `record` is the row's one name, so `record.viewer.can_act`, what * every declared action on framework's `sys_approval_request` gates on - * (framework#3310 / #3424), reaches the row — and the NO-ROW case below. + * (framework#3310 / objectstack-ai/objectstack#3424), reaches the row — and the NO-ROW case below. * `DeclaredActionsBar` and the four generic action renderers once carried * inline copies of this bag and drifted (objectui#4077 / #4079); one named * helper is what keeps a fifth copy from drifting again. diff --git a/packages/react/src/hooks/useFilterScope.ts b/packages/react/src/hooks/useFilterScope.ts index 36377c7a43..a4ec6c141c 100644 --- a/packages/react/src/hooks/useFilterScope.ts +++ b/packages/react/src/hooks/useFilterScope.ts @@ -11,7 +11,7 @@ import type { FilterTokenScope } from '@object-ui/core'; /** * The session values filter placeholders resolve against — `{current_user_id}` - * and `{current_org_id}` (framework #3574). + * and `{current_org_id}` (objectstack-ai/objectstack#3574). * * ## Why a dedicated context * @@ -64,7 +64,7 @@ export function FilterScopeProvider({ * Pass the result straight to `resolveFilterPlaceholders(filter, scope)` from * `@object-ui/core` — that helper expands every placeholder vocabulary in one * call, which is the point: resolving only some of them is the defect behind - * #3574. + * objectstack-ai/objectstack#3574. */ export function useFilterScope(): FilterTokenScope { return useContext(FilterScopeContext); diff --git a/packages/react/src/hooks/useNavigationOverlay.ts b/packages/react/src/hooks/useNavigationOverlay.ts index e99693675f..a2f4c4167b 100644 --- a/packages/react/src/hooks/useNavigationOverlay.ts +++ b/packages/react/src/hooks/useNavigationOverlay.ts @@ -100,9 +100,9 @@ import type { SpecAuthoredInput } from '../spec-input.js'; * * Two per-key notes the hand copy carried, kept here because a derived alias * has no members to hang them on: - * - `size` is the coarse overlay bucket added by #2578; `resolveOverlayWidth` + * - `size` is the coarse overlay bucket added by objectstack-ai/objectstack#2578; `resolveOverlayWidth` * below maps it through {@link OVERLAY_SIZE_WIDTHS}. - * - `width` is DEPRECATED by #2578 in favour of `size`. It still wins when + * - `width` is DEPRECATED by objectstack-ai/objectstack#2578 in favour of `size`. It still wins when * present, because app-shell pre-resolves `size` into it. */ export type NavigationConfig = SpecAuthoredInput; diff --git a/packages/react/src/hooks/useRecordSearch.ts b/packages/react/src/hooks/useRecordSearch.ts index 307afb202f..9ed4f78eba 100644 --- a/packages/react/src/hooks/useRecordSearch.ts +++ b/packages/react/src/hooks/useRecordSearch.ts @@ -292,7 +292,7 @@ export function useRecordSearch(opts: UseRecordSearchOptions): UseRecordSearchRe // per-object `find({ $search })` fanout below only runs each object's // metadata-driven search (ADR-0061) and can miss records the global // search index knows about — the command-palette symptom in framework - // #3371, where `/api/v1/search` returned an account/opportunity the + // objectstack-ai/objectstack#3371, where `/api/v1/search` returned an account/opportunity the // palette never showed. When `searchAll` is absent (mock/test adapters, // non-ObjectStack backends) we fall back to the fanout. const searchAll = (dataSource as { searchAll?: unknown }).searchAll; diff --git a/packages/test-support/src/spec-tombstones.ts b/packages/test-support/src/spec-tombstones.ts index 30d9ed2cec..3dc5acff96 100644 --- a/packages/test-support/src/spec-tombstones.ts +++ b/packages/test-support/src/spec-tombstones.ts @@ -19,7 +19,7 @@ * * on purpose: a deleted key would be SILENTLY STRIPPED by a non-strict parse, * while a `never` member fails `tsc` at the authoring site and raises the - * upgrade prescription itself on parse (upstream #3855 / ADR-0104). The removal + * upgrade prescription itself on parse (upstream objectstack-ai/objectstack#3855 / ADR-0104). The removal * has to be audible, so the entry stays. * * The consequence for a consumer is the whole reason this module exists: a diff --git a/packages/types/src/base.ts b/packages/types/src/base.ts index a12a28cf1c..5f78462a4e 100644 --- a/packages/types/src/base.ts +++ b/packages/types/src/base.ts @@ -165,7 +165,7 @@ export interface BaseSchema { * call a hook, `BridgeContext` declares no locale, and `updateContext()` has * zero callers — so a bridge-resolved label would freeze one audience's * language into the node tree with no re-translation channel, the defect the - * spec's own resolver doc records as #6761. + * spec's own resolver doc records as objectstack-ai/objectstack#6761. * * @example "Submit" * @example { en: 'Submit', 'zh-CN': '提交' } diff --git a/packages/types/src/complex.ts b/packages/types/src/complex.ts index 16f1b44072..7fd518e5c2 100644 --- a/packages/types/src/complex.ts +++ b/packages/types/src/complex.ts @@ -2448,7 +2448,7 @@ export interface DashboardComponentSchema extends BaseSchema, Omit; * `unknown`, and the index signature waves through any member at all — a typo'd * `type: 'formatt'` included. The spec's own comment on `ValidationRuleSchema` * says as much and names the remaining work: "it is not strictness … Removing - * the index signature is the #4075 family of work, not this change." + * the index signature is the [objectstack-ai/objectstack#4075] family of work, not this change." * * So the branches stay re-typed to objectui's discriminated union here. What * changed in #3177 is the tripwire, not the divergence: diff --git a/packages/types/src/data.ts b/packages/types/src/data.ts index adfd3cdd75..f22a9ddd73 100644 --- a/packages/types/src/data.ts +++ b/packages/types/src/data.ts @@ -220,7 +220,7 @@ export interface BatchRef { /** * One operation in a cross-object transactional batch. Field names match the - * server contract of `POST /api/v1/batch` (ObjectStack framework #1604 / + * server contract of `POST /api/v1/batch` (objectstack-ai/objectstack#1604 / * ADR-0034 item 4). * * Distinct from the driver-level `BatchOperation` in `data-protocol.ts` @@ -979,7 +979,7 @@ export interface ImportRequestOptions { /** Source column → target field mapping (compact record or entry array). */ mapping?: Record | ImportFieldMappingEntry[]; /** - * Name of a registered `mapping` metadata artifact (framework #2611). When + * Name of a registered `mapping` metadata artifact (objectstack-ai/objectstack#2611). When * set, the server resolves the mapping by name and applies its * fieldMapping pipeline (rename + transforms, strict projection); mutually * exclusive with the inline `mapping` rename above. @@ -995,9 +995,9 @@ export interface ImportRequestOptions { runAutomations?: boolean; /** Import as established historical facts. Skips the `state_machine` rule so * mid-lifecycle rows (already-closed tickets, closed_won deals) aren't rejected - * by `initialStates` (framework #3479), AND preserves the original audit timeline: + * by `initialStates` (objectstack-ai/objectstack#3479), AND preserves the original audit timeline: * a supplied `updated_at`/`updated_by` and business `readonly` fields are kept - * instead of stamped-now / stripped (framework #3493). @default false */ + * instead of stamped-now / stripped (objectstack-ai/objectstack#3493). @default false */ treatAsHistorical?: boolean; /** Trim leading/trailing whitespace from string cells. @default true */ trimWhitespace?: boolean; diff --git a/packages/types/src/field-types.ts b/packages/types/src/field-types.ts index 27b35c1639..d19987f94f 100644 --- a/packages/types/src/field-types.ts +++ b/packages/types/src/field-types.ts @@ -726,7 +726,7 @@ export interface LookupFieldMetadata extends BaseFieldMetadata { * when the reference is stored by another column — e.g. an approval * `position` approver stores `sys_position.name`, because the engine routes * by machine name and names stay portable across environments - * (objectstack #3508). + * (objectstack-ai/objectstack#3508). */ idField?: string; diff --git a/packages/types/src/form.ts b/packages/types/src/form.ts index d1886de467..e38fc37764 100644 --- a/packages/types/src/form.ts +++ b/packages/types/src/form.ts @@ -1884,7 +1884,7 @@ export interface FormField { colSpan?: number; /** * Relative field width, decoupled from the (auto-derived) column count so it - * stays correct at 1/2/3/4 columns (#2578). `'auto'` (default): width from + * stays correct at 1/2/3/4 columns (objectstack-ai/objectstack#2578). `'auto'` (default): width from * the widget type × current columns (wide widgets take the whole row); * `'full'`: whole row at any column count. Aligns with * @objectstack/spec FormField.span. Prefer this over `colSpan`. diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 4bfd99ecfd..ccf3468268 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -1158,7 +1158,7 @@ export type * as Data from '@objectstack/spec/data'; // shim module since objectui#5716, so the `UI.Theme`-family members are // re-pointed at their owner (`./theme.ts`) and survive the spec's theme // retirement instead of narrowing silently on the pin refresh. See the shim's -// header for the full reasoning. The #4171 caveat still applies: +// header for the full reasoning. The objectstack-ai/objectstack#4171 caveat still applies: // `UI.FormField` erases to `any` until the spec types its unions. export type * as UI from './spec-ui-namespace.js'; export type * as System from '@objectstack/spec/system'; @@ -1245,7 +1245,7 @@ export type { * (`id` / `type` / `title` / `body` / `read` / `data` / `actionUrl` / * `createdAt`), with none of `severity` / `duration` / `dismissible` / * `actions` / `position`. Same name, different shape: aliasing it here would - * re-create the very dual-source trap #4610 closed. + * re-create the very dual-source trap objectstack-ai/objectstack#4610 closed. * * The live objectui equivalent of the removed config is * `NotificationSystemConfig` in `@object-ui/react`'s `NotificationContext`, @@ -1335,7 +1335,7 @@ export type { // v3.0.8 Spec UI Types — Form View (P1.2) // ============================================================================ // Deliberate public aliases (the `Spec` prefix IS the disambiguation the -// #3090 tripwire exists to force). #4171 caveat: SpecFormField is `any` today. +// #3090 tripwire exists to force). objectstack-ai/objectstack#4171 caveat: SpecFormField is `any` today. /* eslint-disable no-restricted-imports -- reported at the specifier line, out of -next-line reach */ export type { FormView as SpecFormView, diff --git a/packages/types/src/objectql.ts b/packages/types/src/objectql.ts index af073a2bce..57e8610147 100644 --- a/packages/types/src/objectql.ts +++ b/packages/types/src/objectql.ts @@ -1717,7 +1717,7 @@ export interface ObjectFormSchema extends BaseSchema { /** * Structured, spec-aligned form action-button config — the authoring surface * for submit/cancel/reset visibility + labels, mirroring `@objectstack/spec` - * `FormViewSchema.buttons` (framework#1894 / #2998). ObjectForm normalizes + * `FormViewSchema.buttons` (framework#1894 / objectstack-ai/objectstack#2998). ObjectForm normalizes * this down onto the flat `showSubmit`/`submitText`/`showCancel`/`cancelText`/ * `showReset` props at render, so prefer this over those flat keys (which * remain only as deprecated back-compat). An explicitly-set flat key wins. @@ -1731,7 +1731,7 @@ export interface ObjectFormSchema extends BaseSchema { /** * Create-mode initial field values, keyed by field machine name — the * spec-aligned alias of the deprecated flat {@link initialValues}, mirroring - * `@objectstack/spec` `FormViewSchema.defaults` (framework#1894 / #2998). + * `@objectstack/spec` `FormViewSchema.defaults` (framework#1894 / objectstack-ai/objectstack#2998). * ObjectForm folds this into `initialValues` at render. */ defaults?: Record; @@ -4758,7 +4758,7 @@ export interface ObjectChartSchema extends BaseSchema { * @deprecated Not a key this node reads. Write `aggregate: { field, function, groupBy }`. */ aggregation?: never; - /** Semantic-layer dataset name (ADR-0021, #1890) */ + /** Semantic-layer dataset name (ADR-0021, objectstack-ai/objectstack#1890) */ dataset?: string; /** Dataset dimension names */ dimensions?: string[]; diff --git a/packages/types/src/ui-action.ts b/packages/types/src/ui-action.ts index 71f69ebb48..7c70979462 100644 --- a/packages/types/src/ui-action.ts +++ b/packages/types/src/ui-action.ts @@ -37,7 +37,7 @@ import type { FieldType as SpecFieldType } from '@objectstack/spec/data'; * * Single source of truth lives in `@objectstack/spec/ui` as * `ACTION_LOCATIONS` + `ActionLocationSchema` + `ActionLocation`. These are now - * literally those three values rather than a restatement of them (#4074): the + * literally those three values rather than a restatement of them (objectstack-ai/objectstack#4074): the * comment claimed "re-export" while the code re-*declared* a parallel union, * `as const` tuple, and `z.enum`. To add a new location, edit * `packages/spec/src/ui/action.zod.ts` — every layer (spec, core, types, @@ -281,7 +281,7 @@ export function resolveDeclaredActionIds( /** * Visual component type for actions — derived from the spec's - * `ActionSchema.component` enum (#4074; formerly a hand-written union). + * `ActionSchema.component` enum (objectstack-ai/objectstack#4074; formerly a hand-written union). * * `action:button` | `action:icon` | `action:menu` | `action:group` * @@ -347,7 +347,7 @@ export type RunnableActionType = ActionType | ObjectUiLocalActionType; /** * Field type for action parameters — derived from the spec's `FieldType` - * (#4074; formerly a hand-written 16-member subset). + * (objectstack-ai/objectstack#4074; formerly a hand-written 16-member subset). * * `ActionParamSchema.type` is `FieldType.optional()`, and `FieldType` carries 49 * members. The old union listed 16 of them, so a spec-valid param typed @@ -373,7 +373,7 @@ export const ACTION_PARAM_FIELD_TYPES = SpecFieldTypeEnum.options; /** * Param-only `type` spellings objectui still resolves that the spec's - * `FieldType` does NOT contain (#4074). + * `FieldType` does NOT contain (objectstack-ai/objectstack#4074). * * These are the keys of `PARAM_TYPE_ALIASES` in * `@object-ui/app-shell`'s `paramToField.ts`, which folds each onto a canonical @@ -413,7 +413,7 @@ export type ResolvableParamFieldType = ActionParamFieldType | ObjectUiLocalParam * "authoring ≠ resolved" note below, and objectui#3174 for what conflating them * cost. * - * It is aligned with the spec's `ActionParamSchema` input (#4074 steps 2–3): + * It is aligned with the spec's `ActionParamSchema` input (objectstack-ai/objectstack#4074 steps 2–3): * `name` / `label` / `type` are optional because the `field` reference form * supplies them from an existing object field. The RESOLVED shape the dialog * consumes — after `resolveActionParams()` in `@object-ui/app-shell` inlines @@ -605,10 +605,10 @@ export interface UIActionSchema { /** * Target for the action (URL, script name, etc.) — the **only** handler slot. * - * The `execute` alias was removed in `@objectstack/spec` 17 (#3855); this + * The `execute` alias was removed in `@objectstack/spec` 17 (objectstack-ai/objectstack#3855); this * interface no longer declares it, so `execute: '…'` now fails `tsc` at the * authoring site instead of binding a second handler nothing agrees on - * (#3713, #3856). Rename to `target`; the value is unchanged. + * (objectstack-ai/objectstack#3713, objectstack-ai/objectstack#3856). Rename to `target`; the value is unchanged. */ target?: string; @@ -824,7 +824,7 @@ export interface UIActionSchema { /** * Predicate DISABLING the control — TRUE means disabled. The primary gate on - * both action renderers since #1885 / ADR-0049; {@link enabled} below is the + * both action renderers since objectstack-ai/objectstack#1885 / ADR-0049; {@link enabled} below is the * legacy non-spec fallback kept so existing metadata keeps working. * * Declared here as an ALIGNMENT (objectui#8648), and this key is the one the diff --git a/packages/types/src/widget.ts b/packages/types/src/widget.ts index 0c2544b9c8..c140406294 100644 --- a/packages/types/src/widget.ts +++ b/packages/types/src/widget.ts @@ -45,7 +45,7 @@ import type { ComponentInputControlType } from './base.js'; * states the relationship these two types always had, verbatim: "objectui's * registry has always carried its own runtime manifest for that * (`RuntimeWidgetManifest` / `RuntimeWidgetSource` in `@object-ui/types`, - * objectui#3161 / #4115), which models different keys and never derived from + * objectui#3161 / [objectstack-ai/objectstack#4115]), which models different keys and never derived from * these". `field.widget` is still what it always was — a `z.string()` naming a * component the RENDERER has registered. * diff --git a/packages/types/src/zod/objectql.zod.ts b/packages/types/src/zod/objectql.zod.ts index 8bc3433c81..a0b7a29a17 100644 --- a/packages/types/src/zod/objectql.zod.ts +++ b/packages/types/src/zod/objectql.zod.ts @@ -1744,7 +1744,7 @@ export const ListViewSchema = BaseSchema // `streaming`), with `'pdf'` refused in both spellings under an // `os migrate meta --from 16` prescription (objectstack#8010). // - // This member used to restate a pre-#8010 shape — `'pdf'` accepted in both + // This member used to restate a pre-objectstack-ai/objectstack#8010 shape — `'pdf'` accepted in both // branches, no `streaming`, a non-strict object — so `ListViewInferred` // (`z.input` of this schema, and through it the `ListViewSchema` TYPE the // ListView renderer is written against) disagreed with its sibling @@ -2752,7 +2752,7 @@ const OBJECT_CHART_NEITHER_CHANNEL = neitherContentChannelGuidance( export const ObjectChartSchema = BaseSchema.extend({ type: z.literal('object-chart'), // Legacy inline path (objectName + aggregate). Optional now that a chart may - // instead bind to a semantic-layer dataset (ADR-0021, #1890). + // instead bind to a semantic-layer dataset (ADR-0021, objectstack-ai/objectstack#1890). objectName: z.string().optional().describe('ObjectQL object name (legacy inline path)'), // ── objectui#10770: the chart family, on either tier's key ── // From a9b1d13299d329da296637c4008502da35c30a2c Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 29 Sep 2026 03:33:16 +0000 Subject: [PATCH 3/5] docs(changeset): date-note the pending entries whose bare number means an objectstack card Nine pending changesets cite an objectstack card by a bare number, which in this repository resolves to an unrelated objectui item. Each gets a dated note in the form the pending-entry corrections use: the note names the card as objectstack-ai/objectstack#N and says what it is, and the entry's own text is kept as the reading of its change. Frontmatter is byte-identical in all nine. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude --- .changeset/4664-related-list-declared-filter.md | 5 +++++ .changeset/6956-listview-export-options-spec-mirror.md | 5 +++++ .changeset/7122-spec-17-3-0-pin-repointing.md | 7 +++++++ .changeset/9137-dataset-drill-conjoin-widget-filter.md | 6 ++++++ .changeset/dashboard-aria-member-retired-5830.md | 5 +++++ .changeset/designer-publish-package-binding.md | 5 +++++ .changeset/gantt-navconfig-comment-once.md | 6 ++++++ .changeset/kanban-calendar-nav-width-converge.md | 6 ++++++ .changeset/render-publish-advisory-findings-5026.md | 6 ++++++ 9 files changed, 51 insertions(+) diff --git a/.changeset/4664-related-list-declared-filter.md b/.changeset/4664-related-list-declared-filter.md index f8fffb8af0..f241bb6a9c 100644 --- a/.changeset/4664-related-list-declared-filter.md +++ b/.changeset/4664-related-list-declared-filter.md @@ -16,6 +16,11 @@ related lists answered wider than the metadata asked, and the driving scenario soft-deleted child rows on auto-derived record pages — had no way to be expressed at all. +⚠️ **Dated note, 2026-09-29 — the pull request beside objectstack#8704 is objectstack's — objectui#11016.** The spec key's +pull request is named above by a bare number, which in this repository resolves +to an unrelated objectui pull request. It is objectstack-ai/objectstack#8955, the +spec change that declared the field-level `relatedListFilter`. The text above is kept as the reading of this change. + What ships: - `deriveRelatedLists` reads the key off the FK and carries it on the derived diff --git a/.changeset/6956-listview-export-options-spec-mirror.md b/.changeset/6956-listview-export-options-spec-mirror.md index 076eb55ce2..74ddc902ce 100644 --- a/.changeset/6956-listview-export-options-spec-mirror.md +++ b/.changeset/6956-listview-export-options-spec-mirror.md @@ -32,6 +32,11 @@ intact. The mirror now IS that schema object, so the four verdicts are the spec's by construction; `export-options-spec-parity.test.ts` pins the identity, the four verdicts, and the survival of `streaming` through a parse. +⚠️ **Dated note, 2026-09-29 — the card behind the mirror's old shape is objectstack's — objectui#11016.** The shape the +mirror used to declare is dated above by a bare number, which in this repository +resolves to an unrelated objectui item. It is objectstack-ai/objectstack#8010, the +card the first paragraph cites as objectstack#8010. The text above is kept as the reading of this change. + **The TS face follows.** `ListViewSchema['exportOptions']` is now the spec's INPUT type: `ListViewExportFormat[] | ListViewExportOptions` — the bare array stays admissible on input because nothing on the render path parses, and the diff --git a/.changeset/7122-spec-17-3-0-pin-repointing.md b/.changeset/7122-spec-17-3-0-pin-repointing.md index 86678dc722..bd9fe2e16c 100644 --- a/.changeset/7122-spec-17-3-0-pin-repointing.md +++ b/.changeset/7122-spec-17-3-0-pin-repointing.md @@ -47,3 +47,10 @@ released by this change. refusal's SHAPE. The `LocationField` fence explicitly re-derives why its key-level assertions stay: no parse stands on the emit path, so strictness changed the consequence of a spread regression, not the widget's exposure. + +⚠️ **Dated note, 2026-09-29 — the ruling number in the first two bullets is objectstack's — objectui#11016.** The first +two bullets name the `submitBehavior.url` ruling by a bare number, once as the +family's name and once inside the quoted 17.2.0 spelling. In this repository that +number resolves to an unrelated objectui item; it means +objectstack-ai/objectstack#7496, the spec card that ruled the semantics. The quoted +spelling is the artifact's own and stays verbatim. The text above is kept as the reading of this change. diff --git a/.changeset/9137-dataset-drill-conjoin-widget-filter.md b/.changeset/9137-dataset-drill-conjoin-widget-filter.md index 7d2384485b..94e2302ba9 100644 --- a/.changeset/9137-dataset-drill-conjoin-widget-filter.md +++ b/.changeset/9137-dataset-drill-conjoin-widget-filter.md @@ -38,6 +38,12 @@ multi-condition dataset drill — including paths pinned by objectui#9085, objectui#4056, objectstack#5473 and #1752 — for no change in the rows selected or the `filter[...]` params emitted. +⚠️ **Dated note, 2026-09-29 — the last pinned path in the list above is objectstack's — objectui#11016.** The list of +pinned paths above ends with a bare number after objectstack#5473, which in this +repository resolves to an unrelated objectui pull request. It is +objectstack-ai/objectstack#1752, the card that made a time-bucketed date dimension +drill by range rather than by equality. The text above is kept as the reading of this change. + **The failure direction, corrected by measurement.** This was filed and graded as a silent fail-OPEN superset, on the premise that an index key is one "nothing reads as a condition". It is not: a bare array is not a legal equality comparand diff --git a/.changeset/dashboard-aria-member-retired-5830.md b/.changeset/dashboard-aria-member-retired-5830.md index a104aca90f..7bb4711efc 100644 --- a/.changeset/dashboard-aria-member-retired-5830.md +++ b/.changeset/dashboard-aria-member-retired-5830.md @@ -9,6 +9,11 @@ claimed alignment with `@objectstack/spec AriaPropsSchema`, but the spec removed a tombstone that refuses any value and tells authors to delete the key — and no dashboard renderer ever read `schema.aria` (objectui#5830). +⚠️ **Dated note, 2026-09-29 — the audit close-out named above is objectstack's — objectui#11016.** The audit close-out +is cited above by a bare number, which in this repository resolves to an unrelated +objectui card. It is objectstack-ai/objectstack#3896, whose audit close-out is where +the spec retired `dashboard.aria`. The text above is kept as the reading of this change. + What an author loses is the **type-level suggestion** only: the key was already refused at parse (the Zod twin inherits the spec tombstone by reference), and `BaseSchema`'s index signature means an existing `aria:` line still compiles. diff --git a/.changeset/designer-publish-package-binding.md b/.changeset/designer-publish-package-binding.md index 7d85201ed7..142c84c2de 100644 --- a/.changeset/designer-publish-package-binding.md +++ b/.changeset/designer-publish-package-binding.md @@ -27,3 +27,8 @@ narrowing at the runtime publish gate fire on an HTTP-driven promotion at all. T narrowing has a second, independent gate this does not touch — objects carrying no `_packageId` provenance are kept unconditionally — so on a tenant-authored overlay corpus stating the package still narrows nothing. + +⚠️ **Dated note, 2026-09-29 — the publish-gate narrowing is an objectstack card — objectui#11016.** The last paragraph +names the package-closure narrowing by a bare number, which in this repository +resolves to an unrelated objectui pull request. It is +objectstack-ai/objectstack#9612, the runtime publish gate's rule snapshot. The text above is kept as the reading of this change. diff --git a/.changeset/gantt-navconfig-comment-once.md b/.changeset/gantt-navconfig-comment-once.md index 0390f51d96..2c0bd2def6 100644 --- a/.changeset/gantt-navconfig-comment-once.md +++ b/.changeset/gantt-navconfig-comment-once.md @@ -12,4 +12,10 @@ `width` default supplies the identical `min(960px, 60vw)`. The resolved overlay width is unchanged on every viewport, and is now pinned by a test. +⚠️ **Dated note, 2026-09-29 — the card in the quoted deprecation tag is objectstack's — objectui#11016.** The second +bullet quotes the spec's deprecation tag for `width`, whose bare number resolves +in this repository to an unrelated objectui item. It is +objectstack-ai/objectstack#2578, the spec card behind the `size` bucket that +replaces `width`. The text above is kept as the reading of this change. + No published behaviour changes. diff --git a/.changeset/kanban-calendar-nav-width-converge.md b/.changeset/kanban-calendar-nav-width-converge.md index 7f827c27d4..9326c1b6ea 100644 --- a/.changeset/kanban-calendar-nav-width-converge.md +++ b/.changeset/kanban-calendar-nav-width-converge.md @@ -14,6 +14,12 @@ calendars take. With both omitted, `resolveOverlayWidth` returns `undefined` and `RecordDetailDrawer`'s own `width` default supplies the identical `min(960px, 60vw)`. +⚠️ **Dated note, 2026-09-29 — the card in the quoted deprecation tag is objectstack's — objectui#11016.** The paragraph +above quotes the spec's deprecation tag for `width`, whose bare number resolves +in this repository to an unrelated objectui item. It is +objectstack-ai/objectstack#2578, the spec card behind the `size` bucket that +replaces `width`. The text above is kept as the reading of this change. + The resolved overlay width is therefore unchanged on every viewport, for both a board/calendar that declares no `navigation` and one that authors `navigation.width` — each is now pinned by a test. The three renderers agree diff --git a/.changeset/render-publish-advisory-findings-5026.md b/.changeset/render-publish-advisory-findings-5026.md index 508311abd7..20ad058f31 100644 --- a/.changeset/render-publish-advisory-findings-5026.md +++ b/.changeset/render-publish-advisory-findings-5026.md @@ -10,6 +10,12 @@ objectui#4133 / PR #4236 wired the gate's advisories to the save door and record The second reason has expired. `PublishMetaItemResponseSchema` now declares the same optional, omitted-when-empty `advisories` key that `SaveMetaItemResponseSchema` has carried since #4717, and `publishMetaItem` populates it. Measured against the installed `@objectstack/spec` (17.2.0) rather than inferred from the version number: the key survives a `safeParse`, a half-shaped finding is rejected, and a clean publish omits the key entirely. That reading is now a test rather than a note, so a spec drift fails CI instead of silently re-muting the door. +⚠️ **Dated note, 2026-09-29 — the save response's advisories key came from an objectstack card — objectui#11016.** The +paragraph above dates the save response's `advisories` key by a bare number, +which in this repository resolves to an unrelated objectui item. It is +objectstack-ai/objectstack#4717, the card that put the runtime authoring gate's +advisory findings on the response. The text above is kept as the reading of this change. + `MetadataClient.publish` and `MetadataClient.publishDraft` — the two methods over the single-item publish route `POST /meta/:type/:name/publish` — now report through the **same** sink, the same event and the same renderer the save door already used. No new UI shape: same warning tier, same 10s duration, same per-finding `rule` + `message` + `hint` formatting, findings still rendered verbatim as server prose. The wiring lands in the data layer rather than at the call sites, so `ResourceEditPage`'s Publish button and the runtime `RuntimeDraftBar` promotion (ObjectView / ReportView / DashboardView) are covered by one change, as are future ones. One thing had to differ, and it is the frame's verb. Save and Publish are two different buttons in this product, so a toast that says "Saved" after a Publish tells the author their change is still a draft — the opposite of what happened. `MetadataSaveAdvisoryEvent` therefore gains a required `door: 'save' | 'publish'` and the renderer picks `console.publishAdvisoryTitle` (added to all ten locale packs) accordingly. `door` exists because `mode` cannot answer this: a direct active save and a draft promotion both report `mode: 'publish'`, since both land the body in the active overlay. It is required rather than optional so a future third door cannot be wired without saying which one it is, and the renderer branches on it through an exhaustive switch with a `never` check, so adding a third member is a compile error rather than a silently wrong verb. From 5d8eefd71bc36a00286ef3abd1d3772c60f6915b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 29 Sep 2026 03:35:22 +0000 Subject: [PATCH 4/5] docs(plugin-grid): hold one ObjectGrid comment that open PR objectui#10278 rewrites beside The server-side pagination comment in ObjectGrid.tsx sits directly above the lines objectui#10278 inserts, so qualifying its citation here makes that PR conflict. It keeps its original spelling in this change and is recorded as held by the serial rule; the other two ObjectGrid.tsx citations merge cleanly. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude --- packages/plugin-grid/src/ObjectGrid.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-grid/src/ObjectGrid.tsx b/packages/plugin-grid/src/ObjectGrid.tsx index f001173883..0e59d84a61 100644 --- a/packages/plugin-grid/src/ObjectGrid.tsx +++ b/packages/plugin-grid/src/ObjectGrid.tsx @@ -1952,7 +1952,7 @@ export const ObjectGrid: React.FC = ({ // ($top/$skip) and the DataTable's display page size are the SAME number here // — the records we hold ARE one page, so paging means refetching the next // slice from the server instead of slicing an in-memory batch. This is what - // makes records beyond the first batch reachable at all (objectstack-ai/objectstack#2212). + // makes records beyond the first batch reachable at all (framework #2212). const [serverPage, setServerPage] = useState(1); const [serverPageSize, setServerPageSize] = useState( resolvePageSize(schema, DEFAULT_SERVER_WINDOW_SIZE), From ba91ecf76ef7d01c6f2b4422b8b6339fb0f8bd8e Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 29 Sep 2026 04:04:35 +0000 Subject: [PATCH 5/5] docs(app-shell,changeset): the generic-substitution card cited as objectui's is objectstack's Two PackageFormDialog.tsx comments and the pending violet-donkeys-brake changeset cite the generic-substitution card under this repository's name. In objectui that number is the check-i18n-en-drift script pull request; the card meant is objectstack-ai/objectstack#3821, the sharing-rule dialog card whose objectui repair (objectui#2920) introduced the substitution. The two comments now name it; the pending entry gets a dated note in this change's form, with its frontmatter byte-identical. The test file's doc comment stays: tests are outside the class. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude --- .changeset/violet-donkeys-brake.md | 6 ++++++ .../src/views/metadata-admin/PackageFormDialog.tsx | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.changeset/violet-donkeys-brake.md b/.changeset/violet-donkeys-brake.md index 107b810607..e4b3b02076 100644 --- a/.changeset/violet-donkeys-brake.md +++ b/.changeset/violet-donkeys-brake.md @@ -6,4 +6,10 @@ PackageFormDialog: a producer-marked `error.userMessage` now outranks the locali Creating or saving a package refused with **409** (id taken) or **403** (no `manage_metadata` capability) answered with a localized constant and discarded the envelope's prose — including a `userMessage` the producer had marked, at throw time, as addressed to the person reading the screen (ADR-0112 / objectui#3821). Those are the two refusals an author meets most on this surface, so the one channel written for them was dropped exactly where it mattered. +⚠️ **Dated note, 2026-09-29 — the card cited beside ADR-0112 is objectstack's — objectui#11016.** The +paragraph above cites the generic-substitution card under this repository's name, +which here resolves to an unrelated objectui pull request (the check-i18n-en-drift +script). It is objectstack-ai/objectstack#3821, the sharing-rule dialog card, whose +objectui repair (objectui#2920) introduced the generic substitution. The text above is kept as the reading of this change. + Both arms now render a marked sentence when the envelope carries one, and keep the localized constant as the fallback for an **unmarked** body — which is every refusal the package doors emit today, so the settled localized posture for a withheld capability (objectstack#8270) is unchanged. This also removes a divergence that depended on the transport: the same marked body used to read one way when an HTTP status survived the wire and another way when it did not. diff --git a/packages/app-shell/src/views/metadata-admin/PackageFormDialog.tsx b/packages/app-shell/src/views/metadata-admin/PackageFormDialog.tsx index 4ea6d7de6d..f995863f6c 100644 --- a/packages/app-shell/src/views/metadata-admin/PackageFormDialog.tsx +++ b/packages/app-shell/src/views/metadata-admin/PackageFormDialog.tsx @@ -73,7 +73,7 @@ export interface PackageSaveResult { * (`userMessage || message`, plus the declared code). Its return value * therefore cannot tell a caller WHICH channel won — and objectui#8051's two * status arms need exactly that bit, because their localized constant is a - * generic substitution that objectui#3821 keeps for UNMARKED bodies only. So + * generic substitution that objectstack-ai/objectstack#3821 keeps for UNMARKED bodies only. So * the mark is read here and carried across the throw; ⛔ the arms cannot * re-derive it from the message they receive. * @@ -291,7 +291,7 @@ export function PackageFormDialog({ const msg: string = e?.message ?? ''; // objectui#8051 — WAS this refusal marked? The two status arms below // answer with a localized constant, and that constant is a GENERIC - // SUBSTITUTION: objectui#3821's rule, which the envelope writer states as + // SUBSTITUTION: objectstack-ai/objectstack#3821's rule, which the envelope writer states as // "a consumer that sees the field renders it verbatim and keeps its // generic substitution for everything unmarked", keeps it for unmarked // bodies and hands a MARKED body straight to the person. Until this card