lalph 0.3.95 → 0.3.97

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lalph",
3
3
  "type": "module",
4
- "version": "0.3.95",
4
+ "version": "0.3.97",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -44,8 +44,8 @@
44
44
  "@linear/sdk": "^78.0.0",
45
45
  "@octokit/plugin-rest-endpoint-methods": "^17.0.0",
46
46
  "@octokit/types": "^16.0.0",
47
- "@typescript/native-preview": "7.0.0-dev.20260320.1",
48
- "clanka": "^0.2.21",
47
+ "@typescript/native-preview": "7.0.0-dev.20260321.1",
48
+ "clanka": "^0.2.26",
49
49
  "concurrently": "^9.2.1",
50
50
  "effect": "4.0.0-beta.36",
51
51
  "husky": "^9.1.7",
package/src/Clanka.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Agent, OutputFormatter, SemanticSearch } from "clanka"
1
+ import * as Agent from "clanka/Agent"
2
+ import * as OutputFormatter from "clanka/OutputFormatter"
2
3
  import {
3
4
  Cause,
4
5
  Config,
@@ -18,6 +19,7 @@ import { NodeHttpClient } from "@effect/platform-node"
18
19
  import type { Prompt } from "effect/unstable/ai"
19
20
  import { OpenAiClient, OpenAiEmbeddingModel } from "@effect/ai-openai"
20
21
  import { Worktree } from "./Worktree.ts"
22
+ import { SemanticSearch } from "clanka"
21
23
 
22
24
  export const ClankaMuxerLayer = Layer.effectDiscard(
23
25
  Effect.gen(function* () {
@@ -8,15 +8,14 @@ import {
8
8
  Schema,
9
9
  ScopedRef,
10
10
  ServiceMap,
11
+ SubscriptionRef,
11
12
  } from "effect"
12
13
  import { allProjects, CurrentProjectId, Setting, Settings } from "./Settings.ts"
13
14
  import { LinearIssueSource } from "./Linear.ts"
14
15
  import { Prompt } from "effect/unstable/cli"
15
16
  import { GithubIssueSource } from "./Github.ts"
16
- import { IssueSource } from "./IssueSource.ts"
17
+ import { IssuesChange, IssueSource } from "./IssueSource.ts"
17
18
  import { PlatformServices } from "./shared/platform.ts"
18
- import { atomRuntime } from "./shared/runtime.ts"
19
- import { Atom, Reactivity } from "effect/unstable/reactivity"
20
19
  import type { PrdIssue } from "./domain/PrdIssue.ts"
21
20
  import type { Project, ProjectId } from "./domain/Project.ts"
22
21
  import type { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"
@@ -109,6 +108,16 @@ export class CurrentIssueSource extends ServiceMap.Service<
109
108
  )
110
109
 
111
110
  const proxy = IssueSource.of({
111
+ ref: (projectId) =>
112
+ ScopedRef.get(ref).pipe(
113
+ Effect.flatMap((source) => source.ref(projectId)),
114
+ unlessRalph(
115
+ projectId,
116
+ SubscriptionRef.make<IssuesChange>(
117
+ IssuesChange.Internal({ issues: [] }),
118
+ ),
119
+ ),
120
+ ),
112
121
  issues: (projectId) =>
113
122
  ScopedRef.get(ref).pipe(
114
123
  Effect.flatMap((source) => source.issues(projectId)),
@@ -186,35 +195,16 @@ const refreshSchedule = Schedule.exponential(100, 1.5).pipe(
186
195
  Schedule.either(Schedule.spaced("30 seconds")),
187
196
  )
188
197
 
189
- // Atoms
190
-
191
- export const issueSourceRuntime = atomRuntime(
192
- CurrentIssueSource.layer.pipe(Layer.orDie),
193
- )
194
-
195
- export const currentIssuesAtom = Atom.family((projectId: ProjectId) =>
196
- pipe(
197
- issueSourceRuntime.atom(
198
- IssueSource.use((s) => s.issues(projectId)).pipe(
199
- Effect.withSpan("currentIssuesAtom"),
200
- ),
201
- ),
202
- atomRuntime.withReactivity([`issues:${projectId}`]),
203
- Atom.withRefresh("30 seconds"),
204
- Atom.keepAlive,
205
- ),
206
- )
207
-
208
198
  // Helpers
209
199
 
210
200
  const getCurrentIssues = (projectId: ProjectId) =>
211
- Atom.getResult(currentIssuesAtom(projectId), {
212
- suspendOnWaiting: true,
213
- })
201
+ IssueSource.use((s) =>
202
+ pipe(s.ref(projectId), Effect.flatMap(SubscriptionRef.get)),
203
+ )
214
204
 
215
205
  export const checkForWork = Effect.fnUntraced(function* (project: Project) {
216
206
  if (project.gitFlow === "ralph") return
217
- const issues = yield* getCurrentIssues(project.id)
207
+ const { issues } = yield* getCurrentIssues(project.id)
218
208
  const hasIncomplete = issues.some(
219
209
  (issue) => issue.state === "todo" && issue.blockedBy.length === 0,
220
210
  )
@@ -225,9 +215,8 @@ export const checkForWork = Effect.fnUntraced(function* (project: Project) {
225
215
 
226
216
  export const resetInProgress = Effect.gen(function* () {
227
217
  const source = yield* IssueSource
228
- const reactivity = yield* Reactivity.Reactivity
229
218
  const projectId = yield* CurrentProjectId
230
- const issues = yield* getCurrentIssues(projectId)
219
+ const { issues } = yield* getCurrentIssues(projectId)
231
220
  const inProgress = issues.filter(
232
221
  (issue): issue is PrdIssue & { id: string } =>
233
222
  issue.state === "in-progress" && issue.id !== null,
@@ -242,7 +231,7 @@ export const resetInProgress = Effect.gen(function* () {
242
231
  state: "todo",
243
232
  }),
244
233
  { concurrency: 5, discard: true },
245
- ).pipe(reactivity.withBatch)
234
+ )
246
235
  })
247
236
 
248
237
  export class NoMoreWork extends Schema.ErrorClass<NoMoreWork>(
@@ -1,15 +1,36 @@
1
- import { Effect, Option, Schema, ServiceMap } from "effect"
1
+ import {
2
+ Array,
3
+ Data,
4
+ Duration,
5
+ Effect,
6
+ Option,
7
+ Schema,
8
+ ScopedCache,
9
+ ServiceMap,
10
+ Stream,
11
+ SubscriptionRef,
12
+ pipe,
13
+ } from "effect"
2
14
  import type { PrdIssue } from "./domain/PrdIssue.ts"
3
- import { Reactivity } from "effect/unstable/reactivity"
4
15
  import type { ProjectId } from "./domain/Project.ts"
5
16
  import type { CurrentProjectId, Settings } from "./Settings.ts"
6
17
  import type { CliAgentPreset } from "./domain/CliAgentPreset.ts"
7
18
  import type { Environment } from "effect/unstable/cli/Prompt"
8
19
  import type { QuitError } from "effect/Terminal"
9
20
 
21
+ export type IssuesChange = Data.TaggedEnum<{
22
+ Internal: { issues: ReadonlyArray<PrdIssue> }
23
+ External: { issues: ReadonlyArray<PrdIssue> }
24
+ }>
25
+ export const IssuesChange = Data.taggedEnum<IssuesChange>()
26
+
10
27
  export class IssueSource extends ServiceMap.Service<
11
28
  IssueSource,
12
29
  {
30
+ readonly ref: (
31
+ projectId: ProjectId,
32
+ ) => Effect.Effect<SubscriptionRef.SubscriptionRef<IssuesChange>>
33
+
13
34
  readonly issues: (
14
35
  projectId: ProjectId,
15
36
  ) => Effect.Effect<ReadonlyArray<PrdIssue>, IssueSourceError>
@@ -71,31 +92,70 @@ export class IssueSource extends ServiceMap.Service<
71
92
  ) => Effect.Effect<void, IssueSourceError>
72
93
  }
73
94
  >()("lalph/IssueSource") {
74
- static make(impl: IssueSource["Service"]) {
95
+ static make(impl: Omit<IssueSource["Service"], "ref">) {
75
96
  return Effect.gen(function* () {
76
- const reactivity = yield* Reactivity.Reactivity
97
+ const refs = yield* ScopedCache.make({
98
+ lookup: Effect.fnUntraced(function* (projectId: ProjectId) {
99
+ const ref = yield* SubscriptionRef.make<IssuesChange>(
100
+ IssuesChange.Internal({
101
+ issues: yield* pipe(
102
+ impl.issues(projectId),
103
+ Effect.orElseSucceed(Array.empty),
104
+ ),
105
+ }),
106
+ )
107
+
108
+ yield* SubscriptionRef.changes(ref).pipe(
109
+ Stream.switchMap((_) =>
110
+ impl.issues(projectId).pipe(
111
+ Effect.tap((issues) =>
112
+ SubscriptionRef.set(ref, IssuesChange.External({ issues })),
113
+ ),
114
+ Effect.delay(Duration.seconds(30)),
115
+ Stream.fromEffectDrain,
116
+ ),
117
+ ),
118
+ Stream.runDrain,
119
+ Effect.forkScoped,
120
+ )
121
+
122
+ return ref
123
+ }),
124
+ capacity: Number.MAX_SAFE_INTEGER,
125
+ })
126
+
127
+ const update = Effect.fnUntraced(function* (
128
+ projectId: ProjectId,
129
+ issues: ReadonlyArray<PrdIssue>,
130
+ ) {
131
+ const ref = yield* ScopedCache.get(refs, projectId)
132
+ yield* SubscriptionRef.set(ref, IssuesChange.Internal({ issues }))
133
+ })
134
+
135
+ const updateIssues = (projectId: ProjectId) =>
136
+ pipe(
137
+ impl.issues(projectId),
138
+ Effect.tap((issues) => update(projectId, issues)),
139
+ )
140
+
77
141
  return IssueSource.of({
78
142
  ...impl,
143
+ ref: (projectId) => ScopedCache.get(refs, projectId),
144
+ issues: updateIssues,
79
145
  createIssue: (projectId, issue) =>
80
- reactivity.mutation(
81
- {
82
- issues: [projectId],
83
- },
146
+ pipe(
84
147
  impl.createIssue(projectId, issue),
148
+ Effect.tap(updateIssues(projectId)),
85
149
  ),
86
150
  updateIssue: (options) =>
87
- reactivity.mutation(
88
- {
89
- issues: [options.projectId],
90
- },
151
+ pipe(
91
152
  impl.updateIssue(options),
153
+ Effect.tap(updateIssues(options.projectId)),
92
154
  ),
93
155
  cancelIssue: (projectId, issueId) =>
94
- reactivity.mutation(
95
- {
96
- issues: [projectId],
97
- },
156
+ pipe(
98
157
  impl.cancelIssue(projectId, issueId),
158
+ Effect.tap(updateIssues(projectId)),
99
159
  ),
100
160
  })
101
161
  })
package/src/Prd.ts CHANGED
@@ -10,12 +10,12 @@ import {
10
10
  Semaphore,
11
11
  ServiceMap,
12
12
  Stream,
13
+ SubscriptionRef,
13
14
  } from "effect"
14
15
  import { Worktree } from "./Worktree.ts"
15
16
  import { PrdIssue } from "./domain/PrdIssue.ts"
16
17
  import { IssueSource, IssueSourceError } from "./IssueSource.ts"
17
- import { AtomRegistry, Reactivity } from "effect/unstable/reactivity"
18
- import { CurrentIssueSource, currentIssuesAtom } from "./CurrentIssueSource.ts"
18
+ import { CurrentIssueSource } from "./CurrentIssueSource.ts"
19
19
  import { CurrentProjectId, Settings } from "./Settings.ts"
20
20
 
21
21
  export class Prd extends ServiceMap.Service<
@@ -46,9 +46,7 @@ export class Prd extends ServiceMap.Service<
46
46
  const worktree = yield* Worktree
47
47
  const pathService = yield* Path.Path
48
48
  const fs = yield* FileSystem.FileSystem
49
- const reactivity = yield* Reactivity.Reactivity
50
49
  const source = yield* IssueSource
51
- const registry = yield* AtomRegistry.AtomRegistry
52
50
  const projectId = yield* CurrentProjectId
53
51
 
54
52
  let chosenIssueId: string | null = null
@@ -60,10 +58,9 @@ export class Prd extends ServiceMap.Service<
60
58
  const yaml = yield* fs.readFileString(prdFile)
61
59
  return PrdIssue.arrayFromYaml(yaml)
62
60
  })
63
- const getCurrentIssues = AtomRegistry.getResult(
64
- registry,
65
- currentIssuesAtom(projectId),
66
- { suspendOnWaiting: true },
61
+ const issuesRef = yield* source.ref(projectId)
62
+ const getCurrentIssues = SubscriptionRef.get(issuesRef).pipe(
63
+ Effect.map((i) => i.issues),
67
64
  )
68
65
 
69
66
  const syncSemaphore = Semaphore.makeUnsafe(1)
@@ -203,7 +200,6 @@ export class Prd extends ServiceMap.Service<
203
200
  { concurrency: "unbounded" },
204
201
  )
205
202
  }).pipe(
206
- reactivity.withBatch,
207
203
  Effect.uninterruptible,
208
204
  syncSemaphore.withPermit,
209
205
  Effect.withSpan("Prd.sync"),
@@ -242,10 +238,10 @@ export class Prd extends ServiceMap.Service<
242
238
  Effect.forkScoped,
243
239
  )
244
240
 
245
- yield* AtomRegistry.toStreamResult(
246
- registry,
247
- currentIssuesAtom(projectId),
248
- ).pipe(Stream.runForEach(updateSync), Effect.forkScoped)
241
+ yield* SubscriptionRef.changes(issuesRef).pipe(
242
+ Stream.runForEach((s) => updateSync(s.issues)),
243
+ Effect.forkScoped,
244
+ )
249
245
 
250
246
  const findById = Effect.fnUntraced(function* (issueId: string) {
251
247
  const current = yield* getCurrentIssues
@@ -277,22 +273,13 @@ export class Prd extends ServiceMap.Service<
277
273
  static layerNoWorktree = Layer.effect(this, this.make)
278
274
  static layer = this.layerNoWorktree.pipe(Layer.provideMerge(Worktree.layer))
279
275
  static layerProvided = this.layer.pipe(
280
- Layer.provide([
281
- AtomRegistry.layer,
282
- Reactivity.layer,
283
- CurrentIssueSource.layer,
284
- Settings.layer,
285
- ]),
276
+ Layer.provide([CurrentIssueSource.layer, Settings.layer]),
286
277
  )
287
278
  static layerLocal = this.layerNoWorktree.pipe(
288
279
  Layer.provideMerge(Worktree.layerLocal),
289
280
  )
290
281
  static layerLocalProvided = this.layerLocal.pipe(
291
- Layer.provide([
292
- AtomRegistry.layer,
293
- Reactivity.layer,
294
- CurrentIssueSource.layer,
295
- ]),
282
+ Layer.provide([CurrentIssueSource.layer]),
296
283
  )
297
284
  static layerNoop = Layer.succeed(this, {
298
285
  path: "",
package/src/TaskTools.ts CHANGED
@@ -1,13 +1,4 @@
1
- import {
2
- Deferred,
3
- Effect,
4
- MutableRef,
5
- Option,
6
- Random,
7
- Schema,
8
- ServiceMap,
9
- Struct,
10
- } from "effect"
1
+ import { Deferred, Effect, Random, Schema, ServiceMap, Struct } from "effect"
11
2
  import { Tool, Toolkit } from "effect/unstable/ai"
12
3
  import { PrdIssue } from "./domain/PrdIssue.ts"
13
4
  import { IssueSource } from "./IssueSource.ts"
@@ -24,17 +15,6 @@ export class ChosenTaskDeferred extends ServiceMap.Reference(
24
15
  },
25
16
  ) {}
26
17
 
27
- export class CurrentTaskRef extends ServiceMap.Service<
28
- CurrentTaskRef,
29
- MutableRef.MutableRef<PrdIssue>
30
- >()("lalph/TaskTools/CurrentTaskRef") {
31
- static update(f: (prev: PrdIssue) => PrdIssue) {
32
- return Effect.serviceOption(CurrentTaskRef).pipe(
33
- Effect.map(Option.map((ref) => MutableRef.updateAndGet(ref, f))),
34
- )
35
- }
36
- }
37
-
38
18
  const Task = Schema.Struct({
39
19
  id: Schema.String.annotate({
40
20
  documentation: "The unique identifier of the task.",
@@ -180,7 +160,6 @@ export const TaskToolsHandlers = TaskToolsWithChoose.toLayer(
180
160
  Effect.annotateLogs({ taskId: options.taskId }),
181
161
  )
182
162
  const projectId = yield* CurrentProjectId
183
- yield* CurrentTaskRef.update((prev) => prev.update(options))
184
163
  yield* source.updateIssue({
185
164
  projectId,
186
165
  issueId: options.taskId,
package/src/cli.ts CHANGED
@@ -12,7 +12,6 @@ import { commandSource } from "./commands/source.ts"
12
12
  import PackageJson from "../package.json" with { type: "json" }
13
13
  import { TracingLayer } from "./Tracing.ts"
14
14
  import { MinimumLogLevel } from "effect/References"
15
- import { atomRuntime, lalphMemoMap } from "./shared/runtime.ts"
16
15
  import { PlatformServices } from "./shared/platform.ts"
17
16
  import { commandProjects } from "./commands/projects.ts"
18
17
  import { commandSh } from "./commands/sh.ts"
@@ -32,14 +31,11 @@ commandRoot.pipe(
32
31
  Command.provide(TracingLayer),
33
32
  Command.provide(({ verbose }) => {
34
33
  if (!verbose) return Layer.empty
35
- const logLevel = Layer.succeed(MinimumLogLevel, "All")
36
- atomRuntime.addGlobalLayer(logLevel)
37
- return logLevel
34
+ return Layer.succeed(MinimumLogLevel, "All")
38
35
  }),
39
36
  Command.run({
40
37
  version: PackageJson.version,
41
38
  }),
42
39
  Effect.provide(PlatformServices),
43
- Effect.provideService(Layer.CurrentMemoMap, lalphMemoMap),
44
40
  NodeRuntime.runMain,
45
41
  )
@@ -9,16 +9,15 @@ import {
9
9
  FileSystem,
10
10
  Iterable,
11
11
  Layer,
12
- MutableRef,
13
12
  Option,
14
13
  Path,
15
14
  PlatformError,
16
15
  Result,
17
- Schedule,
18
16
  Schema,
19
17
  Scope,
20
18
  Semaphore,
21
19
  Stream,
20
+ SubscriptionRef,
22
21
  } from "effect"
23
22
  import { PromptGen } from "../PromptGen.ts"
24
23
  import { Prd } from "../Prd.ts"
@@ -28,7 +27,6 @@ import { IssueSource, IssueSourceError } from "../IssueSource.ts"
28
27
  import {
29
28
  checkForWork,
30
29
  CurrentIssueSource,
31
- currentIssuesAtom,
32
30
  resetInProgress,
33
31
  } from "../CurrentIssueSource.ts"
34
32
  import { GithubCli } from "../Github/Cli.ts"
@@ -60,7 +58,6 @@ import type { TimeoutError } from "effect/Cause"
60
58
  import type { ChildProcessSpawner } from "effect/unstable/process"
61
59
  import type { AiError } from "effect/unstable/ai/AiError"
62
60
  import type { PrdIssue } from "../domain/PrdIssue.ts"
63
- import { CurrentTaskRef } from "../TaskTools.ts"
64
61
  import type { OutputFormatter } from "clanka"
65
62
  import { ClankaMuxerLayer, SemanticSearchLayer } from "../Clanka.ts"
66
63
  import { agentResearcher } from "../Agents/researcher.ts"
@@ -250,14 +247,10 @@ const run = Effect.fnUntraced(
250
247
  gitFlow,
251
248
  })
252
249
 
253
- const issueRef = MutableRef.make(
254
- chosenTask.prd.update({
255
- state: "in-progress",
256
- }),
257
- )
250
+ const issueSemaphore = Semaphore.makeUnsafe(1)
258
251
  const steer = yield* taskUpdateSteer({
259
252
  issueId: taskId,
260
- current: issueRef,
253
+ semaphore: issueSemaphore,
261
254
  })
262
255
 
263
256
  const exitCode = yield* agentWorker({
@@ -268,11 +261,7 @@ const run = Effect.fnUntraced(
268
261
  research: researchResult,
269
262
  steer,
270
263
  currentTask: CurrentTask.task({ task: chosenTask.prd }),
271
- }).pipe(
272
- Effect.provideService(CurrentTaskRef, issueRef),
273
- catchStallInReview,
274
- Effect.withSpan("Main.agentWorker"),
275
- )
264
+ }).pipe(catchStallInReview, Effect.withSpan("Main.agentWorker"))
276
265
  yield* Effect.log(`Agent exited with code: ${exitCode}`)
277
266
 
278
267
  // 3. Review task
@@ -823,18 +812,18 @@ export const commandRoot = Command.make("lalph", {
823
812
  const watchTaskState = Effect.fnUntraced(function* (options: {
824
813
  readonly issueId: string
825
814
  }) {
826
- const registry = yield* AtomRegistry.AtomRegistry
827
815
  const projectId = yield* CurrentProjectId
816
+ const source = yield* IssueSource
817
+ const ref = yield* source.ref(projectId)
828
818
 
829
- return yield* AtomRegistry.toStreamResult(
830
- registry,
831
- currentIssuesAtom(projectId),
832
- ).pipe(
833
- Stream.retry(Schedule.forever),
834
- Stream.orDie,
835
- Stream.debounce(Duration.seconds(10)),
836
- Stream.runForEach((issues) => {
837
- const issue = issues.find((entry) => entry.id === options.issueId)
819
+ return yield* SubscriptionRef.changes(ref).pipe(
820
+ Stream.filterMap((issues) => {
821
+ if (issues._tag === "Internal") return Result.failVoid
822
+ return Result.succeed(
823
+ issues.issues.find((entry) => entry.id === options.issueId),
824
+ )
825
+ }),
826
+ Stream.runForEach((issue) => {
838
827
  if (issue?.state === "in-progress" || issue?.state === "in-review") {
839
828
  return Effect.void
840
829
  }
@@ -851,26 +840,29 @@ const watchTaskState = Effect.fnUntraced(function* (options: {
851
840
 
852
841
  const taskUpdateSteer = Effect.fnUntraced(function* (options: {
853
842
  readonly issueId: string
854
- readonly current: MutableRef.MutableRef<PrdIssue>
843
+ readonly semaphore: Semaphore.Semaphore
855
844
  }) {
856
- const registry = yield* AtomRegistry.AtomRegistry
857
845
  const projectId = yield* CurrentProjectId
846
+ const source = yield* IssueSource
847
+ const ref = yield* source.ref(projectId)
848
+ let current: PrdIssue | undefined = undefined
858
849
 
859
- return AtomRegistry.toStreamResult(
860
- registry,
861
- currentIssuesAtom(projectId),
862
- ).pipe(
863
- Stream.drop(1),
864
- Stream.retry(Schedule.forever),
865
- Stream.orDie,
866
- Stream.debounce(Duration.seconds(10)),
850
+ return SubscriptionRef.changes(ref).pipe(
867
851
  Stream.filterMap((issues) => {
868
- const issue = issues.find((entry) => entry.id === options.issueId)
852
+ const issue = issues.issues.find((entry) => entry.id === options.issueId)
869
853
  if (!issue) return Result.failVoid
870
- if (!issue.isChangedComparedTo(options.current.current)) {
854
+ if (!current) {
855
+ current = issue
856
+ return Result.failVoid
857
+ }
858
+ if (!issue.isChangedComparedTo(current)) {
859
+ return Result.failVoid
860
+ }
861
+ current = issue
862
+ console.log("issue change", issues._tag)
863
+ if (issues._tag === "Internal") {
871
864
  return Result.failVoid
872
865
  }
873
- MutableRef.set(options.current, issue)
874
866
  return Result.succeed(`The task has been updated by the user. Here is the latest information:
875
867
 
876
868
  # ${issue.title}
@@ -107,6 +107,7 @@ export class PrdIssue extends Schema.Class<PrdIssue>("PrdIssue")({
107
107
  }
108
108
 
109
109
  update(options: {
110
+ readonly id?: string | undefined
110
111
  readonly title?: string | undefined
111
112
  readonly description?: string | undefined
112
113
  readonly state?: PrdIssue["state"] | undefined
@@ -114,6 +115,7 @@ export class PrdIssue extends Schema.Class<PrdIssue>("PrdIssue")({
114
115
  }): PrdIssue {
115
116
  return new PrdIssue({
116
117
  ...this,
118
+ id: options.id ?? this.id,
117
119
  title: options.title ?? this.title,
118
120
  description: options.description ?? this.description,
119
121
  state: options.state ?? this.state,
@@ -1,9 +0,0 @@
1
- import { Layer } from "effect"
2
- import { Atom } from "effect/unstable/reactivity"
3
- import { TracingLayer } from "../Tracing.ts"
4
-
5
- export const lalphMemoMap = Layer.makeMemoMapUnsafe()
6
-
7
- export const atomRuntime = Atom.context({ memoMap: lalphMemoMap })
8
-
9
- atomRuntime.addGlobalLayer(TracingLayer)