Skip to main content

Semantic learning and procedural skills

Kheish has a separate daemon-owned learning plane in addition to normal session state and recovered run memory. That learning plane is intentionally split into two products:
  • durable semantic learnings
  • reviewed procedural learnings that can be promoted into daemon-owned reusable skills
These are related, but they are not the same thing.

How this differs from recovered run memory

Recovered run memory is:
  • derived from terminal runs
  • compact and episodic
  • prompt-bounded
  • best-effort recovery data
Durable learning is different:
  • it is stored as first-class records
  • it is scoped to session, persona, project, or workspace
  • it survives restart as daemon-owned state
  • it supports review and lifecycle transitions such as publish, reject, revoke, and supersede
  • it can be captured, judged, and published automatically through daemon policy

Learning kinds

Kheish currently stores five durable learning kinds:
  • run_summary
  • fact
  • preference
  • decision
  • procedure
The daemon treats them differently at retrieval time.

Prompt-eligible kinds

The runtime can inject these kinds back into later prompts when they are active, in scope, and prompt-visible:
  • fact
  • preference
  • decision

Stored but not auto-injected

These kinds are durably stored but excluded from the normal learned_context prompt section:
  • run_summary
  • procedure
That boundary is deliberate:
  • run_summary is review material rather than standing memory
  • procedure is durable procedure state, not free-form prompt memory

Scopes

Every learning belongs to one durable scope:
  • session
  • persona
  • project
  • workspace
The runtime resolves one session’s visible learning scopes in this order:
  • current session
  • bound persona, when one exists
  • linked projects
  • daemon-wide workspace scope
For workspace, the stable scope id is always default.

Retrieval model

Semantic retrieval is daemon-owned and bounded. On input submission, the daemon builds one learned_context bundle from visible scope records and attaches it as derived input state for the current run only. Important prompt-visibility rules:
  • procedure and run_summary stay out of learned_context
  • revoked and superseded records are excluded
  • expired records are excluded
  • publish_tier=provisional is excluded
  • verification_status=failed is excluded
  • automatically published records are prompt-visible only when verification_status=verified
  • policy_decision=escalated is excluded
  • manually published active records remain prompt-visible without that automatic-only gate
The daemon also keeps per-scope indexes for retrieval and search, while still resolving visibility rules such as supersession and prompt gating from the durable learning state.

Inspecting the effective projection

The durable store and the prompt projection are related but not identical.
  • GET /v1/learnings shows stored learning records
  • GET /v1/sessions/{session_id}/memory-context shows the effective eligible projection for one session
  • GET /v1/sessions/{session_id}/memory-search shows the session-scoped memory browse/search view
The session memory-context view includes:
  • effective capability scope
  • visible learning scopes
  • current learned_context
  • current recovered_memory
  • current visible_skills
This is the best operator-facing answer to “what is currently eligible for this session before the runtime packs one specific prompt?”

Review workflow

The learning workflow remains explicit even when automation is enabled.
  1. Create or capture a learning candidate.
  2. Review it automatically or manually.
  3. Publish it into the durable learning store, or reject it.
  4. Later revoke or supersede it if the knowledge changes.
This keeps durable memory daemon-governed instead of letting arbitrary run output mutate long-term behavior directly.

Candidate origins

Every candidate retains one ingress origin:
  • api: created explicitly through the public API or CLI
  • daemon: created by a daemon-owned workflow
This matters because daemon automation only treats provenance and evidence as trusted policy inputs for daemon-origin candidates.

Automatic capture

Kheish has two daemon-owned automatic capture paths.

Run-summary capture

The daemon can create run_summary candidates automatically from terminal runs. Important constraints:
  • this is controlled by runtime policy
  • run_summary remains review material even after publication
  • public attempts to create run_summary candidates are rejected
  • run_summary stays excluded from learned_context

Semantic capture

The daemon can also extract conservative semantic candidates from completed runs. Current behavior:
  • this path is controlled by capture.semantic_candidates
  • it only proposes fact, preference, and decision
  • extracted candidates are daemon-origin and session-scoped
  • extraction uses a model-backed structured prompt when enabled
  • there is a heuristic fallback for explicit Preference:, Fact:, and Decision: request labels
  • the daemon attaches daemon-owned evidence references to extracted candidates
The extraction path is restart-safe:
  • each run-memory record carries a semantic-capture receipt
  • unfinished capture work is replayed on boot
  • duplicate extraction is suppressed for runs already captured or already in flight

Automation modes

The current runtime policy has three modes:
  • manual_only
  • shadow
  • enabled
The current default is shadow. Mode behavior:
  • manual_only: the worker does not review candidates automatically
  • shadow: the worker records its review but leaves the candidate pending
  • enabled: the worker may reject, escalate, or publish automatically

Rule matching

Publication rules are evaluated in order. The first matching rule wins. If nothing matches, the daemon falls back to publication.default_action. Rules can currently match on:
  • scope_kind
  • scope_id
  • kind
  • sensitivity
  • min_confidence
  • require_evidence
  • require_source_run
  • require_source_session
The trusted-input gates are intentionally strict:
  • require_evidence
  • require_source_run
  • require_source_session
These only match for daemon-origin candidates. API-created candidates can still carry source and evidence_refs, but daemon automation does not trust those fields for rule matching. There are also two important publication controls:
  • allow_api_origin_active_publication
  • quarantined_rule_names
allow_api_origin_active_publication defaults to false, so API-origin candidates are downgraded from automatic publish_active to publish_provisional unless the operator opts in. quarantined_rule_names lets operators disable named rules without deleting them from the policy.

Model-backed judge

The daemon now has a configurable model-backed judge. The judge is:
  • daemon-owned
  • optional
  • invoked only after deterministic policy evaluation
  • bounded by its own optional model override and timeout
  • clamped so it cannot expand automation beyond the policy envelope
Important judge rules:
  • it can only choose from actions allowed by the policy baseline
  • it never writes learnings directly
  • in enabled mode, judge failures fail closed to manual_review
  • the final judge review is retained in automation_review.judge
This means the judge is advisory inside a bounded daemon workflow, not an authority that can invent new capabilities.

Automatic active versus provisional

Automatic publication can currently produce:
  • publish_provisional
  • publish_active
publish_active remains guarded. Current constraints:
  • publication.default_action cannot be publish_active
  • publish_active rules must declare an explicit kind
  • procedure learnings cannot be auto-published with the active tier
There is also one runtime verification gate:
  • when policy and the judge still select publish_active, the daemon verifies daemon-owned support for the candidate content
  • for daemon-origin semantic fact, preference, and decision candidates, that verification can use the persisted run-memory record of the source run
  • otherwise the daemon checks source-run debug artifacts referenced by the candidate evidence
  • if verification fails, the daemon downgrades the result to publish_provisional
That downgrade keeps the record durable without making it prompt-visible semantic memory.

Publication tiers and verification

Published learnings carry more than one on/off flag. Current metadata includes:
  • status
  • publish_tier
  • verification_status
  • policy_decision
  • policy_actor
Important runtime behavior:
  • only records with status=active and publish_tier=active are eligible for learned_context
  • verification_status=failed excludes a record from prompt injection
  • policy_decision=automatic requires verification_status=verified before prompt injection
  • policy_decision=manual active records can still be prompt-visible
  • policy_decision=escalated stays out of prompt retrieval
This keeps durability, automation, and prompt visibility as separate concerns.

Procedural learning promotion

Reviewed procedure learnings can optionally be promoted into daemon-owned reusable skills. Promotion is a separate step after publication. A stored procedure does not become a skill automatically.

Current promotion constraints

The current production path is intentionally narrow:
  • only procedure learnings can be promoted
  • the source learning must be active
  • the source learning must use publish_tier=active
  • the source learning must use workspace scope
  • promoted procedure skills must use fork
  • promoted procedure skills must use the verification child-agent profile
Kheish does not currently promote session-scoped procedures into the global daemon skill catalog.

Promotion rollout states

Promoted procedural skills keep their own rollout lifecycle:
  • draft
  • verified
  • canary
  • active
  • revoked
Only active promoted skills are mounted into:
  • GET /v1/skills
  • GET /v1/sessions/{session_id}/skills
  • runtime list_skills
  • runtime use_skill discovery

Runtime behavior of promoted procedures

Promoted procedure skills are designed to execute through a child-agent path. They can carry normal skill runtime metadata such as:
  • allowed_tools
  • blocked_tools
  • agent_profile
  • provider
  • model
  • fallback_model
Because they are fork-only, they are not used as persistent inline session skill state. When one is activated, the daemon creates a dedicated child worktree under the current workspace:
  • .kheish-procedural-worktrees/<safe-skill-name>/<tool-call-id>
When the caller waits for the forked child to settle, the returned spawn payload can include:
  • launch_run_id
  • the child snapshot
  • canonical final_output
Callers should prefer spawn.final_output over raw last_assistant_message when it exists.

Revocation and restart behavior

Semantic learnings and promoted procedure skills stay linked.
  • revoking or superseding a promoted source learning also revokes the linked promoted skill
  • promoted-skill records remain durable for audit
  • only active promoted skills stay mounted in the visible catalog
On boot, the daemon:
  • reloads persisted promoted-skill records
  • repairs missing daemon-owned promoted skill files when needed
  • refuses to silently rebind a promoted record to a foreign skill root
  • replays pending semantic capture work from run-memory receipts

Operational summary

Today, the intended production usage is:
  • use durable learnings for stable facts, preferences, and decisions
  • use memory-context to inspect what one session is currently eligible to receive before final prompt packing
  • use memory-search to browse or query visible learnings, recovered runs, and skills
  • use reviewed procedure learnings as candidates for reusable automation
  • promote only workspace-scoped procedures that are safe to expose through the shared daemon skill catalog
This gives Kheish durable memory and reusable reviewed procedures without collapsing session memory, semantic memory, and procedural execution into one ungoverned system.