Skip to content

Commit 1beeedf

Browse files
Kasper Jungeclaude
authored andcommitted
refactor: extract context-running from _assemble_prompt into visible loop phase
_assemble_prompt previously ran context subprocesses (I/O) as a hidden side effect, making it misleading — the name says "assemble" but it actually executed shell commands. Now the loop has a clear _run_contexts_phase step (mirroring _run_checks_phase) and _assemble_prompt is pure text assembly with no subprocess I/O. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8cda815 commit 1beeedf

File tree

1 file changed

+45
-15
lines changed

1 file changed

+45
-15
lines changed

src/ralphify/engine.py

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@
2424
format_check_failures,
2525
run_all_checks,
2626
)
27-
from ralphify.contexts import Context, discover_contexts, resolve_contexts, run_all_contexts
27+
from ralphify.contexts import (
28+
Context,
29+
ContextResult,
30+
discover_contexts,
31+
resolve_contexts,
32+
run_all_contexts,
33+
)
2834
from ralphify._frontmatter import parse_frontmatter
2935
from ralphify.instructions import Instruction, discover_instructions, resolve_instructions
3036

@@ -215,33 +221,48 @@ def _handle_loop_transitions(
215221
return True, primitives
216222

217223

224+
def _run_contexts_phase(
225+
contexts: list[Context],
226+
project_root: Path,
227+
state: RunState,
228+
emitter: EventEmitter,
229+
) -> list[ContextResult]:
230+
"""Execute all contexts and emit the resolved event.
231+
232+
Mirrors :func:`_run_checks_phase` — the loop has a clear context-running
233+
phase separate from the text-only prompt assembly step.
234+
"""
235+
results = run_all_contexts(contexts, project_root)
236+
emitter.emit(Event(
237+
type=EventType.CONTEXTS_RESOLVED,
238+
run_id=state.run_id,
239+
data={"iteration": state.iteration, "count": len(contexts)},
240+
))
241+
return results
242+
243+
218244
def _assemble_prompt(
219245
config: RunConfig,
220246
primitives: EnabledPrimitives,
247+
context_results: list[ContextResult],
221248
check_failures_text: str,
222249
state: RunState,
223250
emitter: EventEmitter,
224251
) -> str:
225-
"""Build the full prompt for one iteration.
252+
"""Build the full prompt for one iteration (text assembly only).
226253
227-
Reads the prompt source, resolves contexts and instructions, and
228-
appends any check-failure feedback from the previous iteration.
254+
Reads the prompt source, resolves pre-computed context results and
255+
instructions, and appends any check-failure feedback from the previous
256+
iteration. All subprocess I/O happens in the caller before this
257+
function is reached.
229258
"""
230-
iteration = state.iteration
231-
232259
if config.prompt_text:
233260
prompt = config.prompt_text
234261
else:
235262
raw = Path(config.prompt_file).read_text()
236263
_, prompt = parse_frontmatter(raw)
237-
if primitives.contexts:
238-
context_results = run_all_contexts(primitives.contexts, config.project_root)
264+
if context_results:
239265
prompt = resolve_contexts(prompt, context_results)
240-
emitter.emit(Event(
241-
type=EventType.CONTEXTS_RESOLVED,
242-
run_id=state.run_id,
243-
data={"iteration": iteration, "count": len(primitives.contexts)},
244-
))
245266
if primitives.instructions:
246267
prompt = resolve_instructions(prompt, primitives.instructions)
247268
if check_failures_text:
@@ -250,7 +271,7 @@ def _assemble_prompt(
250271
emitter.emit(Event(
251272
type=EventType.PROMPT_ASSEMBLED,
252273
run_id=state.run_id,
253-
data={"iteration": iteration, "prompt_length": len(prompt)},
274+
data={"iteration": state.iteration, "prompt_length": len(prompt)},
254275
))
255276
return prompt
256277

@@ -439,8 +460,17 @@ def run_loop(
439460
data={"iteration": iteration},
440461
))
441462

463+
# Run contexts phase (subprocess I/O)
464+
context_results: list[ContextResult] = []
465+
if primitives.contexts:
466+
context_results = _run_contexts_phase(
467+
primitives.contexts, config.project_root, state, emitter,
468+
)
469+
470+
# Assemble prompt (text resolution only)
442471
prompt = _assemble_prompt(
443-
config, primitives, check_failures_text, state, emitter,
472+
config, primitives, context_results, check_failures_text,
473+
state, emitter,
444474
)
445475

446476
returncode = _execute_agent(

0 commit comments

Comments
 (0)