Skip to content

feat(journeys,core): fix defineModule + derive step ordering/progress (feedback items 3 & 4) - #92

Closed
kibertoad wants to merge 12 commits into
mainfrom
claude/branch-83-conflicts-91-7ed2dk
Closed

feat(journeys,core): fix defineModule + derive step ordering/progress (feedback items 3 & 4)#92
kibertoad wants to merge 12 commits into
mainfrom
claude/branch-83-conflicts-91-7ed2dk

Conversation

@kibertoad

Copy link
Copy Markdown
Owner

Implements the next two items from docs/consumer-feedback-production-app.md.

Item 3 — defineModule usable by real apps (all five variants:
@modular-frontend/core + the four router cores):

  • Infer a trailing TDescriptor from the argument and return it verbatim, so
    entryPoints/exitPoints keep their literal keys instead of widening. typeof
    someModule now drops into a journey TransitionMap/StepSpec with zero casts.
  • Infer TNavItem from the navigation array (descriptor & { navigation?:
    readonly TNavItem[] }), defaulting to NavigationItem only when absent, so
    function-form to: (ctx) => ... type-checks with no generics while the
    inferred-narrow item stays assignable to a NavigationItem-typed register().

Item 4 — derive step ordering + progress from the transition graph:

  • resolveStepSequence(definition, options?) walks the static defineTransition
    targets graph and returns the ordered step list (linear, or branch-selected).
  • JourneyDefinition.steps: per-step { path, progressLabel } metadata, keyed and
    type-checked against the real modules/entries (single source of truth).
  • useJourneyProgress on React and Vue returns { index, total, label, steps } —
    the stepCount that JourneyHost (item 2) deferred, now graph-derived.

Adds acceptance + unit + type tests across the touched packages; updates the
changelog and marks items 3 & 4 shipped in the tracker.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01KThnW7wGDMovXu8JdV4q2E

claude and others added 12 commits July 17, 2026 18:56
… (feedback items 3 & 4)

Implements the next two items from docs/consumer-feedback-production-app.md.

Item 3 — defineModule usable by real apps (all five variants:
@modular-frontend/core + the four router cores):
- Infer a trailing TDescriptor from the argument and return it verbatim, so
  entryPoints/exitPoints keep their literal keys instead of widening. typeof
  someModule now drops into a journey TransitionMap/StepSpec with zero casts.
- Infer TNavItem from the navigation array (descriptor & { navigation?:
  readonly TNavItem[] }), defaulting to NavigationItem only when absent, so
  function-form `to: (ctx) => ...` type-checks with no generics while the
  inferred-narrow item stays assignable to a NavigationItem-typed register().

Item 4 — derive step ordering + progress from the transition graph:
- resolveStepSequence(definition, options?) walks the static defineTransition
  targets graph and returns the ordered step list (linear, or branch-selected).
- JourneyDefinition.steps: per-step { path, progressLabel } metadata, keyed and
  type-checked against the real modules/entries (single source of truth).
- useJourneyProgress on React and Vue returns { index, total, label, steps } —
  the stepCount that JourneyHost (item 2) deferred, now graph-derived.

Adds acceptance + unit + type tests across the touched packages; updates the
changelog and marks items 3 & 4 shipped in the tracker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KThnW7wGDMovXu8JdV4q2E
Follow-up to the item 3/4 PR, addressing code-review findings:

- resolveStepSequence: match the `branch` resolver's return against the
  fork's declared `targets` by module+entry, so a ref that isn't a real
  target (or `undefined`) stops the walk instead of being followed blindly.
- resolveStepSequence docs: note that `wildcard` transitions are not walked,
  and that the start step is derived by invoking `initialState`/`start`
  (which must be safe to call with the provided input).
- useJourneyProgress (React + Vue): correct the `total` JSDoc — it is the
  best-effort statically-resolved spine length (partial on forks/unannotated/
  maxSteps), always >= 1 for a derivable start, `null` only for an empty
  sequence — not the previously-documented "null when no instance / unannotated".
  Document that `index` (live) can reach/exceed `total` (static), and that
  `options.sequence` should be referentially stable.
- define-module type-test comments: the function-form `to` fix infers
  `TNavItem` from the `navigation` array; it does not change the default to
  `NavigationItemBase`. Corrected the misleading comments.
- Add a test for the branch-resolver-returns-foreign-ref case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqsgpXv75wiufKKkjTNLXz
… resolveStepSequence

Address CodeRabbit review on PR #83. `resolveStepSequence(definition)`
previously type-checked for journeys whose `initialState` needs an input,
then called `initialState(undefined)` when `input` was omitted.

Model the options so a non-void `TInput` requires either `input` (handed to
the factories) or `start` (naming the first step, skipping them), while
void-input journeys keep fully-optional options. The trailing options
argument becomes required for non-void input via `StepSequenceOptionsArg`,
so `resolveStepSequence(def)` is now a compile error precisely when it would
have called `initialState(undefined)`.

Propagate the same input-awareness through `useJourneyProgress` (React and
Vue): `UseJourneyProgressOptions.sequence` is required (with `input`/`start`)
for non-void journeys, keeping the forwarding to `resolveStepSequence` sound.

Add type-level regression tests proving the bare non-void call, empty
options, walk-only options, and wrong-typed `input` are all rejected, while
void-input journeys and `input`/`start` forms are accepted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UTynWaEhJz9FYF95seoPvH
Address CodeRabbit nit on PR #83: "Requires annotated (defineTransition)
handlers" → "Requires handlers annotated with defineTransition".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UTynWaEhJz9FYF95seoPvH
…inferred

Address CodeRabbit outside-diff review on PR #83. With partial explicit
generics, `defineModule<AppDeps, AppSlots>(descriptor)` locked `TNavItem` to
its `NavigationItem` default (TypeScript can't partially infer a call's type
arguments — spelling some forces the rest to their defaults), so function-form
`to: (ctx) => ...` stopped type-checking unless the caller also spelled the
full nav-item generic. That partial form is exactly what the scaffolder
templates and core READMEs shipped.

Add a curried overload — `defineModule<AppDeps, AppSlots>()(descriptor)` — to
all five cores (frontend-core + the four router cores). The first, empty call
pins the app-wide TSharedDependencies / TSlots (and optional TMeta); the second
infers TNavItem + TDescriptor from the descriptor, so a typed shell fixes
deps/slots while function-form `to` stays inferred. Same idiom as defineJourney.
The direct `defineModule(descriptor)` (zero generics) and fully-explicit
four-generic forms are unchanged.

- Type tests: curried function-form/plain-string `to` in frontend-core;
  curried literal-preservation in tanstack-router-core; curried `ctx` narrowing
  in vue-core.
- Migrate scaffolder templates (react-router / tanstack / vue), the five core
  READMEs, the getting-started / shell-patterns / framework-mode / remote-
  capability docs, and the example modules to the curried form; refresh CLI
  scaffolding snapshots.

Full-repo typecheck (147/147) and the five core + three CLI test suites pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UTynWaEhJz9FYF95seoPvH
Documentation/examples/CLI review pass:

- README: correct the per-family version claims in Project status
  (react-router-modules & tanstack-react-modules: core/runtime v2.x,
  cli/testing v3.x; @modular-react core/react v2.x, testing v1.x), and drop
  the stale "some examples declare library deps with semver ranges" clause —
  every example pins `workspace:*`.
- docs/remote-capability-manifests.md: retarget five broken source links from
  the non-existent `packages/core/src/{types,remote-manifest}.ts` to their real
  home in `packages/frontend-core/src/`.
- docs/navigation.md link fix: promote "Journey-contributed nav" in the
  journeys README to a heading so the existing `#journey-contributed-nav`
  anchor resolves.
- examples/README: add the undocumented examples to the index tree and
  descriptions — integration-setup-journey, journey-invoke (RR + TSR),
  tanstack remote-capabilities, and the catalog demo portal.
- CLI: genericize the shared `create store` help text (was hardcoded
  "Zustand", wrong for the Vue CLI whose store is `createStore`); add
  @modular-vue/cli to cli-core's consumer list (README + package.json); add
  the now-required `scaffold` field to cli-core's preset example; document the
  `serve` subcommand in the catalog README's CLI section; refresh the catalog
  package status marker (v0.2 → v1.x).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UTynWaEhJz9FYF95seoPvH
Follow-up usefulness pass on the documentation review:

- README: add the experimental Angular family (@angular-router-modules/core,
  @modular-angular/angular) to Project status and a new "Angular (experimental)"
  Packages subsection — marked v0.1.x / core-only and explicitly not yet a peer
  of the router integrations, mirroring how the Nuxt integration is noted.
- getting-started (React Router, TanStack Router): name the shipped journey
  features the journeys section previously glossed as "the runtime hooks" —
  <JourneyHost>/useJourneyHost, useJourneyProgress, and useJourneySync.
- getting-started (Vue Router): note the matching Vue journey composables in
  the closing further-reading list.

Verified every referenced export exists in @modular-react/journeys and
@modular-vue/journeys.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UTynWaEhJz9FYF95seoPvH
…cts-83-gjee83

# Conflicts:
#	README.md
#	docs/remote-capability-manifests.md
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@kibertoad, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 61a2f030-6500-4272-bffc-23a5c3aab552

📥 Commits

Reviewing files that changed from the base of the PR and between 2f46db4 and 4372f7a.

⛔ Files ignored due to path filters (3)
  • packages/react-router-cli/test/__snapshots__/cli.test.ts.snap is excluded by !**/*.snap
  • packages/tanstack-router-cli/test/__snapshots__/cli.test.ts.snap is excluded by !**/*.snap
  • packages/vue-cli/test/__snapshots__/cli.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (65)
  • CHANGELOG.md
  • README.md
  • docs/consumer-feedback-production-app.md
  • docs/framework-mode-nuxt.md
  • docs/framework-mode-tanstack-router.md
  • docs/getting-started-react-router.md
  • docs/getting-started-tanstack-router.md
  • docs/getting-started-vue-router.md
  • docs/remote-capability-manifests.md
  • docs/shell-patterns-react-router.md
  • docs/shell-patterns-tanstack-router.md
  • docs/shell-patterns-vue-router.md
  • docs/shell-patterns.md
  • docs/sibling-modules-shared-screen.md
  • examples/README.md
  • examples/react-router/active-project-manifest/modules/integrations/src/index.ts
  • examples/react-router/customer-onboarding-journey/app-shared/src/index.ts
  • examples/react-router/integration-manager/modules/contentful/src/index.tsx
  • examples/react-router/integration-manager/modules/github/src/index.tsx
  • examples/react-router/integration-manager/modules/strapi/src/index.tsx
  • examples/react-router/remote-capabilities/modules/integrations/src/index.ts
  • examples/tanstack-router/customer-onboarding-journey/app-shared/src/index.ts
  • examples/tanstack-router/integration-manager/modules/contentful/src/index.tsx
  • examples/tanstack-router/integration-manager/modules/github/src/index.tsx
  • examples/tanstack-router/integration-manager/modules/strapi/src/index.tsx
  • examples/tanstack-router/remote-capabilities/modules/integration-catalog/src/index.ts
  • examples/vue/customer-onboarding-journey/app-shared/src/index.ts
  • examples/vue/integration-manager/modules/contentful/src/index.ts
  • examples/vue/integration-manager/modules/github/src/index.ts
  • examples/vue/integration-manager/modules/strapi/src/index.ts
  • packages/angular-router-core/README.md
  • packages/angular-router-core/src/define-module.test-d.ts
  • packages/angular-router-core/src/define-module.ts
  • packages/catalog/README.md
  • packages/cli-core/README.md
  • packages/cli-core/package.json
  • packages/cli-core/src/commands/create-store.ts
  • packages/frontend-core/src/define-module.test-d.ts
  • packages/frontend-core/src/define-module.ts
  • packages/frontend-core/src/index.ts
  • packages/frontend-core/src/journey-contracts.ts
  • packages/journeys-engine/src/index.ts
  • packages/journeys-engine/src/resolve-step-sequence.test-d.ts
  • packages/journeys-engine/src/resolve-step-sequence.test.ts
  • packages/journeys-engine/src/resolve-step-sequence.ts
  • packages/journeys-engine/src/types.ts
  • packages/journeys/README.md
  • packages/journeys/src/index.ts
  • packages/journeys/src/use-journey-progress.test.tsx
  • packages/journeys/src/use-journey-progress.ts
  • packages/react-router-cli/src/templates/module.ts
  • packages/react-router-core/README.md
  • packages/react-router-core/src/define-module.ts
  • packages/tanstack-router-cli/src/templates/module.ts
  • packages/tanstack-router-core/README.md
  • packages/tanstack-router-core/src/define-module.test-d.ts
  • packages/tanstack-router-core/src/define-module.ts
  • packages/tanstack-router-core/vitest.config.ts
  • packages/vue-cli/src/templates/module.ts
  • packages/vue-core/README.md
  • packages/vue-core/src/define-module.test-d.ts
  • packages/vue-core/src/define-module.ts
  • packages/vue-journeys/src/index.ts
  • packages/vue-journeys/src/use-journey-progress.test.ts
  • packages/vue-journeys/src/use-journey-progress.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/branch-83-conflicts-91-7ed2dk

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kibertoad kibertoad closed this Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants