Skip to content

feat: add Checks system for YAML workflow execution - #84

Open
Ziinc wants to merge 6 commits into
mainfrom
claude/checks-yaml-workflows-72iq7u
Open

feat: add Checks system for YAML workflow execution#84
Ziinc wants to merge 6 commits into
mainfrom
claude/checks-yaml-workflows-72iq7u

Conversation

@Ziinc

@Ziinc Ziinc commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Implements a Checks tab in ShowWorkspace that reads workflow definitions
from .treq/workflows/*.yaml and allows manual job execution with per-step
pass/fail results.

Core

  • core/checks.rs: business logic for listing and running workflows, with
    bounded-concurrency job execution and DB persistence of results
  • commands/checks.rs: Tauri command wrappers (list_workflows,
    run_workflow_job, run_workflow, is_repo_trusted, trust_repo)
  • local_db.rs: workflow_runs table for persisting job results, plus a
    repo_trust table backing the execution guard
  • NAPI dispatch: new arms so JS integration tests exercise real Rust code

Security

  • Trusted-repository guard: running any job requires the repo to be
    explicitly trusted first; untrusted repos surface a banner and disabled
    run buttons instead of silently executing repository-defined commands
  • Path containment: workflow filenames reject path separators and ..,
    and resolved paths are canonicalized and confirmed to stay inside
    .treq/workflows/
  • Step working-directory values reject absolute paths and parent
    traversal
  • Invalid YAML files are skipped rather than failing the whole listing

Execution

  • Bounded concurrency (max 4 concurrent jobs) instead of unbounded
    thread-per-job spawning
  • Per-step timeout (60s) that kills the child process on expiry
  • Fail-fast: a failed step stops the remaining steps in that job

Frontend

  • ChecksTab.tsx: per-job and per-workflow Run buttons, step-level
    pass/fail icons, and the trust banner
  • ShowWorkspace.tsx: new Checks tab trigger and content panel
  • api.ts / api-types.ts: TypeScript types and invoke wrappers

Tests

  • Rust unit tests (15), Rust integration tests (7), JS integration tests (6)
  • scripts/screenshot/specs/checks-tab.spec.tsx covering the trust gate,
    the enabled-after-trust state, and per-step pass/fail rendering

Follow-up (not in this PR)

  • Historical run retrieval and display
  • stdout/stderr capture and output truncation
  • Workflow format documentation

claude added 3 commits July 26, 2026 11:14
Implements a Checks tab in ShowWorkspace that reads workflow definitions
from .treq/workflows/*.yaml and allows manual job execution with per-step
pass/fail results.

- core/checks.rs: business logic for listing and running workflows, with
  parallel job execution via std::thread and DB persistence of results
- commands/checks.rs: Tauri command wrappers (list_workflows,
  run_workflow_job, run_workflow)
- local_db.rs: workflow_runs table for persisting job results
- NAPI dispatch: three new arms so JS integration tests use real Rust code
- ChecksTab.tsx: React component with per-job and per-workflow Run buttons,
  step-level pass/fail icons (data-testid for test queries)
- ShowWorkspace.tsx: new Checks tab trigger and content panel
- api.ts / api-types.ts: TypeScript types and invoke wrappers
- Rust unit tests (9), Rust integration tests (7), JS integration tests (6)
- Add explicit repository trust requirement before running any workflow
  job; untrusted repos see a UI banner with a "Trust Repository" button
- Validate workflow filenames (reject path separators and '..') and
  working-directory values (reject absolute paths and parent traversal)
  to prevent path escape from .treq/workflows/
- Canonicalize file paths and confirm containment within the workflows
  directory before reading or executing any workflow file
- Skip invalid YAML files when listing workflows instead of failing the
  entire listing call
- Replace unbounded thread spawning in run_workflow with a bounded
  executor (MAX_CONCURRENT_JOBS = 4) using a channel semaphore pattern
- Add per-step timeout (STEP_TIMEOUT_SECS = 60) with polling loop; kills
  the child process and returns a timeout error on expiry
- Switch step execution from cmd.output() to spawn() + Stdio::null() for
  safe stdin handling in the NAPI/test context while enabling timeout
- Add repo_trust table to local.db; add is_repo_trusted / trust_repo
  functions in local_db, Tauri commands, and NAPI dispatch
- Update JS integration tests to pre-trust repos before running jobs
- Update Rust integration tests to call trust_repo before execution tests
- Add new unit tests: trust guard, path traversal rejection, invalid YAML
  skip, filename and working-directory validation
- Apply biome/cargo formatting to satisfy the verify CI job
- Hoist userEvent.setup() into a beforeEach hook in the checks
  integration test, per the local/user-event-setup-in-setup lint rule
- Remove unused get_latest_workflow_run and the now-orphaned
  WorkflowRunRecord struct, flagged by local/no-unused-pub-rust-functions;
  historical run retrieval is follow-up work with no caller yet
- Add scripts/screenshot/specs/checks-tab.spec.tsx covering the trust
  gate, enabled-after-trust state, and per-step pass/fail rendering
@Ziinc
Ziinc force-pushed the claude/checks-yaml-workflows-72iq7u branch from ed8928b to 172326f Compare July 26, 2026 11:25
@Ziinc Ziinc changed the title Add Checks system for YAML workflow execution feat: add Checks system for YAML workflow execution Jul 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📸 App QA screenshots

Re-ran the flow whose spec this PR adds or modifies — 3 captures. Other specs in the library were not run.

⬇️ Download the screenshots

checks-tab
  • checks-tab-01-untrusted.png
    • An amber/yellow warning banner is visible reading "Trust this repository to enable running workflow checks." with a "Trust Repository" button on its right.
    • The workflow card below shows the title "Pull request checks" with the filename "ci.yaml" underneath, and lists "Greet Job" and "Verify Job".
    • All run buttons ("Run All", "Run Greet Job", "Run Verify Job") appear visually disabled/greyed out.
    • Every step name has a grey neutral dot icon beside it — no green checkmarks and no red X icons anywhere.
  • checks-tab-02-trusted.png
    • The amber trust banner is completely gone from the top of the panel.
    • The run buttons ("Run All", "Run Greet Job", "Run Verify Job") now appear enabled — normal contrast, not greyed out.
    • Step names still show grey neutral dot icons, since nothing has been run yet.
  • checks-tab-03-after-run-all.png
    • Under "Greet Job", both "Say hello" and "Say world" have green checkmark icons.
    • Under "Verify Job", "Failing check" has a red X icon.
    • "Never runs" (the step after the failing one) still shows a grey neutral dot, NOT a green check or red X — it was skipped by fail-fast.
    • There are exactly 2 green checkmarks and exactly 1 red X in the whole panel.

Each bullet under a capture is what the spec claims that image should show — open the PNG and check it.


commit 172326f · workflow run — this comment is updated in place on each run.

claude added 3 commits July 27, 2026 21:44
Captures per-step output from workflow checks into newline-delimited JSON,
queries it with bundled DuckDB, and adds a GitHub-Actions-style viewer.

Log collection
- Step execution switches from discarding output to piped stdout/stderr,
  drained on separate threads so large output on both pipes cannot deadlock
- Each line is timestamped, ANSI-stripped, and classified info/warning/error
  by content (not by stream — cargo and npm write progress to stderr)
- Written to .treq/runs/{run_id}/{job_id}.jsonl; job ids are sanitised to a
  safe filename charset
- A timed-out step records an explicit error line before being terminated

Run history
- workflow_runs now holds one row per invocation, with a new
  workflow_job_results child table carrying per-job status and log path
- Legacy per-job workflow_runs rows are migrated by dropping the old shape
- "Run All" groups every job under a single run; re-running creates a new
  run so older runs stay browsable
- A failing job no longer aborts unrelated in-flight jobs

Querying and export
- core/checks_logs.rs reads the JSONL via DuckDB read_json_auto with
  level, step and substring filters plus pagination
- Log paths are resolved and confirmed to stay inside .treq/runs
- Export renders a run's logs to a plain .log file

UI
- LogsBrowser: monospace lines, timestamp column, amber warnings and red
  errors, level/step/search filters, Back and Export
- ChecksTab gains a run-history list and opens logs from a job or a step;
  results and the open log view reset when the workspace changes

Tests
- 28 Rust unit tests, 11 JS integration tests
- New checks-logs-browser screenshot spec covering history, viewer and filter
…lter

Level filter
- LogQuery.level becomes levels: Vec<String>, applied as a SQL IN clause; an
  empty or absent list means no filtering
- New LogLevelFilter multi-select built on DropdownMenuCheckboxItem, shared by
  the run logs browser and the new Logs tab; the menu stays open on select so
  several levels can be ticked in one pass

Repo-wide data source
- A DuckDB `logs` view spans .treq/runs/**/*.jsonl, recovering run_id and
  job_id from each file's path so lines can be grouped across runs
- get_repo_logs browses every run's lines with level and search filters

SQL explorer
- run_logs_sql executes ad-hoc queries against the `logs` view and returns
  columns plus stringified rows
- Only single read-only statements are accepted (SELECT, WITH, DESCRIBE, SHOW,
  EXPLAIN, SUMMARIZE); writes, multiple statements, and ATTACH/COPY/INSTALL
  style keywords are rejected before reaching DuckDB
- Results are capped by wrapping the user's query in an outer LIMIT

UI
- LogsTab is offered on the home repo only, with Browse and SQL Explorer views
- Browse renders timestamp, run id, job id and message per line, reusing the
  logs browser's level colouring
- LogsSqlExplorer provides a query editor, starter templates, a result grid
  with NULL rendering, and inline error reporting

Tests
- 35 Rust unit tests covering multi-level filtering, the cross-run view and
  SQL validation
- 7 new JS integration tests for the Logs tab, level filter and explorer
- New logs-tab-sql-explorer screenshot spec; existing specs updated for the
  multi-select
Log records now follow the OpenTelemetry log data model, and both logs
surfaces gain a chart, line selection and a path into an agent session.

OpenTelemetry structure
- Records carry time_unix_nano, observed_time_unix_nano, severity_number,
  severity_text, body, trace_id, span_id, resource and scope
- A run becomes a trace and each job a span; ids are derived from the run and
  job so re-reads stay stable rather than random
- Step, stream and run/job identity move into attributes, using OTel's own
  log.iostream convention for the standard stream
- The DuckDB view projects the standard field names and lifts attributes into
  columns, so queries say job_id rather than digging through the map
- UI level names are translated to severity text at the query boundary, so
  stored records stay standard

Timeseries chart
- New query_log_timeseries buckets records by time and severity
- EChart wraps Apache ECharts for React: the instance lives in a ref, only the
  option object is pushed on update, and the canvas plus its resize observer
  are disposed on unmount
- LogsTimeseriesChart stacks severities over a shared time axis above the feed

Logs Explorer
- Renamed from SQL Explorer
- Templates move from a button row into a dropdown, each item carrying a
  description, and expand from three to five

Selection and send-to-agent
- useLineSelection supports drag-select for contiguous runs and a multi-select
  mode for gathering scattered lines
- LogFeed is shared by the run and repo-wide browsers, with a Send to agent
  action for the selection
- The explorer can send a whole result set
- All three open a fresh agent session seeded with the content, following the
  existing create-agent-with-review pattern

Tests
- 41 Rust unit tests covering the OTel shape, severity mapping, trace/span ids
  and timeseries bucketing
- 195 JS tests including drag-select, multi-select, template listing and the
  OTel columns
- New logs-otel-chart-agent screenshot spec; existing specs updated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants