ferix-code 0.0.2-beta.15 → 0.0.2-beta.18

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +1034 -16
  2. package/dist/index.js +1187 -472
  3. package/package.json +1 -1
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.15",
74
+ version: "0.0.2-beta.18",
75
75
  description: "Composable RALPH loops for AI coding agents - v2 with Effect",
76
76
  type: "module",
77
77
  bin: {
@@ -316,7 +316,14 @@ var worktreeCreatedFormatter = {
316
316
  `[WORKTREE] Branch: ${event.branchName} | Path: ${event.worktreePath}`
317
317
  )
318
318
  };
319
+ var worktreeRemovedFormatter = {
320
+ tag: "WorktreeRemoved",
321
+ format: (event) => pc9.cyan(
322
+ `[WORKTREE] Cleaned up worktree for session: ${event.sessionId} (branch preserved)`
323
+ )
324
+ };
319
325
  headlessFormatterRegistry.register(worktreeCreatedFormatter);
326
+ headlessFormatterRegistry.register(worktreeRemovedFormatter);
320
327
 
321
328
  // src/consumers/headless/formatters/index.ts
322
329
  function formatEvent(event) {
@@ -1057,40 +1064,165 @@ init_esm_shims();
1057
1064
 
1058
1065
  // src/consumers/tui/tools/registry.ts
1059
1066
  init_esm_shims();
1067
+ import { Either as Either2 } from "effect";
1060
1068
  import pc13 from "picocolors";
1069
+
1070
+ // src/domain/schemas/tool-inputs.ts
1071
+ init_esm_shims();
1072
+ import { Either, Schema as S } from "effect";
1073
+ var ExtendableRecord = S.Record({ key: S.String, value: S.Unknown });
1074
+ var ReadToolInputSchema = S.Struct({
1075
+ file_path: S.String,
1076
+ offset: S.optional(S.Number),
1077
+ limit: S.optional(S.Number)
1078
+ }).pipe(S.extend(ExtendableRecord));
1079
+ var EditToolInputSchema = S.Struct({
1080
+ file_path: S.String,
1081
+ old_string: S.String,
1082
+ new_string: S.String,
1083
+ replace_all: S.optional(S.Boolean)
1084
+ }).pipe(S.extend(ExtendableRecord));
1085
+ var WriteToolInputSchema = S.Struct({
1086
+ file_path: S.String,
1087
+ content: S.String
1088
+ }).pipe(S.extend(ExtendableRecord));
1089
+ var BashToolInputSchema = S.Struct({
1090
+ command: S.String,
1091
+ description: S.optional(S.String),
1092
+ timeout: S.optional(S.Number),
1093
+ run_in_background: S.optional(S.Boolean)
1094
+ }).pipe(S.extend(ExtendableRecord));
1095
+ var GlobToolInputSchema = S.Struct({
1096
+ pattern: S.String,
1097
+ path: S.optional(S.String)
1098
+ }).pipe(S.extend(ExtendableRecord));
1099
+ var GrepToolInputSchema = S.Struct({
1100
+ pattern: S.String,
1101
+ path: S.optional(S.String),
1102
+ glob: S.optional(S.String),
1103
+ type: S.optional(S.String),
1104
+ output_mode: S.optional(S.Literal("content", "files_with_matches", "count"))
1105
+ }).pipe(S.extend(ExtendableRecord));
1106
+ var TaskToolInputSchema = S.Struct({
1107
+ description: S.String,
1108
+ prompt: S.optional(S.String)
1109
+ }).pipe(S.extend(ExtendableRecord));
1110
+ var WebFetchToolInputSchema = S.Struct({
1111
+ url: S.String,
1112
+ prompt: S.optional(S.String)
1113
+ }).pipe(S.extend(ExtendableRecord));
1114
+ var WebSearchToolInputSchema = S.Struct({
1115
+ query: S.String
1116
+ }).pipe(S.extend(ExtendableRecord));
1117
+ var ToolInputSchemaRegistry = {
1118
+ read: ReadToolInputSchema,
1119
+ edit: EditToolInputSchema,
1120
+ write: WriteToolInputSchema,
1121
+ bash: BashToolInputSchema,
1122
+ glob: GlobToolInputSchema,
1123
+ grep: GrepToolInputSchema,
1124
+ task: TaskToolInputSchema,
1125
+ webfetch: WebFetchToolInputSchema,
1126
+ websearch: WebSearchToolInputSchema
1127
+ };
1128
+ function getToolInputSchema(tool) {
1129
+ const normalized = tool.toLowerCase();
1130
+ if (normalized in ToolInputSchemaRegistry) {
1131
+ return ToolInputSchemaRegistry[normalized];
1132
+ }
1133
+ return void 0;
1134
+ }
1135
+ var AnyToolInputSchema = S.Union(
1136
+ ReadToolInputSchema,
1137
+ EditToolInputSchema,
1138
+ WriteToolInputSchema,
1139
+ BashToolInputSchema,
1140
+ GlobToolInputSchema,
1141
+ GrepToolInputSchema,
1142
+ TaskToolInputSchema,
1143
+ WebFetchToolInputSchema,
1144
+ WebSearchToolInputSchema
1145
+ );
1146
+ function validateToolInput(tool, input) {
1147
+ const schema = getToolInputSchema(tool);
1148
+ if (!schema) {
1149
+ return Either.right(input);
1150
+ }
1151
+ return S.decodeUnknownEither(schema)(input);
1152
+ }
1153
+ var isReadToolInput = S.is(ReadToolInputSchema);
1154
+ var isEditToolInput = S.is(EditToolInputSchema);
1155
+ var isWriteToolInput = S.is(WriteToolInputSchema);
1156
+ var isBashToolInput = S.is(BashToolInputSchema);
1157
+ var isGlobToolInput = S.is(GlobToolInputSchema);
1158
+ var isGrepToolInput = S.is(GrepToolInputSchema);
1159
+ var isTaskToolInput = S.is(TaskToolInputSchema);
1160
+ var isWebFetchToolInput = S.is(WebFetchToolInputSchema);
1161
+ var isWebSearchToolInput = S.is(WebSearchToolInputSchema);
1162
+
1163
+ // src/consumers/tui/tools/registry.ts
1061
1164
  var brightWhite = (s) => pc13.bold(pc13.white(s));
1165
+ function normalizeToolName(tool) {
1166
+ return tool.toLowerCase();
1167
+ }
1168
+ function extractStringValue(obj, key) {
1169
+ const getValue = (k) => {
1170
+ const val = obj[k];
1171
+ return typeof val === "string" ? val : void 0;
1172
+ };
1173
+ const exact = getValue(key);
1174
+ if (exact !== void 0) {
1175
+ return exact;
1176
+ }
1177
+ const camelKey = key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
1178
+ const camel = getValue(camelKey);
1179
+ if (camel !== void 0) {
1180
+ return camel;
1181
+ }
1182
+ const snakeKey = key.replace(/([A-Z])/g, "_$1").toLowerCase();
1183
+ return getValue(snakeKey);
1184
+ }
1185
+ function getValidatedInput(tool, input) {
1186
+ if (!input || typeof input !== "object") {
1187
+ return null;
1188
+ }
1189
+ const result = validateToolInput(tool, input);
1190
+ if (Either2.isRight(result)) {
1191
+ return result.right;
1192
+ }
1193
+ return input;
1194
+ }
1062
1195
  function createToolDisplayRegistry() {
1063
1196
  const configs = /* @__PURE__ */ new Map();
1064
1197
  const defaultColor = pc13.white;
1065
1198
  return {
1066
1199
  register(config) {
1067
- configs.set(config.tool, config);
1200
+ configs.set(normalizeToolName(config.tool), config);
1068
1201
  },
1069
1202
  getInputKey(tool) {
1070
- return configs.get(tool)?.inputKey;
1203
+ return configs.get(normalizeToolName(tool))?.inputKey;
1071
1204
  },
1072
1205
  getColor(tool) {
1073
- return configs.get(tool)?.color ?? defaultColor;
1206
+ return configs.get(normalizeToolName(tool))?.color ?? defaultColor;
1074
1207
  },
1075
1208
  getMaxLength(tool) {
1076
- return configs.get(tool)?.maxLength ?? MAX_TOOL_INPUT_LENGTH;
1209
+ return configs.get(normalizeToolName(tool))?.maxLength ?? MAX_TOOL_INPUT_LENGTH;
1077
1210
  },
1078
1211
  formatInput(tool, input) {
1079
- if (!input || typeof input !== "object") {
1212
+ const config = configs.get(normalizeToolName(tool));
1213
+ if (!config) {
1080
1214
  return "";
1081
1215
  }
1082
- const config = configs.get(tool);
1083
- if (!config) {
1216
+ const obj = getValidatedInput(tool, input);
1217
+ if (!obj) {
1084
1218
  return "";
1085
1219
  }
1086
- const obj = input;
1087
- const value = obj[config.inputKey];
1220
+ const value = extractStringValue(obj, config.inputKey);
1088
1221
  if (!value) {
1089
1222
  return "";
1090
1223
  }
1091
- const str = String(value);
1092
1224
  const maxLen = config.maxLength ?? MAX_TOOL_INPUT_LENGTH;
1093
- return str.length > maxLen ? `${str.slice(0, maxLen)}...` : str;
1225
+ return value.length > maxLen ? `${value.slice(0, maxLen)}...` : value;
1094
1226
  }
1095
1227
  };
1096
1228
  }
@@ -1147,11 +1279,47 @@ function formatToolInput(tool, input) {
1147
1279
  }
1148
1280
 
1149
1281
  // src/consumers/tui/reducers/helpers.ts
1282
+ var FERIX_BLOCK_PATTERNS = [
1283
+ /<ferix:session-name>[\s\S]*?<\/ferix:session-name>/g,
1284
+ /<ferix:tasks>[\s\S]*?<\/ferix:tasks>/g,
1285
+ /<ferix:phases[^>]*>[\s\S]*?<\/ferix:phases>/g,
1286
+ /<ferix:criteria[^>]*>[\s\S]*?<\/ferix:criteria>/g,
1287
+ /<ferix:task-complete[^>]*>[\s\S]*?<\/ferix:task-complete>/g,
1288
+ /<ferix:phase-failed[^>]*>[\s\S]*?<\/ferix:phase-failed>/g,
1289
+ /<ferix:learning[^>]*>[\s\S]*?<\/ferix:learning>/g,
1290
+ /<ferix:guardrail[^>]*>[\s\S]*?<\/ferix:guardrail>/g
1291
+ ];
1292
+ var FERIX_SELF_CLOSING_PATTERNS = [
1293
+ /<ferix:phase-start[^>]*\/>/g,
1294
+ /<ferix:phase-done[^>]*\/>/g,
1295
+ /<ferix:criterion-passed[^>]*\/>/g,
1296
+ /<ferix:criterion-failed[^>]*\/>/g,
1297
+ /<ferix:check-passed\s*\/>/g,
1298
+ /<ferix:check-failed\s*\/>/g,
1299
+ /<ferix:review-complete\s*\/>/g,
1300
+ /<ferix:review-changes-made\s*\/>/g,
1301
+ /<ferix:complete\s*>/g
1302
+ // Note: complete is not self-closing, just <ferix:complete>
1303
+ ];
1304
+ function stripFerixSignals(text) {
1305
+ let result = text;
1306
+ for (const pattern of FERIX_BLOCK_PATTERNS) {
1307
+ result = result.replace(pattern, "");
1308
+ }
1309
+ for (const pattern of FERIX_SELF_CLOSING_PATTERNS) {
1310
+ result = result.replace(pattern, "");
1311
+ }
1312
+ return result;
1313
+ }
1150
1314
  function appendOutput(state, text) {
1151
1315
  if (!text) {
1152
1316
  return state;
1153
1317
  }
1154
- const fullText = state.partialLine + text;
1318
+ const cleanedText = stripFerixSignals(text);
1319
+ if (!cleanedText) {
1320
+ return state;
1321
+ }
1322
+ const fullText = state.partialLine + cleanedText;
1155
1323
  const parts = fullText.split("\n");
1156
1324
  const partialLine = parts.pop() ?? "";
1157
1325
  const newLines = parts.filter((line) => line.length > 0);
@@ -1439,7 +1607,18 @@ Worktree created
1439
1607
  `
1440
1608
  )
1441
1609
  };
1610
+ var worktreeRemovedReducer = {
1611
+ tag: "WorktreeRemoved",
1612
+ reduce: (state, event) => appendOutput(
1613
+ state,
1614
+ `
1615
+ Worktree cleaned up (branch preserved)
1616
+ Session: ${event.sessionId}
1617
+ `
1618
+ )
1619
+ };
1442
1620
  stateReducerRegistry.register(worktreeCreatedReducer);
1621
+ stateReducerRegistry.register(worktreeRemovedReducer);
1443
1622
 
1444
1623
  // src/consumers/tui/reducers/index.ts
1445
1624
  function reduce(state, event) {
@@ -2536,6 +2715,36 @@ var make = {
2536
2715
  Effect4.catchAll(() => Effect4.succeed(void 0))
2537
2716
  );
2538
2717
  }),
2718
+ removeWorktreeKeepBranch: (sessionId) => Effect4.gen(function* () {
2719
+ const worktreeDir = getWorktreeDir(sessionId);
2720
+ const exists = yield* directoryExists(worktreeDir);
2721
+ if (!exists) {
2722
+ return;
2723
+ }
2724
+ yield* gitExec(`git worktree remove "${worktreeDir}" --force`).pipe(
2725
+ Effect4.mapError(
2726
+ (error) => new GitError({
2727
+ message: `Failed to remove worktree: ${error.message}`,
2728
+ operation: "removeWorktreeKeepBranch",
2729
+ cause: error
2730
+ })
2731
+ ),
2732
+ // If git worktree remove fails, try manual cleanup
2733
+ Effect4.catchAll(
2734
+ () => Effect4.tryPromise({
2735
+ try: () => rm(worktreeDir, { recursive: true, force: true }),
2736
+ catch: (error) => new GitError({
2737
+ message: `Failed to remove worktree directory: ${String(error)}`,
2738
+ operation: "removeWorktreeKeepBranch",
2739
+ cause: error
2740
+ })
2741
+ })
2742
+ )
2743
+ );
2744
+ yield* gitExec("git worktree prune").pipe(
2745
+ Effect4.catchAll(() => Effect4.succeed(void 0))
2746
+ );
2747
+ }),
2539
2748
  getWorktreePath: (sessionId) => Effect4.gen(function* () {
2540
2749
  const worktreeDir = getWorktreeDir(sessionId);
2541
2750
  const exists = yield* directoryExists(worktreeDir);
@@ -2646,6 +2855,33 @@ var make = {
2646
2855
  );
2647
2856
  return prUrl;
2648
2857
  }),
2858
+ renameBranch: (sessionId, displayName) => Effect4.gen(function* () {
2859
+ const worktreeDir = getWorktreeDir(sessionId);
2860
+ const oldBranchName = getBranchName(sessionId);
2861
+ const newBranchName = `${BRANCH_PREFIX}/${displayName}`;
2862
+ const exists = yield* directoryExists(worktreeDir);
2863
+ if (!exists) {
2864
+ return yield* Effect4.fail(
2865
+ new GitError({
2866
+ message: `Worktree not found for session: ${sessionId}`,
2867
+ operation: "renameBranch"
2868
+ })
2869
+ );
2870
+ }
2871
+ yield* gitExec(
2872
+ `git branch -m "${oldBranchName}" "${newBranchName}"`,
2873
+ worktreeDir
2874
+ ).pipe(
2875
+ Effect4.mapError(
2876
+ (error) => new GitError({
2877
+ message: `Failed to rename branch: ${error.message}`,
2878
+ operation: "renameBranch",
2879
+ cause: error
2880
+ })
2881
+ )
2882
+ );
2883
+ return newBranchName;
2884
+ }),
2649
2885
  getBranchName
2650
2886
  };
2651
2887
  var Live = Layer.succeed(Git, make);
@@ -2684,6 +2920,11 @@ function createMemoryGitService(stateRef, commitCounterRef) {
2684
2920
  state.delete(sessionId);
2685
2921
  yield* Ref3.set(stateRef, state);
2686
2922
  }),
2923
+ removeWorktreeKeepBranch: (sessionId) => Effect5.gen(function* () {
2924
+ const state = yield* Ref3.get(stateRef);
2925
+ state.delete(sessionId);
2926
+ yield* Ref3.set(stateRef, state);
2927
+ }),
2687
2928
  getWorktreePath: (sessionId) => Effect5.gen(function* () {
2688
2929
  const state = yield* Ref3.get(stateRef);
2689
2930
  const worktree = state.get(sessionId);
@@ -2736,6 +2977,26 @@ function createMemoryGitService(stateRef, commitCounterRef) {
2736
2977
  const slug = title.toLowerCase().replace(/\s+/g, "-").slice(0, 30);
2737
2978
  return `https://github.com/test/repo/pull/${slug}`;
2738
2979
  }),
2980
+ renameBranch: (sessionId, displayName) => Effect5.gen(function* () {
2981
+ const state = yield* Ref3.get(stateRef);
2982
+ const worktree = state.get(sessionId);
2983
+ if (!worktree) {
2984
+ return yield* Effect5.fail(
2985
+ new GitError({
2986
+ message: `Worktree not found for session: ${sessionId}`,
2987
+ operation: "renameBranch"
2988
+ })
2989
+ );
2990
+ }
2991
+ const newBranchName = `${BRANCH_PREFIX2}/${displayName}`;
2992
+ const updatedWorktree = {
2993
+ ...worktree,
2994
+ branch: newBranchName
2995
+ };
2996
+ state.set(sessionId, updatedWorktree);
2997
+ yield* Ref3.set(stateRef, state);
2998
+ return newBranchName;
2999
+ }),
2739
3000
  getBranchName: getBranchName2
2740
3001
  };
2741
3002
  }
@@ -2767,60 +3028,196 @@ init_esm_shims();
2767
3028
  // src/domain/schemas/index.ts
2768
3029
  init_esm_shims();
2769
3030
 
3031
+ // src/domain/schemas/cli-output.ts
3032
+ init_esm_shims();
3033
+ import { Schema as S2 } from "effect";
3034
+ var TextDeltaSchema = S2.Struct({
3035
+ type: S2.Literal("text_delta"),
3036
+ text: S2.String
3037
+ });
3038
+ var InputJsonDeltaSchema = S2.Struct({
3039
+ type: S2.Literal("input_json_delta"),
3040
+ partial_json: S2.String
3041
+ });
3042
+ var DeltaSchema = S2.Union(TextDeltaSchema, InputJsonDeltaSchema);
3043
+ var TextContentBlockSchema = S2.Struct({
3044
+ type: S2.Literal("text"),
3045
+ text: S2.String
3046
+ });
3047
+ var ToolUseContentBlockSchema = S2.Struct({
3048
+ type: S2.Literal("tool_use"),
3049
+ id: S2.optional(S2.String),
3050
+ name: S2.String,
3051
+ input: S2.Unknown
3052
+ });
3053
+ var ContentBlockSchema = S2.Union(
3054
+ TextContentBlockSchema,
3055
+ ToolUseContentBlockSchema
3056
+ );
3057
+ var ContentBlockStartSchema = S2.Struct({
3058
+ type: S2.Literal("content_block_start"),
3059
+ index: S2.optional(S2.Number),
3060
+ content_block: S2.Union(
3061
+ S2.Struct({
3062
+ type: S2.Literal("text"),
3063
+ text: S2.optional(S2.String)
3064
+ }),
3065
+ S2.Struct({
3066
+ type: S2.Literal("tool_use"),
3067
+ id: S2.optional(S2.String),
3068
+ name: S2.String,
3069
+ input: S2.optional(S2.Unknown)
3070
+ })
3071
+ )
3072
+ });
3073
+ var ContentBlockDeltaSchema = S2.Struct({
3074
+ type: S2.Literal("content_block_delta"),
3075
+ index: S2.optional(S2.Number),
3076
+ delta: DeltaSchema
3077
+ });
3078
+ var ContentBlockStopSchema = S2.Struct({
3079
+ type: S2.Literal("content_block_stop"),
3080
+ index: S2.optional(S2.Number)
3081
+ });
3082
+ var AssistantMessageSchema = S2.Struct({
3083
+ type: S2.Literal("assistant"),
3084
+ message: S2.Struct({
3085
+ content: S2.Array(ContentBlockSchema)
3086
+ })
3087
+ });
3088
+ var StreamEventEnvelopeSchema = S2.Struct({
3089
+ type: S2.Literal("stream_event"),
3090
+ event: S2.Unknown
3091
+ });
3092
+ var ClaudeCliEventSchema = S2.Union(
3093
+ ContentBlockStartSchema,
3094
+ ContentBlockDeltaSchema,
3095
+ ContentBlockStopSchema,
3096
+ AssistantMessageSchema,
3097
+ StreamEventEnvelopeSchema
3098
+ );
3099
+ var isContentBlockStart = S2.is(ContentBlockStartSchema);
3100
+ var isContentBlockDelta = S2.is(ContentBlockDeltaSchema);
3101
+ var isContentBlockStop = S2.is(ContentBlockStopSchema);
3102
+ var isAssistantMessage = S2.is(AssistantMessageSchema);
3103
+ var isStreamEventEnvelope = S2.is(StreamEventEnvelopeSchema);
3104
+ var isTextDelta = S2.is(TextDeltaSchema);
3105
+ var isInputJsonDelta = S2.is(InputJsonDeltaSchema);
3106
+ var isToolUseContentBlock = S2.is(ToolUseContentBlockSchema);
3107
+ var isTextContentBlock = S2.is(TextContentBlockSchema);
3108
+ var decodeClaudeCliEvent = S2.decodeUnknown(ClaudeCliEventSchema);
3109
+ var decodeClaudeCliEventSync = S2.decodeUnknownSync(ClaudeCliEventSchema);
3110
+
3111
+ // src/domain/schemas/cli-output-opencode.ts
3112
+ init_esm_shims();
3113
+ import { Schema as S3 } from "effect";
3114
+ var OpenCodeTextEventSchema = S3.Struct({
3115
+ type: S3.Literal("text"),
3116
+ text: S3.String
3117
+ });
3118
+ var OpenCodeToolStateSchema = S3.Struct({
3119
+ status: S3.String,
3120
+ input: S3.Unknown,
3121
+ output: S3.optional(S3.String)
3122
+ });
3123
+ var OpenCodeToolPartSchema = S3.Struct({
3124
+ tool: S3.String,
3125
+ callID: S3.String,
3126
+ state: OpenCodeToolStateSchema
3127
+ });
3128
+ var OpenCodeToolUseEventSchema = S3.Struct({
3129
+ type: S3.Literal("tool_use"),
3130
+ part: OpenCodeToolPartSchema
3131
+ });
3132
+ var OpenCodeStepPartSchema = S3.Struct({}).pipe(
3133
+ S3.extend(S3.Record({ key: S3.String, value: S3.Unknown }))
3134
+ );
3135
+ var OpenCodeStepStartSchema = S3.Struct({
3136
+ type: S3.Literal("step_start"),
3137
+ timestamp: S3.Number,
3138
+ sessionID: S3.String,
3139
+ part: S3.optional(OpenCodeStepPartSchema)
3140
+ });
3141
+ var OpenCodeTokensSchema = S3.Struct({}).pipe(
3142
+ S3.extend(S3.Record({ key: S3.String, value: S3.Unknown }))
3143
+ );
3144
+ var OpenCodeCostSchema = S3.Struct({}).pipe(
3145
+ S3.extend(S3.Record({ key: S3.String, value: S3.Unknown }))
3146
+ );
3147
+ var OpenCodeStepFinishSchema = S3.Struct({
3148
+ type: S3.Literal("step_finish"),
3149
+ tokens: S3.optional(OpenCodeTokensSchema),
3150
+ cost: S3.optional(OpenCodeCostSchema)
3151
+ });
3152
+ var OpenCodeCliEventSchema = S3.Union(
3153
+ OpenCodeTextEventSchema,
3154
+ OpenCodeToolUseEventSchema,
3155
+ OpenCodeStepStartSchema,
3156
+ OpenCodeStepFinishSchema
3157
+ );
3158
+ var isOpenCodeTextEvent = S3.is(OpenCodeTextEventSchema);
3159
+ var isOpenCodeToolUseEvent = S3.is(OpenCodeToolUseEventSchema);
3160
+ var isOpenCodeStepStart = S3.is(OpenCodeStepStartSchema);
3161
+ var isOpenCodeStepFinish = S3.is(OpenCodeStepFinishSchema);
3162
+ var decodeOpenCodeCliEvent = S3.decodeUnknown(OpenCodeCliEventSchema);
3163
+ var decodeOpenCodeCliEventSync = S3.decodeUnknownSync(
3164
+ OpenCodeCliEventSchema
3165
+ );
3166
+
2770
3167
  // src/domain/schemas/config.ts
2771
3168
  init_esm_shims();
2772
- import { Schema as S } from "effect";
2773
- var ProviderNameSchema = S.Literal("claude", "cursor", "opencode");
2774
- var PhasePromptOverridesSchema = S.Struct({
2775
- breakdown: S.optional(S.String),
2776
- planning: S.optional(S.String),
2777
- execution: S.optional(S.String),
2778
- check: S.optional(S.String),
2779
- verify: S.optional(S.String),
2780
- review: S.optional(S.String),
2781
- completion: S.optional(S.String)
2782
- });
2783
- var PromptConfigSchema = S.Struct({
2784
- systemPrompt: S.optional(S.String),
2785
- phases: S.optional(PhasePromptOverridesSchema),
2786
- additionalContext: S.optional(S.String)
2787
- });
2788
- var LoopConfigSchema = S.Struct({
2789
- task: S.String,
2790
- maxIterations: S.Number,
2791
- verifyCommands: S.Array(S.String),
2792
- sessionId: S.optional(S.String),
2793
- branch: S.optional(S.String),
2794
- push: S.optional(S.Boolean),
2795
- pr: S.optional(S.Boolean),
2796
- verbose: S.optional(S.Boolean),
2797
- prompts: S.optional(PromptConfigSchema),
3169
+ import { Schema as S4 } from "effect";
3170
+ var ProviderNameSchema = S4.Literal("claude", "cursor", "opencode");
3171
+ var PhasePromptOverridesSchema = S4.Struct({
3172
+ breakdown: S4.optional(S4.String),
3173
+ planning: S4.optional(S4.String),
3174
+ execution: S4.optional(S4.String),
3175
+ check: S4.optional(S4.String),
3176
+ verify: S4.optional(S4.String),
3177
+ review: S4.optional(S4.String),
3178
+ completion: S4.optional(S4.String)
3179
+ });
3180
+ var PromptConfigSchema = S4.Struct({
3181
+ systemPrompt: S4.optional(S4.String),
3182
+ phases: S4.optional(PhasePromptOverridesSchema),
3183
+ additionalContext: S4.optional(S4.String)
3184
+ });
3185
+ var LoopConfigSchema = S4.Struct({
3186
+ task: S4.String,
3187
+ maxIterations: S4.Number,
3188
+ verifyCommands: S4.Array(S4.String),
3189
+ sessionId: S4.optional(S4.String),
3190
+ branch: S4.optional(S4.String),
3191
+ push: S4.optional(S4.Boolean),
3192
+ pr: S4.optional(S4.Boolean),
3193
+ verbose: S4.optional(S4.Boolean),
3194
+ prompts: S4.optional(PromptConfigSchema),
2798
3195
  /** LLM provider to use. Defaults to "claude". */
2799
- provider: S.optional(ProviderNameSchema)
3196
+ provider: S4.optional(ProviderNameSchema)
2800
3197
  });
2801
- var LoopSummarySchema = S.Struct({
2802
- iterations: S.Number,
2803
- success: S.Boolean,
2804
- sessionId: S.String,
2805
- completedTasks: S.Array(S.String),
2806
- durationMs: S.Number
3198
+ var LoopSummarySchema = S4.Struct({
3199
+ iterations: S4.Number,
3200
+ success: S4.Boolean,
3201
+ sessionId: S4.String,
3202
+ completedTasks: S4.Array(S4.String),
3203
+ durationMs: S4.Number
2807
3204
  });
2808
- var LoopErrorSchema = S.Struct({
2809
- message: S.String,
2810
- phase: S.String,
2811
- iteration: S.optional(S.Number)
3205
+ var LoopErrorSchema = S4.Struct({
3206
+ message: S4.String,
3207
+ phase: S4.String,
3208
+ iteration: S4.optional(S4.Number)
2812
3209
  });
2813
- var decodeLoopConfig = S.decodeUnknown(LoopConfigSchema);
3210
+ var decodeLoopConfig = S4.decodeUnknown(LoopConfigSchema);
2814
3211
 
2815
3212
  // src/domain/schemas/events.ts
2816
3213
  init_esm_shims();
2817
- import { Schema as S4 } from "effect";
3214
+ import { Schema as S7 } from "effect";
2818
3215
 
2819
3216
  // src/domain/schemas/plan.ts
2820
3217
  init_esm_shims();
2821
- import { Brand, Schema as S2 } from "effect";
3218
+ import { Brand, Schema as S5 } from "effect";
2822
3219
  var PlanId = Brand.nominal();
2823
- var TaskStatusSchema = S2.Literal(
3220
+ var TaskStatusSchema = S5.Literal(
2824
3221
  "pending",
2825
3222
  "planning",
2826
3223
  "in_progress",
@@ -2828,114 +3225,114 @@ var TaskStatusSchema = S2.Literal(
2828
3225
  "failed",
2829
3226
  "skipped"
2830
3227
  );
2831
- var PhaseStatusSchema = S2.Literal(
3228
+ var PhaseStatusSchema = S5.Literal(
2832
3229
  "pending",
2833
3230
  "in_progress",
2834
3231
  "done",
2835
3232
  "failed"
2836
3233
  );
2837
- var CriterionStatusSchema = S2.Literal("pending", "passed", "failed");
2838
- var PhaseSchema = S2.Struct({
2839
- id: S2.String,
2840
- description: S2.String,
3234
+ var CriterionStatusSchema = S5.Literal("pending", "passed", "failed");
3235
+ var PhaseSchema = S5.Struct({
3236
+ id: S5.String,
3237
+ description: S5.String,
2841
3238
  status: PhaseStatusSchema
2842
3239
  });
2843
- var CriterionSchema = S2.Struct({
2844
- id: S2.String,
2845
- description: S2.String,
3240
+ var CriterionSchema = S5.Struct({
3241
+ id: S5.String,
3242
+ description: S5.String,
2846
3243
  status: CriterionStatusSchema,
2847
- failureReason: S2.optional(S2.String)
3244
+ failureReason: S5.optional(S5.String)
2848
3245
  });
2849
- var TaskSchema = S2.Struct({
2850
- id: S2.String,
2851
- title: S2.String,
2852
- description: S2.String,
3246
+ var TaskSchema = S5.Struct({
3247
+ id: S5.String,
3248
+ title: S5.String,
3249
+ description: S5.String,
2853
3250
  status: TaskStatusSchema,
2854
- phases: S2.Array(PhaseSchema),
2855
- criteria: S2.Array(CriterionSchema),
2856
- filesToModify: S2.Array(S2.String),
2857
- attempts: S2.Number,
2858
- completionNotes: S2.optional(S2.String)
2859
- });
2860
- var PlanDataSchema = S2.Struct({
2861
- sessionId: S2.String,
2862
- createdAt: S2.String,
2863
- originalTask: S2.String,
2864
- context: S2.optional(S2.String),
2865
- tasks: S2.Array(TaskSchema)
2866
- });
2867
- var PlanSchema = S2.Struct({
2868
- id: S2.String,
2869
- sessionId: S2.String,
2870
- createdAt: S2.String,
2871
- originalTask: S2.String,
2872
- context: S2.optional(S2.String),
2873
- tasks: S2.Array(TaskSchema)
2874
- });
2875
- var decodePlan = S2.decodeUnknown(PlanSchema);
2876
- var decodePlanData = S2.decodeUnknown(PlanDataSchema);
3251
+ phases: S5.Array(PhaseSchema),
3252
+ criteria: S5.Array(CriterionSchema),
3253
+ filesToModify: S5.Array(S5.String),
3254
+ attempts: S5.Number,
3255
+ completionNotes: S5.optional(S5.String)
3256
+ });
3257
+ var PlanDataSchema = S5.Struct({
3258
+ sessionId: S5.String,
3259
+ createdAt: S5.String,
3260
+ originalTask: S5.String,
3261
+ context: S5.optional(S5.String),
3262
+ tasks: S5.Array(TaskSchema)
3263
+ });
3264
+ var PlanSchema = S5.Struct({
3265
+ id: S5.String,
3266
+ sessionId: S5.String,
3267
+ createdAt: S5.String,
3268
+ originalTask: S5.String,
3269
+ context: S5.optional(S5.String),
3270
+ tasks: S5.Array(TaskSchema)
3271
+ });
3272
+ var decodePlan = S5.decodeUnknown(PlanSchema);
3273
+ var decodePlanData = S5.decodeUnknown(PlanDataSchema);
2877
3274
 
2878
3275
  // src/domain/schemas/shared.ts
2879
3276
  init_esm_shims();
2880
- import { Schema as S3 } from "effect";
2881
- var TaskBasicInfoSchema = S3.Struct({
2882
- id: S3.String,
2883
- title: S3.String,
2884
- description: S3.String
3277
+ import { Schema as S6 } from "effect";
3278
+ var TaskBasicInfoSchema = S6.Struct({
3279
+ id: S6.String,
3280
+ title: S6.String,
3281
+ description: S6.String
2885
3282
  });
2886
- var PhaseBasicInfoSchema = S3.Struct({
2887
- id: S3.String,
2888
- description: S3.String
3283
+ var PhaseBasicInfoSchema = S6.Struct({
3284
+ id: S6.String,
3285
+ description: S6.String
2889
3286
  });
2890
- var CriterionBasicInfoSchema = S3.Struct({
2891
- id: S3.String,
2892
- description: S3.String
3287
+ var CriterionBasicInfoSchema = S6.Struct({
3288
+ id: S6.String,
3289
+ description: S6.String
2893
3290
  });
2894
- var TasksDefinedDataSchema = S3.Struct({
2895
- tasks: S3.Array(TaskBasicInfoSchema)
3291
+ var TasksDefinedDataSchema = S6.Struct({
3292
+ tasks: S6.Array(TaskBasicInfoSchema)
2896
3293
  });
2897
- var PhasesDefinedDataSchema = S3.Struct({
2898
- taskId: S3.String,
2899
- phases: S3.Array(PhaseBasicInfoSchema)
3294
+ var PhasesDefinedDataSchema = S6.Struct({
3295
+ taskId: S6.String,
3296
+ phases: S6.Array(PhaseBasicInfoSchema)
2900
3297
  });
2901
- var CriteriaDefinedDataSchema = S3.Struct({
2902
- taskId: S3.String,
2903
- criteria: S3.Array(CriterionBasicInfoSchema)
3298
+ var CriteriaDefinedDataSchema = S6.Struct({
3299
+ taskId: S6.String,
3300
+ criteria: S6.Array(CriterionBasicInfoSchema)
2904
3301
  });
2905
- var PhaseIdDataSchema = S3.Struct({
2906
- phaseId: S3.String
3302
+ var PhaseIdDataSchema = S6.Struct({
3303
+ phaseId: S6.String
2907
3304
  });
2908
- var PhaseFailedDataSchema = S3.Struct({
2909
- phaseId: S3.String,
2910
- reason: S3.String
3305
+ var PhaseFailedDataSchema = S6.Struct({
3306
+ phaseId: S6.String,
3307
+ reason: S6.String
2911
3308
  });
2912
- var CriterionIdDataSchema = S3.Struct({
2913
- criterionId: S3.String
3309
+ var CriterionIdDataSchema = S6.Struct({
3310
+ criterionId: S6.String
2914
3311
  });
2915
- var CriterionFailedDataSchema = S3.Struct({
2916
- criterionId: S3.String,
2917
- reason: S3.String
3312
+ var CriterionFailedDataSchema = S6.Struct({
3313
+ criterionId: S6.String,
3314
+ reason: S6.String
2918
3315
  });
2919
- var ReviewCompleteDataSchema = S3.Struct({
2920
- changesMade: S3.Boolean
3316
+ var ReviewCompleteDataSchema = S6.Struct({
3317
+ changesMade: S6.Boolean
2921
3318
  });
2922
- var TaskCompleteSignalDataSchema = S3.Struct({
2923
- taskId: S3.String,
2924
- summary: S3.String,
2925
- filesModified: S3.Array(S3.String),
2926
- filesCreated: S3.Array(S3.String)
3319
+ var TaskCompleteSignalDataSchema = S6.Struct({
3320
+ taskId: S6.String,
3321
+ summary: S6.String,
3322
+ filesModified: S6.Array(S6.String),
3323
+ filesCreated: S6.Array(S6.String)
2927
3324
  });
2928
- var TaskCompleteDataSchema = S3.Struct({
2929
- taskId: S3.String,
2930
- summary: S3.String
3325
+ var TaskCompleteDataSchema = S6.Struct({
3326
+ taskId: S6.String,
3327
+ summary: S6.String
2931
3328
  });
2932
3329
 
2933
3330
  // src/domain/schemas/events.ts
2934
- var taggedEvent = (tag, fields) => S4.TaggedStruct(tag, fields);
2935
- var taggedFromData = (tag, dataSchema, extraFields = {}) => S4.TaggedStruct(tag, { ...dataSchema.fields, ...extraFields });
3331
+ var taggedEvent = (tag, fields) => S7.TaggedStruct(tag, fields);
3332
+ var taggedFromData = (tag, dataSchema, extraFields = {}) => S7.TaggedStruct(tag, { ...dataSchema.fields, ...extraFields });
2936
3333
  var LoopStartedEventSchema = taggedEvent("LoopStarted", {
2937
3334
  config: LoopConfigSchema,
2938
- timestamp: S4.Number
3335
+ timestamp: S7.Number
2939
3336
  });
2940
3337
  var LoopCompletedEventSchema = taggedEvent("LoopCompleted", {
2941
3338
  summary: LoopSummarySchema
@@ -2944,30 +3341,30 @@ var LoopFailedEventSchema = taggedEvent("LoopFailed", {
2944
3341
  error: LoopErrorSchema
2945
3342
  });
2946
3343
  var DiscoveryStartedEventSchema = taggedEvent("DiscoveryStarted", {
2947
- timestamp: S4.Number
3344
+ timestamp: S7.Number
2948
3345
  });
2949
3346
  var DiscoveryCompletedEventSchema = taggedEvent("DiscoveryCompleted", {
2950
- taskCount: S4.Number,
2951
- timestamp: S4.Number
3347
+ taskCount: S7.Number,
3348
+ timestamp: S7.Number
2952
3349
  });
2953
3350
  var IterationStartedEventSchema = taggedEvent("IterationStarted", {
2954
- iteration: S4.Number
3351
+ iteration: S7.Number
2955
3352
  });
2956
3353
  var IterationCompletedEventSchema = taggedEvent("IterationCompleted", {
2957
- iteration: S4.Number
3354
+ iteration: S7.Number
2958
3355
  });
2959
3356
  var LLMTextEventSchema = taggedEvent("LLMText", {
2960
- text: S4.String
3357
+ text: S7.String
2961
3358
  });
2962
3359
  var LLMToolStartEventSchema = taggedEvent("LLMToolStart", {
2963
- tool: S4.String
3360
+ tool: S7.String
2964
3361
  });
2965
3362
  var LLMToolUseEventSchema = taggedEvent("LLMToolUse", {
2966
- tool: S4.String,
2967
- input: S4.Unknown
3363
+ tool: S7.String,
3364
+ input: S7.Unknown
2968
3365
  });
2969
3366
  var LLMToolEndEventSchema = taggedEvent("LLMToolEnd", {
2970
- tool: S4.String
3367
+ tool: S7.String
2971
3368
  });
2972
3369
  var TasksDefinedEventSchema = taggedFromData(
2973
3370
  "TasksDefined",
@@ -2984,17 +3381,17 @@ var CriteriaDefinedEventSchema = taggedFromData(
2984
3381
  var PhaseStartedEventSchema = taggedFromData(
2985
3382
  "PhaseStarted",
2986
3383
  PhaseIdDataSchema,
2987
- { timestamp: S4.Number }
3384
+ { timestamp: S7.Number }
2988
3385
  );
2989
3386
  var PhaseCompletedEventSchema = taggedFromData(
2990
3387
  "PhaseCompleted",
2991
3388
  PhaseIdDataSchema,
2992
- { timestamp: S4.Number }
3389
+ { timestamp: S7.Number }
2993
3390
  );
2994
3391
  var PhaseFailedEventSchema = taggedFromData(
2995
3392
  "PhaseFailed",
2996
3393
  PhaseFailedDataSchema,
2997
- { timestamp: S4.Number }
3394
+ { timestamp: S7.Number }
2998
3395
  );
2999
3396
  var CriterionPassedEventSchema = taggedFromData(
3000
3397
  "CriterionPassed",
@@ -3004,9 +3401,9 @@ var CriterionFailedEventSchema = taggedFromData(
3004
3401
  "CriterionFailed",
3005
3402
  CriterionFailedDataSchema
3006
3403
  );
3007
- var CheckPassedEventSchema = S4.TaggedStruct("CheckPassed", {});
3404
+ var CheckPassedEventSchema = S7.TaggedStruct("CheckPassed", {});
3008
3405
  var CheckFailedEventSchema = taggedEvent("CheckFailed", {
3009
- failedCriteria: S4.Array(S4.String)
3406
+ failedCriteria: S7.Array(S7.String)
3010
3407
  });
3011
3408
  var ReviewCompleteEventSchema = taggedFromData(
3012
3409
  "ReviewComplete",
@@ -3015,7 +3412,7 @@ var ReviewCompleteEventSchema = taggedFromData(
3015
3412
  var TaskCompletedEventSchema = taggedFromData(
3016
3413
  "TaskCompleted",
3017
3414
  TaskCompleteDataSchema,
3018
- { timestamp: S4.Number }
3415
+ { timestamp: S7.Number }
3019
3416
  );
3020
3417
  var PlanCreatedEventSchema = taggedEvent("PlanCreated", {
3021
3418
  plan: PlanSchema
@@ -3024,43 +3421,52 @@ var PlanUpdatedEventSchema = taggedEvent("PlanUpdated", {
3024
3421
  plan: PlanSchema
3025
3422
  });
3026
3423
  var PlanUpdateFailedEventSchema = taggedEvent("PlanUpdateFailed", {
3027
- operation: S4.Literal("create", "update"),
3028
- error: S4.String,
3029
- planId: S4.optional(S4.String)
3424
+ operation: S7.Literal("create", "update"),
3425
+ error: S7.String,
3426
+ planId: S7.optional(S7.String)
3030
3427
  });
3031
3428
  var LearningRecordedEventSchema = taggedEvent("LearningRecorded", {
3032
- iteration: S4.Number,
3033
- content: S4.String,
3034
- category: S4.optional(S4.Literal("success", "failure", "optimization")),
3035
- timestamp: S4.Number
3429
+ iteration: S7.Number,
3430
+ content: S7.String,
3431
+ category: S7.optional(S7.Literal("success", "failure", "optimization")),
3432
+ timestamp: S7.Number
3036
3433
  });
3037
3434
  var GuardrailAddedEventSchema = taggedEvent("GuardrailAdded", {
3038
- id: S4.String,
3039
- iteration: S4.Number,
3040
- pattern: S4.String,
3041
- sign: S4.String,
3042
- avoidance: S4.String,
3043
- severity: S4.Literal("warning", "critical"),
3044
- timestamp: S4.Number
3435
+ id: S7.String,
3436
+ iteration: S7.Number,
3437
+ pattern: S7.String,
3438
+ sign: S7.String,
3439
+ avoidance: S7.String,
3440
+ severity: S7.Literal("warning", "critical"),
3441
+ timestamp: S7.Number
3045
3442
  });
3046
3443
  var ProgressUpdatedEventSchema = taggedEvent("ProgressUpdated", {
3047
- sessionId: S4.String,
3048
- iteration: S4.Number,
3049
- taskId: S4.String,
3050
- action: S4.Literal("started", "completed", "failed", "learning"),
3051
- timestamp: S4.Number
3444
+ sessionId: S7.String,
3445
+ iteration: S7.Number,
3446
+ taskId: S7.String,
3447
+ action: S7.Literal("started", "completed", "failed", "learning"),
3448
+ timestamp: S7.Number
3052
3449
  });
3053
3450
  var WorktreeCreatedEventSchema = taggedEvent("WorktreeCreated", {
3054
- sessionId: S4.String,
3055
- worktreePath: S4.String,
3056
- branchName: S4.String,
3057
- timestamp: S4.Number
3451
+ sessionId: S7.String,
3452
+ worktreePath: S7.String,
3453
+ branchName: S7.String,
3454
+ timestamp: S7.Number
3058
3455
  });
3059
3456
  var WorktreeRemovedEventSchema = taggedEvent("WorktreeRemoved", {
3060
- sessionId: S4.String,
3061
- timestamp: S4.Number
3457
+ sessionId: S7.String,
3458
+ timestamp: S7.Number
3062
3459
  });
3063
- var DomainEventSchema = S4.Union(
3460
+ var SessionNameGeneratedEventSchema = taggedEvent(
3461
+ "SessionNameGenerated",
3462
+ {
3463
+ sessionId: S7.String,
3464
+ /** Task-based descriptive name (kebab-case slug, e.g., "add-dark-mode-toggle") */
3465
+ displayName: S7.String,
3466
+ timestamp: S7.Number
3467
+ }
3468
+ );
3469
+ var DomainEventSchema = S7.Union(
3064
3470
  LoopStartedEventSchema,
3065
3471
  LoopCompletedEventSchema,
3066
3472
  LoopFailedEventSchema,
@@ -3091,7 +3497,8 @@ var DomainEventSchema = S4.Union(
3091
3497
  GuardrailAddedEventSchema,
3092
3498
  ProgressUpdatedEventSchema,
3093
3499
  WorktreeCreatedEventSchema,
3094
- WorktreeRemovedEventSchema
3500
+ WorktreeRemovedEventSchema,
3501
+ SessionNameGeneratedEventSchema
3095
3502
  );
3096
3503
  var DomainEventUtils = {
3097
3504
  isLLMEvent: (e) => e._tag.startsWith("LLM"),
@@ -3103,132 +3510,149 @@ var DomainEventUtils = {
3103
3510
 
3104
3511
  // src/domain/schemas/guardrails.ts
3105
3512
  init_esm_shims();
3106
- import { Schema as S5 } from "effect";
3107
- var GuardrailSeveritySchema = S5.Literal("warning", "critical");
3108
- var GuardrailSchema = S5.Struct({
3109
- id: S5.String,
3110
- createdAt: S5.String,
3111
- iteration: S5.Number,
3112
- pattern: S5.String,
3113
- sign: S5.String,
3114
- avoidance: S5.String,
3513
+ import { Schema as S8 } from "effect";
3514
+ var GuardrailSeveritySchema = S8.Literal("warning", "critical");
3515
+ var GuardrailSchema = S8.Struct({
3516
+ id: S8.String,
3517
+ createdAt: S8.String,
3518
+ iteration: S8.Number,
3519
+ pattern: S8.String,
3520
+ sign: S8.String,
3521
+ avoidance: S8.String,
3115
3522
  severity: GuardrailSeveritySchema
3116
3523
  });
3117
- var GuardrailsFileSchema = S5.Struct({
3118
- sessionId: S5.String,
3119
- createdAt: S5.String,
3120
- guardrails: S5.Array(GuardrailSchema)
3524
+ var GuardrailsFileSchema = S8.Struct({
3525
+ sessionId: S8.String,
3526
+ createdAt: S8.String,
3527
+ guardrails: S8.Array(GuardrailSchema)
3121
3528
  });
3122
- var decodeGuardrail = S5.decodeUnknown(GuardrailSchema);
3123
- var decodeGuardrailsFile = S5.decodeUnknown(GuardrailsFileSchema);
3529
+ var decodeGuardrail = S8.decodeUnknown(GuardrailSchema);
3530
+ var decodeGuardrailsFile = S8.decodeUnknown(GuardrailsFileSchema);
3124
3531
 
3125
3532
  // src/domain/schemas/llm.ts
3126
3533
  init_esm_shims();
3127
- import { Schema as S6 } from "effect";
3128
- var TextEventSchema = S6.TaggedStruct("Text", {
3129
- text: S6.String
3534
+ import { Either as Either3, Schema as S9 } from "effect";
3535
+ var TextEventSchema = S9.TaggedStruct("Text", {
3536
+ text: S9.String
3537
+ });
3538
+ var ToolStartEventSchema = S9.TaggedStruct("ToolStart", {
3539
+ tool: S9.String
3130
3540
  });
3131
- var ToolStartEventSchema = S6.TaggedStruct("ToolStart", {
3132
- tool: S6.String
3541
+ var ToolUseEventSchema = S9.TaggedStruct("ToolUse", {
3542
+ tool: S9.String,
3543
+ input: S9.Unknown
3133
3544
  });
3134
- var ToolUseEventSchema = S6.TaggedStruct("ToolUse", {
3135
- tool: S6.String,
3136
- input: S6.Unknown
3545
+ var ValidatedToolUseEventSchema = S9.TaggedStruct("ToolUse", {
3546
+ tool: S9.String,
3547
+ input: AnyToolInputSchema
3137
3548
  });
3138
- var ToolEndEventSchema = S6.TaggedStruct("ToolEnd", {
3139
- tool: S6.String
3549
+ var ToolEndEventSchema = S9.TaggedStruct("ToolEnd", {
3550
+ tool: S9.String
3140
3551
  });
3141
- var DoneEventSchema = S6.TaggedStruct("Done", {
3142
- output: S6.String
3552
+ var DoneEventSchema = S9.TaggedStruct("Done", {
3553
+ output: S9.String
3143
3554
  });
3144
- var LLMEventSchema = S6.Union(
3555
+ var LLMEventSchema = S9.Union(
3145
3556
  TextEventSchema,
3146
3557
  ToolStartEventSchema,
3147
3558
  ToolUseEventSchema,
3148
3559
  ToolEndEventSchema,
3149
3560
  DoneEventSchema
3150
3561
  );
3151
- var decodeLLMEvent = S6.decodeUnknown(LLMEventSchema);
3562
+ var decodeLLMEvent = S9.decodeUnknown(LLMEventSchema);
3563
+ function validateToolUseEvent(event) {
3564
+ const validatedInput = validateToolInput(event.tool, event.input);
3565
+ return Either3.map(validatedInput, (input) => ({
3566
+ ...event,
3567
+ input
3568
+ }));
3569
+ }
3152
3570
 
3153
3571
  // src/domain/schemas/logger.ts
3154
3572
  init_esm_shims();
3155
- import { Schema as S7 } from "effect";
3156
- var LogLevelSchema = S7.Literal("debug", "info", "warn", "error");
3157
- var LogEntrySchema = S7.Struct({
3573
+ import { Schema as S10 } from "effect";
3574
+ var LogLevelSchema = S10.Literal("debug", "info", "warn", "error");
3575
+ var LogEntrySchema = S10.Struct({
3158
3576
  level: LogLevelSchema,
3159
- message: S7.String,
3160
- timestamp: S7.String,
3161
- context: S7.optional(S7.Record({ key: S7.String, value: S7.Unknown }))
3577
+ message: S10.String,
3578
+ timestamp: S10.String,
3579
+ context: S10.optional(S10.Record({ key: S10.String, value: S10.Unknown }))
3162
3580
  });
3163
- var ConsoleLoggerConfigSchema = S7.Struct({
3164
- level: S7.optional(LogLevelSchema),
3165
- colors: S7.optional(S7.Boolean)
3581
+ var ConsoleLoggerConfigSchema = S10.Struct({
3582
+ level: S10.optional(LogLevelSchema),
3583
+ colors: S10.optional(S10.Boolean)
3166
3584
  });
3167
- var FileLoggerConfigSchema = S7.Struct({
3168
- path: S7.optional(S7.String),
3169
- level: S7.optional(LogLevelSchema)
3585
+ var FileLoggerConfigSchema = S10.Struct({
3586
+ path: S10.optional(S10.String),
3587
+ level: S10.optional(LogLevelSchema)
3170
3588
  });
3171
3589
 
3172
3590
  // src/domain/schemas/program.ts
3173
3591
  init_esm_shims();
3174
- import { Schema as S8 } from "effect";
3175
- var ConsumerTypeSchema = S8.Literal("tui", "headless", "none");
3176
- var RunOptionsDataSchema = S8.Struct({
3592
+ import { Schema as S11 } from "effect";
3593
+ var ConsumerTypeSchema = S11.Literal("tui", "headless", "none");
3594
+ var RunOptionsDataSchema = S11.Struct({
3177
3595
  config: LoopConfigSchema,
3178
- consumer: S8.optional(ConsumerTypeSchema)
3596
+ consumer: S11.optional(ConsumerTypeSchema)
3179
3597
  });
3180
3598
 
3181
3599
  // src/domain/schemas/progress.ts
3182
3600
  init_esm_shims();
3183
- import { Schema as S9 } from "effect";
3184
- var ProgressActionSchema = S9.Literal(
3601
+ import { Schema as S12 } from "effect";
3602
+ var ProgressActionSchema = S12.Literal(
3185
3603
  "started",
3186
3604
  "completed",
3187
3605
  "failed",
3188
3606
  "learning"
3189
3607
  );
3190
- var ProgressEntrySchema = S9.Struct({
3191
- iteration: S9.Number,
3192
- timestamp: S9.String,
3193
- taskId: S9.String,
3608
+ var ProgressEntrySchema = S12.Struct({
3609
+ iteration: S12.Number,
3610
+ timestamp: S12.String,
3611
+ taskId: S12.String,
3194
3612
  action: ProgressActionSchema,
3195
- summary: S9.String,
3196
- learnings: S9.optional(S9.Array(S9.String)),
3197
- filesModified: S9.optional(S9.Array(S9.String))
3613
+ summary: S12.String,
3614
+ learnings: S12.optional(S12.Array(S12.String)),
3615
+ filesModified: S12.optional(S12.Array(S12.String))
3198
3616
  });
3199
- var ProgressFileSchema = S9.Struct({
3200
- sessionId: S9.String,
3201
- createdAt: S9.String,
3202
- entries: S9.Array(ProgressEntrySchema)
3617
+ var ProgressFileSchema = S12.Struct({
3618
+ sessionId: S12.String,
3619
+ createdAt: S12.String,
3620
+ entries: S12.Array(ProgressEntrySchema)
3203
3621
  });
3204
- var decodeProgressEntry = S9.decodeUnknown(ProgressEntrySchema);
3205
- var decodeProgressFile = S9.decodeUnknown(ProgressFileSchema);
3622
+ var decodeProgressEntry = S12.decodeUnknown(ProgressEntrySchema);
3623
+ var decodeProgressFile = S12.decodeUnknown(ProgressFileSchema);
3206
3624
 
3207
3625
  // src/domain/schemas/session.ts
3208
3626
  init_esm_shims();
3209
- import { Schema as S10 } from "effect";
3210
- var SessionStatusSchema = S10.Literal(
3627
+ import { Schema as S13 } from "effect";
3628
+ var SessionStatusSchema = S13.Literal(
3211
3629
  "active",
3212
3630
  "completed",
3213
3631
  "failed",
3214
3632
  "paused"
3215
3633
  );
3216
- var SessionSchema = S10.Struct({
3217
- id: S10.String,
3218
- createdAt: S10.String,
3634
+ var SessionSchema = S13.Struct({
3635
+ id: S13.String,
3636
+ createdAt: S13.String,
3219
3637
  status: SessionStatusSchema,
3220
- originalTask: S10.String,
3221
- completedTasks: S10.Array(S10.String),
3222
- currentTaskId: S10.optional(S10.String),
3223
- worktreePath: S10.optional(S10.String),
3224
- branchName: S10.optional(S10.String)
3638
+ originalTask: S13.String,
3639
+ completedTasks: S13.Array(S13.String),
3640
+ currentTaskId: S13.optional(S13.String),
3641
+ worktreePath: S13.optional(S13.String),
3642
+ branchName: S13.optional(S13.String),
3643
+ /** Task-based descriptive name (kebab-case slug, e.g., "add-dark-mode-toggle") */
3644
+ displayName: S13.optional(S13.String)
3225
3645
  });
3226
- var decodeSession = S10.decodeUnknown(SessionSchema);
3646
+ var decodeSession = S13.decodeUnknown(SessionSchema);
3647
+
3648
+ // src/domain/schemas/signal-factories.ts
3649
+ init_esm_shims();
3650
+ import { Schema as S15 } from "effect";
3227
3651
 
3228
3652
  // src/domain/schemas/signals.ts
3229
3653
  init_esm_shims();
3230
- import { Schema as S11 } from "effect";
3231
- var taggedFromData2 = (tag, dataSchema) => S11.TaggedStruct(tag, dataSchema.fields);
3654
+ import { Schema as S14 } from "effect";
3655
+ var taggedFromData2 = (tag, dataSchema) => S14.TaggedStruct(tag, dataSchema.fields);
3232
3656
  var TasksDefinedSignalSchema = taggedFromData2(
3233
3657
  "TasksDefined",
3234
3658
  TasksDefinedDataSchema
@@ -3261,8 +3685,8 @@ var CriterionFailedSignalSchema = taggedFromData2(
3261
3685
  "CriterionFailed",
3262
3686
  CriterionFailedDataSchema
3263
3687
  );
3264
- var CheckPassedSignalSchema = S11.TaggedStruct("CheckPassed", {});
3265
- var CheckFailedSignalSchema = S11.TaggedStruct("CheckFailed", {});
3688
+ var CheckPassedSignalSchema = S14.TaggedStruct("CheckPassed", {});
3689
+ var CheckFailedSignalSchema = S14.TaggedStruct("CheckFailed", {});
3266
3690
  var ReviewCompleteSignalSchema = taggedFromData2(
3267
3691
  "ReviewComplete",
3268
3692
  ReviewCompleteDataSchema
@@ -3271,23 +3695,30 @@ var TaskCompleteSignalSchema = taggedFromData2(
3271
3695
  "TaskComplete",
3272
3696
  TaskCompleteSignalDataSchema
3273
3697
  );
3274
- var LoopCompleteSignalSchema = S11.TaggedStruct("LoopComplete", {});
3275
- var LearningCategorySchema = S11.Literal(
3698
+ var LoopCompleteSignalSchema = S14.TaggedStruct("LoopComplete", {});
3699
+ var SessionNameDefinedSignalSchema = S14.TaggedStruct(
3700
+ "SessionNameDefined",
3701
+ {
3702
+ /** Kebab-case slug, e.g., "add-dark-mode-toggle" */
3703
+ name: S14.String
3704
+ }
3705
+ );
3706
+ var LearningCategorySchema = S14.Literal(
3276
3707
  "success",
3277
3708
  "failure",
3278
3709
  "optimization"
3279
3710
  );
3280
- var LearningSignalSchema = S11.TaggedStruct("Learning", {
3281
- content: S11.String,
3282
- category: S11.optional(LearningCategorySchema)
3711
+ var LearningSignalSchema = S14.TaggedStruct("Learning", {
3712
+ content: S14.String,
3713
+ category: S14.optional(LearningCategorySchema)
3283
3714
  });
3284
- var GuardrailSignalSchema = S11.TaggedStruct("Guardrail", {
3285
- pattern: S11.String,
3286
- sign: S11.String,
3287
- avoidance: S11.String,
3288
- severity: S11.Literal("warning", "critical")
3715
+ var GuardrailSignalSchema = S14.TaggedStruct("Guardrail", {
3716
+ pattern: S14.String,
3717
+ sign: S14.String,
3718
+ avoidance: S14.String,
3719
+ severity: S14.Literal("warning", "critical")
3289
3720
  });
3290
- var SignalSchema = S11.Union(
3721
+ var SignalSchema = S14.Union(
3291
3722
  TasksDefinedSignalSchema,
3292
3723
  PhasesDefinedSignalSchema,
3293
3724
  CriteriaDefinedSignalSchema,
@@ -3302,26 +3733,133 @@ var SignalSchema = S11.Union(
3302
3733
  TaskCompleteSignalSchema,
3303
3734
  LoopCompleteSignalSchema,
3304
3735
  LearningSignalSchema,
3305
- GuardrailSignalSchema
3736
+ GuardrailSignalSchema,
3737
+ SessionNameDefinedSignalSchema
3306
3738
  );
3307
- var decodeSignal = S11.decodeUnknown(SignalSchema);
3308
- var decodeSignalSync = S11.decodeUnknownSync(SignalSchema);
3739
+ var decodeSignal = S14.decodeUnknown(SignalSchema);
3740
+ var decodeSignalSync = S14.decodeUnknownSync(SignalSchema);
3741
+
3742
+ // src/domain/schemas/signal-factories.ts
3743
+ function createTasksDefinedSignal(input) {
3744
+ return S15.decodeUnknownEither(TasksDefinedSignalSchema)({
3745
+ _tag: "TasksDefined",
3746
+ tasks: input.tasks
3747
+ });
3748
+ }
3749
+ function createPhasesDefinedSignal(input) {
3750
+ return S15.decodeUnknownEither(PhasesDefinedSignalSchema)({
3751
+ _tag: "PhasesDefined",
3752
+ taskId: input.taskId,
3753
+ phases: input.phases
3754
+ });
3755
+ }
3756
+ function createCriteriaDefinedSignal(input) {
3757
+ return S15.decodeUnknownEither(CriteriaDefinedSignalSchema)({
3758
+ _tag: "CriteriaDefined",
3759
+ taskId: input.taskId,
3760
+ criteria: input.criteria
3761
+ });
3762
+ }
3763
+ function createPhaseStartedSignal(input) {
3764
+ return S15.decodeUnknownEither(PhaseStartedSignalSchema)({
3765
+ _tag: "PhaseStarted",
3766
+ phaseId: input.phaseId
3767
+ });
3768
+ }
3769
+ function createPhaseCompletedSignal(input) {
3770
+ return S15.decodeUnknownEither(PhaseCompletedSignalSchema)({
3771
+ _tag: "PhaseCompleted",
3772
+ phaseId: input.phaseId
3773
+ });
3774
+ }
3775
+ function createPhaseFailedSignal(input) {
3776
+ return S15.decodeUnknownEither(PhaseFailedSignalSchema)({
3777
+ _tag: "PhaseFailed",
3778
+ phaseId: input.phaseId,
3779
+ reason: input.reason
3780
+ });
3781
+ }
3782
+ function createCriterionPassedSignal(input) {
3783
+ return S15.decodeUnknownEither(CriterionPassedSignalSchema)({
3784
+ _tag: "CriterionPassed",
3785
+ criterionId: input.criterionId
3786
+ });
3787
+ }
3788
+ function createCriterionFailedSignal(input) {
3789
+ return S15.decodeUnknownEither(CriterionFailedSignalSchema)({
3790
+ _tag: "CriterionFailed",
3791
+ criterionId: input.criterionId,
3792
+ reason: input.reason
3793
+ });
3794
+ }
3795
+ function createCheckPassedSignal(_input) {
3796
+ return S15.decodeUnknownEither(CheckPassedSignalSchema)({
3797
+ _tag: "CheckPassed"
3798
+ });
3799
+ }
3800
+ function createCheckFailedSignal(_input) {
3801
+ return S15.decodeUnknownEither(CheckFailedSignalSchema)({
3802
+ _tag: "CheckFailed"
3803
+ });
3804
+ }
3805
+ function createReviewCompleteSignal(input) {
3806
+ return S15.decodeUnknownEither(ReviewCompleteSignalSchema)({
3807
+ _tag: "ReviewComplete",
3808
+ changesMade: input.changesMade
3809
+ });
3810
+ }
3811
+ function createTaskCompleteSignal(input) {
3812
+ return S15.decodeUnknownEither(TaskCompleteSignalSchema)({
3813
+ _tag: "TaskComplete",
3814
+ taskId: input.taskId,
3815
+ summary: input.summary,
3816
+ filesModified: input.filesModified,
3817
+ filesCreated: input.filesCreated
3818
+ });
3819
+ }
3820
+ function createLoopCompleteSignal(_input) {
3821
+ return S15.decodeUnknownEither(LoopCompleteSignalSchema)({
3822
+ _tag: "LoopComplete"
3823
+ });
3824
+ }
3825
+ function createLearningSignal(input) {
3826
+ return S15.decodeUnknownEither(LearningSignalSchema)({
3827
+ _tag: "Learning",
3828
+ content: input.content,
3829
+ category: input.category
3830
+ });
3831
+ }
3832
+ function createGuardrailSignal(input) {
3833
+ return S15.decodeUnknownEither(GuardrailSignalSchema)({
3834
+ _tag: "Guardrail",
3835
+ pattern: input.pattern,
3836
+ sign: input.sign,
3837
+ avoidance: input.avoidance,
3838
+ severity: input.severity
3839
+ });
3840
+ }
3841
+ function createSessionNameDefinedSignal(input) {
3842
+ return S15.decodeUnknownEither(SessionNameDefinedSignalSchema)({
3843
+ _tag: "SessionNameDefined",
3844
+ name: input.name
3845
+ });
3846
+ }
3309
3847
 
3310
3848
  // src/domain/schemas/task-generation.ts
3311
3849
  init_esm_shims();
3312
- import { Schema as S12 } from "effect";
3313
- var GeneratedTaskStatusSchema = S12.Literal(
3850
+ import { Schema as S16 } from "effect";
3851
+ var GeneratedTaskStatusSchema = S16.Literal(
3314
3852
  "pending",
3315
3853
  "in_progress",
3316
3854
  "done",
3317
3855
  "failed"
3318
3856
  );
3319
- var GeneratedTaskSchema = S12.Struct({
3320
- id: S12.String,
3321
- title: S12.String,
3857
+ var GeneratedTaskSchema = S16.Struct({
3858
+ id: S16.String,
3859
+ title: S16.String,
3322
3860
  status: GeneratedTaskStatusSchema
3323
3861
  });
3324
- var GeneratedTaskListSchema = S12.Array(GeneratedTaskSchema);
3862
+ var GeneratedTaskListSchema = S16.Array(GeneratedTaskSchema);
3325
3863
  var STATUS_ICONS = {
3326
3864
  done: "[x]",
3327
3865
  in_progress: "[~]",
@@ -3380,15 +3918,15 @@ function parseTasksMd(content) {
3380
3918
 
3381
3919
  // src/domain/schemas/tui.ts
3382
3920
  init_esm_shims();
3383
- import { Schema as S13 } from "effect";
3384
- var ViewModeSchema = S13.Literal("logs", "tasks", "detail");
3385
- var LoopStatusSchema = S13.Literal(
3921
+ import { Schema as S17 } from "effect";
3922
+ var ViewModeSchema = S17.Literal("logs", "tasks", "detail");
3923
+ var LoopStatusSchema = S17.Literal(
3386
3924
  "idle",
3387
3925
  "running",
3388
3926
  "complete",
3389
3927
  "error"
3390
3928
  );
3391
- var ExecutionModeSchema = S13.Literal(
3929
+ var ExecutionModeSchema = S17.Literal(
3392
3930
  "idle",
3393
3931
  "discovery",
3394
3932
  "breakdown",
@@ -3398,73 +3936,73 @@ var ExecutionModeSchema = S13.Literal(
3398
3936
  "verifying",
3399
3937
  "reviewing"
3400
3938
  );
3401
- var TUIPhaseStatusSchema = S13.Literal(
3939
+ var TUIPhaseStatusSchema = S17.Literal(
3402
3940
  "pending",
3403
3941
  "in_progress",
3404
3942
  "done",
3405
3943
  "failed"
3406
3944
  );
3407
- var TUICriterionStatusSchema = S13.Literal(
3945
+ var TUICriterionStatusSchema = S17.Literal(
3408
3946
  "pending",
3409
3947
  "passed",
3410
3948
  "failed"
3411
3949
  );
3412
- var TUITaskStatusSchema = S13.Literal(
3950
+ var TUITaskStatusSchema = S17.Literal(
3413
3951
  "pending",
3414
3952
  "in_progress",
3415
3953
  "done",
3416
3954
  "failed"
3417
3955
  );
3418
- var TUIPhaseSchema = S13.Struct({
3419
- id: S13.String,
3420
- description: S13.String,
3956
+ var TUIPhaseSchema = S17.Struct({
3957
+ id: S17.String,
3958
+ description: S17.String,
3421
3959
  status: TUIPhaseStatusSchema,
3422
- startedAt: S13.optional(S13.Number),
3423
- completedAt: S13.optional(S13.Number)
3960
+ startedAt: S17.optional(S17.Number),
3961
+ completedAt: S17.optional(S17.Number)
3424
3962
  });
3425
- var TUICriterionSchema = S13.Struct({
3426
- id: S13.String,
3427
- description: S13.String,
3963
+ var TUICriterionSchema = S17.Struct({
3964
+ id: S17.String,
3965
+ description: S17.String,
3428
3966
  status: TUICriterionStatusSchema,
3429
- failureReason: S13.optional(S13.String)
3967
+ failureReason: S17.optional(S17.String)
3430
3968
  });
3431
- var TUITaskSchema = S13.Struct({
3432
- id: S13.String,
3433
- title: S13.String,
3969
+ var TUITaskSchema = S17.Struct({
3970
+ id: S17.String,
3971
+ title: S17.String,
3434
3972
  status: TUITaskStatusSchema,
3435
- phases: S13.Array(TUIPhaseSchema),
3436
- criteria: S13.Array(TUICriterionSchema),
3437
- startedAt: S13.optional(S13.Number),
3438
- completedAt: S13.optional(S13.Number)
3973
+ phases: S17.Array(TUIPhaseSchema),
3974
+ criteria: S17.Array(TUICriterionSchema),
3975
+ startedAt: S17.optional(S17.Number),
3976
+ completedAt: S17.optional(S17.Number)
3439
3977
  });
3440
- var TUIStateSchema = S13.Struct({
3978
+ var TUIStateSchema = S17.Struct({
3441
3979
  // Loop info
3442
- task: S13.String,
3443
- iteration: S13.Number,
3444
- maxIterations: S13.Number,
3980
+ task: S17.String,
3981
+ iteration: S17.Number,
3982
+ maxIterations: S17.Number,
3445
3983
  status: LoopStatusSchema,
3446
- startTime: S13.Number,
3984
+ startTime: S17.Number,
3447
3985
  // Discovery phase
3448
- discoveryInProgress: S13.Boolean,
3449
- discoveryCompleted: S13.Boolean,
3986
+ discoveryInProgress: S17.Boolean,
3987
+ discoveryCompleted: S17.Boolean,
3450
3988
  // Current activity
3451
3989
  executionMode: ExecutionModeSchema,
3452
- currentTool: S13.optional(S13.String),
3453
- currentTaskId: S13.optional(S13.String),
3990
+ currentTool: S17.optional(S17.String),
3991
+ currentTaskId: S17.optional(S17.String),
3454
3992
  // Output
3455
- outputLines: S13.Array(S13.String),
3456
- partialLine: S13.String,
3993
+ outputLines: S17.Array(S17.String),
3994
+ partialLine: S17.String,
3457
3995
  // Tasks
3458
- tasks: S13.Array(TUITaskSchema),
3996
+ tasks: S17.Array(TUITaskSchema),
3459
3997
  // Navigation
3460
3998
  viewMode: ViewModeSchema,
3461
- selectedTaskIndex: S13.Number,
3462
- scrollOffset: S13.Number,
3463
- userScrolled: S13.Boolean,
3999
+ selectedTaskIndex: S17.Number,
4000
+ scrollOffset: S17.Number,
4001
+ userScrolled: S17.Boolean,
3464
4002
  // Git
3465
- gitBranch: S13.optional(S13.String),
3466
- gitPushed: S13.Boolean,
3467
- prUrl: S13.optional(S13.String)
4003
+ gitBranch: S17.optional(S17.String),
4004
+ gitPushed: S17.Boolean,
4005
+ prUrl: S17.optional(S17.String)
3468
4006
  });
3469
4007
 
3470
4008
  // src/services/guardrails-store.ts
@@ -3670,7 +4208,7 @@ var MemoryGuardrails = {
3670
4208
 
3671
4209
  // src/layers/llm/mock.ts
3672
4210
  init_esm_shims();
3673
- import { Effect as Effect8, Layer as Layer5, Schema as S14, Stream as Stream4 } from "effect";
4211
+ import { Effect as Effect8, Layer as Layer5, Schema as S18, Stream as Stream4 } from "effect";
3674
4212
 
3675
4213
  // src/services/llm.ts
3676
4214
  init_esm_shims();
@@ -3679,9 +4217,9 @@ var LLM = class extends Context3.Tag("@ferix/LLM")() {
3679
4217
  };
3680
4218
 
3681
4219
  // src/layers/llm/mock.ts
3682
- var MockLLMConfigSchema = S14.Struct({
3683
- events: S14.Array(LLMEventSchema),
3684
- delayMs: S14.optional(S14.Number)
4220
+ var MockLLMConfigSchema = S18.Struct({
4221
+ events: S18.Array(LLMEventSchema),
4222
+ delayMs: S18.optional(S18.Number)
3685
4223
  });
3686
4224
  function createMockLLM(config) {
3687
4225
  return {
@@ -3722,7 +4260,23 @@ import { Effect as Effect11 } from "effect";
3722
4260
 
3723
4261
  // src/layers/llm/types.ts
3724
4262
  init_esm_shims();
3725
- var PROVIDER_CONFIGS = {
4263
+ import { Schema as S19 } from "effect";
4264
+ var PermissionModeSchema = S19.Literal("acceptEdits", "yolo", "prompt");
4265
+ var ProviderConfigSchema = S19.Struct({
4266
+ /** Provider name */
4267
+ name: ProviderNameSchema,
4268
+ /** CLI command to execute */
4269
+ cliCommand: S19.String,
4270
+ /** Default arguments for the CLI */
4271
+ args: S19.Array(S19.String),
4272
+ /** Environment variables to pass */
4273
+ env: S19.optional(S19.Record({ key: S19.String, value: S19.String })),
4274
+ /** Permission mode for the CLI */
4275
+ permissions: S19.optional(PermissionModeSchema),
4276
+ /** URL for installation instructions */
4277
+ installUrl: S19.String
4278
+ });
4279
+ var RAW_PROVIDER_CONFIGS = {
3726
4280
  claude: {
3727
4281
  name: "claude",
3728
4282
  cliCommand: "claude",
@@ -3751,6 +4305,17 @@ var PROVIDER_CONFIGS = {
3751
4305
  installUrl: "https://opencode.ai/docs/"
3752
4306
  }
3753
4307
  };
4308
+ var ProviderConfigsSchema = S19.Record({
4309
+ key: ProviderNameSchema,
4310
+ value: ProviderConfigSchema
4311
+ });
4312
+ var validateProviderConfigs = () => {
4313
+ const decoded = S19.decodeUnknownSync(ProviderConfigsSchema)(
4314
+ RAW_PROVIDER_CONFIGS
4315
+ );
4316
+ return decoded;
4317
+ };
4318
+ var PROVIDER_CONFIGS = validateProviderConfigs();
3754
4319
 
3755
4320
  // src/layers/llm/providers/claude.ts
3756
4321
  init_esm_shims();
@@ -3796,78 +4361,57 @@ init_esm_shims();
3796
4361
 
3797
4362
  // src/layers/llm/providers/parsers/stream-json.ts
3798
4363
  init_esm_shims();
4364
+ import { Either as Either4 } from "effect";
3799
4365
  function parseJsonLine(line) {
3800
4366
  if (!line.startsWith("{")) {
3801
4367
  return null;
3802
4368
  }
3803
- try {
3804
- return JSON.parse(line);
3805
- } catch {
3806
- return null;
3807
- }
3808
- }
3809
- function isTextContent(json) {
3810
- return typeof json === "object" && json !== null && "type" in json && typeof json.type === "string";
3811
- }
3812
- function isToolUse(json) {
3813
- return typeof json === "object" && json !== null && "type" in json && "content_block" in json;
4369
+ return Either4.getOrNull(
4370
+ Either4.try({ try: () => JSON.parse(line), catch: () => null })
4371
+ );
3814
4372
  }
3815
4373
  function extractText(json) {
3816
- if (!isTextContent(json)) {
3817
- return null;
3818
- }
3819
- if (json.type === "content_block_delta") {
3820
- const delta = json;
3821
- if (delta.delta?.type === "text_delta" && delta.delta.text) {
3822
- return delta.delta.text;
3823
- }
4374
+ if (isContentBlockDelta(json) && isTextDelta(json.delta)) {
4375
+ return json.delta.text;
3824
4376
  }
3825
- if (json.type === "assistant" && json.message?.content) {
4377
+ if (isAssistantMessage(json)) {
3826
4378
  for (const block of json.message.content) {
3827
- if (block.type === "text" && block.text) {
4379
+ if (isTextContentBlock(block)) {
3828
4380
  return block.text;
3829
4381
  }
3830
4382
  }
3831
4383
  }
3832
4384
  return null;
3833
4385
  }
3834
- function isToolInputDelta(json) {
3835
- return typeof json === "object" && json !== null && "type" in json && json.type === "content_block_delta" && "delta" in json;
3836
- }
3837
4386
  function extractToolInfo(json) {
3838
- if (typeof json === "object" && json !== null && "type" in json && json.type === "content_block_stop") {
4387
+ if (isContentBlockStop(json)) {
3839
4388
  return {
3840
4389
  type: "end",
3841
4390
  name: "unknown"
3842
4391
  };
3843
4392
  }
3844
- if (!isToolUse(json)) {
3845
- if (isToolInputDelta(json) && json.delta?.type === "input_json_delta" && json.delta.partial_json) {
3846
- return {
3847
- type: "input_delta",
3848
- name: "",
3849
- partialJson: json.delta.partial_json
3850
- };
3851
- }
3852
- return null;
3853
- }
3854
- if (json.type === "content_block_start" && json.content_block?.type === "tool_use") {
4393
+ if (isContentBlockStart(json) && isToolUseContentBlock(json.content_block)) {
3855
4394
  return {
3856
4395
  type: "start",
3857
- name: json.content_block.name || "unknown"
4396
+ name: json.content_block.name
4397
+ };
4398
+ }
4399
+ if (isContentBlockDelta(json) && isInputJsonDelta(json.delta)) {
4400
+ return {
4401
+ type: "input_delta",
4402
+ name: "",
4403
+ partialJson: json.delta.partial_json
3858
4404
  };
3859
4405
  }
3860
4406
  return null;
3861
4407
  }
3862
4408
  function safeParseJson(jsonStr) {
3863
- try {
3864
- return JSON.parse(jsonStr);
3865
- } catch {
3866
- return null;
3867
- }
4409
+ return Either4.getOrNull(
4410
+ Either4.try({ try: () => JSON.parse(jsonStr), catch: () => null })
4411
+ );
3868
4412
  }
3869
4413
  function unwrapStreamEvent(json) {
3870
- if (typeof json === "object" && json !== null && "type" in json && json.type === "stream_event" && "event" in json) {
4414
+ if (isStreamEventEnvelope(json)) {
3871
4415
  return json.event;
3872
4416
  }
3873
4417
  return json;
@@ -4008,50 +4552,26 @@ init_esm_shims();
4008
4552
 
4009
4553
  // src/layers/llm/providers/parsers/opencode.ts
4010
4554
  init_esm_shims();
4555
+ import { Either as Either5 } from "effect";
4011
4556
  function parseJsonLine2(line) {
4012
4557
  if (!line.startsWith("{")) {
4013
4558
  return null;
4014
4559
  }
4015
- try {
4016
- return JSON.parse(line);
4017
- } catch {
4018
- return null;
4019
- }
4020
- }
4021
- function isTextContent2(json) {
4022
- return typeof json === "object" && json !== null && "type" in json && json.type === "text" && "text" in json && typeof json.text === "string";
4560
+ return Either5.getOrNull(
4561
+ Either5.try({ try: () => JSON.parse(line), catch: () => null })
4562
+ );
4023
4563
  }
4024
4564
  function isStepFinish(json) {
4025
- return typeof json === "object" && json !== null && "type" in json && json.type === "step_finish";
4026
- }
4027
- function isToolUse2(json) {
4028
- if (typeof json !== "object" || json === null) {
4029
- return false;
4030
- }
4031
- const obj = json;
4032
- if (obj.type !== "tool_use") {
4033
- return false;
4034
- }
4035
- if (typeof obj.part !== "object" || obj.part === null) {
4036
- return false;
4037
- }
4038
- const part = obj.part;
4039
- if (typeof part.tool !== "string") {
4040
- return false;
4041
- }
4042
- if (typeof part.state !== "object" || part.state === null) {
4043
- return false;
4044
- }
4045
- return true;
4565
+ return isOpenCodeStepFinish(json);
4046
4566
  }
4047
4567
  function extractText2(json) {
4048
- if (isTextContent2(json)) {
4568
+ if (isOpenCodeTextEvent(json)) {
4049
4569
  return json.text;
4050
4570
  }
4051
4571
  return null;
4052
4572
  }
4053
4573
  function extractToolInfo2(json) {
4054
- if (isToolUse2(json)) {
4574
+ if (isOpenCodeToolUseEvent(json)) {
4055
4575
  return {
4056
4576
  type: "complete",
4057
4577
  name: json.part.tool,
@@ -4816,7 +5336,7 @@ init_esm_shims();
4816
5336
 
4817
5337
  // src/layers/signal/specs/check.ts
4818
5338
  init_esm_shims();
4819
- import { Schema as S15 } from "effect";
5339
+ import { Either as Either6 } from "effect";
4820
5340
 
4821
5341
  // src/layers/signal/specs/registry.ts
4822
5342
  init_esm_shims();
@@ -4872,9 +5392,8 @@ var checkPassedSpec = {
4872
5392
  schema: CheckPassedSignalSchema,
4873
5393
  parse: (text) => {
4874
5394
  if (CHECK_PASSED.test(text)) {
4875
- const raw = { _tag: "CheckPassed" };
4876
- const result = S15.decodeUnknownEither(CheckPassedSignalSchema)(raw);
4877
- if (result._tag === "Right") {
5395
+ const result = createCheckPassedSignal({});
5396
+ if (Either6.isRight(result)) {
4878
5397
  return [result.right];
4879
5398
  }
4880
5399
  }
@@ -4888,9 +5407,8 @@ var checkFailedSpec = {
4888
5407
  schema: CheckFailedSignalSchema,
4889
5408
  parse: (text) => {
4890
5409
  if (CHECK_FAILED.test(text)) {
4891
- const raw = { _tag: "CheckFailed" };
4892
- const result = S15.decodeUnknownEither(CheckFailedSignalSchema)(raw);
4893
- if (result._tag === "Right") {
5410
+ const result = createCheckFailedSignal({});
5411
+ if (Either6.isRight(result)) {
4894
5412
  return [result.right];
4895
5413
  }
4896
5414
  }
@@ -4903,7 +5421,7 @@ signalSpecRegistry.register(checkFailedSpec);
4903
5421
 
4904
5422
  // src/layers/signal/specs/criteria.ts
4905
5423
  init_esm_shims();
4906
- import { Schema as S16 } from "effect";
5424
+ import { Either as Either7 } from "effect";
4907
5425
  var CRITERIA_BLOCK = /<ferix:criteria task="(\d+)">([\s\S]*?)<\/ferix:criteria>/g;
4908
5426
  var CRITERION = /<criterion id="([^"]+)">([^<]+)<\/criterion>/g;
4909
5427
  var CRITERION_PASSED = /<ferix:criterion-passed id="([\d.c]+)"\/>/g;
@@ -4929,13 +5447,11 @@ var criteriaDefinedSpec = {
4929
5447
  }
4930
5448
  }
4931
5449
  if (criteria.length > 0) {
4932
- const raw = {
4933
- _tag: "CriteriaDefined",
5450
+ const result = createCriteriaDefinedSignal({
4934
5451
  taskId: match[1],
4935
5452
  criteria
4936
- };
4937
- const result = S16.decodeUnknownEither(CriteriaDefinedSignalSchema)(raw);
4938
- if (result._tag === "Right") {
5453
+ });
5454
+ if (Either7.isRight(result)) {
4939
5455
  signals.push(result.right);
4940
5456
  }
4941
5457
  }
@@ -4952,9 +5468,8 @@ var criterionPassedSpec = {
4952
5468
  const signals = [];
4953
5469
  for (const m of text.matchAll(resetRegex(CRITERION_PASSED))) {
4954
5470
  if (m[1]) {
4955
- const raw = { _tag: "CriterionPassed", criterionId: m[1] };
4956
- const result = S16.decodeUnknownEither(CriterionPassedSignalSchema)(raw);
4957
- if (result._tag === "Right") {
5471
+ const result = createCriterionPassedSignal({ criterionId: m[1] });
5472
+ if (Either7.isRight(result)) {
4958
5473
  signals.push(result.right);
4959
5474
  }
4960
5475
  }
@@ -4971,13 +5486,11 @@ var criterionFailedSpec = {
4971
5486
  const signals = [];
4972
5487
  for (const m of text.matchAll(resetRegex(CRITERION_FAILED))) {
4973
5488
  if (m[1]) {
4974
- const raw = {
4975
- _tag: "CriterionFailed",
5489
+ const result = createCriterionFailedSignal({
4976
5490
  criterionId: m[1],
4977
5491
  reason: m[2] || "Unknown reason"
4978
- };
4979
- const result = S16.decodeUnknownEither(CriterionFailedSignalSchema)(raw);
4980
- if (result._tag === "Right") {
5492
+ });
5493
+ if (Either7.isRight(result)) {
4981
5494
  signals.push(result.right);
4982
5495
  }
4983
5496
  }
@@ -4992,7 +5505,7 @@ signalSpecRegistry.register(criterionFailedSpec);
4992
5505
 
4993
5506
  // src/layers/signal/specs/guardrail.ts
4994
5507
  init_esm_shims();
4995
- import { Schema as S17 } from "effect";
5508
+ import { Either as Either8 } from "effect";
4996
5509
  var GUARDRAIL = /<ferix:guardrail\s+severity="(warning|critical)"\s*>([\s\S]*?)<\/ferix:guardrail>/g;
4997
5510
  var PATTERN = /<pattern>([\s\S]*?)<\/pattern>/;
4998
5511
  var SIGN = /<sign>([\s\S]*?)<\/sign>/;
@@ -5016,15 +5529,13 @@ var guardrailSpec = {
5016
5529
  if (!(pattern && sign && avoidance)) {
5017
5530
  continue;
5018
5531
  }
5019
- const raw = {
5020
- _tag: "Guardrail",
5532
+ const result = createGuardrailSignal({
5021
5533
  pattern,
5022
5534
  sign,
5023
5535
  avoidance,
5024
5536
  severity
5025
- };
5026
- const result = S17.decodeUnknownEither(GuardrailSignalSchema)(raw);
5027
- if (result._tag === "Right") {
5537
+ });
5538
+ if (Either8.isRight(result)) {
5028
5539
  signals.push(result.right);
5029
5540
  }
5030
5541
  }
@@ -5036,7 +5547,7 @@ signalSpecRegistry.register(guardrailSpec);
5036
5547
 
5037
5548
  // src/layers/signal/specs/learning.ts
5038
5549
  init_esm_shims();
5039
- import { Schema as S18 } from "effect";
5550
+ import { Either as Either9 } from "effect";
5040
5551
  var LEARNING = /<ferix:learning(?:\s+category="(success|failure|optimization)")?\s*>([\s\S]*?)<\/ferix:learning>/g;
5041
5552
  var learningSpec = {
5042
5553
  tag: "Learning",
@@ -5051,15 +5562,8 @@ var learningSpec = {
5051
5562
  if (!content) {
5052
5563
  continue;
5053
5564
  }
5054
- const raw = {
5055
- _tag: "Learning",
5056
- content
5057
- };
5058
- if (category) {
5059
- raw.category = category;
5060
- }
5061
- const result = S18.decodeUnknownEither(LearningSignalSchema)(raw);
5062
- if (result._tag === "Right") {
5565
+ const result = createLearningSignal({ content, category });
5566
+ if (Either9.isRight(result)) {
5063
5567
  signals.push(result.right);
5064
5568
  }
5065
5569
  }
@@ -5071,7 +5575,7 @@ signalSpecRegistry.register(learningSpec);
5071
5575
 
5072
5576
  // src/layers/signal/specs/loop-complete.ts
5073
5577
  init_esm_shims();
5074
- import { Schema as S19 } from "effect";
5578
+ import { Schema as S20 } from "effect";
5075
5579
  var LOOP_COMPLETE = /<ferix:complete>/;
5076
5580
  var loopCompleteSpec = {
5077
5581
  tag: "LoopComplete",
@@ -5080,7 +5584,7 @@ var loopCompleteSpec = {
5080
5584
  parse: (text) => {
5081
5585
  if (LOOP_COMPLETE.test(text)) {
5082
5586
  const raw = { _tag: "LoopComplete" };
5083
- const result = S19.decodeUnknownEither(LoopCompleteSignalSchema)(raw);
5587
+ const result = S20.decodeUnknownEither(LoopCompleteSignalSchema)(raw);
5084
5588
  if (result._tag === "Right") {
5085
5589
  return [result.right];
5086
5590
  }
@@ -5093,7 +5597,7 @@ signalSpecRegistry.register(loopCompleteSpec);
5093
5597
 
5094
5598
  // src/layers/signal/specs/phases.ts
5095
5599
  init_esm_shims();
5096
- import { Schema as S20 } from "effect";
5600
+ import { Either as Either10 } from "effect";
5097
5601
  var PHASES_BLOCK = /<ferix:phases task="(\d+)">([\s\S]*?)<\/ferix:phases>/;
5098
5602
  var PHASE = /<phase id="([\d.]+)">([^<]+)<\/phase>/g;
5099
5603
  var PHASE_START = /<ferix:phase-start id="([\d.]+)"\/>/g;
@@ -5121,16 +5625,11 @@ var phasesDefinedSpec = {
5121
5625
  if (phases.length === 0) {
5122
5626
  return [];
5123
5627
  }
5124
- const raw = {
5125
- _tag: "PhasesDefined",
5126
- taskId: match[1],
5127
- phases
5128
- };
5129
- const result = S20.decodeUnknownEither(PhasesDefinedSignalSchema)(raw);
5130
- if (result._tag === "Left") {
5131
- return [];
5628
+ const result = createPhasesDefinedSignal({ taskId: match[1], phases });
5629
+ if (Either10.isRight(result)) {
5630
+ return [result.right];
5132
5631
  }
5133
- return [result.right];
5632
+ return [];
5134
5633
  },
5135
5634
  keyFields: (s) => `${s.taskId}:${s.phases.map((p) => p.id).join(",")}`
5136
5635
  };
@@ -5142,9 +5641,8 @@ var phaseStartedSpec = {
5142
5641
  const signals = [];
5143
5642
  for (const m of text.matchAll(resetRegex2(PHASE_START))) {
5144
5643
  if (m[1]) {
5145
- const raw = { _tag: "PhaseStarted", phaseId: m[1] };
5146
- const result = S20.decodeUnknownEither(PhaseStartedSignalSchema)(raw);
5147
- if (result._tag === "Right") {
5644
+ const result = createPhaseStartedSignal({ phaseId: m[1] });
5645
+ if (Either10.isRight(result)) {
5148
5646
  signals.push(result.right);
5149
5647
  }
5150
5648
  }
@@ -5161,9 +5659,8 @@ var phaseCompletedSpec = {
5161
5659
  const signals = [];
5162
5660
  for (const m of text.matchAll(resetRegex2(PHASE_DONE))) {
5163
5661
  if (m[1]) {
5164
- const raw = { _tag: "PhaseCompleted", phaseId: m[1] };
5165
- const result = S20.decodeUnknownEither(PhaseCompletedSignalSchema)(raw);
5166
- if (result._tag === "Right") {
5662
+ const result = createPhaseCompletedSignal({ phaseId: m[1] });
5663
+ if (Either10.isRight(result)) {
5167
5664
  signals.push(result.right);
5168
5665
  }
5169
5666
  }
@@ -5180,13 +5677,11 @@ var phaseFailedSpec = {
5180
5677
  const signals = [];
5181
5678
  for (const m of text.matchAll(resetRegex2(PHASE_FAILED))) {
5182
5679
  if (m[1]) {
5183
- const raw = {
5184
- _tag: "PhaseFailed",
5680
+ const result = createPhaseFailedSignal({
5185
5681
  phaseId: m[1],
5186
5682
  reason: m[2] || "Unknown reason"
5187
- };
5188
- const result = S20.decodeUnknownEither(PhaseFailedSignalSchema)(raw);
5189
- if (result._tag === "Right") {
5683
+ });
5684
+ if (Either10.isRight(result)) {
5190
5685
  signals.push(result.right);
5191
5686
  }
5192
5687
  }
@@ -5225,6 +5720,37 @@ var reviewCompleteSpec = {
5225
5720
  };
5226
5721
  signalSpecRegistry.register(reviewCompleteSpec);
5227
5722
 
5723
+ // src/layers/signal/specs/session-name.ts
5724
+ init_esm_shims();
5725
+ import { Either as Either11 } from "effect";
5726
+ var SESSION_NAME = /<ferix:session-name>([\s\S]*?)<\/ferix:session-name>/g;
5727
+ function sanitizeSessionName(name) {
5728
+ return name.trim().toLowerCase().replace(/[\s_]+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
5729
+ }
5730
+ var sessionNameSpec = {
5731
+ tag: "SessionNameDefined",
5732
+ closingTag: "</ferix:session-name>",
5733
+ schema: SessionNameDefinedSignalSchema,
5734
+ parse: (text) => {
5735
+ const signals = [];
5736
+ const matches = text.matchAll(SESSION_NAME);
5737
+ for (const match of matches) {
5738
+ const rawName = match[1] || "";
5739
+ const name = sanitizeSessionName(rawName);
5740
+ if (!name) {
5741
+ continue;
5742
+ }
5743
+ const result = createSessionNameDefinedSignal({ name });
5744
+ if (Either11.isRight(result)) {
5745
+ signals.push(result.right);
5746
+ }
5747
+ }
5748
+ return signals;
5749
+ },
5750
+ keyFields: (s) => s.name
5751
+ };
5752
+ signalSpecRegistry.register(sessionNameSpec);
5753
+
5228
5754
  // src/layers/signal/specs/task-complete.ts
5229
5755
  init_esm_shims();
5230
5756
  import { Schema as S22 } from "effect";
@@ -5270,7 +5796,7 @@ signalSpecRegistry.register(taskCompleteSpec);
5270
5796
 
5271
5797
  // src/layers/signal/specs/tasks.ts
5272
5798
  init_esm_shims();
5273
- import { Schema as S23 } from "effect";
5799
+ import { Either as Either12 } from "effect";
5274
5800
  var TASKS_BLOCK = /<ferix:tasks>([\s\S]*?)<\/ferix:tasks>/;
5275
5801
  var TASK = /<task id="(\d+)">([^<]+)<\/task>/g;
5276
5802
  function resetRegex3(pattern) {
@@ -5299,12 +5825,11 @@ var tasksDefinedSpec = {
5299
5825
  if (tasks.length === 0) {
5300
5826
  return [];
5301
5827
  }
5302
- const raw = { _tag: "TasksDefined", tasks };
5303
- const result = S23.decodeUnknownEither(TasksDefinedSignalSchema)(raw);
5304
- if (result._tag === "Left") {
5305
- return [];
5828
+ const result = createTasksDefinedSignal({ tasks });
5829
+ if (Either12.isRight(result)) {
5830
+ return [result.right];
5306
5831
  }
5307
- return [result.right];
5832
+ return [];
5308
5833
  },
5309
5834
  keyFields: (s) => s.tasks.map((t) => t.id).join(",")
5310
5835
  };
@@ -5621,6 +6146,16 @@ eventMappingRegistry.registerSignalMapper({
5621
6146
  timestamp: context.timestamp
5622
6147
  })
5623
6148
  });
6149
+ eventMappingRegistry.registerSignalMapper({
6150
+ tag: "SessionNameDefined",
6151
+ map: (signal, context) => ({
6152
+ _tag: "SessionNameGenerated",
6153
+ sessionId: "",
6154
+ // Will be overwritten by discovery stream
6155
+ displayName: signal.name,
6156
+ timestamp: context.timestamp
6157
+ })
6158
+ });
5624
6159
 
5625
6160
  // src/orchestrator/mapping/index.ts
5626
6161
  function mapLLMEventToDomain(event, context) {
@@ -6057,19 +6592,44 @@ After completing a single task, emit <ferix:task-complete> and continue to the n
6057
6592
  IMPORTANT: Always emit signals on their own lines, never inside markdown code blocks.`;
6058
6593
  var DISCOVERY_SYSTEM_PROMPT = `You are in the DISCOVERY phase of a ralph loop - an iterative AI coding workflow.
6059
6594
 
6060
- Your goal is to analyze the task and break it into logical subtasks.
6595
+ Your goal is to:
6596
+ 1. Generate a short, descriptive name for this session
6597
+ 2. Analyze the task and break it into logical subtasks
6061
6598
 
6062
- Your output must include a <ferix:tasks> signal that the orchestrator will parse.
6063
- This signal MUST appear on its own line, not inside code blocks.
6599
+ Your output must include these signals that the orchestrator will parse.
6600
+ These signals MUST appear on their own lines, not inside code blocks.
6064
6601
 
6065
6602
  ## Signal Format
6066
6603
 
6604
+ ### Session Name (REQUIRED - emit first)
6605
+ <ferix:session-name>short-descriptive-name</ferix:session-name>
6606
+
6607
+ Guidelines for session name:
6608
+ - Use 2-5 words in kebab-case (lowercase with hyphens)
6609
+ - Describe the main purpose/feature being worked on
6610
+ - Keep it concise but meaningful
6611
+ - Examples: "add-dark-mode", "fix-auth-flow", "refactor-api-endpoints", "update-user-profile-ui"
6612
+
6613
+ ### Task Breakdown (REQUIRED)
6067
6614
  <ferix:tasks>
6068
6615
  <task id="1">Brief description of first task</task>
6069
6616
  <task id="2">Brief description of second task</task>
6070
6617
  </ferix:tasks>
6071
6618
 
6072
- IMPORTANT: Always emit the <ferix:tasks> signal on its own line, never inside markdown code blocks.`;
6619
+ ## CRITICAL: Task Exclusions
6620
+
6621
+ Do NOT create tasks for any of the following - these are handled automatically by the orchestrator:
6622
+ - Running verification commands (bun lint, bun format, eslint, prettier, etc.)
6623
+ - Running tests (bun test, jest, vitest, etc.)
6624
+ - Running build commands (bun build, tsc, etc.)
6625
+ - Any "Verification", "Testing", or "Testing Plan" sections from PRDs
6626
+ - Final cleanup, validation, or quality check steps
6627
+ - Commands that just run and check output without changing code
6628
+
6629
+ Tasks should ONLY be for implementation work that creates or modifies source code files.
6630
+ Verification commands are run automatically after each task completes - do not create tasks for them.
6631
+
6632
+ IMPORTANT: Always emit signals on their own lines, never inside markdown code blocks.`;
6073
6633
  var DEFAULT_PLANNING_PROMPT = `## Phase 2: PLANNING
6074
6634
 
6075
6635
  If no phases are defined for the current task, define them now.
@@ -6188,17 +6748,26 @@ ${config.prompts.additionalContext}`
6188
6748
  ${config.task}`);
6189
6749
  sections.push(`## Instructions
6190
6750
 
6191
- Analyze the task above and break it into logical subtasks.
6751
+ Analyze the task above and:
6752
+
6753
+ 1. **Generate a session name** (2-5 words, kebab-case)
6754
+ - Should describe the main purpose of this work
6755
+ - Emit: <ferix:session-name>your-descriptive-name</ferix:session-name>
6192
6756
 
6193
- 1. Read and understand what needs to be done
6194
- 2. Identify the main components or steps
6195
- 3. Break the work into 2-6 discrete tasks
6757
+ 2. **Break the task into logical subtasks** (2-6 tasks)
6758
+ - Read and understand what needs to be done
6759
+ - Identify the main components or steps
6760
+ - Emit: <ferix:tasks>...</ferix:tasks>
6196
6761
 
6197
- Emit a <ferix:tasks> block with your task breakdown.
6198
6762
  Each task should be:
6199
6763
  - Self-contained and independently verifiable
6200
6764
  - Clear and specific
6201
6765
  - Ordered logically (dependencies first)
6766
+ - ONLY for code implementation (NOT for running lint/test/build commands)
6767
+
6768
+ REMINDER: Do NOT create tasks for verification steps like "Run lint", "Run tests", "Verify changes", etc.
6769
+ The orchestrator handles verification automatically after each task completes.
6770
+ If the PRD has a "Verification" or "Testing" section, IGNORE it when creating tasks.
6202
6771
 
6203
6772
  Begin your analysis now.`);
6204
6773
  return sections.join("\n\n");
@@ -6311,7 +6880,7 @@ function planTasksToGeneratedTasks(plan) {
6311
6880
  status: mapTaskStatus(task.status)
6312
6881
  }));
6313
6882
  }
6314
- function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, config, sessionId, worktreePath) {
6883
+ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, config, sessionId, worktreePath, onSessionName) {
6315
6884
  return Stream7.unwrap(
6316
6885
  Effect21.gen(function* () {
6317
6886
  const startTimeUtc = yield* DateTime8.now;
@@ -6320,6 +6889,7 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6320
6889
  dirty: false,
6321
6890
  pendingOperation: null
6322
6891
  });
6892
+ const sessionNameRef = yield* Ref10.make(void 0);
6323
6893
  const discoveryStarted = {
6324
6894
  _tag: "DiscoveryStarted",
6325
6895
  timestamp: startTime
@@ -6352,6 +6922,9 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6352
6922
  );
6353
6923
  const events = [...result.events];
6354
6924
  for (const signal of result.signals) {
6925
+ if (signal._tag === "SessionNameDefined") {
6926
+ yield* Ref10.set(sessionNameRef, signal.name);
6927
+ }
6355
6928
  const planEvents = yield* updatePlanFromSignal(
6356
6929
  currentPlanRef,
6357
6930
  persistenceStateRef,
@@ -6398,12 +6971,38 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6398
6971
  }
6399
6972
  const endTimeUtc = yield* DateTime8.now;
6400
6973
  const endTime = DateTime8.toEpochMillis(endTimeUtc);
6974
+ const events = [...persistEvents];
6975
+ const capturedName = yield* Ref10.get(sessionNameRef);
6976
+ if (capturedName) {
6977
+ if (onSessionName) {
6978
+ yield* onSessionName(capturedName).pipe(
6979
+ Effect21.tapError(
6980
+ (error) => Effect21.logDebug(
6981
+ "Failed to handle session name, continuing",
6982
+ {
6983
+ error: String(error),
6984
+ displayName: capturedName
6985
+ }
6986
+ )
6987
+ ),
6988
+ Effect21.orElseSucceed(() => void 0)
6989
+ );
6990
+ }
6991
+ const sessionNameEvent = {
6992
+ _tag: "SessionNameGenerated",
6993
+ sessionId,
6994
+ displayName: capturedName,
6995
+ timestamp: endTime
6996
+ };
6997
+ events.push(sessionNameEvent);
6998
+ }
6401
6999
  const discoveryCompleted = {
6402
7000
  _tag: "DiscoveryCompleted",
6403
7001
  taskCount,
6404
7002
  timestamp: endTime
6405
7003
  };
6406
- return [...persistEvents, discoveryCompleted];
7004
+ events.push(discoveryCompleted);
7005
+ return events;
6407
7006
  })
6408
7007
  ).pipe(Stream7.flatMap((events) => Stream7.fromIterable(events)));
6409
7008
  return pipe(
@@ -6617,12 +7216,27 @@ function runLoop(config) {
6617
7216
  };
6618
7217
  const loopCompletedRef = yield* Ref12.make(false);
6619
7218
  const currentPlanRef = yield* Ref12.make(void 0);
7219
+ const sessionRef = yield* Ref12.make(session);
6620
7220
  const maxIterations = config.maxIterations === 0 ? Number.POSITIVE_INFINITY : config.maxIterations;
6621
7221
  const loopStarted = {
6622
7222
  _tag: "LoopStarted",
6623
7223
  config,
6624
7224
  timestamp: startTime
6625
7225
  };
7226
+ const handleSessionName = (displayName) => Effect23.gen(function* () {
7227
+ const currentSession = yield* Ref12.get(sessionRef);
7228
+ const newBranchName = yield* git.renameBranch(
7229
+ session.id,
7230
+ displayName
7231
+ );
7232
+ const updatedSession = {
7233
+ ...currentSession,
7234
+ displayName,
7235
+ branchName: newBranchName
7236
+ };
7237
+ yield* sessionStore.update(session.id, updatedSession);
7238
+ yield* Ref12.set(sessionRef, updatedSession);
7239
+ });
6626
7240
  const discoveryStream = createDiscoveryStream(
6627
7241
  llm,
6628
7242
  signalParser,
@@ -6630,7 +7244,8 @@ function runLoop(config) {
6630
7244
  currentPlanRef,
6631
7245
  config,
6632
7246
  session.id,
6633
- worktreePath
7247
+ worktreePath,
7248
+ handleSessionName
6634
7249
  );
6635
7250
  const iterationsStream = Stream9.unfoldEffect(
6636
7251
  1,
@@ -6692,7 +7307,8 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6692
7307
  return Stream9.unwrap(
6693
7308
  Effect23.gen(function* () {
6694
7309
  const endTimeUtc = yield* DateTime10.now;
6695
- const durationMs = DateTime10.toEpochMillis(endTimeUtc) - startTime;
7310
+ const endTime = DateTime10.toEpochMillis(endTimeUtc);
7311
+ const durationMs = endTime - startTime;
6696
7312
  const completed = yield* Ref12.get(loopCompletedRef);
6697
7313
  yield* git.commitChanges(session.id, `feat: complete session ${session.id}`).pipe(
6698
7314
  Effect23.tapError(
@@ -6703,6 +7319,20 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6703
7319
  ),
6704
7320
  Effect23.orElseSucceed(() => void 0)
6705
7321
  );
7322
+ yield* git.removeWorktreeKeepBranch(session.id).pipe(
7323
+ Effect23.tapError(
7324
+ (error) => Effect23.logDebug("Worktree cleanup failed, continuing", {
7325
+ sessionId: session.id,
7326
+ error: String(error)
7327
+ })
7328
+ ),
7329
+ Effect23.orElseSucceed(() => void 0)
7330
+ );
7331
+ const worktreeRemoved = {
7332
+ _tag: "WorktreeRemoved",
7333
+ sessionId: session.id,
7334
+ timestamp: endTime
7335
+ };
6706
7336
  const summary = {
6707
7337
  iterations: config.maxIterations,
6708
7338
  success: completed,
@@ -6712,7 +7342,8 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6712
7342
  };
6713
7343
  yield* sessionStore.update(session.id, {
6714
7344
  ...session,
6715
- status: completed ? "completed" : "paused"
7345
+ status: completed ? "completed" : "paused",
7346
+ worktreePath: void 0
6716
7347
  }).pipe(
6717
7348
  Effect23.tapError(
6718
7349
  (error) => Effect23.logDebug("Session update failed, continuing", {
@@ -6723,7 +7354,10 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6723
7354
  Effect23.orElseSucceed(() => void 0)
6724
7355
  );
6725
7356
  const loopCompleted = { _tag: "LoopCompleted", summary };
6726
- return Stream9.succeed(loopCompleted);
7357
+ return pipe3(
7358
+ Stream9.succeed(worktreeRemoved),
7359
+ Stream9.concat(Stream9.succeed(loopCompleted))
7360
+ );
6727
7361
  })
6728
7362
  );
6729
7363
  }
@@ -6783,13 +7417,21 @@ program.name("ferix-code").description("Composable RALPH loops for AI coding age
6783
7417
  });
6784
7418
  program.parse();
6785
7419
  export {
7420
+ AnyToolInputSchema,
7421
+ AssistantMessageSchema,
7422
+ BashToolInputSchema,
6786
7423
  CheckFailedEventSchema,
6787
7424
  CheckFailedSignalSchema,
6788
7425
  CheckPassedEventSchema,
6789
7426
  CheckPassedSignalSchema,
6790
7427
  ClaudeCLI,
7428
+ ClaudeCliEventSchema,
6791
7429
  ConsoleLoggerConfigSchema,
6792
7430
  ConsumerTypeSchema,
7431
+ ContentBlockDeltaSchema,
7432
+ ContentBlockSchema,
7433
+ ContentBlockStartSchema,
7434
+ ContentBlockStopSchema,
6793
7435
  CriteriaDefinedDataSchema,
6794
7436
  CriteriaDefinedEventSchema,
6795
7437
  CriteriaDefinedSignalSchema,
@@ -6803,11 +7445,13 @@ export {
6803
7445
  CriterionSchema,
6804
7446
  CriterionStatusSchema,
6805
7447
  CursorCLI,
7448
+ DeltaSchema,
6806
7449
  DiscoveryCompletedEventSchema,
6807
7450
  DiscoveryStartedEventSchema,
6808
7451
  DomainEventSchema,
6809
7452
  DomainEventUtils,
6810
7453
  DoneEventSchema,
7454
+ EditToolInputSchema,
6811
7455
  ExecutionModeSchema,
6812
7456
  FerixParser,
6813
7457
  FileLoggerConfigSchema,
@@ -6821,6 +7465,8 @@ export {
6821
7465
  GeneratedTaskStatusSchema,
6822
7466
  Git,
6823
7467
  GitError,
7468
+ GlobToolInputSchema,
7469
+ GrepToolInputSchema,
6824
7470
  GuardrailAddedEventSchema,
6825
7471
  GuardrailSchema,
6826
7472
  GuardrailSeveritySchema,
@@ -6828,6 +7474,7 @@ export {
6828
7474
  GuardrailsFileSchema,
6829
7475
  GuardrailsStore,
6830
7476
  GuardrailsStoreError,
7477
+ InputJsonDeltaSchema,
6831
7478
  IterationCompletedEventSchema,
6832
7479
  IterationStartedEventSchema,
6833
7480
  LLM,
@@ -6857,6 +7504,16 @@ export {
6857
7504
  MemorySession,
6858
7505
  Mock,
6859
7506
  Mock as MockLLM,
7507
+ OpenCodeCliEventSchema,
7508
+ OpenCodeCostSchema,
7509
+ OpenCodeStepFinishSchema,
7510
+ OpenCodeStepPartSchema,
7511
+ OpenCodeStepStartSchema,
7512
+ OpenCodeTextEventSchema,
7513
+ OpenCodeTokensSchema,
7514
+ OpenCodeToolPartSchema,
7515
+ OpenCodeToolStateSchema,
7516
+ OpenCodeToolUseEventSchema,
6860
7517
  OrchestratorError,
6861
7518
  PROVIDER_CONFIGS,
6862
7519
  ParseError,
@@ -6892,16 +7549,20 @@ export {
6892
7549
  ProgressUpdatedEventSchema,
6893
7550
  PromptConfigSchema,
6894
7551
  ProviderNameSchema,
7552
+ ReadToolInputSchema,
6895
7553
  ReviewCompleteDataSchema,
6896
7554
  ReviewCompleteEventSchema,
6897
7555
  ReviewCompleteSignalSchema,
6898
7556
  RunOptionsDataSchema,
7557
+ SessionNameDefinedSignalSchema,
7558
+ SessionNameGeneratedEventSchema,
6899
7559
  SessionSchema,
6900
7560
  SessionStatusSchema,
6901
7561
  SessionStore,
6902
7562
  SessionStoreError,
6903
7563
  SignalParser,
6904
7564
  SignalSchema,
7565
+ StreamEventEnvelopeSchema,
6905
7566
  TUICriterionSchema,
6906
7567
  TUICriterionStatusSchema,
6907
7568
  TUIPhaseSchema,
@@ -6916,28 +7577,57 @@ export {
6916
7577
  TaskCompletedEventSchema,
6917
7578
  TaskSchema,
6918
7579
  TaskStatusSchema,
7580
+ TaskToolInputSchema,
6919
7581
  TasksDefinedDataSchema,
6920
7582
  TasksDefinedEventSchema,
6921
7583
  TasksDefinedSignalSchema,
6922
7584
  TestLayers,
7585
+ TextContentBlockSchema,
7586
+ TextDeltaSchema,
6923
7587
  TextEventSchema,
6924
7588
  ToolEndEventSchema,
7589
+ ToolInputSchemaRegistry,
6925
7590
  ToolStartEventSchema,
7591
+ ToolUseContentBlockSchema,
6926
7592
  ToolUseEventSchema,
7593
+ ValidatedToolUseEventSchema,
6927
7594
  ViewModeSchema,
7595
+ WebFetchToolInputSchema,
7596
+ WebSearchToolInputSchema,
6928
7597
  WorktreeCreatedEventSchema,
6929
7598
  WorktreeRemovedEventSchema,
7599
+ WriteToolInputSchema,
6930
7600
  buildPrompt,
6931
7601
  collectEvents,
7602
+ createCheckFailedSignal,
7603
+ createCheckPassedSignal,
7604
+ createCriteriaDefinedSignal,
7605
+ createCriterionFailedSignal,
7606
+ createCriterionPassedSignal,
7607
+ createGuardrailSignal,
6932
7608
  createHeadlessConsumer,
7609
+ createLearningSignal,
7610
+ createLoopCompleteSignal,
7611
+ createPhaseCompletedSignal,
7612
+ createPhaseFailedSignal,
7613
+ createPhaseStartedSignal,
7614
+ createPhasesDefinedSignal,
6933
7615
  createProductionLayers,
6934
7616
  createProviderLayer2 as createProviderLayer,
7617
+ createReviewCompleteSignal,
7618
+ createSessionNameDefinedSignal,
6935
7619
  createTUIConsumer,
7620
+ createTaskCompleteSignal,
7621
+ createTasksDefinedSignal,
6936
7622
  createTestLayers,
7623
+ decodeClaudeCliEvent,
7624
+ decodeClaudeCliEventSync,
6937
7625
  decodeGuardrail,
6938
7626
  decodeGuardrailsFile,
6939
7627
  decodeLLMEvent,
6940
7628
  decodeLoopConfig,
7629
+ decodeOpenCodeCliEvent,
7630
+ decodeOpenCodeCliEventSync,
6941
7631
  decodePlan,
6942
7632
  decodePlanData,
6943
7633
  decodeProgressEntry,
@@ -6946,9 +7636,34 @@ export {
6946
7636
  decodeSignal,
6947
7637
  decodeSignalSync,
6948
7638
  formatTasksMd,
7639
+ getToolInputSchema,
7640
+ isAssistantMessage,
7641
+ isBashToolInput,
7642
+ isContentBlockDelta,
7643
+ isContentBlockStart,
7644
+ isContentBlockStop,
7645
+ isEditToolInput,
7646
+ isGlobToolInput,
7647
+ isGrepToolInput,
7648
+ isInputJsonDelta,
7649
+ isOpenCodeStepFinish,
7650
+ isOpenCodeStepStart,
7651
+ isOpenCodeTextEvent,
7652
+ isOpenCodeToolUseEvent,
7653
+ isReadToolInput,
7654
+ isStreamEventEnvelope,
7655
+ isTaskToolInput,
7656
+ isTextContentBlock,
7657
+ isTextDelta,
7658
+ isToolUseContentBlock,
7659
+ isWebFetchToolInput,
7660
+ isWebSearchToolInput,
7661
+ isWriteToolInput,
6949
7662
  main,
6950
7663
  parseTasksMd,
6951
7664
  run,
6952
7665
  runLoop,
6953
- runTest
7666
+ runTest,
7667
+ validateToolInput,
7668
+ validateToolUseEvent
6954
7669
  };