Skip to content

feat(observability): issue triage workflow + durable log read-back - #154

Merged
prisis merged 7 commits into
alphafrom
feat/observability-followons
Jul 21, 2026
Merged

feat(observability): issue triage workflow + durable log read-back#154
prisis merged 7 commits into
alphafrom
feat/observability-followons

Conversation

@prisis

@prisis prisis commented Jul 21, 2026

Copy link
Copy Markdown
Member

Finishes the two actionable observability follow-ons from the gap analysis. (The third — cloud-side trace/log viewers — is blocked: apps/cloud isn't on alpha yet, so there's nothing to wire the viewers into.)

1. Issue triage workflow (@lunora/do + @lunora/studio)

Issues were read-only groupings. Now they carry persisted triage state.

  • New reserved table __lunora_issue_state__ (packages/do/src/issue-state.ts), keyed by fingerprint hash: status (open/resolved/ignored), assignee, severity, updated_at/by. ensureIssueStateTable / readIssueStates (batched WHERE hash IN (…)) / upsertIssueState (partial-patch COALESCE, explicit-null clears).
  • Folded into getIssues (readErrorIssues): each derived Issue joins its state. Auto-reopen — a resolved Issue that errs again after the resolution surfaces as open (a regression never hides behind a stale resolve); ignored stays sticky. A status filter is applied after the fold.
  • Four admin RPCsresolveIssue / ignoreIssue / assignIssue / setIssueSeverity — upsert the state, mark the table changed, and flush so the live admin-wildcard Issues subscription re-folds. Gated by the existing LUNORA_ADMIN_TOKEN bearer.
  • Studio Issues panel gains a status filter, status + severity badges, an inline assignee input (Enter commits; empty unassigns), and per-row Resolve / Ignore / Reopen buttons.

2. Read the durable pipelineLogSink back (@lunora/runtime + @lunora/cli)

The pipeline log sink was write-only.

  • createPipelineLogReader (packages/runtime/src/pipeline-log-reader.ts) queries the Iceberg table via @lunora/bindings/r2sql with keyset pagination (ts DESC) and level / function / trace / shard / user filters. observability-sinks.ts now documents the written-column contract as the read-side mirror and gains an opt-in serializeFields.
  • lunora logs --durable consumes it (added as a mode on the existing logs command, so no command clashes).

Tests

  • @lunora/do: issue-state (6) + request-log fold/auto-reopen/filter cases + shard-do admin — 131 green.
  • @lunora/studio: issues-panel (7) + unit (190) + app-level (28) green.
  • @lunora/runtime: pipeline-log-reader (17) + observability-sinks (57) green.
  • @lunora/cli: logs (5) green.
  • All four packages: lint:types clean, eslint clean (--max-warnings=0).

Note: test:affected surfaces one pre-existing failure unrelated to this branch — tests/vis-templates guards astro at major 6 but the astro template is already on ^7.1.3 on alpha. This branch touches neither file.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added durable log archive querying through the CLI, with filtering, pagination, cursors, and NDJSON output.
    • Added runtime support for reading archived pipeline logs and optionally serializing log fields.
    • Added issue triage controls in Studio, including status, severity, assignee, resolve, ignore, and reopen actions.
  • Documentation
    • Added guidance for configuring and querying durable log archives, including CLI and runtime examples.

prisis and others added 2 commits July 21, 2026 12:52
Add a persisted per-Issue triage state (__lunora_issue_state__), keyed by
fingerprint hash, and fold it into the derived getIssues read: status
(open/resolved/ignored), assignee, and severity. A resolved Issue that errs
again after the resolution auto-reopens to open (regression); ignored stays
sticky. Four admin RPCs (resolveIssue/ignoreIssue/assignIssue/setIssueSeverity)
upsert the state and flush so the live Issues subscription re-folds. The studio
Issues panel gains a status filter, status/severity badges, an assignee input,
and per-row action buttons.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197KjhmBDB3PXAc6TXiPqZ9
Add createPipelineLogReader over the Iceberg table @lunora/bindings/r2sql
queries, with keyset pagination and level/function/trace/shard/user filters, and
wire a `lunora logs --durable` mode to consume it. observability-sinks documents
the written-column contract as the read-side mirror and gains an opt-in
serializeFields. The pipelineLogSink is no longer write-only.

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

netlify Bot commented Jul 21, 2026

Copy link
Copy Markdown

Deploy Preview for lunorash ready!

Name Link
🔨 Latest commit 3900efc
🔍 Latest deploy log https://app.netlify.com/projects/lunorash/deploys/6a5f5cc0fbe2d100088433ae
😎 Deploy Preview https://deploy-preview-154--lunorash.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 6 minutes

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

How can I continue?

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

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

How do review limits work?

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

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

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5a0ca597-9e4f-4ae5-8553-4edbb4dfd346

📥 Commits

Reviewing files that changed from the base of the PR and between 6705e58 and 3900efc.

⛔ Files ignored due to path filters (11)
  • api-snapshots/do.api.md is excluded by none and included by none
  • api-snapshots/lunora.api.md is excluded by none and included by none
  • api-snapshots/runtime.api.md is excluded by none and included by none
  • api-snapshots/studio.api.md is excluded by none and included by none
  • packages/do/__tests__/issue-state.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • plans/165-push-notifications.md is excluded by none and included by none
  • plans/166-enterprise-auth-saml-scim.md is excluded by none and included by none
  • plans/170-cdc-export-tap.md is excluded by none and included by none
  • plans/171-non-goals-docs-page.md is excluded by none and included by none
  • plans/README.md is excluded by none and included by none
  • tests/vis-templates/__tests__/templates.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by none
📒 Files selected for processing (1)
  • packages/do/src/issue-state.ts

Walkthrough

This PR adds R2 SQL-backed durable log archive reading through runtime APIs and the CLI, documents archive setup, and introduces persisted issue triage with admin RPCs, status filtering, and Studio controls.

Changes

Durable log archive

Layer / File(s) Summary
Log archive contract and reader
packages/runtime/src/observability-sinks.ts, packages/runtime/src/pipeline-log-reader.ts, packages/runtime/src/index.ts, packages/runtime/package.json
Pipeline logs can serialize fields; the runtime exports a reader that maps columns, decodes rows, applies filters, and paginates with ts DESC keyset cursors.
Durable logs CLI path
packages/cli/src/commands/logs/*, packages/cli/package.json
lunora logs --durable validates options and R2 SQL configuration, queries the archive, and renders table or NDJSON output with pagination feedback.
Durable archive documentation
apps/docs/src/content/docs/concepts/observability.mdx
Documents table schema, credentials, serialization, column mapping, reader usage, CLI filters, and cursor pagination.

Issue triage workflow

Layer / File(s) Summary
Persisted issue-state model
packages/do/src/issue-state.ts
Adds issue status/severity types and SQL-backed state creation, reads, partial updates, clearing, and hydration.
Issue-state folding and admin contracts
packages/do/src/request-log.ts, packages/do/src/introspect.ts
Error issues now include persisted triage fields, auto-reopen resolved issues after newer errors, support status filtering, and register triage RPC paths.
Issue triage admin operations
packages/do/src/shard-do.ts
Adds validation and dispatch for resolve, ignore, assign, and severity updates, then persists and flushes changed issue state.
Studio issue triage controls
packages/studio/src/features/issues/issues-panel.tsx, packages/studio/src/lib/admin.ts, packages/studio/src/locales/en.ts
Adds typed triage contracts, status filters, severity and assignee editing, action buttons, busy/error states, and localized labels.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant DurableLogsCLI
  participant PipelineLogReader
  participant R2SQL
  Operator->>DurableLogsCLI: run lunora logs --durable
  DurableLogsCLI->>PipelineLogReader: submit filters and cursor
  PipelineLogReader->>R2SQL: execute escaped SQL query
  R2SQL-->>PipelineLogReader: ordered log page
  PipelineLogReader-->>DurableLogsCLI: rows and nextCursor
  DurableLogsCLI-->>Operator: table or NDJSON output
Loading
sequenceDiagram
  participant IssuesPanel
  participant ShardDO
  participant IssueStateTable
  IssuesPanel->>ShardDO: resolve, ignore, assign, or set severity
  ShardDO->>IssueStateTable: upsert issue state
  IssueStateTable-->>ShardDO: updated state
  ShardDO-->>IssuesPanel: triage result
  IssuesPanel->>ShardDO: request issues with status filter
  ShardDO-->>IssuesPanel: filtered issues with persisted triage fields
Loading

Possibly related PRs

  • anolilab/lunora#138: Extends the grouped Issues pipeline and Studio issue display that this PR adds triage state to.
  • anolilab/lunora#147: Shares the pipeline log sink and observability documentation that this PR extends with durable archive reading.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the main changes and tests, but it omits required template sections and the exact CLA statement. Add the missing template sections: Linked issues, full Test plan checklist, Checklist, Notes for reviewers, and the exact CLA statement.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the two main additions: issue triage workflow and durable log read-back.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/observability-followons

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.

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for following the naming conventions! 🙏

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for confirming the Contributor License Agreement! 🙏

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 3900efc.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/do/src/issue-state.ts`:
- Around line 123-144: Update readIssueStates to process hashes in batches of no
more than 100 parameters, executing one query per batch and merging each
hydrated row into the existing states Map. Preserve the empty-input early return
and ensure all requested hashes are covered without exceeding the parameter
limit.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 28e29cac-ffc9-4e76-96f7-fbeb00bfd5c4

📥 Commits

Reviewing files that changed from the base of the PR and between 089511d and 6705e58.

⛔ Files ignored due to path filters (6)
  • packages/do/__tests__/issue-state.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/do/__tests__/request-log.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/runtime/__tests__/observability-sinks.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/runtime/__tests__/pipeline-log-reader.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/studio/__tests__/features/issues/issues-panel.test.tsx is excluded by !**/__tests__/** and included by packages/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
📒 Files selected for processing (16)
  • apps/docs/src/content/docs/concepts/observability.mdx
  • packages/cli/package.json
  • packages/cli/src/commands/logs/durable.ts
  • packages/cli/src/commands/logs/handler.ts
  • packages/cli/src/commands/logs/index.ts
  • packages/do/src/introspect.ts
  • packages/do/src/issue-state.ts
  • packages/do/src/request-log.ts
  • packages/do/src/shard-do.ts
  • packages/runtime/package.json
  • packages/runtime/src/index.ts
  • packages/runtime/src/observability-sinks.ts
  • packages/runtime/src/pipeline-log-reader.ts
  • packages/studio/src/features/issues/issues-panel.tsx
  • packages/studio/src/lib/admin.ts
  • packages/studio/src/locales/en.ts

Comment thread packages/do/src/issue-state.ts
@codspeed-hq

codspeed-hq Bot commented Jul 21, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 0.39%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 2 improved benchmarks
❌ 1 regressed benchmark
✅ 157 untouched benchmarks
⏩ 1 skipped benchmark1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
sum merge: 4 scalars 1.4 ms 1.8 ms -19.41%
union: single UNION-ALL probe across all tables 235.3 µs 212.2 µs +10.87%
baseline (Object.keys + toInternal + path spread per field) 72 µs 65.1 µs +10.63%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing feat/observability-followons (3900efc) with alpha (b16cc0e)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

Durable Objects SQLite caps bound parameters at 100 per query. A shard with
>100 distinct issue fingerprints would blow the cap on the single
`WHERE hash IN (?…)` read, failing getIssues. Read in 100-hash chunks and merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197KjhmBDB3PXAc6TXiPqZ9
The astro template is on `astro@^7.1.3` but LATEST_MAJORS still pinned the guard
to 6, reddening the templates suite. Bump the guard to match the template.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197KjhmBDB3PXAc6TXiPqZ9
These landed via #151 (merged into this branch) with unwrapped prose that
`prettier --check .` rejects, reddening the repo-wide prettier pipe. Format-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197KjhmBDB3PXAc6TXiPqZ9
Records the intended surface additions: the four issue-triage ADMIN_FUNCTIONS +
issue types (do, studio), and createPipelineLogReader / DEFAULT_LOG_COLUMNS +
types (runtime, re-exported by lunora). Additions only, no removals.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197KjhmBDB3PXAc6TXiPqZ9
@prisis
prisis merged commit fe1028b into alpha Jul 21, 2026
41 of 42 checks passed
@prisis
prisis deleted the feat/observability-followons branch July 21, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant