Skip to content

fix(automation): region-aware run-history compaction keeps loop containers + early failures (#3234)#3240

Merged
os-zhuang merged 2 commits into
mainfrom
claude/step-logs-run-observability-plxc2p
Jul 18, 2026
Merged

fix(automation): region-aware run-history compaction keeps loop containers + early failures (#3234)#3240
os-zhuang merged 2 commits into
mainfrom
claude/step-logs-run-observability-plxc2p

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #1505 (region step logs). AutomationEngine.compactStepsForHistory() bounded a terminal run's persisted step log to the last MAX_PERSISTED_HISTORY_STEPS entries with a plain tail-slice. With the ADR-0031 structured-region step logs, a single loop can now emit iterations × body-steps entries, so the tail-slice:

  • dropped the loop/parallel/try_catch container step (it precedes all its body steps), leaving getRun/listRuns — served from durable history after a restart or ring-buffer eviction — with body steps the Runs surface (objectui FlowRunsPanel) could no longer nest; and
  • silently hid an early failure (e.g. iteration 2 of 500), the single most useful thing about a failed run.

The fix

New exported, region-aware compactStepLogForHistory (the private method delegates to it). Under budget the log is kept whole (stacks stripped) — unchanged. Over budget it selects a bounded, order-preserving subset that keeps the run's structural backbone:

  1. every top-level step (parentNodeId === undefined) — start/end, main-graph nodes, and the region container steps (bounded by the flow's static node count, not by loop iterations);
  2. every failure, wherever it occurred, each pulled in with its ancestor container chain for context;
  3. the most recent body steps (what the run was doing when it ended), each also with its ancestor chain.

Every retained body step therefore keeps its enclosing container(s) — so the compacted log never contains an orphan and the observability surface's per-iteration / per-region nesting still reconstructs — and the result is hard-capped at max, so steps_json stays bounded (#2585). Parent lookup is O(n) via a running last-seen-index map (the same "nearest preceding container instance" that FlowRunsPanel.buildStepTree nests under).

Verification

  • run-history.test.ts14/14 pass (7 new: cap, container/backbone retention, recent-iteration tail, early-failure retention, order preservation, nested-container no-orphan).
  • Full @objectstack/service-automation suite — 326/326 pass (no regression).
  • tsup build incl. DTS typecheck — pass. ESLint — clean.
  • Changeset: @objectstack/service-automation minor.

Closes #3234.

🤖 Generated with Claude Code


Generated by Claude Code

…iners + early failures (#3234)

`compactStepsForHistory` bounded a terminal run's persisted step log to the last
`MAX_PERSISTED_HISTORY_STEPS` entries with a plain tail-slice. With the ADR-0031
structured-region step logs (#1505) a single `loop` can emit
`iterations × body-steps` entries, so the tail-slice dropped the
`loop`/`parallel`/`try_catch` container step (it precedes all its body steps) and
every early iteration — leaving `getRun`/`listRuns` (after a restart or
ring-buffer eviction) with body steps the Runs surface could no longer nest, and
silently hiding an early failure.

Introduce an exported, region-aware `compactStepLogForHistory`; the private
method now delegates to it. Over budget it keeps the run's structural backbone —
every top-level step (including the region container steps) and every failure,
each pulled in with its ancestor container chain — plus the most recent body
steps, order-preserving and hard-capped at `max` so `steps_json` stays bounded
(#2585). Every retained body step keeps its enclosing container(s), so the
compacted log never contains an orphan and the observability surface's
per-iteration / per-region nesting still reconstructs. Under budget behavior is
unchanged (whole log, stacks stripped).

Adds 7 unit tests (cap, container/backbone retention, recent-iteration tail,
early-failure retention, order preservation, nested-container no-orphan).

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

vercel Bot commented Jul 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Canceled Canceled Jul 18, 2026 5:15pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): packages/services.

6 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/automation/webhooks.mdx (via packages/services)
  • content/docs/kernel/runtime-services/audit-service.mdx (via packages/services)
  • content/docs/kernel/runtime-services/index.mdx (via packages/services)
  • content/docs/kernel/runtime-services/settings-service.mdx (via packages/services)
  • content/docs/plugins/packages.mdx (via packages/services)
  • content/docs/protocol/kernel/i18n-standard.mdx (via packages/services)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…g in flows.mdx

The "Runs" section still described run history as an in-memory ring buffer whose
`sys_automation_run` rows "hold only live pauses", so "history starts fresh on
each boot". That predates the durable terminal run history (#2585): terminal
runs (completed / failed) are mirrored to `sys_automation_run` with a bounded
step log, and `listRuns` / `getRun` merge it so a run's status / steps / failure
reason survive a restart or ring-buffer eviction. Also note the Studio Runs
panel now nests body steps by iteration / branch / handler (#1505, objectui
#2667). Surfaced by the docs-drift check on #3240.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VuvxWgoadqryqBcjs7TpVi
@os-zhuang
os-zhuang marked this pull request as ready for review July 18, 2026 20:43
@os-zhuang
os-zhuang merged commit 1e145eb into main Jul 18, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/step-logs-run-observability-plxc2p branch July 18, 2026 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Long-loop run history truncation drops container + early-iteration step logs (compactStepsForHistory)

2 participants