openmnemex 0.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.
- openmnemex/__init__.py +36 -0
- openmnemex/data/config/mnemex.config.md +72 -0
- openmnemex/data/integrations/opencode/mnemex.ts +86 -0
- openmnemex/data/templates/binding.template.md +23 -0
- openmnemex/data/templates/gitattributes.template +29 -0
- openmnemex/data/templates/gitignore.template +10 -0
- openmnemex/data/templates/index.template.md +20 -0
- openmnemex/data/templates/node.template.md +38 -0
- openmnemex/data/templates/procedures/capture.core.md +150 -0
- openmnemex/data/templates/procedures/curate.core.md +13 -0
- openmnemex/data/templates/procedures/fragments/_digests/capture.md +4 -0
- openmnemex/data/templates/procedures/fragments/_digests/ingest.md +9 -0
- openmnemex/data/templates/procedures/fragments/_digests/promote.md +4 -0
- openmnemex/data/templates/procedures/fragments/_digests/read.md +4 -0
- openmnemex/data/templates/procedures/fragments/capture/bind_status.claude.md +2 -0
- openmnemex/data/templates/procedures/fragments/capture/bind_status.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_add.claude.md +14 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_add.mcp.md +2 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_drop_flag.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_drop_flag.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_drop_flag2.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_drop_flag2.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_status_budget.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_status_budget.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_status_list.claude.md +3 -0
- openmnemex/data/templates/procedures/fragments/capture/capture_status_list.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/glean_step.claude.md +3 -0
- openmnemex/data/templates/procedures/fragments/capture/glean_step.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/init.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/init.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/promote.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/capture/promote.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/curate/capture_discard_all.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/curate/capture_discard_all.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/curate/capture_drop.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/curate/capture_drop.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/curate/capture_status_inline.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/curate/capture_status_inline.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/curate/status.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/curate/status.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/curate/trigger_condition.claude.md +3 -0
- openmnemex/data/templates/procedures/fragments/curate/trigger_condition.mcp.md +3 -0
- openmnemex/data/templates/procedures/fragments/promote/bulk_mode.claude.md +56 -0
- openmnemex/data/templates/procedures/fragments/promote/bulk_mode.mcp.md +28 -0
- openmnemex/data/templates/procedures/fragments/promote/consolidate_invoke.claude.md +2 -0
- openmnemex/data/templates/procedures/fragments/promote/consolidate_invoke.mcp.md +3 -0
- openmnemex/data/templates/procedures/fragments/promote/preflight.claude.md +18 -0
- openmnemex/data/templates/procedures/fragments/promote/preflight.mcp.md +10 -0
- openmnemex/data/templates/procedures/fragments/promote/retry_push.claude.md +11 -0
- openmnemex/data/templates/procedures/fragments/promote/retry_push.mcp.md +8 -0
- openmnemex/data/templates/procedures/fragments/promote/step1_flush.claude.md +4 -0
- openmnemex/data/templates/procedures/fragments/promote/step1_flush.mcp.md +4 -0
- openmnemex/data/templates/procedures/fragments/promote/step5_apply.claude.md +30 -0
- openmnemex/data/templates/procedures/fragments/promote/step5_apply.mcp.md +31 -0
- openmnemex/data/templates/procedures/fragments/read/bind_status.claude.md +2 -0
- openmnemex/data/templates/procedures/fragments/read/bind_status.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/capture.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/capture.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/empty_fork_check.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/empty_fork_check.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/ingest.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/ingest.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/init.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/init.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/promote.claude.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/promote.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/read_cluster.claude.md +3 -0
- openmnemex/data/templates/procedures/fragments/read/read_cluster.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/read_frontier.claude.md +3 -0
- openmnemex/data/templates/procedures/fragments/read/read_frontier.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/read_nodes.claude.md +4 -0
- openmnemex/data/templates/procedures/fragments/read/read_nodes.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/record_usage_revalidated.claude.md +4 -0
- openmnemex/data/templates/procedures/fragments/read/record_usage_revalidated.mcp.md +1 -0
- openmnemex/data/templates/procedures/fragments/read/record_usage_role.claude.md +4 -0
- openmnemex/data/templates/procedures/fragments/read/record_usage_role.mcp.md +1 -0
- openmnemex/data/templates/procedures/promote.core.md +141 -0
- openmnemex/data/templates/procedures/read.core.md +151 -0
- openmnemex/data/templates/registry.template.md +2 -0
- openmnemex/data/templates/user-config.template.md +15 -0
- openmnemex/mnx_binding.py +1078 -0
- openmnemex/mnx_common.py +593 -0
- openmnemex/mnx_compact.py +327 -0
- openmnemex/mnx_config.py +514 -0
- openmnemex/mnx_decay.py +136 -0
- openmnemex/mnx_doctor.py +447 -0
- openmnemex/mnx_er.py +328 -0
- openmnemex/mnx_glean.py +146 -0
- openmnemex/mnx_hooks.py +767 -0
- openmnemex/mnx_index.py +471 -0
- openmnemex/mnx_ingest.py +516 -0
- openmnemex/mnx_init.py +347 -0
- openmnemex/mnx_install.py +741 -0
- openmnemex/mnx_lock.py +259 -0
- openmnemex/mnx_mcp.py +1282 -0
- openmnemex/mnx_mesh.py +254 -0
- openmnemex/mnx_node.py +373 -0
- openmnemex/mnx_phonebook.py +352 -0
- openmnemex/mnx_procedures.py +202 -0
- openmnemex/mnx_promote.py +792 -0
- openmnemex/mnx_read.py +305 -0
- openmnemex/mnx_regen.py +199 -0
- openmnemex/mnx_resolve.py +208 -0
- openmnemex/mnx_simindex.py +194 -0
- openmnemex/mnx_stage.py +681 -0
- openmnemex/mnx_stamp.py +202 -0
- openmnemex/mnx_status.py +232 -0
- openmnemex-0.1.0.dist-info/METADATA +426 -0
- openmnemex-0.1.0.dist-info/RECORD +113 -0
- openmnemex-0.1.0.dist-info/WHEEL +5 -0
- openmnemex-0.1.0.dist-info/entry_points.txt +3 -0
- openmnemex-0.1.0.dist-info/licenses/LICENSE +21 -0
- openmnemex-0.1.0.dist-info/top_level.txt +1 -0
openmnemex/__init__.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""openmnemex — the OpenMnemex Context Graph engine, packaged (plan v2 §7, commit 0a).
|
|
2
|
+
|
|
3
|
+
This bridge makes the flat ``scripts/`` engine importable BOTH ways without touching the
|
|
4
|
+
``mnx_*`` modules themselves:
|
|
5
|
+
|
|
6
|
+
* **repo / Claude-plugin path (unchanged):** ``python3 scripts/mnx_stage.py …`` and plain
|
|
7
|
+
``import mnx_stage`` with ``scripts/`` on ``sys.path`` — the modules import each other
|
|
8
|
+
flat (``import mnx_common``), exactly as before. Running a script directly never
|
|
9
|
+
executes this file.
|
|
10
|
+
* **packaged path (pip / uvx):** ``pyproject.toml`` maps this directory to the
|
|
11
|
+
``openmnemex`` package. Importing ``openmnemex`` (or any ``openmnemex.mnx_*``) runs
|
|
12
|
+
this bridge first, which puts the package directory on ``sys.path`` so the flat
|
|
13
|
+
intra-engine imports keep resolving, then eagerly aliases every engine module as
|
|
14
|
+
``openmnemex.<name>``.
|
|
15
|
+
|
|
16
|
+
The eager aliasing guarantees a SINGLE module identity per engine module — ``import
|
|
17
|
+
mnx_common`` and ``from openmnemex import mnx_common`` return the very same object — so
|
|
18
|
+
module-level state can never fork between the two import styles (the dual-identity trap
|
|
19
|
+
of path-bridged packages). Guarded by tests/test_packaging_imports.py.
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import importlib
|
|
24
|
+
import sys
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
_PKG_DIR = Path(__file__).resolve().parent
|
|
28
|
+
|
|
29
|
+
if str(_PKG_DIR) not in sys.path:
|
|
30
|
+
sys.path.insert(0, str(_PKG_DIR))
|
|
31
|
+
|
|
32
|
+
for _mod_file in sorted(_PKG_DIR.glob("mnx_*.py")):
|
|
33
|
+
_name = _mod_file.stem
|
|
34
|
+
_module = importlib.import_module(_name) # flat identity, same as the plugin path
|
|
35
|
+
sys.modules[f"{__name__}.{_name}"] = _module # `import openmnemex.mnx_x` → same object
|
|
36
|
+
globals()[_name] = _module # `from openmnemex import mnx_x`
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
config_version: 1
|
|
3
|
+
|
|
4
|
+
# --- Decay (the ONE knob you set) ---
|
|
5
|
+
half_life_days: 180
|
|
6
|
+
pattern_halflife_bonus: 0.30 # patterns persist ~30% longer than domain facts (derived)
|
|
7
|
+
|
|
8
|
+
# --- Tiers ---
|
|
9
|
+
hot_k: 12
|
|
10
|
+
warm_band: 0.25
|
|
11
|
+
cold_ttl_days: 120
|
|
12
|
+
cold_recall_multiplier: 1.6
|
|
13
|
+
strength_max: 1.0
|
|
14
|
+
|
|
15
|
+
# --- Freshness (revalidation horizon; independent of decay) ---
|
|
16
|
+
freshness_ttl_days: 30 # a fact goes stale this long after it was last verified
|
|
17
|
+
freshness_pattern_bonus: 0.30 # patterns get a ~30% longer horizon (derived; you set one number)
|
|
18
|
+
|
|
19
|
+
# --- Usage boosts ---
|
|
20
|
+
boost:
|
|
21
|
+
contributed: 1.0
|
|
22
|
+
consulted: 0.5
|
|
23
|
+
traversed: 0.0
|
|
24
|
+
|
|
25
|
+
# --- Budget / scale ---
|
|
26
|
+
node_budget: 35
|
|
27
|
+
|
|
28
|
+
# --- Maintenance ---
|
|
29
|
+
compaction_cadence_days: 14
|
|
30
|
+
reconcile_cold_on: update # always | update | never
|
|
31
|
+
|
|
32
|
+
# --- Death policy ---
|
|
33
|
+
purge_dead: false # false = tombstone-and-retain (recommended)
|
|
34
|
+
|
|
35
|
+
# --- Ingestion (bootstrapping the graph from an existing repo; docs/corpus-ingestion.md) ---
|
|
36
|
+
ingest_bulk_soft_atoms: 500 # a bulk batch past this warns (drained continuously by --bulk promote)
|
|
37
|
+
ingest_bulk_hard_atoms: 5000 # a bulk batch refuses past this (drain it first)
|
|
38
|
+
ingest_max_atoms_per_run: 2000 # per-run cost ceiling; excess resumes on the next run
|
|
39
|
+
er_match_threshold: 0.85 # entity-resolution: ≥ this score → same entity (deterministic merge)
|
|
40
|
+
er_possible_threshold: 0.60 # [possible, match) → the HITL "⚠ suggested" band (LLM judge)
|
|
41
|
+
code_extract: gated # gated | deep | off — code value-gate (public/documented/config-only)
|
|
42
|
+
# max_glean_passes lives in USER config (~/.claude/mnemex/config.md; default 2) — glean is shared with capture.
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
# Mnemex configuration
|
|
46
|
+
|
|
47
|
+
This file controls how your knowledge graph remembers and forgets. It is plain Markdown with a YAML
|
|
48
|
+
front-matter block, so it is readable by both you and the protocol.
|
|
49
|
+
|
|
50
|
+
## The one decision that matters
|
|
51
|
+
|
|
52
|
+
You set **`half_life_days`** — how long an *unused* domain fact takes to lose half its relevance.
|
|
53
|
+
Everything else has a sensible default. Patterns (the "how") automatically persist longer than domain
|
|
54
|
+
facts (the "what") by `pattern_halflife_bonus` (default +30%); you do not tune two rates.
|
|
55
|
+
|
|
56
|
+
## When you change a value
|
|
57
|
+
|
|
58
|
+
Bump `config_version`. The next consolidation (the back half of `mnx-promote`) will **re-normalize**
|
|
59
|
+
stored relevance so nothing jumps tiers abruptly, and `mnx-read` will warn you if a change is pending.
|
|
60
|
+
See `docs/configuration.md`.
|
|
61
|
+
|
|
62
|
+
## Quick guidance
|
|
63
|
+
|
|
64
|
+
- Start with a **long** half-life and **generous** `cold_ttl_days`; tighten once you have observed real
|
|
65
|
+
usage. Nothing should die prematurely while you are still learning the rhythm of your graph.
|
|
66
|
+
- `hot_k` is how many nodes you want visible at *zero* extra read cost (chunk-1). 12–20 is reasonable.
|
|
67
|
+
- `node_budget` exists to keep reconciliation matching fast on writes; size it by write-path comfort.
|
|
68
|
+
- Keep `purge_dead: false` for audit-friendly, recoverable forgetting (tombstones, not deletion).
|
|
69
|
+
- `freshness_ttl_days` is a **separate** clock from decay: it is about whether a fact is still *true*, not
|
|
70
|
+
whether it is still *used*. A fact that is 40 days past verification is flagged `stale` on read so the agent
|
|
71
|
+
re-checks it — even if it is hot. Tag `volatility: timeless` on eternal facts (also stops them ever dying)
|
|
72
|
+
and `volatility: volatile` on fast-rotting ones. See `docs/freshness-and-revalidation.md`.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// OpenCode adapter (multi-agent plan v2, Phase 4 / commit 4a).
|
|
2
|
+
//
|
|
3
|
+
// Thin translator only: normalizes OpenCode's plugin event shape into the host-neutral
|
|
4
|
+
// event dict `mnx_hooks.core_*()` expects (see scripts/mnx_hooks.py), then execs the same
|
|
5
|
+
// Python engine Claude Code's hooks/hooks.json shells out to. No side-effect logic lives here.
|
|
6
|
+
//
|
|
7
|
+
// Mapping (session-lifecycle events only, per plan scope):
|
|
8
|
+
// session.created -> session-start (consent primer + graph sync)
|
|
9
|
+
// session.idle -> stop (usage-stamp flush + capture nudge bookkeeping)
|
|
10
|
+
// session.compacted -> pre-compact (re-arms the Stop nudge for the lost window)
|
|
11
|
+
// dispose() -> session-end (safety-net flush; best-effort synthetic session id,
|
|
12
|
+
// since OpenCode's dispose() carries no event payload)
|
|
13
|
+
//
|
|
14
|
+
// `session.compacted` (stable, post-hoc) is used instead of the experimental
|
|
15
|
+
// `experimental.session.compacting` pre-hook: core_pre_compact() is side-effect-only and never
|
|
16
|
+
// injects context into the compaction itself, so before-vs-after timing does not matter for us,
|
|
17
|
+
// and the stable event is a safer bet across OpenCode versions (§12 item 2 — re-verify the event
|
|
18
|
+
// API at integration time; https://opencode.ai/docs/plugins/ as of 2026-07).
|
|
19
|
+
//
|
|
20
|
+
// Delivery gap (documented in LIMITATIONS.md #3): mnx_hooks.py's HookOutcome (context/block/
|
|
21
|
+
// notice text -- e.g. the session-start consent primer) has no rendering surface here; OpenCode's
|
|
22
|
+
// `event` hook is fire-and-forget with no return channel back into the model's context. Only the
|
|
23
|
+
// underlying SIDE EFFECTS run (graph sync, usage-stamp flush, marker bookkeeping, doctor checks
|
|
24
|
+
// via the pre-compact re-arm); the advisory/consent prompts themselves reach the model via
|
|
25
|
+
// AGENTS.md instructions instead, same as any Assisted-tier host. Do not add a `console.log` of
|
|
26
|
+
// the hook's stdout here as a workaround -- it would print to OpenCode's own process output, not
|
|
27
|
+
// the model's context, and would look like working delivery while doing nothing.
|
|
28
|
+
// Scope boundary: this path is correct for this file's location in THIS repo checkout
|
|
29
|
+
// (integrations/opencode/mnemex.ts -> ../../scripts/mnx_hooks.py). When Phase 5's installer
|
|
30
|
+
// copies/emits this file into a consumer project's `.opencode/plugin/mnemex.ts`, that copy needs
|
|
31
|
+
// an installed-package-relative (or absolute, baked in at install time) path instead — rewriting
|
|
32
|
+
// HOOKS_SCRIPT for the target layout is Phase 5's job (commit 5b), not done here.
|
|
33
|
+
import type { Plugin } from "@opencode-ai/plugin"
|
|
34
|
+
|
|
35
|
+
const HOOKS_SCRIPT = new URL("../../scripts/mnx_hooks.py", import.meta.url).pathname
|
|
36
|
+
|
|
37
|
+
async function runHook(
|
|
38
|
+
cwd: string,
|
|
39
|
+
subcommand: string,
|
|
40
|
+
event: Record<string, unknown>,
|
|
41
|
+
): Promise<void> {
|
|
42
|
+
try {
|
|
43
|
+
const proc = Bun.spawn(["python3", HOOKS_SCRIPT, subcommand], {
|
|
44
|
+
cwd,
|
|
45
|
+
stdin: "pipe",
|
|
46
|
+
stdout: "ignore",
|
|
47
|
+
stderr: "ignore",
|
|
48
|
+
})
|
|
49
|
+
proc.stdin.write(JSON.stringify(event))
|
|
50
|
+
proc.stdin.end()
|
|
51
|
+
await proc.exited
|
|
52
|
+
} catch {
|
|
53
|
+
// advisory hooks must never break a session — same fail-open contract as the Claude adapter
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const MnemexPlugin: Plugin = async ({ directory }) => {
|
|
58
|
+
let lastSessionID = ""
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
event: async ({ event }) => {
|
|
62
|
+
switch (event.type) {
|
|
63
|
+
case "session.created": {
|
|
64
|
+
const sid = (event.properties as any)?.info?.id ?? ""
|
|
65
|
+
lastSessionID = sid
|
|
66
|
+
await runHook(directory, "session-start", { session_id: sid })
|
|
67
|
+
break
|
|
68
|
+
}
|
|
69
|
+
case "session.idle": {
|
|
70
|
+
const sid = (event.properties as any)?.sessionID ?? lastSessionID
|
|
71
|
+
lastSessionID = sid
|
|
72
|
+
await runHook(directory, "stop", { session_id: sid })
|
|
73
|
+
break
|
|
74
|
+
}
|
|
75
|
+
case "session.compacted": {
|
|
76
|
+
const sid = (event.properties as any)?.sessionID ?? lastSessionID
|
|
77
|
+
await runHook(directory, "pre-compact", { session_id: sid })
|
|
78
|
+
break
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
dispose: async () => {
|
|
83
|
+
if (lastSessionID) await runHook(directory, "session-end", { session_id: lastSessionID })
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Project-level Mnemex binding. Lives at <project-repo>/.mnemex.md.
|
|
3
|
+
# Tells the plugin which knowledge graph THIS project reads from and writes to.
|
|
4
|
+
# Overrides the user-level default (~/.claude/mnemex/config.md).
|
|
5
|
+
#
|
|
6
|
+
# Set EXACTLY ONE of graph_remote / graph_path (if both are set, graph_path wins + a warning):
|
|
7
|
+
graph_remote: # a git remote — cloned & synced; writes commit + push. e.g. git@github.com:acme/payments-knowledge.git
|
|
8
|
+
graph_path: # a local folder — used in place, no clone/push. e.g. ~/knowledge/payments
|
|
9
|
+
default_team: # optional — default routing team for this project
|
|
10
|
+
author: # optional — identity for usage stamps / commits
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Mnemex binding
|
|
14
|
+
|
|
15
|
+
This project's work is captured into the knowledge graph at `graph_remote` (a git repo) or `graph_path`
|
|
16
|
+
(a local folder). The graph itself — including its decay/tier behavior (`mnemex.config.md`) — lives in
|
|
17
|
+
that separate location, not here.
|
|
18
|
+
|
|
19
|
+
A **local folder** that is itself a git repo gets a local commit per change; a plain (non-git) folder
|
|
20
|
+
gets an append-only audit trail in its `.mnemex/history.log`. A **git remote** commits and pushes.
|
|
21
|
+
|
|
22
|
+
Commit this file to share the binding with the team, or add `.mnemex.md` to `.gitignore` to keep it
|
|
23
|
+
personal. See `docs/binding-and-graph-sync.md`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Mnemex: truth unions, derived regenerates.
|
|
2
|
+
# Drop this into a knowledge-graph repo as `.gitattributes` (mnx-init does this).
|
|
3
|
+
# The `mnx-regen` driver COMMAND is registered per-clone by `mnx_regen.py install`
|
|
4
|
+
# (mnx-init runs it; mnx-doctor verifies it). Without the command registered, git falls
|
|
5
|
+
# back to a normal 3-way merge — so the doctor flags an unregistered driver.
|
|
6
|
+
|
|
7
|
+
# --- TRUTH: append-only logs concatenate cleanly (built-in union driver) ---
|
|
8
|
+
registry.md merge=union
|
|
9
|
+
**/registry.md merge=union
|
|
10
|
+
.mnemex/highwater/** merge=union
|
|
11
|
+
|
|
12
|
+
# --- DERIVED: discard both sides, regenerate from truth on conflict ---
|
|
13
|
+
index.md merge=mnx-regen
|
|
14
|
+
index.[0-9][0-9][0-9].md merge=mnx-regen
|
|
15
|
+
**/index.md merge=mnx-regen
|
|
16
|
+
**/index.[0-9][0-9][0-9].md merge=mnx-regen
|
|
17
|
+
phonebook.md merge=mnx-regen
|
|
18
|
+
**/phonebook.md merge=mnx-regen
|
|
19
|
+
cross-links.md merge=mnx-regen
|
|
20
|
+
**/cross-links.md merge=mnx-regen
|
|
21
|
+
# split tier files (when tier_files: true)
|
|
22
|
+
warm.md merge=mnx-regen
|
|
23
|
+
cold.md merge=mnx-regen
|
|
24
|
+
dead.md merge=mnx-regen
|
|
25
|
+
cold.[0-9][0-9][0-9].md merge=mnx-regen
|
|
26
|
+
**/warm.md merge=mnx-regen
|
|
27
|
+
**/cold.md merge=mnx-regen
|
|
28
|
+
**/dead.md merge=mnx-regen
|
|
29
|
+
**/cold.[0-9][0-9][0-9].md merge=mnx-regen
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Mnemex knowledge-graph .gitignore
|
|
2
|
+
# Ignore ONLY transient runtime state. Durable state (.mnemex/highwater/,
|
|
3
|
+
# config_version, last_compaction) is intentionally committed for reproducibility.
|
|
4
|
+
|
|
5
|
+
# Transient: a live/stranded team or cluster lock, and an in-flight pass plan.
|
|
6
|
+
.mnemex/locks/
|
|
7
|
+
.mnemex/plans/
|
|
8
|
+
|
|
9
|
+
# OS
|
|
10
|
+
.DS_Store
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# <folder-name> — index
|
|
2
|
+
> One-line description of this cluster. Routing decisions are made on this line. <!-- chunk 1 -->
|
|
3
|
+
|
|
4
|
+
## Children <!-- chunk 1 -->
|
|
5
|
+
- <child-folder>/ — one-line description
|
|
6
|
+
<!-- (leaf clusters: "none") -->
|
|
7
|
+
|
|
8
|
+
## Hot <!-- chunk 1 tail; top-K -->
|
|
9
|
+
| id | type | summary | aliases | strength | last_update | stale_after |
|
|
10
|
+
|----|------|---------|---------|----------|-------------|-------------|
|
|
11
|
+
|
|
12
|
+
## Warm <!-- chunk 2 -->
|
|
13
|
+
| id | type | summary | aliases | strength | last_update | stale_after |
|
|
14
|
+
|----|------|---------|---------|----------|-------------|-------------|
|
|
15
|
+
|
|
16
|
+
## Cold <!-- chunk 3+ -->
|
|
17
|
+
| id | type | summary | aliases | strength | last_update | stale_after | expires |
|
|
18
|
+
|----|------|---------|---------|----------|-------------|-------------|---------|
|
|
19
|
+
|
|
20
|
+
<!-- GENERATED FILE. Do not hand-edit. Regenerated by mnx-promote apply and mnx-doctor --fix. -->
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: REPLACE-with-stable-slug # [a-z0-9-]+, assigned at creation, NEVER changes
|
|
3
|
+
type: domain # domain | pattern
|
|
4
|
+
title: Human-readable title (may change freely)
|
|
5
|
+
summary: One line that lands in the index verbatim — the match + routing surface.
|
|
6
|
+
aliases: [other name, abbreviation, synonym]
|
|
7
|
+
domain: [sub-domain] # may be a LIST (a node can belong to >1 sub-index)
|
|
8
|
+
status: active # active | dead (retired-why is a field: superseded-by, died)
|
|
9
|
+
confidence: high # high | medium | low
|
|
10
|
+
volatility: default # default | timeless | volatile | <int days> — freshness horizon (Freshness & Revalidation)
|
|
11
|
+
trigger: null # REQUIRED (non-null) for type: pattern; null for domain
|
|
12
|
+
mentions: # GENERATED from body [[wiki-links]] at promote (Link Reconciliation). Author links
|
|
13
|
+
- { name: other-node-id, resolved_id: other-node-id, type: null } # inline in the BODY, not here.
|
|
14
|
+
- { name: page-not-created-yet, resolved_id: null, type: null } # resolved_id null = a red-link
|
|
15
|
+
edges: # GENERATED MIRROR of resolved mentions (Link Reconciliation §8) — not hand-authored
|
|
16
|
+
- { to: other-node-id, type: null } # untyped by default; type is optional
|
|
17
|
+
references: [] # SOFT cross-TEAM pointers only (no integrity guarantee)
|
|
18
|
+
provenance:
|
|
19
|
+
artifact: name-of-build-artifact
|
|
20
|
+
reviews: [] # human review-point ids that fed this node
|
|
21
|
+
session: 1970-01-01T00:00:00Z
|
|
22
|
+
created: 1970-01-01T00:00:00Z
|
|
23
|
+
updated: 1970-01-01T00:00:00Z # meaning-change time (NOT usage)
|
|
24
|
+
verified: 1970-01-01T00:00:00Z # last confirmed-still-true time (NOT usage, NOT meaning-change)
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Summary
|
|
28
|
+
One paragraph; read first on a body expansion.
|
|
29
|
+
|
|
30
|
+
## What
|
|
31
|
+
(domain nodes) The knowledge itself. Link to other pages inline by NAME with wiki-links —
|
|
32
|
+
e.g. "…settles against [[other-node-id]] before posting." Promote resolves them (Link Reconciliation).
|
|
33
|
+
|
|
34
|
+
## How / Notes
|
|
35
|
+
(pattern nodes) The prescriptive procedure / rule and its rationale.
|
|
36
|
+
|
|
37
|
+
## Provenance
|
|
38
|
+
Why this node exists; trace to the artifact and the specific human review points.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mnx-capture
|
|
3
|
+
description: Capture the durable knowledge produced in the current build session into the local Mnemex staging tier — cheap, fast, no lock, no graph mutation. Use this when a user finishes building or designing and wants to persist what was learned — domain facts AND the patterns/decisions from human review — or says "save this to the knowledge graph", "remember this for next time", "capture this", "stage this". Run it INCREMENTALLY at natural checkpoints too, not only at session end — after a sub-task lands, a review settles, or a compaction is signalled — staging only the delta (re-capturing identical content is a no-op), keeping keypoints loss-proof. Runs in-session to mine the artifact and review points from the transcript; extracts atoms, scores each now/later/not-needed, stages them with self-sufficient provenance. Also curates staging (--drop <id>, --discard-all) — the escape valve at the hard cap. Does NOT reconcile or merge into the shared graph — that is the deliberate, batched {{PROC:promote}} step.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mnx-capture — stage a session's knowledge (the `git commit` of memory)
|
|
7
|
+
|
|
8
|
+
Turn what this session produced — the artifact **and** the human review/clarification points — into
|
|
9
|
+
**staged atoms**: provisional, local, self-sufficient knowledge units. The *how* lives in the
|
|
10
|
+
conversation (the corrections, the rejected alternatives), so mine the transcript, not just the final
|
|
11
|
+
artifact, **now** — by promote time the transcript is gone.
|
|
12
|
+
|
|
13
|
+
Capture is the **fast, local half** of the capture/promote split. It is cheap, takes no lock, never
|
|
14
|
+
reads the graph's cluster indexes, and **never mutates the graph**. Reconcile / merge / consolidate /
|
|
15
|
+
push all happen later in `{{PROC:promote}}`. (Analogy: capture = `git commit`; promote = `git push`/PR.)
|
|
16
|
+
|
|
17
|
+
**Capture incrementally, at checkpoints — not only at the very end.** Since that transcript shrinks at
|
|
18
|
+
every compaction, one end-of-session dump is the most loss-exposed way to run this: prefer to capture the
|
|
19
|
+
**delta** at each natural checkpoint (a sub-task lands, a review decision settles, a compaction is
|
|
20
|
+
signalled). Capture is built for repetition — it stages only what is new and re-staging identical content
|
|
21
|
+
is an idempotent no-op (content-hash id) — so it stays cheap; the delta mechanics are Phase 0b + Phase 1.
|
|
22
|
+
|
|
23
|
+
Background: `docs/staging-and-promotion.md` (the whole model), `docs/rationale-and-concepts.md`
|
|
24
|
+
(node types, ids), `docs/data-model-and-schemas.md` (staged-atom front-matter). Helper:
|
|
25
|
+
`mnx_stage` (the only writer here) and `mnx_binding` (locate the graph).
|
|
26
|
+
|
|
27
|
+
{{INCLUDE:curate}}
|
|
28
|
+
## Preflight — locate the graph (always first)
|
|
29
|
+
Run {{CALL:bind_status}}.
|
|
30
|
+
- If `resolved` is false → **STOP**: *"No Mnemex graph configured. Run `{{PROC:init}}`."*
|
|
31
|
+
- **Echo the resolved graph before staging** so the author sees where atoms will land: show the
|
|
32
|
+
`resolution` line, e.g. *"Capturing into **payments-knowledge** (source: project .mnemex.md)."*
|
|
33
|
+
If `default_fallback` is true, make it **prominent** — there was no project `.mnemex.md`, so this is
|
|
34
|
+
going to the user's personal graph: *"⚠️ No project binding here — capturing into your personal
|
|
35
|
+
graph **personal-notes**. If that's wrong, cd into the right repo and re-capture."* This closes the
|
|
36
|
+
silent-binding gap (LIMITATIONS.md #2): the graph choice is now visible at capture time, not discovered
|
|
37
|
+
at promote time.
|
|
38
|
+
- Note `graph_root` (for routing intent only — capture writes **nothing** there) and `staging_root`
|
|
39
|
+
(where atoms land). Capture is local; it does **not** need `clone_present` / a sync.
|
|
40
|
+
|
|
41
|
+
## Phase 0 — Budget pre-check (backpressure)
|
|
42
|
+
Run {{CALL:capture_status_budget}}.
|
|
43
|
+
- `budget.level == "hard"` → **STOP capturing** and give the user the two ways out (the backpressure
|
|
44
|
+
bound): either *"run `{{PROC:promote}}` to merge + drain staging"* **or** *"make room by discarding
|
|
45
|
+
with {{CALL:capture_drop_flag}} or `--discard-all`."* Show the staged list (`mnx_stage.py list`)
|
|
46
|
+
so they can choose what to drop.
|
|
47
|
+
- `budget.level == "soft"` → proceed, but **warn** the user once that a promote is due.
|
|
48
|
+
|
|
49
|
+
## Phase 0b — Delta ledger (what is already staged)
|
|
50
|
+
Before extracting, load the staged ledger so you capture only the **delta** and can see what is already
|
|
51
|
+
covered:
|
|
52
|
+
|
|
53
|
+
{{CALL:capture_status_list}}
|
|
54
|
+
|
|
55
|
+
Each row is `provisional-id · type · score · summary · age`. Read it as the running record of "keypoints
|
|
56
|
+
already captured this session." In Phase 1, extract only what this ledger does **not** already cover, then
|
|
57
|
+
look for the next uncaptured keypoint. You do not need to diff by hand — re-staging identical content is an
|
|
58
|
+
idempotent no-op (content-hash id) — but consulting the ledger keeps you from re-mining ground you already
|
|
59
|
+
staged and makes the incremental checkpoint loop cheap. A genuinely refined atom (same concept, better
|
|
60
|
+
body) will hash differently and stage as a new atom; that is fine — reconcile collapses the pair at promote.
|
|
61
|
+
|
|
62
|
+
## Phase 1 — Extract the delta (mine the transcript, honor the node-size budget)
|
|
63
|
+
Decompose the artifact + transcript into candidate atoms, skipping anything the Phase 0b ledger already
|
|
64
|
+
covers — extract the **new** keypoints since your last capture. For each, decide:
|
|
65
|
+
- **`domain`** (a fact about the system/business — the *what*), or
|
|
66
|
+
- **`pattern`** (prescriptive *how*, with a `trigger` = the *when* it applies). **Mine human review
|
|
67
|
+
points specifically**: a correction or a rejected alternative becomes a pattern — *"do X not Y,
|
|
68
|
+
because…"* — with a trigger describing the situation it governs.
|
|
69
|
+
|
|
70
|
+
Draft `summary` (one line), `aliases` (other names the concept goes by), `domain` (routing key(s)),
|
|
71
|
+
and a tight body. **Propose a `volatility`** (freshness horizon, Freshness & Revalidation) from the atom's content shape —
|
|
72
|
+
`volatile` for a fact that rots fast (a URL, version, price, on-call name), `timeless` for a durable
|
|
73
|
+
definition/invariant (also exempts it from ever auto-dying), or leave it `default` (the type-derived
|
|
74
|
+
horizon) for everything else. It is a *suggestion*: the human confirms or overrides it at the promote
|
|
75
|
+
gate, so bias toward `default` when unsure.
|
|
76
|
+
|
|
77
|
+
**Embed links inline as `[[wiki-links]]` (the mesh authoring surface, Link Reconciliation).** When a note refers to
|
|
78
|
+
another concept, name it inline in the body with double brackets — *"…settles against
|
|
79
|
+
`[[iso8583-field124]]` before posting…"*. Link freely **by name**, even to a page that does not exist in
|
|
80
|
+
the graph yet: promote resolves each `[[name]]`, and an unresolved one becomes a **red-link** that goes
|
|
81
|
+
live automatically the day that page is created. The pipe means display text, wiki-native
|
|
82
|
+
(`[[iso8583-field124|Field 124]]`), **not** a relationship type. `mnx_stage` hoists these into the atom's
|
|
83
|
+
`mentions:` for you — you just write natural `[[links]]`. Do **not** hand-author `edges:`; that is a
|
|
84
|
+
generated mirror promote builds.
|
|
85
|
+
|
|
86
|
+
**Node-size budget — do NOT split at capture.** Keep each atom's body focused, but if a genuinely
|
|
87
|
+
single idea runs past the soft cap (`node_body_max_chars`, default ~6000), **capture it whole** — never
|
|
88
|
+
truncate. **Splitting an over-budget note into sibling pages + a link is promote's job, not capture's**
|
|
89
|
+
(promote is graph-aware; capture is local and dumb). Cap the number of atoms per session to what the
|
|
90
|
+
session actually produced; do not pad.
|
|
91
|
+
|
|
92
|
+
## Phase 1b — Glean (one bounded "what did I miss?" re-scan)
|
|
93
|
+
Pass 1 (Phase 1) is your first extraction pass; a single pass reliably **under-captures the *how*** — the
|
|
94
|
+
review-point patterns are the easiest to miss. So run **one** bounded recall pass (this is the shared
|
|
95
|
+
*gleanings* technique, guardrail mode):
|
|
96
|
+
|
|
97
|
+
- Re-read the transcript once and ask specifically: *"what durable fact — **especially a review-point
|
|
98
|
+
pattern** (a correction, a rejected alternative, a 'gotcha') — did I not stage yet?"*, guided by the
|
|
99
|
+
Phase-0b delta ledger so you look only at ground you have **not** already covered.
|
|
100
|
+
- Any new candidate still passes the Phase-2 `now/later/not-needed` scoring gate and Phase-3 staging;
|
|
101
|
+
re-staging identical content stays an idempotent no-op (content-hash id), so this pass can only add.
|
|
102
|
+
- **Bound the loop deterministically.** After the pass, count staged atoms before vs after and check
|
|
103
|
+
whether to stop:
|
|
104
|
+
|
|
105
|
+
{{CALL:glean_step}}
|
|
106
|
+
|
|
107
|
+
`stop:true` (`reason: no-progress` = the pass added nothing new, or `reason: cap` = the pass budget
|
|
108
|
+
`max_glean_passes` is reached — default **2**, from user config) → stop gleaning and go to Phase 2/4.
|
|
109
|
+
Only if `stop:false` do you run one more pass (`--pass 2`). This is **not** a per-topic walk — it is at
|
|
110
|
+
most a couple of bounded re-scans, keeping capture cheap/fast (the design goal). Episodic capture does
|
|
111
|
+
**not** build a coverage checklist — that (checklist mode) is ingest-only.
|
|
112
|
+
|
|
113
|
+
## Phase 2 — Score each atom (`now | later | not-needed`)
|
|
114
|
+
A momentary judgement of **intrinsic importance — NOT novelty**. Drift between sessions is fine; there
|
|
115
|
+
is no rigid rubric. Novelty/dedup is decided later at promote (reconcile may drop an atom as a
|
|
116
|
+
duplicate), so do **not** pre-judge "probably already known."
|
|
117
|
+
- **`now`** → stage **with `--urgent`**. (Urgent never inline-pushes — promote is still the only
|
|
118
|
+
writer; urgent only sharpens the nag.)
|
|
119
|
+
- **`later`** → stage normally.
|
|
120
|
+
- **`not-needed`** → **silently drop.** No staging, no audit, no asking the user. Reserve this for the
|
|
121
|
+
clearly ephemeral or trivially derivable.
|
|
122
|
+
|
|
123
|
+
## Phase 3 — Stage (the only write)
|
|
124
|
+
For each kept atom, write it to the staging tier. Provenance must be **self-sufficient for a cold
|
|
125
|
+
promote** — artifact ref, the specific review ids, rejected alternative(s), the rationale, and the
|
|
126
|
+
session timestamp:
|
|
127
|
+
|
|
128
|
+
{{CALL:capture_add}}
|
|
129
|
+
|
|
130
|
+
(Or use flags for a simple atom: `add --type domain --summary "…" --domain settlement --score later
|
|
131
|
+
--aliases "a;b" --artifact <id> --reviews "r3;r7" --rationale "…" --body "…"`.) The helper mints the
|
|
132
|
+
**provisional id** (a content hash, `stg-…`) — never invent an id, never reuse a real node id. A
|
|
133
|
+
re-capture of identical content is idempotent and reports `action: already-staged` (vs `staged` for
|
|
134
|
+
new content) — count the two separately so your report reflects the true delta.
|
|
135
|
+
|
|
136
|
+
## Phase 4 — Report
|
|
137
|
+
Summarize what was staged **this pass**: the new atoms (counts by score), any `urgent`, and the
|
|
138
|
+
post-stage `budget.level`. When capturing incrementally, distinguish this pass's delta from the total
|
|
139
|
+
staged set so the checkpoint loop is legible ("staged 2 new; 7 total staged"). If the helper
|
|
140
|
+
**refused** an atom (`action: refused`), surface the hard-cap message and give both ways out —
|
|
141
|
+
`{{PROC:promote}}` to drain staging, or {{CALL:capture_drop_flag2}} / `--discard-all` to make
|
|
142
|
+
room. Then stop — **do not** offer to push or merge; that is promote's job.
|
|
143
|
+
|
|
144
|
+
## Never
|
|
145
|
+
- Never reconcile, merge, re-tier, or open the graph's cluster indexes — capture is local-only.
|
|
146
|
+
- Never write into `graph_root`, never take the team lock, never commit or push.
|
|
147
|
+
- Never stamp a staged atom or give it a real node id (the `stg-` provisional id is content-derived).
|
|
148
|
+
- Never `not-needed`-drop on a *novelty* guess — only the clearly ephemeral/derivable.
|
|
149
|
+
- Never split, resolve a `[[link]]`, or hand-author `edges:` — capture preserves links; **promote** splits
|
|
150
|
+
over-budget notes and resolves links (Link Reconciliation). Never truncate an over-budget atom — capture it whole.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: curate
|
|
3
|
+
description: Review, drop, or discard atoms already staged in the local Mnemex staging tier — no extraction, no graph mutation. The un-stage escape valve, including at the hard capture-budget cap.
|
|
4
|
+
---
|
|
5
|
+
## Curate mode — review / drop / discard (no extraction)
|
|
6
|
+
{{BLOCK:trigger_condition}}
|
|
7
|
+
- **Review first** when helpful: {{CALL:capture_status_inline}} shows the
|
|
8
|
+
staged atoms (provisional id · score · summary · age). (`{{PROC:status}}` shows the same list.)
|
|
9
|
+
- `--drop <id>` → {{CALL:capture_drop}}; report the dropped atom's id + summary (or that it
|
|
10
|
+
was not found).
|
|
11
|
+
- `--discard-all` → show the list and **confirm with the user**, then {{CALL:capture_discard_all}}; report the
|
|
12
|
+
count removed.
|
|
13
|
+
This touches **only** the local staging tier — never the graph, never the stamp spill. Then stop.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
Procedure: check `capture_status`'s ledger for what's already staged, mine the transcript for
|
|
2
|
+
the delta (facts + review-point patterns) plus one bounded `glean_step` recall pass, score
|
|
3
|
+
each atom now/later/not-needed, then `capture_add` per atom with self-sufficient provenance.
|
|
4
|
+
Never split an over-budget body — stage it whole; that's promote's job.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Procedure: `ingest_acquire` the repo (read-only) → `ingest_probe` for the extraction
|
|
2
|
+
units + a source-tree→cluster map (gate #1: confirm scope) → distil durable atoms with
|
|
3
|
+
`capture_add(ingest_batch=...)`, never transcribe (zero atoms from a file is fine) →
|
|
4
|
+
`glean_coverage` until complete/cap → `er_resolve` to dedupe and MERGE into existing pages
|
|
5
|
+
(one entity → one node) → drain with `promote_begin`/`promote_apply` in bulk. For every
|
|
6
|
+
NEW cluster created, write its one-line description into the cluster `index.md` header
|
|
7
|
+
(`> …` line) — read routing decides on that line, and regeneration preserves it; never
|
|
8
|
+
leave the scaffold placeholder. Two gates
|
|
9
|
+
only (scope, bulk summary); deleted-file orphans surface for the human, never auto-tombstoned.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
Procedure: `promote_begin` (locks + guards) → `promote_context` (near-matches, link preview)
|
|
2
|
+
→ draft one plan (create/merge/supersede/resurrect/drop_dup/hold per staged atom, plus link
|
|
3
|
+
and consolidate decisions) → present it for human approval → `promote_apply` with
|
|
4
|
+
`approved: true`. Contradictions go to `hold`, never force-resolved or silently dropped.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
Procedure: `read_frontier` to route (by description match) → `read_cluster` (hot tier
|
|
2
|
+
first, widen only if insufficient) → `read_nodes` for only the ids you'll actually use →
|
|
3
|
+
`record_usage` with a role (contributed/consulted/traversed) for every id loaded. Flag stale
|
|
4
|
+
rows and staged-overlay atoms in the answer; never body-merge a staged/graph contradiction.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
the `bind_status` tool
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
```
|
|
2
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/mnx_stage.py" add --binding-session <sid> --json <<'JSON'
|
|
3
|
+
{ "type": "pattern",
|
|
4
|
+
"summary": "Reconcile settlement before posting",
|
|
5
|
+
"aliases": ["settle-recon"],
|
|
6
|
+
"domain": ["settlement"],
|
|
7
|
+
"trigger": "reviewing or curating a settlement spec",
|
|
8
|
+
"score": "now", "urgent": true, "volatility": "default",
|
|
9
|
+
"provenance": { "artifact": "tap-vic-settlement-spec", "reviews": ["r3","r7"],
|
|
10
|
+
"rejected": ["post-then-reconcile (causes orphaned legs)"],
|
|
11
|
+
"rationale": "human correction in review r7" },
|
|
12
|
+
"body": "Always reconcile the settlement batch against [[iso8583-field124]] before posting legs, because …" }
|
|
13
|
+
JSON
|
|
14
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`/mnemex:mnx-capture --drop <id>`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`capture_drop`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`/mnemex:mnx-capture --drop <id>`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`capture_drop`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`python3 "${CLAUDE_PLUGIN_ROOT}/scripts/mnx_stage.py" status`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
the `capture_status` tool (check its `budget.level`)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Call `capture_status` (its staged ledger).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Call `glean_step` with `before=<n_before>`, `after=<n_after>`, `pass_no=1`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/mnemex:mnx-init
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
init_graph
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/mnemex:mnx-promote
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
the promote procedure
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`mnx_stage.py clear`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`capture_discard_all` with `confirm=true`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`mnx_stage.py clear-one --id <id>`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`capture_drop` with `pid=<id>`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`python3 "${CLAUDE_PLUGIN_ROOT}/scripts/mnx_stage.py" list`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`capture_status`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/mnemex:mnx-status
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
status
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
If invoked with `--drop <provisional-id>` or `--discard-all`, this is the local **un-stage** path — the
|
|
2
|
+
cheap way to prune staging (and the escape valve when the hard cap is blocking new captures). It still
|
|
3
|
+
runs the locate preflight (to find the staging tier) but does **no** extraction, scoring, or staging:
|