Skip to content

surface ctx.getHistory() -> { size, stepCount }#206

Open
ianmacartney wants to merge 7 commits intomainfrom
ian/get-history
Open

surface ctx.getHistory() -> { size, stepCount }#206
ianmacartney wants to merge 7 commits intomainfrom
ian/get-history

Conversation

@ianmacartney
Copy link
Copy Markdown
Member

@ianmacartney ianmacartney commented Feb 19, 2026

Adds workflow history tracking with a new ctx.getHistory() method to monitor workflow execution metrics.

Fixes #178

What changed?

  • Refactored StepExecutor to track workflow execution metrics:
    • Replaced journalEntrySize with journalSize and added stepCount to track both total size and number of steps
    • Added a getHistory() method that returns these metrics
    • Modified journal size tracking to increment as steps are processed rather than calculating upfront
  • Exposed the history tracking functionality to workflow context:
    • Added a getHistory() method to the WorkflowCtx type
    • Updated the createWorkflowCtx function to accept and expose the history getter

How to test?

  1. Create a workflow that calls ctx.getHistory()
  2. Run the workflow and verify it returns an object with size and stepCount properties
  3. Run multiple steps in the workflow and check that the metrics increase appropriately
  4. Verify that journal size limits are still enforced correctly

Why make this change?

This change provides developers with visibility into workflow execution metrics, allowing them to monitor the size and complexity of their workflows. This is particularly useful for debugging performance issues and preventing workflows from hitting size limits unexpectedly. The incremental tracking approach is also more efficient than calculating the entire journal size upfront.

Summary by CodeRabbit

  • New Features

    • Exposed getHistory() on workflow context to read current journal size and step count during execution.
  • Documentation

    • Emphasized 8MiB journal-size guidance, added a monitoring tip and polling example for early exit based on size/stepCount, and reflowed README text for readability.
  • Examples

    • Added a workflow example that logs execution-history metrics and demonstrates step calls.
  • Tests

    • Updated tests to include getHistory() in workflow context setup.
  • Chore

    • Clarified a console message and a CI publish-step message.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 19, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds runtime history introspection: StepExecutor now tracks incremental journalSize and stepCount, exposes getHistory() wired into WorkflowCtx.meta.getHistory, README/docs include a polling example, and an example workflow demonstrates reading history during execution.

Changes

Cohort / File(s) Summary
Documentation & examples
README.md, example/convex/README.md, example/convex/historyExample.ts
README: reflowed text, bolded 8MiB journal-size note, added a TypeScript polling "Tip" showing step.meta.getHistory(); added historyExample.ts demonstrating repeated history reads and returning final metrics.
Core executor
src/client/step.ts
Replace constructor precompute with incremental journalSize and stepCount; update completeMessage to increment counters; enforce MAX_JOURNAL_SIZE during startSteps; add public getHistory() returning { size, stepCount }.
Context & wiring
src/client/workflowContext.ts, src/client/workflowMutation.ts
Add meta.getHistory to WorkflowCtx and extend createWorkflowCtx to accept a getHistory callback; workflowMutation creates StepExecutor earlier and passes executor.getHistory.bind(executor) into context.
Tests
src/client/stepContext.test.ts
Update tests to call createWorkflowCtx(workflowId, channel, reporter) with a getHistory callback returning { size: 0, stepCount: 0 } across test cases.
Minor & CI
example/convex/nestedWorkflow.ts, .github/workflows/test.yml
Small console.log string change in nestedWorkflow; CI step failure message adjusted in test.yml.

Sequence Diagram(s)

sequenceDiagram
  participant Workflow as Workflow Handler
  participant Ctx as WorkflowCtx
  participant Channel as BaseChannel
  participant Executor as StepExecutor

  Workflow->>Ctx: ctx.meta.getHistory()
  Ctx->>Executor: getHistory()
  Executor-->>Ctx: { size, stepCount }
  Ctx-->>Workflow: { size, stepCount }

  Workflow->>Ctx: runMutation / runAction
  Ctx->>Channel: send StepRequest
  Channel->>Executor: deliver JournalEntry(s)
  Executor->>Executor: increment journalSize & stepCount (per entry)
  Executor-->>Ctx: updated history available via getHistory()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • sethconvex
  • goffrie
  • reeceyang

Poem

🐰 I counted bytes and hopped through night,

Steps and sizes glowing soft and bright,
I asked the ctx, "How far am I?"
It hummed me counts of steps and size,
A tiny ledger for a rabbit's flight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: exposing a getHistory() method that returns {size, stepCount} for monitoring workflow execution metrics.
Linked Issues check ✅ Passed All coding requirements from issue #178 are met: workflow context now exposes getHistory() to observe history size/step metrics, enabling developers to detect when approaching limits and fork to child workflows.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the getHistory() feature: StepExecutor refactoring, WorkflowCtx updates, example code, documentation, tests, and minor log message updates are all in scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ian/get-history

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 and usage tips.

Copy link
Copy Markdown
Member Author

ianmacartney commented Feb 19, 2026

@ianmacartney ianmacartney marked this pull request as ready for review February 19, 2026 06:02
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Feb 19, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@convex-dev/workflow@206

commit: 3f18038

@ianmacartney ianmacartney force-pushed the ian/resume branch 2 times, most recently from acee365 to b7fdb37 Compare March 3, 2026 23:38
@ianmacartney ianmacartney changed the base branch from ian/resume to graphite-base/206 March 6, 2026 01:38
@ianmacartney ianmacartney changed the base branch from graphite-base/206 to ian/resume March 6, 2026 01:40
@ianmacartney ianmacartney changed the base branch from ian/resume to graphite-base/206 March 21, 2026 04:29
@ianmacartney ianmacartney changed the base branch from graphite-base/206 to main March 21, 2026 04:29
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.

Caution

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

⚠️ Outside diff range comments (1)
src/client/step.ts (1)

226-235: ⚠️ Potential issue | 🟠 Major

Double-counting issue for inline-completed steps.

When startSteps returns entries that complete inline (i.e., entry.step.runResult is set), the counters are incremented here at lines 227-228. However, the caller at lines 82-85 then calls completeMessage for each of these entries, which increments the counters again at lines 119-120. This results in double-counting both stepCount and journalSize for inline-completed steps.

🐛 Proposed fix: skip counting in startSteps for inline-completed entries
     const entries = (await this.ctx.runMutation(
       this.component.journal.startSteps,
       {
         workflowId: this.workflowId,
         generationNumber: this.generationNumber,
         steps,
         workpoolOptions: this.workpoolOptions,
       },
     )) as JournalEntry[];
     for (const entry of entries) {
-      this.stepCount++;
-      this.journalSize += getConvexSize(entry);
+      // Only count entries that won't go through completeMessage
+      // (i.e., entries that are still in progress)
+      if (entry.step.inProgress) {
+        this.stepCount++;
+        this.journalSize += getConvexSize(entry);
+      }
       if (this.journalSize > MAX_JOURNAL_SIZE) {
         throw new Error(
           journalSizeError(this.journalSize, this.workflowId) +
             ` The failing step was ${entry.step.name} (${entry._id})`,
         );
       }
     }

Alternatively, you could move the size check before the conditional increment, but you'd need to compute the size regardless of whether you're tracking it.

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

In `@src/client/step.ts` around lines 226 - 235, The loop in startSteps that
increments this.stepCount and this.journalSize double-counts entries that
completed inline because completeMessage also increments those counters; update
the loop in startSteps to skip the counter increments for entries where
entry.step.runResult is already set (i.e., treat inline-completed entries as
already-counted) so only non-inline-started entries update
this.stepCount/this.journalSize, leaving completeMessage unchanged.
🧹 Nitpick comments (1)
README.md (1)

777-791: Consider using consistent naming for the workflow context.

Throughout this README, the workflow handler uses step as the context parameter name (e.g., line 50: handler: async (step, args)), but this tip example uses ctx. For consistency with the rest of the documentation, consider renaming ctx to step:

📝 Suggested diff for consistency
 while (true) {
-  const result = await ctx.runAction(
+  const result = await step.runAction(
     internal.example.pollForResult,
     { id },
     { runAfter: 1000 }, // Poll every second
   );
   if (result !== null) {
     return result;
   }
-  const { stepCount, size } = ctx.getHistory();
+  const { stepCount, size } = step.getHistory();
   if (stepCount > 100 || size > 2_000_000) {
     return null;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 777 - 791, Rename the workflow context variable from
ctx to step in this example to match the rest of the README: change the
parameter name and all usages so internal.example.pollForResult is invoked via
step.runAction(...) and the history check uses step.getHistory(); ensure you
update the loop variables and any references (result, id, stepCount, size) to
use the renamed context symbol consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/client/step.ts`:
- Around line 226-235: The loop in startSteps that increments this.stepCount and
this.journalSize double-counts entries that completed inline because
completeMessage also increments those counters; update the loop in startSteps to
skip the counter increments for entries where entry.step.runResult is already
set (i.e., treat inline-completed entries as already-counted) so only
non-inline-started entries update this.stepCount/this.journalSize, leaving
completeMessage unchanged.

---

Nitpick comments:
In `@README.md`:
- Around line 777-791: Rename the workflow context variable from ctx to step in
this example to match the rest of the README: change the parameter name and all
usages so internal.example.pollForResult is invoked via step.runAction(...) and
the history check uses step.getHistory(); ensure you update the loop variables
and any references (result, id, stepCount, size) to use the renamed context
symbol consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 34df3b59-5cdc-4b9f-96c7-ee761b1cb340

📥 Commits

Reviewing files that changed from the base of the PR and between 6a348a5 and 3a5d0a0.

⛔ Files ignored due to path filters (1)
  • example/convex/_generated/api.d.ts is excluded by !**/_generated/**
📒 Files selected for processing (6)
  • README.md
  • example/convex/historyExample.ts
  • example/convex/nestedWorkflow.ts
  • src/client/step.ts
  • src/client/workflowContext.ts
  • src/client/workflowMutation.ts

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

🧹 Nitpick comments (1)
src/client/step.ts (1)

98-106: Improve getHistory() JSDoc to document the stepCount/size asymmetry.

The current JSDoc for getHistory() in workflowContext.ts (lines 130-132) doesn't explain why stepCount includes pending steps in the buffer while size reflects only finished steps. The in-code comment (lines 100-102) documents this well, but it should also be reflected in the public API documentation:

/**
 * Get the current history of the workflow execution.
 *
 * `@returns` The size in bytes and number of steps processed so far.
 * Note: size reflects only finished steps, while stepCount includes pending steps in the buffer.
 */
getHistory: () => { size: number; stepCount: number };

Alternatively, consider making both metrics consistent (both include or exclude pending steps) to avoid surprises for callers.

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

In `@src/client/step.ts` around lines 98 - 106, Update the public JSDoc for
getHistory in workflowContext.ts to document the asymmetry between size and
stepCount: state that size reflects only finished steps (journalSize) while
stepCount includes pending buffered steps (this.receiver.bufferSize added to
this.stepCount); modify the comment above getHistory() to match the in-code note
in src/client/step.ts and clearly describe which metric includes pending steps
so callers aren't surprised.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/client/workflowContext.ts`:
- Around line 128-132: The JSDoc for the getHistory accessor is missing the
opening /** delimiter which breaks parsing; update the comment above getHistory
(the JSDoc block that currently starts with "*" before getHistory) to start with
"/**" so it becomes a valid JSDoc comment for the getHistory: () => { size:
number; stepCount: number } declaration.

---

Nitpick comments:
In `@src/client/step.ts`:
- Around line 98-106: Update the public JSDoc for getHistory in
workflowContext.ts to document the asymmetry between size and stepCount: state
that size reflects only finished steps (journalSize) while stepCount includes
pending buffered steps (this.receiver.bufferSize added to this.stepCount);
modify the comment above getHistory() to match the in-code note in
src/client/step.ts and clearly describe which metric includes pending steps so
callers aren't surprised.
🪄 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: f2180424-47b7-448d-a2ad-4870022b0753

📥 Commits

Reviewing files that changed from the base of the PR and between 3a5d0a0 and 68ab18d.

⛔ Files ignored due to path filters (1)
  • example/convex/_generated/api.d.ts is excluded by !**/_generated/**
📒 Files selected for processing (6)
  • README.md
  • example/convex/historyExample.ts
  • example/convex/nestedWorkflow.ts
  • src/client/step.ts
  • src/client/workflowContext.ts
  • src/client/workflowMutation.ts
✅ Files skipped from review due to trivial changes (1)
  • example/convex/nestedWorkflow.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • example/convex/historyExample.ts

Comment thread src/client/workflowContext.ts Outdated
@ianmacartney ianmacartney force-pushed the ian/get-history branch 2 times, most recently from 0372be7 to 2f7161a Compare March 28, 2026 00:16
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.

🧹 Nitpick comments (2)
example/convex/historyExample.ts (1)

9-28: Optional: reduce repeated history snapshot logging boilerplate.

The repeated getHistory() + console.log pattern can be factored into a tiny helper to keep the example tighter.

♻️ Suggested cleanup
 export const historyWorkflow = workflow.define({
   args: {},
   handler: async (ctx) => {
-    const h0 = ctx.getHistory();
-    console.log(`Before any steps: ${h0.stepCount} steps, ${h0.size} bytes`);
+    const logHistory = (label: string) => {
+      const h = ctx.getHistory();
+      console.log(`${label}: ${h.stepCount} steps, ${h.size} bytes`);
+      return h;
+    };
+    const h0 = logHistory("Before any steps");
@@
-    const h1 = ctx.getHistory();
-    console.log(`After step 1: ${h1.stepCount} steps, ${h1.size} bytes`);
+    const h1 = logHistory("After step 1");
@@
-    const h2 = ctx.getHistory();
-    console.log(`After step 2: ${h2.stepCount} steps, ${h2.size} bytes`);
+    const h2 = logHistory("After step 2");
@@
-    const h3 = ctx.getHistory();
-    console.log(`After step 3: ${h3.stepCount} steps, ${h3.size} bytes`);
+    const h3 = logHistory("After step 3");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@example/convex/historyExample.ts` around lines 9 - 28, Factor the repeated
ctx.getHistory() + console.log boilerplate into a small helper function (e.g.,
logHistory or printHistory) and call it before/after each step; locate
occurrences around getHistory() and the runMutation/runAction calls (references:
ctx.getHistory(), ctx.runMutation(internal.historyExample.smallStep),
ctx.runAction(internal.historyExample.mediumStep), variables h0,h1,h2,h3) and
replace the four manual snapshots with calls to the helper that accepts a label
like "Before any steps" / "After step 1" etc., returning or discarding the
History object as needed.
src/client/stepContext.test.ts (1)

100-103: Refactor repeated history stub + add one direct passthrough assertion.

Using a shared stub will reduce duplication, and adding a focused assertion on ctx.getHistory() will explicitly cover the new API wiring.

♻️ Suggested test cleanup and coverage bump
+const zeroHistory = () => ({ size: 0, stepCount: 0 });
+
 describe("StepExecutor + WorkflowCtx integration", () => {
+  it("exposes getHistory from injected callback", () => {
+    const channel = new BaseChannel<StepRequest>(0);
+    const ctx = createWorkflowCtx("wf-history" as any, channel, () => ({
+      size: 12,
+      stepCount: 3,
+    }));
+    expect(ctx.getHistory()).toEqual({ size: 12, stepCount: 3 });
+  });
+
   it("resolves a successful step", async () => {
     const channel = new BaseChannel<StepRequest>(0);
-    const ctx = createWorkflowCtx("wf-1" as any, channel, () => ({
-      size: 0,
-      stepCount: 0,
-    }));
+    const ctx = createWorkflowCtx("wf-1" as any, channel, zeroHistory);

(Apply zeroHistory replacement to the remaining test cases as well.)

Also applies to: 120-123, 141-144, 162-165, 198-201, 238-241, 275-278, 313-316, 339-342, 359-362

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

In `@src/client/stepContext.test.ts` around lines 100 - 103, Introduce a shared
history stub (e.g., zeroHistory) and use it when constructing the test contexts
instead of repeating inline { size: 0, stepCount: 0 } in createWorkflowCtx
calls; update the instantiation at the shown diff (createWorkflowCtx("wf-1",
channel, () => ({ size: 0, stepCount: 0 }))) to pass the shared zeroHistory
object via the factory, then add a direct assertion that ctx.getHistory() ===
zeroHistory to verify passthrough wiring; apply the same replacement to the
other repeated occurrences (lines referenced in the review) so all tests use the
shared stub and include the explicit ctx.getHistory() equality check.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@example/convex/historyExample.ts`:
- Around line 9-28: Factor the repeated ctx.getHistory() + console.log
boilerplate into a small helper function (e.g., logHistory or printHistory) and
call it before/after each step; locate occurrences around getHistory() and the
runMutation/runAction calls (references: ctx.getHistory(),
ctx.runMutation(internal.historyExample.smallStep),
ctx.runAction(internal.historyExample.mediumStep), variables h0,h1,h2,h3) and
replace the four manual snapshots with calls to the helper that accepts a label
like "Before any steps" / "After step 1" etc., returning or discarding the
History object as needed.

In `@src/client/stepContext.test.ts`:
- Around line 100-103: Introduce a shared history stub (e.g., zeroHistory) and
use it when constructing the test contexts instead of repeating inline { size:
0, stepCount: 0 } in createWorkflowCtx calls; update the instantiation at the
shown diff (createWorkflowCtx("wf-1", channel, () => ({ size: 0, stepCount: 0
}))) to pass the shared zeroHistory object via the factory, then add a direct
assertion that ctx.getHistory() === zeroHistory to verify passthrough wiring;
apply the same replacement to the other repeated occurrences (lines referenced
in the review) so all tests use the shared stub and include the explicit
ctx.getHistory() equality check.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b6a67fdc-7ec2-4f20-9ba0-7152941ed071

📥 Commits

Reviewing files that changed from the base of the PR and between 68ab18d and 2f7161a.

⛔ Files ignored due to path filters (1)
  • example/convex/_generated/api.d.ts is excluded by !**/_generated/**
📒 Files selected for processing (9)
  • .github/workflows/test.yml
  • README.md
  • example/convex/README.md
  • example/convex/historyExample.ts
  • example/convex/nestedWorkflow.ts
  • src/client/step.ts
  • src/client/stepContext.test.ts
  • src/client/workflowContext.ts
  • src/client/workflowMutation.ts
✅ Files skipped from review due to trivial changes (3)
  • .github/workflows/test.yml
  • example/convex/README.md
  • example/convex/nestedWorkflow.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/client/workflowMutation.ts
  • src/client/workflowContext.ts
  • README.md
  • src/client/step.ts

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 `@example/convex/historyExample.ts`:
- Around line 9-28: The calls to ctx.getHistory() are using the wrong API;
replace each ctx.getHistory() with ctx.meta.getHistory() so the history is
accessed from the meta object. Update the four occurrences after the initial h0,
h1, h2, and h3 captures (surrounding the ctx.runMutation calls that use
internal.historyExample.smallStep and the ctx.runAction call that uses
internal.historyExample.mediumStep) to call ctx.meta.getHistory() instead,
leaving the surrounding runMutation/runAction invocations and log statements
unchanged.
🪄 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: 06f0a18e-6c5d-4586-b1bb-4c77a637b598

📥 Commits

Reviewing files that changed from the base of the PR and between 2f7161a and 2674a10.

⛔ Files ignored due to path filters (1)
  • example/convex/_generated/api.d.ts is excluded by !**/_generated/**
📒 Files selected for processing (9)
  • .github/workflows/test.yml
  • README.md
  • example/convex/README.md
  • example/convex/historyExample.ts
  • example/convex/nestedWorkflow.ts
  • src/client/step.ts
  • src/client/stepContext.test.ts
  • src/client/workflowContext.ts
  • src/client/workflowMutation.ts
✅ Files skipped from review due to trivial changes (4)
  • .github/workflows/test.yml
  • example/convex/README.md
  • example/convex/nestedWorkflow.ts
  • src/client/stepContext.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • README.md
  • src/client/workflowContext.ts
  • src/client/step.ts

Comment thread example/convex/historyExample.ts Outdated
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.

Get workflow history step size/length from WorkflowCtx

1 participant