ferix-code 0.0.2-beta.12 → 0.0.2-beta.14

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/index.js CHANGED
@@ -71,7 +71,7 @@ import { Command } from "commander";
71
71
  // package.json
72
72
  var package_default = {
73
73
  name: "ferix-code",
74
- version: "0.0.2-beta.12",
74
+ version: "0.0.2-beta.14",
75
75
  description: "Composable RALPH loops for AI coding agents - v2 with Effect",
76
76
  type: "module",
77
77
  bin: {
@@ -118,7 +118,7 @@ var package_default = {
118
118
 
119
119
  // src/program.ts
120
120
  init_esm_shims();
121
- import { Effect as Effect23, Stream as Stream10 } from "effect";
121
+ import { Effect as Effect24, Stream as Stream10 } from "effect";
122
122
 
123
123
  // src/consumers/index.ts
124
124
  init_esm_shims();
@@ -2770,6 +2770,7 @@ init_esm_shims();
2770
2770
  // src/domain/schemas/config.ts
2771
2771
  init_esm_shims();
2772
2772
  import { Schema as S } from "effect";
2773
+ var ProviderNameSchema = S.Literal("claude", "cursor", "opencode");
2773
2774
  var PhasePromptOverridesSchema = S.Struct({
2774
2775
  breakdown: S.optional(S.String),
2775
2776
  planning: S.optional(S.String),
@@ -2793,7 +2794,9 @@ var LoopConfigSchema = S.Struct({
2793
2794
  push: S.optional(S.Boolean),
2794
2795
  pr: S.optional(S.Boolean),
2795
2796
  verbose: S.optional(S.Boolean),
2796
- prompts: S.optional(PromptConfigSchema)
2797
+ prompts: S.optional(PromptConfigSchema),
2798
+ /** LLM provider to use. Defaults to "claude". */
2799
+ provider: S.optional(ProviderNameSchema)
2797
2800
  });
2798
2801
  var LoopSummarySchema = S.Struct({
2799
2802
  iterations: S.Number,
@@ -3665,10 +3668,9 @@ var MemoryGuardrails = {
3665
3668
  layer: layer2
3666
3669
  };
3667
3670
 
3668
- // src/layers/llm/claude-cli.ts
3671
+ // src/layers/llm/mock.ts
3669
3672
  init_esm_shims();
3670
- import { spawn } from "child_process";
3671
- import { Effect as Effect9, Layer as Layer5, Stream as Stream5 } from "effect";
3673
+ import { Effect as Effect8, Layer as Layer5, Schema as S14, Stream as Stream4 } from "effect";
3672
3674
 
3673
3675
  // src/services/llm.ts
3674
3676
  init_esm_shims();
@@ -3676,12 +3678,123 @@ import { Context as Context3 } from "effect";
3676
3678
  var LLM = class extends Context3.Tag("@ferix/LLM")() {
3677
3679
  };
3678
3680
 
3681
+ // src/layers/llm/mock.ts
3682
+ var MockLLMConfigSchema = S14.Struct({
3683
+ events: S14.Array(LLMEventSchema),
3684
+ delayMs: S14.optional(S14.Number)
3685
+ });
3686
+ function createMockLLM(config) {
3687
+ return {
3688
+ execute: (_prompt, _options) => {
3689
+ const baseStream = Stream4.fromIterable(config.events);
3690
+ if (config.delayMs !== void 0 && config.delayMs > 0) {
3691
+ const delay = config.delayMs;
3692
+ return baseStream.pipe(Stream4.tap(() => Effect8.sleep(delay)));
3693
+ }
3694
+ return baseStream;
3695
+ }
3696
+ };
3697
+ }
3698
+ var defaultMockEvents = [
3699
+ { _tag: "Text", text: "Processing task...\n" },
3700
+ { _tag: "ToolStart", tool: "Read" },
3701
+ { _tag: "ToolEnd", tool: "Read" },
3702
+ { _tag: "Text", text: "Task completed successfully.\n" },
3703
+ {
3704
+ _tag: "Done",
3705
+ output: "Processing task...\nTask completed successfully.\n"
3706
+ }
3707
+ ];
3708
+ var defaultMock = createMockLLM({ events: defaultMockEvents });
3709
+ var Live5 = Layer5.succeed(LLM, defaultMock);
3710
+ function layer3(config) {
3711
+ return Layer5.succeed(LLM, createMockLLM(config));
3712
+ }
3713
+ var Mock = {
3714
+ Live: Live5,
3715
+ layer: layer3,
3716
+ createMockLLM
3717
+ };
3718
+
3719
+ // src/layers/llm/providers/index.ts
3720
+ init_esm_shims();
3721
+ import { Effect as Effect11 } from "effect";
3722
+
3723
+ // src/layers/llm/types.ts
3724
+ init_esm_shims();
3725
+ var PROVIDER_CONFIGS = {
3726
+ claude: {
3727
+ name: "claude",
3728
+ cliCommand: "claude",
3729
+ args: [
3730
+ "--permission-mode",
3731
+ "acceptEdits",
3732
+ "--output-format",
3733
+ "stream-json",
3734
+ "--verbose",
3735
+ "--include-partial-messages"
3736
+ ],
3737
+ permissions: "acceptEdits",
3738
+ installUrl: "https://docs.anthropic.com/claude-code"
3739
+ },
3740
+ cursor: {
3741
+ name: "cursor",
3742
+ cliCommand: "cursor-agent",
3743
+ args: ["--print", "--force", "--output-format", "stream-json"],
3744
+ permissions: "acceptEdits",
3745
+ installUrl: "https://cursor.sh/agent"
3746
+ },
3747
+ opencode: {
3748
+ name: "opencode",
3749
+ cliCommand: "opencode",
3750
+ args: ["run", "--format", "json"],
3751
+ installUrl: "https://opencode.ai/docs/"
3752
+ }
3753
+ };
3754
+
3755
+ // src/layers/llm/providers/claude.ts
3756
+ init_esm_shims();
3757
+
3758
+ // src/layers/llm/provider-factory.ts
3759
+ init_esm_shims();
3760
+ import { spawn } from "child_process";
3761
+ import { Effect as Effect9, Layer as Layer6, Stream as Stream5 } from "effect";
3762
+ function createProvider(name, createStream, checkAvailable) {
3763
+ const config = PROVIDER_CONFIGS[name];
3764
+ return {
3765
+ name,
3766
+ execute: (prompt, options) => {
3767
+ return Stream5.unwrap(
3768
+ checkAvailable(name).pipe(
3769
+ Effect9.map(() => {
3770
+ const args = name === "opencode" ? [...config.args, prompt] : [...config.args, "-p", prompt];
3771
+ const child = spawn(config.cliCommand, args, {
3772
+ stdio: ["inherit", "pipe", "pipe"],
3773
+ cwd: options?.cwd,
3774
+ env: {
3775
+ ...process.env,
3776
+ FORCE_COLOR: "1",
3777
+ ...config.env
3778
+ }
3779
+ });
3780
+ return createStream(child);
3781
+ })
3782
+ )
3783
+ );
3784
+ }
3785
+ };
3786
+ }
3787
+ function createProviderLayer(provider) {
3788
+ return Layer6.succeed(LLM, provider);
3789
+ }
3790
+
3679
3791
  // src/layers/llm/stream.ts
3680
3792
  init_esm_shims();
3681
- import { createInterface } from "readline";
3682
- import { Effect as Effect8, Stream as Stream4 } from "effect";
3683
3793
 
3684
- // src/layers/llm/parsers.ts
3794
+ // src/layers/llm/providers/parsers/claude.ts
3795
+ init_esm_shims();
3796
+
3797
+ // src/layers/llm/providers/parsers/stream-json.ts
3685
3798
  init_esm_shims();
3686
3799
  function parseJsonLine(line) {
3687
3800
  if (!line.startsWith("{")) {
@@ -3760,7 +3873,10 @@ function unwrapStreamEvent(json) {
3760
3873
  return json;
3761
3874
  }
3762
3875
 
3763
- // src/layers/llm/stream.ts
3876
+ // src/layers/llm/stream-factory.ts
3877
+ init_esm_shims();
3878
+ import { createInterface } from "readline";
3879
+ import { Effect as Effect10, Stream as Stream6 } from "effect";
3764
3880
  function handleToolEvent(toolInfo, toolState, emit) {
3765
3881
  if (toolInfo.type === "start") {
3766
3882
  toolState.currentTool = toolInfo.name;
@@ -3783,21 +3899,8 @@ function handleToolEvent(toolInfo, toolState, emit) {
3783
3899
  toolState.inputChunks.length = 0;
3784
3900
  }
3785
3901
  }
3786
- function processJsonLine(json, outputChunks, toolState, emit) {
3787
- const event = unwrapStreamEvent(json);
3788
- const text = extractText(event);
3789
- if (text) {
3790
- outputChunks.push(text);
3791
- emit.single({ _tag: "Text", text });
3792
- return;
3793
- }
3794
- const toolInfo = extractToolInfo(event);
3795
- if (toolInfo) {
3796
- handleToolEvent(toolInfo, toolState, emit);
3797
- }
3798
- }
3799
- function createEventStream(child) {
3800
- return Stream4.async((emit) => {
3902
+ function createLLMEventStream(child, parser, providerName) {
3903
+ return Stream6.async((emit) => {
3801
3904
  const outputChunks = [];
3802
3905
  const toolState = { currentTool: "", inputChunks: [] };
3803
3906
  const stdout = child.stdout;
@@ -3805,16 +3908,16 @@ function createEventStream(child) {
3805
3908
  emit.fail(
3806
3909
  new LLMError({ message: "Failed to get stdout from child process" })
3807
3910
  );
3808
- return Effect8.void;
3911
+ return Effect10.void;
3809
3912
  }
3810
3913
  const rl = createInterface({
3811
3914
  input: stdout,
3812
3915
  crlfDelay: Number.POSITIVE_INFINITY
3813
3916
  });
3814
3917
  rl.on("line", (line) => {
3815
- const json = parseJsonLine(line);
3918
+ const json = parser.parseJsonLine(line);
3816
3919
  if (json) {
3817
- processJsonLine(json, outputChunks, toolState, emit);
3920
+ parser.processEvent(json, outputChunks, toolState, emit);
3818
3921
  }
3819
3922
  });
3820
3923
  child.stderr?.on("data", (data) => {
@@ -3827,7 +3930,7 @@ function createEventStream(child) {
3827
3930
  if (exitCode !== 0) {
3828
3931
  emit.fail(
3829
3932
  new LLMError({
3830
- message: `Claude CLI exited with code ${exitCode}`
3933
+ message: `${providerName} CLI exited with code ${exitCode}`
3831
3934
  })
3832
3935
  );
3833
3936
  } else {
@@ -3844,93 +3947,173 @@ function createEventStream(child) {
3844
3947
  })
3845
3948
  );
3846
3949
  });
3847
- return Effect8.sync(() => {
3950
+ return Effect10.sync(() => {
3848
3951
  child.kill("SIGTERM");
3849
3952
  });
3850
3953
  });
3851
3954
  }
3852
3955
 
3853
- // src/layers/llm/claude-cli.ts
3854
- var make3 = {
3855
- execute: (prompt, options) => {
3856
- return Stream5.unwrap(
3857
- Effect9.sync(() => {
3858
- const child = spawn(
3859
- "claude",
3860
- [
3861
- "--permission-mode",
3862
- "acceptEdits",
3863
- "--output-format",
3864
- "stream-json",
3865
- "--verbose",
3866
- "--include-partial-messages",
3867
- "-p",
3868
- prompt
3869
- ],
3870
- {
3871
- stdio: ["inherit", "pipe", "pipe"],
3872
- cwd: options?.cwd,
3873
- env: {
3874
- ...process.env,
3875
- FORCE_COLOR: "1"
3876
- }
3877
- }
3878
- );
3879
- return createEventStream(child);
3880
- })
3881
- );
3956
+ // src/layers/llm/stream.ts
3957
+ function processJsonLine(json, outputChunks, toolState, emit) {
3958
+ const event = unwrapStreamEvent(json);
3959
+ const text = extractText(event);
3960
+ if (text) {
3961
+ outputChunks.push(text);
3962
+ emit.single({ _tag: "Text", text });
3963
+ return;
3882
3964
  }
3965
+ const toolInfo = extractToolInfo(event);
3966
+ if (toolInfo) {
3967
+ handleToolEvent(toolInfo, toolState, emit);
3968
+ }
3969
+ }
3970
+ var streamJsonParser = {
3971
+ parseJsonLine,
3972
+ processEvent: processJsonLine
3883
3973
  };
3884
- var Live5 = Layer5.succeed(LLM, make3);
3974
+ function createEventStream(child, providerName = "LLM") {
3975
+ return createLLMEventStream(child, streamJsonParser, providerName);
3976
+ }
3977
+
3978
+ // src/layers/llm/providers/claude.ts
3979
+ var ClaudeProvider = createProvider(
3980
+ "claude",
3981
+ (child) => createEventStream(child, "Claude"),
3982
+ checkProviderAvailable
3983
+ );
3984
+ var Live6 = createProviderLayer(ClaudeProvider);
3885
3985
  var ClaudeCLI = {
3886
- Live: Live5
3986
+ Live: Live6,
3987
+ Provider: ClaudeProvider
3887
3988
  };
3888
3989
 
3889
- // src/layers/llm/mock.ts
3990
+ // src/layers/llm/providers/cursor.ts
3890
3991
  init_esm_shims();
3891
- import { Effect as Effect10, Layer as Layer6, Schema as S14, Stream as Stream6 } from "effect";
3892
- var MockLLMConfigSchema = S14.Struct({
3893
- events: S14.Array(LLMEventSchema),
3894
- delayMs: S14.optional(S14.Number)
3895
- });
3896
- function createMockLLM(config) {
3897
- return {
3898
- execute: (_prompt, _options) => {
3899
- const baseStream = Stream6.fromIterable(config.events);
3900
- if (config.delayMs !== void 0 && config.delayMs > 0) {
3901
- const delay = config.delayMs;
3902
- return baseStream.pipe(Stream6.tap(() => Effect10.sleep(delay)));
3903
- }
3904
- return baseStream;
3905
- }
3906
- };
3992
+ var CursorProvider = createProvider(
3993
+ "cursor",
3994
+ (child) => createEventStream(child, "Cursor"),
3995
+ checkProviderAvailable
3996
+ );
3997
+ var Live7 = createProviderLayer(CursorProvider);
3998
+ var CursorCLI = {
3999
+ Live: Live7,
4000
+ Provider: CursorProvider
4001
+ };
4002
+
4003
+ // src/layers/llm/providers/opencode.ts
4004
+ init_esm_shims();
4005
+
4006
+ // src/layers/llm/stream-opencode.ts
4007
+ init_esm_shims();
4008
+
4009
+ // src/layers/llm/providers/parsers/opencode.ts
4010
+ init_esm_shims();
4011
+ function parseJsonLine2(line) {
4012
+ if (!line.startsWith("{")) {
4013
+ return null;
4014
+ }
4015
+ try {
4016
+ return JSON.parse(line);
4017
+ } catch {
4018
+ return null;
4019
+ }
3907
4020
  }
3908
- var defaultMockEvents = [
3909
- { _tag: "Text", text: "Processing task...\n" },
3910
- { _tag: "ToolStart", tool: "Read" },
3911
- { _tag: "ToolEnd", tool: "Read" },
3912
- { _tag: "Text", text: "Task completed successfully.\n" },
3913
- {
3914
- _tag: "Done",
3915
- output: "Processing task...\nTask completed successfully.\n"
4021
+ function isTextContent2(json) {
4022
+ return typeof json === "object" && json !== null && "type" in json && json.type === "text" && "text" in json && typeof json.text === "string";
4023
+ }
4024
+ function isStepFinish(json) {
4025
+ return typeof json === "object" && json !== null && "type" in json && json.type === "step_finish";
4026
+ }
4027
+ function extractText2(json) {
4028
+ if (isTextContent2(json)) {
4029
+ return json.text;
3916
4030
  }
3917
- ];
3918
- var defaultMock = createMockLLM({ events: defaultMockEvents });
3919
- var Live6 = Layer6.succeed(LLM, defaultMock);
3920
- function layer3(config) {
3921
- return Layer6.succeed(LLM, createMockLLM(config));
4031
+ return null;
3922
4032
  }
3923
- var Mock = {
3924
- Live: Live6,
3925
- layer: layer3,
3926
- createMockLLM
4033
+
4034
+ // src/layers/llm/stream-opencode.ts
4035
+ function processOpenCodeEvent(json, outputChunks, _toolState, emit) {
4036
+ const text = extractText2(json);
4037
+ if (text) {
4038
+ outputChunks.push(text);
4039
+ emit.single({ _tag: "Text", text });
4040
+ return;
4041
+ }
4042
+ if (isStepFinish(json)) {
4043
+ return;
4044
+ }
4045
+ }
4046
+ var openCodeParser = {
4047
+ parseJsonLine: parseJsonLine2,
4048
+ processEvent: processOpenCodeEvent
4049
+ };
4050
+ function createOpenCodeEventStream(child, providerName = "OpenCode") {
4051
+ return createLLMEventStream(child, openCodeParser, providerName);
4052
+ }
4053
+
4054
+ // src/layers/llm/providers/opencode.ts
4055
+ var OpenCodeProvider = createProvider(
4056
+ "opencode",
4057
+ (child) => createOpenCodeEventStream(child, "OpenCode"),
4058
+ checkProviderAvailable
4059
+ );
4060
+ var Live8 = createProviderLayer(OpenCodeProvider);
4061
+ var OpenCodeCLI = {
4062
+ Live: Live8,
4063
+ Provider: OpenCodeProvider
3927
4064
  };
3928
4065
 
4066
+ // src/layers/llm/providers/index.ts
4067
+ var OpenCodeCLI2 = OpenCodeCLI;
4068
+ function isCommandAvailable(command) {
4069
+ return Effect11.tryPromise({
4070
+ try: async () => {
4071
+ const { execSync } = await import("child_process");
4072
+ try {
4073
+ execSync(`which ${command}`, { stdio: "ignore" });
4074
+ return true;
4075
+ } catch {
4076
+ return false;
4077
+ }
4078
+ },
4079
+ catch: () => false
4080
+ }).pipe(Effect11.orElseSucceed(() => false));
4081
+ }
4082
+ function checkProviderAvailable(name) {
4083
+ const config = PROVIDER_CONFIGS[name];
4084
+ return isCommandAvailable(config.cliCommand).pipe(
4085
+ Effect11.flatMap(
4086
+ (available) => available ? Effect11.void : Effect11.fail(
4087
+ new LLMError({
4088
+ message: `Provider "${name}" is not available. The CLI command "${config.cliCommand}" was not found.
4089
+
4090
+ To use this provider, install it first:
4091
+ ${config.installUrl}`
4092
+ })
4093
+ )
4094
+ )
4095
+ );
4096
+ }
4097
+ function createProviderLayer2(name) {
4098
+ switch (name) {
4099
+ case "claude":
4100
+ return ClaudeCLI.Live;
4101
+ case "cursor":
4102
+ return CursorCLI.Live;
4103
+ case "opencode":
4104
+ return OpenCodeCLI2.Live;
4105
+ default: {
4106
+ const _exhaustive = name;
4107
+ return _exhaustive;
4108
+ }
4109
+ }
4110
+ }
4111
+
3929
4112
  // src/layers/plan/file-system.ts
3930
4113
  init_esm_shims();
3931
4114
  import { access as access2, mkdir as mkdir3, readdir, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
3932
4115
  import { join as join3 } from "path";
3933
- import { Effect as Effect11, Layer as Layer7 } from "effect";
4116
+ import { Effect as Effect12, Layer as Layer7 } from "effect";
3934
4117
 
3935
4118
  // src/services/plan-store.ts
3936
4119
  init_esm_shims();
@@ -3941,14 +4124,14 @@ var PlanStore = class extends Context4.Tag("@ferix/PlanStore")() {
3941
4124
  // src/layers/plan/file-system.ts
3942
4125
  var PLANS_DIR2 = ".ferix/plans";
3943
4126
  function ensureDir2(dirPath) {
3944
- return Effect11.tryPromise({
4127
+ return Effect12.tryPromise({
3945
4128
  try: () => mkdir3(dirPath, { recursive: true }),
3946
4129
  catch: (error) => new PlanStoreError({
3947
4130
  message: `Failed to create directory: ${dirPath}`,
3948
4131
  operation: "create",
3949
4132
  cause: error
3950
4133
  })
3951
- }).pipe(Effect11.asVoid);
4134
+ }).pipe(Effect12.asVoid);
3952
4135
  }
3953
4136
  function getSessionDir2(sessionId) {
3954
4137
  return join3(process.cwd(), PLANS_DIR2, sessionId);
@@ -3963,8 +4146,8 @@ function serializePlan(plan) {
3963
4146
  return JSON.stringify(plan, null, 2);
3964
4147
  }
3965
4148
  function deserializePlan(json, planId) {
3966
- return Effect11.gen(function* () {
3967
- const parsed = yield* Effect11.try({
4149
+ return Effect12.gen(function* () {
4150
+ const parsed = yield* Effect12.try({
3968
4151
  try: () => JSON.parse(json),
3969
4152
  catch: (error) => new PlanStoreError({
3970
4153
  message: `Invalid JSON in plan file: ${String(error)}`,
@@ -3973,7 +4156,7 @@ function deserializePlan(json, planId) {
3973
4156
  })
3974
4157
  });
3975
4158
  const validated = yield* decodePlanData(parsed).pipe(
3976
- Effect11.mapError(
4159
+ Effect12.mapError(
3977
4160
  (error) => new PlanStoreError({
3978
4161
  message: `Plan validation failed: ${String(error)}`,
3979
4162
  operation: "load",
@@ -3987,11 +4170,11 @@ function deserializePlan(json, planId) {
3987
4170
  };
3988
4171
  });
3989
4172
  }
3990
- var make4 = {
3991
- create: (sessionId, plan) => Effect11.gen(function* () {
4173
+ var make3 = {
4174
+ create: (sessionId, plan) => Effect12.gen(function* () {
3992
4175
  const sessionDir = getSessionDir2(sessionId);
3993
4176
  yield* ensureDir2(sessionDir);
3994
- const existingPlans = yield* Effect11.tryPromise({
4177
+ const existingPlans = yield* Effect12.tryPromise({
3995
4178
  try: async () => {
3996
4179
  try {
3997
4180
  const files = await readdir(sessionDir);
@@ -4008,7 +4191,7 @@ var make4 = {
4008
4191
  const planId = generatePlanId(existingPlans + 1);
4009
4192
  const planPath = getPlanPath(sessionId, planId);
4010
4193
  const fullPlan = { ...plan, id: planId };
4011
- yield* Effect11.tryPromise({
4194
+ yield* Effect12.tryPromise({
4012
4195
  try: () => writeFile2(planPath, serializePlan(fullPlan), "utf-8"),
4013
4196
  catch: (error) => new PlanStoreError({
4014
4197
  message: `Failed to write plan file: ${planPath}`,
@@ -4018,10 +4201,10 @@ var make4 = {
4018
4201
  });
4019
4202
  return planId;
4020
4203
  }),
4021
- load: (planId, sessionId) => Effect11.gen(function* () {
4204
+ load: (planId, sessionId) => Effect12.gen(function* () {
4022
4205
  if (sessionId) {
4023
4206
  const planPath = getPlanPath(sessionId, planId);
4024
- const content = yield* Effect11.tryPromise({
4207
+ const content = yield* Effect12.tryPromise({
4025
4208
  try: () => readFile2(planPath, "utf-8"),
4026
4209
  catch: (error) => new PlanStoreError({
4027
4210
  message: `Failed to read plan file: ${planPath}`,
@@ -4031,7 +4214,7 @@ var make4 = {
4031
4214
  });
4032
4215
  return yield* deserializePlan(content, planId);
4033
4216
  }
4034
- const sessionDirs = yield* Effect11.tryPromise({
4217
+ const sessionDirs = yield* Effect12.tryPromise({
4035
4218
  try: async () => {
4036
4219
  const plansDir = join3(process.cwd(), PLANS_DIR2);
4037
4220
  const dirs = await readdir(plansDir);
@@ -4045,7 +4228,7 @@ var make4 = {
4045
4228
  });
4046
4229
  for (const sid of sessionDirs) {
4047
4230
  const planPath = getPlanPath(sid, planId);
4048
- const exists = yield* Effect11.tryPromise({
4231
+ const exists = yield* Effect12.tryPromise({
4049
4232
  try: async () => {
4050
4233
  await access2(planPath);
4051
4234
  return true;
@@ -4054,9 +4237,9 @@ var make4 = {
4054
4237
  message: "File not found",
4055
4238
  operation: "load"
4056
4239
  })
4057
- }).pipe(Effect11.orElseSucceed(() => false));
4240
+ }).pipe(Effect12.orElseSucceed(() => false));
4058
4241
  if (exists) {
4059
- const content = yield* Effect11.tryPromise({
4242
+ const content = yield* Effect12.tryPromise({
4060
4243
  try: () => readFile2(planPath, "utf-8"),
4061
4244
  catch: (error) => new PlanStoreError({
4062
4245
  message: `Failed to read plan file: ${planPath}`,
@@ -4067,16 +4250,16 @@ var make4 = {
4067
4250
  return yield* deserializePlan(content, planId);
4068
4251
  }
4069
4252
  }
4070
- return yield* Effect11.fail(
4253
+ return yield* Effect12.fail(
4071
4254
  new PlanStoreError({
4072
4255
  message: `Plan not found: ${planId}`,
4073
4256
  operation: "load"
4074
4257
  })
4075
4258
  );
4076
4259
  }),
4077
- update: (planId, plan) => Effect11.gen(function* () {
4260
+ update: (planId, plan) => Effect12.gen(function* () {
4078
4261
  const planPath = getPlanPath(plan.sessionId, planId);
4079
- yield* Effect11.tryPromise({
4262
+ yield* Effect12.tryPromise({
4080
4263
  try: () => writeFile2(planPath, serializePlan(plan), "utf-8"),
4081
4264
  catch: (error) => new PlanStoreError({
4082
4265
  message: `Failed to update plan file: ${planPath}`,
@@ -4085,9 +4268,9 @@ var make4 = {
4085
4268
  })
4086
4269
  });
4087
4270
  }),
4088
- list: (sessionId) => Effect11.gen(function* () {
4271
+ list: (sessionId) => Effect12.gen(function* () {
4089
4272
  const sessionDir = getSessionDir2(sessionId);
4090
- const files = yield* Effect11.tryPromise({
4273
+ const files = yield* Effect12.tryPromise({
4091
4274
  try: async () => {
4092
4275
  try {
4093
4276
  return await readdir(sessionDir);
@@ -4104,17 +4287,17 @@ var make4 = {
4104
4287
  return files.filter((f) => f.endsWith(".json")).map((f) => PlanId(f.replace(".json", "")));
4105
4288
  })
4106
4289
  };
4107
- var Live7 = Layer7.succeed(PlanStore, make4);
4290
+ var Live9 = Layer7.succeed(PlanStore, make3);
4108
4291
  var FileSystemPlan = {
4109
- Live: Live7
4292
+ Live: Live9
4110
4293
  };
4111
4294
 
4112
4295
  // src/layers/plan/memory.ts
4113
4296
  init_esm_shims();
4114
- import { Effect as Effect12, Layer as Layer8, Ref as Ref5 } from "effect";
4297
+ import { Effect as Effect13, Layer as Layer8, Ref as Ref5 } from "effect";
4115
4298
  function createMemoryPlanStore(stateRef) {
4116
4299
  return {
4117
- create: (sessionId, plan) => Effect12.gen(function* () {
4300
+ create: (sessionId, plan) => Effect13.gen(function* () {
4118
4301
  const state = yield* Ref5.get(stateRef);
4119
4302
  if (!state.has(sessionId)) {
4120
4303
  state.set(sessionId, /* @__PURE__ */ new Map());
@@ -4129,7 +4312,7 @@ function createMemoryPlanStore(stateRef) {
4129
4312
  yield* Ref5.set(stateRef, state);
4130
4313
  return planId;
4131
4314
  }),
4132
- load: (planId, sessionId) => Effect12.gen(function* () {
4315
+ load: (planId, sessionId) => Effect13.gen(function* () {
4133
4316
  const state = yield* Ref5.get(stateRef);
4134
4317
  if (sessionId) {
4135
4318
  const sessionPlans = state.get(sessionId);
@@ -4137,7 +4320,7 @@ function createMemoryPlanStore(stateRef) {
4137
4320
  if (plan) {
4138
4321
  return plan;
4139
4322
  }
4140
- return yield* Effect12.fail(
4323
+ return yield* Effect13.fail(
4141
4324
  new PlanStoreError({
4142
4325
  message: `Plan not found: ${planId}`,
4143
4326
  operation: "load"
@@ -4150,18 +4333,18 @@ function createMemoryPlanStore(stateRef) {
4150
4333
  return plan;
4151
4334
  }
4152
4335
  }
4153
- return yield* Effect12.fail(
4336
+ return yield* Effect13.fail(
4154
4337
  new PlanStoreError({
4155
4338
  message: `Plan not found: ${planId}`,
4156
4339
  operation: "load"
4157
4340
  })
4158
4341
  );
4159
4342
  }),
4160
- update: (planId, plan) => Effect12.gen(function* () {
4343
+ update: (planId, plan) => Effect13.gen(function* () {
4161
4344
  const state = yield* Ref5.get(stateRef);
4162
4345
  const sessionPlans = state.get(plan.sessionId);
4163
4346
  if (!sessionPlans) {
4164
- return yield* Effect12.fail(
4347
+ return yield* Effect13.fail(
4165
4348
  new PlanStoreError({
4166
4349
  message: `Session not found: ${plan.sessionId}`,
4167
4350
  operation: "update"
@@ -4171,7 +4354,7 @@ function createMemoryPlanStore(stateRef) {
4171
4354
  sessionPlans.set(planId, plan);
4172
4355
  yield* Ref5.set(stateRef, state);
4173
4356
  }),
4174
- list: (sessionId) => Effect12.gen(function* () {
4357
+ list: (sessionId) => Effect13.gen(function* () {
4175
4358
  const state = yield* Ref5.get(stateRef);
4176
4359
  const sessionPlans = state.get(sessionId);
4177
4360
  if (!sessionPlans) {
@@ -4184,15 +4367,15 @@ function createMemoryPlanStore(stateRef) {
4184
4367
  function layer4() {
4185
4368
  return Layer8.effect(
4186
4369
  PlanStore,
4187
- Effect12.gen(function* () {
4370
+ Effect13.gen(function* () {
4188
4371
  const stateRef = yield* Ref5.make(/* @__PURE__ */ new Map());
4189
4372
  return createMemoryPlanStore(stateRef);
4190
4373
  })
4191
4374
  );
4192
4375
  }
4193
- var Live8 = layer4();
4376
+ var Live10 = layer4();
4194
4377
  var MemoryPlan = {
4195
- Live: Live8,
4378
+ Live: Live10,
4196
4379
  layer: layer4
4197
4380
  };
4198
4381
 
@@ -4200,7 +4383,7 @@ var MemoryPlan = {
4200
4383
  init_esm_shims();
4201
4384
  import { mkdir as mkdir4, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
4202
4385
  import { join as join4 } from "path";
4203
- import { DateTime as DateTime3, Effect as Effect13, Layer as Layer9 } from "effect";
4386
+ import { DateTime as DateTime3, Effect as Effect14, Layer as Layer9 } from "effect";
4204
4387
 
4205
4388
  // src/services/progress-store.ts
4206
4389
  init_esm_shims();
@@ -4211,14 +4394,14 @@ var ProgressStore = class extends Context5.Tag("@ferix/ProgressStore")() {
4211
4394
  // src/layers/progress/file-system.ts
4212
4395
  var PLANS_DIR3 = ".ferix/plans";
4213
4396
  function ensureDir3(dirPath) {
4214
- return Effect13.tryPromise({
4397
+ return Effect14.tryPromise({
4215
4398
  try: () => mkdir4(dirPath, { recursive: true }),
4216
4399
  catch: (error) => new ProgressStoreError({
4217
4400
  message: `Failed to create directory: ${dirPath}`,
4218
4401
  operation: "append",
4219
4402
  cause: error
4220
4403
  })
4221
- }).pipe(Effect13.asVoid);
4404
+ }).pipe(Effect14.asVoid);
4222
4405
  }
4223
4406
  function getSessionDir3(sessionId) {
4224
4407
  return join4(process.cwd(), PLANS_DIR3, sessionId);
@@ -4230,8 +4413,8 @@ function serializeProgress(progress) {
4230
4413
  return JSON.stringify(progress, null, 2);
4231
4414
  }
4232
4415
  function deserializeProgress(json) {
4233
- return Effect13.gen(function* () {
4234
- const parsed = yield* Effect13.try({
4416
+ return Effect14.gen(function* () {
4417
+ const parsed = yield* Effect14.try({
4235
4418
  try: () => JSON.parse(json),
4236
4419
  catch: (error) => new ProgressStoreError({
4237
4420
  message: `Invalid JSON in progress file: ${String(error)}`,
@@ -4240,7 +4423,7 @@ function deserializeProgress(json) {
4240
4423
  })
4241
4424
  });
4242
4425
  const validated = yield* decodeProgressFile(parsed).pipe(
4243
- Effect13.mapError(
4426
+ Effect14.mapError(
4244
4427
  (error) => new ProgressStoreError({
4245
4428
  message: `Progress validation failed: ${String(error)}`,
4246
4429
  operation: "load",
@@ -4258,12 +4441,12 @@ function createEmptyProgress(sessionId, createdAt) {
4258
4441
  entries: []
4259
4442
  };
4260
4443
  }
4261
- var make5 = {
4262
- append: (sessionId, entry) => Effect13.gen(function* () {
4444
+ var make4 = {
4445
+ append: (sessionId, entry) => Effect14.gen(function* () {
4263
4446
  const sessionDir = getSessionDir3(sessionId);
4264
4447
  yield* ensureDir3(sessionDir);
4265
4448
  const progressPath = getProgressPath(sessionId);
4266
- const existing = yield* Effect13.tryPromise({
4449
+ const existing = yield* Effect14.tryPromise({
4267
4450
  try: async () => {
4268
4451
  try {
4269
4452
  const content = await readFile3(progressPath, "utf-8");
@@ -4281,7 +4464,7 @@ var make5 = {
4281
4464
  let progress;
4282
4465
  if (existing) {
4283
4466
  progress = yield* deserializeProgress(existing).pipe(
4284
- Effect13.mapError(
4467
+ Effect14.mapError(
4285
4468
  (err) => new ProgressStoreError({
4286
4469
  message: err.message,
4287
4470
  operation: "append",
@@ -4297,7 +4480,7 @@ var make5 = {
4297
4480
  ...progress,
4298
4481
  entries: [...progress.entries, entry]
4299
4482
  };
4300
- yield* Effect13.tryPromise({
4483
+ yield* Effect14.tryPromise({
4301
4484
  try: () => writeFile3(progressPath, serializeProgress(updatedProgress), "utf-8"),
4302
4485
  catch: (error) => new ProgressStoreError({
4303
4486
  message: `Failed to write progress file: ${progressPath}`,
@@ -4306,9 +4489,9 @@ var make5 = {
4306
4489
  })
4307
4490
  });
4308
4491
  }),
4309
- load: (sessionId) => Effect13.gen(function* () {
4492
+ load: (sessionId) => Effect14.gen(function* () {
4310
4493
  const progressPath = getProgressPath(sessionId);
4311
- const content = yield* Effect13.tryPromise({
4494
+ const content = yield* Effect14.tryPromise({
4312
4495
  try: async () => {
4313
4496
  try {
4314
4497
  return await readFile3(progressPath, "utf-8");
@@ -4328,23 +4511,23 @@ var make5 = {
4328
4511
  }
4329
4512
  return yield* deserializeProgress(content);
4330
4513
  }),
4331
- getRecent: (sessionId, count) => Effect13.gen(function* () {
4332
- const progress = yield* make5.load(sessionId);
4514
+ getRecent: (sessionId, count) => Effect14.gen(function* () {
4515
+ const progress = yield* make4.load(sessionId);
4333
4516
  const entries = progress.entries;
4334
4517
  return entries.slice(-count);
4335
4518
  })
4336
4519
  };
4337
- var Live9 = Layer9.succeed(ProgressStore, make5);
4520
+ var Live11 = Layer9.succeed(ProgressStore, make4);
4338
4521
  var FileSystemProgress = {
4339
- Live: Live9
4522
+ Live: Live11
4340
4523
  };
4341
4524
 
4342
4525
  // src/layers/progress/memory.ts
4343
4526
  init_esm_shims();
4344
- import { DateTime as DateTime4, Effect as Effect14, Layer as Layer10, Ref as Ref6 } from "effect";
4527
+ import { DateTime as DateTime4, Effect as Effect15, Layer as Layer10, Ref as Ref6 } from "effect";
4345
4528
  function createMemoryProgressStore(stateRef) {
4346
4529
  return {
4347
- append: (sessionId, entry) => Effect14.gen(function* () {
4530
+ append: (sessionId, entry) => Effect15.gen(function* () {
4348
4531
  const state = yield* Ref6.get(stateRef);
4349
4532
  let progress = state.get(sessionId);
4350
4533
  if (!progress) {
@@ -4362,7 +4545,7 @@ function createMemoryProgressStore(stateRef) {
4362
4545
  state.set(sessionId, updatedProgress);
4363
4546
  yield* Ref6.set(stateRef, state);
4364
4547
  }),
4365
- load: (sessionId) => Effect14.gen(function* () {
4548
+ load: (sessionId) => Effect15.gen(function* () {
4366
4549
  const state = yield* Ref6.get(stateRef);
4367
4550
  const progress = state.get(sessionId);
4368
4551
  if (!progress) {
@@ -4375,7 +4558,7 @@ function createMemoryProgressStore(stateRef) {
4375
4558
  }
4376
4559
  return progress;
4377
4560
  }),
4378
- getRecent: (sessionId, count) => Effect14.gen(function* () {
4561
+ getRecent: (sessionId, count) => Effect15.gen(function* () {
4379
4562
  const state = yield* Ref6.get(stateRef);
4380
4563
  const progress = state.get(sessionId);
4381
4564
  if (!progress) {
@@ -4388,15 +4571,15 @@ function createMemoryProgressStore(stateRef) {
4388
4571
  function layer5() {
4389
4572
  return Layer10.effect(
4390
4573
  ProgressStore,
4391
- Effect14.gen(function* () {
4574
+ Effect15.gen(function* () {
4392
4575
  const stateRef = yield* Ref6.make(/* @__PURE__ */ new Map());
4393
4576
  return createMemoryProgressStore(stateRef);
4394
4577
  })
4395
4578
  );
4396
4579
  }
4397
- var Live10 = layer5();
4580
+ var Live12 = layer5();
4398
4581
  var MemoryProgress = {
4399
- Live: Live10,
4582
+ Live: Live12,
4400
4583
  layer: layer5
4401
4584
  };
4402
4585
 
@@ -4404,7 +4587,7 @@ var MemoryProgress = {
4404
4587
  init_esm_shims();
4405
4588
  import { mkdir as mkdir5, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
4406
4589
  import { join as join5 } from "path";
4407
- import { DateTime as DateTime5, Effect as Effect15, Layer as Layer11 } from "effect";
4590
+ import { DateTime as DateTime5, Effect as Effect16, Layer as Layer11 } from "effect";
4408
4591
  import { humanId } from "human-id";
4409
4592
 
4410
4593
  // src/services/session-store.ts
@@ -4420,14 +4603,14 @@ function generateSessionId(timestampMs) {
4420
4603
  return `${id}-${timestampMs}`;
4421
4604
  }
4422
4605
  function ensureDir4(dirPath) {
4423
- return Effect15.tryPromise({
4606
+ return Effect16.tryPromise({
4424
4607
  try: () => mkdir5(dirPath, { recursive: true }),
4425
4608
  catch: (error) => new SessionStoreError({
4426
4609
  message: `Failed to create directory: ${dirPath}`,
4427
4610
  operation: "create",
4428
4611
  cause: error
4429
4612
  })
4430
- }).pipe(Effect15.asVoid);
4613
+ }).pipe(Effect16.asVoid);
4431
4614
  }
4432
4615
  function getSessionPath(sessionId) {
4433
4616
  return join5(process.cwd(), SESSIONS_DIR, `${sessionId}.json`);
@@ -4436,8 +4619,8 @@ function serializeSession(session) {
4436
4619
  return JSON.stringify(session, null, 2);
4437
4620
  }
4438
4621
  function deserializeSession(json) {
4439
- return Effect15.gen(function* () {
4440
- const parsed = yield* Effect15.try({
4622
+ return Effect16.gen(function* () {
4623
+ const parsed = yield* Effect16.try({
4441
4624
  try: () => JSON.parse(json),
4442
4625
  catch: (error) => new SessionStoreError({
4443
4626
  message: `Invalid JSON in session file: ${String(error)}`,
@@ -4446,7 +4629,7 @@ function deserializeSession(json) {
4446
4629
  })
4447
4630
  });
4448
4631
  const validated = yield* decodeSession(parsed).pipe(
4449
- Effect15.mapError(
4632
+ Effect16.mapError(
4450
4633
  (error) => new SessionStoreError({
4451
4634
  message: `Session validation failed: ${String(error)}`,
4452
4635
  operation: "get",
@@ -4457,8 +4640,8 @@ function deserializeSession(json) {
4457
4640
  return validated;
4458
4641
  });
4459
4642
  }
4460
- var make6 = {
4461
- create: (originalTask) => Effect15.gen(function* () {
4643
+ var make5 = {
4644
+ create: (originalTask) => Effect16.gen(function* () {
4462
4645
  const sessionsDir = join5(process.cwd(), SESSIONS_DIR);
4463
4646
  yield* ensureDir4(sessionsDir);
4464
4647
  const now = yield* DateTime5.now;
@@ -4472,7 +4655,7 @@ var make6 = {
4472
4655
  completedTasks: []
4473
4656
  };
4474
4657
  const sessionPath = getSessionPath(sessionId);
4475
- yield* Effect15.tryPromise({
4658
+ yield* Effect16.tryPromise({
4476
4659
  try: () => writeFile4(sessionPath, serializeSession(session), "utf-8"),
4477
4660
  catch: (error) => new SessionStoreError({
4478
4661
  message: `Failed to write session file: ${sessionPath}`,
@@ -4482,9 +4665,9 @@ var make6 = {
4482
4665
  });
4483
4666
  return session;
4484
4667
  }),
4485
- get: (sessionId) => Effect15.gen(function* () {
4668
+ get: (sessionId) => Effect16.gen(function* () {
4486
4669
  const sessionPath = getSessionPath(sessionId);
4487
- const content = yield* Effect15.tryPromise({
4670
+ const content = yield* Effect16.tryPromise({
4488
4671
  try: () => readFile4(sessionPath, "utf-8"),
4489
4672
  catch: (error) => new SessionStoreError({
4490
4673
  message: `Failed to read session file: ${sessionPath}`,
@@ -4494,9 +4677,9 @@ var make6 = {
4494
4677
  });
4495
4678
  return yield* deserializeSession(content);
4496
4679
  }),
4497
- update: (sessionId, session) => Effect15.gen(function* () {
4680
+ update: (sessionId, session) => Effect16.gen(function* () {
4498
4681
  const sessionPath = getSessionPath(sessionId);
4499
- yield* Effect15.tryPromise({
4682
+ yield* Effect16.tryPromise({
4500
4683
  try: () => writeFile4(sessionPath, serializeSession(session), "utf-8"),
4501
4684
  catch: (error) => new SessionStoreError({
4502
4685
  message: `Failed to update session file: ${sessionPath}`,
@@ -4506,17 +4689,17 @@ var make6 = {
4506
4689
  });
4507
4690
  })
4508
4691
  };
4509
- var Live11 = Layer11.succeed(SessionStore, make6);
4692
+ var Live13 = Layer11.succeed(SessionStore, make5);
4510
4693
  var FileSystemSession = {
4511
- Live: Live11
4694
+ Live: Live13
4512
4695
  };
4513
4696
 
4514
4697
  // src/layers/session/memory.ts
4515
4698
  init_esm_shims();
4516
- import { DateTime as DateTime6, Effect as Effect16, Layer as Layer12, Ref as Ref7 } from "effect";
4699
+ import { DateTime as DateTime6, Effect as Effect17, Layer as Layer12, Ref as Ref7 } from "effect";
4517
4700
  function createMemorySessionStore(stateRef, counterRef) {
4518
4701
  return {
4519
- create: (originalTask) => Effect16.gen(function* () {
4702
+ create: (originalTask) => Effect17.gen(function* () {
4520
4703
  const state = yield* Ref7.get(stateRef);
4521
4704
  const counter = yield* Ref7.updateAndGet(counterRef, (n) => n + 1);
4522
4705
  const sessionId = `test-session-${counter}`;
@@ -4532,11 +4715,11 @@ function createMemorySessionStore(stateRef, counterRef) {
4532
4715
  yield* Ref7.set(stateRef, state);
4533
4716
  return session;
4534
4717
  }),
4535
- get: (sessionId) => Effect16.gen(function* () {
4718
+ get: (sessionId) => Effect17.gen(function* () {
4536
4719
  const state = yield* Ref7.get(stateRef);
4537
4720
  const session = state.get(sessionId);
4538
4721
  if (!session) {
4539
- return yield* Effect16.fail(
4722
+ return yield* Effect17.fail(
4540
4723
  new SessionStoreError({
4541
4724
  message: `Session not found: ${sessionId}`,
4542
4725
  operation: "get"
@@ -4545,10 +4728,10 @@ function createMemorySessionStore(stateRef, counterRef) {
4545
4728
  }
4546
4729
  return session;
4547
4730
  }),
4548
- update: (sessionId, session) => Effect16.gen(function* () {
4731
+ update: (sessionId, session) => Effect17.gen(function* () {
4549
4732
  const state = yield* Ref7.get(stateRef);
4550
4733
  if (!state.has(sessionId)) {
4551
- return yield* Effect16.fail(
4734
+ return yield* Effect17.fail(
4552
4735
  new SessionStoreError({
4553
4736
  message: `Session not found: ${sessionId}`,
4554
4737
  operation: "update"
@@ -4563,22 +4746,22 @@ function createMemorySessionStore(stateRef, counterRef) {
4563
4746
  function layer6() {
4564
4747
  return Layer12.effect(
4565
4748
  SessionStore,
4566
- Effect16.gen(function* () {
4749
+ Effect17.gen(function* () {
4567
4750
  const stateRef = yield* Ref7.make(/* @__PURE__ */ new Map());
4568
4751
  const counterRef = yield* Ref7.make(0);
4569
4752
  return createMemorySessionStore(stateRef, counterRef);
4570
4753
  })
4571
4754
  );
4572
4755
  }
4573
- var Live12 = layer6();
4756
+ var Live14 = layer6();
4574
4757
  var MemorySession = {
4575
- Live: Live12,
4758
+ Live: Live14,
4576
4759
  layer: layer6
4577
4760
  };
4578
4761
 
4579
4762
  // src/layers/signal/ferix-parser.ts
4580
4763
  init_esm_shims();
4581
- import { Effect as Effect17, Layer as Layer13, Ref as Ref8 } from "effect";
4764
+ import { Effect as Effect18, Layer as Layer13, Ref as Ref8 } from "effect";
4582
4765
 
4583
4766
  // src/services/signal-parser.ts
4584
4767
  init_esm_shims();
@@ -5088,10 +5271,10 @@ signalSpecRegistry.register(tasksDefinedSpec);
5088
5271
  // src/layers/signal/ferix-parser.ts
5089
5272
  var MAX_BUFFER_SIZE = 1024 * 1024;
5090
5273
  function createAccumulatorImpl() {
5091
- return Effect17.gen(function* () {
5274
+ return Effect18.gen(function* () {
5092
5275
  const chunksRef = yield* Ref8.make([]);
5093
5276
  const emittedRef = yield* Ref8.make(/* @__PURE__ */ new Set());
5094
- const feed = (text) => Effect17.gen(function* () {
5277
+ const feed = (text) => Effect18.gen(function* () {
5095
5278
  const chunks = yield* Ref8.get(chunksRef);
5096
5279
  chunks.push(text);
5097
5280
  const buffer = chunks.join("");
@@ -5119,7 +5302,7 @@ function createAccumulatorImpl() {
5119
5302
  yield* Ref8.set(emittedRef, emitted);
5120
5303
  return newSignals;
5121
5304
  });
5122
- const flush = () => Effect17.gen(function* () {
5305
+ const flush = () => Effect18.gen(function* () {
5123
5306
  const chunks = yield* Ref8.get(chunksRef);
5124
5307
  const buffer = chunks.join("");
5125
5308
  yield* Ref8.set(chunksRef, []);
@@ -5134,13 +5317,13 @@ function createAccumulatorImpl() {
5134
5317
  return { feed, flush };
5135
5318
  });
5136
5319
  }
5137
- var make7 = {
5138
- parse: (text) => Effect17.succeed(signalSpecRegistry.parseAll(text)),
5320
+ var make6 = {
5321
+ parse: (text) => Effect18.succeed(signalSpecRegistry.parseAll(text)),
5139
5322
  createAccumulator: createAccumulatorImpl
5140
5323
  };
5141
- var Live13 = Layer13.succeed(SignalParser, make7);
5324
+ var Live15 = Layer13.succeed(SignalParser, make6);
5142
5325
  var FerixParser = {
5143
- Live: Live13
5326
+ Live: Live15
5144
5327
  };
5145
5328
 
5146
5329
  // src/layers/index.ts
@@ -5153,6 +5336,18 @@ var ProductionLayers = Layer14.mergeAll(
5153
5336
  FileSystemGuardrails.Live,
5154
5337
  FileSystemGit.Live
5155
5338
  );
5339
+ function createProductionLayers(provider = "claude") {
5340
+ const llmLayer = createProviderLayer2(provider);
5341
+ return Layer14.mergeAll(
5342
+ llmLayer,
5343
+ FerixParser.Live,
5344
+ FileSystemPlan.Live,
5345
+ FileSystemSession.Live,
5346
+ FileSystemProgress.Live,
5347
+ FileSystemGuardrails.Live,
5348
+ FileSystemGit.Live
5349
+ );
5350
+ }
5156
5351
  var TestLayers = Layer14.mergeAll(
5157
5352
  Mock.Live,
5158
5353
  FerixParser.Live,
@@ -5179,27 +5374,27 @@ init_esm_shims();
5179
5374
 
5180
5375
  // src/orchestrator/loop.ts
5181
5376
  init_esm_shims();
5182
- import { DateTime as DateTime10, Effect as Effect22, Option, pipe as pipe3, Ref as Ref12, Stream as Stream9 } from "effect";
5377
+ import { DateTime as DateTime10, Effect as Effect23, Option, pipe as pipe3, Ref as Ref12, Stream as Stream9 } from "effect";
5183
5378
 
5184
5379
  // src/orchestrator/discovery.ts
5185
5380
  init_esm_shims();
5186
- import { DateTime as DateTime8, Effect as Effect20, pipe, Ref as Ref10, Stream as Stream7 } from "effect";
5381
+ import { DateTime as DateTime8, Effect as Effect21, pipe, Ref as Ref10, Stream as Stream7 } from "effect";
5187
5382
 
5188
5383
  // src/layers/plan/task-generation.ts
5189
5384
  init_esm_shims();
5190
5385
  import { mkdir as mkdir6, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
5191
5386
  import { join as join6 } from "path";
5192
- import { Effect as Effect18 } from "effect";
5387
+ import { Effect as Effect19 } from "effect";
5193
5388
  var PLANS_DIR4 = ".ferix/plans";
5194
5389
  function ensureDir5(dirPath) {
5195
- return Effect18.tryPromise({
5390
+ return Effect19.tryPromise({
5196
5391
  try: () => mkdir6(dirPath, { recursive: true }),
5197
5392
  catch: (error) => new PlanStoreError({
5198
5393
  message: `Failed to create directory: ${dirPath}`,
5199
5394
  operation: "create",
5200
5395
  cause: error
5201
5396
  })
5202
- }).pipe(Effect18.asVoid);
5397
+ }).pipe(Effect19.asVoid);
5203
5398
  }
5204
5399
  function getSessionDir4(sessionId) {
5205
5400
  return join6(process.cwd(), PLANS_DIR4, sessionId);
@@ -5208,12 +5403,12 @@ function getTasksMdPath(sessionId) {
5208
5403
  return join6(getSessionDir4(sessionId), "tasks.md");
5209
5404
  }
5210
5405
  function writeTasksMd(sessionId, tasks) {
5211
- return Effect18.gen(function* () {
5406
+ return Effect19.gen(function* () {
5212
5407
  const sessionDir = getSessionDir4(sessionId);
5213
5408
  yield* ensureDir5(sessionDir);
5214
5409
  const tasksMdPath = getTasksMdPath(sessionId);
5215
5410
  const content = formatTasksMd(tasks);
5216
- yield* Effect18.tryPromise({
5411
+ yield* Effect19.tryPromise({
5217
5412
  try: () => writeFile5(tasksMdPath, content, "utf-8"),
5218
5413
  catch: (error) => new PlanStoreError({
5219
5414
  message: `Failed to write tasks.md: ${tasksMdPath}`,
@@ -5395,7 +5590,7 @@ function mapSignalToDomain(signal, context) {
5395
5590
 
5396
5591
  // src/orchestrator/plan-updates.ts
5397
5592
  init_esm_shims();
5398
- import { DateTime as DateTime7, Effect as Effect19, Ref as Ref9 } from "effect";
5593
+ import { DateTime as DateTime7, Effect as Effect20, Ref as Ref9 } from "effect";
5399
5594
 
5400
5595
  // src/orchestrator/plan-updates/index.ts
5401
5596
  init_esm_shims();
@@ -5700,9 +5895,9 @@ function persistPlanUpdate(planStore, plan, operation) {
5700
5895
  tasks: plan.tasks
5701
5896
  }) : planStore.update(plan.id, plan);
5702
5897
  return storeOp.pipe(
5703
- Effect19.map(() => null),
5704
- Effect19.catchAll(
5705
- (error) => Effect19.succeed({
5898
+ Effect20.map(() => null),
5899
+ Effect20.catchAll(
5900
+ (error) => Effect20.succeed({
5706
5901
  _tag: "PlanUpdateFailed",
5707
5902
  operation,
5708
5903
  error: error.message,
@@ -5712,7 +5907,7 @@ function persistPlanUpdate(planStore, plan, operation) {
5712
5907
  );
5713
5908
  }
5714
5909
  function updatePlanFromSignal(currentPlanRef, persistenceStateRef, signal, sessionId, originalTask) {
5715
- return Effect19.gen(function* () {
5910
+ return Effect20.gen(function* () {
5716
5911
  const currentPlan = yield* Ref9.get(currentPlanRef);
5717
5912
  const now = yield* DateTime7.now;
5718
5913
  const timestamp = DateTime7.formatIso(now);
@@ -5734,7 +5929,7 @@ function updatePlanFromSignal(currentPlanRef, persistenceStateRef, signal, sessi
5734
5929
  });
5735
5930
  }
5736
5931
  function flushPlanPersistence(planStore, currentPlanRef, persistenceStateRef) {
5737
- return Effect19.gen(function* () {
5932
+ return Effect20.gen(function* () {
5738
5933
  const state = yield* Ref9.get(persistenceStateRef);
5739
5934
  if (!(state.dirty && state.pendingOperation)) {
5740
5935
  return [];
@@ -6008,12 +6203,12 @@ Begin.`);
6008
6203
 
6009
6204
  // src/orchestrator/discovery.ts
6010
6205
  function processTextSignals(signalParser, text, context) {
6011
- return Effect20.gen(function* () {
6206
+ return Effect21.gen(function* () {
6012
6207
  const events = [];
6013
6208
  const parsedSignals = [];
6014
6209
  const signals = yield* signalParser.parse(text).pipe(
6015
- Effect20.tapError(
6016
- (error) => Effect20.logDebug(
6210
+ Effect21.tapError(
6211
+ (error) => Effect21.logDebug(
6017
6212
  "Signal parsing failed, continuing with empty signals",
6018
6213
  {
6019
6214
  error: String(error),
@@ -6021,7 +6216,7 @@ function processTextSignals(signalParser, text, context) {
6021
6216
  }
6022
6217
  )
6023
6218
  ),
6024
- Effect20.orElseSucceed(() => [])
6219
+ Effect21.orElseSucceed(() => [])
6025
6220
  );
6026
6221
  for (const signal of signals) {
6027
6222
  events.push(mapSignalToDomain(signal, context));
@@ -6031,7 +6226,7 @@ function processTextSignals(signalParser, text, context) {
6031
6226
  });
6032
6227
  }
6033
6228
  function processLLMEvent(signalParser, llmEvent, context) {
6034
- return Effect20.gen(function* () {
6229
+ return Effect21.gen(function* () {
6035
6230
  const domainEvent = mapLLMEventToDomain(llmEvent, context);
6036
6231
  const events = [domainEvent];
6037
6232
  const allSignals = [];
@@ -6076,7 +6271,7 @@ function planTasksToGeneratedTasks(plan) {
6076
6271
  }
6077
6272
  function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, config, sessionId, worktreePath) {
6078
6273
  return Stream7.unwrap(
6079
- Effect20.gen(function* () {
6274
+ Effect21.gen(function* () {
6080
6275
  const startTimeUtc = yield* DateTime8.now;
6081
6276
  const startTime = DateTime8.toEpochMillis(startTimeUtc);
6082
6277
  const persistenceStateRef = yield* Ref10.make({
@@ -6103,7 +6298,7 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6103
6298
  ),
6104
6299
  Stream7.flatMap(
6105
6300
  (llmEvent) => Stream7.unwrap(
6106
- Effect20.gen(function* () {
6301
+ Effect21.gen(function* () {
6107
6302
  const now = yield* DateTime8.now;
6108
6303
  const context = {
6109
6304
  timestamp: DateTime8.toEpochMillis(now)
@@ -6140,7 +6335,7 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6140
6335
  )
6141
6336
  );
6142
6337
  const completionStream = Stream7.fromEffect(
6143
- Effect20.gen(function* () {
6338
+ Effect21.gen(function* () {
6144
6339
  const persistEvents = yield* flushPlanPersistence(
6145
6340
  planStore,
6146
6341
  currentPlanRef,
@@ -6151,12 +6346,12 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6151
6346
  if (plan && plan.tasks.length > 0) {
6152
6347
  const generatedTasks = planTasksToGeneratedTasks(plan);
6153
6348
  yield* writeTasksMd(sessionId, generatedTasks).pipe(
6154
- Effect20.tapError(
6155
- (error) => Effect20.logDebug("Failed to write tasks.md, continuing", {
6349
+ Effect21.tapError(
6350
+ (error) => Effect21.logDebug("Failed to write tasks.md, continuing", {
6156
6351
  error: String(error)
6157
6352
  })
6158
6353
  ),
6159
- Effect20.orElseSucceed(() => void 0)
6354
+ Effect21.orElseSucceed(() => void 0)
6160
6355
  );
6161
6356
  }
6162
6357
  const endTimeUtc = yield* DateTime8.now;
@@ -6181,15 +6376,15 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6181
6376
 
6182
6377
  // src/orchestrator/iteration.ts
6183
6378
  init_esm_shims();
6184
- import { DateTime as DateTime9, Effect as Effect21, pipe as pipe2, Ref as Ref11, Stream as Stream8 } from "effect";
6379
+ import { DateTime as DateTime9, Effect as Effect22, pipe as pipe2, Ref as Ref11, Stream as Stream8 } from "effect";
6185
6380
  function processTextSignals2(signalParser, text, context) {
6186
- return Effect21.gen(function* () {
6381
+ return Effect22.gen(function* () {
6187
6382
  const events = [];
6188
6383
  let completed = false;
6189
6384
  const parsedSignals = [];
6190
6385
  const signals = yield* signalParser.parse(text).pipe(
6191
- Effect21.tapError(
6192
- (error) => Effect21.logDebug(
6386
+ Effect22.tapError(
6387
+ (error) => Effect22.logDebug(
6193
6388
  "Signal parsing failed, continuing with empty signals",
6194
6389
  {
6195
6390
  error: String(error),
@@ -6197,7 +6392,7 @@ function processTextSignals2(signalParser, text, context) {
6197
6392
  }
6198
6393
  )
6199
6394
  ),
6200
- Effect21.orElseSucceed(() => [])
6395
+ Effect22.orElseSucceed(() => [])
6201
6396
  );
6202
6397
  for (const signal of signals) {
6203
6398
  events.push(mapSignalToDomain(signal, context));
@@ -6210,7 +6405,7 @@ function processTextSignals2(signalParser, text, context) {
6210
6405
  });
6211
6406
  }
6212
6407
  function processLLMEvent2(signalParser, llmEvent, context) {
6213
- return Effect21.gen(function* () {
6408
+ return Effect22.gen(function* () {
6214
6409
  const domainEvent = mapLLMEventToDomain(llmEvent, context);
6215
6410
  const events = [domainEvent];
6216
6411
  let completed = false;
@@ -6243,7 +6438,7 @@ function processLLMEvent2(signalParser, llmEvent, context) {
6243
6438
  }
6244
6439
  function createIterationStream(llm, signalParser, planStore, currentPlanRef, loopCompletedRef, config, iteration, sessionId, worktreePath) {
6245
6440
  return Stream8.unwrap(
6246
- Effect21.gen(function* () {
6441
+ Effect22.gen(function* () {
6247
6442
  const currentPlan = yield* Ref11.get(currentPlanRef);
6248
6443
  const persistenceStateRef = yield* Ref11.make({
6249
6444
  dirty: false,
@@ -6266,7 +6461,7 @@ function createIterationStream(llm, signalParser, planStore, currentPlanRef, loo
6266
6461
  ),
6267
6462
  Stream8.flatMap(
6268
6463
  (llmEvent) => Stream8.unwrap(
6269
- Effect21.gen(function* () {
6464
+ Effect22.gen(function* () {
6270
6465
  const now = yield* DateTime9.now;
6271
6466
  const context = {
6272
6467
  timestamp: DateTime9.toEpochMillis(now)
@@ -6307,7 +6502,7 @@ function createIterationStream(llm, signalParser, planStore, currentPlanRef, loo
6307
6502
  )
6308
6503
  );
6309
6504
  const completionStream = Stream8.fromEffect(
6310
- Effect21.gen(function* () {
6505
+ Effect22.gen(function* () {
6311
6506
  const persistEvents = yield* flushPlanPersistence(
6312
6507
  planStore,
6313
6508
  currentPlanRef,
@@ -6332,14 +6527,14 @@ function createIterationStream(llm, signalParser, planStore, currentPlanRef, loo
6332
6527
  // src/orchestrator/loop.ts
6333
6528
  function runLoop(config) {
6334
6529
  return Stream9.unwrap(
6335
- Effect22.gen(function* () {
6530
+ Effect23.gen(function* () {
6336
6531
  const llm = yield* LLM;
6337
6532
  const signalParser = yield* SignalParser;
6338
6533
  const sessionStore = yield* SessionStore;
6339
6534
  const planStore = yield* PlanStore;
6340
6535
  const git = yield* Git;
6341
6536
  const session = yield* sessionStore.create(config.task).pipe(
6342
- Effect22.mapError(
6537
+ Effect23.mapError(
6343
6538
  (e) => new OrchestratorError({
6344
6539
  message: `Failed to create session: ${e.message}`,
6345
6540
  phase: "setup",
@@ -6348,7 +6543,7 @@ function runLoop(config) {
6348
6543
  )
6349
6544
  );
6350
6545
  const worktreePath = yield* git.createWorktree(session.id).pipe(
6351
- Effect22.mapError(
6546
+ Effect23.mapError(
6352
6547
  (e) => new OrchestratorError({
6353
6548
  message: `Failed to create worktree: ${e.message}`,
6354
6549
  phase: "setup",
@@ -6362,12 +6557,12 @@ function runLoop(config) {
6362
6557
  worktreePath,
6363
6558
  branchName
6364
6559
  }).pipe(
6365
- Effect22.tapError(
6366
- (error) => Effect22.logDebug("Failed to update session with worktree info", {
6560
+ Effect23.tapError(
6561
+ (error) => Effect23.logDebug("Failed to update session with worktree info", {
6367
6562
  error: String(error)
6368
6563
  })
6369
6564
  ),
6370
- Effect22.orElseSucceed(() => void 0)
6565
+ Effect23.orElseSucceed(() => void 0)
6371
6566
  );
6372
6567
  const startTimeUtc = yield* DateTime10.now;
6373
6568
  const startTime = DateTime10.toEpochMillis(startTimeUtc);
@@ -6397,7 +6592,7 @@ function runLoop(config) {
6397
6592
  );
6398
6593
  const iterationsStream = Stream9.unfoldEffect(
6399
6594
  1,
6400
- (iteration) => Effect22.gen(function* () {
6595
+ (iteration) => Effect23.gen(function* () {
6401
6596
  const completed = yield* Ref12.get(loopCompletedRef);
6402
6597
  if (completed || iteration > maxIterations) {
6403
6598
  return Option.none();
@@ -6437,8 +6632,8 @@ function runLoop(config) {
6437
6632
  );
6438
6633
  }).pipe(
6439
6634
  // Also catch setup errors (e.g., session creation failure)
6440
- Effect22.catchAll(
6441
- (error) => Effect22.succeed(
6635
+ Effect23.catchAll(
6636
+ (error) => Effect23.succeed(
6442
6637
  Stream9.succeed({
6443
6638
  _tag: "LoopFailed",
6444
6639
  error: {
@@ -6453,18 +6648,18 @@ function runLoop(config) {
6453
6648
  }
6454
6649
  function createCompletionStream(sessionStore, git, session, config, startTime, loopCompletedRef, _worktreePath) {
6455
6650
  return Stream9.unwrap(
6456
- Effect22.gen(function* () {
6651
+ Effect23.gen(function* () {
6457
6652
  const endTimeUtc = yield* DateTime10.now;
6458
6653
  const durationMs = DateTime10.toEpochMillis(endTimeUtc) - startTime;
6459
6654
  const completed = yield* Ref12.get(loopCompletedRef);
6460
6655
  yield* git.commitChanges(session.id, `feat: complete session ${session.id}`).pipe(
6461
- Effect22.tapError(
6462
- (error) => Effect22.logDebug("Final commit failed, continuing", {
6656
+ Effect23.tapError(
6657
+ (error) => Effect23.logDebug("Final commit failed, continuing", {
6463
6658
  sessionId: session.id,
6464
6659
  error: String(error)
6465
6660
  })
6466
6661
  ),
6467
- Effect22.orElseSucceed(() => void 0)
6662
+ Effect23.orElseSucceed(() => void 0)
6468
6663
  );
6469
6664
  const summary = {
6470
6665
  iterations: config.maxIterations,
@@ -6477,13 +6672,13 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6477
6672
  ...session,
6478
6673
  status: completed ? "completed" : "paused"
6479
6674
  }).pipe(
6480
- Effect22.tapError(
6481
- (error) => Effect22.logDebug("Session update failed, continuing", {
6675
+ Effect23.tapError(
6676
+ (error) => Effect23.logDebug("Session update failed, continuing", {
6482
6677
  sessionId: session.id,
6483
6678
  error: String(error)
6484
6679
  })
6485
6680
  ),
6486
- Effect22.orElseSucceed(() => void 0)
6681
+ Effect23.orElseSucceed(() => void 0)
6487
6682
  );
6488
6683
  const loopCompleted = { _tag: "LoopCompleted", summary };
6489
6684
  return Stream9.succeed(loopCompleted);
@@ -6495,10 +6690,9 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6495
6690
  function run(options) {
6496
6691
  const { config, consumer: consumerType = "headless", onEvent } = options;
6497
6692
  const events = runLoop(config);
6498
- const eventsWithCallback = onEvent ? events.pipe(Stream10.tap((event) => Effect23.sync(() => onEvent(event)))) : events;
6499
- const eventsWithLayers = eventsWithCallback.pipe(
6500
- Stream10.provideLayer(ProductionLayers)
6501
- );
6693
+ const eventsWithCallback = onEvent ? events.pipe(Stream10.tap((event) => Effect24.sync(() => onEvent(event)))) : events;
6694
+ const layers = config.provider ? createProductionLayers(config.provider) : ProductionLayers;
6695
+ const eventsWithLayers = eventsWithCallback.pipe(Stream10.provideLayer(layers));
6502
6696
  if (consumerType === "none") {
6503
6697
  return eventsWithLayers.pipe(Stream10.runDrain);
6504
6698
  }
@@ -6508,7 +6702,7 @@ function run(options) {
6508
6702
  function runTest(options, mockEvents) {
6509
6703
  const { config, onEvent } = options;
6510
6704
  const events = runLoop(config);
6511
- const eventsWithCallback = onEvent ? events.pipe(Stream10.tap((event) => Effect23.sync(() => onEvent(event)))) : events;
6705
+ const eventsWithCallback = onEvent ? events.pipe(Stream10.tap((event) => Effect24.sync(() => onEvent(event)))) : events;
6512
6706
  const layers = mockEvents ? createTestLayers(mockEvents) : TestLayers;
6513
6707
  const eventsWithLayers = eventsWithCallback.pipe(Stream10.provideLayer(layers));
6514
6708
  return eventsWithLayers.pipe(Stream10.runDrain);
@@ -6516,11 +6710,11 @@ function runTest(options, mockEvents) {
6516
6710
  function collectEvents(config, mockEvents) {
6517
6711
  const events = runLoop(config);
6518
6712
  const layers = mockEvents ? createTestLayers(mockEvents) : TestLayers;
6519
- return events.pipe(Stream10.provideLayer(layers), Stream10.runCollect).pipe(Effect23.map((chunk) => Array.from(chunk)));
6713
+ return events.pipe(Stream10.provideLayer(layers), Stream10.runCollect).pipe(Effect24.map((chunk) => Array.from(chunk)));
6520
6714
  }
6521
6715
  function main(config) {
6522
6716
  const consumerType = process.stdout.isTTY ? "tui" : "headless";
6523
- return run({ config, consumer: consumerType }).pipe(Effect23.runPromise);
6717
+ return run({ config, consumer: consumerType }).pipe(Effect24.runPromise);
6524
6718
  }
6525
6719
 
6526
6720
  // src/services/index.ts
@@ -6528,14 +6722,15 @@ init_esm_shims();
6528
6722
 
6529
6723
  // src/index.ts
6530
6724
  var program = new Command();
6531
- program.name("ferix-code").description("Composable RALPH loops for AI coding agents").version(package_default.version, "-v, --version", "Output the version number").argument("<task>", "Task description or path to PRD file").option("-i, --iterations <n>", "Maximum iterations", "1").option("-c, --verify <commands...>", "Verification commands to run").option("--branch <name>", "Git branch to create").option("--push", "Push branch after completion").option("--pr", "Create PR after pushing").action(async (task, options) => {
6725
+ program.name("ferix-code").description("Composable RALPH loops for AI coding agents").version(package_default.version, "-v, --version", "Output the version number").argument("<task>", "Task description or path to PRD file").option("-i, --iterations <n>", "Maximum iterations", "1").option("-c, --verify <commands...>", "Verification commands to run").option("--branch <name>", "Git branch to create").option("--push", "Push branch after completion").option("--pr", "Create PR after pushing").option("--provider <name>", "LLM provider to use (claude, cursor)", "claude").action(async (task, options) => {
6532
6726
  const config = {
6533
6727
  task,
6534
6728
  maxIterations: Number.parseInt(options.iterations, 10),
6535
6729
  verifyCommands: options.verify || [],
6536
6730
  branch: options.branch,
6537
6731
  push: options.push,
6538
- pr: options.pr
6732
+ pr: options.pr,
6733
+ provider: options.provider
6539
6734
  };
6540
6735
  try {
6541
6736
  await main(config);
@@ -6565,6 +6760,7 @@ export {
6565
6760
  CriterionPassedSignalSchema,
6566
6761
  CriterionSchema,
6567
6762
  CriterionStatusSchema,
6763
+ CursorCLI,
6568
6764
  DiscoveryCompletedEventSchema,
6569
6765
  DiscoveryStartedEventSchema,
6570
6766
  DomainEventSchema,
@@ -6620,6 +6816,7 @@ export {
6620
6816
  Mock,
6621
6817
  Mock as MockLLM,
6622
6818
  OrchestratorError,
6819
+ PROVIDER_CONFIGS,
6623
6820
  ParseError,
6624
6821
  PhaseBasicInfoSchema,
6625
6822
  PhaseCompletedEventSchema,
@@ -6652,6 +6849,7 @@ export {
6652
6849
  ProgressStoreError,
6653
6850
  ProgressUpdatedEventSchema,
6654
6851
  PromptConfigSchema,
6852
+ ProviderNameSchema,
6655
6853
  ReviewCompleteDataSchema,
6656
6854
  ReviewCompleteEventSchema,
6657
6855
  ReviewCompleteSignalSchema,
@@ -6690,6 +6888,8 @@ export {
6690
6888
  buildPrompt,
6691
6889
  collectEvents,
6692
6890
  createHeadlessConsumer,
6891
+ createProductionLayers,
6892
+ createProviderLayer2 as createProviderLayer,
6693
6893
  createTUIConsumer,
6694
6894
  createTestLayers,
6695
6895
  decodeGuardrail,