ferix-code 0.0.2-beta.16 → 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 +1174 -476
  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.16",
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,24 +1064,133 @@ 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));
1062
1165
  function normalizeToolName(tool) {
1063
1166
  return tool.toLowerCase();
1064
1167
  }
1065
- function getInputValue(obj, key) {
1066
- if (obj[key] !== void 0) {
1067
- return obj[key];
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;
1068
1176
  }
1069
1177
  const camelKey = key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
1070
- if (obj[camelKey] !== void 0) {
1071
- return obj[camelKey];
1178
+ const camel = getValue(camelKey);
1179
+ if (camel !== void 0) {
1180
+ return camel;
1072
1181
  }
1073
1182
  const snakeKey = key.replace(/([A-Z])/g, "_$1").toLowerCase();
1074
- if (obj[snakeKey] !== void 0) {
1075
- return obj[snakeKey];
1183
+ return getValue(snakeKey);
1184
+ }
1185
+ function getValidatedInput(tool, input) {
1186
+ if (!input || typeof input !== "object") {
1187
+ return null;
1076
1188
  }
1077
- return void 0;
1189
+ const result = validateToolInput(tool, input);
1190
+ if (Either2.isRight(result)) {
1191
+ return result.right;
1192
+ }
1193
+ return input;
1078
1194
  }
1079
1195
  function createToolDisplayRegistry() {
1080
1196
  const configs = /* @__PURE__ */ new Map();
@@ -1093,21 +1209,20 @@ function createToolDisplayRegistry() {
1093
1209
  return configs.get(normalizeToolName(tool))?.maxLength ?? MAX_TOOL_INPUT_LENGTH;
1094
1210
  },
1095
1211
  formatInput(tool, input) {
1096
- if (!input || typeof input !== "object") {
1097
- return "";
1098
- }
1099
1212
  const config = configs.get(normalizeToolName(tool));
1100
1213
  if (!config) {
1101
1214
  return "";
1102
1215
  }
1103
- const obj = input;
1104
- const value = getInputValue(obj, config.inputKey);
1216
+ const obj = getValidatedInput(tool, input);
1217
+ if (!obj) {
1218
+ return "";
1219
+ }
1220
+ const value = extractStringValue(obj, config.inputKey);
1105
1221
  if (!value) {
1106
1222
  return "";
1107
1223
  }
1108
- const str = String(value);
1109
1224
  const maxLen = config.maxLength ?? MAX_TOOL_INPUT_LENGTH;
1110
- return str.length > maxLen ? `${str.slice(0, maxLen)}...` : str;
1225
+ return value.length > maxLen ? `${value.slice(0, maxLen)}...` : value;
1111
1226
  }
1112
1227
  };
1113
1228
  }
@@ -1164,11 +1279,47 @@ function formatToolInput(tool, input) {
1164
1279
  }
1165
1280
 
1166
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
+ }
1167
1314
  function appendOutput(state, text) {
1168
1315
  if (!text) {
1169
1316
  return state;
1170
1317
  }
1171
- const fullText = state.partialLine + text;
1318
+ const cleanedText = stripFerixSignals(text);
1319
+ if (!cleanedText) {
1320
+ return state;
1321
+ }
1322
+ const fullText = state.partialLine + cleanedText;
1172
1323
  const parts = fullText.split("\n");
1173
1324
  const partialLine = parts.pop() ?? "";
1174
1325
  const newLines = parts.filter((line) => line.length > 0);
@@ -1456,7 +1607,18 @@ Worktree created
1456
1607
  `
1457
1608
  )
1458
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
+ };
1459
1620
  stateReducerRegistry.register(worktreeCreatedReducer);
1621
+ stateReducerRegistry.register(worktreeRemovedReducer);
1460
1622
 
1461
1623
  // src/consumers/tui/reducers/index.ts
1462
1624
  function reduce(state, event) {
@@ -2553,6 +2715,36 @@ var make = {
2553
2715
  Effect4.catchAll(() => Effect4.succeed(void 0))
2554
2716
  );
2555
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
+ }),
2556
2748
  getWorktreePath: (sessionId) => Effect4.gen(function* () {
2557
2749
  const worktreeDir = getWorktreeDir(sessionId);
2558
2750
  const exists = yield* directoryExists(worktreeDir);
@@ -2663,6 +2855,33 @@ var make = {
2663
2855
  );
2664
2856
  return prUrl;
2665
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
+ }),
2666
2885
  getBranchName
2667
2886
  };
2668
2887
  var Live = Layer.succeed(Git, make);
@@ -2701,6 +2920,11 @@ function createMemoryGitService(stateRef, commitCounterRef) {
2701
2920
  state.delete(sessionId);
2702
2921
  yield* Ref3.set(stateRef, state);
2703
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
+ }),
2704
2928
  getWorktreePath: (sessionId) => Effect5.gen(function* () {
2705
2929
  const state = yield* Ref3.get(stateRef);
2706
2930
  const worktree = state.get(sessionId);
@@ -2753,6 +2977,26 @@ function createMemoryGitService(stateRef, commitCounterRef) {
2753
2977
  const slug = title.toLowerCase().replace(/\s+/g, "-").slice(0, 30);
2754
2978
  return `https://github.com/test/repo/pull/${slug}`;
2755
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
+ }),
2756
3000
  getBranchName: getBranchName2
2757
3001
  };
2758
3002
  }
@@ -2784,60 +3028,196 @@ init_esm_shims();
2784
3028
  // src/domain/schemas/index.ts
2785
3029
  init_esm_shims();
2786
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
+
2787
3167
  // src/domain/schemas/config.ts
2788
3168
  init_esm_shims();
2789
- import { Schema as S } from "effect";
2790
- var ProviderNameSchema = S.Literal("claude", "cursor", "opencode");
2791
- var PhasePromptOverridesSchema = S.Struct({
2792
- breakdown: S.optional(S.String),
2793
- planning: S.optional(S.String),
2794
- execution: S.optional(S.String),
2795
- check: S.optional(S.String),
2796
- verify: S.optional(S.String),
2797
- review: S.optional(S.String),
2798
- completion: S.optional(S.String)
2799
- });
2800
- var PromptConfigSchema = S.Struct({
2801
- systemPrompt: S.optional(S.String),
2802
- phases: S.optional(PhasePromptOverridesSchema),
2803
- additionalContext: S.optional(S.String)
2804
- });
2805
- var LoopConfigSchema = S.Struct({
2806
- task: S.String,
2807
- maxIterations: S.Number,
2808
- verifyCommands: S.Array(S.String),
2809
- sessionId: S.optional(S.String),
2810
- branch: S.optional(S.String),
2811
- push: S.optional(S.Boolean),
2812
- pr: S.optional(S.Boolean),
2813
- verbose: S.optional(S.Boolean),
2814
- 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),
2815
3195
  /** LLM provider to use. Defaults to "claude". */
2816
- provider: S.optional(ProviderNameSchema)
3196
+ provider: S4.optional(ProviderNameSchema)
2817
3197
  });
2818
- var LoopSummarySchema = S.Struct({
2819
- iterations: S.Number,
2820
- success: S.Boolean,
2821
- sessionId: S.String,
2822
- completedTasks: S.Array(S.String),
2823
- 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
2824
3204
  });
2825
- var LoopErrorSchema = S.Struct({
2826
- message: S.String,
2827
- phase: S.String,
2828
- iteration: S.optional(S.Number)
3205
+ var LoopErrorSchema = S4.Struct({
3206
+ message: S4.String,
3207
+ phase: S4.String,
3208
+ iteration: S4.optional(S4.Number)
2829
3209
  });
2830
- var decodeLoopConfig = S.decodeUnknown(LoopConfigSchema);
3210
+ var decodeLoopConfig = S4.decodeUnknown(LoopConfigSchema);
2831
3211
 
2832
3212
  // src/domain/schemas/events.ts
2833
3213
  init_esm_shims();
2834
- import { Schema as S4 } from "effect";
3214
+ import { Schema as S7 } from "effect";
2835
3215
 
2836
3216
  // src/domain/schemas/plan.ts
2837
3217
  init_esm_shims();
2838
- import { Brand, Schema as S2 } from "effect";
3218
+ import { Brand, Schema as S5 } from "effect";
2839
3219
  var PlanId = Brand.nominal();
2840
- var TaskStatusSchema = S2.Literal(
3220
+ var TaskStatusSchema = S5.Literal(
2841
3221
  "pending",
2842
3222
  "planning",
2843
3223
  "in_progress",
@@ -2845,114 +3225,114 @@ var TaskStatusSchema = S2.Literal(
2845
3225
  "failed",
2846
3226
  "skipped"
2847
3227
  );
2848
- var PhaseStatusSchema = S2.Literal(
3228
+ var PhaseStatusSchema = S5.Literal(
2849
3229
  "pending",
2850
3230
  "in_progress",
2851
3231
  "done",
2852
3232
  "failed"
2853
3233
  );
2854
- var CriterionStatusSchema = S2.Literal("pending", "passed", "failed");
2855
- var PhaseSchema = S2.Struct({
2856
- id: S2.String,
2857
- description: S2.String,
3234
+ var CriterionStatusSchema = S5.Literal("pending", "passed", "failed");
3235
+ var PhaseSchema = S5.Struct({
3236
+ id: S5.String,
3237
+ description: S5.String,
2858
3238
  status: PhaseStatusSchema
2859
3239
  });
2860
- var CriterionSchema = S2.Struct({
2861
- id: S2.String,
2862
- description: S2.String,
3240
+ var CriterionSchema = S5.Struct({
3241
+ id: S5.String,
3242
+ description: S5.String,
2863
3243
  status: CriterionStatusSchema,
2864
- failureReason: S2.optional(S2.String)
3244
+ failureReason: S5.optional(S5.String)
2865
3245
  });
2866
- var TaskSchema = S2.Struct({
2867
- id: S2.String,
2868
- title: S2.String,
2869
- description: S2.String,
3246
+ var TaskSchema = S5.Struct({
3247
+ id: S5.String,
3248
+ title: S5.String,
3249
+ description: S5.String,
2870
3250
  status: TaskStatusSchema,
2871
- phases: S2.Array(PhaseSchema),
2872
- criteria: S2.Array(CriterionSchema),
2873
- filesToModify: S2.Array(S2.String),
2874
- attempts: S2.Number,
2875
- completionNotes: S2.optional(S2.String)
2876
- });
2877
- var PlanDataSchema = S2.Struct({
2878
- sessionId: S2.String,
2879
- createdAt: S2.String,
2880
- originalTask: S2.String,
2881
- context: S2.optional(S2.String),
2882
- tasks: S2.Array(TaskSchema)
2883
- });
2884
- var PlanSchema = S2.Struct({
2885
- id: S2.String,
2886
- sessionId: S2.String,
2887
- createdAt: S2.String,
2888
- originalTask: S2.String,
2889
- context: S2.optional(S2.String),
2890
- tasks: S2.Array(TaskSchema)
2891
- });
2892
- var decodePlan = S2.decodeUnknown(PlanSchema);
2893
- 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);
2894
3274
 
2895
3275
  // src/domain/schemas/shared.ts
2896
3276
  init_esm_shims();
2897
- import { Schema as S3 } from "effect";
2898
- var TaskBasicInfoSchema = S3.Struct({
2899
- id: S3.String,
2900
- title: S3.String,
2901
- 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
2902
3282
  });
2903
- var PhaseBasicInfoSchema = S3.Struct({
2904
- id: S3.String,
2905
- description: S3.String
3283
+ var PhaseBasicInfoSchema = S6.Struct({
3284
+ id: S6.String,
3285
+ description: S6.String
2906
3286
  });
2907
- var CriterionBasicInfoSchema = S3.Struct({
2908
- id: S3.String,
2909
- description: S3.String
3287
+ var CriterionBasicInfoSchema = S6.Struct({
3288
+ id: S6.String,
3289
+ description: S6.String
2910
3290
  });
2911
- var TasksDefinedDataSchema = S3.Struct({
2912
- tasks: S3.Array(TaskBasicInfoSchema)
3291
+ var TasksDefinedDataSchema = S6.Struct({
3292
+ tasks: S6.Array(TaskBasicInfoSchema)
2913
3293
  });
2914
- var PhasesDefinedDataSchema = S3.Struct({
2915
- taskId: S3.String,
2916
- phases: S3.Array(PhaseBasicInfoSchema)
3294
+ var PhasesDefinedDataSchema = S6.Struct({
3295
+ taskId: S6.String,
3296
+ phases: S6.Array(PhaseBasicInfoSchema)
2917
3297
  });
2918
- var CriteriaDefinedDataSchema = S3.Struct({
2919
- taskId: S3.String,
2920
- criteria: S3.Array(CriterionBasicInfoSchema)
3298
+ var CriteriaDefinedDataSchema = S6.Struct({
3299
+ taskId: S6.String,
3300
+ criteria: S6.Array(CriterionBasicInfoSchema)
2921
3301
  });
2922
- var PhaseIdDataSchema = S3.Struct({
2923
- phaseId: S3.String
3302
+ var PhaseIdDataSchema = S6.Struct({
3303
+ phaseId: S6.String
2924
3304
  });
2925
- var PhaseFailedDataSchema = S3.Struct({
2926
- phaseId: S3.String,
2927
- reason: S3.String
3305
+ var PhaseFailedDataSchema = S6.Struct({
3306
+ phaseId: S6.String,
3307
+ reason: S6.String
2928
3308
  });
2929
- var CriterionIdDataSchema = S3.Struct({
2930
- criterionId: S3.String
3309
+ var CriterionIdDataSchema = S6.Struct({
3310
+ criterionId: S6.String
2931
3311
  });
2932
- var CriterionFailedDataSchema = S3.Struct({
2933
- criterionId: S3.String,
2934
- reason: S3.String
3312
+ var CriterionFailedDataSchema = S6.Struct({
3313
+ criterionId: S6.String,
3314
+ reason: S6.String
2935
3315
  });
2936
- var ReviewCompleteDataSchema = S3.Struct({
2937
- changesMade: S3.Boolean
3316
+ var ReviewCompleteDataSchema = S6.Struct({
3317
+ changesMade: S6.Boolean
2938
3318
  });
2939
- var TaskCompleteSignalDataSchema = S3.Struct({
2940
- taskId: S3.String,
2941
- summary: S3.String,
2942
- filesModified: S3.Array(S3.String),
2943
- 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)
2944
3324
  });
2945
- var TaskCompleteDataSchema = S3.Struct({
2946
- taskId: S3.String,
2947
- summary: S3.String
3325
+ var TaskCompleteDataSchema = S6.Struct({
3326
+ taskId: S6.String,
3327
+ summary: S6.String
2948
3328
  });
2949
3329
 
2950
3330
  // src/domain/schemas/events.ts
2951
- var taggedEvent = (tag, fields) => S4.TaggedStruct(tag, fields);
2952
- 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 });
2953
3333
  var LoopStartedEventSchema = taggedEvent("LoopStarted", {
2954
3334
  config: LoopConfigSchema,
2955
- timestamp: S4.Number
3335
+ timestamp: S7.Number
2956
3336
  });
2957
3337
  var LoopCompletedEventSchema = taggedEvent("LoopCompleted", {
2958
3338
  summary: LoopSummarySchema
@@ -2961,30 +3341,30 @@ var LoopFailedEventSchema = taggedEvent("LoopFailed", {
2961
3341
  error: LoopErrorSchema
2962
3342
  });
2963
3343
  var DiscoveryStartedEventSchema = taggedEvent("DiscoveryStarted", {
2964
- timestamp: S4.Number
3344
+ timestamp: S7.Number
2965
3345
  });
2966
3346
  var DiscoveryCompletedEventSchema = taggedEvent("DiscoveryCompleted", {
2967
- taskCount: S4.Number,
2968
- timestamp: S4.Number
3347
+ taskCount: S7.Number,
3348
+ timestamp: S7.Number
2969
3349
  });
2970
3350
  var IterationStartedEventSchema = taggedEvent("IterationStarted", {
2971
- iteration: S4.Number
3351
+ iteration: S7.Number
2972
3352
  });
2973
3353
  var IterationCompletedEventSchema = taggedEvent("IterationCompleted", {
2974
- iteration: S4.Number
3354
+ iteration: S7.Number
2975
3355
  });
2976
3356
  var LLMTextEventSchema = taggedEvent("LLMText", {
2977
- text: S4.String
3357
+ text: S7.String
2978
3358
  });
2979
3359
  var LLMToolStartEventSchema = taggedEvent("LLMToolStart", {
2980
- tool: S4.String
3360
+ tool: S7.String
2981
3361
  });
2982
3362
  var LLMToolUseEventSchema = taggedEvent("LLMToolUse", {
2983
- tool: S4.String,
2984
- input: S4.Unknown
3363
+ tool: S7.String,
3364
+ input: S7.Unknown
2985
3365
  });
2986
3366
  var LLMToolEndEventSchema = taggedEvent("LLMToolEnd", {
2987
- tool: S4.String
3367
+ tool: S7.String
2988
3368
  });
2989
3369
  var TasksDefinedEventSchema = taggedFromData(
2990
3370
  "TasksDefined",
@@ -3001,17 +3381,17 @@ var CriteriaDefinedEventSchema = taggedFromData(
3001
3381
  var PhaseStartedEventSchema = taggedFromData(
3002
3382
  "PhaseStarted",
3003
3383
  PhaseIdDataSchema,
3004
- { timestamp: S4.Number }
3384
+ { timestamp: S7.Number }
3005
3385
  );
3006
3386
  var PhaseCompletedEventSchema = taggedFromData(
3007
3387
  "PhaseCompleted",
3008
3388
  PhaseIdDataSchema,
3009
- { timestamp: S4.Number }
3389
+ { timestamp: S7.Number }
3010
3390
  );
3011
3391
  var PhaseFailedEventSchema = taggedFromData(
3012
3392
  "PhaseFailed",
3013
3393
  PhaseFailedDataSchema,
3014
- { timestamp: S4.Number }
3394
+ { timestamp: S7.Number }
3015
3395
  );
3016
3396
  var CriterionPassedEventSchema = taggedFromData(
3017
3397
  "CriterionPassed",
@@ -3021,9 +3401,9 @@ var CriterionFailedEventSchema = taggedFromData(
3021
3401
  "CriterionFailed",
3022
3402
  CriterionFailedDataSchema
3023
3403
  );
3024
- var CheckPassedEventSchema = S4.TaggedStruct("CheckPassed", {});
3404
+ var CheckPassedEventSchema = S7.TaggedStruct("CheckPassed", {});
3025
3405
  var CheckFailedEventSchema = taggedEvent("CheckFailed", {
3026
- failedCriteria: S4.Array(S4.String)
3406
+ failedCriteria: S7.Array(S7.String)
3027
3407
  });
3028
3408
  var ReviewCompleteEventSchema = taggedFromData(
3029
3409
  "ReviewComplete",
@@ -3032,7 +3412,7 @@ var ReviewCompleteEventSchema = taggedFromData(
3032
3412
  var TaskCompletedEventSchema = taggedFromData(
3033
3413
  "TaskCompleted",
3034
3414
  TaskCompleteDataSchema,
3035
- { timestamp: S4.Number }
3415
+ { timestamp: S7.Number }
3036
3416
  );
3037
3417
  var PlanCreatedEventSchema = taggedEvent("PlanCreated", {
3038
3418
  plan: PlanSchema
@@ -3041,43 +3421,52 @@ var PlanUpdatedEventSchema = taggedEvent("PlanUpdated", {
3041
3421
  plan: PlanSchema
3042
3422
  });
3043
3423
  var PlanUpdateFailedEventSchema = taggedEvent("PlanUpdateFailed", {
3044
- operation: S4.Literal("create", "update"),
3045
- error: S4.String,
3046
- planId: S4.optional(S4.String)
3424
+ operation: S7.Literal("create", "update"),
3425
+ error: S7.String,
3426
+ planId: S7.optional(S7.String)
3047
3427
  });
3048
3428
  var LearningRecordedEventSchema = taggedEvent("LearningRecorded", {
3049
- iteration: S4.Number,
3050
- content: S4.String,
3051
- category: S4.optional(S4.Literal("success", "failure", "optimization")),
3052
- timestamp: S4.Number
3429
+ iteration: S7.Number,
3430
+ content: S7.String,
3431
+ category: S7.optional(S7.Literal("success", "failure", "optimization")),
3432
+ timestamp: S7.Number
3053
3433
  });
3054
3434
  var GuardrailAddedEventSchema = taggedEvent("GuardrailAdded", {
3055
- id: S4.String,
3056
- iteration: S4.Number,
3057
- pattern: S4.String,
3058
- sign: S4.String,
3059
- avoidance: S4.String,
3060
- severity: S4.Literal("warning", "critical"),
3061
- 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
3062
3442
  });
3063
3443
  var ProgressUpdatedEventSchema = taggedEvent("ProgressUpdated", {
3064
- sessionId: S4.String,
3065
- iteration: S4.Number,
3066
- taskId: S4.String,
3067
- action: S4.Literal("started", "completed", "failed", "learning"),
3068
- 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
3069
3449
  });
3070
3450
  var WorktreeCreatedEventSchema = taggedEvent("WorktreeCreated", {
3071
- sessionId: S4.String,
3072
- worktreePath: S4.String,
3073
- branchName: S4.String,
3074
- timestamp: S4.Number
3451
+ sessionId: S7.String,
3452
+ worktreePath: S7.String,
3453
+ branchName: S7.String,
3454
+ timestamp: S7.Number
3075
3455
  });
3076
3456
  var WorktreeRemovedEventSchema = taggedEvent("WorktreeRemoved", {
3077
- sessionId: S4.String,
3078
- timestamp: S4.Number
3457
+ sessionId: S7.String,
3458
+ timestamp: S7.Number
3079
3459
  });
3080
- 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(
3081
3470
  LoopStartedEventSchema,
3082
3471
  LoopCompletedEventSchema,
3083
3472
  LoopFailedEventSchema,
@@ -3108,7 +3497,8 @@ var DomainEventSchema = S4.Union(
3108
3497
  GuardrailAddedEventSchema,
3109
3498
  ProgressUpdatedEventSchema,
3110
3499
  WorktreeCreatedEventSchema,
3111
- WorktreeRemovedEventSchema
3500
+ WorktreeRemovedEventSchema,
3501
+ SessionNameGeneratedEventSchema
3112
3502
  );
3113
3503
  var DomainEventUtils = {
3114
3504
  isLLMEvent: (e) => e._tag.startsWith("LLM"),
@@ -3120,132 +3510,149 @@ var DomainEventUtils = {
3120
3510
 
3121
3511
  // src/domain/schemas/guardrails.ts
3122
3512
  init_esm_shims();
3123
- import { Schema as S5 } from "effect";
3124
- var GuardrailSeveritySchema = S5.Literal("warning", "critical");
3125
- var GuardrailSchema = S5.Struct({
3126
- id: S5.String,
3127
- createdAt: S5.String,
3128
- iteration: S5.Number,
3129
- pattern: S5.String,
3130
- sign: S5.String,
3131
- 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,
3132
3522
  severity: GuardrailSeveritySchema
3133
3523
  });
3134
- var GuardrailsFileSchema = S5.Struct({
3135
- sessionId: S5.String,
3136
- createdAt: S5.String,
3137
- guardrails: S5.Array(GuardrailSchema)
3524
+ var GuardrailsFileSchema = S8.Struct({
3525
+ sessionId: S8.String,
3526
+ createdAt: S8.String,
3527
+ guardrails: S8.Array(GuardrailSchema)
3138
3528
  });
3139
- var decodeGuardrail = S5.decodeUnknown(GuardrailSchema);
3140
- var decodeGuardrailsFile = S5.decodeUnknown(GuardrailsFileSchema);
3529
+ var decodeGuardrail = S8.decodeUnknown(GuardrailSchema);
3530
+ var decodeGuardrailsFile = S8.decodeUnknown(GuardrailsFileSchema);
3141
3531
 
3142
3532
  // src/domain/schemas/llm.ts
3143
3533
  init_esm_shims();
3144
- import { Schema as S6 } from "effect";
3145
- var TextEventSchema = S6.TaggedStruct("Text", {
3146
- text: S6.String
3534
+ import { Either as Either3, Schema as S9 } from "effect";
3535
+ var TextEventSchema = S9.TaggedStruct("Text", {
3536
+ text: S9.String
3147
3537
  });
3148
- var ToolStartEventSchema = S6.TaggedStruct("ToolStart", {
3149
- tool: S6.String
3538
+ var ToolStartEventSchema = S9.TaggedStruct("ToolStart", {
3539
+ tool: S9.String
3150
3540
  });
3151
- var ToolUseEventSchema = S6.TaggedStruct("ToolUse", {
3152
- tool: S6.String,
3153
- input: S6.Unknown
3541
+ var ToolUseEventSchema = S9.TaggedStruct("ToolUse", {
3542
+ tool: S9.String,
3543
+ input: S9.Unknown
3154
3544
  });
3155
- var ToolEndEventSchema = S6.TaggedStruct("ToolEnd", {
3156
- tool: S6.String
3545
+ var ValidatedToolUseEventSchema = S9.TaggedStruct("ToolUse", {
3546
+ tool: S9.String,
3547
+ input: AnyToolInputSchema
3157
3548
  });
3158
- var DoneEventSchema = S6.TaggedStruct("Done", {
3159
- output: S6.String
3549
+ var ToolEndEventSchema = S9.TaggedStruct("ToolEnd", {
3550
+ tool: S9.String
3160
3551
  });
3161
- var LLMEventSchema = S6.Union(
3552
+ var DoneEventSchema = S9.TaggedStruct("Done", {
3553
+ output: S9.String
3554
+ });
3555
+ var LLMEventSchema = S9.Union(
3162
3556
  TextEventSchema,
3163
3557
  ToolStartEventSchema,
3164
3558
  ToolUseEventSchema,
3165
3559
  ToolEndEventSchema,
3166
3560
  DoneEventSchema
3167
3561
  );
3168
- 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
+ }
3169
3570
 
3170
3571
  // src/domain/schemas/logger.ts
3171
3572
  init_esm_shims();
3172
- import { Schema as S7 } from "effect";
3173
- var LogLevelSchema = S7.Literal("debug", "info", "warn", "error");
3174
- 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({
3175
3576
  level: LogLevelSchema,
3176
- message: S7.String,
3177
- timestamp: S7.String,
3178
- 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 }))
3179
3580
  });
3180
- var ConsoleLoggerConfigSchema = S7.Struct({
3181
- level: S7.optional(LogLevelSchema),
3182
- colors: S7.optional(S7.Boolean)
3581
+ var ConsoleLoggerConfigSchema = S10.Struct({
3582
+ level: S10.optional(LogLevelSchema),
3583
+ colors: S10.optional(S10.Boolean)
3183
3584
  });
3184
- var FileLoggerConfigSchema = S7.Struct({
3185
- path: S7.optional(S7.String),
3186
- level: S7.optional(LogLevelSchema)
3585
+ var FileLoggerConfigSchema = S10.Struct({
3586
+ path: S10.optional(S10.String),
3587
+ level: S10.optional(LogLevelSchema)
3187
3588
  });
3188
3589
 
3189
3590
  // src/domain/schemas/program.ts
3190
3591
  init_esm_shims();
3191
- import { Schema as S8 } from "effect";
3192
- var ConsumerTypeSchema = S8.Literal("tui", "headless", "none");
3193
- var RunOptionsDataSchema = S8.Struct({
3592
+ import { Schema as S11 } from "effect";
3593
+ var ConsumerTypeSchema = S11.Literal("tui", "headless", "none");
3594
+ var RunOptionsDataSchema = S11.Struct({
3194
3595
  config: LoopConfigSchema,
3195
- consumer: S8.optional(ConsumerTypeSchema)
3596
+ consumer: S11.optional(ConsumerTypeSchema)
3196
3597
  });
3197
3598
 
3198
3599
  // src/domain/schemas/progress.ts
3199
3600
  init_esm_shims();
3200
- import { Schema as S9 } from "effect";
3201
- var ProgressActionSchema = S9.Literal(
3601
+ import { Schema as S12 } from "effect";
3602
+ var ProgressActionSchema = S12.Literal(
3202
3603
  "started",
3203
3604
  "completed",
3204
3605
  "failed",
3205
3606
  "learning"
3206
3607
  );
3207
- var ProgressEntrySchema = S9.Struct({
3208
- iteration: S9.Number,
3209
- timestamp: S9.String,
3210
- taskId: S9.String,
3608
+ var ProgressEntrySchema = S12.Struct({
3609
+ iteration: S12.Number,
3610
+ timestamp: S12.String,
3611
+ taskId: S12.String,
3211
3612
  action: ProgressActionSchema,
3212
- summary: S9.String,
3213
- learnings: S9.optional(S9.Array(S9.String)),
3214
- 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))
3215
3616
  });
3216
- var ProgressFileSchema = S9.Struct({
3217
- sessionId: S9.String,
3218
- createdAt: S9.String,
3219
- entries: S9.Array(ProgressEntrySchema)
3617
+ var ProgressFileSchema = S12.Struct({
3618
+ sessionId: S12.String,
3619
+ createdAt: S12.String,
3620
+ entries: S12.Array(ProgressEntrySchema)
3220
3621
  });
3221
- var decodeProgressEntry = S9.decodeUnknown(ProgressEntrySchema);
3222
- var decodeProgressFile = S9.decodeUnknown(ProgressFileSchema);
3622
+ var decodeProgressEntry = S12.decodeUnknown(ProgressEntrySchema);
3623
+ var decodeProgressFile = S12.decodeUnknown(ProgressFileSchema);
3223
3624
 
3224
3625
  // src/domain/schemas/session.ts
3225
3626
  init_esm_shims();
3226
- import { Schema as S10 } from "effect";
3227
- var SessionStatusSchema = S10.Literal(
3627
+ import { Schema as S13 } from "effect";
3628
+ var SessionStatusSchema = S13.Literal(
3228
3629
  "active",
3229
3630
  "completed",
3230
3631
  "failed",
3231
3632
  "paused"
3232
3633
  );
3233
- var SessionSchema = S10.Struct({
3234
- id: S10.String,
3235
- createdAt: S10.String,
3634
+ var SessionSchema = S13.Struct({
3635
+ id: S13.String,
3636
+ createdAt: S13.String,
3236
3637
  status: SessionStatusSchema,
3237
- originalTask: S10.String,
3238
- completedTasks: S10.Array(S10.String),
3239
- currentTaskId: S10.optional(S10.String),
3240
- worktreePath: S10.optional(S10.String),
3241
- 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)
3242
3645
  });
3243
- 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";
3244
3651
 
3245
3652
  // src/domain/schemas/signals.ts
3246
3653
  init_esm_shims();
3247
- import { Schema as S11 } from "effect";
3248
- 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);
3249
3656
  var TasksDefinedSignalSchema = taggedFromData2(
3250
3657
  "TasksDefined",
3251
3658
  TasksDefinedDataSchema
@@ -3278,8 +3685,8 @@ var CriterionFailedSignalSchema = taggedFromData2(
3278
3685
  "CriterionFailed",
3279
3686
  CriterionFailedDataSchema
3280
3687
  );
3281
- var CheckPassedSignalSchema = S11.TaggedStruct("CheckPassed", {});
3282
- var CheckFailedSignalSchema = S11.TaggedStruct("CheckFailed", {});
3688
+ var CheckPassedSignalSchema = S14.TaggedStruct("CheckPassed", {});
3689
+ var CheckFailedSignalSchema = S14.TaggedStruct("CheckFailed", {});
3283
3690
  var ReviewCompleteSignalSchema = taggedFromData2(
3284
3691
  "ReviewComplete",
3285
3692
  ReviewCompleteDataSchema
@@ -3288,23 +3695,30 @@ var TaskCompleteSignalSchema = taggedFromData2(
3288
3695
  "TaskComplete",
3289
3696
  TaskCompleteSignalDataSchema
3290
3697
  );
3291
- var LoopCompleteSignalSchema = S11.TaggedStruct("LoopComplete", {});
3292
- 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(
3293
3707
  "success",
3294
3708
  "failure",
3295
3709
  "optimization"
3296
3710
  );
3297
- var LearningSignalSchema = S11.TaggedStruct("Learning", {
3298
- content: S11.String,
3299
- category: S11.optional(LearningCategorySchema)
3711
+ var LearningSignalSchema = S14.TaggedStruct("Learning", {
3712
+ content: S14.String,
3713
+ category: S14.optional(LearningCategorySchema)
3300
3714
  });
3301
- var GuardrailSignalSchema = S11.TaggedStruct("Guardrail", {
3302
- pattern: S11.String,
3303
- sign: S11.String,
3304
- avoidance: S11.String,
3305
- 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")
3306
3720
  });
3307
- var SignalSchema = S11.Union(
3721
+ var SignalSchema = S14.Union(
3308
3722
  TasksDefinedSignalSchema,
3309
3723
  PhasesDefinedSignalSchema,
3310
3724
  CriteriaDefinedSignalSchema,
@@ -3319,26 +3733,133 @@ var SignalSchema = S11.Union(
3319
3733
  TaskCompleteSignalSchema,
3320
3734
  LoopCompleteSignalSchema,
3321
3735
  LearningSignalSchema,
3322
- GuardrailSignalSchema
3736
+ GuardrailSignalSchema,
3737
+ SessionNameDefinedSignalSchema
3323
3738
  );
3324
- var decodeSignal = S11.decodeUnknown(SignalSchema);
3325
- 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
+ }
3326
3847
 
3327
3848
  // src/domain/schemas/task-generation.ts
3328
3849
  init_esm_shims();
3329
- import { Schema as S12 } from "effect";
3330
- var GeneratedTaskStatusSchema = S12.Literal(
3850
+ import { Schema as S16 } from "effect";
3851
+ var GeneratedTaskStatusSchema = S16.Literal(
3331
3852
  "pending",
3332
3853
  "in_progress",
3333
3854
  "done",
3334
3855
  "failed"
3335
3856
  );
3336
- var GeneratedTaskSchema = S12.Struct({
3337
- id: S12.String,
3338
- title: S12.String,
3857
+ var GeneratedTaskSchema = S16.Struct({
3858
+ id: S16.String,
3859
+ title: S16.String,
3339
3860
  status: GeneratedTaskStatusSchema
3340
3861
  });
3341
- var GeneratedTaskListSchema = S12.Array(GeneratedTaskSchema);
3862
+ var GeneratedTaskListSchema = S16.Array(GeneratedTaskSchema);
3342
3863
  var STATUS_ICONS = {
3343
3864
  done: "[x]",
3344
3865
  in_progress: "[~]",
@@ -3397,15 +3918,15 @@ function parseTasksMd(content) {
3397
3918
 
3398
3919
  // src/domain/schemas/tui.ts
3399
3920
  init_esm_shims();
3400
- import { Schema as S13 } from "effect";
3401
- var ViewModeSchema = S13.Literal("logs", "tasks", "detail");
3402
- var LoopStatusSchema = S13.Literal(
3921
+ import { Schema as S17 } from "effect";
3922
+ var ViewModeSchema = S17.Literal("logs", "tasks", "detail");
3923
+ var LoopStatusSchema = S17.Literal(
3403
3924
  "idle",
3404
3925
  "running",
3405
3926
  "complete",
3406
3927
  "error"
3407
3928
  );
3408
- var ExecutionModeSchema = S13.Literal(
3929
+ var ExecutionModeSchema = S17.Literal(
3409
3930
  "idle",
3410
3931
  "discovery",
3411
3932
  "breakdown",
@@ -3415,73 +3936,73 @@ var ExecutionModeSchema = S13.Literal(
3415
3936
  "verifying",
3416
3937
  "reviewing"
3417
3938
  );
3418
- var TUIPhaseStatusSchema = S13.Literal(
3939
+ var TUIPhaseStatusSchema = S17.Literal(
3419
3940
  "pending",
3420
3941
  "in_progress",
3421
3942
  "done",
3422
3943
  "failed"
3423
3944
  );
3424
- var TUICriterionStatusSchema = S13.Literal(
3945
+ var TUICriterionStatusSchema = S17.Literal(
3425
3946
  "pending",
3426
3947
  "passed",
3427
3948
  "failed"
3428
3949
  );
3429
- var TUITaskStatusSchema = S13.Literal(
3950
+ var TUITaskStatusSchema = S17.Literal(
3430
3951
  "pending",
3431
3952
  "in_progress",
3432
3953
  "done",
3433
3954
  "failed"
3434
3955
  );
3435
- var TUIPhaseSchema = S13.Struct({
3436
- id: S13.String,
3437
- description: S13.String,
3956
+ var TUIPhaseSchema = S17.Struct({
3957
+ id: S17.String,
3958
+ description: S17.String,
3438
3959
  status: TUIPhaseStatusSchema,
3439
- startedAt: S13.optional(S13.Number),
3440
- completedAt: S13.optional(S13.Number)
3960
+ startedAt: S17.optional(S17.Number),
3961
+ completedAt: S17.optional(S17.Number)
3441
3962
  });
3442
- var TUICriterionSchema = S13.Struct({
3443
- id: S13.String,
3444
- description: S13.String,
3963
+ var TUICriterionSchema = S17.Struct({
3964
+ id: S17.String,
3965
+ description: S17.String,
3445
3966
  status: TUICriterionStatusSchema,
3446
- failureReason: S13.optional(S13.String)
3967
+ failureReason: S17.optional(S17.String)
3447
3968
  });
3448
- var TUITaskSchema = S13.Struct({
3449
- id: S13.String,
3450
- title: S13.String,
3969
+ var TUITaskSchema = S17.Struct({
3970
+ id: S17.String,
3971
+ title: S17.String,
3451
3972
  status: TUITaskStatusSchema,
3452
- phases: S13.Array(TUIPhaseSchema),
3453
- criteria: S13.Array(TUICriterionSchema),
3454
- startedAt: S13.optional(S13.Number),
3455
- 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)
3456
3977
  });
3457
- var TUIStateSchema = S13.Struct({
3978
+ var TUIStateSchema = S17.Struct({
3458
3979
  // Loop info
3459
- task: S13.String,
3460
- iteration: S13.Number,
3461
- maxIterations: S13.Number,
3980
+ task: S17.String,
3981
+ iteration: S17.Number,
3982
+ maxIterations: S17.Number,
3462
3983
  status: LoopStatusSchema,
3463
- startTime: S13.Number,
3984
+ startTime: S17.Number,
3464
3985
  // Discovery phase
3465
- discoveryInProgress: S13.Boolean,
3466
- discoveryCompleted: S13.Boolean,
3986
+ discoveryInProgress: S17.Boolean,
3987
+ discoveryCompleted: S17.Boolean,
3467
3988
  // Current activity
3468
3989
  executionMode: ExecutionModeSchema,
3469
- currentTool: S13.optional(S13.String),
3470
- currentTaskId: S13.optional(S13.String),
3990
+ currentTool: S17.optional(S17.String),
3991
+ currentTaskId: S17.optional(S17.String),
3471
3992
  // Output
3472
- outputLines: S13.Array(S13.String),
3473
- partialLine: S13.String,
3993
+ outputLines: S17.Array(S17.String),
3994
+ partialLine: S17.String,
3474
3995
  // Tasks
3475
- tasks: S13.Array(TUITaskSchema),
3996
+ tasks: S17.Array(TUITaskSchema),
3476
3997
  // Navigation
3477
3998
  viewMode: ViewModeSchema,
3478
- selectedTaskIndex: S13.Number,
3479
- scrollOffset: S13.Number,
3480
- userScrolled: S13.Boolean,
3999
+ selectedTaskIndex: S17.Number,
4000
+ scrollOffset: S17.Number,
4001
+ userScrolled: S17.Boolean,
3481
4002
  // Git
3482
- gitBranch: S13.optional(S13.String),
3483
- gitPushed: S13.Boolean,
3484
- prUrl: S13.optional(S13.String)
4003
+ gitBranch: S17.optional(S17.String),
4004
+ gitPushed: S17.Boolean,
4005
+ prUrl: S17.optional(S17.String)
3485
4006
  });
3486
4007
 
3487
4008
  // src/services/guardrails-store.ts
@@ -3687,7 +4208,7 @@ var MemoryGuardrails = {
3687
4208
 
3688
4209
  // src/layers/llm/mock.ts
3689
4210
  init_esm_shims();
3690
- 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";
3691
4212
 
3692
4213
  // src/services/llm.ts
3693
4214
  init_esm_shims();
@@ -3696,9 +4217,9 @@ var LLM = class extends Context3.Tag("@ferix/LLM")() {
3696
4217
  };
3697
4218
 
3698
4219
  // src/layers/llm/mock.ts
3699
- var MockLLMConfigSchema = S14.Struct({
3700
- events: S14.Array(LLMEventSchema),
3701
- delayMs: S14.optional(S14.Number)
4220
+ var MockLLMConfigSchema = S18.Struct({
4221
+ events: S18.Array(LLMEventSchema),
4222
+ delayMs: S18.optional(S18.Number)
3702
4223
  });
3703
4224
  function createMockLLM(config) {
3704
4225
  return {
@@ -3739,7 +4260,23 @@ import { Effect as Effect11 } from "effect";
3739
4260
 
3740
4261
  // src/layers/llm/types.ts
3741
4262
  init_esm_shims();
3742
- 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 = {
3743
4280
  claude: {
3744
4281
  name: "claude",
3745
4282
  cliCommand: "claude",
@@ -3768,6 +4305,17 @@ var PROVIDER_CONFIGS = {
3768
4305
  installUrl: "https://opencode.ai/docs/"
3769
4306
  }
3770
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();
3771
4319
 
3772
4320
  // src/layers/llm/providers/claude.ts
3773
4321
  init_esm_shims();
@@ -3813,78 +4361,57 @@ init_esm_shims();
3813
4361
 
3814
4362
  // src/layers/llm/providers/parsers/stream-json.ts
3815
4363
  init_esm_shims();
4364
+ import { Either as Either4 } from "effect";
3816
4365
  function parseJsonLine(line) {
3817
4366
  if (!line.startsWith("{")) {
3818
4367
  return null;
3819
4368
  }
3820
- try {
3821
- return JSON.parse(line);
3822
- } catch {
3823
- return null;
3824
- }
3825
- }
3826
- function isTextContent(json) {
3827
- return typeof json === "object" && json !== null && "type" in json && typeof json.type === "string";
3828
- }
3829
- function isToolUse(json) {
3830
- 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
+ );
3831
4372
  }
3832
4373
  function extractText(json) {
3833
- if (!isTextContent(json)) {
3834
- return null;
4374
+ if (isContentBlockDelta(json) && isTextDelta(json.delta)) {
4375
+ return json.delta.text;
3835
4376
  }
3836
- if (json.type === "content_block_delta") {
3837
- const delta = json;
3838
- if (delta.delta?.type === "text_delta" && delta.delta.text) {
3839
- return delta.delta.text;
3840
- }
3841
- }
3842
- if (json.type === "assistant" && json.message?.content) {
4377
+ if (isAssistantMessage(json)) {
3843
4378
  for (const block of json.message.content) {
3844
- if (block.type === "text" && block.text) {
4379
+ if (isTextContentBlock(block)) {
3845
4380
  return block.text;
3846
4381
  }
3847
4382
  }
3848
4383
  }
3849
4384
  return null;
3850
4385
  }
3851
- function isToolInputDelta(json) {
3852
- return typeof json === "object" && json !== null && "type" in json && json.type === "content_block_delta" && "delta" in json;
3853
- }
3854
4386
  function extractToolInfo(json) {
3855
- if (typeof json === "object" && json !== null && "type" in json && json.type === "content_block_stop") {
4387
+ if (isContentBlockStop(json)) {
3856
4388
  return {
3857
4389
  type: "end",
3858
4390
  name: "unknown"
3859
4391
  };
3860
4392
  }
3861
- if (!isToolUse(json)) {
3862
- if (isToolInputDelta(json) && json.delta?.type === "input_json_delta" && json.delta.partial_json) {
3863
- return {
3864
- type: "input_delta",
3865
- name: "",
3866
- partialJson: json.delta.partial_json
3867
- };
3868
- }
3869
- return null;
3870
- }
3871
- if (json.type === "content_block_start" && json.content_block?.type === "tool_use") {
4393
+ if (isContentBlockStart(json) && isToolUseContentBlock(json.content_block)) {
3872
4394
  return {
3873
4395
  type: "start",
3874
- 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
3875
4404
  };
3876
4405
  }
3877
4406
  return null;
3878
4407
  }
3879
4408
  function safeParseJson(jsonStr) {
3880
- try {
3881
- return JSON.parse(jsonStr);
3882
- } catch {
3883
- return null;
3884
- }
4409
+ return Either4.getOrNull(
4410
+ Either4.try({ try: () => JSON.parse(jsonStr), catch: () => null })
4411
+ );
3885
4412
  }
3886
4413
  function unwrapStreamEvent(json) {
3887
- if (typeof json === "object" && json !== null && "type" in json && json.type === "stream_event" && "event" in json) {
4414
+ if (isStreamEventEnvelope(json)) {
3888
4415
  return json.event;
3889
4416
  }
3890
4417
  return json;
@@ -4025,50 +4552,26 @@ init_esm_shims();
4025
4552
 
4026
4553
  // src/layers/llm/providers/parsers/opencode.ts
4027
4554
  init_esm_shims();
4555
+ import { Either as Either5 } from "effect";
4028
4556
  function parseJsonLine2(line) {
4029
4557
  if (!line.startsWith("{")) {
4030
4558
  return null;
4031
4559
  }
4032
- try {
4033
- return JSON.parse(line);
4034
- } catch {
4035
- return null;
4036
- }
4037
- }
4038
- function isTextContent2(json) {
4039
- 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
+ );
4040
4563
  }
4041
4564
  function isStepFinish(json) {
4042
- return typeof json === "object" && json !== null && "type" in json && json.type === "step_finish";
4043
- }
4044
- function isToolUse2(json) {
4045
- if (typeof json !== "object" || json === null) {
4046
- return false;
4047
- }
4048
- const obj = json;
4049
- if (obj.type !== "tool_use") {
4050
- return false;
4051
- }
4052
- if (typeof obj.part !== "object" || obj.part === null) {
4053
- return false;
4054
- }
4055
- const part = obj.part;
4056
- if (typeof part.tool !== "string") {
4057
- return false;
4058
- }
4059
- if (typeof part.state !== "object" || part.state === null) {
4060
- return false;
4061
- }
4062
- return true;
4565
+ return isOpenCodeStepFinish(json);
4063
4566
  }
4064
4567
  function extractText2(json) {
4065
- if (isTextContent2(json)) {
4568
+ if (isOpenCodeTextEvent(json)) {
4066
4569
  return json.text;
4067
4570
  }
4068
4571
  return null;
4069
4572
  }
4070
4573
  function extractToolInfo2(json) {
4071
- if (isToolUse2(json)) {
4574
+ if (isOpenCodeToolUseEvent(json)) {
4072
4575
  return {
4073
4576
  type: "complete",
4074
4577
  name: json.part.tool,
@@ -4833,7 +5336,7 @@ init_esm_shims();
4833
5336
 
4834
5337
  // src/layers/signal/specs/check.ts
4835
5338
  init_esm_shims();
4836
- import { Schema as S15 } from "effect";
5339
+ import { Either as Either6 } from "effect";
4837
5340
 
4838
5341
  // src/layers/signal/specs/registry.ts
4839
5342
  init_esm_shims();
@@ -4889,9 +5392,8 @@ var checkPassedSpec = {
4889
5392
  schema: CheckPassedSignalSchema,
4890
5393
  parse: (text) => {
4891
5394
  if (CHECK_PASSED.test(text)) {
4892
- const raw = { _tag: "CheckPassed" };
4893
- const result = S15.decodeUnknownEither(CheckPassedSignalSchema)(raw);
4894
- if (result._tag === "Right") {
5395
+ const result = createCheckPassedSignal({});
5396
+ if (Either6.isRight(result)) {
4895
5397
  return [result.right];
4896
5398
  }
4897
5399
  }
@@ -4905,9 +5407,8 @@ var checkFailedSpec = {
4905
5407
  schema: CheckFailedSignalSchema,
4906
5408
  parse: (text) => {
4907
5409
  if (CHECK_FAILED.test(text)) {
4908
- const raw = { _tag: "CheckFailed" };
4909
- const result = S15.decodeUnknownEither(CheckFailedSignalSchema)(raw);
4910
- if (result._tag === "Right") {
5410
+ const result = createCheckFailedSignal({});
5411
+ if (Either6.isRight(result)) {
4911
5412
  return [result.right];
4912
5413
  }
4913
5414
  }
@@ -4920,7 +5421,7 @@ signalSpecRegistry.register(checkFailedSpec);
4920
5421
 
4921
5422
  // src/layers/signal/specs/criteria.ts
4922
5423
  init_esm_shims();
4923
- import { Schema as S16 } from "effect";
5424
+ import { Either as Either7 } from "effect";
4924
5425
  var CRITERIA_BLOCK = /<ferix:criteria task="(\d+)">([\s\S]*?)<\/ferix:criteria>/g;
4925
5426
  var CRITERION = /<criterion id="([^"]+)">([^<]+)<\/criterion>/g;
4926
5427
  var CRITERION_PASSED = /<ferix:criterion-passed id="([\d.c]+)"\/>/g;
@@ -4946,13 +5447,11 @@ var criteriaDefinedSpec = {
4946
5447
  }
4947
5448
  }
4948
5449
  if (criteria.length > 0) {
4949
- const raw = {
4950
- _tag: "CriteriaDefined",
5450
+ const result = createCriteriaDefinedSignal({
4951
5451
  taskId: match[1],
4952
5452
  criteria
4953
- };
4954
- const result = S16.decodeUnknownEither(CriteriaDefinedSignalSchema)(raw);
4955
- if (result._tag === "Right") {
5453
+ });
5454
+ if (Either7.isRight(result)) {
4956
5455
  signals.push(result.right);
4957
5456
  }
4958
5457
  }
@@ -4969,9 +5468,8 @@ var criterionPassedSpec = {
4969
5468
  const signals = [];
4970
5469
  for (const m of text.matchAll(resetRegex(CRITERION_PASSED))) {
4971
5470
  if (m[1]) {
4972
- const raw = { _tag: "CriterionPassed", criterionId: m[1] };
4973
- const result = S16.decodeUnknownEither(CriterionPassedSignalSchema)(raw);
4974
- if (result._tag === "Right") {
5471
+ const result = createCriterionPassedSignal({ criterionId: m[1] });
5472
+ if (Either7.isRight(result)) {
4975
5473
  signals.push(result.right);
4976
5474
  }
4977
5475
  }
@@ -4988,13 +5486,11 @@ var criterionFailedSpec = {
4988
5486
  const signals = [];
4989
5487
  for (const m of text.matchAll(resetRegex(CRITERION_FAILED))) {
4990
5488
  if (m[1]) {
4991
- const raw = {
4992
- _tag: "CriterionFailed",
5489
+ const result = createCriterionFailedSignal({
4993
5490
  criterionId: m[1],
4994
5491
  reason: m[2] || "Unknown reason"
4995
- };
4996
- const result = S16.decodeUnknownEither(CriterionFailedSignalSchema)(raw);
4997
- if (result._tag === "Right") {
5492
+ });
5493
+ if (Either7.isRight(result)) {
4998
5494
  signals.push(result.right);
4999
5495
  }
5000
5496
  }
@@ -5009,7 +5505,7 @@ signalSpecRegistry.register(criterionFailedSpec);
5009
5505
 
5010
5506
  // src/layers/signal/specs/guardrail.ts
5011
5507
  init_esm_shims();
5012
- import { Schema as S17 } from "effect";
5508
+ import { Either as Either8 } from "effect";
5013
5509
  var GUARDRAIL = /<ferix:guardrail\s+severity="(warning|critical)"\s*>([\s\S]*?)<\/ferix:guardrail>/g;
5014
5510
  var PATTERN = /<pattern>([\s\S]*?)<\/pattern>/;
5015
5511
  var SIGN = /<sign>([\s\S]*?)<\/sign>/;
@@ -5033,15 +5529,13 @@ var guardrailSpec = {
5033
5529
  if (!(pattern && sign && avoidance)) {
5034
5530
  continue;
5035
5531
  }
5036
- const raw = {
5037
- _tag: "Guardrail",
5532
+ const result = createGuardrailSignal({
5038
5533
  pattern,
5039
5534
  sign,
5040
5535
  avoidance,
5041
5536
  severity
5042
- };
5043
- const result = S17.decodeUnknownEither(GuardrailSignalSchema)(raw);
5044
- if (result._tag === "Right") {
5537
+ });
5538
+ if (Either8.isRight(result)) {
5045
5539
  signals.push(result.right);
5046
5540
  }
5047
5541
  }
@@ -5053,7 +5547,7 @@ signalSpecRegistry.register(guardrailSpec);
5053
5547
 
5054
5548
  // src/layers/signal/specs/learning.ts
5055
5549
  init_esm_shims();
5056
- import { Schema as S18 } from "effect";
5550
+ import { Either as Either9 } from "effect";
5057
5551
  var LEARNING = /<ferix:learning(?:\s+category="(success|failure|optimization)")?\s*>([\s\S]*?)<\/ferix:learning>/g;
5058
5552
  var learningSpec = {
5059
5553
  tag: "Learning",
@@ -5068,15 +5562,8 @@ var learningSpec = {
5068
5562
  if (!content) {
5069
5563
  continue;
5070
5564
  }
5071
- const raw = {
5072
- _tag: "Learning",
5073
- content
5074
- };
5075
- if (category) {
5076
- raw.category = category;
5077
- }
5078
- const result = S18.decodeUnknownEither(LearningSignalSchema)(raw);
5079
- if (result._tag === "Right") {
5565
+ const result = createLearningSignal({ content, category });
5566
+ if (Either9.isRight(result)) {
5080
5567
  signals.push(result.right);
5081
5568
  }
5082
5569
  }
@@ -5088,7 +5575,7 @@ signalSpecRegistry.register(learningSpec);
5088
5575
 
5089
5576
  // src/layers/signal/specs/loop-complete.ts
5090
5577
  init_esm_shims();
5091
- import { Schema as S19 } from "effect";
5578
+ import { Schema as S20 } from "effect";
5092
5579
  var LOOP_COMPLETE = /<ferix:complete>/;
5093
5580
  var loopCompleteSpec = {
5094
5581
  tag: "LoopComplete",
@@ -5097,7 +5584,7 @@ var loopCompleteSpec = {
5097
5584
  parse: (text) => {
5098
5585
  if (LOOP_COMPLETE.test(text)) {
5099
5586
  const raw = { _tag: "LoopComplete" };
5100
- const result = S19.decodeUnknownEither(LoopCompleteSignalSchema)(raw);
5587
+ const result = S20.decodeUnknownEither(LoopCompleteSignalSchema)(raw);
5101
5588
  if (result._tag === "Right") {
5102
5589
  return [result.right];
5103
5590
  }
@@ -5110,7 +5597,7 @@ signalSpecRegistry.register(loopCompleteSpec);
5110
5597
 
5111
5598
  // src/layers/signal/specs/phases.ts
5112
5599
  init_esm_shims();
5113
- import { Schema as S20 } from "effect";
5600
+ import { Either as Either10 } from "effect";
5114
5601
  var PHASES_BLOCK = /<ferix:phases task="(\d+)">([\s\S]*?)<\/ferix:phases>/;
5115
5602
  var PHASE = /<phase id="([\d.]+)">([^<]+)<\/phase>/g;
5116
5603
  var PHASE_START = /<ferix:phase-start id="([\d.]+)"\/>/g;
@@ -5138,16 +5625,11 @@ var phasesDefinedSpec = {
5138
5625
  if (phases.length === 0) {
5139
5626
  return [];
5140
5627
  }
5141
- const raw = {
5142
- _tag: "PhasesDefined",
5143
- taskId: match[1],
5144
- phases
5145
- };
5146
- const result = S20.decodeUnknownEither(PhasesDefinedSignalSchema)(raw);
5147
- if (result._tag === "Left") {
5148
- return [];
5628
+ const result = createPhasesDefinedSignal({ taskId: match[1], phases });
5629
+ if (Either10.isRight(result)) {
5630
+ return [result.right];
5149
5631
  }
5150
- return [result.right];
5632
+ return [];
5151
5633
  },
5152
5634
  keyFields: (s) => `${s.taskId}:${s.phases.map((p) => p.id).join(",")}`
5153
5635
  };
@@ -5159,9 +5641,8 @@ var phaseStartedSpec = {
5159
5641
  const signals = [];
5160
5642
  for (const m of text.matchAll(resetRegex2(PHASE_START))) {
5161
5643
  if (m[1]) {
5162
- const raw = { _tag: "PhaseStarted", phaseId: m[1] };
5163
- const result = S20.decodeUnknownEither(PhaseStartedSignalSchema)(raw);
5164
- if (result._tag === "Right") {
5644
+ const result = createPhaseStartedSignal({ phaseId: m[1] });
5645
+ if (Either10.isRight(result)) {
5165
5646
  signals.push(result.right);
5166
5647
  }
5167
5648
  }
@@ -5178,9 +5659,8 @@ var phaseCompletedSpec = {
5178
5659
  const signals = [];
5179
5660
  for (const m of text.matchAll(resetRegex2(PHASE_DONE))) {
5180
5661
  if (m[1]) {
5181
- const raw = { _tag: "PhaseCompleted", phaseId: m[1] };
5182
- const result = S20.decodeUnknownEither(PhaseCompletedSignalSchema)(raw);
5183
- if (result._tag === "Right") {
5662
+ const result = createPhaseCompletedSignal({ phaseId: m[1] });
5663
+ if (Either10.isRight(result)) {
5184
5664
  signals.push(result.right);
5185
5665
  }
5186
5666
  }
@@ -5197,13 +5677,11 @@ var phaseFailedSpec = {
5197
5677
  const signals = [];
5198
5678
  for (const m of text.matchAll(resetRegex2(PHASE_FAILED))) {
5199
5679
  if (m[1]) {
5200
- const raw = {
5201
- _tag: "PhaseFailed",
5680
+ const result = createPhaseFailedSignal({
5202
5681
  phaseId: m[1],
5203
5682
  reason: m[2] || "Unknown reason"
5204
- };
5205
- const result = S20.decodeUnknownEither(PhaseFailedSignalSchema)(raw);
5206
- if (result._tag === "Right") {
5683
+ });
5684
+ if (Either10.isRight(result)) {
5207
5685
  signals.push(result.right);
5208
5686
  }
5209
5687
  }
@@ -5242,6 +5720,37 @@ var reviewCompleteSpec = {
5242
5720
  };
5243
5721
  signalSpecRegistry.register(reviewCompleteSpec);
5244
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
+
5245
5754
  // src/layers/signal/specs/task-complete.ts
5246
5755
  init_esm_shims();
5247
5756
  import { Schema as S22 } from "effect";
@@ -5287,7 +5796,7 @@ signalSpecRegistry.register(taskCompleteSpec);
5287
5796
 
5288
5797
  // src/layers/signal/specs/tasks.ts
5289
5798
  init_esm_shims();
5290
- import { Schema as S23 } from "effect";
5799
+ import { Either as Either12 } from "effect";
5291
5800
  var TASKS_BLOCK = /<ferix:tasks>([\s\S]*?)<\/ferix:tasks>/;
5292
5801
  var TASK = /<task id="(\d+)">([^<]+)<\/task>/g;
5293
5802
  function resetRegex3(pattern) {
@@ -5316,12 +5825,11 @@ var tasksDefinedSpec = {
5316
5825
  if (tasks.length === 0) {
5317
5826
  return [];
5318
5827
  }
5319
- const raw = { _tag: "TasksDefined", tasks };
5320
- const result = S23.decodeUnknownEither(TasksDefinedSignalSchema)(raw);
5321
- if (result._tag === "Left") {
5322
- return [];
5828
+ const result = createTasksDefinedSignal({ tasks });
5829
+ if (Either12.isRight(result)) {
5830
+ return [result.right];
5323
5831
  }
5324
- return [result.right];
5832
+ return [];
5325
5833
  },
5326
5834
  keyFields: (s) => s.tasks.map((t) => t.id).join(",")
5327
5835
  };
@@ -5638,6 +6146,16 @@ eventMappingRegistry.registerSignalMapper({
5638
6146
  timestamp: context.timestamp
5639
6147
  })
5640
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
+ });
5641
6159
 
5642
6160
  // src/orchestrator/mapping/index.ts
5643
6161
  function mapLLMEventToDomain(event, context) {
@@ -6074,19 +6592,44 @@ After completing a single task, emit <ferix:task-complete> and continue to the n
6074
6592
  IMPORTANT: Always emit signals on their own lines, never inside markdown code blocks.`;
6075
6593
  var DISCOVERY_SYSTEM_PROMPT = `You are in the DISCOVERY phase of a ralph loop - an iterative AI coding workflow.
6076
6594
 
6077
- 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
6078
6598
 
6079
- Your output must include a <ferix:tasks> signal that the orchestrator will parse.
6080
- 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.
6081
6601
 
6082
6602
  ## Signal Format
6083
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)
6084
6614
  <ferix:tasks>
6085
6615
  <task id="1">Brief description of first task</task>
6086
6616
  <task id="2">Brief description of second task</task>
6087
6617
  </ferix:tasks>
6088
6618
 
6089
- 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.`;
6090
6633
  var DEFAULT_PLANNING_PROMPT = `## Phase 2: PLANNING
6091
6634
 
6092
6635
  If no phases are defined for the current task, define them now.
@@ -6205,17 +6748,26 @@ ${config.prompts.additionalContext}`
6205
6748
  ${config.task}`);
6206
6749
  sections.push(`## Instructions
6207
6750
 
6208
- 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>
6209
6756
 
6210
- 1. Read and understand what needs to be done
6211
- 2. Identify the main components or steps
6212
- 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>
6213
6761
 
6214
- Emit a <ferix:tasks> block with your task breakdown.
6215
6762
  Each task should be:
6216
6763
  - Self-contained and independently verifiable
6217
6764
  - Clear and specific
6218
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.
6219
6771
 
6220
6772
  Begin your analysis now.`);
6221
6773
  return sections.join("\n\n");
@@ -6328,7 +6880,7 @@ function planTasksToGeneratedTasks(plan) {
6328
6880
  status: mapTaskStatus(task.status)
6329
6881
  }));
6330
6882
  }
6331
- function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, config, sessionId, worktreePath) {
6883
+ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, config, sessionId, worktreePath, onSessionName) {
6332
6884
  return Stream7.unwrap(
6333
6885
  Effect21.gen(function* () {
6334
6886
  const startTimeUtc = yield* DateTime8.now;
@@ -6337,6 +6889,7 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6337
6889
  dirty: false,
6338
6890
  pendingOperation: null
6339
6891
  });
6892
+ const sessionNameRef = yield* Ref10.make(void 0);
6340
6893
  const discoveryStarted = {
6341
6894
  _tag: "DiscoveryStarted",
6342
6895
  timestamp: startTime
@@ -6369,6 +6922,9 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6369
6922
  );
6370
6923
  const events = [...result.events];
6371
6924
  for (const signal of result.signals) {
6925
+ if (signal._tag === "SessionNameDefined") {
6926
+ yield* Ref10.set(sessionNameRef, signal.name);
6927
+ }
6372
6928
  const planEvents = yield* updatePlanFromSignal(
6373
6929
  currentPlanRef,
6374
6930
  persistenceStateRef,
@@ -6415,12 +6971,38 @@ function createDiscoveryStream(llm, signalParser, planStore, currentPlanRef, con
6415
6971
  }
6416
6972
  const endTimeUtc = yield* DateTime8.now;
6417
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
+ }
6418
6999
  const discoveryCompleted = {
6419
7000
  _tag: "DiscoveryCompleted",
6420
7001
  taskCount,
6421
7002
  timestamp: endTime
6422
7003
  };
6423
- return [...persistEvents, discoveryCompleted];
7004
+ events.push(discoveryCompleted);
7005
+ return events;
6424
7006
  })
6425
7007
  ).pipe(Stream7.flatMap((events) => Stream7.fromIterable(events)));
6426
7008
  return pipe(
@@ -6634,12 +7216,27 @@ function runLoop(config) {
6634
7216
  };
6635
7217
  const loopCompletedRef = yield* Ref12.make(false);
6636
7218
  const currentPlanRef = yield* Ref12.make(void 0);
7219
+ const sessionRef = yield* Ref12.make(session);
6637
7220
  const maxIterations = config.maxIterations === 0 ? Number.POSITIVE_INFINITY : config.maxIterations;
6638
7221
  const loopStarted = {
6639
7222
  _tag: "LoopStarted",
6640
7223
  config,
6641
7224
  timestamp: startTime
6642
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
+ });
6643
7240
  const discoveryStream = createDiscoveryStream(
6644
7241
  llm,
6645
7242
  signalParser,
@@ -6647,7 +7244,8 @@ function runLoop(config) {
6647
7244
  currentPlanRef,
6648
7245
  config,
6649
7246
  session.id,
6650
- worktreePath
7247
+ worktreePath,
7248
+ handleSessionName
6651
7249
  );
6652
7250
  const iterationsStream = Stream9.unfoldEffect(
6653
7251
  1,
@@ -6709,7 +7307,8 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6709
7307
  return Stream9.unwrap(
6710
7308
  Effect23.gen(function* () {
6711
7309
  const endTimeUtc = yield* DateTime10.now;
6712
- const durationMs = DateTime10.toEpochMillis(endTimeUtc) - startTime;
7310
+ const endTime = DateTime10.toEpochMillis(endTimeUtc);
7311
+ const durationMs = endTime - startTime;
6713
7312
  const completed = yield* Ref12.get(loopCompletedRef);
6714
7313
  yield* git.commitChanges(session.id, `feat: complete session ${session.id}`).pipe(
6715
7314
  Effect23.tapError(
@@ -6720,6 +7319,20 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6720
7319
  ),
6721
7320
  Effect23.orElseSucceed(() => void 0)
6722
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
+ };
6723
7336
  const summary = {
6724
7337
  iterations: config.maxIterations,
6725
7338
  success: completed,
@@ -6729,7 +7342,8 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6729
7342
  };
6730
7343
  yield* sessionStore.update(session.id, {
6731
7344
  ...session,
6732
- status: completed ? "completed" : "paused"
7345
+ status: completed ? "completed" : "paused",
7346
+ worktreePath: void 0
6733
7347
  }).pipe(
6734
7348
  Effect23.tapError(
6735
7349
  (error) => Effect23.logDebug("Session update failed, continuing", {
@@ -6740,7 +7354,10 @@ function createCompletionStream(sessionStore, git, session, config, startTime, l
6740
7354
  Effect23.orElseSucceed(() => void 0)
6741
7355
  );
6742
7356
  const loopCompleted = { _tag: "LoopCompleted", summary };
6743
- return Stream9.succeed(loopCompleted);
7357
+ return pipe3(
7358
+ Stream9.succeed(worktreeRemoved),
7359
+ Stream9.concat(Stream9.succeed(loopCompleted))
7360
+ );
6744
7361
  })
6745
7362
  );
6746
7363
  }
@@ -6800,13 +7417,21 @@ program.name("ferix-code").description("Composable RALPH loops for AI coding age
6800
7417
  });
6801
7418
  program.parse();
6802
7419
  export {
7420
+ AnyToolInputSchema,
7421
+ AssistantMessageSchema,
7422
+ BashToolInputSchema,
6803
7423
  CheckFailedEventSchema,
6804
7424
  CheckFailedSignalSchema,
6805
7425
  CheckPassedEventSchema,
6806
7426
  CheckPassedSignalSchema,
6807
7427
  ClaudeCLI,
7428
+ ClaudeCliEventSchema,
6808
7429
  ConsoleLoggerConfigSchema,
6809
7430
  ConsumerTypeSchema,
7431
+ ContentBlockDeltaSchema,
7432
+ ContentBlockSchema,
7433
+ ContentBlockStartSchema,
7434
+ ContentBlockStopSchema,
6810
7435
  CriteriaDefinedDataSchema,
6811
7436
  CriteriaDefinedEventSchema,
6812
7437
  CriteriaDefinedSignalSchema,
@@ -6820,11 +7445,13 @@ export {
6820
7445
  CriterionSchema,
6821
7446
  CriterionStatusSchema,
6822
7447
  CursorCLI,
7448
+ DeltaSchema,
6823
7449
  DiscoveryCompletedEventSchema,
6824
7450
  DiscoveryStartedEventSchema,
6825
7451
  DomainEventSchema,
6826
7452
  DomainEventUtils,
6827
7453
  DoneEventSchema,
7454
+ EditToolInputSchema,
6828
7455
  ExecutionModeSchema,
6829
7456
  FerixParser,
6830
7457
  FileLoggerConfigSchema,
@@ -6838,6 +7465,8 @@ export {
6838
7465
  GeneratedTaskStatusSchema,
6839
7466
  Git,
6840
7467
  GitError,
7468
+ GlobToolInputSchema,
7469
+ GrepToolInputSchema,
6841
7470
  GuardrailAddedEventSchema,
6842
7471
  GuardrailSchema,
6843
7472
  GuardrailSeveritySchema,
@@ -6845,6 +7474,7 @@ export {
6845
7474
  GuardrailsFileSchema,
6846
7475
  GuardrailsStore,
6847
7476
  GuardrailsStoreError,
7477
+ InputJsonDeltaSchema,
6848
7478
  IterationCompletedEventSchema,
6849
7479
  IterationStartedEventSchema,
6850
7480
  LLM,
@@ -6874,6 +7504,16 @@ export {
6874
7504
  MemorySession,
6875
7505
  Mock,
6876
7506
  Mock as MockLLM,
7507
+ OpenCodeCliEventSchema,
7508
+ OpenCodeCostSchema,
7509
+ OpenCodeStepFinishSchema,
7510
+ OpenCodeStepPartSchema,
7511
+ OpenCodeStepStartSchema,
7512
+ OpenCodeTextEventSchema,
7513
+ OpenCodeTokensSchema,
7514
+ OpenCodeToolPartSchema,
7515
+ OpenCodeToolStateSchema,
7516
+ OpenCodeToolUseEventSchema,
6877
7517
  OrchestratorError,
6878
7518
  PROVIDER_CONFIGS,
6879
7519
  ParseError,
@@ -6909,16 +7549,20 @@ export {
6909
7549
  ProgressUpdatedEventSchema,
6910
7550
  PromptConfigSchema,
6911
7551
  ProviderNameSchema,
7552
+ ReadToolInputSchema,
6912
7553
  ReviewCompleteDataSchema,
6913
7554
  ReviewCompleteEventSchema,
6914
7555
  ReviewCompleteSignalSchema,
6915
7556
  RunOptionsDataSchema,
7557
+ SessionNameDefinedSignalSchema,
7558
+ SessionNameGeneratedEventSchema,
6916
7559
  SessionSchema,
6917
7560
  SessionStatusSchema,
6918
7561
  SessionStore,
6919
7562
  SessionStoreError,
6920
7563
  SignalParser,
6921
7564
  SignalSchema,
7565
+ StreamEventEnvelopeSchema,
6922
7566
  TUICriterionSchema,
6923
7567
  TUICriterionStatusSchema,
6924
7568
  TUIPhaseSchema,
@@ -6933,28 +7577,57 @@ export {
6933
7577
  TaskCompletedEventSchema,
6934
7578
  TaskSchema,
6935
7579
  TaskStatusSchema,
7580
+ TaskToolInputSchema,
6936
7581
  TasksDefinedDataSchema,
6937
7582
  TasksDefinedEventSchema,
6938
7583
  TasksDefinedSignalSchema,
6939
7584
  TestLayers,
7585
+ TextContentBlockSchema,
7586
+ TextDeltaSchema,
6940
7587
  TextEventSchema,
6941
7588
  ToolEndEventSchema,
7589
+ ToolInputSchemaRegistry,
6942
7590
  ToolStartEventSchema,
7591
+ ToolUseContentBlockSchema,
6943
7592
  ToolUseEventSchema,
7593
+ ValidatedToolUseEventSchema,
6944
7594
  ViewModeSchema,
7595
+ WebFetchToolInputSchema,
7596
+ WebSearchToolInputSchema,
6945
7597
  WorktreeCreatedEventSchema,
6946
7598
  WorktreeRemovedEventSchema,
7599
+ WriteToolInputSchema,
6947
7600
  buildPrompt,
6948
7601
  collectEvents,
7602
+ createCheckFailedSignal,
7603
+ createCheckPassedSignal,
7604
+ createCriteriaDefinedSignal,
7605
+ createCriterionFailedSignal,
7606
+ createCriterionPassedSignal,
7607
+ createGuardrailSignal,
6949
7608
  createHeadlessConsumer,
7609
+ createLearningSignal,
7610
+ createLoopCompleteSignal,
7611
+ createPhaseCompletedSignal,
7612
+ createPhaseFailedSignal,
7613
+ createPhaseStartedSignal,
7614
+ createPhasesDefinedSignal,
6950
7615
  createProductionLayers,
6951
7616
  createProviderLayer2 as createProviderLayer,
7617
+ createReviewCompleteSignal,
7618
+ createSessionNameDefinedSignal,
6952
7619
  createTUIConsumer,
7620
+ createTaskCompleteSignal,
7621
+ createTasksDefinedSignal,
6953
7622
  createTestLayers,
7623
+ decodeClaudeCliEvent,
7624
+ decodeClaudeCliEventSync,
6954
7625
  decodeGuardrail,
6955
7626
  decodeGuardrailsFile,
6956
7627
  decodeLLMEvent,
6957
7628
  decodeLoopConfig,
7629
+ decodeOpenCodeCliEvent,
7630
+ decodeOpenCodeCliEventSync,
6958
7631
  decodePlan,
6959
7632
  decodePlanData,
6960
7633
  decodeProgressEntry,
@@ -6963,9 +7636,34 @@ export {
6963
7636
  decodeSignal,
6964
7637
  decodeSignalSync,
6965
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,
6966
7662
  main,
6967
7663
  parseTasksMd,
6968
7664
  run,
6969
7665
  runLoop,
6970
- runTest
7666
+ runTest,
7667
+ validateToolInput,
7668
+ validateToolUseEvent
6971
7669
  };