Files
pocketpaw/ee/instinct/__init__.py
Prakash-1 bb09dd23a0 feat(instinct): ReasoningTrace + TraceCollector + fabric snapshots
The audit log already records that a decision happened — actor, event,
timestamp. It never recorded *why* that decision was made. This PR
lays the foundation so every proposal carries its reasoning context.

Three pieces:

- `ee/instinct/trace.py`
  - `ToolCallRef` — a tool invocation captured during proposal reasoning:
    tool name, a stable args fingerprint, a 200-char result preview, and
    a duration reading. The hash lets repeated calls dedupe without
    losing the first result.
  - `ReasoningTrace` — the top-level structure stored inside
    `AuditEntry.context["reasoning_trace"]`. Holds the referenced
    fabric_query / soul_recall / kb_article IDs, the tool_calls list,
    and the prompt version + backend + model metadata needed to
    reproduce what the agent saw.
  - `FabricObjectSnapshot` — an immutable snapshot of a Fabric object
    at decision time, keyed by `(object_id, audit_id)`. The trace only
    stores IDs; the snapshot is what lets a compliance reviewer
    reproduce the inputs three months later even after the live object
    has moved.

- `ee/instinct/trace_collector.py`
  - `TraceCollector` is the async context manager PR-B will wrap around
    the `instinct_propose` tool. It subscribes to `SystemEvent`s on
    enter, aggregates anything tagged `fabric_query`, `soul_recall`,
    `kb_inject`, `tool_start`, or `tool_end`/`tool_result` into the
    trace, and unsubscribes on exit — even when the body raises.
  - Tool calls are deduplicated on `(tool, args_hash)` within a single
    trace so repeated lookups stay compact. Reference lists
    (fabric_queries, soul_memories, kb_articles) are deduplicated on
    exit while preserving first-seen order.
  - Unknown event types and malformed payloads are silently ignored.
    The collector never fails the surrounding proposal.

- `InstinctStore` adds `record_fabric_snapshot`,
  `get_snapshots_for_audit`, and `get_snapshots_for_object` plus a new
  `instinct_fabric_snapshots` SQLite table with indexes on both
  `audit_id` and `object_id` so hydration and history queries stay
  cheap.

Tests: 19 new in `tests/cloud/test_decision_traces.py` covering the
model round-trip, subscribe/unsubscribe on enter and exit (including
exception path), every event-type branch, tool-call dedup and
truncation, malformed-event tolerance, and the snapshot read paths.
Full suite: 3991 passed; ruff clean.

Paired with PR-B (wire collector into `instinct_propose` + hydration
endpoint) and PR-C (Why? drawer in paw-enterprise), landing next.
2026-04-13 00:16:43 +05:30

47 lines
1.3 KiB
Python

# Instinct — decision pipeline for Paw OS.
# Created: 2026-03-28 — Actions, approvals, audit log.
# Updated: 2026-03-30 — Exported ActionStatus, ActionCategory, ActionPriority, AuditCategory.
# Updated: 2026-04-12 (Move 1 PR-A) — Exported Correction, CorrectionPatch, compute_patches.
# The decision loop: Agent proposes -> Human approves (optionally edits) ->
# Action executes -> Correction captured -> Soul learns.
from ee.instinct.correction import (
Correction,
CorrectionPatch,
compute_patches,
summarize_correction,
)
from ee.instinct.models import (
Action,
ActionCategory,
ActionContext,
ActionPriority,
ActionStatus,
ActionTrigger,
AuditCategory,
AuditEntry,
)
from ee.instinct.store import InstinctStore
from ee.instinct.trace import FabricObjectSnapshot, ReasoningTrace, ToolCallRef
from ee.instinct.trace_collector import TraceCollector
__all__ = [
"Action",
"ActionCategory",
"ActionContext",
"ActionPriority",
"ActionStatus",
"ActionTrigger",
"AuditCategory",
"AuditEntry",
"Correction",
"CorrectionPatch",
"FabricObjectSnapshot",
"InstinctStore",
"ReasoningTrace",
"ToolCallRef",
"TraceCollector",
"compute_patches",
"summarize_correction",
]