lalph 0.3.7 → 0.3.9

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
@@ -6268,7 +6268,7 @@ const append$1 = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
6268
6268
  * @category concatenating
6269
6269
  * @since 2.0.0
6270
6270
  */
6271
- const appendAll$2 = /* @__PURE__ */ dual(2, (self, that) => fromIterable$4(self).concat(fromIterable$4(that)));
6271
+ const appendAll$1 = /* @__PURE__ */ dual(2, (self, that) => fromIterable$4(self).concat(fromIterable$4(that)));
6272
6272
  /**
6273
6273
  * Determine if `unknown` is an Array.
6274
6274
  *
@@ -6574,7 +6574,7 @@ const unionWith = /* @__PURE__ */ dual(3, (self, that, isEquivalent) => {
6574
6574
  const a = fromIterable$4(self);
6575
6575
  const b = fromIterable$4(that);
6576
6576
  if (isReadonlyArrayNonEmpty(a)) {
6577
- if (isReadonlyArrayNonEmpty(b)) return dedupeWith(isEquivalent)(appendAll$2(a, b));
6577
+ if (isReadonlyArrayNonEmpty(b)) return dedupeWith(isEquivalent)(appendAll$1(a, b));
6578
6578
  return a;
6579
6579
  }
6580
6580
  return b;
@@ -25930,7 +25930,7 @@ const drop = /* @__PURE__ */ dual(2, (self, n) => {
25930
25930
  * @category concatenating
25931
25931
  * @since 2.0.0
25932
25932
  */
25933
- const appendAll$1 = /* @__PURE__ */ dual(2, (self, that) => {
25933
+ const appendAll = /* @__PURE__ */ dual(2, (self, that) => {
25934
25934
  if (self.backing._tag === "IEmpty") return that;
25935
25935
  if (that.backing._tag === "IEmpty") return self;
25936
25936
  const diff = that.depth - self.depth;
@@ -25940,14 +25940,14 @@ const appendAll$1 = /* @__PURE__ */ dual(2, (self, that) => {
25940
25940
  right: that
25941
25941
  });
25942
25942
  else if (diff < -1) if (self.left.depth >= self.right.depth) {
25943
- const nr = appendAll$1(self.right, that);
25943
+ const nr = appendAll(self.right, that);
25944
25944
  return makeChunk({
25945
25945
  _tag: "IConcat",
25946
25946
  left: self.left,
25947
25947
  right: nr
25948
25948
  });
25949
25949
  } else {
25950
- const nrr = appendAll$1(self.right.right, that);
25950
+ const nrr = appendAll(self.right.right, that);
25951
25951
  if (nrr.depth === self.depth - 3) {
25952
25952
  const nr = makeChunk({
25953
25953
  _tag: "IConcat",
@@ -25971,11 +25971,11 @@ const appendAll$1 = /* @__PURE__ */ dual(2, (self, that) => {
25971
25971
  }
25972
25972
  else if (that.right.depth >= that.left.depth) return makeChunk({
25973
25973
  _tag: "IConcat",
25974
- left: appendAll$1(self, that.left),
25974
+ left: appendAll(self, that.left),
25975
25975
  right: that.right
25976
25976
  });
25977
25977
  else {
25978
- const nll = appendAll$1(self, that.left.left);
25978
+ const nll = appendAll(self, that.left.left);
25979
25979
  if (nll.depth === that.depth - 3) return makeChunk({
25980
25980
  _tag: "IConcat",
25981
25981
  left: makeChunk({
@@ -26472,42 +26472,6 @@ const runIn = fiberRunIn;
26472
26472
  //#endregion
26473
26473
  //#region node_modules/.pnpm/effect@https+++pkg.pr.new+Effect-TS+effect-smol+effect@3519468_8750329d33fefc387eb55044ef2141e0/node_modules/effect/dist/MutableList.js
26474
26474
  /**
26475
- * @fileoverview
26476
- * MutableList is an efficient, mutable linked list implementation optimized for high-throughput
26477
- * scenarios like logging, queuing, and streaming. It uses a bucket-based architecture where
26478
- * elements are stored in arrays (buckets) linked together, providing optimal performance for
26479
- * both append and prepend operations.
26480
- *
26481
- * The implementation uses a sophisticated bucket system:
26482
- * - Each bucket contains an array of elements with an offset pointer
26483
- * - Buckets can be marked as mutable or immutable for optimization
26484
- * - Elements are taken from the head and added to the tail
26485
- * - Memory is efficiently managed through bucket reuse and cleanup
26486
- *
26487
- * Key Features:
26488
- * - Highly optimized for high-frequency append/prepend operations
26489
- * - Memory efficient with automatic cleanup of consumed elements
26490
- * - Support for bulk operations (appendAll, prependAll, takeN)
26491
- * - Filtering and removal operations
26492
- * - Zero-copy optimizations for certain scenarios
26493
- *
26494
- * Performance Characteristics:
26495
- * - Append/Prepend: O(1) amortized
26496
- * - Take/TakeN: O(1) per element taken
26497
- * - Length: O(1)
26498
- * - Clear: O(1)
26499
- * - Filter: O(n)
26500
- *
26501
- * Ideal Use Cases:
26502
- * - High-throughput logging systems
26503
- * - Producer-consumer queues
26504
- * - Streaming data buffers
26505
- * - Real-time data processing pipelines
26506
- *
26507
- * @since 4.0.0
26508
- * @category data-structures
26509
- */
26510
- /**
26511
26475
  * A unique symbol used to represent an empty result when taking elements from a MutableList.
26512
26476
  * This symbol is returned by `take` when the list is empty, allowing for safe type checking.
26513
26477
  *
@@ -26621,92 +26585,6 @@ const append = (self, message) => {
26621
26585
  self.length++;
26622
26586
  };
26623
26587
  /**
26624
- * Appends all elements from an iterable to the end of the MutableList.
26625
- * Returns the number of elements added.
26626
- *
26627
- * @example
26628
- * ```ts
26629
- * import * as MutableList from "effect/MutableList"
26630
- *
26631
- * const list = MutableList.make<number>()
26632
- * MutableList.append(list, 1)
26633
- * MutableList.append(list, 2)
26634
- *
26635
- * // Append multiple elements
26636
- * const added = MutableList.appendAll(list, [3, 4, 5])
26637
- * console.log(added) // 3
26638
- * console.log(list.length) // 5
26639
- *
26640
- * // Elements maintain order: [1, 2, 3, 4, 5]
26641
- * console.log(MutableList.takeAll(list)) // [1, 2, 3, 4, 5]
26642
- *
26643
- * // Works with any iterable
26644
- * const newList = MutableList.make<string>()
26645
- * MutableList.appendAll(newList, new Set(["a", "b", "c"]))
26646
- * console.log(MutableList.takeAll(newList)) // ["a", "b", "c"]
26647
- *
26648
- * // Useful for bulk loading
26649
- * const bulkList = MutableList.make<number>()
26650
- * const count = MutableList.appendAll(
26651
- * bulkList,
26652
- * Array.from({ length: 1000 }, (_, i) => i)
26653
- * )
26654
- * console.log(count) // 1000
26655
- * ```
26656
- *
26657
- * @since 4.0.0
26658
- * @category mutations
26659
- */
26660
- const appendAll = (self, messages) => appendAllUnsafe(self, fromIterable$4(messages), !Array.isArray(messages));
26661
- /**
26662
- * Appends all elements from a ReadonlyArray to the end of the MutableList.
26663
- * This is an optimized version that can reuse the array when mutable=true.
26664
- * Returns the number of elements added.
26665
- *
26666
- * ⚠️ **Warning**: When mutable=true, the input array may be modified internally.
26667
- * Only use mutable=true when you control the array lifecycle.
26668
- *
26669
- * @example
26670
- * ```ts
26671
- * import * as MutableList from "effect/MutableList"
26672
- *
26673
- * const list = MutableList.make<number>()
26674
- * MutableList.append(list, 1)
26675
- *
26676
- * // Safe usage (default mutable=false)
26677
- * const items = [2, 3, 4]
26678
- * const added = MutableList.appendAllUnsafe(list, items)
26679
- * console.log(added) // 3
26680
- * console.log(items) // [2, 3, 4] - unchanged
26681
- *
26682
- * // Unsafe but efficient usage (mutable=true)
26683
- * const mutableItems = [5, 6, 7]
26684
- * MutableList.appendAllUnsafe(list, mutableItems, true)
26685
- * // mutableItems may be modified internally for efficiency
26686
- *
26687
- * console.log(MutableList.takeAll(list)) // [1, 2, 3, 4, 5, 6, 7]
26688
- *
26689
- * // High-performance bulk operations
26690
- * const bigArray = new Array(10000).fill(0).map((_, i) => i)
26691
- * MutableList.appendAllUnsafe(list, bigArray, true) // Very efficient
26692
- * ```
26693
- *
26694
- * @since 4.0.0
26695
- * @category mutations
26696
- */
26697
- const appendAllUnsafe = (self, messages, mutable = false) => {
26698
- const chunk = {
26699
- array: messages,
26700
- mutable,
26701
- offset: 0,
26702
- next: void 0
26703
- };
26704
- if (self.head) self.tail = self.tail.next = chunk;
26705
- else self.head = self.tail = chunk;
26706
- self.length += messages.length;
26707
- return messages.length;
26708
- };
26709
- /**
26710
26588
  * Removes all elements from the MutableList, resetting it to an empty state.
26711
26589
  * This operation is highly optimized and releases all internal memory.
26712
26590
  *
@@ -27333,9 +27211,6 @@ var PubSubImpl = class {
27333
27211
 
27334
27212
  //#endregion
27335
27213
  //#region node_modules/.pnpm/effect@https+++pkg.pr.new+Effect-TS+effect-smol+effect@3519468_8750329d33fefc387eb55044ef2141e0/node_modules/effect/dist/Queue.js
27336
- /**
27337
- * @since 3.8.0
27338
- */
27339
27214
  const TypeId$47 = "~effect/Queue";
27340
27215
  const EnqueueTypeId = "~effect/Queue/Enqueue";
27341
27216
  const DequeueTypeId = "~effect/Queue/Dequeue";
@@ -27532,84 +27407,6 @@ const offerUnsafe = (self, message) => {
27532
27407
  return true;
27533
27408
  };
27534
27409
  /**
27535
- * Add multiple messages to the queue. Returns the remaining messages that
27536
- * were not added.
27537
- *
27538
- * For bounded queues, this operation may suspend if the queue doesn't have
27539
- * enough capacity. The operation returns an array of messages that couldn't
27540
- * be added (empty array means all messages were successfully added).
27541
- *
27542
- * @example
27543
- * ```ts
27544
- * import { Cause, Effect, Queue } from "effect"
27545
- *
27546
- * const program = Effect.gen(function*() {
27547
- * const queue = yield* Queue.bounded<number>(3)
27548
- *
27549
- * // Try to add more messages than capacity
27550
- * const remaining1 = yield* Queue.offerAll(queue, [1, 2, 3, 4, 5])
27551
- * console.log(remaining1) // [4, 5] - couldn't fit the last 2
27552
- * })
27553
- * ```
27554
- *
27555
- * @category Offering
27556
- * @since 4.0.0
27557
- */
27558
- const offerAll = (self, messages) => suspend$4(() => {
27559
- if (self.state._tag !== "Open") return succeed$5(fromIterable$4(messages));
27560
- const remaining = offerAllUnsafe(self, messages);
27561
- if (remaining.length === 0) return exitSucceed([]);
27562
- else if (self.strategy === "dropping") return succeed$5(remaining);
27563
- return offerRemainingArray(self, remaining);
27564
- });
27565
- /**
27566
- * Add multiple messages to the queue synchronously. Returns the remaining messages that
27567
- * were not added.
27568
- *
27569
- * This is an unsafe operation that directly modifies the queue without Effect wrapping.
27570
- *
27571
- * @example
27572
- * ```ts
27573
- * import { Cause, Effect, Queue } from "effect"
27574
- *
27575
- * // Create a bounded queue and use unsafe API
27576
- * const program = Effect.gen(function*() {
27577
- * const queue = yield* Queue.bounded<number>(3)
27578
- *
27579
- * // Try to add 5 messages to capacity-3 queue using unsafe API
27580
- * const remaining = Queue.offerAllUnsafe(queue, [1, 2, 3, 4, 5])
27581
- * console.log(remaining) // [4, 5] - couldn't fit the last 2
27582
- *
27583
- * // Check what's in the queue
27584
- * const size = Queue.sizeUnsafe(queue)
27585
- * console.log(size) // 3
27586
- * })
27587
- * ```
27588
- *
27589
- * @category Offering
27590
- * @since 4.0.0
27591
- */
27592
- const offerAllUnsafe = (self, messages) => {
27593
- if (self.state._tag !== "Open") return fromIterable$4(messages);
27594
- else if (self.capacity === Number.POSITIVE_INFINITY || self.strategy === "sliding") {
27595
- appendAll(self.messages, messages);
27596
- if (self.strategy === "sliding") takeN(self.messages, self.messages.length - self.capacity);
27597
- scheduleReleaseTaker(self);
27598
- return [];
27599
- }
27600
- const free = self.capacity <= 0 ? self.state.takers.size : self.capacity - self.messages.length;
27601
- if (free === 0) return fromIterable$4(messages);
27602
- const remaining = [];
27603
- let i = 0;
27604
- for (const message of messages) {
27605
- if (i < free) append(self.messages, message);
27606
- else remaining.push(message);
27607
- i++;
27608
- }
27609
- scheduleReleaseTaker(self);
27610
- return remaining;
27611
- };
27612
- /**
27613
27410
  * Fail the queue with a cause. If the queue is already done, `false` is
27614
27411
  * returned.
27615
27412
  *
@@ -27996,21 +27793,6 @@ const offerRemainingSingle = (self, message) => {
27996
27793
  });
27997
27794
  });
27998
27795
  };
27999
- const offerRemainingArray = (self, remaining) => {
28000
- return callback$2((resume) => {
28001
- if (self.state._tag !== "Open") return resume(exitSucceed(remaining));
28002
- const entry = {
28003
- _tag: "Array",
28004
- remaining,
28005
- offset: 0,
28006
- resume
28007
- };
28008
- self.state.offers.add(entry);
28009
- return sync$1(() => {
28010
- if (self.state._tag === "Open") self.state.offers.delete(entry);
28011
- });
28012
- });
28013
- };
28014
27796
  const releaseCapacity = (self) => {
28015
27797
  if (self.state._tag === "Done") return isDoneCause(self.state.exit.cause);
28016
27798
  else if (self.state.offers.size === 0) {
@@ -29204,23 +28986,6 @@ const unwrap$2 = (channel) => fromTransform$1((upstream, scope) => {
29204
28986
  }));
29205
28987
  });
29206
28988
  /**
29207
- * Allows a faster producer to progress independently of a slower consumer by
29208
- * buffering up to `capacity` elements in a queue.
29209
- *
29210
- * @since 2.0.0
29211
- * @category Buffering
29212
- */
29213
- const bufferArray = /* @__PURE__ */ dual(2, (self, options) => fromTransform$1(fnUntraced(function* (upstream, scope) {
29214
- const pull = yield* toTransform(self)(upstream, scope);
29215
- const queue = yield* make$46({
29216
- capacity: options.capacity === "unbounded" ? void 0 : options.capacity,
29217
- strategy: options.capacity === "unbounded" ? void 0 : options.strategy
29218
- });
29219
- yield* addFinalizer$1(scope, shutdown(queue));
29220
- yield* pull.pipe(flatMap$2((value) => offerAll(queue, value)), forever({ autoYield: false }), onError((cause) => failCause$1(queue, cause)), forkIn(scope));
29221
- return takeAll(queue);
29222
- })));
29223
- /**
29224
28989
  * Returns a new channel with an attached finalizer. The finalizer is
29225
28990
  * guaranteed to be executed so long as the channel begins execution (and
29226
28991
  * regardless of whether or not it completes).
@@ -30952,33 +30717,6 @@ const filter$2 = /* @__PURE__ */ dual(2, (self, predicate) => fromChannel(filter
30952
30717
  */
30953
30718
  const filterMapEffect = /* @__PURE__ */ dual(2, (self, filter) => fromChannel(filterMapArrayEffect(toChannel(self), filter)));
30954
30719
  /**
30955
- * Buffers up to `capacity` elements so a faster producer can progress
30956
- * independently of a slower consumer.
30957
- *
30958
- * Note: This combinator destroys chunking. Use `Stream.rechunk` afterwards if
30959
- * you need fixed chunk sizes.
30960
- *
30961
- * @example
30962
- * ```ts
30963
- * import { Console, Effect, Stream } from "effect"
30964
- *
30965
- * const program = Effect.gen(function*() {
30966
- * const values = yield* Stream.make(1, 2, 3).pipe(
30967
- * Stream.buffer({ capacity: 1 }),
30968
- * Stream.runCollect
30969
- * )
30970
- * yield* Console.log(values)
30971
- * })
30972
- *
30973
- * Effect.runPromise(program)
30974
- * // Output: [ 1, 2, 3 ]
30975
- * ```
30976
- *
30977
- * @since 2.0.0
30978
- * @category Rate Limiting
30979
- */
30980
- const buffer = /* @__PURE__ */ dual(2, (self, options) => fromChannel(bufferArray(self.channel, options)));
30981
- /**
30982
30720
  * Transforms the errors emitted by this stream using `f`.
30983
30721
  *
30984
30722
  * @example
@@ -68652,7 +68390,7 @@ const makeStreamPullEffect = (get, pullSignal, create, options) => flatMap$2(toP
68652
68390
  let items;
68653
68391
  if (options?.disableAccumulation) items = chunk;
68654
68392
  else {
68655
- items = appendAll$2(acc, chunk);
68393
+ items = appendAll$1(acc, chunk);
68656
68394
  acc = items;
68657
68395
  }
68658
68396
  return succeed$1({
@@ -151219,23 +150957,21 @@ To remove a task, simply delete the item from the prd.yml file.
151219
150957
  \`\`\`json
151220
150958
  ${JSON.stringify(PrdIssue.jsonSchema, null, 2)}
151221
150959
  \`\`\``;
151222
- const promptChoose = (options) => `Your job is to choose the next task to work on from the prd.yml file. **DO NOT** implement the task yet.
150960
+ const promptChoose = (options) => `Your job is to choose the next task to work on from the prd.yml file and save it in a task.json file.
150961
+ **DO NOT** implement the task yet.
151223
150962
 
151224
150963
  The following instructions should be done without interaction or asking for permission.
151225
150964
 
151226
150965
  - Decide which single task to work on next from the prd.yml file. This should
151227
- be the task YOU decide as the most important to work on next, not just the
151228
- first task in the list.
151229
- - Only start tasks that are in a "todo" state.
151230
- - You **cannot** start tasks unless they have an empty \`blockedBy\` field.
151231
- - **Before doing anything else**, mark the task as "in-progress" by updating its
151232
- \`state\` in the prd.yml file.
151233
- This prevents other people or agents from working on the same task simultaneously.${options.gitFlow.requiresGithubPr ? `
150966
+ be the task YOU decide as the most important to work on next, not just the
150967
+ first task in the list.
150968
+ - Only start tasks that are in a "todo" state.
150969
+ - You **cannot** start tasks unless they have an empty \`blockedBy\` field.${options.gitFlow.requiresGithubPr ? `
151234
150970
  - Check if there is an open Github PR for the chosen task. If there is, note the PR number for inclusion in the task.json file.
151235
150971
  - Only include "open" PRs that are not yet merged.
151236
150972
  - The pull request will contain the task id in the title or description.` : ""}
151237
150973
  - Once you have chosen a task, save its information in a "task.json" file alongside
151238
- the prd.yml file. Use the following format:
150974
+ the prd.yml file. Use the following format:
151239
150975
 
151240
150976
  \`\`\`json
151241
150977
  {
@@ -151246,8 +150982,7 @@ This prevents other people or agents from working on the same task simultaneousl
151246
150982
 
151247
150983
  Set \`githubPrNumber\` to the PR number if one exists, otherwise use \`null\`.
151248
150984
  ` : "\n\nLeave `githubPrNumber` as null."}
151249
-
151250
- ${prdNotes()}`;
150985
+ `;
151251
150986
  const keyInformation = (options) => `## Important: Adding new tasks
151252
150987
 
151253
150988
  **If at any point** you discover something that needs fixing, or another task
@@ -151768,7 +151503,7 @@ const makeExecHelpers = fnUntraced(function* (options) {
151768
151503
  const handle = yield* provide(command.asEffect());
151769
151504
  yield* handle.all.pipe(decodeText(), options.cliAgent.outputTransformer ? options.cliAgent.outputTransformer : identity, runForEachArray((output) => {
151770
151505
  for (const chunk of output) process.stdout.write(chunk);
151771
- registry.update(worker.output, flow(appendAll$1(fromArrayUnsafe(output)), takeRight(constWorkerMaxOutputChunks)));
151506
+ registry.update(worker.output, flow(appendAll(fromArrayUnsafe(output)), takeRight(constWorkerMaxOutputChunks)));
151772
151507
  return void_$1;
151773
151508
  }));
151774
151509
  return yield* handle.exitCode;
@@ -151788,7 +151523,7 @@ const makeExecHelpers = fnUntraced(function* (options) {
151788
151523
  yield* handle.all.pipe(decodeText(), options.cliAgent.outputTransformer ? options.cliAgent.outputTransformer : identity, runForEachArray((output) => {
151789
151524
  lastOutputAt = nowUnsafe();
151790
151525
  for (const chunk of output) process.stdout.write(chunk);
151791
- registry.update(worker.output, flow(appendAll$1(fromArrayUnsafe(output)), takeRight(constWorkerMaxOutputChunks)));
151526
+ registry.update(worker.output, flow(appendAll(fromArrayUnsafe(output)), takeRight(constWorkerMaxOutputChunks)));
151792
151527
  return void_$1;
151793
151528
  }), raceFirst(stallTimeout));
151794
151529
  return yield* handle.exitCode;
@@ -151924,11 +151659,8 @@ var Prd = class extends Service$1()("lalph/Prd", { make: gen(function* () {
151924
151659
  const nextYaml = PrdIssue.arrayToYaml(sourceIssues).trim();
151925
151660
  if (currentYaml === nextYaml) return;
151926
151661
  yield* fs.writeFileString(prdFile, nextYaml);
151927
- }, scoped$1, syncSemaphore.withPermitsIfAvailable(1), withSpan("Prd.updateSync"), run$3(updateSyncHandle, { onlyIfMissing: true }));
151928
- yield* fs.watch(lalphDir).pipe(debounce(50), buffer({
151929
- capacity: 1,
151930
- strategy: "dropping"
151931
- }), runForEach((_) => clear(updateSyncHandle).pipe(andThen(ignore(sync$2)))), retry$1(forever$1), forkScoped);
151662
+ }, scoped$1, withSpan("Prd.updateSync"), run$3(updateSyncHandle, { onlyIfMissing: true }), syncSemaphore.withPermitsIfAvailable(1));
151663
+ yield* fs.watch(lalphDir).pipe(debounce(50), runForEach((_) => clear(updateSyncHandle).pipe(andThen(ignore(sync$2)))), retry$1(forever$1), forkScoped);
151932
151664
  yield* toStreamResult(registry, currentIssuesAtom(projectId)).pipe(runForEach(updateSync), forkScoped);
151933
151665
  const findById = fnUntraced(function* (issueId) {
151934
151666
  return (yield* getCurrentIssues).find((i) => i.id === issueId) ?? null;
@@ -152092,7 +151824,7 @@ const agentChooser = fnUntraced(function* (options) {
152092
151824
  }), raceFirst(taskJsonCreated));
152093
151825
  return yield* pipe(fs.readFileString(pathService.join(worktree.directory, ".lalph", "task.json")), flatMap$2(decodeEffect(ChosenTask)), mapError$2((_) => new ChosenTaskNotFound()), flatMap$2(fnUntraced(function* (task) {
152094
151826
  const prdTask = yield* prd.findById(task.id);
152095
- if (prdTask?.state === "in-progress") return {
151827
+ if (prdTask) return {
152096
151828
  ...task,
152097
151829
  prd: prdTask
152098
151830
  };
@@ -152190,6 +151922,11 @@ const run = fnUntraced(function* (options) {
152190
151922
  preset
152191
151923
  }).pipe(withSpan("Main.agentChooser"));
152192
151924
  taskId = chosenTask.id;
151925
+ yield* source.updateIssue({
151926
+ projectId,
151927
+ issueId: taskId,
151928
+ state: "in-progress"
151929
+ });
152193
151930
  yield* prd.setChosenIssueId(taskId);
152194
151931
  yield* prd.setAutoMerge(chosenTask.prd.autoMerge);
152195
151932
  yield* source.ensureInProgress(projectId, taskId).pipe(timeoutOrElse({
@@ -152328,6 +152065,7 @@ const commandRoot = make$35("lalph", {
152328
152065
  const watchTaskState = fnUntraced(function* (options) {
152329
152066
  const registry = yield* AtomRegistry;
152330
152067
  const projectId = yield* CurrentProjectId;
152068
+ yield* sleep(seconds(10));
152331
152069
  return yield* toStreamResult(registry, currentIssuesAtom(projectId)).pipe(runForEach((issues) => {
152332
152070
  const issue = issues.find((entry) => entry.id === options.issueId);
152333
152071
  if (!issue) return fail$4(new TaskStateChanged({
@@ -152557,7 +152295,7 @@ const commandSource = make$35("source").pipe(withDescription("Select the issue s
152557
152295
 
152558
152296
  //#endregion
152559
152297
  //#region package.json
152560
- var version = "0.3.7";
152298
+ var version = "0.3.9";
152561
152299
 
152562
152300
  //#endregion
152563
152301
  //#region src/commands/projects/ls.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lalph",
3
3
  "type": "module",
4
- "version": "0.3.7",
4
+ "version": "0.3.9",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -52,9 +52,7 @@ export const agentChooser = Effect.fnUntraced(function* (options: {
52
52
  Effect.flatMap(
53
53
  Effect.fnUntraced(function* (task) {
54
54
  const prdTask = yield* prd.findById(task.id)
55
- if (prdTask?.state === "in-progress") {
56
- return { ...task, prd: prdTask }
57
- }
55
+ if (prdTask) return { ...task, prd: prdTask }
58
56
  return yield* new ChosenTaskNotFound()
59
57
  }),
60
58
  ),
package/src/Prd.ts CHANGED
@@ -224,17 +224,13 @@ export class Prd extends ServiceMap.Service<
224
224
  yield* fs.writeFileString(prdFile, nextYaml)
225
225
  },
226
226
  Effect.scoped,
227
- syncSemaphore.withPermitsIfAvailable(1),
228
227
  Effect.withSpan("Prd.updateSync"),
229
228
  FiberHandle.run(updateSyncHandle, { onlyIfMissing: true }),
229
+ syncSemaphore.withPermitsIfAvailable(1),
230
230
  )
231
231
 
232
232
  yield* fs.watch(lalphDir).pipe(
233
233
  Stream.debounce(50),
234
- Stream.buffer({
235
- capacity: 1,
236
- strategy: "dropping",
237
- }),
238
234
  Stream.runForEach((_) =>
239
235
  FiberHandle.clear(updateSyncHandle).pipe(
240
236
  Effect.andThen(Effect.ignore(sync)),
package/src/PromptGen.ts CHANGED
@@ -74,27 +74,25 @@ ${JSON.stringify(PrdIssue.jsonSchema, null, 2)}
74
74
 
75
75
  const promptChoose = (options: {
76
76
  readonly gitFlow: GitFlow["Service"]
77
- }) => `Your job is to choose the next task to work on from the prd.yml file. **DO NOT** implement the task yet.
77
+ }) => `Your job is to choose the next task to work on from the prd.yml file and save it in a task.json file.
78
+ **DO NOT** implement the task yet.
78
79
 
79
80
  The following instructions should be done without interaction or asking for permission.
80
81
 
81
82
  - Decide which single task to work on next from the prd.yml file. This should
82
- be the task YOU decide as the most important to work on next, not just the
83
- first task in the list.
84
- - Only start tasks that are in a "todo" state.
85
- - You **cannot** start tasks unless they have an empty \`blockedBy\` field.
86
- - **Before doing anything else**, mark the task as "in-progress" by updating its
87
- \`state\` in the prd.yml file.
88
- This prevents other people or agents from working on the same task simultaneously.${
89
- options.gitFlow.requiresGithubPr
90
- ? `
83
+ be the task YOU decide as the most important to work on next, not just the
84
+ first task in the list.
85
+ - Only start tasks that are in a "todo" state.
86
+ - You **cannot** start tasks unless they have an empty \`blockedBy\` field.${
87
+ options.gitFlow.requiresGithubPr
88
+ ? `
91
89
  - Check if there is an open Github PR for the chosen task. If there is, note the PR number for inclusion in the task.json file.
92
90
  - Only include "open" PRs that are not yet merged.
93
91
  - The pull request will contain the task id in the title or description.`
94
- : ""
95
- }
92
+ : ""
93
+ }
96
94
  - Once you have chosen a task, save its information in a "task.json" file alongside
97
- the prd.yml file. Use the following format:
95
+ the prd.yml file. Use the following format:
98
96
 
99
97
  \`\`\`json
100
98
  {
@@ -109,8 +107,7 @@ Set \`githubPrNumber\` to the PR number if one exists, otherwise use \`null\`.
109
107
  `
110
108
  : "\n\nLeave `githubPrNumber` as null."
111
109
  }
112
-
113
- ${prdNotes()}`
110
+ `
114
111
 
115
112
  const keyInformation = (options: {
116
113
  readonly specsDirectory: string
@@ -111,6 +111,11 @@ const run = Effect.fnUntraced(
111
111
  }).pipe(Effect.withSpan("Main.agentChooser"))
112
112
 
113
113
  taskId = chosenTask.id
114
+ yield* source.updateIssue({
115
+ projectId,
116
+ issueId: taskId,
117
+ state: "in-progress",
118
+ })
114
119
  yield* prd.setChosenIssueId(taskId)
115
120
  yield* prd.setAutoMerge(chosenTask.prd.autoMerge)
116
121
 
@@ -414,6 +419,8 @@ const watchTaskState = Effect.fnUntraced(function* (options: {
414
419
  const registry = yield* AtomRegistry.AtomRegistry
415
420
  const projectId = yield* CurrentProjectId
416
421
 
422
+ yield* Effect.sleep(Duration.seconds(10))
423
+
417
424
  return yield* AtomRegistry.toStreamResult(
418
425
  registry,
419
426
  currentIssuesAtom(projectId),