| 1886 | } |
| 1887 | |
| 1888 | async setGoal(input: SetGoalInput): Promise<Result<GoalRecordV1, GoalSetError>> { |
| 1889 | // Catch the two known throw paths (`assertParentWorkspace` and |
| 1890 | // `applyMutableFields`/`validateStatusTransition`) and surface them as |
| 1891 | // typed Result errors so the oRPC `setGoal` handler does not leak them as |
| 1892 | // unhandled 500s. |
| 1893 | try { |
| 1894 | return await this.setGoalInternal(input); |
| 1895 | } catch (error) { |
| 1896 | if (error instanceof WorkspaceGoalChildWorkspaceError) { |
| 1897 | return Err({ type: "child_workspace", message: error.message }); |
| 1898 | } |
| 1899 | if (error instanceof WorkspaceGoalTransitionError) { |
| 1900 | return Err({ type: "invalid_transition", message: error.message }); |
| 1901 | } |
| 1902 | throw error; |
| 1903 | } |
| 1904 | } |
| 1905 | |
| 1906 | private async setGoalInternal(input: SetGoalInput): Promise<Result<GoalRecordV1, GoalSetError>> { |
| 1907 | const objective = input.objective?.trim(); |