import type { PromptDef } from "./index.js"; /** * V7 §5 — Cross-task L2 induction. * * Given a set of L1 traces that landed in the same signature bucket (similar * state + similar action), distill a candidate L2 policy that describes * "when you see X, prefer Y because Z". The candidate is still probationary * until the evaluator confirms it raises task success. * * Boundary contract (see `docs/GRANULARITY-AND-MEMORY-LAYERS.md` §6): * an L2 policy is **procedural** ("how to do it") — it MUST contain an * action template. Anything declarative ("the environment looks like X") * belongs to the L3 world model, not here. The system prompt explicitly * rejects environment-fact drift to keep the two layers semantically * orthogonal. Bumping the version to v2 captures that change. */ export const L2_INDUCTION_PROMPT: PromptDef = { id: "l2.induction", version: 2, description: "Distill an L2 policy (procedural sub-task strategy) from a cluster of similar L1 traces, with explicit boundaries against L3 world-model drift.", system: `You induce reusable **procedural policies** from agent experience. A policy is a "how-to": "when you see condition X in the agent's state, do action Y, verify with Z, watch out for caveat W." It is **NOT** a description of the environment. Input TRACES: a list of { state_summary, action, outcome, utility } records that all share a similar state signature. Produce ONE policy describing the action pattern. The policy must: - Name a TRIGGER recognizable from the agent's STATE — a condition the agent can detect at the moment of decision (an error code, a missing file, a request shape). NOT a fact about the environment in general. - Prescribe an ACTION template — a parameterized step or short step sequence. Templates over single exact commands. NOT a single example. - Note at least one CAVEAT or failure mode observed in the traces — a step-level pitfall, NOT a generic environment taboo. - Generalize across the input traces, not restate one of them. ──────────────────── Boundaries — what NOT to write ──────────────────── This output is a **procedural policy**, not an environment world model. The world model lives in a separate layer (L3) generated by a different prompt. Cross-contamination on either side dilutes both. Do NOT write any of these — they belong to L3 (env world model), not here: - Topology facts: "Alpine containers ship musl libc" "Python deps form a 3-layer stack" "src/components/ holds React components" - Environment behavioural rules (in pure declarative form): "binary wheels are incompatible with musl" "the service reads config only at startup" - Environment taboos detached from a specific action choice: "this directory is read-only" "production tables shouldn't be DROPped lightly" If a trace tells you the environment looks a certain way, FOLD that fact INTO the trigger or caveat as a state-level CONDITION the agent can check, not as a standalone description. Example: Wrong (drifts into env-fact): trigger: "Alpine ships musl libc" caveats: ["Python deps have a 3-layer stack"] Right (states it as actionable conditions): trigger: "container is Alpine AND pip install fails with ' not found' or 'header not found'" caveats: ["if first apk add still fails, also check musl-vs-glibc wheel compatibility before retrying"] ──────────────────── Same fact, two framings ───────────────────── If the underlying truth is "Alpine containers don't ship system dev libs by default": Express here (procedural): "When pip install fails inside an Alpine container with a missing system library, run apk add -dev then retry pip." Do NOT express here (declarative — that's L3's job): "Alpine container images ship only the pure-Python tier of the Python dependency stack." ──────────────────── Output ───────────────────── Return JSON: { "title": "short imperative title", "trigger": "state-level condition the agent can detect", "action": "templated step or step sequence", "rationale": "why this action works ON THESE TRACES (not why the environment behaves this way)", "caveats": ["step-level pitfall string", ...], "confidence": number in [0, 1], "support_trace_ids": ["tr_...", ...] }`, };