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) <noreply@anthropic.com>
This commit is contained in:
2026-05-17 08:17:53 +00:00
parent cbef05ff40
commit e4780483ad
+21
View File
@@ -166,4 +166,25 @@ function M.extract_delegate_lines(text)
return out return out
end end
-- Phase 10 / #89: extract `TASK: <imperative>` 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 return M