Skip to content

title, description and public#630

Merged
alexanderkirtzel merged 6 commits intomainfrom
629-step-examples
Apr 21, 2026
Merged

title, description and public#630
alexanderkirtzel merged 6 commits intomainfrom
629-step-examples

Conversation

@alexanderkirtzel
Copy link
Copy Markdown
Collaborator

@alexanderkirtzel alexanderkirtzel commented Apr 21, 2026

Summary by CodeRabbit

  • New Features

    • Step examples now support title, description, and a public flag; non-public examples are hidden by default and can be included via an includeHidden option.
  • Documentation

    • Guidance updated to require title/description for public examples and to mark test-only fixtures as public: false; CLI/docs updated for preview workflow.
  • Tests

    • New tests cover example metadata validation, visibility filtering, includeHidden behavior, and preview command flows.

@alexanderkirtzel alexanderkirtzel linked an issue Apr 21, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

Important

Review skipped

Too many files!

This PR contains 173 files, which is 23 over the limit of 150.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9923b3f1-17a7-4872-8bb5-af1520136faf

📥 Commits

Reviewing files that changed from the base of the PR and between 75aa26b and 2f9aa22.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (173)
  • apps/cli/CHANGELOG.md
  • apps/cli/package.json
  • apps/demos/react/CHANGELOG.md
  • apps/demos/react/package.json
  • apps/demos/storybook/CHANGELOG.md
  • apps/demos/storybook/package.json
  • apps/explorer/CHANGELOG.md
  • apps/explorer/package.json
  • apps/quickstart/CHANGELOG.md
  • apps/quickstart/package.json
  • apps/storybook-addon/CHANGELOG.md
  • apps/storybook-addon/package.json
  • apps/walkerjs/CHANGELOG.md
  • apps/walkerjs/package.json
  • packages/cli/CHANGELOG.md
  • packages/cli/package.json
  • packages/cli/src/__tests__/unit/bundle/preview-preflight-jsdom.test.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/commands/bundle/bundler.ts
  • packages/cli/src/commands/previews/__tests__/previews.test.ts
  • packages/cli/src/commands/previews/index.ts
  • packages/cli/src/commands/previews/output.ts
  • packages/collector/CHANGELOG.md
  • packages/collector/package.json
  • packages/config/CHANGELOG.md
  • packages/config/package.json
  • packages/core/CHANGELOG.md
  • packages/core/package.json
  • packages/mcps/mcp/CHANGELOG.md
  • packages/mcps/mcp/package.json
  • packages/mcps/mcp/src/tools/api.ts
  • packages/mcps/source-browser/CHANGELOG.md
  • packages/mcps/source-browser/package.json
  • packages/server/core/CHANGELOG.md
  • packages/server/core/package.json
  • packages/server/destinations/amplitude/CHANGELOG.md
  • packages/server/destinations/amplitude/package.json
  • packages/server/destinations/api/CHANGELOG.md
  • packages/server/destinations/api/package.json
  • packages/server/destinations/aws/CHANGELOG.md
  • packages/server/destinations/aws/package.json
  • packages/server/destinations/bing/CHANGELOG.md
  • packages/server/destinations/bing/package.json
  • packages/server/destinations/criteo/CHANGELOG.md
  • packages/server/destinations/criteo/package.json
  • packages/server/destinations/customerio/CHANGELOG.md
  • packages/server/destinations/customerio/package.json
  • packages/server/destinations/datamanager/CHANGELOG.md
  • packages/server/destinations/datamanager/package.json
  • packages/server/destinations/file/CHANGELOG.md
  • packages/server/destinations/file/package.json
  • packages/server/destinations/gcp/CHANGELOG.md
  • packages/server/destinations/gcp/package.json
  • packages/server/destinations/hubspot/CHANGELOG.md
  • packages/server/destinations/hubspot/package.json
  • packages/server/destinations/kafka/CHANGELOG.md
  • packages/server/destinations/kafka/package.json
  • packages/server/destinations/klaviyo/CHANGELOG.md
  • packages/server/destinations/klaviyo/package.json
  • packages/server/destinations/linkedin/CHANGELOG.md
  • packages/server/destinations/linkedin/package.json
  • packages/server/destinations/meta/CHANGELOG.md
  • packages/server/destinations/meta/package.json
  • packages/server/destinations/mixpanel/CHANGELOG.md
  • packages/server/destinations/mixpanel/package.json
  • packages/server/destinations/mparticle/CHANGELOG.md
  • packages/server/destinations/mparticle/package.json
  • packages/server/destinations/pinterest/CHANGELOG.md
  • packages/server/destinations/pinterest/package.json
  • packages/server/destinations/posthog/CHANGELOG.md
  • packages/server/destinations/posthog/package.json
  • packages/server/destinations/reddit/CHANGELOG.md
  • packages/server/destinations/reddit/package.json
  • packages/server/destinations/redis/CHANGELOG.md
  • packages/server/destinations/redis/package.json
  • packages/server/destinations/rudderstack/CHANGELOG.md
  • packages/server/destinations/rudderstack/package.json
  • packages/server/destinations/segment/CHANGELOG.md
  • packages/server/destinations/segment/package.json
  • packages/server/destinations/slack/CHANGELOG.md
  • packages/server/destinations/slack/package.json
  • packages/server/destinations/snapchat/CHANGELOG.md
  • packages/server/destinations/snapchat/package.json
  • packages/server/destinations/sqlite/CHANGELOG.md
  • packages/server/destinations/sqlite/package.json
  • packages/server/destinations/tiktok/CHANGELOG.md
  • packages/server/destinations/tiktok/package.json
  • packages/server/destinations/twitter/CHANGELOG.md
  • packages/server/destinations/twitter/package.json
  • packages/server/sources/aws/CHANGELOG.md
  • packages/server/sources/aws/package.json
  • packages/server/sources/express/CHANGELOG.md
  • packages/server/sources/express/package.json
  • packages/server/sources/fetch/CHANGELOG.md
  • packages/server/sources/fetch/package.json
  • packages/server/sources/gcp/CHANGELOG.md
  • packages/server/sources/gcp/package.json
  • packages/server/stores/fs/CHANGELOG.md
  • packages/server/stores/fs/package.json
  • packages/server/stores/gcs/CHANGELOG.md
  • packages/server/stores/gcs/package.json
  • packages/server/stores/s3/CHANGELOG.md
  • packages/server/stores/s3/package.json
  • packages/server/transformers/file/CHANGELOG.md
  • packages/server/transformers/file/package.json
  • packages/server/transformers/fingerprint/CHANGELOG.md
  • packages/server/transformers/fingerprint/package.json
  • packages/stores/memory/CHANGELOG.md
  • packages/stores/memory/package.json
  • packages/transformers/demo/CHANGELOG.md
  • packages/transformers/demo/package.json
  • packages/transformers/validator/CHANGELOG.md
  • packages/transformers/validator/package.json
  • packages/web/core/CHANGELOG.md
  • packages/web/core/package.json
  • packages/web/destinations/amplitude/CHANGELOG.md
  • packages/web/destinations/amplitude/package.json
  • packages/web/destinations/api/CHANGELOG.md
  • packages/web/destinations/api/package.json
  • packages/web/destinations/clarity/CHANGELOG.md
  • packages/web/destinations/clarity/package.json
  • packages/web/destinations/demo/CHANGELOG.md
  • packages/web/destinations/demo/package.json
  • packages/web/destinations/fullstory/CHANGELOG.md
  • packages/web/destinations/fullstory/package.json
  • packages/web/destinations/gtag/CHANGELOG.md
  • packages/web/destinations/gtag/package.json
  • packages/web/destinations/heap/CHANGELOG.md
  • packages/web/destinations/heap/package.json
  • packages/web/destinations/hotjar/CHANGELOG.md
  • packages/web/destinations/hotjar/package.json
  • packages/web/destinations/linkedin/CHANGELOG.md
  • packages/web/destinations/linkedin/package.json
  • packages/web/destinations/matomo/CHANGELOG.md
  • packages/web/destinations/matomo/package.json
  • packages/web/destinations/meta/CHANGELOG.md
  • packages/web/destinations/meta/package.json
  • packages/web/destinations/mixpanel/CHANGELOG.md
  • packages/web/destinations/mixpanel/package.json
  • packages/web/destinations/optimizely/CHANGELOG.md
  • packages/web/destinations/optimizely/package.json
  • packages/web/destinations/pinterest/CHANGELOG.md
  • packages/web/destinations/pinterest/package.json
  • packages/web/destinations/piwikpro/CHANGELOG.md
  • packages/web/destinations/piwikpro/package.json
  • packages/web/destinations/plausible/CHANGELOG.md
  • packages/web/destinations/plausible/package.json
  • packages/web/destinations/posthog/CHANGELOG.md
  • packages/web/destinations/posthog/package.json
  • packages/web/destinations/segment/CHANGELOG.md
  • packages/web/destinations/segment/package.json
  • packages/web/destinations/snowplow/CHANGELOG.md
  • packages/web/destinations/snowplow/package.json
  • packages/web/destinations/tiktok/CHANGELOG.md
  • packages/web/destinations/tiktok/package.json
  • packages/web/sources/browser/CHANGELOG.md
  • packages/web/sources/browser/package.json
  • packages/web/sources/cmps/cookiefirst/CHANGELOG.md
  • packages/web/sources/cmps/cookiefirst/package.json
  • packages/web/sources/cmps/cookiepro/CHANGELOG.md
  • packages/web/sources/cmps/cookiepro/package.json
  • packages/web/sources/cmps/usercentrics/CHANGELOG.md
  • packages/web/sources/cmps/usercentrics/package.json
  • packages/web/sources/dataLayer/CHANGELOG.md
  • packages/web/sources/dataLayer/package.json
  • packages/web/sources/demo/CHANGELOG.md
  • packages/web/sources/demo/package.json
  • packages/web/sources/session/CHANGELOG.md
  • packages/web/sources/session/package.json
  • skills/walkeros-using-cli/commands-reference.md
  • website/CHANGELOG.md
  • website/docs/apps/cli.mdx
  • website/package.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds optional per-step example metadata (title, description, public) across schemas, types, examples, website rendering, MCP tool output/filtering (opt-in includeHidden), and tests; updates JSON schema and explorer theming unrelated to examples.

Changes

Cohort / File(s) Summary
Core schema & types
\.changeset/step-example-metadata.md, packages/core/src/schemas/flow.ts, packages/core/src/types/flow.ts
Introduce title?: string, description?: string, and public?: boolean on StepExample schema/type and document semantics.
Core tests
packages/core/src/schemas/__tests__/step-example-metadata.test.ts, packages/core/src/__tests__/useHooks.test.ts
Add validation and behavior tests for new example metadata and for updated useHooks warning/logger behavior.
MCP tool & output
packages/mcps/mcp/src/tools/examples.ts, packages/mcps/mcp/src/schemas/output.ts, packages/mcps/mcp/src/__tests__/tools/examples.test.ts
Add includeHidden input, default-filter examples where public === false, surface title/description/public in output; tests for default filtering and includeHidden.
Website rendering & schema
website/src/components/snippets/StepExample.tsx, website/src/components/snippets/_configuration.mdx, website/static/schema/flow/v3.json
Prefer example.title for headings, render description, filter non-public examples for examples section, and extend/adjust JSON schema (add title/public, rename mapping def to MappingValue, add WalkerOSConsent).
Repository-wide examples (server & web)
packages/server/.../examples/step.ts, packages/web/.../examples/step.ts, packages/stores/memory/src/examples/step.ts, packages/transformers/*/src/examples/step.ts, etc.
Add title/description to many public step examples; mark internal/test fixtures with public: false in many example files (numerous additive edits).
MCP API & CLI previews (related feature additions)
packages/cli/src/cli.ts, packages/cli/src/commands/previews/*, packages/mcps/mcp/src/tools/api.ts, .changeset/*-preview*.md, website docs website/docs/apps/cli.mdx, website/docs/apps/mcp.mdx
Add previews CLI commands and preview-related MCP api actions (list/get/create/delete), CLI preview output formatting, tests, and docs (separate but present in this diff).
Collector / hooks changes
packages/core/src/useHooks.ts, packages/collector/src/{command,destination,push,store,transformer}.ts
useHooks accepts optional logger and logs warnings on hook failures; collector call sites pass collector.logger into useHooks.
Explorer theming & code rendering
apps/explorer/src/themes/*, apps/explorer/src/components/atoms/code-static.tsx, apps/explorer/src/components/atoms/code.tsx, apps/explorer/src/themes/names.ts, apps/explorer/src/themes/token-groups.ts, apps/explorer/src/styles/index.scss
Introduce theme name constants, token-group driven Monaco theme generation, Shiki theme conversion, and update code rendering to use derived themes; add SCSS import.
Storage & web core
packages/web/core/src/storage.ts, packages/web/core/src/__tests__/storage.test.ts
Wrap storage/cookie access in try/catch to avoid thrown errors; tests added to assert fallback behavior.
Misc utilities & build
scripts/generate-flow-schema.ts, assorted small docs (skills/*/SKILL.md) and changesets
Strip nonstandard id fields when generating schema JSON, update skills docs templates to require title/description for public examples and public: false for test fixtures, and add changesets.

Sequence Diagram(s)

sequenceDiagram
  participant UI as MCP UI
  participant API as MCP API tool handler
  participant FS as Flow examples source (repo)
  participant Schema as Examples output schema

  UI->>API: request flow_examples (includeHidden? false)
  API->>FS: load flow settings & examples
  FS-->>API: examples list (with example.public flags)
  API->>API: filter out examples where public === false (unless includeHidden)
  API->>Schema: attach title/description/public to each example item
  API-->>UI: return filtered examples list (count + examples)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through examples, tidy and bright,

I gave each a title, a description, and light.
Hidden flags tuck test fixtures out of view,
Docs and tools now know which to show you.
🥕🎉

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 629-step-examples

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
skills/walkeros-create-source/SKILL.md (1)

282-319: ⚠️ Potential issue | 🟡 Minor

Make the copyable examples follow the new metadata guidance.

The new comment requires title and description for public examples, but both sample Flow.StepExample objects below are public by default and omit those fields.

Suggested template update
 export const pageView: Flow.StepExample = {
+  title: 'Page view',
+  description: 'A browser load trigger emits a page view event.',
   trigger: {
     type: 'load',
     options: {
       url: 'https://example.com/docs',
@@
 // Server example: HTTP POST carrying a walker event payload.
 export const orderComplete: Flow.StepExample = {
+  title: 'Order complete',
+  description: 'An HTTP POST carrying an order payload emits an order complete event.',
   trigger: { type: 'POST' },
   in: {
     method: 'POST',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/walkeros-create-source/SKILL.md` around lines 282 - 319, Both public
Flow.StepExample objects (pageView and orderComplete) are missing the required
title and description metadata; update the pageView and orderComplete objects to
include a descriptive "title" and a short "description" at the top-level of each
example, and if either example is intended to be test-only instead of public,
add "public: false" to that object instead of metadata. Ensure the fields are
present on the exported objects (pageView, orderComplete) per the new guidance.
skills/walkeros-create-transformer/SKILL.md (1)

119-135: ⚠️ Potential issue | 🟡 Minor

Update the template to include the required public metadata.

The text now tells authors to set title and description for public examples, but the copyable examples/step.ts snippet still omits both on public-by-default entries.

Suggested template update
 export const step = {
   'order-passes': {
+    title: 'Order passes',
+    description: 'A valid order event passes through unchanged.',
     in: { name: 'order complete', data: { id: 'ORD-123' } },
     out: { name: 'order complete', data: { id: 'ORD-123' } },
   },
   'debug-filtered': {
+    public: false,
     in: { name: 'debug test', data: { message: 'noise' } },
     out: false, // Transformer rejects this event
   },
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/walkeros-create-transformer/SKILL.md` around lines 119 - 135, The
examples/step.ts snippet defines the exported const step with entries
'order-passes' and 'debug-filtered' but omits the required public metadata;
update the template so each public example entry (e.g., step['order-passes'])
includes title and description properties and if an entry is only a test fixture
(e.g., debug-filtered) mark it with public: false; ensure the README/example
text and the example object structure both demonstrate adding title and
description for public examples and using public: false for test-only fixtures
to keep the docs and copyable snippet consistent.
skills/walkeros-create-destination/SKILL.md (1)

235-260: ⚠️ Potential issue | 🟡 Minor

Update the adjacent template to follow the new metadata rule.

The new note says public examples should set title and description, but the purchase template immediately below still omits both. Add the fields to the copy-paste example so new destinations follow the rule by default.

Proposed fix
 export const purchase: Flow.StepExample = {
+  title: 'Purchase',
+  description: 'Send a purchase event with transaction value and currency.',
   in: getEvent('order complete', { timestamp: 1700000100 }),
   mapping: {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/walkeros-create-destination/SKILL.md` around lines 235 - 260, The
example Flow.StepExample named "purchase" is missing the required public
metadata fields; update the purchase object (export const purchase:
Flow.StepExample) to include top-level title and description properties and keep
the existing in/mapping/out structure, e.g. add a descriptive title string and a
brief description string to the purchase object so public examples follow the
new metadata rule.
🧹 Nitpick comments (1)
skills/walkeros-using-step-examples/SKILL.md (1)

237-310: Minor inconsistency in description length guidance.

Best Practices (line 238) states descriptions should be "10-25 words", but the example purchase description ("A completed order mapped to the Meta Pixel Purchase standard event.") is 11 words — fine — while several of this PR's actual examples (e.g., defaultEventForwarding at ~14 words, gtagPurchase at ~22 words) are within range. However, a few across the PR push close to or just over 25 (e.g., the PostHog userLoginIdentify and orderCompleteWithInclude descriptions). Consider either relaxing the upper bound in guidance or tightening those examples so the documentation and practice stay aligned.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/walkeros-using-step-examples/SKILL.md` around lines 237 - 310, The
guidance for example descriptions currently says "10-25 words" but some examples
(e.g., userLoginIdentify, orderCompleteWithInclude) exceed 25 words; update
either the guidance or the examples so they match: either relax the upper bound
in the Best Practices sentence (change "10-25 words" to a larger max) or shorten
long descriptions (for examples like defaultEventForwarding, gtagPurchase,
userLoginIdentify, orderCompleteWithInclude, and purchase) to <=25 words; edit
the SKILL.md metadata guidance or adjust the specific Flow.StepExample
description strings accordingly to ensure consistency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/server/destinations/customerio/src/examples/step.ts`:
- Around line 131-133: Update the description string in the example object (the
entry with title 'Destination identify') to avoid implying a repeated identify
on every track; change the wording from “before each track” to something
narrower such as “before the first track push” or “on the first push before this
track call” so it matches the fixture behavior that only fires an identify once
prior to the demonstrated track.

In `@packages/server/destinations/gcp/src/bigquery/examples/step.ts`:
- Around line 71-73: The description text currently implies only arrays are
JSON-stringified when, in fact, expectedRow() stringifies the entire nested data
object; update the example's description (the title/description block) to
explicitly say that the whole nested data object is JSON-stringified into the
data field (not only arrays) and mention expectedRow() as the source of that
behavior so readers understand the resulting row shape.

In `@packages/server/destinations/mixpanel/src/examples/step.ts`:
- Around line 229-231: The title/description metadata ("title" and "description"
in step.ts) overstate coverage because the example doesn't exercise delete_user;
either update the title and description to soften the claim (e.g., "Common
Mixpanel people operations" or "Most Mixpanel people operations") or add a
delete_user scenario to the example so the metadata is accurate; locate the
"title" and "description" properties in the example object and either change the
wording to avoid "All"/"full" or implement and document a delete_user case to
match the current wording.

In `@packages/server/destinations/rudderstack/src/examples/step.ts`:
- Around line 81-84: The description for the exported constant
destinationIdentify (type RudderStackStepExample) incorrectly says it "fires
analytics.identify with traits before each track call"; update the description
string to match the documented "first push" behavior (e.g., "fires
analytics.identify with traits on the first push only") so the metadata aligns
with the docblock and MCP docs; locate destinationIdentify and replace the
description text accordingly.

In `@packages/server/destinations/segment/src/examples/step.ts`:
- Around line 52-55: The description in the SegmentStepExample object
mappedEventName contains a typo/awkward phrase "Segments canonical"; update the
user-facing string in mappedEventName (type SegmentStepExample) to use correct
possessive and clearer wording—e.g. "the Segment's canonical 'Order Completed'
name" or "Segment's canonical event name 'Order Completed'"—so docs/metadata
show the corrected phrase.
- Around line 81-84: The description for the example object destinationIdentify
(type SegmentStepExample) is inaccurate; update the description string to match
the documented “first push” behavior (e.g., state that destination-level
identify fires on the first push rather than before each track call) so the
example’s wording matches the adjacent docblock and MCP docs.

In `@packages/web/destinations/amplitude/src/examples/step.ts`:
- Around line 106-108: The description string for the "Destination identify"
example currently claims identity setters run "before each track" but the
implementation (the cached identity logic in the example) avoids re-firing when
values are unchanged; update the description to reflect that identity setters
set userId/deviceId/sessionId on the Amplitude client before sending events and
only re-run when those values change (i.e., cached values are not re-applied).
Locate the title 'Destination identify' and its description string and replace
the inaccurate phrase "before each track" with wording that makes the cached
behavior explicit.

In `@website/src/components/snippets/_configuration.mdx`:
- Around line 41-49: The Examples heading is rendered even when all step
examples are filtered out; compute the filtered list from
props.data?.examples?.step (e.g., const visible =
Object.entries(props.data.examples.step).filter(([,ex]) => ex?.public !==
false)) and only render the <h2>Examples</h2> and the mapped
stepTitle/StepExample entries when visible.length > 0; update the JSX around
stepTitle and <StepExample> to iterate over this filtered list instead of
calling filter/flatMap inline so the section is fully gated.

In `@website/static/schema/flow/v3.json`:
- Around line 1161-1163: The schema uses non-standard "id" properties in
definitions like "MappingValue" and "WalkerOSConsent" while targeting draft-07;
remove those "id" fields (leave "title"/"description" intact) so the definitions
rely on the existing `#/definitions/` pointers, and verify no code references the
removed "id" keys (update any that expect an "id" string to use the definition
name or $id if you intentionally need a global identifier).

---

Outside diff comments:
In `@skills/walkeros-create-destination/SKILL.md`:
- Around line 235-260: The example Flow.StepExample named "purchase" is missing
the required public metadata fields; update the purchase object (export const
purchase: Flow.StepExample) to include top-level title and description
properties and keep the existing in/mapping/out structure, e.g. add a
descriptive title string and a brief description string to the purchase object
so public examples follow the new metadata rule.

In `@skills/walkeros-create-source/SKILL.md`:
- Around line 282-319: Both public Flow.StepExample objects (pageView and
orderComplete) are missing the required title and description metadata; update
the pageView and orderComplete objects to include a descriptive "title" and a
short "description" at the top-level of each example, and if either example is
intended to be test-only instead of public, add "public: false" to that object
instead of metadata. Ensure the fields are present on the exported objects
(pageView, orderComplete) per the new guidance.

In `@skills/walkeros-create-transformer/SKILL.md`:
- Around line 119-135: The examples/step.ts snippet defines the exported const
step with entries 'order-passes' and 'debug-filtered' but omits the required
public metadata; update the template so each public example entry (e.g.,
step['order-passes']) includes title and description properties and if an entry
is only a test fixture (e.g., debug-filtered) mark it with public: false; ensure
the README/example text and the example object structure both demonstrate adding
title and description for public examples and using public: false for test-only
fixtures to keep the docs and copyable snippet consistent.

---

Nitpick comments:
In `@skills/walkeros-using-step-examples/SKILL.md`:
- Around line 237-310: The guidance for example descriptions currently says
"10-25 words" but some examples (e.g., userLoginIdentify,
orderCompleteWithInclude) exceed 25 words; update either the guidance or the
examples so they match: either relax the upper bound in the Best Practices
sentence (change "10-25 words" to a larger max) or shorten long descriptions
(for examples like defaultEventForwarding, gtagPurchase, userLoginIdentify,
orderCompleteWithInclude, and purchase) to <=25 words; edit the SKILL.md
metadata guidance or adjust the specific Flow.StepExample description strings
accordingly to ensure consistency.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc9b1d44-4335-4b87-bdea-338254299d89

📥 Commits

Reviewing files that changed from the base of the PR and between 2bb4d65 and 12adf24.

📒 Files selected for processing (80)
  • .changeset/step-example-metadata.md
  • packages/core/src/schemas/__tests__/step-example-metadata.test.ts
  • packages/core/src/schemas/flow.ts
  • packages/core/src/types/flow.ts
  • packages/mcps/mcp/src/__tests__/tools/examples.test.ts
  • packages/mcps/mcp/src/schemas/output.ts
  • packages/mcps/mcp/src/tools/examples.ts
  • packages/server/destinations/amplitude/src/examples/step.ts
  • packages/server/destinations/api/src/examples/step.ts
  • packages/server/destinations/aws/src/firehose/examples/step.ts
  • packages/server/destinations/bing/src/examples/step.ts
  • packages/server/destinations/criteo/src/examples/step.ts
  • packages/server/destinations/customerio/src/examples/step.ts
  • packages/server/destinations/datamanager/src/examples/step.ts
  • packages/server/destinations/file/src/examples/step.ts
  • packages/server/destinations/gcp/src/bigquery/examples/step.ts
  • packages/server/destinations/hubspot/src/examples/step.ts
  • packages/server/destinations/kafka/src/examples/step.ts
  • packages/server/destinations/klaviyo/src/examples/step.ts
  • packages/server/destinations/linkedin/src/examples/step.ts
  • packages/server/destinations/meta/src/examples/step.ts
  • packages/server/destinations/mixpanel/src/examples/step.ts
  • packages/server/destinations/mparticle/src/examples/step.ts
  • packages/server/destinations/pinterest/src/examples/step.ts
  • packages/server/destinations/posthog/src/examples/step.ts
  • packages/server/destinations/reddit/src/examples/step.ts
  • packages/server/destinations/redis/src/examples/step.ts
  • packages/server/destinations/rudderstack/src/examples/step.ts
  • packages/server/destinations/segment/src/examples/step.ts
  • packages/server/destinations/slack/src/examples/step.ts
  • packages/server/destinations/snapchat/src/examples/step.ts
  • packages/server/destinations/sqlite/src/examples/step.ts
  • packages/server/destinations/tiktok/src/examples/step.ts
  • packages/server/destinations/twitter/src/examples/step.ts
  • packages/server/sources/aws/src/lambda/examples/step.ts
  • packages/server/sources/express/src/examples/step.ts
  • packages/server/sources/fetch/src/examples/step.ts
  • packages/server/sources/gcp/src/cloudfunction/examples/step.ts
  • packages/server/stores/fs/src/examples/step.ts
  • packages/server/stores/gcs/src/examples/step.ts
  • packages/server/stores/s3/src/examples/step.ts
  • packages/server/transformers/file/src/examples/step.ts
  • packages/server/transformers/fingerprint/src/examples/step.ts
  • packages/stores/memory/src/examples/step.ts
  • packages/transformers/demo/src/examples/step.ts
  • packages/transformers/validator/src/examples/step.ts
  • packages/web/destinations/amplitude/src/examples/step.ts
  • packages/web/destinations/api/src/examples/step.ts
  • packages/web/destinations/clarity/src/examples/step.ts
  • packages/web/destinations/demo/src/examples/step.ts
  • packages/web/destinations/fullstory/src/examples/step.ts
  • packages/web/destinations/gtag/src/examples/step.ts
  • packages/web/destinations/heap/src/examples/step.ts
  • packages/web/destinations/hotjar/src/examples/step.ts
  • packages/web/destinations/linkedin/src/examples/step.ts
  • packages/web/destinations/matomo/src/examples/step.ts
  • packages/web/destinations/meta/src/examples/step.ts
  • packages/web/destinations/mixpanel/src/examples/step.ts
  • packages/web/destinations/optimizely/src/examples/step.ts
  • packages/web/destinations/pinterest/src/examples/step.ts
  • packages/web/destinations/piwikpro/src/examples/step.ts
  • packages/web/destinations/plausible/src/examples/step.ts
  • packages/web/destinations/posthog/src/examples/step.ts
  • packages/web/destinations/segment/src/examples/step.ts
  • packages/web/destinations/snowplow/src/examples/step.ts
  • packages/web/destinations/tiktok/src/examples/step.ts
  • packages/web/sources/browser/src/examples/step.ts
  • packages/web/sources/cmps/cookiefirst/src/examples/step.ts
  • packages/web/sources/cmps/cookiepro/src/examples/step.ts
  • packages/web/sources/cmps/usercentrics/src/examples/step.ts
  • packages/web/sources/dataLayer/src/examples/step.ts
  • packages/web/sources/demo/src/examples/step.ts
  • packages/web/sources/session/src/examples/step.ts
  • skills/walkeros-create-destination/SKILL.md
  • skills/walkeros-create-source/SKILL.md
  • skills/walkeros-create-transformer/SKILL.md
  • skills/walkeros-using-step-examples/SKILL.md
  • website/src/components/snippets/StepExample.tsx
  • website/src/components/snippets/_configuration.mdx
  • website/static/schema/flow/v3.json

Comment thread packages/server/destinations/customerio/src/examples/step.ts Outdated
Comment thread packages/server/destinations/gcp/src/bigquery/examples/step.ts Outdated
Comment thread packages/server/destinations/mixpanel/src/examples/step.ts Outdated
Comment thread packages/server/destinations/rudderstack/src/examples/step.ts Outdated
Comment thread packages/server/destinations/segment/src/examples/step.ts Outdated
Comment thread packages/server/destinations/segment/src/examples/step.ts Outdated
Comment thread packages/web/destinations/amplitude/src/examples/step.ts Outdated
Comment thread website/src/components/snippets/_configuration.mdx Outdated
Comment thread website/static/schema/flow/v3.json Outdated
@github-actions
Copy link
Copy Markdown
Contributor

Preview deployed

https://walkeros-io.b-cdn.net/preview/pr-630/

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/explorer/src/themes/lighthouse.ts`:
- Around line 30-33: The numericConstant, operator, and operatorKeyword color
values in lighthouse theme are too light for a white background; update the hex
values for numericConstant, operator, and operatorKeyword (and optionally
keyword if needed) to higher-contrast, darker variants—e.g., replace `#fb923c`
with a deeper orange like `#d97706`, replace `#01b5e2` with a darker cyan like
`#0b66c2`, and replace `#0086B3` with a deeper teal like `#00608f`—by editing the
numericConstant, operator, and operatorKeyword entries in the lighthouse theme
so tokens are more readable on the light theme.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1468cb5d-e25e-4d33-bd99-2e0788f9c896

📥 Commits

Reviewing files that changed from the base of the PR and between 12adf24 and d913e5a.

📒 Files selected for processing (8)
  • apps/explorer/src/components/atoms/code-static.tsx
  • apps/explorer/src/components/atoms/code.tsx
  • apps/explorer/src/styles/index.scss
  • apps/explorer/src/themes/index.ts
  • apps/explorer/src/themes/lighthouse.ts
  • apps/explorer/src/themes/names.ts
  • apps/explorer/src/themes/palenight.ts
  • apps/explorer/src/themes/token-groups.ts
✅ Files skipped from review due to trivial changes (2)
  • apps/explorer/src/styles/index.scss
  • apps/explorer/src/themes/names.ts

Comment on lines +30 to +33
numericConstant: 'fb923c',
keyword: '6F42C1',
operator: '01b5e2', // Brand cyan — `operator` / `operators` tokens only
operatorKeyword: '0086B3', // Darker teal — `keyword.operator*`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Darken the light-theme orange/cyan tokens for readability.

#fb923c, #01b5e2, and #0086B3 are low-contrast on the light theme’s white background, so numeric constants/operators can be hard to read. Consider darker equivalents.

🎨 Proposed palette adjustment
-  numericConstant: 'fb923c',
+  numericConstant: 'B45309',
   keyword: '6F42C1',
-  operator: '01b5e2', // Brand cyan — `operator` / `operators` tokens only
-  operatorKeyword: '0086B3', // Darker teal — `keyword.operator*`
+  operator: '007A9E', // Brand cyan — `operator` / `operators` tokens only
+  operatorKeyword: '006D8F', // Darker teal — `keyword.operator*`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
numericConstant: 'fb923c',
keyword: '6F42C1',
operator: '01b5e2', // Brand cyan — `operator` / `operators` tokens only
operatorKeyword: '0086B3', // Darker teal — `keyword.operator*`
numericConstant: 'B45309',
keyword: '6F42C1',
operator: '007A9E', // Brand cyan — `operator` / `operators` tokens only
operatorKeyword: '006D8F', // Darker teal — `keyword.operator*`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/explorer/src/themes/lighthouse.ts` around lines 30 - 33, The
numericConstant, operator, and operatorKeyword color values in lighthouse theme
are too light for a white background; update the hex values for numericConstant,
operator, and operatorKeyword (and optionally keyword if needed) to
higher-contrast, darker variants—e.g., replace `#fb923c` with a deeper orange like
`#d97706`, replace `#01b5e2` with a darker cyan like `#0b66c2`, and replace `#0086B3`
with a deeper teal like `#00608f`—by editing the numericConstant, operator, and
operatorKeyword entries in the lighthouse theme so tokens are more readable on
the light theme.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (3)
scripts/generate-flow-schema.ts (1)

22-33: Avoid rewriting literal schema payloads while stripping schema ids.

The recursive walk removes any string-valued id, including inside data-bearing JSON Schema keywords like examples, default, const, or enum. If those payloads ever include { id: "..." }, the generated public schema will silently corrupt the example/default value rather than only removing Zod’s schema metadata.

♻️ Proposed safer traversal
-function stripNonStandardIds(value: unknown): unknown {
-  if (Array.isArray(value)) return value.map(stripNonStandardIds);
+const literalValueKeywords = new Set(['default', 'examples', 'const', 'enum']);
+
+function stripNonStandardIds(value: unknown, preserveLiteralValue = false): unknown {
+  if (preserveLiteralValue) return value;
+  if (Array.isArray(value)) return value.map((item) => stripNonStandardIds(item));
   if (value && typeof value === 'object') {
     const out: Record<string, unknown> = {};
     for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
       if (k === 'id' && typeof v === 'string') continue;
-      out[k] = stripNonStandardIds(v);
+      out[k] = stripNonStandardIds(v, literalValueKeywords.has(k));
     }
     return out;
   }
   return value;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/generate-flow-schema.ts` around lines 22 - 33, The current
stripNonStandardIds function removes any string-valued "id" anywhere (including
inside examples/default/const/enum), corrupting literal payloads; update
stripNonStandardIds so when iterating object entries it preserves values for
data-bearing JSON Schema keywords (e.g., "examples","default","const","enum") by
copying them verbatim without recursing or stripping "id" inside them, while
still continuing to strip schema metadata "id" elsewhere; modify the loop in
stripNonStandardIds to check if k is in a dataKeywords set and if so assign
out[k] = v (no recursion/remove), otherwise keep the existing logic (drop string
"id" keys and recurse for other keys).
packages/collector/src/store.ts (1)

35-52: Use the scoped store logger for hook warnings.

storeLogger already includes the store/storeId scope. Passing it to useHooks makes failures in StoreGet, StoreSet, and StoreDelete easier to attribute.

🔎 Proposed logging-scope tweak
     instance.get = useHooks(
       originalGet,
       'StoreGet',
       collector.hooks,
-      collector.logger,
+      storeLogger,
     );
     instance.set = useHooks(
       originalSet,
       'StoreSet',
       collector.hooks,
-      collector.logger,
+      storeLogger,
     );
     instance.delete = useHooks(
       originalDelete,
       'StoreDelete',
       collector.hooks,
-      collector.logger,
+      storeLogger,
     );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/collector/src/store.ts` around lines 35 - 52, The hook wrappers for
store operations are using the global collector.logger instead of the scoped
storeLogger, so change the calls to useHooks for
instance.get/instance.set/instance.delete to pass storeLogger (which already
includes the store/storeId scope) instead of collector.logger; update the three
calls that currently wrap originalGet, originalSet, originalDelete with
'StoreGet'/'StoreSet'/'StoreDelete' to supply storeLogger so hook warnings are
attributed to the specific store.
packages/collector/src/destination.ts (1)

508-513: Prefer the scoped destination logger for hook warnings.

destLogger is already created for these destination paths. Passing it into useHooks keeps hook failure warnings scoped to the destination instead of emitting from the root collector logger.

🔎 Proposed logging-scope tweak
     const configResult = await useHooks(
       destination.init,
       'DestinationInit',
       collector.hooks,
-      collector.logger,
+      destLogger,
     )(context);
           useHooks(
             destination.pushBatch!,
             'DestinationPushBatch',
             collector.hooks,
-            collector.logger,
+            destLogger,
           )(currentBatched, batchContext);
     const response = await useHooks(
       destination.push,
       'DestinationPush',
       collector.hooks,
-      collector.logger,
+      destLogger,
     )(processed.event, context);

Also applies to: 634-639, 661-666

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/collector/src/destination.ts` around lines 508 - 513, The useHooks
call is using the root collector.logger instead of the per-destination logger,
so change the logger argument passed to useHooks to destLogger to scope hook
warnings to the destination; update the three occurrences where useHooks is
invoked for destination.init (the call with 'DestinationInit') and the other
similar calls around the same block (the calls at the spots referencing
collector.hooks and collector.logger) to pass destLogger instead of
collector.logger, ensuring DestinationInit and related hook invocations use
destLogger and keep context as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli/src/cli.ts`:
- Around line 497-511: The CLI action currently calls createPreview(...) before
validating options.url which can create a remote preview that later fails
formatting; move or perform URL validation for options.url before invoking
createPreview (either reuse the validation logic from printPreviewCreated or
call a shared validateUrl helper) so that invalid URLs are rejected and the
action exits prior to calling createPreview; update the action block that
references createPreview, printPreviewCreated, and options.url to validate
options.url first and only call createPreview when the URL is valid.

In `@packages/cli/src/commands/bundle/bundler.ts`:
- Around line 1764-1778: The HEAD probe using await fetch(__previewSrc, {
method: 'HEAD' }) can hang indefinitely; wrap this probe in an AbortController
with a short timeout (e.g. 1500–3000ms) and pass controller.signal to fetch,
clear the timeout on success, and let the existing catch branch call
__clearPreviewCookie on abort/error so the production walker runs; update the
code around __probe, __previewSrc and __clearPreviewCookie (the async IIFE /
startFlow probe logic) to create controller, schedule controller.abort() via
setTimeout, and clean up the timer, and add a jsdom test that mocks fetch
returning a never-resolving Promise to assert the timeout path executes and
production walker initializes.

In `@packages/cli/src/commands/previews/index.ts`:
- Around line 93-104: The deletePreview function currently calls response.json()
unconditionally which throws on 204 No Content or empty 200 responses; update
deletePreview (and its handling of the apiFetch response) to check
response.status (or response.headers.get('content-length')/response.bodyUsed)
and if the status is 204 or the body is empty return null (or an empty object)
instead of calling response.json(), otherwise parse and return response.json();
ensure the error path unchanged (keep throwApiError(body, 'Failed to delete
preview') when !response.ok).

In `@packages/cli/src/commands/previews/output.ts`:
- Around line 66-73: The spawn call that opens the preview URL should use a
Windows-compatible opener and handle spawn errors: replace the Windows branch
that currently returns 'start' with 'rundll32.exe' and pass args
['url.dll,FileProtocolHandler', stdoutLast] for Windows, keep 'open' for darwin
and 'xdg-open' for other platforms, and attach an 'error' listener to the
ChildProcess returned by spawn (the current spawn(...) call around options.open
&& options.url using stdoutLast) to log or handle failures instead of letting an
unhandled 'error' event crash the process.

In `@packages/core/src/__tests__/useHooks.test.ts`:
- Around line 49-98: Add tests that cover async hook failures by creating
preTest and postTest hooks that return rejected promises (e.g.,
jest.fn().mockRejectedValue(new Error('...'))) and asserting that
useHooks-wrapped calls still return the original result and that warnSpy was
called with the hook name and an Error; specifically add one test for a rejected
preTest hook (useHooks(fn, 'Test', { preTest })) and one for a rejected postTest
hook (useHooks(fn, 'Test', { postTest })), and for each ensure wrapped(5) yields
10 (await if wrapped is async) and warnSpy received
expect.stringContaining('preTest'/'postTest') and expect.any(Error).

In `@packages/core/src/useHooks.ts`:
- Around line 39-58: The preHook/postHook wrapper currently uses synchronous
try/catch which won't catch rejected promises and may double-invoke fn; update
the logic around preHookFn and postHookFn to detect promise-like returns (e.g.,
result && typeof result.then === 'function'), attach a .catch handler to handle
async rejections and call warn there, and avoid immediately calling fn when a
preHook returned a promise—instead wait for the promise to resolve or reject;
also introduce a boolean flag (e.g., didCallOriginal) scoped with the wrapper to
track whether fn(...args) has already been invoked (so callers inside a preHook
can't cause a duplicate call) and only call fn if !didCallOriginal after
resolving the preHook result; apply the same promise-detection + rejection
handling for postHookFn to preserve original behavior without unhandled
rejections.

In `@packages/mcps/mcp/src/tools/api.ts`:
- Around line 399-436: The code creates a preview via createPreviewApi() before
validating siteUrl, which can produce orphan previews if siteUrl is invalid;
update the preview.create branch to validate siteUrl (e.g., attempt new
URL(siteUrl) inside a try/catch or use a URL validation helper) before calling
createPreviewApi(), only proceed to create the preview when siteUrl is either
absent or valid, and if validation fails throw or return a user-facing error;
keep references to createPreviewApi, siteUrl, new URL(siteUrl), preview, and
enriched.activationUrl/deactivationUrl when reordering the logic.

In `@packages/web/core/src/__tests__/storage.test.ts`:
- Around line 176-190: The test "cookie storageWrite does not throw when
document.cookie setter throws" currently only ensures no exception escapes;
update it to also assert that storageWrite('k', 'v', 30, 'cookie', undefined,
env) returns an empty value on failure (matching local/session behavior). Locate
the test block in packages/web/core/src/__tests__/storage.test.ts and add an
assertion that the returned value is '' (or the empty return value your
implementation uses) after calling storageWrite, while keeping the existing
no-throw expectation.

---

Nitpick comments:
In `@packages/collector/src/destination.ts`:
- Around line 508-513: The useHooks call is using the root collector.logger
instead of the per-destination logger, so change the logger argument passed to
useHooks to destLogger to scope hook warnings to the destination; update the
three occurrences where useHooks is invoked for destination.init (the call with
'DestinationInit') and the other similar calls around the same block (the calls
at the spots referencing collector.hooks and collector.logger) to pass
destLogger instead of collector.logger, ensuring DestinationInit and related
hook invocations use destLogger and keep context as-is.

In `@packages/collector/src/store.ts`:
- Around line 35-52: The hook wrappers for store operations are using the global
collector.logger instead of the scoped storeLogger, so change the calls to
useHooks for instance.get/instance.set/instance.delete to pass storeLogger
(which already includes the store/storeId scope) instead of collector.logger;
update the three calls that currently wrap originalGet, originalSet,
originalDelete with 'StoreGet'/'StoreSet'/'StoreDelete' to supply storeLogger so
hook warnings are attributed to the specific store.

In `@scripts/generate-flow-schema.ts`:
- Around line 22-33: The current stripNonStandardIds function removes any
string-valued "id" anywhere (including inside examples/default/const/enum),
corrupting literal payloads; update stripNonStandardIds so when iterating object
entries it preserves values for data-bearing JSON Schema keywords (e.g.,
"examples","default","const","enum") by copying them verbatim without recursing
or stripping "id" inside them, while still continuing to strip schema metadata
"id" elsewhere; modify the loop in stripNonStandardIds to check if k is in a
dataKeywords set and if so assign out[k] = v (no recursion/remove), otherwise
keep the existing logic (drop string "id" keys and recurse for other keys).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6f3b0d8e-4be0-4913-877e-e6f391fcefc5

📥 Commits

Reviewing files that changed from the base of the PR and between d913e5a and 75aa26b.

📒 Files selected for processing (37)
  • .changeset/cli-previews-command.md
  • .changeset/mcp-preview-actions.md
  • .changeset/preview-preflight-self-heal.md
  • .changeset/usehooks-error-boundary.md
  • .changeset/web-core-storage-try-catch.md
  • packages/cli/src/__tests__/unit/bundle/preview-preflight-jsdom.test.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/commands/bundle/bundler.ts
  • packages/cli/src/commands/previews/__tests__/output.test.ts
  • packages/cli/src/commands/previews/__tests__/previews.test.ts
  • packages/cli/src/commands/previews/index.ts
  • packages/cli/src/commands/previews/output.ts
  • packages/cli/src/index.ts
  • packages/collector/src/command.ts
  • packages/collector/src/destination.ts
  • packages/collector/src/push.ts
  • packages/collector/src/store.ts
  • packages/collector/src/transformer.ts
  • packages/core/src/__tests__/useHooks.test.ts
  • packages/core/src/useHooks.ts
  • packages/mcps/mcp/src/__tests__/tools/api-preview.test.ts
  • packages/mcps/mcp/src/tools/api.ts
  • packages/server/destinations/customerio/src/examples/step.ts
  • packages/server/destinations/gcp/src/bigquery/examples/step.ts
  • packages/server/destinations/mixpanel/src/examples/step.ts
  • packages/server/destinations/rudderstack/src/examples/step.ts
  • packages/server/destinations/segment/src/examples/step.ts
  • packages/web/core/src/__tests__/storage.test.ts
  • packages/web/core/src/storage.ts
  • packages/web/destinations/amplitude/src/examples/step.ts
  • scripts/generate-flow-schema.ts
  • skills/walkeros-using-cli/SKILL.md
  • skills/walkeros-using-cli/commands-reference.md
  • website/docs/apps/cli.mdx
  • website/docs/apps/mcp.mdx
  • website/src/components/snippets/_configuration.mdx
  • website/static/schema/flow/v3.json
✅ Files skipped from review due to trivial changes (14)
  • skills/walkeros-using-cli/SKILL.md
  • .changeset/cli-previews-command.md
  • .changeset/preview-preflight-self-heal.md
  • .changeset/web-core-storage-try-catch.md
  • .changeset/mcp-preview-actions.md
  • .changeset/usehooks-error-boundary.md
  • packages/collector/src/transformer.ts
  • packages/server/destinations/gcp/src/bigquery/examples/step.ts
  • skills/walkeros-using-cli/commands-reference.md
  • packages/cli/src/commands/previews/tests/previews.test.ts
  • packages/server/destinations/customerio/src/examples/step.ts
  • website/docs/apps/cli.mdx
  • packages/server/destinations/rudderstack/src/examples/step.ts
  • packages/server/destinations/mixpanel/src/examples/step.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/static/schema/flow/v3.json
  • packages/web/destinations/amplitude/src/examples/step.ts

Comment thread packages/cli/src/cli.ts Outdated
Comment thread packages/cli/src/commands/bundle/bundler.ts
Comment thread packages/cli/src/commands/previews/index.ts
Comment on lines +66 to +73
if (options.open && options.url) {
const opener =
process.platform === 'darwin'
? 'open'
: process.platform === 'win32'
? 'start'
: 'xdg-open';
spawn(opener, [stdoutLast], { stdio: 'ignore', detached: true }).unref();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Node.js child_process.spawn Windows start command shell built-in error event

💡 Result:

When using Node.js child_process.spawn on Windows to execute the built-in 'start' command (typically via shell: true or spawning cmd.exe /c start ...), the 'error' event is not triggered for command failures. The 'start' command starts a separate process asynchronously and immediately returns exit code 0 to the cmd.exe shell process, even if the started application fails to launch or encounters issues. The Node.js child process (cmd.exe) thus completes successfully with code 0, emitting 'close' or 'exit' with 0, without propagating the target application's failure via the 'error' event. To handle errors in the started process: - Use {detached: true, stdio: 'ignore'} and child.unref to fully detach, but this loses event access. - Listen to 'exit'/'close' events (code will be 0 for success). - For critical apps, avoid 'start' and spawn the executable directly with appropriate options. - The 'error' event only fires for spawn failures (e.g., ENOENT if command not found without shell: true), not runtime issues in shell commands like 'start'. Official Node.js docs confirm spawn with shell: true runs commands via shell, and 'error' is for spawn failures only. Stack Overflow examples show shell commands like 'dir' succeed with shell: true, no 'error' for invalid subcommands.

Citations:


🏁 Script executed:

# Check if file exists and read the relevant section
if [ -f "packages/cli/src/commands/previews/output.ts" ]; then
    echo "=== File found ==="
    wc -l packages/cli/src/commands/previews/output.ts
    echo "=== Lines 60-80 ==="
    sed -n '60,80p' packages/cli/src/commands/previews/output.ts
else
    echo "File not found"
fi

Repository: elbwalker/walkerOS

Length of output: 646


🏁 Script executed:

# Check if there are any error handlers on spawn results elsewhere in the file
rg -n "spawn\(" packages/cli/src/commands/previews/output.ts -A 3 -B 2

Repository: elbwalker/walkerOS

Length of output: 204


🏁 Script executed:

# Check Node.js version constraints in the project
fd -e package.json | head -5 | xargs grep -l "engines.*node" 2>/dev/null || echo "Checking for Node versions in main package.json"
cat package.json | grep -A 5 '"engines"' || cat package.json | grep '"node"' || echo "No explicit Node version constraint found"

Repository: elbwalker/walkerOS

Length of output: 199


Add error handling to the spawn call and use Windows-compatible opener.

spawn('start', ...) will fail on Windows because start is a shell built-in, not an executable. The unhandled error event will crash the command. Use rundll32.exe to open URLs on Windows and add an error listener on all platforms.

Proposed fix
  if (options.open && options.url) {
-    const opener =
-      process.platform === 'darwin'
-        ? 'open'
-        : process.platform === 'win32'
-          ? 'start'
-          : 'xdg-open';
-    spawn(opener, [stdoutLast], { stdio: 'ignore', detached: true }).unref();
+    const spawnOptions = {
+      stdio: 'ignore',
+      detached: true,
+      windowsHide: true,
+    } as const;
+    const child =
+      process.platform === 'darwin'
+        ? spawn('open', [stdoutLast], spawnOptions)
+        : process.platform === 'win32'
+          ? spawn(
+              'rundll32',
+              ['url.dll,FileProtocolHandler', stdoutLast],
+              spawnOptions,
+            )
+          : spawn('xdg-open', [stdoutLast], spawnOptions);
+
+    child.on('error', (error) => {
+      process.stderr.write(`Could not open preview URL: ${error.message}\n`);
+    });
+    child.unref();
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (options.open && options.url) {
const opener =
process.platform === 'darwin'
? 'open'
: process.platform === 'win32'
? 'start'
: 'xdg-open';
spawn(opener, [stdoutLast], { stdio: 'ignore', detached: true }).unref();
if (options.open && options.url) {
const spawnOptions = {
stdio: 'ignore',
detached: true,
windowsHide: true,
} as const;
const child =
process.platform === 'darwin'
? spawn('open', [stdoutLast], spawnOptions)
: process.platform === 'win32'
? spawn(
'rundll32',
['url.dll,FileProtocolHandler', stdoutLast],
spawnOptions,
)
: spawn('xdg-open', [stdoutLast], spawnOptions);
child.on('error', (error) => {
process.stderr.write(`Could not open preview URL: ${error.message}\n`);
});
child.unref();
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/previews/output.ts` around lines 66 - 73, The spawn
call that opens the preview URL should use a Windows-compatible opener and
handle spawn errors: replace the Windows branch that currently returns 'start'
with 'rundll32.exe' and pass args ['url.dll,FileProtocolHandler', stdoutLast]
for Windows, keep 'open' for darwin and 'xdg-open' for other platforms, and
attach an 'error' listener to the ChildProcess returned by spawn (the current
spawn(...) call around options.open && options.url using stdoutLast) to log or
handle failures instead of letting an unhandled 'error' event crash the process.

Comment on lines +49 to +98
test('preHook error falls back to original fn and warns via console', () => {
const fn = jest.fn((x: number) => x * 2);
const preHook = jest.fn(() => {
throw new Error('preHook exploded');
});
const wrapped = useHooks(fn, 'Test', {
preTest: preHook,
} as unknown as Hooks.Functions);

expect(wrapped(5)).toBe(10);
expect(fn).toHaveBeenCalledWith(5);
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('preTest'),
expect.any(Error),
);
});

test('postHook error returns original result and warns via console', () => {
const fn = jest.fn((x: number) => x * 2);
const postHook = jest.fn(() => {
throw new Error('postHook exploded');
});
const wrapped = useHooks(fn, 'Test', {
postTest: postHook,
} as unknown as Hooks.Functions);

expect(wrapped(5)).toBe(10);
expect(fn).toHaveBeenCalledWith(5);
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('postTest'),
expect.any(Error),
);
});

test('both hooks erroring keeps pipeline alive', () => {
const fn = jest.fn((x: number) => x * 2);
const preHook = jest.fn(() => {
throw new Error('pre');
});
const postHook = jest.fn(() => {
throw new Error('post');
});
const wrapped = useHooks(fn, 'Test', {
preTest: preHook,
postTest: postHook,
} as unknown as Hooks.Functions);

expect(wrapped(5)).toBe(10);
expect(warnSpy).toHaveBeenCalledTimes(2);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, find and examine the useHooks implementation
find . -type f -name "*.ts" -o -name "*.tsx" | xargs grep -l "export.*useHooks\|function useHooks" | head -20

Repository: elbwalker/walkerOS

Length of output: 122


🏁 Script executed:

# Look for the useHooks function definition
fd -e ts -e tsx | xargs grep -l "useHooks" | grep -E "(src/|lib/)" | grep -v test | head -20

Repository: elbwalker/walkerOS

Length of output: 291


🏁 Script executed:

# Search in packages/core
fd -e ts -e tsx packages/core/src | grep -v test | xargs grep -l "useHooks" 2>/dev/null

Repository: elbwalker/walkerOS

Length of output: 437


🏁 Script executed:

# Examine the useHooks implementation
cat -n packages/core/src/useHooks.ts

Repository: elbwalker/walkerOS

Length of output: 2347


🏁 Script executed:

# Check how useHooks is used in collector - particularly with async functions
grep -A 5 -B 5 "useHooks" packages/collector/src/destination.ts | head -50

Repository: elbwalker/walkerOS

Length of output: 1163


🏁 Script executed:

# Check collector push for async usage
grep -A 5 -B 5 "useHooks" packages/collector/src/push.ts | head -50

Repository: elbwalker/walkerOS

Length of output: 712


🏁 Script executed:

# Examine the test file to see what's currently tested
cat -n packages/core/src/__tests__/useHooks.test.ts

Repository: elbwalker/walkerOS

Length of output: 4652


Add async rejection coverage for hook isolation.

The current tests only validate synchronous throws. Since useHooks wraps async collector/destination functions in production (e.g., destination.init, destination.push), add test cases for rejected-promise pre- and post-hook scenarios to ensure hook failures are handled gracefully in async contexts.

🧪 Suggested tests
+  test('async preHook rejection falls back to original fn and warns', async () => {
+    const fn = jest.fn(async (x: number) => x * 2);
+    const preHook = jest.fn(async () => {
+      throw new Error('async preHook exploded');
+    });
+    const wrapped = useHooks(fn, 'Test', {
+      preTest: preHook,
+    } as unknown as Hooks.Functions);
+
+    await expect(wrapped(5)).resolves.toBe(10);
+    expect(fn).toHaveBeenCalledWith(5);
+    expect(warnSpy).toHaveBeenCalledWith(
+      expect.stringContaining('preTest'),
+      expect.any(Error),
+    );
+  });
+
+  test('async postHook rejection keeps original result and warns', async () => {
+    const fn = jest.fn(async (x: number) => x * 2);
+    const postHook = jest.fn(async () => {
+      throw new Error('async postHook exploded');
+    });
+    const wrapped = useHooks(fn, 'Test', {
+      postTest: postHook,
+    } as unknown as Hooks.Functions);
+
+    await expect(wrapped(5)).resolves.toBe(10);
+    expect(fn).toHaveBeenCalledWith(5);
+    expect(warnSpy).toHaveBeenCalledWith(
+      expect.stringContaining('postTest'),
+      expect.any(Error),
+    );
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/__tests__/useHooks.test.ts` around lines 49 - 98, Add tests
that cover async hook failures by creating preTest and postTest hooks that
return rejected promises (e.g., jest.fn().mockRejectedValue(new Error('...')))
and asserting that useHooks-wrapped calls still return the original result and
that warnSpy was called with the hook name and an Error; specifically add one
test for a rejected preTest hook (useHooks(fn, 'Test', { preTest })) and one for
a rejected postTest hook (useHooks(fn, 'Test', { postTest })), and for each
ensure wrapped(5) yields 10 (await if wrapped is async) and warnSpy received
expect.stringContaining('preTest'/'postTest') and expect.any(Error).

Comment on lines 39 to +58
if (preHookFn) {
// Call the original function within the preHook
result = preHookFn({ fn }, ...args);
try {
result = preHookFn({ fn }, ...args);
} catch (error) {
warn(
`Hook ${String(preHook)} failed, falling back to original function`,
error,
);
result = fn(...args);
}
} else {
// Regular function call
result = fn(...args);
}

if (postHookFn) {
// Call the post-hook function with fn, result, and the original args
result = postHookFn({ fn, result }, ...args);
try {
result = postHookFn({ fn, result }, ...args);
} catch (error) {
warn(`Hook ${String(postHook)} failed, keeping original result`, error);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

wc -l packages/core/src/useHooks.ts

Repository: elbwalker/walkerOS

Length of output: 94


🏁 Script executed:

cat -n packages/core/src/useHooks.ts

Repository: elbwalker/walkerOS

Length of output: 2347


🏁 Script executed:

rg "useHooks" --type ts --type tsx -A 3 -B 3 | head -100

Repository: elbwalker/walkerOS

Length of output: 89


🏁 Script executed:

rg "Hook\[" --type ts --type tsx -A 5 -B 5 | head -150

Repository: elbwalker/walkerOS

Length of output: 89


🏁 Script executed:

rg "useHooks\(" --type ts -A 2 -B 2

Repository: elbwalker/walkerOS

Length of output: 5799


🏁 Script executed:

rg "pre\w+\s*[:=]|post\w+\s*[:=]" --type ts -A 3 -B 1 | head -200

Repository: elbwalker/walkerOS

Length of output: 12395


🏁 Script executed:

rg "hooks\[" --type ts -A 5

Repository: elbwalker/walkerOS

Length of output: 558


🏁 Script executed:

fd -t f "\.ts$" packages/core/src | head -20

Repository: elbwalker/walkerOS

Length of output: 964


🏁 Script executed:

cat -n packages/core/src/__tests__/useHooks.test.ts

Repository: elbwalker/walkerOS

Length of output: 4652


🏁 Script executed:

rg "async.*preHook|async.*postHook" packages/core/src/__tests__/useHooks.test.ts -A 5 -B 2

Repository: elbwalker/walkerOS

Length of output: 44


🏁 Script executed:

cat -n packages/collector/src/push.ts | head -50

Repository: elbwalker/walkerOS

Length of output: 1911


🏁 Script executed:

cat -n packages/collector/src/destination.ts | sed -n '1,150p'

Repository: elbwalker/walkerOS

Length of output: 5090


🏁 Script executed:

cat -n packages/collector/src/transformer.ts | sed -n '1,100p'

Repository: elbwalker/walkerOS

Length of output: 4198


🏁 Script executed:

rg "await useHooks" packages/collector/src -A 2 -B 2

Repository: elbwalker/walkerOS

Length of output: 1379


🏁 Script executed:

rg "Hooks.HookFn|HookFn<" packages/core/src/types -A 3

Repository: elbwalker/walkerOS

Length of output: 335


🏁 Script executed:

cat -n packages/collector/src/transformer.ts | sed -n '150,250p'

Repository: elbwalker/walkerOS

Length of output: 3784


🏁 Script executed:

rg "const configResult = await useHooks" packages/collector/src -A 10 -B 2

Repository: elbwalker/walkerOS

Length of output: 1768


🏁 Script executed:

cat -n packages/collector/src/push.ts | sed -n '40,100p'

Repository: elbwalker/walkerOS

Length of output: 2473


🏁 Script executed:

rg "await useHooks" packages/collector/src -B 2 -A 5

Repository: elbwalker/walkerOS

Length of output: 2105


🏁 Script executed:

rg "type.*HookFn|interface.*HookFn" packages/core/src/types -A 5

Repository: elbwalker/walkerOS

Length of output: 335


🏁 Script executed:

cat -n packages/core/src/types/index.ts | grep -i hook

Repository: elbwalker/walkerOS

Length of output: 102


🏁 Script executed:

cat -n packages/core/src/types/hooks.ts

Repository: elbwalker/walkerOS

Length of output: 859


🏁 Script executed:

rg "preDestinationPush|postDestinationPush|preTransformerPush|postTransformerPush" packages/core/src -A 3 -B 1

Repository: elbwalker/walkerOS

Length of output: 44


🏁 Script executed:

rg "async.*Hook|Hook.*async" packages --type ts -A 2 -B 2 | head -60

Repository: elbwalker/walkerOS

Length of output: 44


🏁 Script executed:

cat -n packages/collector/src/destination.ts | sed -n '200,350p'

Repository: elbwalker/walkerOS

Length of output: 6737


🏁 Script executed:

rg "tryCatchAsync" packages/core/src/types -A 5

Repository: elbwalker/walkerOS

Length of output: 44


🏁 Script executed:

cat -n packages/collector/src/destination.ts | sed -n '340,370p'

Repository: elbwalker/walkerOS

Length of output: 1234


Handle async hook failures and prevent double invocation of wrapped functions.

Lines 40–48 wrap async functions in synchronous try/catch, which cannot catch rejected promises from async hooks. Additionally, line 47 can invoke fn(...args) a second time if a pre-hook calls fn and then throws synchronously, duplicating side effects in non-idempotent operations like external API calls or database writes. Tests cover only synchronous scenarios and do not exercise async hooks or rejections.

The proposed solution correctly detects promise-like results and attaches rejection handlers before falling back, while tracking whether the original function was already called to prevent duplication.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/useHooks.ts` around lines 39 - 58, The preHook/postHook
wrapper currently uses synchronous try/catch which won't catch rejected promises
and may double-invoke fn; update the logic around preHookFn and postHookFn to
detect promise-like returns (e.g., result && typeof result.then === 'function'),
attach a .catch handler to handle async rejections and call warn there, and
avoid immediately calling fn when a preHook returned a promise—instead wait for
the promise to resolve or reject; also introduce a boolean flag (e.g.,
didCallOriginal) scoped with the wrapper to track whether fn(...args) has
already been invoked (so callers inside a preHook can't cause a duplicate call)
and only call fn if !didCallOriginal after resolving the preHook result; apply
the same promise-detection + rejection handling for postHookFn to preserve
original behavior without unhandled rejections.

Comment thread packages/mcps/mcp/src/tools/api.ts
Comment on lines +176 to +190
test('cookie storageWrite does not throw when document.cookie setter throws', () => {
const env = {
document: {
get cookie() {
return '';
},
set cookie(_val: string) {
throw new DOMException('Cookies disabled', 'SecurityError');
},
} as unknown as Document,
};
expect(() =>
storageWrite('k', 'v', 30, 'cookie', undefined, env),
).not.toThrow();
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Assert the cookie write failure return value too.

storageWrite now returns an empty value on write failure; this cookie test only checks that no exception escapes, unlike the local/session cases.

🧪 Proposed test assertion
-    expect(() =>
-      storageWrite('k', 'v', 30, 'cookie', undefined, env),
-    ).not.toThrow();
+    expect(storageWrite('k', 'v', 30, 'cookie', undefined, env)).toBe('');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test('cookie storageWrite does not throw when document.cookie setter throws', () => {
const env = {
document: {
get cookie() {
return '';
},
set cookie(_val: string) {
throw new DOMException('Cookies disabled', 'SecurityError');
},
} as unknown as Document,
};
expect(() =>
storageWrite('k', 'v', 30, 'cookie', undefined, env),
).not.toThrow();
});
test('cookie storageWrite does not throw when document.cookie setter throws', () => {
const env = {
document: {
get cookie() {
return '';
},
set cookie(_val: string) {
throw new DOMException('Cookies disabled', 'SecurityError');
},
} as unknown as Document,
};
expect(storageWrite('k', 'v', 30, 'cookie', undefined, env)).toBe('');
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/web/core/src/__tests__/storage.test.ts` around lines 176 - 190, The
test "cookie storageWrite does not throw when document.cookie setter throws"
currently only ensures no exception escapes; update it to also assert that
storageWrite('k', 'v', 30, 'cookie', undefined, env) returns an empty value on
failure (matching local/session behavior). Locate the test block in
packages/web/core/src/__tests__/storage.test.ts and add an assertion that the
returned value is '' (or the empty return value your implementation uses) after
calling storageWrite, while keeping the existing no-throw expectation.

@github-actions
Copy link
Copy Markdown
Contributor

📦 Pre-release published (next)

Packages

Install: npm i @walkeros/core@next

🐳 Docker images published

  • walkeros/flow:3.4.1-next-1776790594143 (:next)
  • walkeros/cli:3.4.1-next-1776790594143 (:next)

Docker: docker pull walkeros/flow:next

@github-actions
Copy link
Copy Markdown
Contributor

🚀 Stable release published

Packages

Install: npm i @walkeros/core@latest

🐳 Docker images published

  • walkeros/flow:3.4.1 (:latest)
  • walkeros/cli:3.4.1 (:latest)

Docker: docker pull walkeros/flow:latest

@alexanderkirtzel alexanderkirtzel merged commit 5e5c9fc into main Apr 21, 2026
1 check passed
@alexanderkirtzel alexanderkirtzel deleted the 629-step-examples branch April 21, 2026 18:17
@coderabbitai coderabbitai Bot mentioned this pull request Apr 23, 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.

step examples

1 participant