From e4780483ad8d9fe7cb41f676f689f1cee496e59e Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Sun, 17 May 2026 08:17:53 +0000 Subject: [PATCH] executor: extract_task_lines for Phase 10 preplan parsing Pure function parallel to extract_cmd_lines, but more permissive to accommodate cloud-model output variation: tolerates leading whitespace (cloud often indents), tolerates extra whitespace after the colon, strips trailing whitespace. Strict on the literal "TASK:" prefix. Returns an array of trimmed strings; empty TASKs and non-TASK lines dropped silently. Callers cap the list size per cfg.norris.tasks_max. 10 inline unit cases verified: empty/nil, single TASK, mixed CMD+TASK (only TASKs returned), leading whitespace tolerated, empty-body TASKs dropped, trailing whitespace stripped, extra-spaces-after-colon AND no-space-after-colon both tolerated, prose interleaving (3 TASKs extracted from a realistic cloud response with intro+outro prose), TASK content with embedded quotes/punctuation preserved. Nothing in the tree calls this yet (Phase 10 C1 is the foundation commit; C4 lights it up). No regression. Co-Authored-By: Claude Opus 4.7 (1M context) --- executor.lua | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/executor.lua b/executor.lua index 10c6b28..76927e2 100644 --- a/executor.lua +++ b/executor.lua @@ -166,4 +166,25 @@ function M.extract_delegate_lines(text) return out end +-- Phase 10 / #89: extract `TASK: ` lines from a cloud +-- preplanner's response. Wire contract for the planning/executor +-- split: cloud emits a list of imperative TASKs once per :norris +-- launch, local model executes each. +-- +-- More permissive than extract_cmd_lines: tolerates leading +-- whitespace (cloud models often indent) AND leading whitespace +-- after the colon, AND strips trailing whitespace. Strict only on +-- the literal "TASK:" prefix. +-- +-- Returns an array of strings (already trimmed); empty TASKs and +-- non-TASK lines are dropped silently. +function M.extract_task_lines(text) + local out = {} + for line in (text or ""):gmatch("[^\n]+") do + local task = line:match("^%s*TASK:%s*(.-)%s*$") + if task and task:match("%S") then out[#out + 1] = task end + end + return out +end + return M