@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
package/dist/cli.js ADDED
@@ -0,0 +1,828 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.dispatch = dispatch;
38
+ exports.runCliBootstrap = runCliBootstrap;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const observability_1 = require("./lib/observability");
42
+ const git_1 = require("./lib/git");
43
+ const consent_1 = require("./lib/analytics/consent");
44
+ const capture_1 = require("./lib/analytics/capture");
45
+ const http_1 = require("./lib/http");
46
+ const config_1 = require("./lib/config");
47
+ const workspace_1 = require("./lib/workspace");
48
+ const init_1 = require("./commands/init");
49
+ const login_1 = require("./commands/login");
50
+ const logout_1 = require("./commands/logout");
51
+ const uninstall_1 = require("./commands/uninstall");
52
+ const whoami_1 = require("./commands/whoami");
53
+ const rewire_1 = require("./commands/rewire");
54
+ const activate_1 = require("./commands/activate");
55
+ const review_1 = require("./commands/review");
56
+ const flush_1 = require("./commands/flush");
57
+ const queue_prune_1 = require("./commands/queue-prune");
58
+ const doctor_1 = require("./commands/doctor");
59
+ const internal_finalize_1 = require("./commands/internal-finalize");
60
+ const internal_active_review_1 = require("./commands/internal-active-review");
61
+ const internal_auto_index_1 = require("./commands/internal-auto-index");
62
+ const internal_evidence_inject_1 = require("./commands/internal-evidence-inject");
63
+ const internal_evidence_correlate_1 = require("./commands/internal-evidence-correlate");
64
+ const internal_evidence_hooks_1 = require("./commands/internal-evidence-hooks");
65
+ const internal_steer_sync_1 = require("./commands/internal-steer-sync");
66
+ const internal_capture_decisions_1 = require("./commands/internal-capture-decisions");
67
+ const internal_pretool_observe_1 = require("./commands/internal-pretool-observe");
68
+ const internal_turn_recap_1 = require("./commands/internal-turn-recap");
69
+ const internal_refresh_1 = require("./commands/internal-refresh");
70
+ const internal_session_nudge_1 = require("./commands/internal-session-nudge");
71
+ const update_notifier_1 = require("./lib/update-notifier");
72
+ const upgrade_apply_1 = require("./lib/upgrade-apply");
73
+ const wire_1 = require("./lib/wire");
74
+ const scan_context_1 = require("./commands/scan-context");
75
+ const kb_1 = require("./commands/kb");
76
+ const enrich_1 = require("./commands/enrich");
77
+ const graph_1 = require("./commands/graph");
78
+ const summary_1 = require("./commands/summary");
79
+ const label_1 = require("./commands/label");
80
+ const stats_1 = require("./commands/stats");
81
+ const turn_1 = require("./commands/turn");
82
+ const ask_1 = require("./commands/ask");
83
+ const session_1 = require("./commands/session");
84
+ const workspace_2 = require("./commands/workspace");
85
+ const debug_1 = require("./commands/debug");
86
+ const mcp_1 = require("./commands/mcp");
87
+ const mcp_supervisor_1 = require("./commands/mcp-supervisor");
88
+ const mcp_restart_1 = require("./lib/mcp-restart");
89
+ const context_1 = require("./commands/context");
90
+ const status_1 = require("./commands/status");
91
+ const evidence_1 = require("./commands/evidence");
92
+ const rules_1 = require("./commands/rules");
93
+ // `mla` dispatcher (§3 hour 6).
94
+ //
95
+ // Commands:
96
+ // mla init [flags]
97
+ // mla rewire [flags]
98
+ // mla activate [--name <name>] [--note <text>] [--here|--create|--repair] [--bootstrap <fast|agentic|full>]
99
+ // mla deactivate [--yes] [--from-root|--marker <path>]
100
+ // mla mute | mla unmute
101
+ // mla review [--plain] [--no-flush]
102
+ // mla review <id>
103
+ // mla flush [--all|--session <sid>] [--quiet] [--gc|--reap-only]
104
+ // mla doctor
105
+ // mla _internal finalize-session <sessionId>
106
+ // mla _internal auto-index [--session <sid>]
107
+ const USAGE = `mla: Meetless Agent CLI
108
+
109
+ usage:
110
+ mla init [--control-url <url>] [--control-token <token>] [--intel-url <url>]
111
+ [--actor <id>] [--no-post-tool-use] [--skill-only]
112
+ (machine setup + credential update. Defaults to logged-out (auth.mode
113
+ none): run 'mla login' next to sign in. Pass --control-token only for a
114
+ headless shared-key install. A tokenless re-run preserves a live login.
115
+ No workspace binding here; use 'mla activate' to bind a folder.)
116
+ mla rewire [--no-post-tool-use] [--no-install-flock] [--skill-only]
117
+ (idempotent re-wiring after binary upgrade; no token needed)
118
+ mla upgrade [--check] [--force]
119
+ (self-upgrade to the latest signed release: verifies the release
120
+ manifest's Ed25519 signature, enforces the downgrade guard, and
121
+ atomically swaps the binary (curl installs only; brew/npm are
122
+ redirected to their package manager). --check reports without
123
+ installing; --force allows a same-version or downgrade reinstall.)
124
+ mla login [--no-browser] [--console-url <url>] [--port <n>]
125
+ (browser login: opens the Console authorize page, captures a
126
+ user session into cli-config.json. --no-browser prints the URL
127
+ for SSH/headless and REQUIRES --port (the forwarded loopback
128
+ port). No-op when already logged in with >24h of refresh
129
+ runway; force re-login with 'mla logout && mla login'.)
130
+ mla logout
131
+ (revoke the current user session server-side and clear it from
132
+ cli-config.json (auth.mode -> none). A network failure still
133
+ clears locally; NEVER restores a prior shared key. No --all.)
134
+ mla uninstall [--dry-run] [--yes]
135
+ (remove the entire local Meetless footprint: ~/.meetless,
136
+ the Claude hook + MCP entries, and the /mla skill. Prints
137
+ how to remove the binary. Local only; server data and other
138
+ repos' .meetless.json markers are untouched.)
139
+ mla whoami
140
+ (print the identity behind the current cli-config.json: a
141
+ user session resolves live via the control /auth/me endpoint;
142
+ a shared key prints its mode without a network call. Exit 1
143
+ when not configured.)
144
+ mla activate [--name <name>] [--note <text>]
145
+ (provision-or-bind a workspace for this folder: no marker in
146
+ the tree provisions a new one named after the dir; a marker
147
+ present binds to it)
148
+ mla activate --here
149
+ (in-Git subdir override: bind/provision THIS subdir, shadowing
150
+ any parent marker via nearest-wins)
151
+ mla activate --create
152
+ (non-Git override: provision a workspace in a directory that
153
+ is not inside a Git repository)
154
+ mla activate --repair
155
+ (re-check the existing binding's membership + connectivity;
156
+ never mints a new id)
157
+ mla activate --bootstrap <fast|agentic|full>
158
+ (bootstrap tier for the activation preview: fast (default) shows
159
+ the deterministic review bundle; agentic ALSO emits a deep-read
160
+ scout mission to hand a coding agent; full adds the temporal
161
+ legacy-note graph (not built yet, falls back to agentic))
162
+ mla deactivate [--yes] [--from-root|--marker <path>]
163
+ (REMOVE this folder's workspace binding: deletes the nearest
164
+ .meetless.json. Confirms first (--yes to skip); from a subdir
165
+ it refuses to delete a parent marker unless --from-root or
166
+ --marker <path>. For per-session silencing use 'mla mute'.)
167
+ mla mute
168
+ (per-session: silence capture + Push for the CURRENT Claude
169
+ Code session only; does not touch .meetless.json)
170
+ mla unmute
171
+ (per-session: re-enable capture for the CURRENT session;
172
+ does not touch .meetless.json)
173
+ mla workspace [show]
174
+ (print the workspace bound to this folder + its health)
175
+ mla review [--plain] [--no-flush]
176
+ mla review <id>
177
+ mla session show [sessionId] [--json] [--last <N>]
178
+ mla session reconcile [--dry-run] [--json]
179
+ (archive sessions whose Claude Code transcript was deleted
180
+ on disk; reversible, fail-safe, skips anything uncertain)
181
+ mla ask "<query>" [--mode answer|search|canonical|compare] [--workspace <id>]
182
+ [--as-of <date>] [--max <n>] [--min <n>] [--plain]
183
+ (--as-of YYYY-MM-DD answers point-in-time: relations not yet
184
+ valid at that instant are excluded. The validity axis is
185
+ SEPARATE from posture/relationship; see \`mla kb help\`.)
186
+ mla mcp
187
+ (start the Meetless MCP server over stdio, authenticated as
188
+ the logged-in human (cli-config user-token) and scoped to
189
+ the marker workspace. No service key, no MEETLESS_WORKSPACE_ID
190
+ pin. Wire it into an MCP client's config as the command.)
191
+ mla kb summary [--json]
192
+ mla kb dump [--markdown] [--json]
193
+ mla kb add <path> --mode file|corpus --provenance <kind>
194
+ [--workspace <id>] [--profile <p>] [--glob <g>]
195
+ [--vault-root <dir>] [--ingest-run-id <id>]
196
+ [--queue] [--open]
197
+ (<kind>: human_authored | agent_distilled | tool_emitted |
198
+ external_imported | external_scraped. --provenance is now
199
+ ADVISORY: the server derives trust from the capture path, so
200
+ every ingest is born PENDING (reviewOutcome=PENDING) and is
201
+ readable but not yet trusted for knowledge-use until accepted
202
+ via \`kb accept\` / Console review. Trust (reviewOutcome) is a
203
+ SEPARATE axis from relationship review (\`kb pending\`/\`kb
204
+ review\`). See \`mla kb help\`.)
205
+ mla kb show <kbdoc:<id>|note:<path>|<path>>
206
+ [--workspace <id>] [--posture both|LIVE|SHADOW] [--as-of <date>]
207
+ [--include-tombstoned] [--all] [--audit-all] [--json]
208
+ [--open]
209
+ (--as-of YYYY-MM-DD renders the doc as of that instant:
210
+ relations not yet valid then, or on an untrusted clock, are
211
+ excluded. Same validity axis as \`mla ask --as-of\`. Each
212
+ promoted relation also prints its valid-time window and
213
+ whether its clock is trusted.)
214
+ mla kb reingest <kbdoc:<id>|note:<path>|<path>>
215
+ [--workspace <id>] [--path <new-path>] [--profile <p>]
216
+ [--ingest-run-id <id>] [--reason <s>]
217
+ mla kb forget <kbdoc:<id>|note:<path>|<path>>
218
+ [--workspace <id>] [--reason <s>]
219
+ mla kb purge <kbdoc:<id>|note:<path>|<path>> --reason <s>
220
+ [--workspace <id>] [--force]
221
+ mla kb move <kbdoc:<id>|note:<path>|<path>> <new-path>
222
+ [--workspace <id>] [--reason <s>] [--allow-file-missing]
223
+ mla kb retime <source-item-id> --effective-date <date>
224
+ [--reason <s>] [--anchor-type <t>] [--json]
225
+ (correct the source item's effective date and regenerate its
226
+ derived relations via the Phase 4 correction path. Edits the
227
+ SOURCE ITEM, not a relation: an accepted relation is never
228
+ edited in place nor deleted. The corrected date re-drives
229
+ valid-time, the same axis \`mla kb show --as-of\` filters on.)
230
+ mla kb pending [--doc <id>] [--json]
231
+ (list PENDING_REVIEW relationship candidates to decide on;
232
+ canonical home for this is now \`mla graph pending\`)
233
+ mla kb review <candidate-id> --accept | --reject [--note <text>] [--agent]
234
+ (record a verdict; --accept is human-only, an agent proxy
235
+ may --reject only mechanically-invalid candidates;
236
+ canonical home for this is now \`mla graph review\`)
237
+ mla kb promote <doc-id> | mla kb promote --reject <doc-id>
238
+ (flip a SHADOW Personal-KB doc to LIVE so the workspace grounds
239
+ on it; --reject declines and leaves it SHADOW)
240
+ mla kb personal list | mla kb personal show <id>
241
+ (this actor's own SHADOW Personal-KB docs)
242
+ mla kb help
243
+ (full KB catalog + the posture-vs-relationship-review model)
244
+ mla graph review [scope] [--json] | mla graph review <id> --accept|--reject
245
+ mla graph pending [scope]
246
+ mla graph help (alias: mla cg)
247
+ (the coordination graph: relationship review (typed edges
248
+ SUPERSEDES / CONTRADICTS / REFINES / REFERENCES between docs).
249
+ Same handlers as \`mla kb review\`/\`kb pending\`, given the
250
+ relationship axis its own home so it stops hiding under the
251
+ storage noun \`kb\`. Document ingestion + grounding (posture)
252
+ stay under \`mla kb\`; doc verbs typed here redirect there.)
253
+ mla summary [--last <n>] [--json] [--all]
254
+ (defaults to the current session; --all for every session)
255
+ mla label [<trace_id>] [--useful] [--noisy] [--harmful]
256
+ [--prevented-mistake] [--note <text>]
257
+ (mark an enrichment's operator_label; no trace_id labels the
258
+ latest trace in the current session)
259
+ mla stats [evidence] [--window <Nd>] [--json] [--verbose] [--global]
260
+ (usefulness-first dashboard from local events.jsonl: evidence
261
+ followthrough, contradictions caught, coverage gaps. default
262
+ window 30d. \`evidence\` is the focused adoption join below.)
263
+ mla turn [N] [--session <sid>] [--json]
264
+ (per-turn assist recap: did mla run this turn and did it help?
265
+ no N recaps the latest completed turn of the current session;
266
+ N recaps turn N. The per-turn analog of \`mla stats\`; also
267
+ reachable as \`mla stats --turn [N]\`.)
268
+ mla adoption [--last <n>] [--window <w>] [--json] [--all]
269
+ (A1 evidence-followthrough: did the agent pull or cite the
270
+ evidence we injected? alias of \`mla stats evidence\`;
271
+ defaults to the current session)
272
+ mla flush [--all|--session <sid>] [--quiet] [--gc|--reap-only]
273
+ (--gc drains the spool(s) then reaps stale-session litter;
274
+ --reap-only reaps stale litter without draining)
275
+ mla queue prune [--yes] [--dry-run] [--no-flush] [--max-age-hours N] [--session SID]
276
+ (reclaim orphaned queue files from dead sessions; previews
277
+ unless --yes. Unlike flush --gc it also reclaims non-empty
278
+ stranded tails, flushing them best-effort first)
279
+ mla doctor
280
+ (health check; reports both lifecycles distinctly: workspace
281
+ binding (activated / not) and session capture (active / muted))
282
+ mla status
283
+ (show whether Meetless is active for this repo and print
284
+ scan-cache counts: confirmed rules injected, pending review
285
+ items, inventory)
286
+ mla context <accept|dismiss> <id> | mla context list
287
+ (accept or dismiss a stale-context review item; list shows all
288
+ pending items. Verdicts are local; a rescan runs immediately
289
+ so the next session's injected context reflects the change.)
290
+ mla context advisory
291
+ (list the untracked agent-memory rules the cold-start scan
292
+ discovered. These are machine_inferred and NEVER auto-injected;
293
+ they ride a review-only worklist until a human attests them in a
294
+ tracked instruction file. Read-only by design.)
295
+ mla debug bundle --trace-id <id> [--out <path>] [--no-backend]
296
+ [--include-prompts] [--include-diffs] [--yes|-y]
297
+ [--command <name>] [--run-id <id>] [--session-id <id>] [-q]
298
+ (write a local, inspectable .zip for a trace_id so you can
299
+ attach it to an issue by choice. Nothing uploads. Raw
300
+ payloads (prompts, bodies, diffs) are EXCLUDED by default;
301
+ the include flags require an interactive confirm or --yes.
302
+ Manifest-first + mandatory redaction report; offline-capable.
303
+ Default output: ~/.meetless/debug/<trace_id>.zip)
304
+ mla evidence ce0-export
305
+ mla evidence ce0-import-labels <file>
306
+ (the human-only CE0 evidence-consultation labeling workflow:
307
+ ce0-export writes the JSONL of deadline-claimed obligations
308
+ with the deterministic machine baseline; ce0-import-labels
309
+ reads a labeled file back and CAS-finalizes each obligation
310
+ with the human's terminal outcome. Local only, no egress.)
311
+ mla help
312
+ mla _internal finalize-session <sessionId>
313
+ mla _internal auto-index [--session <sid>]
314
+ (Zone 2: index this session's produced docs into the owner's
315
+ Personal KB as SHADOW; fired detached from the Stop hook)
316
+ mla _internal evidence-correlate
317
+ (close pending evidence-inject windows and append
318
+ mla_evidence_outcome; fired detached from the Stop hook)
319
+ mla _internal evidence-turn-open
320
+ (CE0 RECORD_ONLY: classify the turn's memory requirement and
321
+ open its obligation; fired from the UserPromptSubmit hook)
322
+ mla _internal evidence-capture
323
+ (CE0 RECORD_ONLY: record a governed-memory pull as a
324
+ ConsultationAttempt; fired from the PostToolUse hook)
325
+ mla _internal evidence-stop
326
+ (CE0 RECORD_ONLY: freeze the turn obligation's eligibility
327
+ boundary; fired from the Stop hook)
328
+ mla _internal steer-sync --session <sid>
329
+ (pull pending cross-session steers into the local cache and
330
+ mark the surfaced ones injected; invoked by flush.sh)
331
+ mla _internal capture-decisions --source <post_tool_use|stop_transcript_scan>
332
+ --session <id> [--transcript <path>] [--spool <path>]
333
+ (normalize AskUserQuestion Q&A into agent_decision_captured
334
+ spool events; post_tool_use reads the hook payload from
335
+ stdin, stop_transcript_scan scans the session transcript)
336
+ mla _internal pretool-observe
337
+ (observe-only PreToolUse hook entrypoint; reads the raw
338
+ PreToolUse payload from stdin, records a side-channel
339
+ observation, and always emits the empty {} pass-through body
340
+ so it can never change a permission decision)
341
+ mla _internal turn-recap [--session <sid>] [--turn <n>]
342
+ [--style footer|block|block-context] [--json] [--emit-langfuse]
343
+ (the machine-facing per-turn assist recap; shelled out by the
344
+ UserPromptSubmit hook (block-context injection) and stop.sh
345
+ (--emit-langfuse). Fail-soft: prints nothing and exits 0 on any
346
+ non-argv error so it can never disturb the hook.)
347
+ mla _internal refresh [--quiet] [--if-expiring-within <secs>]
348
+ (trigger the concurrency-safe user-token refresh and map the
349
+ outcome to a sysexits code (0 refreshed / 75 busy / 77 dead
350
+ refresh -> mla login / 64 wrong mode); shelled out by the
351
+ auth hooks to self-heal an expired access token.)
352
+ mla _internal session-nudge [--cwd <dir>]
353
+ (SessionStart hook helper: in a logged-in git repo that is
354
+ NOT activated, prints a one-line 'Meetless installed but
355
+ inactive here' additionalContext for Claude Code. Silent and
356
+ exits 0 otherwise. Reuses the same resolver as mla mcp.)
357
+ mla _internal update-check
358
+ (detached, throttled background version check; fetches the
359
+ latest release and caches it for the upgrade nag. Honors
360
+ MLA_NO_UPDATE_NOTIFIER; always exits 0.)
361
+ `;
362
+ // Build-stamped version string. dist/build-info.json is generated by
363
+ // scripts/gen-build-info.js as the second step of `pnpm build`, so the running
364
+ // binary reports the exact commit + build time it was compiled from. Under
365
+ // ts-node (dev) the file is absent; fall back to the bare package version.
366
+ // This is the antidote to the stale-dist footgun: `mla --version` no longer
367
+ // returns a frozen "0.1.0" that never moves across rebuilds.
368
+ function versionString() {
369
+ const pkg = require("../package.json");
370
+ const base = pkg.version ?? "0.0.0";
371
+ try {
372
+ const info = JSON.parse(fs.readFileSync(path.join(__dirname, "build-info.json"), "utf8"));
373
+ const dirty = info.dirty ? "-dirty" : "";
374
+ return `${base} (${info.sha ?? "unknown"}${dirty}, built ${info.builtAt ?? "?"})`;
375
+ }
376
+ catch {
377
+ return `${base} (dev build, no build-info.json)`;
378
+ }
379
+ }
380
+ async function dispatch(argv) {
381
+ const [cmd, sub, ...rest] = argv;
382
+ if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
383
+ console.log(USAGE);
384
+ return 0;
385
+ }
386
+ if (cmd === "--version" || cmd === "-v") {
387
+ console.log(versionString());
388
+ return 0;
389
+ }
390
+ switch (cmd) {
391
+ case "init":
392
+ return (0, init_1.runInit)(argv.slice(1));
393
+ case "rewire":
394
+ return (0, rewire_1.runRewire)(argv.slice(1));
395
+ case "login":
396
+ return (0, login_1.runLogin)(argv.slice(1));
397
+ case "logout":
398
+ return (0, logout_1.runLogout)(argv.slice(1));
399
+ case "uninstall":
400
+ return (0, uninstall_1.runUninstall)(argv.slice(1));
401
+ case "whoami":
402
+ return (0, whoami_1.runWhoami)(argv.slice(1));
403
+ case "activate":
404
+ return (0, activate_1.runActivate)(argv.slice(1));
405
+ case "deactivate":
406
+ return (0, activate_1.runDeactivate)(argv.slice(1));
407
+ case "mute":
408
+ return (0, activate_1.runMute)(argv.slice(1));
409
+ case "unmute":
410
+ return (0, activate_1.runUnmute)(argv.slice(1));
411
+ case "workspace":
412
+ return (0, workspace_2.runWorkspace)(argv.slice(1));
413
+ case "doctor":
414
+ return (0, doctor_1.runDoctor)(argv.slice(1));
415
+ case "status":
416
+ return (0, status_1.runStatus)(argv.slice(1));
417
+ case "context":
418
+ return (0, context_1.runContext)(argv.slice(1));
419
+ case "flush":
420
+ return (0, flush_1.runFlush)(argv.slice(1));
421
+ case "queue": {
422
+ if (sub === "prune")
423
+ return (0, queue_prune_1.runQueuePrune)(rest);
424
+ console.error(`Unknown queue subcommand: ${sub ?? "(none)"}\n\n${USAGE}`);
425
+ return 2;
426
+ }
427
+ case "rules": {
428
+ // `list` reads durable R0 observations in the active runtime scope; `activity` is the R2-LOCAL
429
+ // accountability projection (per LIVE rule: observed N, violated M, denied; proposal §2.6 / §3.7);
430
+ // `attest` mints the LIVE notes-location version from an observed snapshot (R1, proposal §10.2 /
431
+ // §2.4); `revoke` is the kill switch that disarms a LIVE rule so the enforce seam fails open;
432
+ // `publish` projects the LIVE attested set in the active scope into control so the console Rules
433
+ // page surfaces it (the local-store -> backend bridge, idempotent + reconcile-by-omission).
434
+ if (sub === "list")
435
+ return (0, rules_1.runRulesList)(rest);
436
+ if (sub === "activity")
437
+ return (0, rules_1.runRulesActivity)(rest);
438
+ if (sub === "attest")
439
+ return (0, rules_1.runRulesAttest)(rest);
440
+ if (sub === "revoke")
441
+ return (0, rules_1.runRulesRevoke)(rest);
442
+ if (sub === "publish")
443
+ return (0, rules_1.runRulesPublish)(rest);
444
+ console.error(`Unknown rules subcommand: ${sub ?? "(none)"}\n\n${USAGE}`);
445
+ return 2;
446
+ }
447
+ case "review": {
448
+ // `mla review` -> current session, no positional, only flags.
449
+ // `mla review <id>` -> deep-link emission, exactly one positional.
450
+ // Old `latest` / `by-session` are intentionally removed; surface a clear
451
+ // pointer instead of silently routing the operator to the wrong path.
452
+ if (sub === undefined || sub.startsWith("--")) {
453
+ return (0, review_1.runReview)(argv.slice(1));
454
+ }
455
+ if (sub === "latest") {
456
+ console.error("`mla review latest` was removed. Run `mla review` inside a Claude Code " +
457
+ "session, or open the queues at /relationships and /cases in the console.");
458
+ return 2;
459
+ }
460
+ if (sub === "by-session") {
461
+ console.error("`mla review by-session <sid>` was removed. The current session is the only " +
462
+ "session `mla review` will surface; open the console queues to browse others.");
463
+ return 2;
464
+ }
465
+ return (0, review_1.runReviewById)([sub, ...rest]);
466
+ }
467
+ case "cases": {
468
+ console.error("`mla cases` was removed. Open the cases queue in the console, or run " +
469
+ "`mla review <id>` to get a deep link for a specific case.");
470
+ return 2;
471
+ }
472
+ case "session": {
473
+ if (sub === "show")
474
+ return (0, session_1.runSessionShow)(rest);
475
+ if (sub === "reconcile")
476
+ return (0, session_1.runSessionReconcile)(rest);
477
+ // `distill` + `remember` were removed (dogfood scaffold; the learning
478
+ // loop captures agent output directly per turn). See
479
+ // notes/20260531-agent-review-retraction-and-pending-items-loop.md §2.
480
+ console.error(`Unknown session subcommand: ${sub ?? "(none)"}\n\n${USAGE}`);
481
+ return 2;
482
+ }
483
+ case "ask":
484
+ // `mla ask` loads @meetless/ask-core. ask-core is ESM-only, so it ships as
485
+ // a CJS bundle the binary loads via require() (scripts/bundle-esm.js);
486
+ // runAsk handles bundle-vs-source resolution. Works in the binary and from
487
+ // a source/npm install alike, so no binary gate here.
488
+ return (0, ask_1.runAsk)(argv.slice(1));
489
+ case "kb":
490
+ return (0, kb_1.runKb)(argv.slice(1));
491
+ // `mla enrich`: agent-orchestrated onboarding enrichment. `enrich plan` scans the
492
+ // repo into an immutable run record + prints the plan the agent reads; `enrich
493
+ // ingest` validates + persists the scouts' candidates born PENDING. The agent
494
+ // dispatches the read-only scouts in between. See commands/enrich.ts.
495
+ case "enrich":
496
+ return (0, enrich_1.runEnrich)(argv.slice(1));
497
+ // `mla graph` (alias `cg` = coordination graph) is the relationship axis's own
498
+ // home: `review`/`pending` route to the SAME handlers as `mla kb review`/`kb
499
+ // pending` (one implementation, two entry points). It exists so the coordination
500
+ // graph stops hiding under the storage noun `kb`. Document/posture verbs typed
501
+ // here are redirected back to `mla kb` rather than conflated. See commands/graph.ts.
502
+ case "graph":
503
+ case "cg":
504
+ return (0, graph_1.runGraph)(argv.slice(1));
505
+ case "summary":
506
+ return (0, summary_1.runSummary)(argv.slice(1));
507
+ case "label":
508
+ return (0, label_1.runLabel)(argv.slice(1));
509
+ case "stats":
510
+ return (0, stats_1.runStats)(argv.slice(1));
511
+ // `mla turn [N]` is the per-turn analog of `mla stats`; `mla stats --turn`
512
+ // routes to the SAME runTurn handler (one implementation, two entry points).
513
+ case "turn":
514
+ return (0, turn_1.runTurn)(argv.slice(1));
515
+ // `mla adoption` is an alias for `mla stats evidence` (INV-ADOPTION-SOURCE-1):
516
+ // both route through the same runStats -> runAdoption code path, so the two
517
+ // entry points are byte-identical, not two implementations.
518
+ case "adoption":
519
+ return (0, stats_1.runStats)(["evidence", ...argv.slice(1)]);
520
+ case "debug":
521
+ return (0, debug_1.runDebug)(argv.slice(1));
522
+ // `mla evidence` is the one human-only CE0 evidence-consultation labeling workflow
523
+ // (notes/20260617-evidence-consultation-forcing-function-proposal.md §2.3): ce0-export writes
524
+ // the JSONL a labeler audits, ce0-import-labels reads it back and CAS-finalizes. Local only.
525
+ case "evidence":
526
+ return (0, evidence_1.runEvidence)(argv.slice(1));
527
+ // `mla mcp` boots the Meetless MCP server over stdio, authenticated as the
528
+ // logged-in human (cli-config user-token) and scoped to the marker
529
+ // workspace. Replaces the old standalone `meetless-mcp` service-key bin.
530
+ //
531
+ // Self-heal split (lib/mcp-restart.ts): a bare `mla mcp` runs the thin
532
+ // supervising parent, which respawns a `mla mcp --child` worker whenever a
533
+ // newer build lands on disk, so the long-lived daemon stops serving stale
534
+ // code (the "This operation was aborted" footgun) without an editor restart.
535
+ // The child (and the MEETLESS_MCP_SUPERVISOR=0 kill switch) run the worker
536
+ // directly.
537
+ case "mcp":
538
+ // @meetless/mcp is ESM-only and ships as a CJS bundle the binary loads via
539
+ // require() (scripts/bundle-esm.js); runMcp/loadAndServe handle
540
+ // bundle-vs-source resolution. Works in the binary and from a source/npm
541
+ // install alike, so no binary gate here.
542
+ return (0, mcp_restart_1.shouldSuperviseMcp)(argv.slice(1), process.env)
543
+ ? (0, mcp_supervisor_1.runMcpSupervisor)(argv.slice(1))
544
+ : (0, mcp_1.runMcp)(argv.slice(1));
545
+ // `mla upgrade` [--check] [--force]: explicit, foreground self-upgrade. Fetches
546
+ // and Ed25519-verifies the signed release manifest, enforces the downgrade
547
+ // guard, and atomically swaps the binary in place (curl installs only; brew/
548
+ // npm/unknown are redirected to their package manager). The silent background
549
+ // path (stage + apply-on-launch) is separate; this is the user-driven command.
550
+ case "upgrade":
551
+ return (0, upgrade_apply_1.runUpgrade)({ argv: argv.slice(1) });
552
+ case "_internal": {
553
+ if (sub === "finalize-session")
554
+ return (0, internal_finalize_1.runInternalFinalize)(rest);
555
+ if (sub === "active-review")
556
+ return (0, internal_active_review_1.runInternalActiveReview)(rest);
557
+ if (sub === "auto-index")
558
+ return (0, internal_auto_index_1.runInternalAutoIndex)(rest);
559
+ if (sub === "evidence-inject")
560
+ return (0, internal_evidence_inject_1.runInternalEvidenceInject)(rest);
561
+ if (sub === "evidence-correlate")
562
+ return (0, internal_evidence_correlate_1.runInternalEvidenceCorrelate)(rest);
563
+ if (sub === "evidence-turn-open")
564
+ return (0, internal_evidence_hooks_1.runInternalEvidenceTurnOpen)(rest);
565
+ if (sub === "evidence-capture")
566
+ return (0, internal_evidence_hooks_1.runInternalEvidenceCapture)(rest);
567
+ if (sub === "evidence-stop")
568
+ return (0, internal_evidence_hooks_1.runInternalEvidenceStop)(rest);
569
+ if (sub === "steer-sync")
570
+ return (0, internal_steer_sync_1.runInternalSteerSync)(rest);
571
+ if (sub === "capture-decisions")
572
+ return (0, internal_capture_decisions_1.runCaptureDecisions)(rest);
573
+ if (sub === "pretool-observe")
574
+ return (0, internal_pretool_observe_1.runInternalPretoolObserve)(rest);
575
+ if (sub === "turn-recap")
576
+ return (0, internal_turn_recap_1.runInternalTurnRecap)(rest);
577
+ if (sub === "refresh")
578
+ return (0, internal_refresh_1.runInternalRefresh)(rest);
579
+ if (sub === "session-nudge")
580
+ return (0, internal_session_nudge_1.runInternalSessionNudge)(rest);
581
+ if (sub === "update-check")
582
+ return (0, update_notifier_1.runInternalUpdateCheck)();
583
+ if (sub === "scan-context")
584
+ return (0, scan_context_1.runScanContext)(rest);
585
+ console.error(`Unknown _internal subcommand: ${sub ?? "(none)"}`);
586
+ return 2;
587
+ }
588
+ default:
589
+ console.error(`Unknown command: ${cmd}\n\n${USAGE}`);
590
+ return 2;
591
+ }
592
+ }
593
+ // Observability bootstrap: Sentry init MUST run BEFORE any other work so
594
+ // bootstrap failures (config load, http first-hop) still surface as alerts.
595
+ // trace_id is minted once per invocation and threaded through every outbound
596
+ // HTTP request via lib/http.ts (X-Trace-ID header). It is IMMUTABLE for the
597
+ // run; mlaFetch never reads response X-Trace-ID back. See spec §4.
598
+ //
599
+ // Spine note (notes/20260530-mla-observability-diagnostic-spine.md):
600
+ // - Canonical trace_id is 32 hex chars (OTel-native), NOT UUIDv4. This
601
+ // matches intel's RequestContext.langfuse_trace_id format and avoids any
602
+ // translation across Sentry/Langfuse/X-Trace-ID planes.
603
+ // - P2 lifecycle: one root span per command (`mla.<cmd>.<sub>`), one child
604
+ // span per outbound HTTP call (wired in lib/http.ts), root carries
605
+ // redacted argv + exit code, deep link printed only when trace landed.
606
+ // Read CliConfig if present; return null otherwise. Used by the lifecycle
607
+ // wrapper to know whether the run has any control hop at all (`mla init`,
608
+ // `mla --help`, `mla doctor` on a fresh box have no config). When null, the
609
+ // run uses a no-op tracer and skips the workspace/me prefetch.
610
+ function tryReadConfig() {
611
+ try {
612
+ return (0, config_1.readConfig)();
613
+ }
614
+ catch {
615
+ return null;
616
+ }
617
+ }
618
+ // Best-effort GET /internal/v1/workspaces/me. Hydrates the run-local workspace
619
+ // config so workspaceSentryAllowed + the Langfuse deep-link gate have real
620
+ // data.
621
+ //
622
+ // If a workspace config is already preset (test fixtures, future programmatic
623
+ // callers), we DO NOT touch it: the existing value is treated as authoritative
624
+ // and we skip the network hop entirely. On a fresh run with no preset, success
625
+ // stores the config; failure (control down, bad token, 404) is a silent no-op
626
+ // so the run continues with sentryEnabled=false + no deep link.
627
+ async function prefetchWorkspaceConfig(cfg, workspaceId) {
628
+ if ((0, observability_1.getWorkspaceConfig)())
629
+ return;
630
+ try {
631
+ const data = await (0, http_1.get)(cfg, `/internal/v1/workspaces/me?workspaceId=${encodeURIComponent(workspaceId)}`, 4000);
632
+ (0, observability_1.setWorkspaceConfig)(data);
633
+ }
634
+ catch {
635
+ // Intentional no-op.
636
+ }
637
+ }
638
+ // Testable orchestration: mints trace_id, hydrates workspace config, opens the
639
+ // root span, runs dispatch, captures non-zero / throw signals, ends the root,
640
+ // flushes the trace, prints the Langfuse deep link only when the trace likely
641
+ // landed. The real require.main entrypoint wraps this and calls process.exit.
642
+ async function runCliBootstrap(argv) {
643
+ // Apply-on-launch (D3), FIRST thing of all: if the background check has staged
644
+ // a verified newer binary and auto-apply is on (curl installs only), promote it
645
+ // with a cheap local swap and re-exec this exact command on the new binary. The
646
+ // re-exec'd child carries MLA_UPGRADE_REEXECED=1 so it skips this block (loop
647
+ // guard). Runs before the trace/analytics machinery so a promoted run is not
648
+ // double-counted. Best-effort and fail-open: any failure leaves the current
649
+ // binary running. The `_internal`, `upgrade`, and `mcp` commands are carved out
650
+ // inside maybePromoteStagedAndReExec so the check child, explicit upgrades, and
651
+ // the long-lived MCP daemon (which self-heals a stale dist in-band) never
652
+ // self-promote underneath themselves.
653
+ const promote = await (0, upgrade_apply_1.maybePromoteStagedAndReExec)({ command: argv[0], env: process.env });
654
+ if (promote.reExeced)
655
+ return promote.code ?? 0;
656
+ // Hook auto-resync, the SECOND thing of all: the installed hooks under
657
+ // ~/.meetless/hooks are a copy of this binary's templates, and only `mla
658
+ // rewire` refreshes them, so any binary upgrade (curl/brew/npm/manual) leaves
659
+ // the live hooks lagging the new code until the operator re-rewires. This
660
+ // self-heals that the moment a new binary runs: a cheap stamp read short-
661
+ // circuits the steady state, and on a build-id change it re-copies only the
662
+ // drifted, already-installed hooks (never adds new hooks or touches
663
+ // settings.json -- those still need an explicit rewire). Best-effort and
664
+ // fail-open: it never throws and never changes the exit code. Runs for every
665
+ // command (including the hook-invoked `_internal` calls, which is exactly how
666
+ // a fresh binary first heals mid-session) since it is idempotent and gated on
667
+ // the stamp. See notes/20260626-hook-auto-resync.md.
668
+ (0, wire_1.maybeResyncHooks)();
669
+ // Wall-clock at the very top: duration_ms for the mla_command journey event is
670
+ // measured from here to finalize, and the sequence idle-gap uses this as the
671
+ // command's start time (spec section 6.2). Captured before any I/O so it
672
+ // reflects the user-perceived command duration.
673
+ const startedAtMs = Date.now();
674
+ const traceId = (0, observability_1.mintTraceId)();
675
+ (0, observability_1.setRunTraceId)(traceId);
676
+ // run_id (INV-RUN-1): the analytics invocation key, minted independently from
677
+ // trace_id (never derived from it). 1:1 with trace_id at the CLI in v1, but a
678
+ // distinct identity so hooks/MCP/child-traces can later mint their own run_id
679
+ // under a shared trace. Every analytics event this run emits reads it back via
680
+ // getRunId().
681
+ (0, observability_1.setRunId)((0, observability_1.mintRunId)());
682
+ // Repo fingerprint (T1.10): a one-way hash of the repo identity for analytics
683
+ // attribution, computed ONCE here (it shells out to git) and stashed in a
684
+ // run-local singleton that every event reads back via getRepoFingerprint().
685
+ // Null outside a git repo; never a raw path (INV-POSTHOG-PII-1).
686
+ (0, observability_1.setRepoFingerprint)((0, git_1.computeRepoFingerprint)());
687
+ // Agent session capture (Channel A substrate): the raw Claude session UUID,
688
+ // canonicalized ONCE here so every intel call this run stamps the same
689
+ // X-Agent-Session-ID and intel composes the workspace-namespaced Langfuse
690
+ // Session a single time. Null when not inside a Claude session or the env value
691
+ // is malformed; the header is then simply omitted. The raw UUID is never
692
+ // composed CLI-side (INV-COMPOSE-ONCE).
693
+ (0, observability_1.setRunSessionId)((0, observability_1.canonicalizeSessionId)(process.env.CLAUDE_CODE_SESSION_ID ?? null));
694
+ const [cmd, sub] = argv;
695
+ const cmdName = cmd ?? "(none)";
696
+ const subName = sub ?? null;
697
+ const cfg = tryReadConfig();
698
+ // Folder = workspace (T1.1): the trace workspace comes from the nearest
699
+ // `.meetless.json` marker, never cli-config. This bootstrap runs for EVERY
700
+ // command (including non-workspace ones like `mla init` from an unbound dir),
701
+ // so resolution is best-effort: no marker -> no workspace attribution, and the
702
+ // trace prefetch + flush are simply skipped rather than throwing.
703
+ const workspaceId = cfg ? (0, workspace_1.tryResolveWorkspaceId)() : null;
704
+ if (cfg && workspaceId) {
705
+ await prefetchWorkspaceConfig(cfg, workspaceId);
706
+ }
707
+ const buildInfo = (0, observability_1.loadBuildInfo)();
708
+ // Update notifier (I5): kick off a detached, throttled background version check
709
+ // BEFORE dispatch so it overlaps the command and the parent never waits. The
710
+ // nag itself is printed at the end of the run from whatever the LAST completed
711
+ // check cached. Both halves are best-effort and can never change the exit code.
712
+ (0, update_notifier_1.maybeSpawnBackgroundCheck)({ command: cmdName, env: process.env, now: startedAtMs });
713
+ // Content sub-kill: a null flushFn yields a no-op tracer (createRunTracer), so
714
+ // when trace upload is off the trace plane never POSTs a span batch to control.
715
+ // Gated on traceUploadEnabled() (master kill OR the MEETLESS_TRACE_UPLOAD content
716
+ // sub-kill), the SAME gate as initSentry below, because agent-trace spans are
717
+ // content-bearing (spec section 9). Spans are still built in-process (cheap, never
718
+ // leave the machine).
719
+ const flushFn = cfg && workspaceId && (0, consent_1.traceUploadEnabled)()
720
+ ? (0, observability_1.makeHttpFlush)({
721
+ controlUrl: cfg.controlUrl,
722
+ controlToken: cfg.controlToken,
723
+ workspaceId,
724
+ actorUserId: cfg.actorUserId,
725
+ })
726
+ : null;
727
+ const tracer = (0, observability_1.createRunTracer)({
728
+ traceId,
729
+ rootName: `mla.${cmdName}.${subName ?? "none"}`,
730
+ buildInfo,
731
+ flushFn,
732
+ });
733
+ // Stamp the redacted argv on the root span before dispatch. Doing it here
734
+ // (not inside dispatch) keeps the attribute on the root regardless of which
735
+ // command runs, and the redactor strips any token-shaped flag values that a
736
+ // user pasted on the command line.
737
+ tracer.root.setAttribute("argv", (0, observability_1.redactArgvForSpan)(argv));
738
+ (0, observability_1.setRunTracer)(tracer);
739
+ let code = 1;
740
+ let threw = false;
741
+ let thrown = null;
742
+ try {
743
+ code = await dispatch(argv);
744
+ if (code !== 0) {
745
+ (0, observability_1.captureCliNonZeroExit)({
746
+ traceId,
747
+ command: cmdName,
748
+ sub: subName,
749
+ exitCode: code,
750
+ });
751
+ }
752
+ }
753
+ catch (err) {
754
+ threw = true;
755
+ thrown = err;
756
+ const e = err;
757
+ if (e.status) {
758
+ console.error(`HTTP ${e.status}: ${e.message}`);
759
+ }
760
+ else {
761
+ console.error(e.message || String(err));
762
+ }
763
+ (0, observability_1.captureCliError)(err, { traceId, command: cmdName, sub: subName });
764
+ code = 1;
765
+ }
766
+ tracer.endRoot(threw
767
+ ? { status: "error", output: { exitCode: code }, error: thrown }
768
+ : { status: code === 0 ? "ok" : "error", output: { exitCode: code } });
769
+ tracer.root.setAttribute("exit_code", code);
770
+ await (0, observability_1.boundedTraceFlush)(tracer);
771
+ (0, observability_1.setRunTracer)(null);
772
+ // mla_command journey event (spec section 6.2, section 11.4). Recorded after the
773
+ // result is known: a normalized command/subcommand/flags-shape (never raw argv),
774
+ // the closed-enum outcome, the run's sequence fields, and timing. Local-first and
775
+ // fully best-effort: captureCommandEvent swallows every failure so analytics can
776
+ // never change the exit code below. sessionId is the ambient Claude Code session
777
+ // the same way `mla review`/`mla summary` bind it.
778
+ await (0, capture_1.captureCommandEvent)({
779
+ argv,
780
+ exitCode: code,
781
+ threw,
782
+ thrown,
783
+ workspaceId,
784
+ sessionId: (process.env.CLAUDE_CODE_SESSION_ID || "").trim() || null,
785
+ actorUserId: cfg?.actorUserId ?? null,
786
+ mlaVersion: buildInfo.version,
787
+ gitSha: buildInfo.sha,
788
+ startedAtMs,
789
+ nowMs: Date.now(),
790
+ cfg: cfg ?? null,
791
+ });
792
+ // Deep link: print iff tracing.enabled === true AND langfuseProjectId set
793
+ // AND (flush succeeded OR intel echoed the inbound X-Trace-ID). The gate is
794
+ // checked inside maybePrintDeepLink; a no-op tracer + missing workspace
795
+ // config always falls through silently.
796
+ (0, observability_1.maybePrintDeepLink)({
797
+ traceId,
798
+ config: (0, observability_1.getWorkspaceConfig)(),
799
+ flushSucceeded: (0, observability_1.didTraceFlushSucceed)(),
800
+ intelEchoed: (0, observability_1.didIntelEchoTraceId)(),
801
+ });
802
+ // Update notifier (I5): print the install-method-aware upgrade nag last, so it
803
+ // is the final thing the user sees. Reads only the cache; gated on TTY, off CI,
804
+ // and MLA_NO_UPDATE_NOTIFIER. Never affects `code`.
805
+ (0, update_notifier_1.maybeShowUpdateNag)({ currentVersion: buildInfo.version, env: process.env });
806
+ return code;
807
+ }
808
+ if (require.main === module) {
809
+ const buildInfo = (0, observability_1.loadBuildInfo)();
810
+ // Sentry is the content-bearing error plane, so it is gated on the trace-upload
811
+ // posture (opt-out, master-kill-aware), not just the bare telemetry kill switch.
812
+ // initSentry itself also refuses when telemetryDisabled(); this is the explicit
813
+ // content sub-kill in front of it (INV-CONSENT-1).
814
+ if ((0, consent_1.traceUploadEnabled)()) {
815
+ (0, observability_1.initSentry)(buildInfo);
816
+ }
817
+ const argv = process.argv.slice(2);
818
+ runCliBootstrap(argv)
819
+ .then(async (code) => {
820
+ await (0, observability_1.boundedSentryFlush)();
821
+ process.exit(code);
822
+ })
823
+ .catch(async (err) => {
824
+ console.error(err?.message || String(err));
825
+ await (0, observability_1.boundedSentryFlush)();
826
+ process.exit(1);
827
+ });
828
+ }