Summary
Add first-class Linear support as a hybrid forge provider — Linear handles issue concepts (issue-view, issue-list, issue-comment, recently-closed, auth-status, user-identity), while PR concepts (pr-list, pr-exists, pr-merge, pr-diff, etc.) fall through to GitHub defaults.
Motivation
Teams using Linear for issue tracking but GitHub for code hosting currently have no way to wire codev's forge abstraction to Linear. The forge system (spec 589) was designed for pluggable providers, but the existing resolution logic has a bug: buildPresetFromScripts sets null for concepts without an on-disk script, which means "disabled" rather than "fall through to default." This blocks any hybrid provider model.
Design
Architectural fix: Change buildPresetFromScripts to omit missing concepts from the preset instead of setting them to null. This lets them fall through to the GitHub default via the existing resolution chain (override → preset → default). This fix benefits all non-GitHub providers (GitLab, Gitea) that don't implement every concept.
Linear provider: 6 POSIX shell scripts using curl + jq against the Linear GraphQL API, authenticated via LINEAR_API_KEY. Config-driven team filtering via forge.linear-team → CODEV_LINEAR_TEAM env var (generalized buildForgeEnv helper exports non-concept forge config keys as CODEV_* env vars).
Alphanumeric issue identifiers: Widen issueNumber from number to number | string across the agent-farm surface to accept identifiers like ENG-123.
Implementation
PR: #716
Tasks from review feedback
Summary
Add first-class Linear support as a hybrid forge provider — Linear handles issue concepts (issue-view, issue-list, issue-comment, recently-closed, auth-status, user-identity), while PR concepts (pr-list, pr-exists, pr-merge, pr-diff, etc.) fall through to GitHub defaults.
Motivation
Teams using Linear for issue tracking but GitHub for code hosting currently have no way to wire codev's forge abstraction to Linear. The forge system (spec 589) was designed for pluggable providers, but the existing resolution logic has a bug:
buildPresetFromScriptssetsnullfor concepts without an on-disk script, which means "disabled" rather than "fall through to default." This blocks any hybrid provider model.Design
Architectural fix: Change
buildPresetFromScriptsto omit missing concepts from the preset instead of setting them tonull. This lets them fall through to the GitHub default via the existing resolution chain (override → preset → default). This fix benefits all non-GitHub providers (GitLab, Gitea) that don't implement every concept.Linear provider: 6 POSIX shell scripts using
curl+jqagainst the Linear GraphQL API, authenticated viaLINEAR_API_KEY. Config-driven team filtering viaforge.linear-team→CODEV_LINEAR_TEAMenv var (generalizedbuildForgeEnvhelper exports non-concept forge config keys as CODEV_* env vars).Alphanumeric issue identifiers: Widen
issueNumberfromnumbertonumber | stringacross the agent-farm surface to accept identifiers likeENG-123.Implementation
PR: #716
Tasks from review feedback
issue_numbercolumn from INTEGER to TEXT in db/schema.ts, db/types.ts, and migration paths in db/index.tsparseIntguard incommands/porch/prompts.ts:31-37to pass alphanumeric IDs through tofetchIssuerecently-closed.sh— replaceorderBy: completedAtwithorderBy: updatedAt(Linear'sPaginationOrderByonly supportscreatedAt/updatedAt)issue-view.shagainst emptynodes[]result (issue not found)buildPresetFromScriptsomission behavior,ENG-123CLI parsing,buildForgeEnvpassthrough