@meetless/mla 0.1.4 → 0.1.6
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/build-info.json +3 -3
- package/dist/cli.js +31 -5
- package/dist/commands/activate.js +39 -18
- package/dist/commands/agent-memory.js +333 -0
- package/dist/commands/enrich.js +211 -2
- package/dist/commands/internal-auto-index.js +64 -1
- package/dist/commands/internal-pretool-observe.js +86 -1
- package/dist/commands/internal-redact-capture.js +130 -0
- package/dist/commands/pilot.js +385 -0
- package/dist/lib/agent-memory-capture/binding.js +115 -0
- package/dist/lib/agent-memory-capture/classify.js +68 -0
- package/dist/lib/agent-memory-capture/collector.js +69 -0
- package/dist/lib/agent-memory-capture/containment.js +74 -0
- package/dist/lib/agent-memory-capture/ledger.js +43 -0
- package/dist/lib/agent-memory-capture/live-collector.js +148 -0
- package/dist/lib/agent-memory-capture/live-ledger.js +45 -0
- package/dist/lib/agent-memory-capture/live-pipeline.js +344 -0
- package/dist/lib/agent-memory-capture/lock.js +98 -0
- package/dist/lib/agent-memory-capture/paths.js +47 -0
- package/dist/lib/agent-memory-capture/pipeline.js +222 -0
- package/dist/lib/agent-memory-capture/report.js +131 -0
- package/dist/lib/agent-memory-capture/types.js +14 -0
- package/dist/lib/agent-memory-capture/upsert-client.js +104 -0
- package/dist/lib/analytics/enforcement-classify.js +65 -0
- package/dist/lib/analytics/enforcement-incident.js +83 -0
- package/dist/lib/analytics/envelope.js +55 -1
- package/dist/lib/analytics/pilot.js +313 -0
- package/dist/lib/enrichment/ingest.js +98 -13
- package/dist/lib/enrichment/materialize-rules.js +81 -0
- package/dist/lib/enrichment/plan.js +72 -15
- package/dist/lib/enrichment/protocol.js +85 -5
- package/dist/lib/enrichment/scout-brief.js +35 -6
- package/dist/lib/redactor.js +104 -1
- package/dist/lib/scanner/agent-memory.js +55 -4
- package/dist/lib/scanner/managed-rules.js +0 -0
- package/dist/lib/scanner/scan.js +52 -1
- package/dist/lib/scanner/score.js +41 -3
- package/dist/lib/scanner/scout-mission.js +9 -7
- package/dist/lib/upgrade-apply.js +30 -0
- package/dist/lib/wire.js +2 -0
- package/package.json +3 -3
package/dist/build-info.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -65,6 +65,7 @@ const internal_evidence_hooks_1 = require("./commands/internal-evidence-hooks");
|
|
|
65
65
|
const internal_steer_sync_1 = require("./commands/internal-steer-sync");
|
|
66
66
|
const internal_capture_decisions_1 = require("./commands/internal-capture-decisions");
|
|
67
67
|
const internal_pretool_observe_1 = require("./commands/internal-pretool-observe");
|
|
68
|
+
const internal_redact_capture_1 = require("./commands/internal-redact-capture");
|
|
68
69
|
const internal_turn_recap_1 = require("./commands/internal-turn-recap");
|
|
69
70
|
const internal_refresh_1 = require("./commands/internal-refresh");
|
|
70
71
|
const internal_session_nudge_1 = require("./commands/internal-session-nudge");
|
|
@@ -73,11 +74,13 @@ const upgrade_apply_1 = require("./lib/upgrade-apply");
|
|
|
73
74
|
const wire_1 = require("./lib/wire");
|
|
74
75
|
const scan_context_1 = require("./commands/scan-context");
|
|
75
76
|
const kb_1 = require("./commands/kb");
|
|
77
|
+
const agent_memory_1 = require("./commands/agent-memory");
|
|
76
78
|
const enrich_1 = require("./commands/enrich");
|
|
77
79
|
const graph_1 = require("./commands/graph");
|
|
78
80
|
const summary_1 = require("./commands/summary");
|
|
79
81
|
const label_1 = require("./commands/label");
|
|
80
82
|
const stats_1 = require("./commands/stats");
|
|
83
|
+
const pilot_1 = require("./commands/pilot");
|
|
81
84
|
const turn_1 = require("./commands/turn");
|
|
82
85
|
const ask_1 = require("./commands/ask");
|
|
83
86
|
const session_1 = require("./commands/session");
|
|
@@ -95,7 +98,7 @@ const rules_1 = require("./commands/rules");
|
|
|
95
98
|
// Commands:
|
|
96
99
|
// mla init [flags]
|
|
97
100
|
// mla rewire [flags]
|
|
98
|
-
// mla activate [--name <name>] [--note <text>] [--here|--create|--repair] [--bootstrap <fast|agentic
|
|
101
|
+
// mla activate [--name <name>] [--note <text>] [--here|--create|--repair] [--bootstrap <fast|agentic>]
|
|
99
102
|
// mla deactivate [--yes] [--from-root|--marker <path>]
|
|
100
103
|
// mla mute | mla unmute
|
|
101
104
|
// mla review [--plain] [--no-flush]
|
|
@@ -154,11 +157,12 @@ usage:
|
|
|
154
157
|
mla activate --repair
|
|
155
158
|
(re-check the existing binding's membership + connectivity;
|
|
156
159
|
never mints a new id)
|
|
157
|
-
mla activate --bootstrap <fast|agentic
|
|
160
|
+
mla activate --bootstrap <fast|agentic>
|
|
158
161
|
(bootstrap tier for the activation preview: fast (default) shows
|
|
159
|
-
the deterministic review bundle
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
the deterministic review bundle. agentic is DEPRECATED: it still
|
|
163
|
+
emits a static deep-read scout mission, but the consolidated
|
|
164
|
+
agent-driven onboarding is /mla onboard. The old full tier was
|
|
165
|
+
removed; --bootstrap full now errors with a migration note.)
|
|
162
166
|
mla deactivate [--yes] [--from-root|--marker <path>]
|
|
163
167
|
(REMOVE this folder's workspace binding: deletes the nearest
|
|
164
168
|
.meetless.json. Confirms first (--yes to skip); from a subdir
|
|
@@ -260,6 +264,11 @@ usage:
|
|
|
260
264
|
(usefulness-first dashboard from local events.jsonl: evidence
|
|
261
265
|
followthrough, contradictions caught, coverage gaps. default
|
|
262
266
|
window 30d. \`evidence\` is the focused adoption join below.)
|
|
267
|
+
mla pilot <feedback|report|export|sample-check> ...
|
|
268
|
+
(pilot value signal: record one explicit verdict at a natural
|
|
269
|
+
point (feedback), score the four hypotheses (report), dump the
|
|
270
|
+
raw pilot subset (export), or consult the 1-in-N injection
|
|
271
|
+
sampling gate (sample-check). Local events.jsonl; no dashboard.)
|
|
263
272
|
mla turn [N] [--session <sid>] [--json]
|
|
264
273
|
(per-turn assist recap: did mla run this turn and did it help?
|
|
265
274
|
no N recaps the latest completed turn of the current session;
|
|
@@ -488,6 +497,14 @@ async function dispatch(argv) {
|
|
|
488
497
|
return (0, ask_1.runAsk)(argv.slice(1));
|
|
489
498
|
case "kb":
|
|
490
499
|
return (0, kb_1.runKb)(argv.slice(1));
|
|
500
|
+
// `mla agent-memory <enable|disable|status|scan|report>`: operator surface for
|
|
501
|
+
// the agent-memory capture pipeline (notes/20260626-agent-memory-auto-capture-
|
|
502
|
+
// proposal.md). Phase 1 is DRY-RUN ONLY: `scan` observes/classifies/secret-scans
|
|
503
|
+
// project-type Claude auto-memory files and records metadata-only decisions
|
|
504
|
+
// locally; it uploads nothing. Live ingestion is blocked upstream by the missing
|
|
505
|
+
// cross-revision claim-grain idempotency and is intentionally not wired.
|
|
506
|
+
case "agent-memory":
|
|
507
|
+
return (0, agent_memory_1.runAgentMemory)(argv.slice(1));
|
|
491
508
|
// `mla enrich`: agent-orchestrated onboarding enrichment. `enrich plan` scans the
|
|
492
509
|
// repo into an immutable run record + prints the plan the agent reads; `enrich
|
|
493
510
|
// ingest` validates + persists the scouts' candidates born PENDING. The agent
|
|
@@ -508,6 +525,13 @@ async function dispatch(argv) {
|
|
|
508
525
|
return (0, label_1.runLabel)(argv.slice(1));
|
|
509
526
|
case "stats":
|
|
510
527
|
return (0, stats_1.runStats)(argv.slice(1));
|
|
528
|
+
// `mla pilot` is the pilot value-signal surface (memo §6 Phase 3): record one
|
|
529
|
+
// explicit human verdict at a natural point (`feedback`), fold local events into
|
|
530
|
+
// the four hypotheses (`report`), dump the raw pilot subset (`export`), or consult
|
|
531
|
+
// the deterministic occasional-injection sampling gate (`sample-check`). No
|
|
532
|
+
// dashboard, no server -- it reads/writes the same local events.jsonl.
|
|
533
|
+
case "pilot":
|
|
534
|
+
return (0, pilot_1.runPilot)(argv.slice(1));
|
|
511
535
|
// `mla turn [N]` is the per-turn analog of `mla stats`; `mla stats --turn`
|
|
512
536
|
// routes to the SAME runTurn handler (one implementation, two entry points).
|
|
513
537
|
case "turn":
|
|
@@ -572,6 +596,8 @@ async function dispatch(argv) {
|
|
|
572
596
|
return (0, internal_capture_decisions_1.runCaptureDecisions)(rest);
|
|
573
597
|
if (sub === "pretool-observe")
|
|
574
598
|
return (0, internal_pretool_observe_1.runInternalPretoolObserve)(rest);
|
|
599
|
+
if (sub === "redact-capture")
|
|
600
|
+
return (0, internal_redact_capture_1.runInternalRedactCapture)(rest);
|
|
575
601
|
if (sub === "turn-recap")
|
|
576
602
|
return (0, internal_turn_recap_1.runInternalTurnRecap)(rest);
|
|
577
603
|
if (sub === "refresh")
|
|
@@ -37,7 +37,8 @@ exports.renderActivationCard = void 0;
|
|
|
37
37
|
exports.parseActivateArgs = parseActivateArgs;
|
|
38
38
|
exports.resolveBootstrapTier = resolveBootstrapTier;
|
|
39
39
|
exports.bootstrapTierEmitsMission = bootstrapTierEmitsMission;
|
|
40
|
-
exports.
|
|
40
|
+
exports.bootstrapTierIsDeprecated = bootstrapTierIsDeprecated;
|
|
41
|
+
exports.agenticDeprecationNote = agenticDeprecationNote;
|
|
41
42
|
exports.writeActivationMarker = writeActivationMarker;
|
|
42
43
|
exports.clearDeactivateSentinel = clearDeactivateSentinel;
|
|
43
44
|
exports.removeStaleGitignoreEntry = removeStaleGitignoreEntry;
|
|
@@ -59,7 +60,7 @@ Object.defineProperty(exports, "renderActivationCard", { enumerable: true, get:
|
|
|
59
60
|
const scout_mission_1 = require("../lib/scanner/scout-mission");
|
|
60
61
|
const scan_context_1 = require("./scan-context");
|
|
61
62
|
const workspace_1 = require("../lib/workspace");
|
|
62
|
-
const BOOTSTRAP_TIERS = ["fast", "agentic"
|
|
63
|
+
const BOOTSTRAP_TIERS = ["fast", "agentic"];
|
|
63
64
|
const VALUE_FLAGS = new Set(["--name", "--note", "--bootstrap"]);
|
|
64
65
|
const BOOLEAN_FLAGS = new Set(["--here", "--create", "--repair"]);
|
|
65
66
|
function parseActivateArgs(argv) {
|
|
@@ -76,6 +77,15 @@ function parseActivateArgs(argv) {
|
|
|
76
77
|
else if (a === "--note")
|
|
77
78
|
out.note = v;
|
|
78
79
|
else if (a === "--bootstrap") {
|
|
80
|
+
// The removed `full` tier gets a migration message, never a silent fallback
|
|
81
|
+
// to a shallower tier (Phase 2: "never silently fall back from a named-but-
|
|
82
|
+
// unbuilt tier").
|
|
83
|
+
if (v === "full") {
|
|
84
|
+
throw new Error("The `full` bootstrap tier was removed: its temporal legacy-note graph was " +
|
|
85
|
+
"never built. The deep, agent-driven read now lives in `/mla onboard` " +
|
|
86
|
+
"(two read-only scouts; candidates land born PENDING for you to review). " +
|
|
87
|
+
"Use `--bootstrap fast` (default) or run `/mla onboard` inside a session.");
|
|
88
|
+
}
|
|
79
89
|
if (!BOOTSTRAP_TIERS.includes(v)) {
|
|
80
90
|
throw new Error(`Invalid value for --bootstrap: ${v}. Supported tiers: ${BOOTSTRAP_TIERS.join(", ")}.`);
|
|
81
91
|
}
|
|
@@ -103,17 +113,27 @@ function parseActivateArgs(argv) {
|
|
|
103
113
|
function resolveBootstrapTier(flags) {
|
|
104
114
|
return flags.bootstrap ?? "fast";
|
|
105
115
|
}
|
|
106
|
-
// Whether a tier emits the
|
|
107
|
-
// deterministic `fast` tier stays silent;
|
|
108
|
-
// deep
|
|
116
|
+
// Whether a tier emits the static scout mission after the review bundle. Only the
|
|
117
|
+
// deterministic `fast` tier stays silent; the deprecated `agentic` tier still emits
|
|
118
|
+
// the deep-read mission for back-compat.
|
|
109
119
|
function bootstrapTierEmitsMission(tier) {
|
|
110
120
|
return tier !== "fast";
|
|
111
121
|
}
|
|
112
|
-
// Whether a tier
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
// Whether a tier is deprecated. `agentic` is kept working but steered toward the
|
|
123
|
+
// consolidated `/mla onboard` flow; the activation tail prints the steer below it.
|
|
124
|
+
function bootstrapTierIsDeprecated(tier) {
|
|
125
|
+
return tier === "agentic";
|
|
126
|
+
}
|
|
127
|
+
// Pure steer printed above the static `agentic` mission, pointing at the consolidated
|
|
128
|
+
// `/mla onboard` flow. Exported so the writing-style + content guards can assert it
|
|
129
|
+
// without driving the whole activation tail.
|
|
130
|
+
function agenticDeprecationNote() {
|
|
131
|
+
return [
|
|
132
|
+
"`--bootstrap agentic` is deprecated. The richer, agent-driven onboarding is",
|
|
133
|
+
"`/mla onboard`: two read-only scouts read your docs and git history and surface",
|
|
134
|
+
"candidates born PENDING for you to review (the static mission below is a copy/paste",
|
|
135
|
+
"fallback for shells without a Claude Code session).",
|
|
136
|
+
].join("\n");
|
|
117
137
|
}
|
|
118
138
|
// Pure marker writer (no console output). Writes a `.meetless.json` into `cwd`
|
|
119
139
|
// unless one already exists and `force` is not set. Returns whether a NEW marker
|
|
@@ -481,6 +501,9 @@ function onboardRecommendation(opts) {
|
|
|
481
501
|
" history. They surface constraints, decisions, conventions, boundaries, and",
|
|
482
502
|
" deprecations as candidates born PENDING for you to review; nothing is accepted",
|
|
483
503
|
" automatically. You can run it now or any time later.",
|
|
504
|
+
" First run only: the scout agents were just installed, and Claude Code loads",
|
|
505
|
+
" agents at session start. If `/mla onboard` reports a scout agent is not found,",
|
|
506
|
+
" restart Claude Code (or open a new session) and run it again.",
|
|
484
507
|
].join("\n");
|
|
485
508
|
}
|
|
486
509
|
// Shared tail for the provision/bind paths: clear any per-session OFF sentinel,
|
|
@@ -508,18 +531,16 @@ function finishActivate(cwd, tier, recommendOnboard = false) {
|
|
|
508
531
|
const result = (0, scan_context_1.rescanAndCache)({ cwd, workspaceId: scanWorkspaceId });
|
|
509
532
|
console.log("");
|
|
510
533
|
console.log((0, bootstrap_summary_1.renderBootstrapSummary)(result));
|
|
511
|
-
//
|
|
512
|
-
// deterministic pass could only count
|
|
513
|
-
//
|
|
514
|
-
// built here, so we say so plainly and fall back to the agentic mission.
|
|
534
|
+
// The deprecated `agentic` tier still prints the static scout mission for the
|
|
535
|
+
// messy Tier-2 docs the deterministic pass could only count, but steers the
|
|
536
|
+
// operator to the consolidated `/mla onboard` flow first (Phase 2).
|
|
515
537
|
if (bootstrapTierEmitsMission(tier)) {
|
|
516
|
-
if (
|
|
538
|
+
if (bootstrapTierIsDeprecated(tier)) {
|
|
517
539
|
console.log("");
|
|
518
|
-
console.log(
|
|
519
|
-
console.log("coordination graph. Running the agentic tier below, the deepest available now.");
|
|
540
|
+
console.log(agenticDeprecationNote());
|
|
520
541
|
}
|
|
521
542
|
console.log("");
|
|
522
|
-
console.log("
|
|
543
|
+
console.log("Static scout mission (hand this to a coding agent):");
|
|
523
544
|
console.log("");
|
|
524
545
|
console.log((0, scout_mission_1.renderManualScoutMission)(result));
|
|
525
546
|
}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runAgentMemory = runAgentMemory;
|
|
4
|
+
// src/commands/agent-memory.ts
|
|
5
|
+
//
|
|
6
|
+
// `mla agent-memory <enable|disable|status|scan|push|report>`: the operator
|
|
7
|
+
// surface for the agent-memory capture pipeline
|
|
8
|
+
// (notes/20260626-agent-memory-auto-capture-proposal.md).
|
|
9
|
+
//
|
|
10
|
+
// `scan` is the Phase 1 DRY-RUN: it observes, classifies, secret-scans
|
|
11
|
+
// (observe-only: signals are recorded, nothing is blocked), and records
|
|
12
|
+
// metadata-only decisions locally; it uploads NOTHING.
|
|
13
|
+
//
|
|
14
|
+
// `push` is the Phase 2A LIVE pass: it uploads changed project-type memory
|
|
15
|
+
// revisions to the governed KB (born PENDING, non-grounding), withholding any
|
|
16
|
+
// file carrying a known credential format (SECRET-1). It is DEFAULT OFF behind
|
|
17
|
+
// MEETLESS_AGENT_MEMORY_LIVE and refuses without --yes. The same collector also
|
|
18
|
+
// runs (gated identically) from the Stop auto-index worker. Phase 2A keeps
|
|
19
|
+
// claim extraction OFF; Phase 2B turns it on and is what the missing
|
|
20
|
+
// cross-revision claim-grain idempotency (DERIVED-IDEMPOTENCY-1) gates.
|
|
21
|
+
//
|
|
22
|
+
// Consent (CONSENT-1) is explicit and per-directory: `enable` shows the resolved
|
|
23
|
+
// directory, the target workspace, and exactly what capture does, and refuses to
|
|
24
|
+
// persist a binding without `--yes`.
|
|
25
|
+
const node_fs_1 = require("node:fs");
|
|
26
|
+
const agent_memory_1 = require("../lib/scanner/agent-memory");
|
|
27
|
+
const workspace_1 = require("../lib/workspace");
|
|
28
|
+
const binding_1 = require("../lib/agent-memory-capture/binding");
|
|
29
|
+
const collector_1 = require("../lib/agent-memory-capture/collector");
|
|
30
|
+
const live_collector_1 = require("../lib/agent-memory-capture/live-collector");
|
|
31
|
+
const ledger_1 = require("../lib/agent-memory-capture/ledger");
|
|
32
|
+
const live_ledger_1 = require("../lib/agent-memory-capture/live-ledger");
|
|
33
|
+
const report_1 = require("../lib/agent-memory-capture/report");
|
|
34
|
+
function parseArgs(argv) {
|
|
35
|
+
const out = { sub: null, dir: null, workspace: null, yes: false, json: false };
|
|
36
|
+
for (let i = 0; i < argv.length; i++) {
|
|
37
|
+
const a = argv[i];
|
|
38
|
+
if (a === "--dir") {
|
|
39
|
+
out.dir = argv[++i] ?? null;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (a === "--workspace") {
|
|
43
|
+
out.workspace = argv[++i] ?? null;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (a === "--yes" || a === "-y") {
|
|
47
|
+
out.yes = true;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (a === "--json") {
|
|
51
|
+
out.json = true;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (a.startsWith("-")) {
|
|
55
|
+
throw new Error(`Unknown flag: ${a}`);
|
|
56
|
+
}
|
|
57
|
+
if (out.sub === null) {
|
|
58
|
+
out.sub = a;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`Unexpected argument: ${a}`);
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
function nowIso() {
|
|
66
|
+
return new Date().toISOString();
|
|
67
|
+
}
|
|
68
|
+
// Resolve the directory to operate on: --dir override, else the Claude
|
|
69
|
+
// auto-memory dir for the current project cwd.
|
|
70
|
+
function resolveDir(dir) {
|
|
71
|
+
return dir && dir.trim() ? dir.trim() : (0, agent_memory_1.agentMemoryDir)(process.cwd());
|
|
72
|
+
}
|
|
73
|
+
const CONSENT_LINES = [
|
|
74
|
+
"This enables LOCAL DRY-RUN capture only (Phase 1).",
|
|
75
|
+
"mla will observe project-type memory files in this directory, hash and",
|
|
76
|
+
"secret-scan them, and record metadata-only decisions to a local log.",
|
|
77
|
+
"Nothing is uploaded in this phase.",
|
|
78
|
+
"",
|
|
79
|
+
"Secret patterns are recorded as observations only here; they do not block",
|
|
80
|
+
"anything, because nothing leaves the machine. Pre-upload credential",
|
|
81
|
+
"blocking arrives with remote capture (Phase 2B), not in this phase.",
|
|
82
|
+
"Raw memory notes never ground any agent answer.",
|
|
83
|
+
];
|
|
84
|
+
function runEnable(args) {
|
|
85
|
+
const dir = resolveDir(args.dir);
|
|
86
|
+
let workspaceId;
|
|
87
|
+
if (args.workspace && args.workspace.trim()) {
|
|
88
|
+
workspaceId = args.workspace.trim();
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
try {
|
|
92
|
+
workspaceId = (0, workspace_1.resolveWorkspaceContext)().workspaceId;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
console.error("No activated workspace found. Run this inside an activated repo or pass --workspace <id>.");
|
|
96
|
+
return 2;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const canonical = (0, binding_1.canonicalizeDir)(dir);
|
|
100
|
+
if (!canonical) {
|
|
101
|
+
console.error(`Memory directory does not resolve: ${dir}`);
|
|
102
|
+
console.error("Pass an existing directory with --dir, or activate Claude memory first.");
|
|
103
|
+
return 2;
|
|
104
|
+
}
|
|
105
|
+
if (!args.yes) {
|
|
106
|
+
console.log(`Directory: ${canonical}`);
|
|
107
|
+
console.log(`Workspace: ${workspaceId}`);
|
|
108
|
+
console.log("");
|
|
109
|
+
for (const l of CONSENT_LINES)
|
|
110
|
+
console.log(l);
|
|
111
|
+
console.log("");
|
|
112
|
+
console.log("Re-run with --yes to consent and enable dry-run capture.");
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
const outcome = (0, binding_1.enableBinding)(canonical, workspaceId, nowIso());
|
|
116
|
+
if (!outcome.ok) {
|
|
117
|
+
if (outcome.reason === "workspace-conflict") {
|
|
118
|
+
console.error(`This directory is already bound to workspace ${outcome.conflictWorkspaceId}. ` +
|
|
119
|
+
"One memory directory binds exactly one workspace (MEMORY-WORKSPACE-1). " +
|
|
120
|
+
"Disable the existing binding first.");
|
|
121
|
+
return 2;
|
|
122
|
+
}
|
|
123
|
+
console.error(`Memory directory does not resolve: ${dir}`);
|
|
124
|
+
return 2;
|
|
125
|
+
}
|
|
126
|
+
const b = outcome.binding;
|
|
127
|
+
console.log(`${outcome.reactivated ? "Reactivated" : "Enabled"} dry-run capture for ${b.memoryDir}`);
|
|
128
|
+
console.log(`Binding: ${b.bindingId} -> workspace ${b.workspaceId}`);
|
|
129
|
+
console.log("Run `mla agent-memory scan` to record a dry-run pass (uploads nothing).");
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
function runDisable(args) {
|
|
133
|
+
const dir = resolveDir(args.dir);
|
|
134
|
+
const canonical = (0, binding_1.canonicalizeDir)(dir) ?? dir;
|
|
135
|
+
const b = (0, binding_1.disableBinding)(canonical);
|
|
136
|
+
if (!b) {
|
|
137
|
+
console.error(`No capture binding found for ${canonical}`);
|
|
138
|
+
return 1;
|
|
139
|
+
}
|
|
140
|
+
console.log(`Disabled capture for ${b.memoryDir} (binding ${b.bindingId} preserved).`);
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
143
|
+
// Derive the live ledger's counts for one binding: how many paths the SERVER has
|
|
144
|
+
// acked (uploaded), how many are currently WITHHELD by the credential denylist
|
|
145
|
+
// (blocked), and the total tracked. The live ledger stores acks/blocks, not
|
|
146
|
+
// outcomes, so these are computed from the entry shape.
|
|
147
|
+
function liveLedgerCounts(bindingId) {
|
|
148
|
+
const entries = Object.values((0, live_ledger_1.readLiveLedger)(bindingId).entries);
|
|
149
|
+
let uploaded = 0;
|
|
150
|
+
let blocked = 0;
|
|
151
|
+
for (const e of entries) {
|
|
152
|
+
if (e.lastUploadedHash)
|
|
153
|
+
uploaded++;
|
|
154
|
+
if (e.blockedHash)
|
|
155
|
+
blocked++;
|
|
156
|
+
}
|
|
157
|
+
return { tracked: entries.length, uploaded, blocked };
|
|
158
|
+
}
|
|
159
|
+
function runStatus(args) {
|
|
160
|
+
const bindings = (0, binding_1.listBindings)();
|
|
161
|
+
if (args.json) {
|
|
162
|
+
const rows = bindings.map((b) => ({
|
|
163
|
+
...b,
|
|
164
|
+
ledgerEntries: Object.keys((0, ledger_1.readLedger)(b.bindingId).entries).length,
|
|
165
|
+
live: liveLedgerCounts(b.bindingId),
|
|
166
|
+
}));
|
|
167
|
+
console.log(JSON.stringify({ liveCaptureEnabled: (0, live_collector_1.liveCaptureEnabled)(), bindings: rows }, null, 2));
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
if (bindings.length === 0) {
|
|
171
|
+
console.log("No agent-memory capture bindings. Run `mla agent-memory enable` to create one.");
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
console.log(`Live capture: ${(0, live_collector_1.liveCaptureEnabled)() ? "ENABLED" : "off (default)"}`);
|
|
175
|
+
for (const b of bindings) {
|
|
176
|
+
const entries = Object.keys((0, ledger_1.readLedger)(b.bindingId).entries).length;
|
|
177
|
+
const live = liveLedgerCounts(b.bindingId);
|
|
178
|
+
console.log(`${b.enabled ? "[enabled] " : "[disabled]"} ${b.memoryDir}`);
|
|
179
|
+
console.log(` binding ${b.bindingId}`);
|
|
180
|
+
console.log(` workspace ${b.workspaceId}`);
|
|
181
|
+
console.log(` consented ${b.consentedAt}`);
|
|
182
|
+
console.log(` tracked ${entries} file(s) in dry-run ledger`);
|
|
183
|
+
console.log(` live ${live.tracked} tracked, ${live.uploaded} uploaded, ${live.blocked} blocked`);
|
|
184
|
+
}
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
function tally(records) {
|
|
188
|
+
const t = {};
|
|
189
|
+
for (const r of records)
|
|
190
|
+
t[r.decision] = (t[r.decision] ?? 0) + 1;
|
|
191
|
+
return t;
|
|
192
|
+
}
|
|
193
|
+
function runScan(args) {
|
|
194
|
+
const results = (0, collector_1.runDryRunCollector)({ nowIso: nowIso() });
|
|
195
|
+
if (args.json) {
|
|
196
|
+
console.log(JSON.stringify({ results }, null, 2));
|
|
197
|
+
return 0;
|
|
198
|
+
}
|
|
199
|
+
if (results.length === 0) {
|
|
200
|
+
console.log("No enabled bindings. Run `mla agent-memory enable` first.");
|
|
201
|
+
return 0;
|
|
202
|
+
}
|
|
203
|
+
for (const r of results) {
|
|
204
|
+
if (!r.locked) {
|
|
205
|
+
console.log(`${r.bindingId}: skipped (another collector holds the lock)`);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const s = r.summary;
|
|
209
|
+
if (!s) {
|
|
210
|
+
console.log(`${r.bindingId}: no summary`);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const t = tally(s.records);
|
|
214
|
+
const parts = Object.entries(t).map(([k, v]) => `${k}=${v}`).join(" ");
|
|
215
|
+
console.log(`${s.memoryDir} [scan ${s.scanComplete ? "complete" : "PARTIAL"}] ${parts || "(no files)"}`);
|
|
216
|
+
console.log(` appended ${r.appended} actionable decision(s) to the dry-run log`);
|
|
217
|
+
}
|
|
218
|
+
return 0;
|
|
219
|
+
}
|
|
220
|
+
function liveTally(records) {
|
|
221
|
+
const t = {};
|
|
222
|
+
for (const r of records)
|
|
223
|
+
t[r.outcome] = (t[r.outcome] ?? 0) + 1;
|
|
224
|
+
return t;
|
|
225
|
+
}
|
|
226
|
+
// `push`: the Phase 2A LIVE upload pass. DEFAULT OFF (MEETLESS_AGENT_MEMORY_LIVE)
|
|
227
|
+
// and refuses without --yes. Shares the exact collector + gates the Stop worker
|
|
228
|
+
// uses, so a manual push and an automatic Stop pass behave identically.
|
|
229
|
+
async function runPush(args) {
|
|
230
|
+
if (!(0, live_collector_1.liveCaptureEnabled)()) {
|
|
231
|
+
console.error("Live agent-memory capture is OFF (the default).");
|
|
232
|
+
console.error("");
|
|
233
|
+
console.error("When enabled, this uploads changed project-type memory revisions to the");
|
|
234
|
+
console.error("governed KB as born-PENDING sources. They never ground any agent answer");
|
|
235
|
+
console.error("until a human accepts a derived claim. A pre-upload credential denylist");
|
|
236
|
+
console.error("withholds any file carrying a known credential format.");
|
|
237
|
+
console.error("");
|
|
238
|
+
console.error("To enable, set MEETLESS_AGENT_MEMORY_LIVE=1 and re-run with --yes:");
|
|
239
|
+
console.error(" MEETLESS_AGENT_MEMORY_LIVE=1 mla agent-memory push --yes");
|
|
240
|
+
return 0;
|
|
241
|
+
}
|
|
242
|
+
if (!args.yes) {
|
|
243
|
+
console.log("Live capture is ENABLED.");
|
|
244
|
+
console.log("This will UPLOAD changed project-type memory files from every enabled binding");
|
|
245
|
+
console.log("to the governed KB (born PENDING, non-grounding). Files carrying a known");
|
|
246
|
+
console.log("credential format are withheld. Re-run with --yes to upload.");
|
|
247
|
+
return 0;
|
|
248
|
+
}
|
|
249
|
+
const results = await (0, live_collector_1.runLiveCollector)({ nowIso: nowIso() });
|
|
250
|
+
if (args.json) {
|
|
251
|
+
console.log(JSON.stringify({ results }, null, 2));
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
if (results.length === 0) {
|
|
255
|
+
console.log("No live upload performed (no enabled bindings, or no resolvable actor identity).");
|
|
256
|
+
return 0;
|
|
257
|
+
}
|
|
258
|
+
for (const r of results) {
|
|
259
|
+
if (!r.locked) {
|
|
260
|
+
console.log(`${r.bindingId}: skipped (another collector holds the lock)`);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const s = r.summary;
|
|
264
|
+
if (!s) {
|
|
265
|
+
console.log(`${r.bindingId}: no summary`);
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
const t = liveTally(s.records);
|
|
269
|
+
const parts = Object.entries(t)
|
|
270
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
271
|
+
.join(" ");
|
|
272
|
+
console.log(`${s.memoryDir} [scan ${s.scanComplete ? "complete" : "PARTIAL"}] ${parts || "(no files)"}`);
|
|
273
|
+
console.log(` appended ${r.appended} actionable outcome(s) to the live log`);
|
|
274
|
+
}
|
|
275
|
+
return 0;
|
|
276
|
+
}
|
|
277
|
+
function runReport(args) {
|
|
278
|
+
const dir = resolveDir(args.dir);
|
|
279
|
+
if (!(0, node_fs_1.existsSync)(dir) || !(0, node_fs_1.statSync)(dir).isDirectory()) {
|
|
280
|
+
console.error(`Not a directory: ${dir}`);
|
|
281
|
+
return 2;
|
|
282
|
+
}
|
|
283
|
+
const report = (0, report_1.analyzeCorpus)(dir);
|
|
284
|
+
if (args.json) {
|
|
285
|
+
console.log(JSON.stringify(report, null, 2));
|
|
286
|
+
return 0;
|
|
287
|
+
}
|
|
288
|
+
console.log(`Corpus: ${report.memoryDir}`);
|
|
289
|
+
console.log(`Total .md files: ${report.totalMdFiles}`);
|
|
290
|
+
console.log(`By type: ${JSON.stringify(report.byType)}`);
|
|
291
|
+
console.log(`Size bytes: min=${report.sizeBytes.min} median=${report.sizeBytes.median} ` +
|
|
292
|
+
`p90=${report.sizeBytes.p90} max=${report.sizeBytes.max}`);
|
|
293
|
+
console.log(`Project files with a secret signal (observe-only): ${report.secretSignalFiles.length}`);
|
|
294
|
+
for (const b of report.secretSignalFiles) {
|
|
295
|
+
console.log(` ${b.file}: ${b.ruleIds.join(", ")}`);
|
|
296
|
+
}
|
|
297
|
+
console.log(`Phase 2B credential-denylist probe (known fixtures caught): ${report.credentialProbePass ? "PASS" : "FAIL"}`);
|
|
298
|
+
if (report.credentialProbeMisses.length > 0) {
|
|
299
|
+
console.log(` UNDETECTED known credential token(s) in: ${report.credentialProbeMisses.join(", ")}`);
|
|
300
|
+
}
|
|
301
|
+
console.log("");
|
|
302
|
+
console.log("Manual gates (not auto-measured):");
|
|
303
|
+
for (const g of report.manualGates)
|
|
304
|
+
console.log(` - ${g}`);
|
|
305
|
+
return 0;
|
|
306
|
+
}
|
|
307
|
+
async function runAgentMemory(argv) {
|
|
308
|
+
let args;
|
|
309
|
+
try {
|
|
310
|
+
args = parseArgs(argv);
|
|
311
|
+
}
|
|
312
|
+
catch (e) {
|
|
313
|
+
console.error(e.message);
|
|
314
|
+
return 2;
|
|
315
|
+
}
|
|
316
|
+
switch (args.sub) {
|
|
317
|
+
case "enable":
|
|
318
|
+
return runEnable(args);
|
|
319
|
+
case "disable":
|
|
320
|
+
return runDisable(args);
|
|
321
|
+
case "status":
|
|
322
|
+
return runStatus(args);
|
|
323
|
+
case "scan":
|
|
324
|
+
return runScan(args);
|
|
325
|
+
case "push":
|
|
326
|
+
return runPush(args);
|
|
327
|
+
case "report":
|
|
328
|
+
return runReport(args);
|
|
329
|
+
default:
|
|
330
|
+
console.error("Usage: mla agent-memory <enable|disable|status|scan|push|report> [--dir <path>] [--workspace <id>] [--yes] [--json]");
|
|
331
|
+
return 2;
|
|
332
|
+
}
|
|
333
|
+
}
|