Repository navigation
feat(spec,plugin-audit): publish the sys_activity.type built-in vocabulary from @objectstack/spec (#11807) - #12331
Conversation
…ulary from @objectstack/spec Export SYS_ACTIVITY_BUILTIN_TYPES / SysActivityBuiltinType from @objectstack/spec/data (feed.zod.ts, beside FeedItemType) and derive the sys_activity object's type options from it, so the built-in set has one readable source instead of hand-copies that drift. The set is the built-in floor of an open, author-extensible vocabulary — deliberately a plain tuple, not a z.enum, so it cannot be used to re-close the column. Census test gains a wiring pin (object options === published set); spec-side test pins the mechanical invariants. Regenerated: api-surface, export-origins, docs reference page, skill refs index (one generated description line). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV
📓 Docs Drift Check3 anchor(s) derived from 2 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 128 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 20ea09c2a8800624aab63d7c2208f37e9b483fe2 && git checkout 20ea09c2a8800624aab63d7c2208f37e9b483fe2
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin b8419bd5a349c76ef133e176e8dbc65a8bf156e6 3152889559caefbbc100515c0289246e247de54e && git checkout -B drift-repro b8419bd5a349c76ef133e176e8dbc65a8bf156e6 && git merge --no-ff 3152889559caefbbc100515c0289246e247de54e
node scripts/docs-audit/affected-docs.mjs --json b8419bd5a349c76ef133e176e8dbc65a8bf156e6 |
Fixes #11807
What
sys_activity.type's built-in vocabulary existed only insideplugin-audit's object declaration, so UI packages hand-copied it — and the copy drifted the same day #11522 declaredscheduled. This PR publishes the set where consumers can read it:packages/spec/src/data/feed.zod.ts— new exportsSYS_ACTIVITY_BUILTIN_TYPES(a plainas consttuple) andSysActivityBuiltinType(derived union), co-located withFeedItemTypeas the issue proposed. The TSDoc states the [Decision] Issys_activity.typea closed platform vocabulary or an author-extensible one? Both readings are true of the code today #11507 boundary: this is the built-in set of an OPEN, author-extensible vocabulary, never the column's value domain — consumers must render unknown values, not drop or reject them. It is deliberately not az.enum: a Zod schema here would read as a validator and quietly re-close the vocabulary.packages/plugins/plugin-audit/src/objects/sys-activity.object.ts— thetypefield's options now spread the published constant instead of inlining the list (single source; parsed output is byte-identical, so the generated i18n bundles do not move).sys-activity-type-vocabulary.test.ts— new wiring pin: the object's declared options must equal the published set, so a diverging re-inlined list cannot come back silently. The existing literal writer census is kept verbatim and now transitively pins the spec constant: editing the published set without redoing the census goes red there. Chain closed in both directions: spec constant === object declaration === writer census.packages/spec/src/data/feed.test.ts— mechanical invariants for the new export (non-empty, unique, snake_case; plain tuple with noparse/safeParseaffordance). The semantic census deliberately stays in plugin-audit — a second literal inventory in spec would be a second copy that can drift, which is what this card retires.check:generated --fix, only the four proved stale):api-surface/data.json,export-origins/data.json,content/docs/references/data/feed.mdx,skills/objectstack-ui/references/_index.md.@objectstack/specminor (new public export),@objectstack/plugin-auditpatch. Additive — no ADR-0087 disposition required (check:adr-0087-registrationgreen).Out of scope, unchanged here: objectui's census pin retires in the UI lane after the pin bump (objectui#5969 lineage; cross-repo mirror gap already tracked as #8852). #11507 remains the governing ruling — nothing here narrows
activityMilestones[].typeor adds enforcement, and #11522 stays untouched by this PR.App-side extension interaction — measured, two-layer shape NOT needed
The #11807 dispatch asked whether the published set must be two-layer ("built-in + extensions"). Measured answer: no.
activityMilestones[].typeisz.string().optional()(object.zod.ts:2021) forwarded verbatim byaudit-writers.ts:1328(if (milestone.type) activityType = milestone.type); app actions insert directly (both measured sites live in hotcrm, per the census). Spec cannot enumerate those at build time — a published "extension layer" would be structurally empty or a lie.recordActivityFeed.ts) is an open map —ACTIVITY_TYPE_TO_FEED_TYPE, a readonly record keyed by arbitrary string whose values are optional FeedItemType entries (the angle-bracket generic is spelled in words here because the platform body sanitizer eats it) — withUNMAPPED_ACTIVITY_FEED_TYPE = 'system'fallback plus a one-shot diagnostic, so app-contributed values already render generically with no published list required.scheduled/fix(plugin-audit): declare sys_activity.type 'scheduled' and record its writer #11522 precedent), which one layer expresses as an ordinary addition.Governed surface note (generated, zero net growth)
gen:skill-refssynced one module-description line inskills/objectstack-ui/references/_index.md(the feed.zod.ts header line). Readings: changed file 56 → 56 lines; whole published catalog SKILL.md sum 10512 → 10512 lines (net 0). No hand edits toskills/**. Because the diff touchesskills/**, this PR is human-merge only (Prime Directive #14) — do not queue, arm, or flip it out of draft.Verification
All heavy commands ran through
scripts/pm/os-verify-lock.sh; exits captured before any pipe; verdict lines quoted from the gates' own output. Union run at head31528895:pnpm --filter @objectstack/spec build— VERDICTcommand-exit 0;check-dts-emitted: @objectstack/spec - 34/34 declared declaration file(s) present.pnpm --filter @objectstack/spec check:generated— re-run at this head after the reverse-verification rebuild: "All 14 generated artifacts are up to date." (verbatim); api-surface delta is exactly+ SYS_ACTIVITY_BUILTIN_TYPES (const),+ SysActivityBuiltinType (type), no removals.pnpm --filter @objectstack/spec test—Test Files 428 passed (428),Tests 11403 passed (11403).pnpm --filter @objectstack/spec typecheck— exit 0 (check:test-typecheck: OK).pnpm --filter '@objectstack/plugin-audit^...' build— VERDICTcommand-exit 0.pnpm --filter @objectstack/plugin-audit test—Test Files 22 passed (22),Tests 326 passed (326).pnpm --filter @objectstack/plugin-audit typecheck— exit 0.dispatch-gates.mjsre-derivation on the actual diff): 50 gates green, listed in the dev report.check:dev-prereqsred is a fresh-worktree precondition (52/67 workspace packages unbuilt — none of them touched here; spec dist freshly built and hash-stamped), not a finding of this diff; CI builds the workspace before running it.SYS_ACTIVITY_BUILTIN_TYPESturns the census set-equality test red while the wiring pin stays green (object follows spec); restoring turns everything green. plugin-audit's vitest aliases@objectstack/spec/*to source (vitest.config.ts), so no rebuild is involved in either leg; the mutation and its restoration were both confirmed on disk by grep before each run.Generated by Claude Code