Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cfa540c066 | |||
| 13241aae25 | |||
| 2c346ee2b8 | |||
| fa5de69358 | |||
| a54770d606 |
+2
-1
@@ -1,4 +1,4 @@
|
|||||||
// auto-generated by elc --emit-header — do not edit
|
// auto-generated by elc --emit-header - do not edit
|
||||||
extern fn idle_count() -> Int
|
extern fn idle_count() -> Int
|
||||||
extern fn idle_inc() -> Int
|
extern fn idle_inc() -> Int
|
||||||
extern fn idle_reset() -> Void
|
extern fn idle_reset() -> Void
|
||||||
@@ -7,6 +7,7 @@ extern fn elapsed_ms() -> Int
|
|||||||
extern fn elapsed_human() -> String
|
extern fn elapsed_human() -> String
|
||||||
extern fn embed_ok() -> Int
|
extern fn embed_ok() -> Int
|
||||||
extern fn emit_heartbeat() -> Void
|
extern fn emit_heartbeat() -> Void
|
||||||
|
extern fn auto_term_try_slot(slot_type: String, slot_lbl: String) -> Void
|
||||||
extern fn proactive_curiosity() -> Bool
|
extern fn proactive_curiosity() -> Bool
|
||||||
extern fn pulse_count() -> Int
|
extern fn pulse_count() -> Int
|
||||||
extern fn pulse_inc() -> Int
|
extern fn pulse_inc() -> Int
|
||||||
|
|||||||
@@ -1680,8 +1680,16 @@ fn dispatch_tool(tool_name: String, tool_input: String) -> String {
|
|||||||
if !path_within_root(path, root) {
|
if !path_within_root(path, root) {
|
||||||
return json_safe("denied: path is outside the agent workspace root")
|
return json_safe("denied: path is outside the agent workspace root")
|
||||||
}
|
}
|
||||||
fs_write(resolve_in_root(path, root), content)
|
// BUG-6 fix (2026-07-17): never claim ok without disk truth. fs_write's result was
|
||||||
return json_safe("{\"ok\":true}")
|
// never checked, so a failed write reported ok — the exact false-receipt failure
|
||||||
|
// the run guards exist to kill. Verify the file landed and return the RESOLVED
|
||||||
|
// path so callers and the model can only narrate what is really on disk.
|
||||||
|
let dest: String = resolve_in_root(path, root)
|
||||||
|
fs_write(dest, content)
|
||||||
|
if !fs_exists(dest) {
|
||||||
|
return json_safe("{\"error\":\"write failed - nothing landed at " + dest + "\"}")
|
||||||
|
}
|
||||||
|
return json_safe("{\"ok\":true,\"path\":\"" + dest + "\"}")
|
||||||
}
|
}
|
||||||
if str_eq(tool_name, "web_get") {
|
if str_eq(tool_name, "web_get") {
|
||||||
let url: String = json_get(tool_input, "url")
|
let url: String = json_get(tool_input, "url")
|
||||||
@@ -1935,8 +1943,24 @@ fn handle_chat_agentic(body: String) -> String {
|
|||||||
// no root (or cleared the field), and we must not overwrite a server-configured root
|
// no root (or cleared the field), and we must not overwrite a server-configured root
|
||||||
// from NEURON_AGENT_ROOT with an empty string, which would silently un-scope the agent.
|
// from NEURON_AGENT_ROOT with an empty string, which would silently un-scope the agent.
|
||||||
let ws_root: String = json_get(body, "agent_workspace_root")
|
let ws_root: String = json_get(body, "agent_workspace_root")
|
||||||
|
// BUG-LEAK fix (2026-07-16): the root used to live ONLY in the shared key, so any
|
||||||
|
// request that omitted it INHERITED the previous session's folder (proven: a rootless
|
||||||
|
// curl session wrote into another session's run folder). Now each session keeps its
|
||||||
|
// own copy, and every request RE-ASSERTS its own root (possibly empty) into the shared
|
||||||
|
// key the tool guards read — no session can ever act under another session's root.
|
||||||
|
// Empty state still falls through to env NEURON_AGENT_ROOT inside
|
||||||
|
// agent_workspace_root(), so a server-configured root survives unchanged.
|
||||||
|
// LIMITATION (for review): assumes serialized request handling; true per-call scoping
|
||||||
|
// means threading session_id through dispatch_tool/classify — deeper change, Will's call.
|
||||||
|
let sess_for_root: String = json_get(body, "session_id")
|
||||||
if !str_eq(ws_root, "") {
|
if !str_eq(ws_root, "") {
|
||||||
|
if !str_eq(sess_for_root, "") {
|
||||||
|
state_set("agent_workspace_root_" + sess_for_root, ws_root)
|
||||||
|
}
|
||||||
state_set("agent_workspace_root", ws_root)
|
state_set("agent_workspace_root", ws_root)
|
||||||
|
} else {
|
||||||
|
let own_root: String = if str_eq(sess_for_root, "") { "" } else { state_get("agent_workspace_root_" + sess_for_root) }
|
||||||
|
state_set("agent_workspace_root", own_root)
|
||||||
}
|
}
|
||||||
|
|
||||||
// L1 safety screen — agentic path must pass the same gate as layered_cycle.
|
// L1 safety screen — agentic path must pass the same gate as layered_cycle.
|
||||||
@@ -2066,6 +2090,14 @@ fn handle_chat_agentic(body: String) -> String {
|
|||||||
|
|
||||||
// Use caller-supplied session_id if provided, otherwise generate a bridge id.
|
// Use caller-supplied session_id if provided, otherwise generate a bridge id.
|
||||||
let session_id: String = if str_eq(req_session, "") { next_bridge_id() } else { req_session }
|
let session_id: String = if str_eq(req_session, "") { next_bridge_id() } else { req_session }
|
||||||
|
// PAUSE-CONTRACT fix (2026-07-16): honor the client's require_approval field — the
|
||||||
|
// Phase 1c contract ("the soul pauses on EVERY tool; the client's tier gate decides
|
||||||
|
// what actually prompts") was never implemented engine-side, which made the client's
|
||||||
|
// Ask autonomy silently inert for builtin sub-escalate tools. Persisted per session
|
||||||
|
// (set/reset on every request) so the /approve resume path keeps the same behavior
|
||||||
|
// for the rest of the run. Absent/false = behavior identical to before this fix.
|
||||||
|
let req_ask_all: String = json_get(body, "require_approval")
|
||||||
|
state_set("require_approval_" + session_id, if str_eq(req_ask_all, "true") { "true" } else { "" })
|
||||||
// Provider fork: OpenAI-compatible providers (Ollama/OpenAI/Grok/Gemini) take the plain-completion
|
// Provider fork: OpenAI-compatible providers (Ollama/OpenAI/Grok/Gemini) take the plain-completion
|
||||||
// path (v1, no tools); everything else stays on the Anthropic agentic loop (the default).
|
// path (v1, no tools); everything else stays on the Anthropic agentic loop (the default).
|
||||||
let use_openai: Bool = !str_eq(llm_base_url(), "") && str_eq(llm_wire_format(), "openai")
|
let use_openai: Bool = !str_eq(llm_base_url(), "") && str_eq(llm_wire_format(), "openai")
|
||||||
@@ -2126,6 +2158,12 @@ fn handle_chat_agentic(body: String) -> String {
|
|||||||
fn agentic_loop(session_id: String, model: String, safe_sys: String, tools_json: String, messages_in: String, h: Map, tools_log_in: String) -> String {
|
fn agentic_loop(session_id: String, model: String, safe_sys: String, tools_json: String, messages_in: String, h: Map, tools_log_in: String) -> String {
|
||||||
let api_url: String = "https://api.anthropic.com/v1/messages"
|
let api_url: String = "https://api.anthropic.com/v1/messages"
|
||||||
|
|
||||||
|
// PAUSE-CONTRACT fix (2026-07-16): when the client asked to approve every action
|
||||||
|
// (require_approval on the request, persisted per session), EVERY tool turn bridges —
|
||||||
|
// the client's tier gate decides what actually prompts vs auto-continues. Read from
|
||||||
|
// session state so the /approve resume re-entry keeps the same behavior mid-run.
|
||||||
|
let ask_all: Bool = !str_eq(session_id, "") && str_eq(state_get("require_approval_" + session_id), "true")
|
||||||
|
|
||||||
let messages: String = messages_in
|
let messages: String = messages_in
|
||||||
let final_text: String = ""
|
let final_text: String = ""
|
||||||
let tools_log: String = tools_log_in
|
let tools_log: String = tools_log_in
|
||||||
@@ -2212,7 +2250,10 @@ fn agentic_loop(session_id: String, model: String, safe_sys: String, tools_json:
|
|||||||
// confirm). Escalated calls suspend to the client's consent flow; the
|
// confirm). Escalated calls suspend to the client's consent flow; the
|
||||||
// /approve round-trip is the only path that executes them.
|
// /approve round-trip is the only path that executes them.
|
||||||
let risk_tier: String = if is_tool_turn { classify_tool_risk(tool_name, tool_input) } else { "" }
|
let risk_tier: String = if is_tool_turn { classify_tool_risk(tool_name, tool_input) } else { "" }
|
||||||
let needs_bridge: Bool = is_tool_turn && (str_eq(risk_tier, "escalate") || (!is_builtin_tool(tool_name) && !is_always_allowed))
|
// PAUSE-CONTRACT fix (2026-07-16): ask_all bridges EVERYTHING — stricter only.
|
||||||
|
// Escalate keeps its unconditional bridge; "always allow" shortcuts never apply
|
||||||
|
// under ask_all (the client owns its own standing grants at its tier gate).
|
||||||
|
let needs_bridge: Bool = is_tool_turn && (ask_all || str_eq(risk_tier, "escalate") || (!is_builtin_tool(tool_name) && !is_always_allowed))
|
||||||
|
|
||||||
// Built-in tools dispatch locally; bridged tools yield "" (never sent upstream).
|
// Built-in tools dispatch locally; bridged tools yield "" (never sent upstream).
|
||||||
let tool_result_raw: String = if is_tool_turn && !needs_bridge { dispatch_tool(tool_name, tool_input) } else { "" }
|
let tool_result_raw: String = if is_tool_turn && !needs_bridge { dispatch_tool(tool_name, tool_input) } else { "" }
|
||||||
@@ -2352,6 +2393,10 @@ fn agentic_resume(session_id: String, tool_use_id: String, content: String) -> S
|
|||||||
if str_eq(blob, "") {
|
if str_eq(blob, "") {
|
||||||
return "{\"error\":\"unknown session_id\",\"reply\":\"\"}"
|
return "{\"error\":\"unknown session_id\",\"reply\":\"\"}"
|
||||||
}
|
}
|
||||||
|
// BUG-LEAK fix (2026-07-16): re-assert THIS session's own workspace root before the
|
||||||
|
// loop continues — a resume must never run under whatever root the last unrelated
|
||||||
|
// request happened to leave in the shared key.
|
||||||
|
state_set("agent_workspace_root", state_get("agent_workspace_root_" + session_id))
|
||||||
|
|
||||||
let model: String = json_get(blob, "model")
|
let model: String = json_get(blob, "model")
|
||||||
let safe_sys: String = json_get(blob, "safe_sys")
|
let safe_sys: String = json_get(blob, "safe_sys")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// auto-generated by elc --emit-header — do not edit
|
// auto-generated by elc --emit-header - do not edit
|
||||||
extern fn chat_default_model() -> String
|
extern fn chat_default_model() -> String
|
||||||
extern fn engram_numeric_valid(s: String) -> Bool
|
extern fn engram_numeric_valid(s: String) -> Bool
|
||||||
extern fn parse_float_x100(s: String) -> Int
|
extern fn parse_float_x100(s: String) -> Int
|
||||||
@@ -17,7 +17,9 @@ extern fn id_in_seen(node_id: String, seen: String) -> Bool
|
|||||||
extern fn add_to_seen(seen: String, node_id: String) -> String
|
extern fn add_to_seen(seen: String, node_id: String) -> String
|
||||||
extern fn engram_extract_ids(nodes_json: String) -> String
|
extern fn engram_extract_ids(nodes_json: String) -> String
|
||||||
extern fn engram_compile(intent: String) -> String
|
extern fn engram_compile(intent: String) -> String
|
||||||
|
extern fn distill_transcript(transcript: String) -> String
|
||||||
extern fn json_safe(s: String) -> String
|
extern fn json_safe(s: String) -> String
|
||||||
|
extern fn current_engine_note(model: String) -> String
|
||||||
extern fn build_system_prompt(ctx: String, chat_mode: Bool) -> String
|
extern fn build_system_prompt(ctx: String, chat_mode: Bool) -> String
|
||||||
extern fn hist_append(hist: String, role: String, content: String) -> String
|
extern fn hist_append(hist: String, role: String, content: String) -> String
|
||||||
extern fn hist_trim(hist: String) -> String
|
extern fn hist_trim(hist: String) -> String
|
||||||
@@ -26,10 +28,15 @@ extern fn clean_llm_response(s: String) -> String
|
|||||||
extern fn conv_history_persist(hist: String) -> Void
|
extern fn conv_history_persist(hist: String) -> Void
|
||||||
extern fn conv_history_load() -> String
|
extern fn conv_history_load() -> String
|
||||||
extern fn session_preload_bullets(nodes: String, max_bullets: Int, snip_len: Int) -> String
|
extern fn session_preload_bullets(nodes: String, max_bullets: Int, snip_len: Int) -> String
|
||||||
|
extern fn affective_context_prefix() -> String
|
||||||
extern fn handle_chat(body: String) -> String
|
extern fn handle_chat(body: String) -> String
|
||||||
extern fn handle_see(body: String) -> String
|
extern fn handle_see(body: String) -> String
|
||||||
extern fn studio_tools_json() -> String
|
extern fn studio_tools_json() -> String
|
||||||
extern fn agentic_api_key() -> String
|
extern fn agentic_api_key() -> String
|
||||||
|
extern fn llm_base_url() -> String
|
||||||
|
extern fn llm_wire_format() -> String
|
||||||
|
extern fn json_escape(s: String) -> String
|
||||||
|
extern fn openai_chat_complete(model: String, base_url: String, api_key: String, safe_sys: String, messages_json: String) -> String
|
||||||
extern fn agentic_tools_literal() -> String
|
extern fn agentic_tools_literal() -> String
|
||||||
extern fn agentic_tools_with_web() -> String
|
extern fn agentic_tools_with_web() -> String
|
||||||
extern fn connector_tools_json() -> String
|
extern fn connector_tools_json() -> String
|
||||||
@@ -40,6 +47,10 @@ extern fn call_neuron_mcp(tool_name: String, args: String) -> String
|
|||||||
extern fn agent_workspace_root() -> String
|
extern fn agent_workspace_root() -> String
|
||||||
extern fn path_within_root(path: String, root: String) -> Bool
|
extern fn path_within_root(path: String, root: String) -> Bool
|
||||||
extern fn resolve_in_root(path: String, root: String) -> String
|
extern fn resolve_in_root(path: String, root: String) -> String
|
||||||
|
extern fn run_command_is_readonly(cmd: String) -> Bool
|
||||||
|
extern fn cmd_abs_escape_at(cmd: String, root: String, needle: String) -> Bool
|
||||||
|
extern fn run_command_guard(cmd: String, root: String) -> String
|
||||||
|
extern fn classify_tool_risk(tool_name: String, tool_input: String) -> String
|
||||||
extern fn dispatch_tool(tool_name: String, tool_input: String) -> String
|
extern fn dispatch_tool(tool_name: String, tool_input: String) -> String
|
||||||
extern fn is_builtin_tool(tool_name: String) -> Bool
|
extern fn is_builtin_tool(tool_name: String) -> Bool
|
||||||
extern fn next_bridge_id() -> String
|
extern fn next_bridge_id() -> String
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Narrated runs — engine notes for Will (2026-07-13)
|
||||||
|
|
||||||
|
Source half: commit aa67f86 on feat/agent-phase1-soul (run-progress ledger,
|
||||||
|
`/api/run-progress/<sid>` route, narration on the pause envelope, config display
|
||||||
|
default). E2E-verified via the compiled test bed on Tim's clean profile.
|
||||||
|
|
||||||
|
Compiled-form-only fixes (in `neuron-container-build/soul-narrated-runs-20260713.patch`,
|
||||||
|
applies ON TOP of `soul-webfix-20260711.patch` — these need porting to chat.el when the
|
||||||
|
webfix itself is ported):
|
||||||
|
|
||||||
|
1. **pause_turn + tool_use interleave**: a pause_turn response can ALSO carry a client
|
||||||
|
tool_use; resuming verbatim leaves it unpaired → Anthropic 400 "tool_use ids were
|
||||||
|
found without tool_result". Fix: tool-bearing pause rounds are tool turns
|
||||||
|
(dispatch + pair); verbatim resume only when the round has no client tool.
|
||||||
|
2. **Agentic toolset scope**: agentic_tools_all() fed EVERY connector/MCP tool (Notion,
|
||||||
|
code-execution…) into the loop. Code-execution flips the API into programmatic
|
||||||
|
tool calling, whose pairing protocol the single-tool manual loop does not speak —
|
||||||
|
source of the dangling-pair 400s AND the bash_code_execution workspace-dodge.
|
||||||
|
Fix: handle_chat_agentic declares builtins + ONE server web_search only.
|
||||||
|
Connector tools return when the loop gains real multi-tool/programmatic support.
|
||||||
|
3. **disable_parallel_tool_use: true** on agentic requests — the loop captures only the
|
||||||
|
first tool_use per round; Opus-class models parallel-call. Enforce the invariant.
|
||||||
|
4. **web_search server-tool default variant → web_search_20250305 (GA)**. The 20260209
|
||||||
|
variant couples to code-execution ⇒ programmatic mode (see #2, and the June note:
|
||||||
|
"inert unless code-execution attached").
|
||||||
|
5. **Homegrown web_search removed** from the tool catalog (server-side is the one tool).
|
||||||
|
|
||||||
|
Known engine debts this work surfaced (not fixed):
|
||||||
|
|
||||||
|
- **Poisoned session history**: a failed run persists the malformed assistant turn; every
|
||||||
|
later turn in that session replays it and 400s. Needs history sanitation on load.
|
||||||
|
- **Huge-history invalid-escape 400** (~346KB request) — likely the same poisoned blob.
|
||||||
|
- **macOS note**: replacing a binary in place invalidates its ad-hoc signature (instant
|
||||||
|
silent SIGKILL, looks like exit 0). `rm + cp + codesign -f -s -` is the swap ritual.
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// auto-generated by elc --emit-header — do not edit
|
// auto-generated by elc --emit-header - do not edit
|
||||||
extern fn imprint_current() -> String
|
extern fn imprint_current() -> String
|
||||||
extern fn imprint_load(imprint_id: String) -> String
|
extern fn imprint_load(imprint_id: String) -> String
|
||||||
extern fn imprint_respond(input: String, imprint_id: String) -> String
|
extern fn imprint_respond(input: String, imprint_id: String) -> String
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// auto-generated by elc --emit-header — do not edit
|
// auto-generated by elc --emit-header - do not edit
|
||||||
extern fn is_protected_node(id: String) -> Bool
|
extern fn is_protected_node(id: String) -> Bool
|
||||||
extern fn api_err_protected(id: String) -> String
|
extern fn api_err_protected(id: String) -> String
|
||||||
extern fn api_json_escape(s: String) -> String
|
extern fn api_json_escape(s: String) -> String
|
||||||
|
|||||||
+1
-10
@@ -1,4 +1,4 @@
|
|||||||
// auto-generated by elc --emit-header — do not edit
|
// auto-generated by elc --emit-header - do not edit
|
||||||
extern fn soft_bell_threshold() -> Int
|
extern fn soft_bell_threshold() -> Int
|
||||||
extern fn hard_bell_threshold() -> Int
|
extern fn hard_bell_threshold() -> Int
|
||||||
extern fn safety_score_crisis(input: String) -> Int
|
extern fn safety_score_crisis(input: String) -> Int
|
||||||
@@ -13,12 +13,3 @@ extern fn safety_self_harm_phrases() -> String
|
|||||||
extern fn safety_abuse_phrases() -> String
|
extern fn safety_abuse_phrases() -> String
|
||||||
extern fn safety_general_hard_phrases() -> String
|
extern fn safety_general_hard_phrases() -> String
|
||||||
extern fn safety_soft_phrases() -> String
|
extern fn safety_soft_phrases() -> String
|
||||||
extern fn safety_detect_positive_level(message: String) -> String
|
|
||||||
extern fn safety_detect_bell_level(message: String) -> String
|
|
||||||
extern fn safety_classify_hard_bell(message: String) -> String
|
|
||||||
extern fn safety_soft_directive() -> String
|
|
||||||
extern fn safety_hard_directive(hard_type: String) -> String
|
|
||||||
extern fn safety_augment_system(system: String, user_msg: String) -> String
|
|
||||||
extern fn safety_contact_path() -> String
|
|
||||||
extern fn handle_safety_contact_get() -> String
|
|
||||||
extern fn handle_safety_contact_post(body: String) -> String
|
|
||||||
|
|||||||
+12
-1
@@ -677,6 +677,11 @@ fn handle_session_approve(session_id: String, body: String) -> String {
|
|||||||
// path for all sessions created through handle_chat_agentic / agentic_loop.
|
// path for all sessions created through handle_chat_agentic / agentic_loop.
|
||||||
let bridge_blob: String = state_get("mcp_bridge:" + session_id)
|
let bridge_blob: String = state_get("mcp_bridge:" + session_id)
|
||||||
if !str_eq(bridge_blob, "") {
|
if !str_eq(bridge_blob, "") {
|
||||||
|
// BUG-LEAK fix (2026-07-16): the approved tool executes below via dispatch_tool,
|
||||||
|
// whose path/command guards read the shared workspace-root key. Re-assert THIS
|
||||||
|
// session's own root first — an approval must never execute under whatever root
|
||||||
|
// the last unrelated request left behind.
|
||||||
|
state_set("agent_workspace_root", state_get("agent_workspace_root_" + session_id))
|
||||||
// For "always": record tool_name in the always-allow list before resuming.
|
// For "always": record tool_name in the always-allow list before resuming.
|
||||||
// The tool_name is not stored in the bridge blob (only tool_use_id is).
|
// The tool_name is not stored in the bridge blob (only tool_use_id is).
|
||||||
// Accept it from the body so the client can pass it along.
|
// Accept it from the body so the client can pass it along.
|
||||||
@@ -708,7 +713,13 @@ fn handle_session_approve(session_id: String, body: String) -> String {
|
|||||||
// For builtin tools with no client-provided content: fall back to
|
// For builtin tools with no client-provided content: fall back to
|
||||||
// dispatch_tool so those tools still execute correctly.
|
// dispatch_tool so those tools still execute correctly.
|
||||||
let client_content: String = json_get(body, "content")
|
let client_content: String = json_get(body, "content")
|
||||||
let use_client_content: Bool = !str_eq(client_content, "")
|
// BUG-6 fix (2026-07-17): the naive json_get scanner matches "content" ANYWHERE
|
||||||
|
// in the body — including INSIDE tool_input — so every approved write_file (whose
|
||||||
|
// input always carries a content field) was mistaken for client-executed, never
|
||||||
|
// dispatched, and narrated as done: a false receipt with no file on disk. Builtin
|
||||||
|
// tools now ALWAYS dispatch server-side; client content is only honored for
|
||||||
|
// non-builtin (MCP/client-executed) tools. Stricter only.
|
||||||
|
let use_client_content: Bool = !str_eq(client_content, "") && !is_builtin_tool(approve_tool_name)
|
||||||
let use_dispatch: Bool = is_builtin_tool(approve_tool_name) && !use_client_content
|
let use_dispatch: Bool = is_builtin_tool(approve_tool_name) && !use_client_content
|
||||||
let raw_input: String = json_get_raw(body, "tool_input")
|
let raw_input: String = json_get_raw(body, "tool_input")
|
||||||
let eff_input: String = if str_eq(raw_input, "") { "{}" } else { raw_input }
|
let eff_input: String = if str_eq(raw_input, "") { "{}" } else { raw_input }
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ extern fn session_list() -> String
|
|||||||
extern fn session_get(session_id: String) -> String
|
extern fn session_get(session_id: String) -> String
|
||||||
extern fn session_delete(session_id: String) -> String
|
extern fn session_delete(session_id: String) -> String
|
||||||
extern fn session_update_patch(session_id: String, body: String) -> String
|
extern fn session_update_patch(session_id: String, body: String) -> String
|
||||||
|
extern fn session_search_entry(node: String) -> String
|
||||||
extern fn session_search(query: String) -> String
|
extern fn session_search(query: String) -> String
|
||||||
extern fn session_hist_load(session_id: String) -> String
|
extern fn session_hist_load(session_id: String) -> String
|
||||||
extern fn session_hist_save(session_id: String, hist: String) -> Void
|
extern fn session_hist_save(session_id: String, hist: String) -> Void
|
||||||
|
|||||||
+3
-7
@@ -1,15 +1,11 @@
|
|||||||
// stewardship.elh — Layer 2 public surface
|
// auto-generated by elc --emit-header - do not edit
|
||||||
// auto-generated by elc --emit-header — do not edit
|
extern fn steward_log_event(kind: String, detail: String) -> Void
|
||||||
extern fn steward_get_mission() -> String
|
extern fn steward_get_mission() -> String
|
||||||
extern fn steward_align(input: String, imprint_id: String) -> String
|
extern fn steward_align(input: String, imprint_id: String) -> String
|
||||||
extern fn steward_validate_imprint(imprint_id: String, tool_name: String) -> String
|
extern fn steward_validate_imprint(imprint_id: String, tool_name: String) -> String
|
||||||
extern fn steward_cgi_check(action: String) -> String
|
extern fn steward_cgi_check(action: String) -> String
|
||||||
// steward_log_event is an internal helper exported here because El has no access modifiers.
|
|
||||||
// External callers have no business invoking this directly — use steward_align,
|
|
||||||
// steward_validate_imprint, or steward_cgi_check, which call it at the correct points.
|
|
||||||
extern fn steward_log_event(kind: String, detail: String) -> Void
|
|
||||||
// Behavioral profiling and continuity detection (Layer 2 — session fingerprinting).
|
|
||||||
extern fn steward_fingerprint_session(input: String, session_id: String) -> String
|
extern fn steward_fingerprint_session(input: String, session_id: String) -> String
|
||||||
|
extern fn extract_dim(content: String, key: String) -> String
|
||||||
extern fn steward_build_baseline() -> String
|
extern fn steward_build_baseline() -> String
|
||||||
extern fn steward_check_continuity(current_fingerprint: String, session_id: String) -> String
|
extern fn steward_check_continuity(current_fingerprint: String, session_id: String) -> String
|
||||||
extern fn steward_session_check(input: String, session_id: String) -> String
|
extern fn steward_session_check(input: String, session_id: String) -> String
|
||||||
|
|||||||
Reference in New Issue
Block a user