feat(examples): add review-agent + linear-shipper (Relayfile-VFS clients)#93
feat(examples): add review-agent + linear-shipper (Relayfile-VFS clients)#93khaliqgant wants to merge 5 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
| if (!ctx.linear) throw new Error('linear-shipper requires the linear integration'); | ||
| if (!ctx.github) throw new Error('linear-shipper requires the github integration'); | ||
|
|
||
| const issueRef = (event as LinearIssueEvent).issue; |
There was a problem hiding this comment.
🔴 Linear issue data read from event envelope instead of event.payload
On line 29, (event as LinearIssueEvent).issue casts the WorkforceProviderEvent envelope itself to LinearIssueEvent and reads .issue from it. However, the WorkforceProviderEvent type (packages/runtime/src/types.ts:49-62) stores the raw provider payload in event.payload, not on the event envelope. Since WorkforceProviderEvent has no issue field, issueRef is always undefined, causing issueId to be undefined, and the handler always throws "Linear event is missing an issue id" on line 31. The review-agent correctly uses payloadOf(event.payload) (examples/review-agent/agent.ts:96) to extract the nested payload. The fix is to read from event.payload instead of event.
| const issueRef = (event as LinearIssueEvent).issue; | |
| const issueRef = (event.payload as LinearIssueEvent)?.issue; |
Was this helpful? React with 👍 or 👎 to provide feedback.
…t style
Switches workforce's integration clients from direct REST calls to the
Relayfile-VFS writeback pattern used by sage + the cloud workflows.
Handler-side surface (ctx.github.upsertIssue, ctx.linear.comment, etc.)
stays identical; the wire underneath flips from "speak HTTP to GitHub"
to "write a JSON draft inside the Relayfile mount and let the writeback
worker do the actual API call." Aligns workforce with the rest of the
org's integration story and inherits writeback durability + retry for
free.
Substrate
- packages/runtime/src/errors.ts (top-level): WorkforceIntegrationError
moves here with the { provider, operation, cause, retryable } shape
sage/cloud already use. Old clients/errors.ts is removed; the public
surface re-exports it from the same package import path so existing
consumers (mcp-workforce) keep compiling.
- packages/runtime/src/clients/request.ts: shared VFS helpers
(readJsonFile, readTextFile, listJsonFiles, listDirectoryEntries,
writeJsonFile + atomic write-then-rename) with mount-root path
validation and optional writeback-receipt polling.
Clients
- github.ts is rewritten as a VFS client. Same GithubClient interface
(comment, createIssue, upsertIssue, getPr, postReview); each method
now reads/writes files at canonical paths under
`/github/repos/<owner>/<repo>/...`.
- linear, slack, notion, jira ship as new typed clients with the same
pattern. IntegrationClients in types.ts now types all five concretely
instead of leaving four as unknown.
Tests
- github.test.ts is rewritten end-to-end against a tempdir mount.
- linear/slack/notion/jira tests run against tempdir mounts too.
- 29 runtime tests pass (up from 18), 386 across the repo.
Example
- weekly-digest/agent.ts drops the WORKFORCE_INTEGRATION_GITHUB_TOKEN
plumbing; the github client picks up RELAYFILE_MOUNT_ROOT instead.
- weekly-digest/README.md documents the writeback model + Relayfile
mount env requirement, and drops the GITHUB_TOKEN setup step.
Notes
- mcp-workforce (PR #91) imports createGithubClient with a different
construction shape today (`{ token }`); it'll need a follow-up
commit to switch to IntegrationClientOptions once this lands. The
MCP package depends on the new shape, not the old.
- The direct-REST github implementation that shipped in #90 is
replaced wholesale. No persona today depends on it; weekly-digest
is updated in this commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Follow-on to the persona-tier flatten refactor — the openclaw-routing example still read from selection.runtime.* and selection.tier, which no longer exist after PersonaSelection lost its per-tier wrapper. Required to keep the examples typecheck green on top of the flatten.
efb115b to
1f8dcdb
Compare
Ports the two example agents from the closed codex/deploy-v1-pr branch to the Relayfile-VFS integration-client style introduced in #92. review-agent - GitHub PR opened: pulls the diff via ctx.github.getPr, runs the persona's harness on the diff body, posts a review via ctx.github.postReview. - @mention in an issue/review comment: harness with the comment thread as context, posts the reply via ctx.github.comment. - check_run.completed (failure): harness with the failed CI logs as context, proposes a fix in a comment. - Slack app_mention: conversational reply via ctx.slack. linear-shipper - Linear issue created: clones the target repo into the sandbox, runs ctx.harness.run on the issue body, opens a draft PR via ctx.github, comments back on the Linear issue with the PR link. - Headless (no traits in the persona); demonstrates the paraglide "Linear issue → ship" pattern. Both examples adapt to the WorkforceProviderEvent shape — they read the raw provider payload from event.payload rather than treating the event as the payload itself. Tests: typecheck clean across the workspace and against examples/tsconfig.json (which path-maps @agentworkforce/runtime to the workspace source). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same shape mismatch I fixed in review-agent: the agent was reading event.issue as if event were the raw Linear webhook body, but WorkforceProviderEvent.payload is where the provider payload lives. Without this fix, every linear.issue.created delivery to the shipper failed at the "Linear event is missing an issue id" guard because issueRef was always undefined. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
persona-kit's parser rejects unknown intents. "implementation" is in PERSONA_TAGS, not PERSONA_INTENTS, so the persona failed at parsePersonaSpec(...) with `persona[implementation].intent is invalid` before deploy could do anything. Swap to `implement-frontend` — the closest valid intent. Not a perfect domain match (the shipper isn't frontend-specific) but accurate enough to demonstrate the pattern; users will customize per their own routing taxonomy. Verified end-to-end: `workforce deploy ./examples/linear-shipper/persona.json --dry-run` now exits 0 with "persona linear-shipper: 2 integration(s)". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6718791 to
b84f738
Compare
af8f4a2 to
2fa0ef9
Compare
Summary
Two reference example agents demonstrating the Relayfile-VFS integration-client pattern landed in #92:
examples/review-agent/— GitHub PR review + autofix. Reviews opened PRs (`pull_request.opened`), responds to `@mention` in issue/review comments, proposes fixes on failed CI checks, replies in Slack on `app_mention`. Uses `ctx.github.{getPr,postReview,comment}` + `ctx.slack.reply` + `ctx.harness.run`.examples/linear-shipper/— Paraglide-style headless agent. On `linear.issue.created`, clones the target repo into the sandbox, runs the harness on the issue body, opens a draft PR via `ctx.github`, comments back on the Linear issue.Ported from the closed `codex/deploy-v1-pr` branch (#88) and adapted to the `WorkforceProviderEvent` shape — examples read the provider payload from `event.payload` rather than treating the event as the payload itself.
Stacked on #92 (Relayfile-VFS substrate). Will rebase to `main` once that lands.
Test plan
🤖 Generated with Claude Code