lalph 0.3.54 → 0.3.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -17455,12 +17455,12 @@ function set$10(self, key, value) {
17455
17455
  //#endregion
17456
17456
  //#region node_modules/.pnpm/effect@4.0.0-beta.31/node_modules/effect/dist/internal/schema/annotations.js
17457
17457
  /** @internal */
17458
- function resolve$3(ast) {
17458
+ function resolve$4(ast) {
17459
17459
  return ast.checks ? ast.checks[ast.checks.length - 1].annotations : ast.annotations;
17460
17460
  }
17461
17461
  /** @internal */
17462
17462
  function resolveAt$1(key) {
17463
- return (ast) => resolve$3(ast)?.[key];
17463
+ return (ast) => resolve$4(ast)?.[key];
17464
17464
  }
17465
17465
  /** @internal */
17466
17466
  const resolveIdentifier$1 = /* @__PURE__ */ resolveAt$1("identifier");
@@ -31552,7 +31552,7 @@ function fromFileUrl$1(url) {
31552
31552
  }
31553
31553
  return succeed$3(decodeURIComponent(pathname));
31554
31554
  }
31555
- const resolve$1 = function resolve() {
31555
+ const resolve$2 = function resolve() {
31556
31556
  let resolvedPath = "";
31557
31557
  let resolvedAbsolute = false;
31558
31558
  let cwd = void 0;
@@ -31577,7 +31577,7 @@ const resolve$1 = function resolve() {
31577
31577
  const CHAR_FORWARD_SLASH = 47;
31578
31578
  function toFileUrl$1(filepath) {
31579
31579
  const outURL = new URL("file://");
31580
- let resolved = resolve$1(filepath);
31580
+ let resolved = resolve$2(filepath);
31581
31581
  if (filepath.charCodeAt(filepath.length - 1) === CHAR_FORWARD_SLASH && resolved[resolved.length - 1] !== "/") resolved += "/";
31582
31582
  outURL.pathname = encodePathChars(resolved);
31583
31583
  return succeed$3(outURL);
@@ -31597,7 +31597,7 @@ function encodePathChars(filepath) {
31597
31597
  }
31598
31598
  const posixImpl = /* @__PURE__ */ Path$1.of({
31599
31599
  [TypeId$44]: TypeId$44,
31600
- resolve: resolve$1,
31600
+ resolve: resolve$2,
31601
31601
  normalize(path) {
31602
31602
  if (path.length === 0) return ".";
31603
31603
  const isAbsolute = path.charCodeAt(0) === 47;
@@ -32947,11 +32947,11 @@ const recur$1 = /* @__PURE__ */ memoize((ast) => {
32947
32947
  let parser;
32948
32948
  if (!ast.context && !ast.encoding && !ast.checks) return (ou, options) => {
32949
32949
  parser ??= ast.getParser(recur$1);
32950
- return parser(ou, resolve$3(ast)?.["parseOptions"] ?? options);
32950
+ return parser(ou, resolve$4(ast)?.["parseOptions"] ?? options);
32951
32951
  };
32952
32952
  const isStructural = isArrays(ast) || isObjects(ast) || isDeclaration(ast) && ast.typeParameters.length > 0;
32953
32953
  return (ou, options) => {
32954
- options = resolve$3(ast)?.["parseOptions"] ?? options;
32954
+ options = resolve$4(ast)?.["parseOptions"] ?? options;
32955
32955
  const encoding = ast.encoding;
32956
32956
  let srou;
32957
32957
  if (encoding) {
@@ -76481,7 +76481,7 @@ var require_snapshot_utils = /* @__PURE__ */ __commonJSMin$1(((exports, module)
76481
76481
  //#region node_modules/.pnpm/undici@7.22.0/node_modules/undici/lib/mock/snapshot-recorder.js
76482
76482
  var require_snapshot_recorder = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
76483
76483
  const { writeFile, readFile, mkdir } = __require("node:fs/promises");
76484
- const { dirname, resolve } = __require("node:path");
76484
+ const { dirname, resolve: resolve$1 } = __require("node:path");
76485
76485
  const { setTimeout: setTimeout$1, clearTimeout: clearTimeout$1 } = __require("node:timers");
76486
76486
  const { InvalidArgumentError, UndiciError } = require_errors$1();
76487
76487
  const { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -76746,7 +76746,7 @@ var require_snapshot_recorder = /* @__PURE__ */ __commonJSMin$1(((exports, modul
76746
76746
  const path = filePath || this.#snapshotPath;
76747
76747
  if (!path) throw new InvalidArgumentError("Snapshot path is required");
76748
76748
  try {
76749
- const data = await readFile(resolve(path), "utf8");
76749
+ const data = await readFile(resolve$1(path), "utf8");
76750
76750
  const parsed = JSON.parse(data);
76751
76751
  if (Array.isArray(parsed)) {
76752
76752
  this.#snapshots.clear();
@@ -76766,7 +76766,7 @@ var require_snapshot_recorder = /* @__PURE__ */ __commonJSMin$1(((exports, modul
76766
76766
  async saveSnapshots(filePath) {
76767
76767
  const path = filePath || this.#snapshotPath;
76768
76768
  if (!path) throw new InvalidArgumentError("Snapshot path is required");
76769
- const resolvedPath = resolve(path);
76769
+ const resolvedPath = resolve$1(path);
76770
76770
  await mkdir(dirname(resolvedPath), { recursive: true });
76771
76771
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
76772
76772
  hash,
@@ -225446,20 +225446,21 @@ const parseInput = flow(decodeUnknownEffect(Tuple([
225446
225446
  String$1,
225447
225447
  Reasoning
225448
225448
  ])), orDie$2);
225449
- const clankaSubagent = fnUntraced(function* (models, input) {
225450
- const [provider, model] = yield* parseInput(input.split("/"));
225451
- return models.get(`${provider}/${model}/low`);
225452
- }, unwrap$3);
225453
225449
  var ClankaModels = class extends Service()("lalph/ClankaModels", {
225454
225450
  dependencies: [ModelServices],
225455
225451
  lookup: fnUntraced(function* (input) {
225456
- const [provider, model$2, reasoning] = yield* parseInput(input.split("/"));
225457
- switch (provider) {
225458
- case "openai": return model$1(model$2, { reasoning: { effort: reasoning } });
225459
- case "copilot": return model(model$2, { ...reasoningToCopilotConfig(model$2, reasoning) });
225460
- }
225452
+ const [provider, model, reasoning] = yield* parseInput(input.split("/"));
225453
+ const layer = resolve(provider, model, reasoning);
225454
+ if (reasoning === "low" || reasoning === "medium") return layer;
225455
+ return merge$6(layer, layerSubagentModel(resolve(provider, model, "medium")));
225461
225456
  }, unwrap$3)
225462
225457
  }) {};
225458
+ const resolve = (provider, model$2, reasoning) => {
225459
+ switch (provider) {
225460
+ case "openai": return model$1(model$2, { reasoning: { effort: reasoning } });
225461
+ case "copilot": return model(model$2, { ...reasoningToCopilotConfig(model$2, reasoning) });
225462
+ }
225463
+ };
225463
225464
  const reasoningToCopilotConfig = (model, reasoning) => {
225464
225465
  if (model.startsWith("claude")) switch (reasoning) {
225465
225466
  case "low": return {};
@@ -233025,24 +233026,18 @@ If for any reason you get stuck on a task, mark the task back as "todo" by updat
233025
233026
  challenges faced.
233026
233027
 
233027
233028
  ${taskGuidelines(options)}`;
233028
- const prompt = (options) => `# The task
233029
+ const prompt = (options) => `# ${options.task.title}
233029
233030
 
233030
- ID: ${options.task.id}
233031
- Task: ${options.task.title}
233032
- Description:
233031
+ Task ID: ${options.task.id}
233033
233032
 
233034
233033
  ${options.task.description}
233035
233034
 
233036
- # Instructions
233035
+ ### Instructions
233037
233036
 
233038
- Your job is to implement the task described above.
233037
+ Your job is to implement the task described above.${options.task.description.includes(options.specsDirectory) ? `\nMake sure to review the prd.yml for any key information that may help you with this task.` : ""}
233039
233038
 
233040
- 1. Carefully study the prd.yml file to understand the context of the task, and
233041
- discover any key learnings from previous work.
233042
- Also read the ${options.specsDirectory}/README.md file (if available), to see
233043
- if any previous specifications could assist you.
233044
- 2. ${options.gitFlow.setupInstructions(options)}
233045
- 3. Implement the task.
233039
+ 1. ${options.gitFlow.setupInstructions(options)}
233040
+ 2. Implement the task.
233046
233041
  - If this task is a research task, **do not** make any code changes yet.
233047
233042
  - If this task is a research task and you add follow-up tasks, include (at least) "${options.task.id}" in the new task's \`blockedBy\` field.
233048
233043
  - **If at any point** you discover something that needs fixing, or another task
@@ -233050,15 +233045,14 @@ Your job is to implement the task described above.
233050
233045
  you plan to fix it as part of this task.
233051
233046
  - Add important discoveries about the codebase, or challenges faced to the task's
233052
233047
  \`description\`. More details below.
233053
- 4. Run any checks / feedback loops, such as type checks, unit tests, or linting.
233054
- 5. ${options.gitFlow.commitInstructions({
233048
+ 3. Run any checks / feedback loops, such as type checks, unit tests, or linting.
233049
+ 4. ${options.gitFlow.commitInstructions({
233055
233050
  githubPrInstructions: sourceMeta.githubPrInstructions,
233056
233051
  githubPrNumber: options.githubPrNumber,
233057
233052
  taskId: options.task.id ?? "unknown",
233058
233053
  targetBranch: options.targetBranch
233059
233054
  })}
233060
- 6. **After ${options.gitFlow.requiresGithubPr ? "pushing" : "committing"}**
233061
- your changes, update the prd.yml to reflect any changes in the task state.
233055
+ 5. **After ${options.gitFlow.requiresGithubPr ? "pushing" : "committing"}** your changes, update the prd.yml to reflect any changes in the task state.
233062
233056
  - Rewrite the notes in the description to include only the key discoveries and information that could speed up future work on other tasks. Make sure to preserve important information such as specification file references.
233063
233057
  - If you believe the task is complete, update the \`state\` to "in-review".
233064
233058
 
@@ -233069,16 +233063,12 @@ Task ID: ${options.task.id}
233069
233063
 
233070
233064
  ${options.task.description}
233071
233065
 
233072
- # Workflow
233066
+ ### Instructions
233073
233067
 
233074
- All steps must be done before the task can be considered complete.
233068
+ All steps must be done before the task can be considered complete.${options.task.description.includes(options.specsDirectory) ? `\nMake sure to review the previous tasks (using "listTasks") for any key information that may help you with this task.` : ""}
233075
233069
 
233076
- 1. Carefully study the current task list to understand the context of the task, and
233077
- discover any key learnings from previous work.
233078
- Also read the ${options.specsDirectory}/README.md file (if available), to see
233079
- if any previous specifications could assist you.
233080
- 2. ${options.gitFlow.setupInstructions(options)}
233081
- 3. Implement the task.
233070
+ 1. ${options.gitFlow.setupInstructions(options)}
233071
+ 2. Implement the task.
233082
233072
  - If this task is a research task, **do not** make any code changes yet.
233083
233073
  - If this task is a research task and you add follow-up tasks, include (at least) "${options.task.id}" in the new task's \`blockedBy\` field.
233084
233074
  - **If at any point** you discover something that needs fixing, or another task
@@ -233086,15 +233076,14 @@ All steps must be done before the task can be considered complete.
233086
233076
  as part of this task.
233087
233077
  - Add important discoveries about the codebase, or challenges faced to the task's
233088
233078
  \`description\`. More details below.
233089
- 4. Run any checks / feedback loops, such as type checks, unit tests, or linting.
233090
- 5. ${options.gitFlow.commitInstructions({
233079
+ 3. Run any checks / feedback loops, such as type checks, unit tests, or linting.
233080
+ 4. ${options.gitFlow.commitInstructions({
233091
233081
  githubPrInstructions: sourceMeta.githubPrInstructions,
233092
233082
  githubPrNumber: options.githubPrNumber,
233093
233083
  taskId: options.task.id ?? "unknown",
233094
233084
  targetBranch: options.targetBranch
233095
233085
  })}
233096
- 6. **After ${options.gitFlow.requiresGithubPr ? "pushing" : "committing"}**
233097
- your changes, update current task to reflect any changes in the task state.
233086
+ 5. **After ${options.gitFlow.requiresGithubPr ? "pushing" : "committing"}** your changes, update current task to reflect any changes in the task state.
233098
233087
  - Rewrite the notes in the description to include only the key discoveries and information that could speed up future work on other tasks. Make sure to preserve important information such as specification file references.
233099
233088
  - If you believe the task is complete, update the \`state\` to "in-review".`;
233100
233089
  const promptReview = (options) => `A previous engineer has completed a task from the instructions below.
@@ -233867,7 +233856,7 @@ const runClanka = fnUntraced(function* (options) {
233867
233856
  const output = yield* pipe$1(agent.send({
233868
233857
  prompt: options.prompt,
233869
233858
  system: options.system
233870
- }), provide$1([models.get(options.model), layerSubagentModel(clankaSubagent(models, options.model))]));
233859
+ }), provide$1(models.get(options.model)));
233871
233860
  yield* muxer.add(output);
233872
233861
  let stream = options.stallTimeout ? withStallTimeout(options.stallTimeout)(output) : output;
233873
233862
  if (options.steer) yield* options.steer.pipe(switchMap(fnUntraced(function* (message) {
@@ -233918,7 +233907,7 @@ const GitFlowPR = succeed$4(GitFlow, GitFlow.of({
233918
233907
  requiresGithubPr: true,
233919
233908
  branch: void 0,
233920
233909
  setupInstructions: ({ githubPrNumber }) => githubPrNumber ? `The Github PR #${githubPrNumber} has been detected for this task and the branch has been checked out.
233921
- - **REVIEW FEEDBACK** in the .lalph/feedback.md file.` : `Create a new branch for the task using the format \`{task id}/description\`, using the current HEAD as the base (don't checkout any other branches first).`,
233910
+ - **REVIEW ALL FEEDBACK** in the .lalph/feedback.md file.` : `You are currently on a new branch for this task. You do not need to checkout any other branches.`,
233922
233911
  commitInstructions: (options) => `${!options.githubPrNumber ? `Create a pull request for this task. If the target branch does not exist, create it first.` : "Commit and push your changes to the pull request."}
233923
233912
  ${options.githubPrInstructions}
233924
233913
  The PR description should include a summary of the changes made.${options.targetBranch ? `\n - The target branch for the PR should be \`${options.targetBranch}\`.` : ""}
@@ -234185,6 +234174,10 @@ const run = fnUntraced(function* (options) {
234185
234174
  yield* worktree.exec`gh pr checkout ${chosenTask.githubPrNumber}`;
234186
234175
  const feedback = yield* gh.prFeedbackMd(chosenTask.githubPrNumber);
234187
234176
  yield* fs.writeFileString(pathService.join(worktree.directory, ".lalph", "feedback.md"), feedback);
234177
+ } else if (gitFlow.requiresGithubPr) {
234178
+ const branchName = `lalph/${taskId.replace(/#/g, "").replace(/[^a-zA-Z0-9-_]/g, "-")}`;
234179
+ yield* worktree.exec`git branch -D ${branchName}`;
234180
+ yield* worktree.exec`git checkout -b ${branchName}`;
234188
234181
  }
234189
234182
  const taskPreset = getOrElse$2(yield* source.issueCliAgentPreset(chosenTask.prd), () => preset);
234190
234183
  const catchStallInReview = (effect) => catchIf$2(effect, (u) => u instanceof RunnerStalled, fnUntraced(function* (e) {
@@ -234627,7 +234620,7 @@ const commandEdit = make$46("edit").pipe(withDescription("Open the selected proj
234627
234620
  const commandSource = make$46("source").pipe(withDescription("Select the issue source to use (e.g. GitHub Issues or Linear). This applies to all projects."), withHandler(() => selectIssueSource), provide(Settings.layer));
234628
234621
  //#endregion
234629
234622
  //#region package.json
234630
- var version = "0.3.54";
234623
+ var version = "0.3.56";
234631
234624
  //#endregion
234632
234625
  //#region src/commands/projects/ls.ts
234633
234626
  const commandProjectsLs = make$46("ls").pipe(withDescription("List configured projects and how they run (enabled state, concurrency, branch, git flow, review agent)."), withHandler(fnUntraced(function* () {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lalph",
3
3
  "type": "module",
4
- "version": "0.3.54",
4
+ "version": "0.3.56",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
package/src/Clanka.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Agent, OutputFormatter } from "clanka"
2
2
  import { Duration, Effect, Layer, pipe, Stdio, Stream } from "effect"
3
3
  import { TaskChooseTools, TaskTools, TaskToolsHandlers } from "./TaskTools.ts"
4
- import { ClankaModels, clankaSubagent } from "./ClankaModels.ts"
4
+ import { ClankaModels } from "./ClankaModels.ts"
5
5
  import { withStallTimeout } from "./shared/stream.ts"
6
6
  import { NodeHttpClient } from "@effect/platform-node"
7
7
 
@@ -32,10 +32,7 @@ export const runClanka = Effect.fnUntraced(
32
32
  prompt: options.prompt,
33
33
  system: options.system,
34
34
  }),
35
- Effect.provide([
36
- models.get(options.model),
37
- Agent.layerSubagentModel(clankaSubagent(models, options.model)),
38
- ]),
35
+ Effect.provide(models.get(options.model)),
39
36
  )
40
37
 
41
38
  yield* muxer.add(output)
@@ -1,6 +1,6 @@
1
1
  // oxlint-disable typescript/no-explicit-any
2
2
  import { NodeHttpClient } from "@effect/platform-node"
3
- import { Codex, Copilot } from "clanka"
3
+ import { Agent, Codex, Copilot } from "clanka"
4
4
  import { Effect, flow, Layer, LayerMap, Schema } from "effect"
5
5
  import { layerKvs } from "./Kvs.ts"
6
6
 
@@ -20,38 +20,45 @@ const parseInput = flow(
20
20
  Effect.orDie,
21
21
  )
22
22
 
23
- export const clankaSubagent = Effect.fnUntraced(function* (
24
- models: ClankaModels["Service"],
25
- input: string,
26
- ) {
27
- const [provider, model] = yield* parseInput(input.split("/"))
28
- return models.get(`${provider}/${model}/low`)
29
- }, Layer.unwrap)
30
-
31
23
  export class ClankaModels extends LayerMap.Service<ClankaModels>()(
32
24
  "lalph/ClankaModels",
33
25
  {
34
26
  dependencies: [ModelServices],
35
27
  lookup: Effect.fnUntraced(function* (input: string) {
36
28
  const [provider, model, reasoning] = yield* parseInput(input.split("/"))
37
- switch (provider) {
38
- case "openai": {
39
- return Codex.model(model, {
40
- reasoning: {
41
- effort: reasoning,
42
- },
43
- })
44
- }
45
- case "copilot": {
46
- return Copilot.model(model, {
47
- ...reasoningToCopilotConfig(model, reasoning),
48
- })
49
- }
29
+ const layer = resolve(provider, model, reasoning)
30
+ if (reasoning === "low" || reasoning === "medium") {
31
+ return layer
50
32
  }
33
+ return Layer.merge(
34
+ layer,
35
+ Agent.layerSubagentModel(resolve(provider, model, "medium")),
36
+ )
51
37
  }, Layer.unwrap),
52
38
  },
53
39
  ) {}
54
40
 
41
+ const resolve = (
42
+ provider: "openai" | "copilot",
43
+ model: string,
44
+ reasoning: typeof Reasoning.Type,
45
+ ) => {
46
+ switch (provider) {
47
+ case "openai": {
48
+ return Codex.model(model, {
49
+ reasoning: {
50
+ effort: reasoning,
51
+ },
52
+ })
53
+ }
54
+ case "copilot": {
55
+ return Copilot.model(model, {
56
+ ...reasoningToCopilotConfig(model, reasoning),
57
+ })
58
+ }
59
+ }
60
+ }
61
+
55
62
  const reasoningToCopilotConfig = (
56
63
  model: string,
57
64
  reasoning: typeof Reasoning.Type,
package/src/GitFlow.ts CHANGED
@@ -61,8 +61,8 @@ export const GitFlowPR = Layer.succeed(
61
61
  setupInstructions: ({ githubPrNumber }) =>
62
62
  githubPrNumber
63
63
  ? `The Github PR #${githubPrNumber} has been detected for this task and the branch has been checked out.
64
- - **REVIEW FEEDBACK** in the .lalph/feedback.md file.`
65
- : `Create a new branch for the task using the format \`{task id}/description\`, using the current HEAD as the base (don't checkout any other branches first).`,
64
+ - **REVIEW ALL FEEDBACK** in the .lalph/feedback.md file.`
65
+ : `You are currently on a new branch for this task. You do not need to checkout any other branches.`,
66
66
 
67
67
  commitInstructions: (
68
68
  options,
package/src/PromptGen.ts CHANGED
@@ -178,24 +178,22 @@ ${taskGuidelines(options)}`
178
178
  readonly specsDirectory: string
179
179
  readonly githubPrNumber: number | undefined
180
180
  readonly gitFlow: GitFlow["Service"]
181
- }) => `# The task
181
+ }) => `# ${options.task.title}
182
182
 
183
- ID: ${options.task.id}
184
- Task: ${options.task.title}
185
- Description:
183
+ Task ID: ${options.task.id}
186
184
 
187
185
  ${options.task.description}
188
186
 
189
- # Instructions
187
+ ### Instructions
190
188
 
191
- Your job is to implement the task described above.
189
+ Your job is to implement the task described above.${
190
+ options.task.description.includes(options.specsDirectory)
191
+ ? `\nMake sure to review the prd.yml for any key information that may help you with this task.`
192
+ : ""
193
+ }
192
194
 
193
- 1. Carefully study the prd.yml file to understand the context of the task, and
194
- discover any key learnings from previous work.
195
- Also read the ${options.specsDirectory}/README.md file (if available), to see
196
- if any previous specifications could assist you.
197
- 2. ${options.gitFlow.setupInstructions(options)}
198
- 3. Implement the task.
195
+ 1. ${options.gitFlow.setupInstructions(options)}
196
+ 2. Implement the task.
199
197
  - If this task is a research task, **do not** make any code changes yet.
200
198
  - If this task is a research task and you add follow-up tasks, include (at least) "${options.task.id}" in the new task's \`blockedBy\` field.
201
199
  - **If at any point** you discover something that needs fixing, or another task
@@ -203,15 +201,14 @@ Your job is to implement the task described above.
203
201
  you plan to fix it as part of this task.
204
202
  - Add important discoveries about the codebase, or challenges faced to the task's
205
203
  \`description\`. More details below.
206
- 4. Run any checks / feedback loops, such as type checks, unit tests, or linting.
207
- 5. ${options.gitFlow.commitInstructions({
204
+ 3. Run any checks / feedback loops, such as type checks, unit tests, or linting.
205
+ 4. ${options.gitFlow.commitInstructions({
208
206
  githubPrInstructions: sourceMeta.githubPrInstructions,
209
207
  githubPrNumber: options.githubPrNumber,
210
208
  taskId: options.task.id ?? "unknown",
211
209
  targetBranch: options.targetBranch,
212
210
  })}
213
- 6. **After ${options.gitFlow.requiresGithubPr ? "pushing" : "committing"}**
214
- your changes, update the prd.yml to reflect any changes in the task state.
211
+ 5. **After ${options.gitFlow.requiresGithubPr ? "pushing" : "committing"}** your changes, update the prd.yml to reflect any changes in the task state.
215
212
  - Rewrite the notes in the description to include only the key discoveries and information that could speed up future work on other tasks. Make sure to preserve important information such as specification file references.
216
213
  - If you believe the task is complete, update the \`state\` to "in-review".
217
214
 
@@ -229,16 +226,16 @@ Task ID: ${options.task.id}
229
226
 
230
227
  ${options.task.description}
231
228
 
232
- # Workflow
229
+ ### Instructions
233
230
 
234
- All steps must be done before the task can be considered complete.
231
+ All steps must be done before the task can be considered complete.${
232
+ options.task.description.includes(options.specsDirectory)
233
+ ? `\nMake sure to review the previous tasks (using "listTasks") for any key information that may help you with this task.`
234
+ : ""
235
+ }
235
236
 
236
- 1. Carefully study the current task list to understand the context of the task, and
237
- discover any key learnings from previous work.
238
- Also read the ${options.specsDirectory}/README.md file (if available), to see
239
- if any previous specifications could assist you.
240
- 2. ${options.gitFlow.setupInstructions(options)}
241
- 3. Implement the task.
237
+ 1. ${options.gitFlow.setupInstructions(options)}
238
+ 2. Implement the task.
242
239
  - If this task is a research task, **do not** make any code changes yet.
243
240
  - If this task is a research task and you add follow-up tasks, include (at least) "${options.task.id}" in the new task's \`blockedBy\` field.
244
241
  - **If at any point** you discover something that needs fixing, or another task
@@ -246,15 +243,14 @@ All steps must be done before the task can be considered complete.
246
243
  as part of this task.
247
244
  - Add important discoveries about the codebase, or challenges faced to the task's
248
245
  \`description\`. More details below.
249
- 4. Run any checks / feedback loops, such as type checks, unit tests, or linting.
250
- 5. ${options.gitFlow.commitInstructions({
246
+ 3. Run any checks / feedback loops, such as type checks, unit tests, or linting.
247
+ 4. ${options.gitFlow.commitInstructions({
251
248
  githubPrInstructions: sourceMeta.githubPrInstructions,
252
249
  githubPrNumber: options.githubPrNumber,
253
250
  taskId: options.task.id ?? "unknown",
254
251
  targetBranch: options.targetBranch,
255
252
  })}
256
- 6. **After ${options.gitFlow.requiresGithubPr ? "pushing" : "committing"}**
257
- your changes, update current task to reflect any changes in the task state.
253
+ 5. **After ${options.gitFlow.requiresGithubPr ? "pushing" : "committing"}** your changes, update current task to reflect any changes in the task state.
258
254
  - Rewrite the notes in the description to include only the key discoveries and information that could speed up future work on other tasks. Make sure to preserve important information such as specification file references.
259
255
  - If you believe the task is complete, update the \`state\` to "in-review".`
260
256
 
@@ -178,6 +178,10 @@ const run = Effect.fnUntraced(
178
178
  pathService.join(worktree.directory, ".lalph", "feedback.md"),
179
179
  feedback,
180
180
  )
181
+ } else if (gitFlow.requiresGithubPr) {
182
+ const branchName = `lalph/${taskId.replace(/#/g, "").replace(/[^a-zA-Z0-9-_]/g, "-")}`
183
+ yield* worktree.exec`git branch -D ${branchName}`
184
+ yield* worktree.exec`git checkout -b ${branchName}`
181
185
  }
182
186
 
183
187
  const taskPreset = Option.getOrElse(