symfonic.core.learning.procedural_extractor¶
procedural_extractor ¶
Moved to :mod:symfonic.capabilities.memory.phases.drafts.
The draft a procedural extractor returns, and the protocol it answers to, are the seam phase 12 consumes -- so they live with the phase, in the capability, and are imported back here for the shipped extractor and its tests to keep using.
ProceduralKind
module-attribute
¶
Allowed values for ProceduralDraft.kind.
The four-way split tracks the failure modes adopter identified in their
deep-dive (symfonic-core-ask-llm-procedural-extractor.md):
action— repeated tool usage that should become a learned habit.preflight— pre-flight check that prevents downstream failure ("before X, call Y"). The most load-bearing kind for v7.6 since the regex extractor structurally cannot represent it.recovery— error-recovery rule ("after E, call R").guardrail— negative rule ("never X — use Y instead").
VALID_PROCEDURAL_KINDS
module-attribute
¶
VALID_PROCEDURAL_KINDS: frozenset[str] = frozenset({'action', 'preflight', 'recovery', 'guardrail'})
Runtime mirror of :data:ProceduralKind for response-shape validation.
The Literal type is gone at runtime so the LLM-response parser uses this
frozenset to clamp unknown kinds back to "action" (the most benign
default — a noisy action draft surfaces to human review, a fabricated
preflight rule could hide a real precondition gap).
ProceduralDraft
dataclass
¶
ProceduralDraft(kind: ProceduralKind, trigger: str, action: str, rationale: str, confidence: float = 0.0, precondition: str | list[str] | None = None, source_episode_ids: list[str] = list())
Structured draft produced by a :class:ProceduralExtractor.
Frozen so the dispatch site can pass instances around without
worrying about downstream mutation. Defaults match the LLM prompt's
nullable / optional fields so a minimal response can still
construct a valid draft (only kind, trigger, action,
and rationale are strictly required).
precondition shape (v7.6.3 -- adopter multi-precondition ask):
None-- no pre-flight gate.str-- single pre-flight rule (v7.6.0 byte-identical shape; preserved so consumers thatisinstance(p, str)still match the common case).list[str]-- ordered multi-pre-flight rule. Mirrors the v7.6.2 storage widening on :meth:~symfonic.memory.layers.procedural.layer.ProceduralLayer.seed_authored_skill, so LLM-extracted drafts and hand-authored skills share one storage shape. The v7.5.1 :class:~symfonic.memory.layers.procedural.router.CapabilityRouterrenders one indentedPRE-FLIGHT:line per entry in supplied order.
ProceduralExtractor ¶
Bases: Protocol
Pluggable Phase 12 extractor interface.
Implementations MUST be best-effort: a malformed response, a missing
field, or an exception during model invocation must yield []
rather than raise. The dispatch site logs the empty result via the
standard Phase 12 telemetry line so consumers can tell "extractor
found nothing" from "extractor crashed" via the cost_usd /
llm_calls fields.
draft_to_memory_entry ¶
Convert a :class:ProceduralDraft to a procedural MemoryEntry.
Moved here with the draft it reads. Phase 12's two extractors -- the regex
one and the model-backed one -- write through one store_skill contract,
and the phase is on a roster the kernel composes, so the conversion cannot
live in the legacy package the concrete LLM adapter stays in.
Used by the Phase 12 dispatch site in
:func:promote_episodic_to_procedural so the LLM and regex paths
share the same store_skill write contract. The draft's
structured fields land in the entry metadata under stable keys so
the v7.5 query_skills projection surfaces them:
precondition->properties['precondition'](v7.5)source->"phase_12_llm_extractor"(distinct from the regex extractor's"phase_12_promotion"so SRE telemetry can split adoption).kind/confidence/rationale/trigger/source_episode_idsare first-class properties for v7.7+ router enrichment.
The label field follows the v6.1 "Auto-learned: <name>"
convention so downstream label-prefix grouping (e.g. SemanticMerge
similarity, /procedures listing UI) keeps working unchanged.