|
| 1 | +# Persistent MCP interaction observability (issue 3) |
| 2 | + |
| 3 | +Status: Accepted (local fixture qualification). Acceptance: satisfied. Operation: verify. Owner: implementation agent; |
| 4 | +publication and merge authority remain with the parent/operator. Baseline: |
| 5 | +`188beda1fa477d21d576c233dd8c7f4c4c267d23` (interface 46). |
| 6 | +Canonical plan: `docs/plans/mcp-observability/plan.md`. |
| 7 | + |
| 8 | +## Objective and authority |
| 9 | + |
| 10 | +Implement opt-in, local, agent-invisible SQLite observations at the existing MCP |
| 11 | +boundary. Keep domain transactions, tools, outcomes, protocol, retries, generated |
| 12 | +contracts, normative standards and observer-v3 qualification unchanged. No model |
| 13 | +calls, Tuldok changes, installation configuration or live telemetry collection. |
| 14 | +The subsequent user approval permits pushing the verified feature branch and |
| 15 | +opening a PR containing only code, synthetic tests and sanitized documentation. |
| 16 | +Parent owns merge. No deployment or enabling on existing installations. |
| 17 | + |
| 18 | +Private feature branch `feat/issue3-mcp-observability` in the separate clone |
| 19 | +`/workspace/Coding-Standards`; target `main`, integration owner parent. Retain |
| 20 | +branch/checkout for publication decision and review; no cleanup or history rewrite. |
| 21 | +No writes to Nearwork or other mounted repositories. |
| 22 | + |
| 23 | +## Routed owners and decisions |
| 24 | + |
| 25 | +Core and Router select implementation, verification/oracles, planning/discovery, |
| 26 | +proportionality, commit, documentation; library application, IPC and persistence; diagnostics, |
| 27 | +architecture, code-design, contracts/evolution/protocols, concurrency, security, |
| 28 | +resilience, performance and cross-platform. Python has no language profile. |
| 29 | +No normative or generated contract changes: no generated-contract profile, |
| 30 | +standards-authoring workflow, release or framework profile is needed. |
| 31 | +No AGENTS.md exists in this clone or its workspace ancestors. Runtime identity |
| 32 | +uses process UUID and exact catalog/schema/implementation digests, independent |
| 33 | +of Git/content authority. Observer v3 remains qualification evidence and retains |
| 34 | +its independent exact-source replay. No production dependency on test code. |
| 35 | + |
| 36 | +## Binding design |
| 37 | + |
| 38 | +- MCP owns request execution and response delivery. Recorder owns only sanitized |
| 39 | + observations, SQLite transactions, retention and health. Operator CLI reads |
| 40 | + that separate database; Engine stores and authorization remain untouched. |
| 41 | +- Explicit operator CLI configuration supplies a database in an existing trusted |
| 42 | + directory and a deployment label. Omission creates no recorder/file. POSIX local |
| 43 | + regular files only; reject symlinks, nonprivate files, unrelated databases and |
| 44 | + unsupported schemas. The trusted directory must exclude concurrent hostile |
| 45 | + path replacement. Same-user agents can read files: filesystem modes are damage |
| 46 | + reduction, never an agent authorization boundary. Store no secrets regardless. |
| 47 | +- Schema v1: immutable interaction starts plus independent terminal events, joined |
| 48 | + by generated UUID; process/session UUID and ordinal establish local chronology. |
| 49 | + Sessions bind runtime metadata, deployment label and per-operation schema |
| 50 | + digests. No client-supplied request IDs, names or paths are stored verbatim. |
| 51 | +- Pair end/error with begin only after response write/flush in stdio. Direct |
| 52 | + dispatch records a constructed response (distinct delivery evidence). Parsing, |
| 53 | + validation, typed rejection, tool exceptions and interruption are classified |
| 54 | + without raw messages. Unmatched starts remain incomplete/unknown, including |
| 55 | + process kill and response delivery failure; never infer completion on restart. |
| 56 | +- Bounded input shape: fixed schema-derived property names, scalar type markers, |
| 57 | + depth/node/array caps; redact sensitive subtrees and unknown member names. |
| 58 | + Never retain scalar values, arbitrary map keys, prompts, bodies, tokens, |
| 59 | + credentials, outputs, exception messages or client metadata. Static schema |
| 60 | + selector/operation names are admitted only by exact installed-catalog membership. |
| 61 | + Feedback retains sanitized field pointers and fixed constraint keywords only. |
| 62 | +- No raw input digests (dictionary attacks). Shape digests identify structural |
| 63 | + variants only. Catalog and implementation digests identify exact source material. |
| 64 | + MCP has no legitimate cross-process session/task continuation in this server; |
| 65 | + do not invent one from prompts or domain handles. Reports state that limitation. |
| 66 | +- Serial synchronous recorder, no queue/thread/retry. SQLite `BEGIN IMMEDIATE` |
| 67 | + owns each mutation and rollback. Finite busy timeout and page quota; rollback |
| 68 | + journal rather than unbounded WAL. Maximum retained interactions and age are |
| 69 | + operator policies with bounded defaults; prune starts and events atomically. |
| 70 | + Retention may evict unmatched observations and is explicitly reported. |
| 71 | +- Version 0 is accepted only for a zero-length new database and migrates transactionally |
| 72 | + to v1. Existing v1 reopens intact; future/corrupt/unrelated databases fail open |
| 73 | + without replacement. No inferred migration or automatic destructive recovery. |
| 74 | +- Recorder failure degrades once, disables further recording for that process, |
| 75 | + and reports a fixed nonsensitive reason plus counters on operator stderr. |
| 76 | + It never retries domain work or changes its return. Operator fixes storage and |
| 77 | + restarts to recover recording. Health is independent of the failing database. |
| 78 | +- Read-only bounded JSON report: operation/error/shape counts, observed latency |
| 79 | + and bytes, incomplete counts, discovery/failed-attempt sequences before a |
| 80 | + later success in the same process/operation, catalog comparisons. Denominators |
| 81 | + and delivery scope explicit. Correlation cannot prove intent, actual repair, |
| 82 | + client acquisition, token usage or billing. Retained traces cannot reconstruct |
| 83 | + redacted requests; observer v3 remains the source-backed replay authority. |
| 84 | + |
| 85 | +## Composed-design admission: applicable |
| 86 | + |
| 87 | +1. Independent concerns: MCP owns execution/delivery; recorder owns privacy, |
| 88 | + observations and local retention; operator report owns read-only interpretation; |
| 89 | + RuntimeIdentity/catalog own source/contract attribution. No observer-v3 coupling. |
| 90 | +2. Necessary interleaving: begin before dispatch, terminal after delivery, metadata |
| 91 | + captured at recorder construction. Accidental coupling avoided: no Engine SQL, |
| 92 | + tool registration, hidden model work or telemetry-driven domain decisions. |
| 93 | +3. Composition root knows configuration, immutable runtime/catalog and close; |
| 94 | + dispatch/stdio know begin/finish lifecycle. Callers never own SQL or redaction. |
| 95 | +4. Privacy changes touch recorder/tests/docs; schema revisions flow through existing |
| 96 | + catalog identity; delivery changes touch MCP integration; storage revisions |
| 97 | + touch recorder migration and CLI together. Domain changes need no recorder edits. |
| 98 | +5. Stable runtime metadata crosses the seam; no store handles or validator internals. |
| 99 | + Schema property vocabulary is diagnostic disclosure authority, not validation. |
| 100 | +6. Recorder can fail and be disabled independently; CLI reads across restart. |
| 101 | + MCP remains independently usable. Tests exercise both enabled and omitted paths. |
| 102 | +7. Deleting recorder moves necessary privacy/storage/retention/lifecycle complexity |
| 103 | + back into MCP, so retain it. No generic adapter registry, background worker, |
| 104 | + second protocol, exported observer tool or migration framework is admitted. |
| 105 | +8. Inherent complexity is bounded evidence, privacy and SQLite lifecycle; keep it |
| 106 | + in one production module plus its read-only reporting entrypoint, not harnesses. |
| 107 | + |
| 108 | +## Milestones and evidence |
| 109 | + |
| 110 | +A Accepted: design/source/privacy review; write set this plan directory only. |
| 111 | +B Accepted: recorder and MCP integration; write set |
| 112 | +`tools/standards_engine/standards_engine/{interaction_observer.py,mcp.py}`, |
| 113 | +`tools/standards_engine/tests/test_interaction_observer.py`. Gate: focused |
| 114 | +privacy, failure and outcome-preservation tests. |
| 115 | +C Accepted: operator report, configuration and operational documentation; same |
| 116 | +module plus `tools/standards_engine/MCP-OBSERVABILITY.md` and README link. |
| 117 | +Gate: bounded read-only report, catalog changes, accurate denominators. |
| 118 | +D Accepted: cold stdio/process replacement, exceptions/interruption, real unavailable, |
| 119 | +locked/full SQLite, concurrent processes, migration/retention/privacy. Existing MCP, |
| 120 | +runtime identity, discovery and observer-v3 tests plus full Engine suite and |
| 121 | +contract projection check. Synthetic baseline/candidate call and byte comparison. |
| 122 | +E Accepted: independent GPT-6.1 Sol High design/source/privacy review accepted with all seven findings resolved; staged and full branch review, local commits, authorized push and PR. |
| 123 | +No real logs or confidential artifacts in Git. Parent owns merge. The generated |
| 124 | +`evaluation/standards-effectiveness/generated/suite-inputs.json` is an allowed |
| 125 | +adjacent write: refresh through the Engine after staging declared inputs; it |
| 126 | +tracks source/README digests and is not a normative standards change. |
| 127 | + |
| 128 | +F Accepted: repair I1 using the actual policy semantic revision from the immutable |
| 129 | +snapshot, before entering the existing counting mocks. Write set: |
| 130 | +`tools/standards_engine/tests/test_analysis.py`, this plan/ledger/issues, a bounded |
| 131 | +fixture-review report and current verification evidence; generated verifier input |
| 132 | +manifest only if its compiler requires a refresh. Gate: failing case, analysis |
| 133 | +module and full Engine suite pass; independent review; reviewed commit/push to |
| 134 | +existing approved PR #4 branch. Validator, normative content and both count |
| 135 | +assertions remain unchanged. No telemetry activation or raw log publication. |
| 136 | + |
| 137 | +Current phase: complete local qualification. Next slice: none. Blockers: none. |
| 138 | +F evidence: targeted case passed; analysis module 23/23; full serial Engine suite |
| 139 | +636/636; independent fixture review satisfied. I1 is resolved without changing |
| 140 | +validator, normative content or either count assertion; historical baseline failure |
| 141 | +remains in issues/evidence. I2 resolved through the existing Git transport; parent |
| 142 | +opened PR #4. The verified follow-up is packaged for the explicitly approved branch |
| 143 | +push; Git/PR refs own publication identity and parent owns hosted CI/merge. |
| 144 | +See [verification](reports/verification.md), [fixture review](reports/fixture-review.md), [independent source/privacy review](reports/independent-review.md), [ledger](execution-ledger.md) and [issues](issues.md). |
0 commit comments