mark-sdk 0.2.0a5__tar.gz

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.
Files changed (147) hide show
  1. mark_sdk-0.2.0a5/.github/ISSUE_TEMPLATE/bug_report.yml +53 -0
  2. mark_sdk-0.2.0a5/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. mark_sdk-0.2.0a5/.github/ISSUE_TEMPLATE/feature_request.yml +33 -0
  4. mark_sdk-0.2.0a5/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  5. mark_sdk-0.2.0a5/.github/workflows/ci.yml +36 -0
  6. mark_sdk-0.2.0a5/.github/workflows/release.yml +57 -0
  7. mark_sdk-0.2.0a5/.gitignore +80 -0
  8. mark_sdk-0.2.0a5/AGENTS.md +65 -0
  9. mark_sdk-0.2.0a5/ARCHITECTURE.md +250 -0
  10. mark_sdk-0.2.0a5/CHANGELOG.md +240 -0
  11. mark_sdk-0.2.0a5/CODE_OF_CONDUCT.md +30 -0
  12. mark_sdk-0.2.0a5/CONTRIBUTING.md +66 -0
  13. mark_sdk-0.2.0a5/LICENSE +21 -0
  14. mark_sdk-0.2.0a5/PKG-INFO +348 -0
  15. mark_sdk-0.2.0a5/README.md +273 -0
  16. mark_sdk-0.2.0a5/SECURITY.md +27 -0
  17. mark_sdk-0.2.0a5/VERSIONING.md +54 -0
  18. mark_sdk-0.2.0a5/examples/01_local_memory_live.py +36 -0
  19. mark_sdk-0.2.0a5/examples/02_agent_ab_live.py +42 -0
  20. mark_sdk-0.2.0a5/examples/03_sessions_and_observe_live.py +41 -0
  21. mark_sdk-0.2.0a5/examples/04_sync_boundary_live.py +44 -0
  22. mark_sdk-0.2.0a5/examples/README.md +36 -0
  23. mark_sdk-0.2.0a5/examples/getting_started_with_mark.ipynb +424 -0
  24. mark_sdk-0.2.0a5/examples/run_live_examples.py +29 -0
  25. mark_sdk-0.2.0a5/pyproject.toml +141 -0
  26. mark_sdk-0.2.0a5/src/.gitkeep +0 -0
  27. mark_sdk-0.2.0a5/src/mark/.gitkeep +0 -0
  28. mark_sdk-0.2.0a5/src/mark/__init__.py +173 -0
  29. mark_sdk-0.2.0a5/src/mark/_version.py +3 -0
  30. mark_sdk-0.2.0a5/src/mark/adapters/__init__.py +9 -0
  31. mark_sdk-0.2.0a5/src/mark/adapters/backend.py +131 -0
  32. mark_sdk-0.2.0a5/src/mark/adapters/langchain/__init__.py +15 -0
  33. mark_sdk-0.2.0a5/src/mark/adapters/langchain/middleware.py +1094 -0
  34. mark_sdk-0.2.0a5/src/mark/adapters/langchain/tools.py +95 -0
  35. mark_sdk-0.2.0a5/src/mark/adapters/mcp/__init__.py +157 -0
  36. mark_sdk-0.2.0a5/src/mark/agent.py +76 -0
  37. mark_sdk-0.2.0a5/src/mark/context/.gitkeep +0 -0
  38. mark_sdk-0.2.0a5/src/mark/context/__init__.py +4 -0
  39. mark_sdk-0.2.0a5/src/mark/context/builder.py +68 -0
  40. mark_sdk-0.2.0a5/src/mark/context/window.py +7 -0
  41. mark_sdk-0.2.0a5/src/mark/deep_rl/__init__.py +20 -0
  42. mark_sdk-0.2.0a5/src/mark/deep_rl/safety.py +95 -0
  43. mark_sdk-0.2.0a5/src/mark/embeddings/__init__.py +4 -0
  44. mark_sdk-0.2.0a5/src/mark/embeddings/base.py +54 -0
  45. mark_sdk-0.2.0a5/src/mark/embeddings/cache.py +62 -0
  46. mark_sdk-0.2.0a5/src/mark/embeddings/ollama.py +48 -0
  47. mark_sdk-0.2.0a5/src/mark/embeddings/sentence_transformers.py +36 -0
  48. mark_sdk-0.2.0a5/src/mark/governance/__init__.py +18 -0
  49. mark_sdk-0.2.0a5/src/mark/governance/audit.py +93 -0
  50. mark_sdk-0.2.0a5/src/mark/governance/gates.py +103 -0
  51. mark_sdk-0.2.0a5/src/mark/governance/pipeline.py +69 -0
  52. mark_sdk-0.2.0a5/src/mark/governance/sanitizer.py +40 -0
  53. mark_sdk-0.2.0a5/src/mark/index/__init__.py +3 -0
  54. mark_sdk-0.2.0a5/src/mark/index/vector.py +106 -0
  55. mark_sdk-0.2.0a5/src/mark/intelligence/__init__.py +64 -0
  56. mark_sdk-0.2.0a5/src/mark/intelligence/classifier.py +198 -0
  57. mark_sdk-0.2.0a5/src/mark/intelligence/compressor.py +139 -0
  58. mark_sdk-0.2.0a5/src/mark/intelligence/extractor.py +485 -0
  59. mark_sdk-0.2.0a5/src/mark/intelligence/query_expander.py +76 -0
  60. mark_sdk-0.2.0a5/src/mark/intelligence/reranker.py +132 -0
  61. mark_sdk-0.2.0a5/src/mark/intelligence/retrieval.py +563 -0
  62. mark_sdk-0.2.0a5/src/mark/media/__init__.py +20 -0
  63. mark_sdk-0.2.0a5/src/mark/media/entity.py +158 -0
  64. mark_sdk-0.2.0a5/src/mark/media/session_memory.py +95 -0
  65. mark_sdk-0.2.0a5/src/mark/media/world_bible.py +125 -0
  66. mark_sdk-0.2.0a5/src/mark/memory/.gitkeep +0 -0
  67. mark_sdk-0.2.0a5/src/mark/memory/__init__.py +57 -0
  68. mark_sdk-0.2.0a5/src/mark/memory/block.py +119 -0
  69. mark_sdk-0.2.0a5/src/mark/memory/block_chain.py +293 -0
  70. mark_sdk-0.2.0a5/src/mark/memory/block_graph.py +270 -0
  71. mark_sdk-0.2.0a5/src/mark/memory/consolidation.py +116 -0
  72. mark_sdk-0.2.0a5/src/mark/memory/contradiction.py +124 -0
  73. mark_sdk-0.2.0a5/src/mark/memory/conversation.py +148 -0
  74. mark_sdk-0.2.0a5/src/mark/memory/deduplication.py +219 -0
  75. mark_sdk-0.2.0a5/src/mark/memory/global_bus.py +93 -0
  76. mark_sdk-0.2.0a5/src/mark/memory/graph.py +77 -0
  77. mark_sdk-0.2.0a5/src/mark/memory/mark_memory.py +871 -0
  78. mark_sdk-0.2.0a5/src/mark/memory/migration.py +126 -0
  79. mark_sdk-0.2.0a5/src/mark/memory/observe.py +200 -0
  80. mark_sdk-0.2.0a5/src/mark/memory/record.py +73 -0
  81. mark_sdk-0.2.0a5/src/mark/memory/retrieval.py +27 -0
  82. mark_sdk-0.2.0a5/src/mark/memory/runtime.py +258 -0
  83. mark_sdk-0.2.0a5/src/mark/memory/scoring.py +56 -0
  84. mark_sdk-0.2.0a5/src/mark/memory/simple.py +334 -0
  85. mark_sdk-0.2.0a5/src/mark/memory/store.py +117 -0
  86. mark_sdk-0.2.0a5/src/mark/memory/trust_bus.py +336 -0
  87. mark_sdk-0.2.0a5/src/mark/memory/working.py +88 -0
  88. mark_sdk-0.2.0a5/src/mark/observability/.gitkeep +0 -0
  89. mark_sdk-0.2.0a5/src/mark/observability/__init__.py +12 -0
  90. mark_sdk-0.2.0a5/src/mark/observability/events.py +30 -0
  91. mark_sdk-0.2.0a5/src/mark/observability/replay.py +63 -0
  92. mark_sdk-0.2.0a5/src/mark/observability/session.py +57 -0
  93. mark_sdk-0.2.0a5/src/mark/observability/trace.py +62 -0
  94. mark_sdk-0.2.0a5/src/mark/plasticity/__init__.py +34 -0
  95. mark_sdk-0.2.0a5/src/mark/plasticity/decay.py +101 -0
  96. mark_sdk-0.2.0a5/src/mark/plasticity/hebbian.py +73 -0
  97. mark_sdk-0.2.0a5/src/mark/plasticity/pruner.py +87 -0
  98. mark_sdk-0.2.0a5/src/mark/plasticity/router.py +69 -0
  99. mark_sdk-0.2.0a5/src/mark/plugins/__init__.py +57 -0
  100. mark_sdk-0.2.0a5/src/mark/plugins/registry.py +200 -0
  101. mark_sdk-0.2.0a5/src/mark/policies/.gitkeep +0 -0
  102. mark_sdk-0.2.0a5/src/mark/policies/__init__.py +15 -0
  103. mark_sdk-0.2.0a5/src/mark/policies/base.py +46 -0
  104. mark_sdk-0.2.0a5/src/mark/policies/builtin.py +50 -0
  105. mark_sdk-0.2.0a5/src/mark/policies/registry.py +36 -0
  106. mark_sdk-0.2.0a5/src/mark/rl/__init__.py +28 -0
  107. mark_sdk-0.2.0a5/src/mark/rl/buffer.py +99 -0
  108. mark_sdk-0.2.0a5/src/mark/rl/collectors.py +113 -0
  109. mark_sdk-0.2.0a5/src/mark/rl/encoder.py +56 -0
  110. mark_sdk-0.2.0a5/src/mark/rl/reward.py +59 -0
  111. mark_sdk-0.2.0a5/src/mark/runtime.py +301 -0
  112. mark_sdk-0.2.0a5/src/mark/sandbox/.dockerignore +0 -0
  113. mark_sdk-0.2.0a5/src/mark/sandbox/Dockerfile +0 -0
  114. mark_sdk-0.2.0a5/src/mark/sandbox/__init__.py +3 -0
  115. mark_sdk-0.2.0a5/src/mark/sandbox/compose.yaml +0 -0
  116. mark_sdk-0.2.0a5/src/mark/sandbox/docker.py +180 -0
  117. mark_sdk-0.2.0a5/src/mark/security/.gitkeep +0 -0
  118. mark_sdk-0.2.0a5/src/mark/security/__init__.py +12 -0
  119. mark_sdk-0.2.0a5/src/mark/security/encryption.py +114 -0
  120. mark_sdk-0.2.0a5/src/mark/security/hasher.py +38 -0
  121. mark_sdk-0.2.0a5/src/mark/security/redaction.py +40 -0
  122. mark_sdk-0.2.0a5/src/mark/skills/.gitkeep +0 -0
  123. mark_sdk-0.2.0a5/src/mark/skills/__init__.py +21 -0
  124. mark_sdk-0.2.0a5/src/mark/skills/base.py +366 -0
  125. mark_sdk-0.2.0a5/src/mark/skills/builtin.py +86 -0
  126. mark_sdk-0.2.0a5/src/mark/skills/mark-memory-middleware/SKILL.md +36 -0
  127. mark_sdk-0.2.0a5/src/mark/skills/mark-usage/SKILL.md +255 -0
  128. mark_sdk-0.2.0a5/src/mark/skills/persona.py +77 -0
  129. mark_sdk-0.2.0a5/src/mark/skills/registry.py +38 -0
  130. mark_sdk-0.2.0a5/src/mark/skills/web_search.py +311 -0
  131. mark_sdk-0.2.0a5/src/mark/storage/.gitkeep +0 -0
  132. mark_sdk-0.2.0a5/src/mark/storage/__init__.py +3 -0
  133. mark_sdk-0.2.0a5/src/mark/storage/json_store.py +84 -0
  134. mark_sdk-0.2.0a5/src/mark/store/__init__.py +4 -0
  135. mark_sdk-0.2.0a5/src/mark/store/activity_log.py +79 -0
  136. mark_sdk-0.2.0a5/src/mark/store/sqlite.py +1045 -0
  137. mark_sdk-0.2.0a5/src/mark/sync/.gitkeep +0 -0
  138. mark_sdk-0.2.0a5/src/mark/sync/__init__.py +11 -0
  139. mark_sdk-0.2.0a5/src/mark/sync/cloud.py +193 -0
  140. mark_sdk-0.2.0a5/src/mark/sync/redaction.py +16 -0
  141. mark_sdk-0.2.0a5/src/mark/types/__init__.py +32 -0
  142. mark_sdk-0.2.0a5/src/mark/types/attribution.py +80 -0
  143. mark_sdk-0.2.0a5/src/mark/types/gap.py +95 -0
  144. mark_sdk-0.2.0a5/src/mark/types/graph.py +232 -0
  145. mark_sdk-0.2.0a5/src/mark/types/llm.py +30 -0
  146. mark_sdk-0.2.0a5/src/mark/types/memory.py +338 -0
  147. mark_sdk-0.2.0a5/uv.lock +3572 -0
@@ -0,0 +1,53 @@
1
+ name: Bug report
2
+ description: Something in mark-sdk doesn't work as documented
3
+ title: "[bug]: "
4
+ labels: ["bug", "triage"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for taking the time — bug reports like yours are how MARK gets solid.
10
+ Two minutes of detail here usually saves days of back-and-forth.
11
+ - type: input
12
+ id: version
13
+ attributes:
14
+ label: mark-sdk version
15
+ placeholder: "0.2.0a5 (python -c 'import mark; print(mark.__version__)')"
16
+ validations:
17
+ required: true
18
+ - type: input
19
+ id: python
20
+ attributes:
21
+ label: Python version and OS
22
+ placeholder: "Python 3.12 on Ubuntu 24.04"
23
+ validations:
24
+ required: true
25
+ - type: textarea
26
+ id: what-happened
27
+ attributes:
28
+ label: What happened?
29
+ description: What did you do, what did you expect, what happened instead?
30
+ validations:
31
+ required: true
32
+ - type: textarea
33
+ id: repro
34
+ attributes:
35
+ label: Minimal reproduction
36
+ description: Smallest snippet that shows the problem. Use a temp directory if it involves the store.
37
+ render: python
38
+ validations:
39
+ required: true
40
+ - type: textarea
41
+ id: logs
42
+ attributes:
43
+ label: Traceback / output
44
+ render: text
45
+ - type: checkboxes
46
+ id: checks
47
+ attributes:
48
+ label: Checks
49
+ options:
50
+ - label: I searched existing issues first
51
+ required: true
52
+ - label: This report contains no secrets or private data
53
+ required: true
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Question / discussion
4
+ url: https://github.com/emsoftanalytics/MARK-SDK/discussions
5
+ about: Ask usage questions or share what you're building with MARK.
6
+ - name: Security report (private)
7
+ url: https://github.com/emsoftanalytics/MARK-SDK/security/advisories/new
8
+ about: Please report vulnerabilities privately, never as public issues.
@@ -0,0 +1,33 @@
1
+ name: Feature request
2
+ description: Suggest an improvement to the local SDK
3
+ title: "[feature]: "
4
+ labels: ["enhancement", "triage"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Ideas welcome — especially ones grounded in a real agent workload you're building.
10
+ - type: textarea
11
+ id: problem
12
+ attributes:
13
+ label: What problem are you trying to solve?
14
+ description: Describe the agent/memory workflow where the SDK falls short.
15
+ validations:
16
+ required: true
17
+ - type: textarea
18
+ id: proposal
19
+ attributes:
20
+ label: What would you like MARK to do?
21
+ validations:
22
+ required: true
23
+ - type: textarea
24
+ id: alternatives
25
+ attributes:
26
+ label: What are you doing today instead?
27
+ - type: checkboxes
28
+ id: checks
29
+ attributes:
30
+ label: Checks
31
+ options:
32
+ - label: This fits the local-first SDK (works offline, no required services)
33
+ required: false
@@ -0,0 +1,15 @@
1
+ ## What does this PR do?
2
+
3
+ <!-- One or two sentences. Link the issue it fixes: Fixes #123 -->
4
+
5
+ ## How was it tested?
6
+
7
+ - [ ] `uv run pytest` passes locally
8
+ - [ ] New behavior is covered by a test
9
+ - [ ] Docstrings updated where behavior changed
10
+
11
+ ## Checklist
12
+
13
+ - [ ] Core stays local-first (no new required dependencies or network calls)
14
+ - [ ] Schema changes include a `_MIGRATIONS` entry and a migration test
15
+ - [ ] No secrets, keys, or private data in the diff
@@ -0,0 +1,36 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ name: Test (Python ${{ matrix.python-version }})
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: astral-sh/setup-uv@v6
22
+ - uses: actions/setup-python@v6
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+ - run: uv run --extra dev pytest
26
+
27
+ build:
28
+ name: Build distributions
29
+ runs-on: ubuntu-latest
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ - uses: astral-sh/setup-uv@v6
33
+ - run: uv build
34
+ - run: |
35
+ # Shipped artifacts must not contain tests, tutorials, or planning docs.
36
+ ! unzip -l dist/*.whl | grep -E "tests/|tutorial|PLAN\.md"
@@ -0,0 +1,57 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ name: Test (Python ${{ matrix.python-version }})
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - uses: astral-sh/setup-uv@v6
23
+ - uses: actions/setup-python@v6
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+ - run: uv run --extra dev pytest
27
+
28
+ build:
29
+ name: Build
30
+ runs-on: ubuntu-latest
31
+ needs: test
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ - uses: astral-sh/setup-uv@v6
35
+ - run: uv build
36
+ - run: |
37
+ ! unzip -l dist/*.whl | grep -E "tests/|tutorial|PLAN\.md|__pycache__|\.pyc|\.env|\.venv"
38
+ - uses: actions/upload-artifact@v4
39
+ with:
40
+ name: dist
41
+ path: dist/*
42
+
43
+ publish:
44
+ name: Publish to PyPI
45
+ runs-on: ubuntu-latest
46
+ needs: build
47
+ environment: pypi
48
+ permissions:
49
+ id-token: write
50
+ contents: read
51
+ steps:
52
+ - uses: actions/download-artifact@v4
53
+ with:
54
+ name: dist
55
+ path: dist
56
+ - uses: astral-sh/setup-uv@v6
57
+ - run: uv publish
@@ -0,0 +1,80 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ .pytest_cache/
6
+ .mypy_cache/
7
+ .ruff_cache/
8
+ .coverage
9
+ htmlcov/
10
+ dist/
11
+ build/
12
+ *.egg-info/
13
+ .venv/
14
+ venv/
15
+
16
+ # Node / frontend
17
+ node_modules/
18
+ .next/
19
+ out/
20
+ coverage/
21
+ *.tsbuildinfo
22
+
23
+ # Keep this repository scoped to the Python MARK SDK package.
24
+ /typescript/
25
+ /python/mark-cloud/
26
+ /python/mark-adapters/
27
+ /mark-cloud/
28
+ /mark-adapters/
29
+
30
+ # Local MARK/runtime state
31
+ .mark/
32
+ mark_runs/
33
+ mark_runs_test/
34
+
35
+ # Proprietary planning and system design documentation
36
+ history/
37
+ **/PLAN.md
38
+ docs/
39
+ *.design.md
40
+ *.architecture.md
41
+ *.roadmap.md
42
+ *proposal*.md
43
+ *overview*.md
44
+ recent-thoughts.md
45
+ memory.md
46
+
47
+ # Environment and secrets
48
+ .env
49
+ .env.*
50
+ !.env.example
51
+ *.pem
52
+ *.key
53
+ *.crt
54
+
55
+ # Editors and OS
56
+ .vscode/
57
+ .idea/
58
+ Thumbs.db
59
+ .DS_Store
60
+
61
+ # Logs and temp files
62
+ *.log
63
+ tmp/
64
+ temp/
65
+
66
+ # Infrastructure state
67
+ .terraform/
68
+ *.tfstate
69
+ *.tfstate.*
70
+
71
+ # Generated notebooks
72
+ .ipynb_checkpoints/
73
+ .aiStoryTeller/
74
+ # SDK tutorial run artifacts and local review output
75
+ tutorial.py
76
+ tutorial_mcp_server.py
77
+ tutorial_output/
78
+ review.json
79
+ mark_tutorial_runs/
80
+ tools/ab/results.json
@@ -0,0 +1,65 @@
1
+ # MARK Python SDK Agent Guide
2
+
3
+ This package implements the local-first MARK SDK. When working in this package, treat MARK as the agent cognitive runtime: local memory, context assembly, policies, skills, and agent wrapping.
4
+
5
+ ## Product Boundary
6
+
7
+ - `mark` is local-first and must work without network, Docker, cloud accounts, or hosted APIs.
8
+ - `mark-cloud` owns HTTP/cloud sync, auth, tenancy, and hosted control-plane behavior.
9
+ - `mark-adapters` owns LangChain, MCP, LangGraph, and framework-specific integrations.
10
+ - Do not turn `mark` into a presentation app or product UI.
11
+
12
+ ## Agent Usage Pattern
13
+
14
+ When demonstrating MARK usage, show the same task without MARK and with MARK.
15
+
16
+ When MARK is active, treat it as persistent working memory, not an optional lookup step. The intended loop is:
17
+
18
+ - recall from MARK before planning,
19
+ - ground memory against current evidence,
20
+ - act with remembered context,
21
+ - reflect on durable outcomes,
22
+ - remember verified facts, decisions, and procedures for future agents.
23
+
24
+ Use MARK to improve:
25
+
26
+ - recall: stored project facts are retrieved,
27
+ - planning: steps are grounded in project context,
28
+ - reasoning: decisions cite known constraints,
29
+ - continuity: durable outcomes are written back.
30
+
31
+ ## SDK Integration Modes
32
+
33
+ Agents should be able to use MARK as:
34
+
35
+ - direct runtime: `Mark.local()` and `mark.wrap_agent(...)`,
36
+ - tool: callable retrieval/write functions,
37
+ - skill: `src/mark/skills/mark-usage/SKILL.md`,
38
+ - MCP: protocol server exposing retrieve/write/list operations,
39
+ - middleware: context retrieval before model/tool execution and memory writeback after accepted outcomes.
40
+
41
+ Middleware and direct runtime examples should make MARK feel natural: the agent should receive context before it reasons and save durable outcomes after the task is accepted.
42
+
43
+ ## Development Rules
44
+
45
+ - Keep local SDK dependencies minimal.
46
+ - Add tests with every behavioral change.
47
+ - Do not require LangChain, MCP, or cloud packages in the local SDK core.
48
+ - Optional examples may mention LangChain, but local tests must run without provider API keys.
49
+ - Do not store secrets in examples or memory fixtures except fake redaction test values.
50
+ - Package non-Python skill assets explicitly so installed users can load them through `importlib.resources`.
51
+
52
+ ## Verification
53
+
54
+ From `sdk/python/mark`, run:
55
+
56
+ ```bash
57
+ uv run --extra dev pytest
58
+ uv build
59
+ ```
60
+
61
+ Before committing, verify the package contains the MARK usage skill:
62
+
63
+ ```bash
64
+ uv run python -B -c "from importlib.resources import files; print(files('mark.skills').joinpath('mark-usage/SKILL.md').read_text().splitlines()[1])"
65
+ ```
@@ -0,0 +1,250 @@
1
+ # MARK Python SDK Architecture
2
+
3
+ The MARK Python SDK is a local-first runtime for agent memory. It is the open,
4
+ MIT-licensed layer that helps agents recall project facts, organize working
5
+ context, and expose memory to tools, middleware, and framework adapters.
6
+
7
+ Everything documented here runs locally. Hosted MARK services are separate
8
+ products that connect through the SDK's public plugin hooks; their design is
9
+ out of scope for this document.
10
+
11
+ ## Entrypoints
12
+
13
+ ### `Mark.local()`
14
+
15
+ `Mark.local()` is the public entrypoint for local use cases.
16
+
17
+ It is designed for:
18
+
19
+ - tutorials and quick scripts,
20
+ - lightweight coding agents,
21
+ - local project memory,
22
+ - SQLite persistence in `.mark/memory.db`,
23
+ - direct use as a tool, middleware helper, or agent wrapper.
24
+
25
+ It wires:
26
+
27
+ - `MarkRuntime.local()` as the runtime engine,
28
+ - `SimpleMemory` as the ergonomic block/retrieve surface,
29
+ - `ContextBuilder`,
30
+ - `PolicyRegistry`,
31
+ - `SkillRegistry`,
32
+ - `MarkAgent`.
33
+
34
+ ```python
35
+ from mark import Mark
36
+
37
+ with Mark.local(".") as mark:
38
+ mark.memory.block("project").write("The API framework is FastAPI.")
39
+ print(mark.memory.retrieve("Which API framework?").as_text())
40
+ ```
41
+
42
+ Advanced path:
43
+
44
+ ```python
45
+ with Mark.local(".") as mark:
46
+ agent = mark.runtime.memory("coder")
47
+ agent.store_sync("FastAPI handles routing.")
48
+ mark.runtime.run_cycle("coder") # consolidate + deduplicate + prune
49
+ mark.runtime.integrity_check() # []
50
+ ```
51
+
52
+ ### `MarkRuntime.local()`
53
+
54
+ `MarkRuntime.local()` is the explicit runtime engine. Most developers should
55
+ start with `Mark.local()`, but framework integrations and advanced
56
+ applications can use `MarkRuntime` directly.
57
+
58
+ It wires:
59
+
60
+ - `LocalMemoryStore` with SQLite,
61
+ - `HashEmbeddingProvider` or developer-provided `EmbeddingProvider`,
62
+ - `VectorIndex`,
63
+ - `RetrievalPipeline`,
64
+ - `PluginRegistry`,
65
+ - `MarkMemory`,
66
+ - `GlobalMemoryBus`,
67
+ - `TrustAwareGlobalMemoryBus`,
68
+ - `LocalTracer`,
69
+ - `GovernanceAuditLog`.
70
+
71
+ ## Memory Model
72
+
73
+ ```text
74
+ fragment → atomic evidence (content, session, tags, importance, confidence)
75
+ node → semantic anchor built from fragments (character, fact, location…)
76
+ edge → directed, typed, weighted relation between nodes
77
+ block → bounded set of fragments, nodes, and the edges between them
78
+ chain → blocks sealed and linked forward/backward per agent
79
+ ```
80
+
81
+ An agent owns a namespace. Sessions partition it (`session_id`,
82
+ `session_prefix`), tags narrow it, and blocks group it into inspectable units.
83
+
84
+ ### Memory Blocks And Provenance
85
+
86
+ Blocks are graph containers: a block can represent a topic within a session,
87
+ an entire session, or a world-bible scope.
88
+
89
+ - Node membership is many-to-many (`block_nodes`), so canonical entities are
90
+ never duplicated across blocks.
91
+ - Edges may be scoped to a block; scoped edges only connect member nodes.
92
+ - Blocks connect to other blocks through directed `BlockLink`s and are
93
+ traversable forward and backward, like nodes through edges.
94
+ - Sealing (`BlockChain.seal`) computes a deterministic SHA-256 content hash
95
+ over immutable member fields and links the block to the previously sealed
96
+ block (`prev_block_hash`), forming a local, tamper-evident hash chain.
97
+ - `verify()` pinpoints corrupted, missing, or injected members;
98
+ `verify_chain()` checks the whole chain.
99
+ - Quarantining a block removes its members from retrieval and traversal
100
+ without affecting any other block or the agent's function.
101
+ - Mutable plasticity fields (importance, access counts, edge weights) are
102
+ excluded from hashes so reinforcement never breaks a seal.
103
+
104
+ ## Lifecycle
105
+
106
+ | Method | Role |
107
+ |---|---|
108
+ | `working_memory(agent_id)` | TTL-bound short-term memory |
109
+ | `consolidate(agent_id)` | Governed working-memory promotion |
110
+ | `deduplicate(agent_id)` | Embedding cluster merge and provenance |
111
+ | `prune(agent_id)` | Decay, fragment pruning, edge dissolution |
112
+ | `run_cycle(agent_id)` | Consolidate, deduplicate, prune |
113
+ | `integrity_check()` | SQLite health check |
114
+
115
+ Retrieval is live. Each retrieved fragment is touched, access count increases,
116
+ importance can strengthen through Hebbian reinforcement, and co-retrieved graph
117
+ edges strengthen through co-activation. Promoted/permanent memories are exempt
118
+ from decay.
119
+
120
+ Consolidation is governed locally before promotion. `ConsolidationGate` redacts
121
+ common secrets/PII, blocks empty or low-confidence content, rejects failure
122
+ artifacts, and can reject exact duplicate hashes. `MarkRuntime` keeps an
123
+ in-process `GovernanceAuditLog`.
124
+
125
+ Deduplication is transparent and local. The SDK clusters stored embeddings,
126
+ keeps the highest-importance canonical fragment, records `merged_from_ids`,
127
+ and reattaches graph nodes from deleted duplicates to the kept fragment.
128
+
129
+ ## Architecture Diagram
130
+
131
+ ```mermaid
132
+ flowchart TD
133
+ Dev[Developer Agent] --> Simple["Mark.local()"]
134
+
135
+ Simple --> SM[SimpleMemory]
136
+ Simple --> Skills[SkillRegistry]
137
+ Simple --> Policies[PolicyRegistry]
138
+ Simple --> Agent[MarkAgent]
139
+ Simple --> RT[MarkRuntime]
140
+
141
+ SM --> RT
142
+ RT --> SQLite[(LocalMemoryStore SQLite)]
143
+ RT --> Embeddings[EmbeddingProvider]
144
+ RT --> Vector[VectorIndex]
145
+ RT --> Retrieval[RetrievalPipeline]
146
+ RT --> Blocks[BlockGraph / BlockChain]
147
+ RT --> Bus[GlobalMemoryBus]
148
+ RT --> TrustBus[TrustAwareGlobalMemoryBus]
149
+ RT --> Obs[LocalTracer]
150
+ RT --> Governance[Local Governance]
151
+ RT --> Plugins[PluginRegistry]
152
+ RT --> Lifecycle[Lifecycle]
153
+
154
+ Retrieval --> Hebbian[Hebbian Reinforcement]
155
+ Lifecycle --> Consolidation[ConsolidationManager]
156
+ Lifecycle --> Dedup[DeduplicationConsolidator]
157
+ Lifecycle --> Pruner[MemoryPruner]
158
+ Consolidation --> Governance
159
+ ```
160
+
161
+ ## Package Boundary
162
+
163
+ This package includes:
164
+
165
+ - memory data contracts,
166
+ - SQLite storage with schema versioning and in-place migrations,
167
+ - local retrieval, graph expansion, and gap reporting,
168
+ - graph-scoped memory blocks, block links, seal/verify, and quarantine,
169
+ - working memory, governed consolidation, deduplication, and pruning,
170
+ - graph nodes, edges, neighborhoods, and graph-connected context,
171
+ - session-aware retrieval and session activity logs,
172
+ - local governance heuristics and in-process audit logs,
173
+ - local observability events, session traces, and JSONL replay,
174
+ - local sync delta preparation with redaction,
175
+ - trust-aware global memory bus,
176
+ - plugin interfaces and hook constants,
177
+ - optional framework adapters and skills.
178
+
179
+ Hosted services, managed infrastructure, and commercial features are not part
180
+ of this package. The only paths from the SDK outward are `PluginRegistry`
181
+ hooks and clients that the developer explicitly supplies.
182
+
183
+ ## Tool, Middleware, And Adapters
184
+
185
+ MARK can be used in three common ways:
186
+
187
+ - As a tool: the agent explicitly calls MARK retrieval.
188
+ - As middleware: MARK injects relevant memory before agent planning and records
189
+ observations after tool/action results.
190
+ - As an MCP server: `mark.adapters.mcp` exposes local memory operations to any
191
+ MCP-compatible client.
192
+
193
+ Framework adapters ship inside `mark-sdk` under `mark.adapters` with optional
194
+ dependency extras:
195
+
196
+ ```text
197
+ mark/
198
+ adapters/
199
+ backend.py MarkBackend protocol + LocalMarkBackend
200
+ langchain/ tools + AgentMiddleware
201
+ mcp/ MCP server factory
202
+ ```
203
+
204
+ ```bash
205
+ pip install "mark-sdk[langchain]"
206
+ pip install "mark-sdk[mcp]"
207
+ pip install "mark-sdk[adapters]"
208
+ ```
209
+
210
+ Adapter modules are thin framework glue over public MARK APIs. Adapter
211
+ namespaces without complete implementations are excluded from distributions
212
+ until they have real code and tests.
213
+
214
+ ## Sync And Observability
215
+
216
+ The SDK can prepare local sync envelopes but does not implement any remote
217
+ transport. `CloudSync.prepare_delta()` returns a `SyncDelta` containing
218
+ redacted fragments, optional local events, options, and stats.
219
+ `CloudSync.sync()` forwards that envelope only when a caller supplies a client
220
+ object with `upload_delta(delta)`.
221
+
222
+ ```mermaid
223
+ flowchart LR
224
+ Runtime[MarkRuntime] --> Store[(SQLite)]
225
+ Runtime --> Tracer[LocalTracer]
226
+ Store --> Prepare[CloudSync.prepare_delta]
227
+ Tracer --> Prepare
228
+ Prepare --> Delta[SyncDelta]
229
+ Delta --> OptionalClient[Developer-supplied client]
230
+ ```
231
+
232
+ `LocalTracer` is available through `MarkRuntime.tracer()`, and
233
+ `MarkRuntime.session_trace(session_id)` provides a session-scoped view of
234
+ local events.
235
+
236
+ ## Trust-Aware Bus
237
+
238
+ `TrustAwareGlobalMemoryBus` wraps `GlobalMemoryBus` with publisher trust,
239
+ subscriptions, snapshots, and trust-filtered retrieval. Messages persist as
240
+ global-bus fragments with trust tags and can be rehydrated when a runtime
241
+ reopens the same SQLite store.
242
+
243
+ ```mermaid
244
+ flowchart TB
245
+ Publisher[Agent Publisher] --> TrustBus[TrustAwareGlobalMemoryBus]
246
+ TrustBus --> Store[(SQLite Global Fragments)]
247
+ TrustBus --> Snapshot[BusSnapshot]
248
+ TrustBus --> Subscription[BusSubscription]
249
+ Subscription --> Consumer[Consumer Agent]
250
+ ```