mirror of
https://github.com/pocketpaw/pocketpaw.git
synced 2026-05-21 01:04:57 +00:00
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.
47 lines
1.3 KiB
Python
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",
|
|
]
|