feat: add log-parser support for behavior-defined engines - #50991
Conversation
Add a `log-parser` field to `EngineBehaviorDefinition` that allows behavior-defined engines (crush, opencode, goose, aider) to declare inline JavaScript log parsers. The parser code is written to disk via heredoc and wrapped with `createEngineLogParser` from `log_parser_shared.cjs` to produce normalized events files matching the contract of built-in engine parsers. Changes: - Add `LogParser` field to `EngineBehaviorDefinition` struct - Add `log-parser` property to JSON schema for behaviors - Implement `GetLogParserScriptId()` on `BehaviorDefinedEngine` - Add `buildLogParserWriteStep()` with heredoc safety checks - Wire log-parser write step into `buildBehaviorDefinedSetupSteps()` - Add comprehensive unit tests Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot implement log parser for opencode/goose/crush based on workflow run data. |
Implement engine-specific log parsers using the new log-parser behavior field for each behavior-defined engine: - Goose: parses plain-text streaming output with tool call markers - OpenCode: parses JSON-structured log lines from --print-logs output - Crush: parses plain-text output with tool invocation patterns Each parser extracts conversation blocks, tool calls, MCP failures, and max-turns detection, producing formatted step summaries. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Implemented log parsers for all three engines in
Each parser produces formatted markdown step summaries with metrics tables and collapsible conversation details. |
|
@copilot the parser should not render anything, it should return the normalized agent event datastructure that will be renderered by code in agents/setup/js function. Refactor code so that all agents use the same rendering helper functions. |
…ng markdown Goose, OpenCode, and Crush parsers now return logEntries in the normalized agent event format (type: assistant/user/system/result with message.content arrays). The shared rendering helpers in log_parser_bootstrap.cjs handle all markdown generation. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Refactored in the latest commit. All three parsers (goose, opencode, crush) now return normalized agent event entries ( |
|
|
|
|
|
|
|
|
There was a problem hiding this comment.
Pull request overview
Adds declarative log-parser support for behavior-defined engines.
Changes:
- Adds the
log-parserbehavior and runtime wrapper. - Adds parsers for OpenCode, Goose, and Crush.
- Regenerates affected workflows and adds Go tests.
Show a summary per file
| File | Description |
|---|---|
pkg/workflow/engine_definition.go |
Defines the new behavior field. |
pkg/workflow/behavior_defined_engine.go |
Generates and registers parser scripts. |
pkg/workflow/behavior_defined_engine_log_parser_test.go |
Tests parser-step generation. |
pkg/parser/schemas/main_workflow_schema.json |
Exposes log-parser in the schema. |
.github/workflows/shared/opencode.md |
Adds the OpenCode parser. |
.github/workflows/shared/goose.md |
Adds the Goose parser. |
.github/workflows/shared/crush.md |
Adds the Crush parser. |
.github/workflows/smoke-opencode.lock.yml |
Regenerates the OpenCode smoke workflow. |
.github/workflows/smoke-goose.lock.yml |
Regenerates the Goose smoke workflow. |
.github/workflows/smoke-crush.lock.yml |
Regenerates the Crush smoke workflow. |
.github/workflows/daily-token-consumption-report.lock.yml |
Includes the Goose parser. |
.github/workflows/daily-team-evolution-insights.lock.yml |
Includes the Goose parser. |
.github/workflows/daily-security-red-team.lock.yml |
Includes the OpenCode parser. |
.github/workflows/daily-reliability-review.lock.yml |
Includes the OpenCode parser. |
.github/workflows/daily-code-metrics.lock.yml |
Includes the Crush parser. |
.github/workflows/daily-arxiv-researcher.lock.yml |
Includes the Crush parser. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 16/16 changed files
- Comments generated: 5
- Review effort level: Balanced
🧪 Test Quality Sentinel Report✅ Test Quality Score: 82/100 — Excellent
📊 Metrics (4 tests)
|
🏗️ Design Decision Gate — ADR RequiredThis PR makes significant changes to core business logic (257 new lines exceeding the 100-line threshold) but does not have a linked Architecture Decision Record (ADR). 📄 Draft ADR committed:
📋 What to do next
Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision. ❓ Why ADRs Matter
ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you. 📋 Michael Nygard ADR Format ReferenceAn ADR must contain these four sections to be considered complete:
All ADRs are stored in
|
There was a problem hiding this comment.
Review: feat: add log-parser support for behavior-defined engines
The implementation is well-structured and follows existing patterns (harness-script, config-adapter). The heredoc delimiter safety check, auto-wrapping via createEngineLogParser, and test coverage are all solid.
One non-blocking issue found across all three engine log parsers: goose.md, crush.md, and opencode.md each return markdown: "parsed" as a placeholder. In the normal path this field is ignored (the bootstrap generates rich Copilot CLI-style markdown from logEntries), but on the fallback path (empty or missing logEntries) this placeholder appears verbatim in the GitHub Actions step summary.
🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 68.3 AIC · ⊞ 5.3K
|
@copilot Please address the outstanding review feedback, refresh the branch if needed, and run the Open review items to address:
Branch refresh was requested. Run context: https://github.com/github/gh-aw/actions/runs/31150518831
|
…, comments, changeset) Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
…comment Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Done. All three parsers (goose, opencode, crush) now return the normalized agent event data structure (entries with
Addressed in the latest commits:
|
|
@copilot Please address the outstanding review feedback, refresh the branch if needed, and run the Open review items to address:
Branch refresh was requested. Run context: https://github.com/github/gh-aw/actions/runs/31154408939
|
PR TriageCategory: feature (log-parser support for behavior-defined engines) · Risk: high · Score: 82/100 (impact 42, urgency 22, quality 18) Recommendation: Large feature PR (21 files, +2390/-11) adding log-parser support across crush/goose/opencode engines, schema, ADR, and 6 regenerated
|
…e ADR-50991 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Addressed in the latest commits:
ADR is at |
|
@copilot Please address the remaining review feedback and run the Open review items to address:
Branch refresh was requested.
|
|
@copilot Please address the remaining review feedback and run the Open review items to address:
Branch refresh was requested.
|
|
🎉 This pull request is included in a new release. Release: |
Behavior-defined engines (crush, opencode, goose, aider) had no way to produce normalized event files from their logs. Built-in engines each have a hardcoded JS parser, but the declarative engine path had no equivalent hook.
Changes
EngineBehaviorDefinition: newlog-parserYAML field (inline JS) alongside the existingharness-scriptandconfig-adapterpatternsBehaviorDefinedEngine: overrideGetLogParserScriptId()→ returns<engine-id>_log_parserwhen set;buildLogParserWriteStep()writes the script to${RUNNER_TEMP}/gh-aw/actions/via heredoc with the same delimiter safety checks as harness-scriptparseLog(logContent)function is wrapped withcreateEngineLogParserfromlog_parser_shared.cjs, so the author only provides the parse function and gets the full bootstrap (file reading, events enrichment, step summary) for freelog-parseradded tobehaviorswithadditionalProperties: falsecomplianceUsage
The compiler emits a write step before execution and
generateLogParsing()picks up the script ID automatically — no changes needed in the compilation pipeline.