repl: Norris driver + \C-n + :norris/:safety meta (Phase 3 commit #5)
Phase 3 commit #5 per docs/PHASE3.md §12. Wires safety.norris_step (commit #4) into the REPL with the user-facing surface. ffi/readline.lua extensions (A1 + R-C4): - rl_insert_text + rl_redisplay added to ffi.cdef block; M.insert_text and M.redisplay wrappers exposed. - M.bind: removed `:free()` on previous callback. Now keeps every bound callback pinned for process lifetime in `_pinned` list (alongside `_bound[seq]` for current lookup). Avoids the use-after-free window between unbind and rebind that R-C4 flagged. Memory cost is bounded — one closure per key sequence binding. context.lua Norris suffix (R-C3 / §8): - to_messages() composes a dynamic NORRIS MODE block onto the system prompt when ctx.norris_active is set. The block carries ctx.norris_goal so eviction of the user's "[norris] goal:" turn doesn't lose the anchor. Returns to plain system prompt when Norris exits. repl.lua Norris driver: - prompt() now shows ⚡ marker when ctx.norris_active per PHASE0.md §9. - \C-n bound to a real handler — inserts ":norris " at the cursor (replaces Phase 1 status placeholder). - run_norris(goal) function: sets norris_active + norris_goal, appends a "[norris] <goal>" user turn, renders the banner, then loops calling safety.norris_step with an injected helpers table until a terminal status returns. Renders the closing banner. - norris_halt(): the [N] proceed/skip/abort prompt called by safety.norris_step via helpers.halt. Empty input → abort (safe). - dispatch_tool(): factored from the Phase 2 ask_ai code so safety.norris_step can call it. - norris_exec(): factored exec path for autonomous mode (skips the interactive run_shell cd-status renderer). - :norris <goal> meta — launches autonomous mode - :norris off meta — drops Norris flag (rare; usually 'abort') - :safety patterns meta — lists active is_destructive rules - :safety check <cmd> meta — probes a hypothetical command End-to-end mock-driven test: Submitted ":norris find files in /tmp" → banner → step 1 emits tool_call (auto_approved per policy) → dispatched → frame rendered → step 2 emits "GOAL: complete" → sub-loop exits → DONE banner. 2 broker invocations, no stalls. config.lua safety example block lands in commit #6. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+33
-1
@@ -136,8 +136,40 @@ end
|
||||
-- model (user → assistant → user → assistant), no strict-template breakage.
|
||||
--
|
||||
-- The system prompt is NOT stored in self.turns per §6.
|
||||
-- Phase 3: NORRIS MODE suffix appended to the system prompt when
|
||||
-- self.norris_active. Carries self.norris_goal so eviction of the
|
||||
-- user's "[norris] goal: ..." turn doesn't lose the anchor.
|
||||
local NORRIS_SUFFIX_TEMPLATE = [[
|
||||
|
||||
|
||||
[NORRIS MODE] You are operating autonomously toward the following goal:
|
||||
|
||||
%s
|
||||
|
||||
Plan and execute step by step using CMD: lines (for shell) or tool_calls
|
||||
(when MCP tools are available). After each action, you will see its
|
||||
result in the next turn. Re-plan based on what you observe.
|
||||
|
||||
When the goal is achieved, emit a single line:
|
||||
GOAL: complete
|
||||
on its own line, optionally followed by a brief summary.
|
||||
|
||||
If the goal is unreachable or you need user input, emit:
|
||||
GOAL: blocked
|
||||
with a one-line reason.
|
||||
|
||||
Avoid destructive operations unless the goal explicitly requires them.
|
||||
The user will be prompted to confirm destructive actions; expect their
|
||||
verdict in the next turn as a synthesized "[aish] ... skipped by user"
|
||||
message if they declined.]]
|
||||
|
||||
function Context:to_messages()
|
||||
local msgs = { { role = "system", content = self.system_prompt } }
|
||||
local sys_content = self.system_prompt
|
||||
if self.norris_active and self.norris_goal then
|
||||
sys_content = sys_content
|
||||
.. string.format(NORRIS_SUFFIX_TEMPLATE, self.norris_goal)
|
||||
end
|
||||
local msgs = { { role = "system", content = sys_content } }
|
||||
|
||||
if self.use_tool_role then
|
||||
for _, t in ipairs(self.turns) do
|
||||
|
||||
Reference in New Issue
Block a user