From 62cce5facfc7937842370d59186815e3acb638a5 Mon Sep 17 00:00:00 2001 From: joshwheelock Date: Tue, 7 Jul 2026 09:13:59 +0200 Subject: [PATCH] Remove deprecated goal qualify command --- CHANGELOG.md | 4 + docs/guides/advanced-workflows.md | 2 +- docs/reference/commands/goal.md | 26 ------- .../commands/goals/approve/goal.approve.ts | 3 +- .../goals/qualify/GoalQualifyOutputBuilder.ts | 78 ------------------- .../commands/goals/qualify/goal.qualify.ts | 66 ---------------- .../cli/commands/goals/reject/goal.reject.ts | 2 +- .../cli/commands/goals/review/goal.review.ts | 2 +- .../commands/registry/generated-commands.ts | 6 -- .../qualify/GoalQualifyOutputBuilder.test.ts | 65 ---------------- .../registry/RequiresProjectMetadata.test.ts | 7 ++ 11 files changed, 15 insertions(+), 246 deletions(-) delete mode 100644 src/presentation/cli/commands/goals/qualify/GoalQualifyOutputBuilder.ts delete mode 100644 src/presentation/cli/commands/goals/qualify/goal.qualify.ts delete mode 100644 tests/presentation/cli/commands/goals/qualify/GoalQualifyOutputBuilder.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dc0233e..55b03d8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Removed + +- **Deprecated goal qualification command**: Removed the `jumbo goal qualify` command surface. Use `jumbo goal approve` for successful QA review approvals. + ## [3.12.2] - 2026-07-06 ### Fixed diff --git a/docs/guides/advanced-workflows.md b/docs/guides/advanced-workflows.md index 1c58cfe4..9844b580 100644 --- a/docs/guides/advanced-workflows.md +++ b/docs/guides/advanced-workflows.md @@ -27,7 +27,7 @@ Tips: - Use `jumbo goal update-progress --id --task-description "..."` after each meaningful sub-task. - If QA finds issues, use `jumbo goal reject --id --audit-findings "..."`, fix, then `submit` again. -- `jumbo goal qualify --id ` exists for backward compatibility but is deprecated in favor of `goal approve`. +- Use `jumbo goal approve --id ` after QA review passes. ## Control phase handoffs with --continue diff --git a/docs/reference/commands/goal.md b/docs/reference/commands/goal.md index a1051f0e..34893f11 100644 --- a/docs/reference/commands/goal.md +++ b/docs/reference/commands/goal.md @@ -313,32 +313,6 @@ Approve a goal after successful QA review — transitions from `in-review` to `a > jumbo goal approve --id goal_abc123 --continue ``` ---- - -## jumbo goal qualify - -Qualify a goal after successful QA review. This command is deprecated and retained for compatibility. Prefer `jumbo goal approve`. - -### Synopsis - -```bash -> jumbo goal qualify --id -``` - -### Options - -| Option | Description | -|--------|-------------| -| `-i, --id ` | ID of the goal to qualify (required) | - -### Examples - -```bash -> jumbo goal qualify --id goal_abc123 -``` - ---- - ## jumbo goal reject Reject a goal after failed QA review — transitions from `in-review` back to `doing`. diff --git a/src/presentation/cli/commands/goals/approve/goal.approve.ts b/src/presentation/cli/commands/goals/approve/goal.approve.ts index 09447d88..d97d4d49 100644 --- a/src/presentation/cli/commands/goals/approve/goal.approve.ts +++ b/src/presentation/cli/commands/goals/approve/goal.approve.ts @@ -5,7 +5,6 @@ * Transitions goal from 'in-review' to 'approved' status and renders codification instructions. * * This is the primary command for review approval. - * See also: goal.qualify (deprecated alias). */ import { CommandMetadata, CONTINUE_OPTION } from "../../registry/CommandMetadata.js"; @@ -49,7 +48,7 @@ export async function goalApprove( const outputBuilder = new GoalApproveOutputBuilder(); try { - // 1. Execute via controller (delegates to same QualifyGoalController) + // 1. Execute via the existing approval workflow const response = await container.qualifyGoalController.handle({ goalId: options.id, }); diff --git a/src/presentation/cli/commands/goals/qualify/GoalQualifyOutputBuilder.ts b/src/presentation/cli/commands/goals/qualify/GoalQualifyOutputBuilder.ts deleted file mode 100644 index cd21a4b4..00000000 --- a/src/presentation/cli/commands/goals/qualify/GoalQualifyOutputBuilder.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { TerminalOutputBuilder } from '../../../output/TerminalOutputBuilder.js'; -import { TerminalOutput } from '../../../output/TerminalOutput.js'; -import { QualifyGoalResponse } from '../../../../../application/context/goals/qualify/QualifyGoalResponse.js'; -import { Colors, Symbols } from '../../../rendering/StyleConfig.js'; -import { EDGE, heading, contentLine, metaField } from '../../../rendering/OutputLayout.js'; - -/** - * Specialized builder for goal.qualify command output. - * Encapsulates all output rendering for the qualify goal command. - * - * Pattern: Output builders contain ALL prompt and output content. - * Command files must not duplicate or add additional output after calling the builder. - * - * @deprecated Use GoalApproveOutputBuilder instead. This command is deprecated - * in favor of 'jumbo goal approve'. - */ -export class GoalQualifyOutputBuilder { - private builder: TerminalOutputBuilder; - - constructor() { - this.builder = new TerminalOutputBuilder(); - } - - /** - * Build deprecation warning output. - * Advises users to switch to 'jumbo goal approve'. - */ - buildDeprecationWarning(): TerminalOutput { - this.builder.reset(); - const lines: string[] = []; - lines.push(""); - lines.push(heading("Deprecation Notice")); - lines.push(contentLine(`${Symbols.warning} ${Colors.warning("'jumbo goal qualify' is deprecated. Use 'jumbo goal approve' instead.")}`)); - this.builder.addPrompt(lines.join("\n")); - return this.builder.build(); - } - - /** - * Build output for successful goal qualification. - * Renders qualification result with next steps. - */ - buildSuccess(response: QualifyGoalResponse): TerminalOutput { - this.builder.reset(); - const lines: string[] = []; - - lines.push(""); - lines.push(heading("Goal Qualified")); - lines.push(contentLine(`${Symbols.check} ${Colors.success("QA review passed — ready for codification")}`)); - lines.push(""); - lines.push(metaField("Id", Colors.muted(response.goalId), 11)); - lines.push(metaField("Objective", Colors.primary(response.objective), 11)); - lines.push(metaField("Status", Colors.primary(response.status), 11)); - - if (response.nextGoalId) { - lines.push(metaField("Next Goal", Colors.muted(response.nextGoalId), 11)); - } - - this.builder.addPrompt(lines.join("\n")); - this.builder.addPrompt( - "\n" + `${EDGE}${Colors.primary("➤")} ${Colors.primary(`To codify: jumbo goal codify --id ${response.goalId}`)}` - ); - - return this.builder.build(); - } - - /** - * Build output for goal qualification failure. - * Renders error message when goal qualification fails. - */ - buildFailureError(error: Error | string): TerminalOutput { - this.builder.reset(); - this.builder.addPrompt(`${Symbols.cross} ${Colors.error("Failed to qualify goal")}`); - this.builder.addData({ - message: error instanceof Error ? error.message : error - }); - return this.builder.build(); - } -} diff --git a/src/presentation/cli/commands/goals/qualify/goal.qualify.ts b/src/presentation/cli/commands/goals/qualify/goal.qualify.ts deleted file mode 100644 index 58c2f1f4..00000000 --- a/src/presentation/cli/commands/goals/qualify/goal.qualify.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * CLI Command: jumbo goal qualify - * - * Qualifies a goal after successful QA review. - * Transitions goal from 'in-review' to 'approved' status and renders codification instructions. - */ - -import { CommandMetadata } from "../../registry/CommandMetadata.js"; -import { IApplicationContainer } from "../../../../../application/host/IApplicationContainer.js"; -import { Renderer } from "../../../rendering/Renderer.js"; -import { GoalQualifyOutputBuilder } from "./GoalQualifyOutputBuilder.js"; - -/** - * Command metadata for auto-registration - */ -export const metadata: CommandMetadata = { - description: "Qualify a goal after successful QA review", - category: "work", - requiredOptions: [ - { - flags: "-i, --id ", - description: "ID of the goal to qualify" - } - ], - options: [], - examples: [ - { - command: "jumbo goal qualify --id abc123", - description: "Qualify a goal after QA review passes" - } - ], - related: ["goal review", "goal complete", "goal start"], - requiresProject: true -}; - -/** - * Command handler - * Called by Commander with parsed options - */ -export async function goalQualify( - options: { id: string }, - container: IApplicationContainer -) { - const renderer = Renderer.getInstance(); - - try { - // 1. Emit deprecation warning - const outputBuilder = new GoalQualifyOutputBuilder(); - const warning = outputBuilder.buildDeprecationWarning(); - renderer.info(warning.toHumanReadable()); - - // 2. Execute via controller - const response = await container.qualifyGoalController.handle({ - goalId: options.id, - }); - - // 3. Build and render output using builder pattern - const output = outputBuilder.buildSuccess(response); - - renderer.info(output.toHumanReadable()); - - } catch (error) { - renderer.error("Failed to qualify goal", error instanceof Error ? error : String(error)); - process.exit(1); - } -} diff --git a/src/presentation/cli/commands/goals/reject/goal.reject.ts b/src/presentation/cli/commands/goals/reject/goal.reject.ts index a79d7769..8492a8c8 100644 --- a/src/presentation/cli/commands/goals/reject/goal.reject.ts +++ b/src/presentation/cli/commands/goals/reject/goal.reject.ts @@ -34,7 +34,7 @@ export const metadata: CommandMetadata = { description: "Reject a goal with review issues" } ], - related: ["goal review", "goal qualify", "goal start"], + related: ["goal review", "goal approve", "goal start"], requiresProject: true }; diff --git a/src/presentation/cli/commands/goals/review/goal.review.ts b/src/presentation/cli/commands/goals/review/goal.review.ts index b733bdea..03f751bd 100644 --- a/src/presentation/cli/commands/goals/review/goal.review.ts +++ b/src/presentation/cli/commands/goals/review/goal.review.ts @@ -30,7 +30,7 @@ export const metadata: CommandMetadata = { description: "Start QA review on a submitted goal" } ], - related: ["goal submit", "goal qualify", "goal reject"], + related: ["goal submit", "goal approve", "goal reject"], requiresProject: true }; diff --git a/src/presentation/cli/commands/registry/generated-commands.ts b/src/presentation/cli/commands/registry/generated-commands.ts index 8b332d8a..29a9cde1 100644 --- a/src/presentation/cli/commands/registry/generated-commands.ts +++ b/src/presentation/cli/commands/registry/generated-commands.ts @@ -49,7 +49,6 @@ import { goalCodify, metadata as goalCodifyMeta } from '../../commands/goals/cod import { goalCommit, metadata as goalCommitMeta } from '../../commands/goals/commit/goal.commit.js'; import { goalsList, metadata as goalsListMeta } from '../../commands/goals/list/goals.list.js'; import { goalPause, metadata as goalPauseMeta } from '../../commands/goals/pause/goal.pause.js'; -import { goalQualify, metadata as goalQualifyMeta } from '../../commands/goals/qualify/goal.qualify.js'; import { goalRefine, metadata as goalRefineMeta } from '../../commands/goals/refine/goal.refine.js'; import { goalReject, metadata as goalRejectMeta } from '../../commands/goals/reject/goal.reject.js'; import { goalRemove, metadata as goalRemoveMeta } from '../../commands/goals/remove/goal.remove.js'; @@ -300,11 +299,6 @@ export const commands: RegisteredCommand[] = [ metadata: goalPauseMeta, handler: goalPause }, - { - path: 'goal qualify', - metadata: goalQualifyMeta, - handler: goalQualify - }, { path: 'goal refine', metadata: goalRefineMeta, diff --git a/tests/presentation/cli/commands/goals/qualify/GoalQualifyOutputBuilder.test.ts b/tests/presentation/cli/commands/goals/qualify/GoalQualifyOutputBuilder.test.ts deleted file mode 100644 index 74b1fbec..00000000 --- a/tests/presentation/cli/commands/goals/qualify/GoalQualifyOutputBuilder.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { GoalQualifyOutputBuilder } from "../../../../../../src/presentation/cli/commands/goals/qualify/GoalQualifyOutputBuilder"; -import { QualifyGoalResponse } from "../../../../../../src/application/context/goals/qualify/QualifyGoalResponse"; - -describe("GoalQualifyOutputBuilder", () => { - let builder: GoalQualifyOutputBuilder; - - beforeEach(() => { - builder = new GoalQualifyOutputBuilder(); - }); - - it("should build deprecation warning", () => { - const output = builder.buildDeprecationWarning(); - const text = output.toHumanReadable(); - - expect(text).toContain("Deprecation Notice"); - expect(text).toContain("jumbo goal approve"); - }); - - it("should build success output with goal details and next step", () => { - const response: QualifyGoalResponse = { - goalId: "goal_123", - status: "approved", - objective: "Implement authentication", - }; - - const output = builder.buildSuccess(response); - const text = output.toHumanReadable(); - - expect(text).toContain("Goal Qualified"); - expect(text).toContain("goal_123"); - expect(text).toContain("Implement authentication"); - expect(text).toContain("approved"); - expect(text).toContain("jumbo goal codify --id goal_123"); - }); - - it("should include next goal ID when present", () => { - const response: QualifyGoalResponse = { - goalId: "goal_123", - status: "approved", - objective: "Implement authentication", - nextGoalId: "goal_456", - }; - - const output = builder.buildSuccess(response); - const text = output.toHumanReadable(); - - expect(text).toContain("goal_456"); - }); - - it("should build failure error output", () => { - const output = builder.buildFailureError("Something went wrong"); - const text = output.toHumanReadable(); - - expect(text).toContain("Failed to qualify goal"); - expect(text).toContain("Something went wrong"); - }); - - it("should build failure error output from Error object", () => { - const output = builder.buildFailureError(new Error("Domain error")); - const text = output.toHumanReadable(); - - expect(text).toContain("Failed to qualify goal"); - expect(text).toContain("Domain error"); - }); -}); diff --git a/tests/presentation/cli/commands/registry/RequiresProjectMetadata.test.ts b/tests/presentation/cli/commands/registry/RequiresProjectMetadata.test.ts index 19ca198c..2e719332 100644 --- a/tests/presentation/cli/commands/registry/RequiresProjectMetadata.test.ts +++ b/tests/presentation/cli/commands/registry/RequiresProjectMetadata.test.ts @@ -41,4 +41,11 @@ describe("requiresProject metadata", () => { expect(command).toBeDefined(); expect(command?.metadata.requiresProject).toBe(true); }); + + it("registers goal approve and no longer registers goal qualify", () => { + const paths = commands.map((c) => c.path); + + expect(paths).toContain("goal approve"); + expect(paths).not.toContain("goal qualify"); + }); });