mneme-code 3.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mneme_code/__init__.py +71 -0
- mneme_code/agents.py +240 -0
- mneme_code/cli.py +174 -0
- mneme_code/failure.py +175 -0
- mneme_code/py.typed +0 -0
- mneme_code/resolve.py +116 -0
- mneme_code/stacktrace.py +191 -0
- mneme_code/testrun.py +293 -0
- mneme_code/trajectory.py +140 -0
- mneme_code-3.1.0.dist-info/METADATA +59 -0
- mneme_code-3.1.0.dist-info/RECORD +13 -0
- mneme_code-3.1.0.dist-info/WHEEL +4 -0
- mneme_code-3.1.0.dist-info/entry_points.txt +2 -0
mneme_code/trajectory.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""FixTrajectory dataclass and vault-ready markdown serialization.
|
|
2
|
+
|
|
3
|
+
A fix-trajectory links a :class:`~mneme_code.failure.FailureMemory` to its
|
|
4
|
+
resolution via temporal supersession. The fix note is rendered with
|
|
5
|
+
``type: claim`` and ``supersedes: <failure_note_id>`` so the mneme-temporal
|
|
6
|
+
layer's ``as_of`` / ``current`` queries automatically treat the failure as
|
|
7
|
+
resolved after ``resolved_at`` — no new infrastructure required.
|
|
8
|
+
|
|
9
|
+
Provenance invariant: every ``FixTrajectory`` carries:
|
|
10
|
+
trajectory_id — deterministic UUID5 derived from failure_id + redacted fix_summary.
|
|
11
|
+
failure_id — the ``FailureMemory.failure_id`` being resolved.
|
|
12
|
+
failure_note_id — the vault note id of the failure note (target of ``supersedes``).
|
|
13
|
+
fix_summary — redacted human summary of the fix.
|
|
14
|
+
resolved_at — injected by caller; never produced inside this module.
|
|
15
|
+
trust — default ``"user"`` (operator-supplied resolution).
|
|
16
|
+
confidence — default ``"EXTRACTED"`` (directly observed, no inference).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import uuid
|
|
23
|
+
from dataclasses import dataclass, field
|
|
24
|
+
from datetime import UTC, datetime
|
|
25
|
+
|
|
26
|
+
from mneme_core.privacy import redact
|
|
27
|
+
|
|
28
|
+
from mneme_code.failure import FailureMemory
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class FixTrajectory:
|
|
33
|
+
"""A provenance-labelled, redacted record of one failure resolution.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
trajectory_id Deterministic UUID5 (namespace URL) derived from
|
|
37
|
+
``failure_id`` and the redacted ``fix_summary``.
|
|
38
|
+
failure_id The ``FailureMemory.failure_id`` being resolved.
|
|
39
|
+
failure_note_id The vault note id of the failure note; used as the
|
|
40
|
+
``supersedes`` target in the temporal claim frontmatter.
|
|
41
|
+
fix_summary Redacted human summary of the fix applied.
|
|
42
|
+
resolved_at Tz-aware UTC datetime injected by the caller.
|
|
43
|
+
trust Provenance tier; default ``"user"``.
|
|
44
|
+
confidence Confidence label; default ``"EXTRACTED"``.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
trajectory_id: str
|
|
48
|
+
failure_id: str
|
|
49
|
+
failure_note_id: str
|
|
50
|
+
fix_summary: str
|
|
51
|
+
resolved_at: datetime
|
|
52
|
+
trust: str = field(default="user")
|
|
53
|
+
confidence: str = field(default="EXTRACTED")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def fix_from_failure(
|
|
57
|
+
failure: FailureMemory,
|
|
58
|
+
*,
|
|
59
|
+
fix_summary: str,
|
|
60
|
+
resolved_at: datetime,
|
|
61
|
+
failure_note_id: str | None = None,
|
|
62
|
+
) -> FixTrajectory:
|
|
63
|
+
"""Construct a :class:`FixTrajectory` from a :class:`FailureMemory`.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
failure: The :class:`FailureMemory` being resolved.
|
|
67
|
+
fix_summary: Human summary of the fix; redacted via
|
|
68
|
+
:func:`mneme_core.privacy.redact` before storage.
|
|
69
|
+
resolved_at: Tz-aware UTC datetime for this resolution.
|
|
70
|
+
Must be injected by the caller; this function never
|
|
71
|
+
calls ``datetime.now()``.
|
|
72
|
+
failure_note_id: Vault note id of the failure note. Defaults to
|
|
73
|
+
``failure.failure_id`` when omitted.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
A deterministic :class:`FixTrajectory` — same inputs always produce
|
|
77
|
+
the same ``trajectory_id``.
|
|
78
|
+
"""
|
|
79
|
+
note_id = failure_note_id if failure_note_id is not None else failure.failure_id
|
|
80
|
+
redacted_summary = redact(fix_summary)
|
|
81
|
+
|
|
82
|
+
# Deterministic UUID5: namespace URL + failure_id + NUL separator + redacted summary.
|
|
83
|
+
key = f"{failure.failure_id}\x00{redacted_summary}"
|
|
84
|
+
trajectory_id = str(uuid.uuid5(uuid.NAMESPACE_URL, key))
|
|
85
|
+
|
|
86
|
+
return FixTrajectory(
|
|
87
|
+
trajectory_id=trajectory_id,
|
|
88
|
+
failure_id=failure.failure_id,
|
|
89
|
+
failure_note_id=note_id,
|
|
90
|
+
fix_summary=redacted_summary,
|
|
91
|
+
resolved_at=resolved_at,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def fix_to_markdown(fix: FixTrajectory) -> str:
|
|
96
|
+
"""Render a :class:`FixTrajectory` as a vault-ready temporal claim note.
|
|
97
|
+
|
|
98
|
+
Frontmatter fields:
|
|
99
|
+
id fix.trajectory_id
|
|
100
|
+
type ``"claim"`` — indexes the note into the temporal layer.
|
|
101
|
+
created fix.resolved_at as tz-aware UTC ISO 8601 with microseconds.
|
|
102
|
+
tags ``["fix", "trajectory"]``
|
|
103
|
+
claim_key ``"failure.<failure_id>"`` — ties fix and failure together.
|
|
104
|
+
supersedes fix.failure_note_id — temporal supersession target.
|
|
105
|
+
valid_from fix.resolved_at as tz-aware UTC ISO 8601 with microseconds.
|
|
106
|
+
trust fix.trust
|
|
107
|
+
confidence fix.confidence
|
|
108
|
+
|
|
109
|
+
Body: heading ``# Fix for <failure_id>`` followed by the redacted fix_summary.
|
|
110
|
+
|
|
111
|
+
All content has already been redacted at construction time; this function
|
|
112
|
+
does not re-apply redaction.
|
|
113
|
+
"""
|
|
114
|
+
# Normalise resolved_at to tz-aware UTC (mirrors failure_to_markdown and _to_utc_iso).
|
|
115
|
+
resolved = fix.resolved_at
|
|
116
|
+
resolved = resolved.replace(tzinfo=UTC) if resolved.tzinfo is None else resolved.astimezone(UTC)
|
|
117
|
+
resolved_str = resolved.isoformat(timespec="microseconds")
|
|
118
|
+
|
|
119
|
+
fm_lines = [
|
|
120
|
+
"---",
|
|
121
|
+
f"id: {fix.trajectory_id}",
|
|
122
|
+
"type: claim",
|
|
123
|
+
f"created: {resolved_str}",
|
|
124
|
+
"tags:",
|
|
125
|
+
" - fix",
|
|
126
|
+
" - trajectory",
|
|
127
|
+
f"claim_key: {json.dumps(f'failure.{fix.failure_id}')}",
|
|
128
|
+
f"supersedes: {json.dumps(fix.failure_note_id)}",
|
|
129
|
+
f"valid_from: {resolved_str}",
|
|
130
|
+
f"trust: {fix.trust}",
|
|
131
|
+
f"confidence: {fix.confidence}",
|
|
132
|
+
"---",
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
body_lines: list[str] = []
|
|
136
|
+
body_lines.append(f"# Fix for {fix.failure_id}")
|
|
137
|
+
body_lines.append("")
|
|
138
|
+
body_lines.append(fix.fix_summary)
|
|
139
|
+
|
|
140
|
+
return "\n".join(fm_lines) + "\n" + "\n".join(body_lines) + "\n"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mneme-code
|
|
3
|
+
Version: 3.1.0
|
|
4
|
+
Summary: Deterministic Python code-failure memory layer for mneme: redact-before-store, provenance-labelled FailureMemory, vault-ready markdown output.
|
|
5
|
+
Author: Onour Impram
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Keywords: code-failure,memory,mneme,redaction,traceback
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: mneme-core<4,>=3.0.0
|
|
18
|
+
Requires-Dist: mneme-graph>=0.1.0
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest>=8.2; extra == 'dev'
|
|
23
|
+
Requires-Dist: ruff>=0.4.7; extra == 'dev'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# mneme-code
|
|
27
|
+
|
|
28
|
+
Deterministic Python code-failure memory for mneme. Parses CPython tracebacks
|
|
29
|
+
into structured failures, renders them as vault-ground-truth markdown memories,
|
|
30
|
+
and resolves stack frames to [mneme-graph](../mneme-graph) function nodes.
|
|
31
|
+
|
|
32
|
+
Part of the [mneme](https://github.com/TheGoatPsy/mneme) memory engine.
|
|
33
|
+
|
|
34
|
+
## What it does (v1)
|
|
35
|
+
|
|
36
|
+
- **Traceback parsing.** `parse_traceback` turns a standard CPython traceback
|
|
37
|
+
into a `ParsedTraceback` (exception type, message, frames). It never raises;
|
|
38
|
+
unrecognised input returns `None`.
|
|
39
|
+
- **Failure memories.** `failure_from_traceback` + `failure_to_markdown` produce
|
|
40
|
+
a markdown note the user owns, with provenance (`content_hash`, `observed_at`,
|
|
41
|
+
`trust`) and a confidence label.
|
|
42
|
+
- **Frame resolution.** `resolve_frames` pairs each frame with a mneme-graph
|
|
43
|
+
`function` node when one matches, with a clean fallback to `None`.
|
|
44
|
+
|
|
45
|
+
Redaction (`mneme_core.privacy.redact`) is applied to every user-derived string
|
|
46
|
+
(exception message, code context, file path) before it is stored or rendered.
|
|
47
|
+
No LLM, no network; library functions are pure (the caller injects timestamps).
|
|
48
|
+
|
|
49
|
+
## Scope and deferrals (v1)
|
|
50
|
+
|
|
51
|
+
The following are **not** implemented yet and are documented here for honesty:
|
|
52
|
+
|
|
53
|
+
- Live test-runner integration.
|
|
54
|
+
- Branch-aware failure tracking.
|
|
55
|
+
- `AGENTS.md` procedural-memory parsing and repo runbook generation.
|
|
56
|
+
- Fix-trajectory wiring: a *fix* is modelled as a `mneme-temporal` claim that
|
|
57
|
+
**supersedes** the failure memory. That lifecycle lives in `mneme-temporal`
|
|
58
|
+
and is reused, not reinvented here.
|
|
59
|
+
- Non-Python tracebacks.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
mneme_code/__init__.py,sha256=UXoCFsJCxAfLWR2FlrM_o3pUNmGuSdJaj0dLsEiorAI,2770
|
|
2
|
+
mneme_code/agents.py,sha256=RxBIZ6mt7uDpRG2L4aDvcNaBlqBBDACiGpp0Ec7i5OQ,9065
|
|
3
|
+
mneme_code/cli.py,sha256=3O0NHi9tXHFZtWqDn4DECeTxylw1Qv6JJeoLMZU9fIQ,5953
|
|
4
|
+
mneme_code/failure.py,sha256=cCarpK-EPyOaYWnHevkLtvZvD6jyxImT_Dhqi_uTIyM,6908
|
|
5
|
+
mneme_code/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
mneme_code/resolve.py,sha256=eIE5vZUHEBjCEtElZ4V1bPWls1vuWfFJl7sa-XZI7sI,4487
|
|
7
|
+
mneme_code/stacktrace.py,sha256=r3qCA_3Pjw6iYQXiAA5Jh5JVluydaUCIw1mYIidkEEM,6218
|
|
8
|
+
mneme_code/testrun.py,sha256=zGsSvgwdh6AJ5yI6bPRnLTJZc6c1YkEN_7Cum5C0Ul0,10805
|
|
9
|
+
mneme_code/trajectory.py,sha256=y0BZ8mq4M9-iegnVv6P25DCfi3r_XLJbDwwjM7jNf_Y,5631
|
|
10
|
+
mneme_code-3.1.0.dist-info/METADATA,sha256=APNuMAELyb7jHQVC1eWYGpzQvrLXftOuWuv2lLiboVY,2642
|
|
11
|
+
mneme_code-3.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
12
|
+
mneme_code-3.1.0.dist-info/entry_points.txt,sha256=pmHq6U16MqppYske97Ht9_baKKaOEpgAV63ZCF6UKbY,51
|
|
13
|
+
mneme_code-3.1.0.dist-info/RECORD,,
|