Add basic version: SemIf decision engine, urgency queue, skill tree, skill loop, decision log, dream pass, CLI

This commit is contained in:
semif-agent
2026-09-23 03:01:45 -05:00
commit 4e0e0534c4
21 changed files with 1629 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
"""The skill execution loop: observe -> predict -> act -> observe -> assess.
Every SemIf decision made during a run is logged as a training row; the
assessment outcome is kept on the row so the dream pass can weigh failed runs.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from .decisions import Request
from .llm import Assessment, LLMClient
from .log import DecisionLog
from .skills import ActionContext, Prediction, Skill
@dataclass
class RunResult:
skill: str
success: bool
summary: str
action_log: str
new_state: str
updated_request: str | None = None
decisions_logged: int = 0
error: str | None = None
class SkillRunner:
def __init__(self, ctx: ActionContext, llm: LLMClient, log: DecisionLog):
self.ctx = ctx
self.llm = llm
self.log = log
def run(self, skill: Skill, request: Request) -> RunResult:
baseline = request.text
try:
prediction = skill.predict(self.ctx, request) if skill.predict else Prediction(text="")
action = skill.act(self.ctx, request, prediction)
observed = action.new_state
assessment: Assessment = self.llm.assess(skill.name, baseline, action.action_log)
except Exception as exc:
return RunResult(
skill=skill.name,
success=False,
summary="",
action_log="",
new_state=baseline,
error=str(exc),
)
run_ok = assessment.success
decisions = getattr(prediction, "decisions", [])
for decision, result in decisions:
self.log.append(decision, result, extra={"skill": skill.name, "run_ok": run_ok})
return RunResult(
skill=skill.name,
success=assessment.success,
summary=assessment.summary,
action_log=action.action_log,
new_state=observed,
updated_request=assessment.updated_request,
decisions_logged=len(decisions),
)