@meetless/mla 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +81 -0
  3. package/dist/build-info.json +9 -0
  4. package/dist/bundles/ask-core.js +396 -0
  5. package/dist/bundles/mcp.js +16592 -0
  6. package/dist/bundles/trace-core.js +263 -0
  7. package/dist/cli.js +828 -0
  8. package/dist/commands/activate.js +781 -0
  9. package/dist/commands/adoption.js +130 -0
  10. package/dist/commands/ask.js +290 -0
  11. package/dist/commands/context.js +114 -0
  12. package/dist/commands/debug.js +313 -0
  13. package/dist/commands/doctor.js +1021 -0
  14. package/dist/commands/enrich.js +427 -0
  15. package/dist/commands/evidence.js +229 -0
  16. package/dist/commands/flush.js +184 -0
  17. package/dist/commands/graph.js +104 -0
  18. package/dist/commands/init.js +272 -0
  19. package/dist/commands/internal-active-review.js +322 -0
  20. package/dist/commands/internal-auto-index.js +188 -0
  21. package/dist/commands/internal-capture-decisions.js +320 -0
  22. package/dist/commands/internal-evidence-correlate.js +239 -0
  23. package/dist/commands/internal-evidence-hooks.js +240 -0
  24. package/dist/commands/internal-evidence-inject.js +231 -0
  25. package/dist/commands/internal-finalize.js +221 -0
  26. package/dist/commands/internal-pretool-observe.js +225 -0
  27. package/dist/commands/internal-refresh.js +136 -0
  28. package/dist/commands/internal-session-nudge.js +120 -0
  29. package/dist/commands/internal-steer-sync.js +117 -0
  30. package/dist/commands/internal-turn-recap.js +140 -0
  31. package/dist/commands/kb.js +375 -0
  32. package/dist/commands/kb_add.js +681 -0
  33. package/dist/commands/kb_forget.js +283 -0
  34. package/dist/commands/kb_move.js +45 -0
  35. package/dist/commands/kb_pending.js +410 -0
  36. package/dist/commands/kb_personal.js +149 -0
  37. package/dist/commands/kb_promote.js +188 -0
  38. package/dist/commands/kb_purge.js +168 -0
  39. package/dist/commands/kb_reingest.js +335 -0
  40. package/dist/commands/kb_retime.js +170 -0
  41. package/dist/commands/kb_review.js +391 -0
  42. package/dist/commands/kb_revision.js +179 -0
  43. package/dist/commands/kb_show.js +385 -0
  44. package/dist/commands/label.js +226 -0
  45. package/dist/commands/login.js +295 -0
  46. package/dist/commands/logout.js +108 -0
  47. package/dist/commands/mcp-supervisor.js +93 -0
  48. package/dist/commands/mcp.js +227 -0
  49. package/dist/commands/queue-prune.js +98 -0
  50. package/dist/commands/review.js +358 -0
  51. package/dist/commands/rewire.js +124 -0
  52. package/dist/commands/rules.js +728 -0
  53. package/dist/commands/scan-context.js +67 -0
  54. package/dist/commands/session.js +347 -0
  55. package/dist/commands/stats.js +479 -0
  56. package/dist/commands/status.js +61 -0
  57. package/dist/commands/summary.js +250 -0
  58. package/dist/commands/turn.js +114 -0
  59. package/dist/commands/uninstall.js +222 -0
  60. package/dist/commands/whoami.js +102 -0
  61. package/dist/commands/workspace.js +130 -0
  62. package/dist/hooks-template/ce0-post-tool-use.sh +34 -0
  63. package/dist/hooks-template/ce0-session-start.sh +49 -0
  64. package/dist/hooks-template/ce0-stop.sh +29 -0
  65. package/dist/hooks-template/ce0-user-prompt-submit.sh +38 -0
  66. package/dist/hooks-template/common.sh +934 -0
  67. package/dist/hooks-template/event-batch-filter.jq +67 -0
  68. package/dist/hooks-template/flush.sh +503 -0
  69. package/dist/hooks-template/post-tool-use.sh +423 -0
  70. package/dist/hooks-template/pre-tool-use.sh +69 -0
  71. package/dist/hooks-template/session-start.sh +140 -0
  72. package/dist/hooks-template/stop.sh +308 -0
  73. package/dist/hooks-template/user-prompt-submit.sh +1162 -0
  74. package/dist/lib/activation.js +79 -0
  75. package/dist/lib/active-conflict-cache.js +141 -0
  76. package/dist/lib/active-memory.js +59 -0
  77. package/dist/lib/active-review-runner.js +26 -0
  78. package/dist/lib/agent-decision/index.js +25 -0
  79. package/dist/lib/agent-decision/keys.js +49 -0
  80. package/dist/lib/agent-decision/normalize-claude.js +183 -0
  81. package/dist/lib/agent-decision/types.js +21 -0
  82. package/dist/lib/agent-decision/validate.js +216 -0
  83. package/dist/lib/analytics/capture.js +96 -0
  84. package/dist/lib/analytics/command-event.js +267 -0
  85. package/dist/lib/analytics/consent.js +58 -0
  86. package/dist/lib/analytics/coverage-gap.js +96 -0
  87. package/dist/lib/analytics/envelope.js +236 -0
  88. package/dist/lib/analytics/event-id.js +86 -0
  89. package/dist/lib/analytics/evidence.js +150 -0
  90. package/dist/lib/analytics/followthrough.js +194 -0
  91. package/dist/lib/analytics/forwarder.js +109 -0
  92. package/dist/lib/analytics/logs.js +78 -0
  93. package/dist/lib/analytics/metrics.js +78 -0
  94. package/dist/lib/analytics/recorder.js +92 -0
  95. package/dist/lib/analytics/review-analytics.js +75 -0
  96. package/dist/lib/analytics/sequence.js +77 -0
  97. package/dist/lib/analytics/store.js +131 -0
  98. package/dist/lib/analytics/turn-recap.js +279 -0
  99. package/dist/lib/artifact_id.js +108 -0
  100. package/dist/lib/auth-breaker.js +161 -0
  101. package/dist/lib/auto-index.js +112 -0
  102. package/dist/lib/classifier.js +88 -0
  103. package/dist/lib/config.js +298 -0
  104. package/dist/lib/conflict-advisory.js +64 -0
  105. package/dist/lib/debug-bundle.js +520 -0
  106. package/dist/lib/enrichment/ingest.js +301 -0
  107. package/dist/lib/enrichment/plan.js +253 -0
  108. package/dist/lib/enrichment/protocol.js +359 -0
  109. package/dist/lib/enrichment/scout-brief.js +176 -0
  110. package/dist/lib/failure-telemetry.js +444 -0
  111. package/dist/lib/git.js +200 -0
  112. package/dist/lib/governance-cache.js +77 -0
  113. package/dist/lib/governed-path-cache.js +76 -0
  114. package/dist/lib/http.js +677 -0
  115. package/dist/lib/identity-envelope.js +23 -0
  116. package/dist/lib/kb-candidate.js +65 -0
  117. package/dist/lib/kb_acl.js +98 -0
  118. package/dist/lib/login.js +353 -0
  119. package/dist/lib/mcp-fetchers.js +130 -0
  120. package/dist/lib/mcp-restart.js +47 -0
  121. package/dist/lib/observability.js +805 -0
  122. package/dist/lib/open-url.js +33 -0
  123. package/dist/lib/orphan-guard.js +70 -0
  124. package/dist/lib/packaged.js +21 -0
  125. package/dist/lib/reconcile-sessions.js +171 -0
  126. package/dist/lib/redactor.js +89 -0
  127. package/dist/lib/relationship-candidate-query.js +27 -0
  128. package/dist/lib/render.js +611 -0
  129. package/dist/lib/rules/applicability.js +64 -0
  130. package/dist/lib/rules/attest-code-rule-version.js +47 -0
  131. package/dist/lib/rules/attest-notes-location.js +217 -0
  132. package/dist/lib/rules/attest-rule-version.js +69 -0
  133. package/dist/lib/rules/canonical-json.js +97 -0
  134. package/dist/lib/rules/ce0-emit.js +64 -0
  135. package/dist/lib/rules/ce0-evidence.js +281 -0
  136. package/dist/lib/rules/ce0-recall-sample.js +82 -0
  137. package/dist/lib/rules/ce0-rule.js +55 -0
  138. package/dist/lib/rules/ce0-sampling-bucket.js +15 -0
  139. package/dist/lib/rules/ce0-store.js +683 -0
  140. package/dist/lib/rules/ce0-telemetry-project.js +93 -0
  141. package/dist/lib/rules/ce0-telemetry.js +158 -0
  142. package/dist/lib/rules/code-rule-registry.js +17 -0
  143. package/dist/lib/rules/command-match.js +185 -0
  144. package/dist/lib/rules/consult-evidence-binding.js +27 -0
  145. package/dist/lib/rules/consultation-capture-adapter.js +193 -0
  146. package/dist/lib/rules/content-match.js +56 -0
  147. package/dist/lib/rules/deny-admission.js +99 -0
  148. package/dist/lib/rules/durable-observation.js +190 -0
  149. package/dist/lib/rules/enforce-notes-version.js +421 -0
  150. package/dist/lib/rules/evaluation-input-hash.js +126 -0
  151. package/dist/lib/rules/evaluator.js +108 -0
  152. package/dist/lib/rules/inert-rule-families.js +51 -0
  153. package/dist/lib/rules/input-authority-resolver.js +241 -0
  154. package/dist/lib/rules/interception-schema.js +170 -0
  155. package/dist/lib/rules/interception-store.js +267 -0
  156. package/dist/lib/rules/live-input-authority.js +66 -0
  157. package/dist/lib/rules/local-matcher.js +108 -0
  158. package/dist/lib/rules/local-observe.js +79 -0
  159. package/dist/lib/rules/local-rule-version-repo.js +214 -0
  160. package/dist/lib/rules/memory-requirement.js +109 -0
  161. package/dist/lib/rules/notes-observe.js +39 -0
  162. package/dist/lib/rules/notes-path.js +261 -0
  163. package/dist/lib/rules/notes-rule.js +75 -0
  164. package/dist/lib/rules/observe-adapter.js +114 -0
  165. package/dist/lib/rules/observed-rule-hash.js +119 -0
  166. package/dist/lib/rules/prompt-submit-adapter.js +132 -0
  167. package/dist/lib/rules/requirement-subject.js +240 -0
  168. package/dist/lib/rules/rule-activity.js +67 -0
  169. package/dist/lib/rules/rule-version-hash.js +151 -0
  170. package/dist/lib/rules/runtime-scope.js +55 -0
  171. package/dist/lib/rules/stop-adapter.js +116 -0
  172. package/dist/lib/rules/stop-response-snapshot.js +174 -0
  173. package/dist/lib/rules/types.js +10 -0
  174. package/dist/lib/rules/ulid.js +46 -0
  175. package/dist/lib/rules/version-evaluation.js +156 -0
  176. package/dist/lib/scanner/agent-memory.js +99 -0
  177. package/dist/lib/scanner/bootstrap-summary.js +87 -0
  178. package/dist/lib/scanner/cache.js +59 -0
  179. package/dist/lib/scanner/frontmatter.js +42 -0
  180. package/dist/lib/scanner/parse-directives.js +69 -0
  181. package/dist/lib/scanner/parse-structured.js +72 -0
  182. package/dist/lib/scanner/render.js +73 -0
  183. package/dist/lib/scanner/scan.js +132 -0
  184. package/dist/lib/scanner/score.js +38 -0
  185. package/dist/lib/scanner/scout-mission.js +126 -0
  186. package/dist/lib/scanner/types.js +7 -0
  187. package/dist/lib/session-scope.js +195 -0
  188. package/dist/lib/spool.js +355 -0
  189. package/dist/lib/staleness.js +100 -0
  190. package/dist/lib/steer-cache.js +87 -0
  191. package/dist/lib/tagged-reference.js +20 -0
  192. package/dist/lib/temporal.js +109 -0
  193. package/dist/lib/turn-recap-emit.js +67 -0
  194. package/dist/lib/unwire.js +253 -0
  195. package/dist/lib/update-check.js +469 -0
  196. package/dist/lib/update-notifier.js +217 -0
  197. package/dist/lib/upgrade-apply.js +643 -0
  198. package/dist/lib/wire.js +1087 -0
  199. package/dist/lib/workspace.js +96 -0
  200. package/dist/lib/zip.js +154 -0
  201. package/dist/pretool-entry.js +37 -0
  202. package/package.json +75 -0
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseReportCitations = exports.parseMcpCalls = exports.parseInjectTurns = exports.computeFollowthrough = exports.buildAdoption = void 0;
37
+ exports.parseAdoptionArgs = parseAdoptionArgs;
38
+ exports.runAdoption = runAdoption;
39
+ const path = __importStar(require("path"));
40
+ const followthrough_1 = require("../lib/analytics/followthrough");
41
+ Object.defineProperty(exports, "buildAdoption", { enumerable: true, get: function () { return followthrough_1.buildAdoption; } });
42
+ Object.defineProperty(exports, "computeFollowthrough", { enumerable: true, get: function () { return followthrough_1.computeFollowthrough; } });
43
+ Object.defineProperty(exports, "parseInjectTurns", { enumerable: true, get: function () { return followthrough_1.parseInjectTurns; } });
44
+ Object.defineProperty(exports, "parseMcpCalls", { enumerable: true, get: function () { return followthrough_1.parseMcpCalls; } });
45
+ Object.defineProperty(exports, "parseReportCitations", { enumerable: true, get: function () { return followthrough_1.parseReportCitations; } });
46
+ const logs_1 = require("../lib/analytics/logs");
47
+ function parseAdoptionArgs(argv) {
48
+ const out = { last: 50, json: false, all: false, window: 1 };
49
+ for (let i = 0; i < argv.length; i++) {
50
+ const a = argv[i];
51
+ if (a === "--json")
52
+ out.json = true;
53
+ else if (a === "--all")
54
+ out.all = true;
55
+ else if (a === "--last") {
56
+ const v = argv[++i];
57
+ const parsed = Number(v);
58
+ if (!v || !Number.isInteger(parsed) || parsed <= 0) {
59
+ throw new Error(`--last requires a positive integer (got: ${v ?? "(none)"})`);
60
+ }
61
+ out.last = parsed;
62
+ }
63
+ else if (a === "--window") {
64
+ const v = argv[++i];
65
+ const parsed = Number(v);
66
+ if (v === undefined || !Number.isInteger(parsed) || parsed < 0) {
67
+ throw new Error(`--window requires a non-negative integer (got: ${v ?? "(none)"})`);
68
+ }
69
+ out.window = parsed;
70
+ }
71
+ else
72
+ throw new Error(`Unknown flag for \`mla adoption\`: ${a}`);
73
+ }
74
+ return out;
75
+ }
76
+ function renderAdoption(a) {
77
+ const pct = (r) => (r * 100).toFixed(0) + "%";
78
+ const frac = (x) => `${x}/${a.inject_turns}`;
79
+ return [
80
+ `Evidence-followthrough (A1) over ${a.inject_turns} high-value inject turn(s):`,
81
+ ` A1c any followthrough: ${frac(a.a1c_any)} (${pct(a.a1c_rate)})`,
82
+ ` A1a pull-followthrough: ${frac(a.a1a_pull)} (${pct(a.a1a_rate)})`,
83
+ ` A1b push-reference: ${frac(a.a1b_push_reference)} (${pct(a.a1b_rate)})`,
84
+ ` No followthrough: ${frac(a.no_followthrough)} (${pct(a.inject_turns ? a.no_followthrough / a.inject_turns : 0)})`,
85
+ ].join("\n");
86
+ }
87
+ function runAdoption(argv) {
88
+ let args;
89
+ try {
90
+ args = parseAdoptionArgs(argv);
91
+ }
92
+ catch (e) {
93
+ console.error(e.message);
94
+ return 2;
95
+ }
96
+ let injects = (0, followthrough_1.parseInjectTurns)((0, logs_1.readLogJsonl)("ask-traces.jsonl"));
97
+ const calls = (0, followthrough_1.parseMcpCalls)((0, logs_1.readLogJsonl)("mcp-calls.jsonl"));
98
+ const citations = (0, followthrough_1.parseReportCitations)((0, logs_1.readLogJsonl)("report-citations.jsonl"));
99
+ // Auto-scope to the current live session (same contract as `mla summary`).
100
+ // Scope the inject denominator BEFORE --last so the window is "last N inject
101
+ // turns of this session". The pull/report sides are matched per-session in the
102
+ // join, so scoping only the inject side is sufficient.
103
+ const session = (process.env.CLAUDE_CODE_SESSION_ID || "").trim();
104
+ const scoped = !args.all && session.length > 0;
105
+ if (scoped)
106
+ injects = injects.filter((t) => t.session_id === session);
107
+ if (injects.length === 0) {
108
+ const at = path.join((0, logs_1.logsDir)(), "ask-traces.jsonl");
109
+ console.error(scoped
110
+ ? `No high-value inject turns for the current session (${session}) in ${at}. Use --all for every session.`
111
+ : `No high-value inject turns found in ${at}.`);
112
+ return 1;
113
+ }
114
+ // Stable per-session turn order, then keep the most recent N inject turns.
115
+ injects.sort((a, b) => a.session_id === b.session_id
116
+ ? a.turn_index - b.turn_index
117
+ : a.session_id < b.session_id
118
+ ? -1
119
+ : 1);
120
+ injects = injects.slice(-args.last);
121
+ const rows = (0, followthrough_1.computeFollowthrough)(injects, calls, citations, args.window);
122
+ const agg = (0, followthrough_1.buildAdoption)(rows);
123
+ if (args.json) {
124
+ console.log(JSON.stringify(agg, null, 2));
125
+ }
126
+ else {
127
+ console.log(renderAdoption(agg));
128
+ }
129
+ return 0;
130
+ }
@@ -0,0 +1,290 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseArgs = parseArgs;
37
+ exports.runAsk = runAsk;
38
+ const path = __importStar(require("path"));
39
+ const url_1 = require("url");
40
+ const config_1 = require("../lib/config");
41
+ const http_1 = require("../lib/http");
42
+ const temporal_1 = require("../lib/temporal");
43
+ const packaged_1 = require("../lib/packaged");
44
+ const MODES = ["answer", "search", "canonical", "compare"];
45
+ function parseArgs(argv) {
46
+ const out = { query: "", mode: "answer", json: true };
47
+ let sawQuery = false;
48
+ for (let i = 0; i < argv.length; i++) {
49
+ const a = argv[i];
50
+ if (a === "--mode") {
51
+ const v = argv[++i];
52
+ if (!MODES.includes(v)) {
53
+ throw new Error(`Unknown mode '${v ?? ""}'. Valid: ${MODES.join(", ")}.`);
54
+ }
55
+ out.mode = v;
56
+ }
57
+ else if (a === "--workspace" || a === "--workspace-id") {
58
+ out.workspaceId = argv[++i];
59
+ }
60
+ else if (a === "--max") {
61
+ out.maxResults = Number(argv[++i]);
62
+ }
63
+ else if (a === "--min") {
64
+ out.minResults = Number(argv[++i]);
65
+ }
66
+ else if (a === "--as-of") {
67
+ // parseAsOf throws on a malformed date; the throw propagates out of
68
+ // parseArgs and runAsk maps it to exit 2, so a typo never silently
69
+ // answers as-of "now".
70
+ out.asOf = (0, temporal_1.parseAsOf)(argv[++i] ?? "");
71
+ }
72
+ else if (a === "--plain") {
73
+ out.json = false;
74
+ }
75
+ else if (a === "--json") {
76
+ out.json = true;
77
+ }
78
+ else if (a.startsWith("--")) {
79
+ throw new Error(`Unknown flag for \`mla ask\`: ${a}`);
80
+ }
81
+ else if (!sawQuery) {
82
+ out.query = a;
83
+ sawQuery = true;
84
+ }
85
+ else {
86
+ throw new Error(`Unexpected positional argument: ${a} (quote the query as a single argument).`);
87
+ }
88
+ }
89
+ if (!out.query.trim()) {
90
+ throw new Error(`Usage: mla ask "<query>" [--mode answer|search|canonical|compare] [--workspace <id>] [--as-of <date>] [--max <n>] [--min <n>] [--plain]`);
91
+ }
92
+ return out;
93
+ }
94
+ // ask-core is plain ESM; `mla` compiles to CommonJS. A literal dynamic import()
95
+ // would be downleveled by tsc to require(), which cannot load an ESM-only
96
+ // package on Node < 22. The Function constructor preserves a TRUE runtime
97
+ // import() so it works on every supported Node (>=18.18). Used only by the dev
98
+ // fallback below (ts-node, no built dist). Resolve ask-core as a sibling package
99
+ // directory (packages/ask-core), three levels up from the compiled commands dir
100
+ // (dist/commands -> dist -> cli -> packages).
101
+ const trueDynamicImport = new Function("u", "return import(u)");
102
+ function askCoreDir() {
103
+ return path.resolve(__dirname, "..", "..", "..", "ask-core");
104
+ }
105
+ // The CJS bundle the build emits (scripts/bundle-esm.js -> dist/bundles/). It
106
+ // sits a sibling level up from the compiled commands dir: dist/commands -> dist
107
+ // -> dist/bundles.
108
+ function bundlePath(name) {
109
+ return path.resolve(__dirname, "..", "bundles", name);
110
+ }
111
+ function notesRoot() {
112
+ if (process.env.MEETLESS_NOTES_ROOT)
113
+ return process.env.MEETLESS_NOTES_ROOT;
114
+ // Best-effort: the standalone notes repo is a sibling of the code repo. A
115
+ // missing INDEX.md degrades to retrieval, so an imperfect guess here is
116
+ // non-fatal.
117
+ return path.resolve(__dirname, "..", "..", "..", "..", "..", "notes");
118
+ }
119
+ // Load ask-core from its ESM source files (the original path). Kept as the dev
120
+ // fallback for `pnpm dev` (ts-node), where no dist/bundles exists. Never reached
121
+ // inside the pkg binary: a true import() throws there (no ESM dynamic-import
122
+ // callback in the V8 snapshot), which is exactly why the bundle exists.
123
+ async function loadAskCoreFromSource() {
124
+ const dir = askCoreDir();
125
+ const askModes = (await trueDynamicImport((0, url_1.pathToFileURL)(path.join(dir, "ask_modes.js")).href));
126
+ const sf = (await trueDynamicImport((0, url_1.pathToFileURL)(path.join(dir, "status_fallback.js")).href));
127
+ const mc = (await trueDynamicImport((0, url_1.pathToFileURL)(path.join(dir, "match_canonical.js")).href));
128
+ return { ...askModes, ...sf, ...mc };
129
+ }
130
+ // Prefer the bundled CJS: require() works inside the pkg snapshot, unlike a true
131
+ // import(). On a source/npm install the bundle is present after `pnpm build`.
132
+ // The dev fallback covers ts-node (`pnpm dev`), where no dist exists yet.
133
+ async function loadAskCore() {
134
+ try {
135
+ return require(bundlePath("ask-core.js"));
136
+ }
137
+ catch (e) {
138
+ // Inside the binary there is no source tree to fall back to, and require of
139
+ // an embedded bundle should never fail; surface the real error rather than
140
+ // attempting a true import() that the snapshot cannot host.
141
+ if ((0, packaged_1.isPackagedBinary)())
142
+ throw e;
143
+ // Dev/source without a built dist (ts-node): only fall through on a genuine
144
+ // "module not found"; a real load error inside the bundle must surface.
145
+ const code = e?.code;
146
+ if (code !== "MODULE_NOT_FOUND" && code !== "ERR_MODULE_NOT_FOUND")
147
+ throw e;
148
+ return loadAskCoreFromSource();
149
+ }
150
+ }
151
+ // A citation field is "meaningful" only if it's a non-empty string that isn't
152
+ // the "UNKNOWN" sentinel ask-core stamps when intel returns no value. Used to
153
+ // keep noise (`[UNKNOWN]`) out of the --plain footer.
154
+ function meaningful(v) {
155
+ if (typeof v !== "string")
156
+ return null;
157
+ const t = v.trim();
158
+ if (!t || t.toUpperCase() === "UNKNOWN")
159
+ return null;
160
+ return t;
161
+ }
162
+ // The bracketed metadata after a citation path: the doc KIND (docType, which
163
+ // ask-core always sets -- defaulting to "note") and, when present, the
164
+ // lifecycle STATUS (SHIPPED/PROPOSED/...). Before this, the footer rendered
165
+ // r.status alone, so every grounded note printed a useless `[UNKNOWN]` (notes
166
+ // carry a docType but no status) even though the inline `[NT:...]` citation
167
+ // already knew the kind. Kind-first, status-when-real.
168
+ function citationMeta(r) {
169
+ const parts = [meaningful(r.docType), meaningful(r.status)].filter((x) => x !== null);
170
+ return parts.length > 0 ? ` [${parts.join(", ")}]` : "";
171
+ }
172
+ function renderPlain(result) {
173
+ const lines = [];
174
+ const answer = result.answer;
175
+ if (typeof answer === "string" && answer.trim()) {
176
+ lines.push(answer.trim());
177
+ lines.push("");
178
+ }
179
+ const results = Array.isArray(result.results) ? result.results : [];
180
+ if (results.length > 0) {
181
+ lines.push(`Citations (${results.length}):`);
182
+ for (const r of results) {
183
+ const p = r.path ?? r.title ?? "(unknown)";
184
+ lines.push(` - ${String(p)}${citationMeta(r)}`);
185
+ }
186
+ }
187
+ const warnings = Array.isArray(result.warnings) ? result.warnings : [];
188
+ if (warnings.length > 0) {
189
+ lines.push("");
190
+ lines.push("Warnings:");
191
+ for (const w of warnings)
192
+ lines.push(` ! ${String(w)}`);
193
+ }
194
+ lines.push("");
195
+ lines.push(`(workspace: ${String(result.workspace ?? "")}, mode: ${String(result.mode ?? "")}, confidence: ${String(result.confidence ?? "")})`);
196
+ return lines.join("\n");
197
+ }
198
+ // The ask-core loader is injectable so the glue (workspace resolution, mode
199
+ // routing, render, error->exit-code mapping) can be unit-tested without the
200
+ // true runtime import(): jest's VM sandbox rejects native dynamic import
201
+ // unless run with --experimental-vm-modules, and ask-core is ESM-only. The
202
+ // REAL dynamic import is proven by a runtime smoke against the built binary,
203
+ // not by jest. cli.ts always calls the single-arg form, so the seam never
204
+ // reaches the shipped path.
205
+ async function runAsk(argv, deps = {}) {
206
+ let args;
207
+ try {
208
+ args = parseArgs(argv);
209
+ }
210
+ catch (e) {
211
+ console.error(e.message);
212
+ return 2;
213
+ }
214
+ // Folder = workspace (T1.1): resolve the workspace from the nearest marker,
215
+ // honoring `--workspace <id>` as an explicit override so an operator can ask
216
+ // against another workspace from an unbound directory without tripping the
217
+ // "not activated" guard. Loading after parseArgs is what lets the override
218
+ // short-circuit marker resolution.
219
+ const cfg = (0, config_1.loadWorkspaceConfig)(args.workspaceId);
220
+ const intelUrl = cfg.intelUrl || http_1.DEFAULT_INTEL_URL;
221
+ // cfg.controlToken IS intel's INTERNAL_API_KEY in the dogfood config (same
222
+ // bearer the hook uses for /v1/ask; see lib/http.ts).
223
+ const apiKey = cfg.controlToken;
224
+ const effectiveWorkspace = cfg.workspaceId;
225
+ let core;
226
+ try {
227
+ core = await (deps.loadCore ?? loadAskCore)();
228
+ }
229
+ catch (e) {
230
+ console.error(`failed to load @meetless/ask-core: ${e.message}`);
231
+ return 1;
232
+ }
233
+ const intelAsk = core.makeIntelAsk({ intelBaseUrl: intelUrl, apiKey });
234
+ const matchCanonical = core.makeMatchCanonical({ notesRoot: notesRoot() });
235
+ const modes = core.makeAskModes({
236
+ intelAsk,
237
+ defaultWorkspaceId: effectiveWorkspace,
238
+ matchCanonical,
239
+ statusFallback: core.statusFallback,
240
+ });
241
+ const callArgs = {
242
+ query: args.query,
243
+ workspace_id: effectiveWorkspace,
244
+ };
245
+ if (args.maxResults !== undefined)
246
+ callArgs.maxResults = args.maxResults;
247
+ if (args.minResults !== undefined)
248
+ callArgs.minResults = args.minResults;
249
+ // B9: forward the valid-time cutoff ONLY when the operator set it, so the live
250
+ // (no --as-of) path stays byte-identical to today. The one-line banner goes to
251
+ // stderr so `mla ask` stdout stays pure JSON for piping.
252
+ if (args.asOf) {
253
+ callArgs.as_of = args.asOf;
254
+ console.error(`Point-in-time answer as of ${args.asOf} (relations not yet valid at that instant are excluded).`);
255
+ }
256
+ const handler = args.mode === "search"
257
+ ? modes.runSearch
258
+ : args.mode === "canonical"
259
+ ? modes.runCanonical
260
+ : args.mode === "compare"
261
+ ? modes.runCompare
262
+ : modes.runAnswer;
263
+ let result;
264
+ try {
265
+ result = await handler(callArgs);
266
+ }
267
+ catch (e) {
268
+ const msg = e.message || String(e);
269
+ if (/ECONNREFUSED|fetch failed|ENOTFOUND/i.test(msg)) {
270
+ console.error(`intel not reachable at ${intelUrl}. Is it running? Try \`mla doctor\`.`);
271
+ }
272
+ else {
273
+ console.error(`mla ask failed: ${msg}`);
274
+ }
275
+ return 1;
276
+ }
277
+ // Echo the effective workspace so the caller always sees which corpus
278
+ // answered (mirrors the MCP's server.js behavior; makes ingest/answer drift
279
+ // impossible to miss).
280
+ if (result && typeof result === "object") {
281
+ result.workspace = effectiveWorkspace;
282
+ }
283
+ if (args.json) {
284
+ console.log(JSON.stringify(result, null, 2));
285
+ }
286
+ else {
287
+ console.log(renderPlain(result));
288
+ }
289
+ return 0;
290
+ }
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyContextVerdict = applyContextVerdict;
4
+ exports.advisoryLines = advisoryLines;
5
+ exports.latestReviewCardItems = latestReviewCardItems;
6
+ exports.runContext = runContext;
7
+ // src/commands/context.ts
8
+ const node_fs_1 = require("node:fs");
9
+ const node_os_1 = require("node:os");
10
+ const node_path_1 = require("node:path");
11
+ const cache_1 = require("../lib/scanner/cache");
12
+ const workspace_1 = require("../lib/workspace");
13
+ const scan_context_1 = require("./scan-context");
14
+ // Pure verdict bookkeeping (no rescan); the command wrapper triggers the rescan.
15
+ function applyContextVerdict(args) {
16
+ const v = (0, cache_1.readVerdicts)(args.home, args.workspaceId);
17
+ const add = (list, id) => (list.includes(id) ? list : [...list, id]);
18
+ const drop = (list, id) => list.filter((x) => x !== id);
19
+ if (args.action === "accept") {
20
+ v.accepted = add(v.accepted, args.id);
21
+ v.dismissed = drop(v.dismissed, args.id);
22
+ }
23
+ else {
24
+ v.dismissed = add(v.dismissed, args.id);
25
+ v.accepted = drop(v.accepted, args.id);
26
+ }
27
+ (0, cache_1.writeVerdicts)(args.home, args.workspaceId, v);
28
+ }
29
+ // Read-only view of the advisory agent-memory rules captured in the scan cache.
30
+ // These are machine_inferred (untracked, per-machine, agent-distilled), so they are
31
+ // NEVER auto-injected as must-follow; this list is a human review surface only.
32
+ // `?? []` guards a pre-M1 on-disk cache that predates the advisoryDirectives field.
33
+ function advisoryLines(home, workspaceId) {
34
+ const cache = (0, cache_1.readScanCache)(home, workspaceId);
35
+ const advisory = cache?.advisoryDirectives ?? [];
36
+ return advisory.map((d) => `${d.id} [${d.strength}] ${d.text} (${d.source})`);
37
+ }
38
+ function latestReviewCardItems(home, workspaceId) {
39
+ const path = (0, node_path_1.join)(home, ".meetless", "workspaces", workspaceId, "review-cards.jsonl");
40
+ let lines;
41
+ try {
42
+ lines = (0, node_fs_1.readFileSync)(path, "utf8").split("\n").filter(Boolean);
43
+ }
44
+ catch {
45
+ return [];
46
+ }
47
+ for (let i = lines.length - 1; i >= 0; i--) {
48
+ try {
49
+ const row = JSON.parse(lines[i]);
50
+ if (row.event === "review_card" && Array.isArray(row.items))
51
+ return row.items;
52
+ }
53
+ catch {
54
+ // skip malformed line
55
+ }
56
+ }
57
+ return [];
58
+ }
59
+ async function runContext(argv) {
60
+ const [sub, id] = argv;
61
+ const workspaceId = (0, workspace_1.resolveWorkspaceIdWithEnv)();
62
+ if (!workspaceId) {
63
+ console.error("context: run inside an activated workspace (MEETLESS_WORKSPACE_ID unset and no .meetless.json marker found).");
64
+ return 2;
65
+ }
66
+ const home = (0, node_os_1.homedir)();
67
+ if (sub === "list") {
68
+ const cache = (0, cache_1.readScanCache)(home, workspaceId);
69
+ if (cache && cache.staleSignals.length) {
70
+ for (const s of cache.staleSignals)
71
+ console.log(`${s.id} ${s.detail}`);
72
+ return 0;
73
+ }
74
+ if (!cache) {
75
+ // No live scan cache (workspace not scanned yet, or cache cleared). Fall back to
76
+ // the last session's review card as a degraded, clearly-labelled view.
77
+ const card = latestReviewCardItems(home, workspaceId);
78
+ if (card.length) {
79
+ console.log("No current scan cache; showing the last session's review card. Run `mla activate` to refresh.");
80
+ for (const item of card)
81
+ console.log(`${item.id} ${item.detail}`);
82
+ return 0;
83
+ }
84
+ }
85
+ console.log("No pending review items.");
86
+ return 0;
87
+ }
88
+ if (sub === "advisory") {
89
+ const lines = advisoryLines(home, workspaceId);
90
+ if (!lines.length) {
91
+ console.log("No advisory agent-memory rules.");
92
+ return 0;
93
+ }
94
+ // Advisory rules are machine_inferred and never injected; this is review-only.
95
+ // accept/dismiss is deliberately NOT wired here: promoting a machine_inferred rule
96
+ // to attested is a state transition that belongs to a human attestation flow.
97
+ console.log("Advisory rules from agent memory (machine_inferred; NOT injected; review only):");
98
+ for (const l of lines)
99
+ console.log(` ${l}`);
100
+ return 0;
101
+ }
102
+ if ((sub === "accept" || sub === "dismiss") && id) {
103
+ applyContextVerdict({ home, workspaceId, action: sub, id });
104
+ // Anchor the refresh to the marker dir, not cwd: a dismiss/accept from a
105
+ // package subdir must rescan the WHOLE workspace, or the cache loses every
106
+ // rule outside the subdir and the just-dismissed signal resurfaces under a
107
+ // new (path-relative) id. See resolveScanRoot.
108
+ void (0, scan_context_1.rescanAndCache)({ cwd: (0, scan_context_1.resolveScanRoot)(process.cwd()), workspaceId, home });
109
+ console.log(`${sub === "accept" ? "Accepted" : "Dismissed"} ${id}. Next session's context updated.`);
110
+ return 0;
111
+ }
112
+ console.error("usage: mla context <accept|dismiss> <id> | mla context list | mla context advisory");
113
+ return 2;
114
+ }