Uh oh!
There was an error while loading. Please reload this page.
docs(plugin-gantt): stop documenting a navigation key the spec refuses - #6256
Merged
yinlianghui merged 2 commits intoAug 25, 2026
Merged
Conversation
The record-navigation override example showed
`{ mode: 'page', basePath: '/console/apps/.../campaign' }`. `basePath` is not
a `NavigationConfig` member: `useNavigationOverlay` — where a gantt's
`navigation` lands — builds no URL out of the config, and `ObjectGantt` calls
it with no `onNavigate`, so a page-mode click falls through to the host's
`onRowClick`. The route was never authorable through this key.
`NavigationConfigSchema` is a strict object, so the key was worse than inert:
it rejected the whole config with `unrecognized_keys`, and the `mode: 'page'`
the sentence was teaching never took effect.
Corrects the example to the shape the sentence actually demonstrates, says who
owns the destination route, and points at the spec for the member list rather
than restating it. Adds a pin that EXTRACTS the example from the README and
parses it against the schema, with a control proving the parse still rejects
an undeclared key.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSoz9uGhaaSgiq3hshtN7L`tsconfig.test.json` names `node` in `types` so the README-reading pin compiles; its comment had recorded that no test in this package touches a Node global, and that is corrected rather than left standing. The extractor drops its wrapper try/catch — `JSON.parse`'s own SyntaxError is thrown from the extracting line, and a wrapper would need `Error.cause` (ES2022) to satisfy `preserve-caught-error` under this project's ES2020 lib. Adds the changeset `check-changeset-presence` asked for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSoz9uGhaaSgiq3hshtN7L
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
yinlianghui
marked this pull request as ready for review
August 25, 2026 05:01
Uh oh!
There was an error while loading. Please reload this page.
yinlianghui
deleted the
claude/issue-6050-gantt-readme-navigation-basepath
branch
August 25, 2026 05:12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#6050
What was wrong
packages/plugin-gantt/README.md:48documented the record-navigation override as{ mode: 'page', basePath: '/console/apps/.../campaign' }.basePathis not aNavigationConfigmember, and becauseNavigationConfigSchemais a strictobject the key did not merely sit there inert — it rejected the whole config
with
unrecognized_keys, taking down themode: 'page'the sentence wasactually teaching. Copy the documented snippet, get no page navigation.
The intent judgment (this was explicitly not a
sed)The sentence teaches one thing: route to the standalone detail page instead of
the drawer. Verified against the real consumer,
useNavigationOverlay:mode: 'page'callsonNavigate(recordId, view ?? 'view'), and the only URL it ever constructs(the
new_windowfallback) comes fromobjectName, not from config;ObjectGantt.tsx:1154calls the hook with noonNavigate, so apage-mode click falls through to the host's
onRowClick.So the destination route is host-owned and was never authorable here under any
spelling.
mode: 'page'alone is the whole demonstration, and that is what theexample now shows.
viewwas NOT substituted forbasePath. Triage floated it as ahypothesis; the schema's own
.describe()calls it "Name of the form view touse for details" and the hook forwards it to
onNavigateas the actionargument. It names a form view, not a route — putting it where
basePathstoodwould have swapped an invented key for a wrong one. It is documented for what it
actually does, separately.
Vocabulary is aligned with PR #6053's
ObjectGanttSchema.navigationdoc commenton merged
main, including its instruction not to restate the member list: theREADME now points at
@objectstack/spec'sNavigationConfigSchemainstead ofenumerating members.
The measurement (assumptions verified, not inherited)
Probed against the installed
@objectstack/spec@17.2.0, carrying a control:The controls are what make the failure a key-by-key result rather than a schema
that refuses everything.
Repo-wide
basePathsweep: the only read sites areUploadProvider.tsx(storage prefix),
createAuthClient.ts(better-auth URL split) and@object-ui/layout'sAppSchemaRenderer/NavigationRendererprop (an app-navhref prefix). The layout one is a real
basePathbut a different concept and isunreachable from
useNavigationOverlay; none of the three is aNavigationConfigmember. No producer/consumer disagreement — this is a docs defect, as filed.
check-doc-snippet-typescompilests/tsxfences andcheck-doc-component-typesreadstypeliterals. Neither parses a metadata keyin a README — that gate's own header records schema-key validity as "a different
question with a different answer … left unruled on purpose". Every gate below
being green means I broke nothing; it is not evidence the new example is
correct. The
safeParsemeasurement above and the pin test are theverification.
The pin (#6053's dev found this defect exactly this way)
packages/plugin-gantt/src/readme-navigation-example.test.tsextracts theexample from the README on every run (bounded to its own
### Create / Edit / Delete / Viewsection, anchor asserted unique) and parses it withJSON.parse→NavigationConfigSchema.safeParse. Nothing is hand-retyped; acopy would drift and pin nothing. To make mechanical extraction practical the
example moved from inline prose backticks into a
jsonfence — authoredmetadata is JSON, and
jsonfences are established in nine other packageREADMEs.
The pin ships its own live control: the same parse must still reject an
undeclared key by name, so its green cannot come from a schema that stopped
being strict.
Which assertions would still pass on a revert
Measured, not asserted — two ablations, each proving its mutation on disk
(injected text and removed text grepped separately) and restoring under
trap … EXIT INT TERM, withgit diff HEAD --statempty afterwards:1 failed (1),no testsError: no ```json fence follows the navigation-override sentence in the README.basePathinto it3 failed | 2 passed (5)So, stated plainly: on a straight revert every assertion in the file fails,
but it fails as a suite error rather than five assertion failures — the
extractor dies before any test runs. The two assertions that survive the
sharper ablation are CONTROL: the same parse still REJECTS an undeclared key
and still teaches … page mode — the first is a statement about the schema
rather than about the README and would survive any README revert whose fence
still parsed; the second survives only because that ablation added a key
rather than removing
mode.No ablation here needed a rebuild: the subject is a file read off disk at
runtime plus the prebuilt
@objectstack/specdist, so there is no stale-dist/path for a mutation to hide behind. Both legs were run from a committed state.
Gates run locally, at the final commit
04facb0bd(tree clean)check-changeset-presence✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/6050-gantt-navigation-basepath.md.check-changeset-no-major✅ No changeset declares a 'major' bump.check-doc-fence-languages(+--self-test)✅ check:doc-fences — … No unknown fence spelling hides one.(self-test:26 cases pass)check-doc-component-types✅ Every documented component type is registered.check-doc-linksLinks are valid across 15 scan roots.check-control-bytes✅ check-control-bytes: OK (scanned 5159 tracked text file(s); skipped 85 binary).check-type-check-coverage✅ test type-check coverage: 41/41 packages compile their tests, 0 declared debt…check-lint-coverage✅ lint coverage: 46/46 packages linted, 0 with outstanding errors (0 total).check-vi-mock-specifiers✅ check-vi-mock-specifiers: OK (…)check-shell-escape-residue✅ check-shell-escape-residue: OK (4/4 root(s) resolved…)pnpm --filter @object-ui/plugin-gantt type-checktsc --noEmit && tsc -p tsconfig.test.json(so it really ran — a zero-match filter exits 0 silently)vitest run packages/plugin-gantt(from the repo root)Test Files 47 passed (47)·Tests 402 passed (402)eslint packages/plugin-gantt/src/readme-navigation-example.test.tsThe vitest count is the Trap ③ sanity check: 47 reported files == 47 files on
disk, so this is not
apps/console's 22 running under a false green.Declared narrowing:
check-readme-exportswas not run locally — its jobbuilds every package first, and this README adds no self-import example for it
to judge. CI owns that run, along with the repo-wide
pnpm lint.Two findings fixed in place, both inside this card's own file set
tsconfig.test.jsonnamesnodeintypesso the README-reading pincompiles. Its comment asserted "none of them touches a Node global" — this
PR makes that false, so the comment is rewritten rather than left standing.
Same shape as
packages/plugin-calendar/packages/layout, which name it forthe same reason.
try/catchwas dropped:preserve-caught-errorrequires an attached
cause, andError.causeis ES2022, above thisproject's ES2020 lib.
JSON.parse's ownSyntaxErrorthrows from theextracting line, which is louder than the wrapper was.
Not folded in
⛔ #6051 (24 more undeclared gantt keys) is open in this same package and is
untouched here.
packages/plugin-gantt/CHANGELOG.mdis history and was notedited.
Generated by Claude Code