fix(smithy): sf task commands honor merge.requireApproval config#107
Open
fnnzzz wants to merge 1 commit into
Open
fix(smithy): sf task commands honor merge.requireApproval config#107fnnzzz wants to merge 1 commit into
fnnzzz wants to merge 1 commit into
Conversation
The shared createTaskAssignmentService helper used by sf task complete, sf task merge, sf task handoff, etc. was hardcoded to wire a LocalMergeProvider regardless of workspace config. The workflow preset 'approve' (which sets merge.requireApproval=true) was therefore silently downgraded to a no-op local merge instead of the GitHub PR flow the long-running orchestrator already uses in server/services.ts. This change mirrors that wiring in the CLI: when merge.requireApproval is true the CLI uses GitHubMergeProvider via the existing createGitHubMergeProvider() factory, otherwise it stays on the existing LocalMergeProvider. Default behaviour for users without merge config is unchanged. When requireApproval=true and the gh CLI is not on PATH, the command fails fast with an actionable error pointing the user at install/auth or at the requireApproval=false fallback — instead of silently degrading to LocalMergeProvider, which is the original bug. Tests: adds task.bun.test.ts covering provider selection (default, explicit false, true, missing config), the gh-missing error path, and command-structure parity with sibling test files.
ddc29ea to
ac24935
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
sf tasksubcommands (complete,merge,handoff,reject,sync) silently bypassmerge.requireApprovalbecause the shared helper that wires their merge provider is hardcoded toLocalMergeProvider. Workspaces using theapproveworkflow preset never see GitHub PRs created from the CLI even though the long-running orchestrator (server/services.ts) does the right thing — the CLI just no-ops.Problem
In
packages/smithy/src/cli/commands/task.ts,createTaskAssignmentService(options)(the helper everysf task ...subcommand routes through) builds the merge provider with:That wiring ignores
config.merge.requireApprovalentirely. Server-side,packages/smithy/src/server/services.tsalready does the right thing:So setting the workspace to the
approvepreset turns on PR creation only when the orchestrator runs work — invokingsf task complete <id>from the CLI silently falls back to a no-op local merge instead of opening a GitHub PR. From the user's POV, the workflow preset is broken.Root cause
packages/smithy/src/cli/commands/task.ts:46(pre-fix) —const mergeProvider = createLocalMergeProvider();runs unconditionally insidecreateTaskAssignmentService, with no read ofloadConfig()orconfig.merge.requireApproval.Fix
createTaskAssignmentServicenow mirrors the canonical pattern fromserver/services.ts:loadConfig()is destructured from@stoneforge/quarry(the same module the helper already imports dynamically).selectMergeProvider(config, factories)which returnsGitHubMergeProviderwhenconfig.merge?.requireApproval === trueandLocalMergeProviderotherwise. The helper is exported (@internal) so unit tests can pass stub factories.requireApprovalis true, a newassertGhCliAvailable()runsgh --versionand throws a user-friendly error ifghis missing on PATH — instead of silently degrading toLocalMergeProvider(the original bug). The error tells the user how to installghor how to fliprequireApprovalback to false.Default behaviour is unchanged: when
requireApprovalis unset, false, ormergeis absent entirely,LocalMergeProvideris used exactly as before.Changes
packages/smithy/src/cli/commands/task.ts— load config and select provider conditionally; exportselectMergeProvider,assertGhCliAvailable, and the supporting types for tests.packages/smithy/src/cli/commands/task.bun.test.ts— new test file (notask.bun.test.tsexisted previously) covering provider selection, the gh-missing error path, and command-structure parity with sibling test files..changeset/fix-sf-task-merge-honor-require-approval.md— patch bump for@stoneforge/smithy.Test coverage
New cases in
task.bun.test.ts:selectMergeProvider(the regression):requireApproval=false→ LocalMergeProvider, github factory not invoked.requireApproval=true→ GitHubMergeProvider, local factory not invoked.merge.requireApprovalisundefined→ falls back to LocalMergeProvider (?? false).mergeconfig absent entirely → falls back to LocalMergeProvider.merge.requireApprovalis explicitlyundefined→ falls back to LocalMergeProvider.assertGhCliAvailable(the new error path):available: true.Cannot create GitHub pull requestswhen probe reportsavailable: false.cli.github.comandmerge.requireApprovalso users know how to fix it.()when the probe gives no reason.Command-structure parity with
task-merge-status.bun.test.ts/agent.bun.test.ts:name/description/handlerfortaskHandoffCommand,taskCompleteCommand,taskMergeCommand,taskRejectCommand,taskSyncCommand,taskSetOwnerCommandplus a few key options (--no-mr,--reason).All 21 new tests pass; the package's full Bun suite (
bun test src) is green at 1589 pass / 0 fail / 19 skip.Test plan
pnpm installat the monorepo root.cd packages/smithy && pnpm run typecheck— clean.cd packages/smithy && pnpm run build— clean (compileddist/cli/commands/task.jsreflects the fix).cd packages/smithy && bun test src/cli/commands/task.bun.test.ts— 21 pass, 0 fail.cd packages/smithy && pnpm run test— 1589 pass, 0 fail, 19 skip across 53 files.merge.requireApproval=true,ghstripped from PATH → command exits with the new clear error:Cannot create GitHub pull requests: the \gh` CLI is not available on PATH (Executable not found in $PATH: "gh"). Install it from https://cli.github.com/ and run `gh auth login`, or set `merge.requireApproval` to `false` in your workspace config to use the local merge provider.`merge.requireApproval=false→ command proceeds past provider initialization (errors later on the unrelated "Task not found" lookup, exactly as on master).merge.requireApproval=true,ghavailable → command proceeds past provider initialization (same "Task not found" downstream error, confirming gh check passes).Checklist