mneme-ai 2.76.0 → 2.78.0
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.
- package/dist/commands/immune.d.ts +18 -0
- package/dist/commands/immune.d.ts.map +1 -0
- package/dist/commands/immune.js +96 -0
- package/dist/commands/immune.js.map +1 -0
- package/dist/commands/ui.d.ts +16 -0
- package/dist/commands/ui.d.ts.map +1 -0
- package/dist/commands/ui.js +114 -0
- package/dist/commands/ui.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -1
- package/dist/ui/tui_core.d.ts +63 -0
- package/dist/ui/tui_core.d.ts.map +1 -0
- package/dist/ui/tui_core.js +158 -0
- package/dist/ui/tui_core.js.map +1 -0
- package/dist/ui/tui_render.d.ts +11 -0
- package/dist/ui/tui_render.d.ts.map +1 -0
- package/dist/ui/tui_render.js +107 -0
- package/dist/ui/tui_render.js.map +1 -0
- package/package.json +73 -73
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.78.0 — `mneme immune selftest`
|
|
3
|
+
*
|
|
4
|
+
* WORM-CANARY for humans. Two checks:
|
|
5
|
+
* 1. Mneme's OWN output: render a worst-case version-mismatch agent block
|
|
6
|
+
* (one carrying an upgrade autoAction) and prove it has zero worm
|
|
7
|
+
* signatures — Mneme informs, never commands.
|
|
8
|
+
* 2. This repo's agent files (CLAUDE.md / AGENTS.md / .cursorrules /
|
|
9
|
+
* .windsurfrules): scan the live Mneme block (or whole file) for any
|
|
10
|
+
* worm directive that may have been written by an OLDER Mneme.
|
|
11
|
+
*
|
|
12
|
+
* Exit 0 when clean, 1 when a worm directive is found.
|
|
13
|
+
*/
|
|
14
|
+
export declare function immuneCommand(opts: {
|
|
15
|
+
cwd: string;
|
|
16
|
+
json?: boolean;
|
|
17
|
+
}): Promise<number>;
|
|
18
|
+
//# sourceMappingURL=immune.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"immune.d.ts","sourceRoot":"","sources":["../../src/commands/immune.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAaH,wBAAsB,aAAa,CAAC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgE1F"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.78.0 — `mneme immune selftest`
|
|
3
|
+
*
|
|
4
|
+
* WORM-CANARY for humans. Two checks:
|
|
5
|
+
* 1. Mneme's OWN output: render a worst-case version-mismatch agent block
|
|
6
|
+
* (one carrying an upgrade autoAction) and prove it has zero worm
|
|
7
|
+
* signatures — Mneme informs, never commands.
|
|
8
|
+
* 2. This repo's agent files (CLAUDE.md / AGENTS.md / .cursorrules /
|
|
9
|
+
* .windsurfrules): scan the live Mneme block (or whole file) for any
|
|
10
|
+
* worm directive that may have been written by an OLDER Mneme.
|
|
11
|
+
*
|
|
12
|
+
* Exit 0 when clean, 1 when a worm directive is found.
|
|
13
|
+
*/
|
|
14
|
+
import { writeSync } from "node:fs";
|
|
15
|
+
import * as core from "@mneme-ai/core";
|
|
16
|
+
const AGENT_FILES = ["CLAUDE.md", "AGENTS.md", ".cursorrules", ".windsurfrules"];
|
|
17
|
+
// fd-1 synchronous write — survives the immediate process.exit() the action
|
|
18
|
+
// handler calls (an async stdout pipe would otherwise be truncated on Windows).
|
|
19
|
+
function out(s) {
|
|
20
|
+
try {
|
|
21
|
+
writeSync(1, s);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
process.stdout.write(s);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function immuneCommand(opts) {
|
|
28
|
+
const { scanForWormSignatures, KNOWN_WORM_PAYLOAD } = core.immune;
|
|
29
|
+
const { renderMnemeBlock, readMnemeBlock } = core.notifier;
|
|
30
|
+
// Check 1 — Mneme's own worst-case output.
|
|
31
|
+
const ownBlock = renderMnemeBlock({
|
|
32
|
+
id: "version-up-to-date",
|
|
33
|
+
severity: "info",
|
|
34
|
+
title: "Mneme update available",
|
|
35
|
+
body: "installed v0.0.0, npm latest v9.9.9. The user can run `mneme upgrade` when convenient.",
|
|
36
|
+
autoAction: { tool: "mneme.system.upgrade", args: { mode: "install", force: true } },
|
|
37
|
+
});
|
|
38
|
+
const ownScan = scanForWormSignatures(ownBlock);
|
|
39
|
+
const control = scanForWormSignatures(KNOWN_WORM_PAYLOAD); // positive control
|
|
40
|
+
// Check 2 — this repo's persistent agent files.
|
|
41
|
+
const fileScans = [];
|
|
42
|
+
for (const f of AGENT_FILES) {
|
|
43
|
+
let block = null;
|
|
44
|
+
try {
|
|
45
|
+
block = readMnemeBlock(opts.cwd, f);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
block = null;
|
|
49
|
+
}
|
|
50
|
+
if (block === null)
|
|
51
|
+
continue; // file or Mneme block absent — nothing to scan
|
|
52
|
+
const scan = scanForWormSignatures(block);
|
|
53
|
+
fileScans.push({
|
|
54
|
+
file: f,
|
|
55
|
+
clean: scan.clean,
|
|
56
|
+
findings: scan.findings.length,
|
|
57
|
+
detail: scan.findings.map((x) => `${x.kind}: "${x.match}"`),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
const dirtyFiles = fileScans.filter((s) => !s.clean);
|
|
61
|
+
const ok = ownScan.clean && !control.clean && dirtyFiles.length === 0;
|
|
62
|
+
if (opts.json) {
|
|
63
|
+
out(JSON.stringify({
|
|
64
|
+
ok,
|
|
65
|
+
ownOutputClean: ownScan.clean,
|
|
66
|
+
canaryCatchesKnownPayload: !control.clean,
|
|
67
|
+
ownFindings: ownScan.findings,
|
|
68
|
+
files: fileScans,
|
|
69
|
+
}, null, 2) + "\n");
|
|
70
|
+
return ok ? 0 : 1;
|
|
71
|
+
}
|
|
72
|
+
const lines = [];
|
|
73
|
+
lines.push("🧬 MNEME IMMUNE SELFTEST — WORM-CANARY");
|
|
74
|
+
lines.push("");
|
|
75
|
+
lines.push(` ${ownScan.clean ? "🟢" : "🔴"} Mneme's own agent-file output: ${ownScan.clean ? "no worm signatures (informs, never commands)" : `${ownScan.findings.length} signature(s)!`}`);
|
|
76
|
+
for (const f of ownScan.findings)
|
|
77
|
+
lines.push(` └─ ${f.kind}: "${f.match}"`);
|
|
78
|
+
lines.push(` ${!control.clean ? "🟢" : "🔴"} Canary self-test: ${!control.clean ? "catches the known pre-v2.78 worm payload (positive control)" : "FAILED to catch the known payload — canary is broken!"}`);
|
|
79
|
+
if (fileScans.length === 0) {
|
|
80
|
+
lines.push(" · No Mneme blocks found in this repo's agent files (nothing to scan).");
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
for (const s of fileScans) {
|
|
84
|
+
lines.push(` ${s.clean ? "🟢" : "🔴"} ${s.file}: ${s.clean ? "clean" : `${s.findings} worm signature(s)!`}`);
|
|
85
|
+
for (const d of s.detail)
|
|
86
|
+
lines.push(` └─ ${d}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
lines.push("");
|
|
90
|
+
lines.push(ok
|
|
91
|
+
? " ✅ CLEAN — Mneme is not a worm. It states version availability as informational context; upgrades are user-initiated only."
|
|
92
|
+
: " ❌ WORM DIRECTIVE present — see above. (If a repo file is dirty, an OLDER Mneme wrote it; run `mneme upgrade` then re-run this.)");
|
|
93
|
+
out(lines.join("\n") + "\n");
|
|
94
|
+
return ok ? 0 : 1;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=immune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"immune.js","sourceRoot":"","sources":["../../src/commands/immune.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.77.0 — `mneme ui` : full-screen, arrow-key interactive TUI.
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency (raw-mode stdin + ANSI), on-brand with Mneme's local-first
|
|
5
|
+
* ethos. Type plain language → the right capability surfaces; ↑↓ to navigate;
|
|
6
|
+
* Enter runs a parameterless command live (or shows how to run a parameterized
|
|
7
|
+
* one); Esc clears the query then quits. New tools appear automatically because
|
|
8
|
+
* the list IS the live MNEME_COMMAND_CATALOG. All UI LOGIC is pure + tested in
|
|
9
|
+
* src/ui/tui_core.ts; this file is just the terminal driver.
|
|
10
|
+
*/
|
|
11
|
+
export interface UiOptions {
|
|
12
|
+
cwd: string;
|
|
13
|
+
version?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function uiCommand(opts: UiOptions): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=ui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/commands/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,MAAM,WAAW,SAAS;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAAE;AAa7D,wBAAsB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAqF9D"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.77.0 — `mneme ui` : full-screen, arrow-key interactive TUI.
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency (raw-mode stdin + ANSI), on-brand with Mneme's local-first
|
|
5
|
+
* ethos. Type plain language → the right capability surfaces; ↑↓ to navigate;
|
|
6
|
+
* Enter runs a parameterless command live (or shows how to run a parameterized
|
|
7
|
+
* one); Esc clears the query then quits. New tools appear automatically because
|
|
8
|
+
* the list IS the live MNEME_COMMAND_CATALOG. All UI LOGIC is pure + tested in
|
|
9
|
+
* src/ui/tui_core.ts; this file is just the terminal driver.
|
|
10
|
+
*/
|
|
11
|
+
import * as readline from "node:readline";
|
|
12
|
+
import { spawnSync } from "node:child_process";
|
|
13
|
+
import { initState, reduce, isParameterless, shellArgsFor, loadCatalog } from "../ui/tui_core.js";
|
|
14
|
+
import { renderFrame, stripAnsi } from "../ui/tui_render.js";
|
|
15
|
+
const ALT_ON = "\x1b[?1049h\x1b[?25l"; // enter alt-screen + hide cursor
|
|
16
|
+
const ALT_OFF = "\x1b[?25h\x1b[?1049l"; // show cursor + leave alt-screen
|
|
17
|
+
const HOME_CLEAR = "\x1b[H\x1b[2J";
|
|
18
|
+
async function loadItems() {
|
|
19
|
+
try {
|
|
20
|
+
const core = await import("@mneme-ai/core");
|
|
21
|
+
return loadCatalog(core.agentManifest?.MNEME_COMMAND_CATALOG ?? []);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function uiCommand(opts) {
|
|
28
|
+
const items = await loadItems();
|
|
29
|
+
// Non-interactive fallback — a TUI needs a real TTY. Print a useful pointer
|
|
30
|
+
// instead of corrupting a pipe / CI log.
|
|
31
|
+
if (!process.stdout.isTTY || !process.stdin.isTTY || items.length === 0) {
|
|
32
|
+
process.stdout.write(items.length === 0
|
|
33
|
+
? "mneme ui: capability catalog unavailable.\n"
|
|
34
|
+
: "mneme ui needs an interactive terminal (TTY).\n • Run it in a real shell, or\n • use `mneme atlas` (static capability map) / `mneme <command> --help`.\n");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const rows = process.stdout.rows || 24;
|
|
38
|
+
const cols = process.stdout.columns || 80;
|
|
39
|
+
// Reserve ~9 rows for title/search/separators/detail/footer; rest is the list.
|
|
40
|
+
let state = initState(items, Math.max(3, rows - 12));
|
|
41
|
+
const paint = () => {
|
|
42
|
+
const r = process.stdout.rows || 24;
|
|
43
|
+
const c = process.stdout.columns || 80;
|
|
44
|
+
if (state.mode === "browse")
|
|
45
|
+
state = { ...state, listRows: Math.max(3, r - 12) };
|
|
46
|
+
const frame = renderFrame(state, c, r, opts.version ?? "?");
|
|
47
|
+
process.stdout.write(HOME_CLEAR + frame.join("\n"));
|
|
48
|
+
};
|
|
49
|
+
const cleanup = () => {
|
|
50
|
+
try {
|
|
51
|
+
process.stdin.setRawMode?.(false);
|
|
52
|
+
}
|
|
53
|
+
catch { /* */ }
|
|
54
|
+
process.stdin.pause();
|
|
55
|
+
process.stdout.write(ALT_OFF);
|
|
56
|
+
};
|
|
57
|
+
// Run a parameterless `mneme <verb>` live; capture output into the pane.
|
|
58
|
+
const runItem = (item) => {
|
|
59
|
+
if (!isParameterless(item)) {
|
|
60
|
+
state = { ...state, mode: "output", outputTitle: `${item.command} (needs arguments)`, output: `This capability takes arguments, so it can't be run blind from the menu.\n\n` +
|
|
61
|
+
`Run it yourself:\n ${item.command}\n\n` +
|
|
62
|
+
(item.when ? `When to use:\n ${item.when}\n` : ""),
|
|
63
|
+
};
|
|
64
|
+
paint();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const args = shellArgsFor(item);
|
|
68
|
+
process.stdout.write(HOME_CLEAR + `\x1b[1m▶ running:\x1b[0m mneme ${args.join(" ")}\n\n(please wait…)`);
|
|
69
|
+
const r = spawnSync(process.execPath, [process.argv[1], ...args], {
|
|
70
|
+
cwd: opts.cwd,
|
|
71
|
+
encoding: "utf8",
|
|
72
|
+
timeout: 60000,
|
|
73
|
+
env: { ...process.env, MNEME_WARMCALL: "0", NO_COLOR: "1" }, // fresh + clean text in the pane
|
|
74
|
+
});
|
|
75
|
+
const out = [r.stdout, r.stderr].filter(Boolean).join("\n").trim();
|
|
76
|
+
state = { ...state, mode: "output", outputTitle: `mneme ${args.join(" ")} ${r.status === 0 ? "✓" : `(exit ${r.status ?? "?"})`}`,
|
|
77
|
+
output: stripAnsi(out || "(no output)") };
|
|
78
|
+
paint();
|
|
79
|
+
};
|
|
80
|
+
return new Promise((resolve) => {
|
|
81
|
+
process.stdout.write(ALT_ON);
|
|
82
|
+
readline.emitKeypressEvents(process.stdin);
|
|
83
|
+
try {
|
|
84
|
+
process.stdin.setRawMode?.(true);
|
|
85
|
+
}
|
|
86
|
+
catch { /* some terminals */ }
|
|
87
|
+
process.stdin.resume();
|
|
88
|
+
paint();
|
|
89
|
+
const onResize = () => paint();
|
|
90
|
+
process.stdout.on("resize", onResize);
|
|
91
|
+
const finish = () => {
|
|
92
|
+
process.stdin.removeListener("keypress", onKey);
|
|
93
|
+
process.stdout.removeListener("resize", onResize);
|
|
94
|
+
cleanup();
|
|
95
|
+
resolve();
|
|
96
|
+
};
|
|
97
|
+
const onKey = (_str, key) => {
|
|
98
|
+
const k = { name: key?.name, ctrl: !!key?.ctrl, sequence: key?.sequence };
|
|
99
|
+
const { state: next, action } = reduce(state, k);
|
|
100
|
+
state = next;
|
|
101
|
+
if (action.type === "quit") {
|
|
102
|
+
finish();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (action.type === "run") {
|
|
106
|
+
runItem(action.item);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
paint();
|
|
110
|
+
};
|
|
111
|
+
process.stdin.on("keypress", onKey);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/commands/ui.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuIA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuIA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwzMvD"}
|
package/dist/index.js
CHANGED
|
@@ -114,6 +114,18 @@ export async function run(argv) {
|
|
|
114
114
|
}
|
|
115
115
|
catch { /* fall through to commander on failure */ }
|
|
116
116
|
}
|
|
117
|
+
// v2.77.0 — INTERACTIVE-BY-DEFAULT. Bare `mneme` in a real terminal launches
|
|
118
|
+
// the full-screen TUI (type plain language → run any capability, zero
|
|
119
|
+
// memorization). Non-TTY (pipes / CI / scripts) keep the classic behavior, so
|
|
120
|
+
// nothing automated breaks. `MNEME_NO_UI=1` opts out.
|
|
121
|
+
if (slice.length === 0 && process.stdout.isTTY && process.stdin.isTTY && process.env["MNEME_NO_UI"] !== "1") {
|
|
122
|
+
try {
|
|
123
|
+
const { uiCommand } = await import("./commands/ui.js");
|
|
124
|
+
await uiCommand({ cwd: process.cwd(), version: getVersion() });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
catch { /* fall through to commander default on any failure */ }
|
|
128
|
+
}
|
|
117
129
|
const program = new Command()
|
|
118
130
|
.name("mneme")
|
|
119
131
|
.description("μνήμη — the memory layer of your codebase. Knows the WHY, the WHAT, the WHERE-IT-BREAKS.")
|
|
@@ -4144,6 +4156,31 @@ export async function run(argv) {
|
|
|
4144
4156
|
// command / 14k token blast-radius without deleting any command.
|
|
4145
4157
|
// Default `mneme --help` still works (backward compat); AI agents
|
|
4146
4158
|
// are told to use these layered surfaces instead.
|
|
4159
|
+
// v2.77.0 — INTERACTIVE TUI. Type plain language → the right capability
|
|
4160
|
+
// surfaces; ↑↓ navigate every command; Enter runs it. Zero memorization.
|
|
4161
|
+
program
|
|
4162
|
+
.command("ui")
|
|
4163
|
+
.aliases(["menu", "tui"])
|
|
4164
|
+
.description("🖥 Interactive full-screen menu — type plain language to search every capability, ↑↓ to navigate, Enter to run. Zero command memorization. (Needs a real terminal.)")
|
|
4165
|
+
.action(async () => {
|
|
4166
|
+
const { uiCommand } = await import("./commands/ui.js");
|
|
4167
|
+
await uiCommand({ cwd: process.cwd(), version: getVersion() });
|
|
4168
|
+
});
|
|
4169
|
+
// v2.78.0 — WORM-CANARY selftest. Prove Mneme is not an AI worm: its
|
|
4170
|
+
// agent-file output carries no imperative directives, and any worm payload
|
|
4171
|
+
// an OLDER Mneme may have written into this repo's CLAUDE.md/etc is detected.
|
|
4172
|
+
program
|
|
4173
|
+
.command("immune <action>")
|
|
4174
|
+
.description("🧬 IMMUNE — `mneme immune selftest` runs the WORM-CANARY: proves Mneme never injects a self-upgrade/self-propagation directive into AI agent files (CLAUDE.md/AGENTS.md/.cursorrules/.windsurfrules), and scans this repo's files for any worm payload left by an older Mneme.")
|
|
4175
|
+
.option("--json", "machine-readable output", false)
|
|
4176
|
+
.action(async (action, opts) => {
|
|
4177
|
+
if (action !== "selftest") {
|
|
4178
|
+
ui.error(`Unknown immune action "${action}". Try: selftest`);
|
|
4179
|
+
process.exit(2);
|
|
4180
|
+
}
|
|
4181
|
+
const { immuneCommand } = await import("./commands/immune.js");
|
|
4182
|
+
process.exit(await immuneCommand({ cwd: process.cwd(), json: !!opts.json }));
|
|
4183
|
+
});
|
|
4147
4184
|
program
|
|
4148
4185
|
.command("atlas")
|
|
4149
4186
|
.description("🗺 ATLAS HELP — six-layer discovery (TASTE · BLOOM · HOT · TAGS · INTENT · FULL). AI agents read 200 bytes here instead of 14 KB from --help.")
|