@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,184 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseArgs = parseArgs;
4
+ exports.runFlush = runFlush;
5
+ const spool_1 = require("../lib/spool");
6
+ const config_1 = require("../lib/config");
7
+ // Strict argv parsing for `mla flush` (Wedge v6 Epoch 48).
8
+ //
9
+ // The old parser had a genuinely dangerous silent-drop trap and a dead
10
+ // flag:
11
+ //
12
+ // 1. `--session` / `-s` with no following value silently bound
13
+ // `out.session = undefined`. Downstream, `flags.session ? [...] :
14
+ // listActiveSessions()` then treated undefined as falsy and
15
+ // drained EVERY pending session in the queue. The operator's
16
+ // intent ("drain just this one") flipped to "drain everything"
17
+ // with no diagnostic. On a busy machine that is dozens to
18
+ // hundreds of sessions and minutes of un-bounded fan-out.
19
+ //
20
+ // 2. `--all` was a dead flag. The ternary collapsed to
21
+ // `flags.all ? listActiveSessions() : listActiveSessions()`,
22
+ // so `--all` and the default both did the same thing. Operators
23
+ // reading the help text reasonably inferred the default behaved
24
+ // differently.
25
+ //
26
+ // Strict rules below:
27
+ // - Unknown `--`-prefixed token throws with the supported set.
28
+ // - `--session`/`-s` MUST be followed by a non-`--` value; a missing
29
+ // or flag-shape value throws rather than silently widening to
30
+ // "drain everything".
31
+ // - Positional argument is still allowed as a shortcut for
32
+ // `--session <sid>`, but a second positional throws.
33
+ // - `--all` and `--session` are mutually exclusive (passing both
34
+ // throws, rather than silently letting `--session` win).
35
+ // - `--all` is preserved as an explicit synonym for the default
36
+ // (drain every active session) but it is no longer a no-op
37
+ // branch; the runFlush body uses the single resolved
38
+ // `listActiveSessions()` call.
39
+ // - `--gc` additionally runs the age-gated stale-session reaper
40
+ // (reapQueue) AFTER the drain, removing dead-session litter
41
+ // (`.lock`/`.turn`/`.repoPath`/`.gitBaseline` and 0-byte spools
42
+ // idle longer than MEETLESS_QUEUE_GC_MAX_AGE_SEC, default 24h). It
43
+ // NEVER touches a session with undelivered work, so it is safe to
44
+ // pair with the default drain. `--gc` is whole-queue, so it is
45
+ // mutually exclusive with `--session` (draining one session while
46
+ // reaping all is contradictory intent).
47
+ // - `--reap-only` runs the SAME reaper but SKIPS the drain loop
48
+ // entirely. This is the Stop-hook path: the session that just
49
+ // ended already self-flushes via spawn_flush, so the hook only
50
+ // needs the cheap age-gated litter sweep. Tail-calling `--gc`
51
+ // there would re-drain EVERY active session on every Stop -- an
52
+ // O(sessions) fan-out per Stop, the exact pile-up that left 99
53
+ // stranded `.lock` files. `--reap-only` is whole-queue and pure
54
+ // reap, so it is mutually exclusive with `--gc` (redundant),
55
+ // `--all`, `--session`, and a positional id (all drain selectors).
56
+ const KNOWN_FLAGS = new Set(["--all", "--session", "-s", "--quiet", "-q", "--gc", "--reap-only"]);
57
+ // `--reap-only` reaps without draining; combining it with any drain
58
+ // selector is contradictory intent. Centralized so every branch raises
59
+ // the same message.
60
+ const REAP_ONLY_CONFLICT = "--reap-only reaps without draining; it cannot be combined with --gc/--all/--session";
61
+ function parseArgs(argv) {
62
+ const out = {};
63
+ for (let i = 0; i < argv.length; i++) {
64
+ const a = argv[i];
65
+ if (a === "--reap-only") {
66
+ if (out.all || out.gc || out.session !== undefined) {
67
+ throw new Error(REAP_ONLY_CONFLICT);
68
+ }
69
+ out.reapOnly = true;
70
+ continue;
71
+ }
72
+ if (a === "--all") {
73
+ if (out.session !== undefined) {
74
+ throw new Error("--all and --session are mutually exclusive");
75
+ }
76
+ if (out.reapOnly) {
77
+ throw new Error(REAP_ONLY_CONFLICT);
78
+ }
79
+ out.all = true;
80
+ continue;
81
+ }
82
+ if (a === "--gc") {
83
+ if (out.session !== undefined) {
84
+ throw new Error("--gc and --session are mutually exclusive (--gc reaps the whole queue)");
85
+ }
86
+ if (out.reapOnly) {
87
+ throw new Error(REAP_ONLY_CONFLICT);
88
+ }
89
+ out.gc = true;
90
+ continue;
91
+ }
92
+ if (a === "--session" || a === "-s") {
93
+ if (out.all) {
94
+ throw new Error("--all and --session are mutually exclusive");
95
+ }
96
+ if (out.gc) {
97
+ throw new Error("--gc and --session are mutually exclusive (--gc reaps the whole queue)");
98
+ }
99
+ if (out.reapOnly) {
100
+ throw new Error(REAP_ONLY_CONFLICT);
101
+ }
102
+ const v = argv[i + 1];
103
+ if (v === undefined) {
104
+ throw new Error(`Missing value for ${a}`);
105
+ }
106
+ if (v.startsWith("--") || v.startsWith("-")) {
107
+ throw new Error(`Missing value for ${a} (got the next flag ${v} instead)`);
108
+ }
109
+ out.session = v;
110
+ i += 1;
111
+ continue;
112
+ }
113
+ if (a === "--quiet" || a === "-q") {
114
+ out.quiet = true;
115
+ continue;
116
+ }
117
+ if (a.startsWith("--") || a.startsWith("-")) {
118
+ if (!KNOWN_FLAGS.has(a)) {
119
+ throw new Error(`Unknown flag: ${a}. Supported flags: --all, --session/-s, --quiet/-q, --gc, --reap-only`);
120
+ }
121
+ // Should be unreachable; KNOWN_FLAGS aligns with the branches above.
122
+ throw new Error(`Unhandled known flag: ${a}`);
123
+ }
124
+ if (out.reapOnly) {
125
+ throw new Error(REAP_ONLY_CONFLICT);
126
+ }
127
+ if (out.all) {
128
+ throw new Error(`Unexpected positional argument: ${a}. --all already drains every session.`);
129
+ }
130
+ if (out.gc) {
131
+ throw new Error(`--gc and a per-session id are mutually exclusive (--gc reaps the whole queue).`);
132
+ }
133
+ if (out.session !== undefined) {
134
+ throw new Error(`Unexpected extra positional argument: ${a}. \`mla flush\` accepts at most one session id.`);
135
+ }
136
+ out.session = a;
137
+ }
138
+ return out;
139
+ }
140
+ async function runFlush(argv, opts = {}) {
141
+ const flags = parseArgs(argv);
142
+ const hookDir = opts.hookDir ?? config_1.HOOKS_DIR;
143
+ const quiet = opts.quiet ?? flags.quiet;
144
+ let bad = 0;
145
+ // --reap-only skips the drain loop entirely (Stop-hook path). Everything
146
+ // else (`--all`, `--session`, the bare default) drains. `--all` and the bare
147
+ // default both mean "drain every active session"; the distinction is
148
+ // documentation-only. Collapse to a single resolved call so the dead-branch
149
+ // pattern that hid the missing-value trap cannot return.
150
+ if (!flags.reapOnly) {
151
+ const sessions = flags.session ? [flags.session] : (0, spool_1.listActiveSessions)();
152
+ if (sessions.length === 0) {
153
+ if (!quiet)
154
+ console.log("No sessions to flush.");
155
+ }
156
+ else {
157
+ for (const sid of sessions) {
158
+ const r = (0, spool_1.runFlushScript)(sid, hookDir);
159
+ if (!r.ok) {
160
+ bad += 1;
161
+ if (!quiet)
162
+ console.error(`[flush] ${sid} FAILED: ${r.stderr.slice(0, 200)}`);
163
+ }
164
+ else if (!quiet) {
165
+ console.log(`[flush] ${sid} ok`);
166
+ }
167
+ }
168
+ }
169
+ }
170
+ // --gc reaps dead-session litter AFTER the drain; --reap-only reaps WITHOUT
171
+ // draining. Drain-first (for --gc) is the conservative ordering -- a session
172
+ // that is still deliverable gets delivered (and self-cleaned by flush.sh's
173
+ // RC1 path) before the reaper looks at it, and reapQueue never touches a
174
+ // session with undelivered work regardless. Runs even when there was nothing
175
+ // to drain.
176
+ if (flags.gc || flags.reapOnly) {
177
+ const gc = (0, spool_1.reapQueue)();
178
+ if (!quiet) {
179
+ console.log(`[gc] reaped ${gc.reaped.length} stale session(s), removed ${gc.removedFiles} file(s)` +
180
+ ` (${gc.skippedPending} with pending work and ${gc.skippedFresh} still-fresh kept)`);
181
+ }
182
+ }
183
+ return bad > 0 ? 1 : 0;
184
+ }
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GRAPH_USAGE = void 0;
4
+ exports.runGraph = runGraph;
5
+ const kb_1 = require("./kb");
6
+ const kb_pending_1 = require("./kb_pending");
7
+ const kb_review_1 = require("./kb_review");
8
+ // `mla graph`: the coordination-graph (relationship) surface.
9
+ //
10
+ // notes/20260608-mla-ml-generalization-review.md, Q1. `mla kb` had grown to span
11
+ // two orthogonal axes:
12
+ // (a) document / posture: ingestion + grounding, LIVE vs SHADOW.
13
+ // (b) relationship / graph: typed edges between docs, decided via verdicts.
14
+ // Calling axis (b) "kb" buries the coordination graph (the product's substrate)
15
+ // under a storage noun. `mla graph` gives axis (b) its own home WITHOUT moving
16
+ // axis (a): `review`/`pending` route to the EXACT same handlers as
17
+ // `mla kb review`/`mla kb pending` (one implementation, two entry points), and the
18
+ // overload boundary + pending-alias semantics are imported from `./kb` so the two
19
+ // surfaces can never drift. `kb review`/`kb pending` stay as working back-compat.
20
+ //
21
+ // Deliberately NOT here: any document ingestion verb. The review's explicit trap
22
+ // is `graph add <file>` reading as "ingest"; that would re-blur the two axes the
23
+ // codebase fought to separate. Document/posture verbs typed under `graph` are
24
+ // redirected to `mla kb`, not silently rejected.
25
+ // The document/posture verbs that live under `mla kb`. Typing one of these under
26
+ // `graph` is an axis mismatch, not a typo, so each gets a pointed redirect rather
27
+ // than the generic unknown-subcommand catalog. `share` is the deprecated alias for
28
+ // `promote`; include it so the redirect fires for muscle-memory too.
29
+ const KB_DOC_POSTURE_VERBS = new Set([
30
+ "add",
31
+ "show",
32
+ "reingest",
33
+ "forget",
34
+ "purge",
35
+ "move",
36
+ "retime",
37
+ "promote",
38
+ "share",
39
+ "personal",
40
+ "summary",
41
+ "dump",
42
+ ]);
43
+ // The user-facing `mla graph` catalog. It teaches the one fact that keeps the two
44
+ // axes apart: reviewing an edge records how docs RELATE; it never changes whether a
45
+ // doc is grounded (that is posture, under `mla kb`). The graph + control-projection
46
+ // layers expose per-item reads as counts only today (their per-item read endpoints
47
+ // remain deferred), so the catalog points at `mla kb summary` for graph counts
48
+ // rather than pretending a per-edge inspector exists. Keep "Usage" present: the
49
+ // unknown-subcommand path re-emits this block and a test locks that contract.
50
+ exports.GRAPH_USAGE = `mla graph: the coordination graph — relationship review (typed edges between docs).
51
+
52
+ The graph axis decides how docs RELATE: SUPERSEDES / CONTRADICTS / REFINES /
53
+ REFERENCES. It is independent of the document/posture axis (ingestion + grounding,
54
+ LIVE vs SHADOW), which lives under \`mla kb\`. Reviewing an edge records how two docs
55
+ relate; it NEVER changes whether a doc is grounded.
56
+
57
+ Usage:
58
+ mla graph review list the queue (defaults to your current session)
59
+ mla graph review --all list the full workspace queue
60
+ mla graph review --session <sid|current|latest> list a specific session's candidates
61
+ mla graph review [scope] --json structured output (agent policy + scope)
62
+ mla graph review <candidate-id> --accept | --reject [--note <text>] [--agent]
63
+ record a verdict (--accept is human-only)
64
+ mla graph pending [scope] deprecated alias for \`graph review\` (list mode)
65
+
66
+ Related (the OTHER axis — document/posture, not relationships):
67
+ mla kb ... ingest, ground (posture LIVE/SHADOW), and curate documents
68
+ mla kb summary substrate counts (includes graph entities + knowledge_relations)`;
69
+ // Router for the relationship/graph axis. Mirrors `runKb`'s help + dispatch
70
+ // shape; `review`/`pending` delegate to the shared handlers, document/posture
71
+ // verbs are redirected, everything else re-emits the catalog with exit 2.
72
+ async function runGraph(argv) {
73
+ const sub = argv[0];
74
+ const rest = argv.slice(1);
75
+ // Help is workspace-free: full catalog to stdout, exit 0. Reached by
76
+ // `mla graph`, `mla graph help`, and `mla graph --help/-h`.
77
+ if (sub === undefined || sub === "help" || sub === "--help" || sub === "-h") {
78
+ console.log(exports.GRAPH_USAGE);
79
+ return 0;
80
+ }
81
+ switch (sub) {
82
+ case "review":
83
+ // Same overload boundary as `mla kb review`: a leading candidate id records
84
+ // a verdict; anything else (no args / leading flag) lists the queue.
85
+ return (0, kb_1.isReviewListInvocation)(rest) ? (0, kb_pending_1.runKbReviewList)(rest) : (0, kb_review_1.runKbReview)(rest);
86
+ case "pending":
87
+ // Deprecated alias for `review` (list mode); injects --all when no explicit
88
+ // scope so the historical workspace-wide default holds.
89
+ return (0, kb_pending_1.runKbReviewList)((0, kb_1.pendingAliasArgs)(rest));
90
+ }
91
+ // Axis mismatch: a document/posture verb typed under `graph`. Redirect to the
92
+ // surface that owns it instead of a generic "unknown subcommand" — this is the
93
+ // anti-conflation guardrail made executable.
94
+ if (KB_DOC_POSTURE_VERBS.has(sub)) {
95
+ console.error(`\`${sub}\` is a document/posture command (ingestion + grounding), not a ` +
96
+ `relationship (graph) command.\n` +
97
+ `Documents are ingested and grounded under \`mla kb\`. Run: mla kb ${sub} ...\n\n` +
98
+ `\`mla graph\` only reviews how docs RELATE. See \`mla graph help\`.`);
99
+ return 2;
100
+ }
101
+ console.error(`unknown \`mla graph\` subcommand: ${sub}\n`);
102
+ console.error(exports.GRAPH_USAGE);
103
+ return 2;
104
+ }
@@ -0,0 +1,272 @@
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.parseInitArgs = parseInitArgs;
37
+ exports.buildInitConfig = buildInitConfig;
38
+ exports.runInit = runInit;
39
+ const fs = __importStar(require("fs"));
40
+ const config_1 = require("../lib/config");
41
+ const wire_1 = require("../lib/wire");
42
+ // Strict argv parsing for `mla init` (Wedge v6 Epoch 54).
43
+ //
44
+ // The old parser used `const next = () => argv[++i]` and switched on
45
+ // the flag name. That shape had three real silent-drop classes, the
46
+ // first one is genuinely dangerous because it writes a corrupt
47
+ // 0o600-mode config that breaks every subsequent CLI call:
48
+ //
49
+ // 1. `mla init --control-token --intel-url http://x` bound
50
+ // controlToken = "--intel-url" (next() ate the next flag) and
51
+ // then "http://x" fell through the switch's `default` branch
52
+ // (positional, no `--` prefix) and was silently dropped. The
53
+ // operator's intent ("set token AND intel url") flipped to "set
54
+ // token to the string '--intel-url'", and the config was written
55
+ // at 0o600 perms with a wrong token. Every downstream `mla` call
56
+ // then 401'd with no obvious cause. (The trap applies to any value
57
+ // flag; `--workspace-id` was the original example before T3.1
58
+ // removed that flag.)
59
+ //
60
+ // 2. `mla init -x` (any short flag) hit the `default` branch's
61
+ // `if (a.startsWith("--"))` guard which is `--` only -- so `-x`
62
+ // was silently dropped with no diagnostic.
63
+ //
64
+ // 3. `mla init some_positional --control-token T` silently dropped
65
+ // the positional. No `mla init` flow takes positionals.
66
+ //
67
+ // Strict rules below:
68
+ // - Unknown `--`-prefixed or `-`-prefixed token throws with the
69
+ // supported set.
70
+ // - Value flags MUST be followed by a non-`--`/`-` value; missing
71
+ // or flag-shape value throws.
72
+ // - Positional arguments throw; `mla init` takes none.
73
+ const VALUE_FLAGS = new Set([
74
+ "--control-url",
75
+ "--control-token",
76
+ "--intel-url",
77
+ "--actor",
78
+ ]);
79
+ const BOOLEAN_FLAGS = new Set([
80
+ "--no-post-tool-use",
81
+ "--unsafe-capture-non-bash",
82
+ "--skill-only",
83
+ "--no-install-flock",
84
+ "--no-project-rules",
85
+ "--no-mcp",
86
+ ]);
87
+ function parseInitArgs(argv) {
88
+ const out = {};
89
+ for (let i = 0; i < argv.length; i++) {
90
+ const a = argv[i];
91
+ if (VALUE_FLAGS.has(a)) {
92
+ const v = argv[i + 1];
93
+ if (v === undefined) {
94
+ throw new Error(`Missing value for ${a}`);
95
+ }
96
+ if (v.startsWith("--") || v.startsWith("-")) {
97
+ throw new Error(`Missing value for ${a} (got the next flag ${v} instead)`);
98
+ }
99
+ if (a === "--control-url")
100
+ out.controlUrl = v;
101
+ else if (a === "--control-token")
102
+ out.controlToken = v;
103
+ else if (a === "--intel-url")
104
+ out.intelUrl = v;
105
+ else if (a === "--actor")
106
+ out.actorUserId = v;
107
+ i += 1;
108
+ continue;
109
+ }
110
+ if (BOOLEAN_FLAGS.has(a)) {
111
+ if (a === "--no-post-tool-use")
112
+ out.noPostToolUse = true;
113
+ else if (a === "--unsafe-capture-non-bash")
114
+ out.unsafeCaptureNonBash = true;
115
+ else if (a === "--skill-only")
116
+ out.skillOnly = true;
117
+ else if (a === "--no-install-flock")
118
+ out.noInstallFlock = true;
119
+ else if (a === "--no-project-rules")
120
+ out.noProjectRules = true;
121
+ else if (a === "--no-mcp")
122
+ out.noMcp = true;
123
+ continue;
124
+ }
125
+ if (a.startsWith("--") || a.startsWith("-")) {
126
+ throw new Error(`Unknown flag: ${a}. Supported flags: ${[...VALUE_FLAGS, ...BOOLEAN_FLAGS].sort().join(", ")}`);
127
+ }
128
+ throw new Error(`Unexpected positional argument: ${a}. \`mla init\` takes no positional arguments.`);
129
+ }
130
+ return out;
131
+ }
132
+ // Assemble the cli-config that `mla init` writes, inheriting unset fields from a
133
+ // prior config (idempotent re-run / token rotation). Pure (no I/O beyond
134
+ // resolveMlaPath reading argv) so the folder = workspace contract is unit-pinned
135
+ // in init-config-shape.spec.ts.
136
+ //
137
+ // Folder = workspace (T3.1): the assembled config carries NO `workspaceId`. The
138
+ // field is omitted from the literal entirely, so even a stale workspaceId on a
139
+ // pre-cutover `prior` is dropped rather than carried forward. The workspace
140
+ // binding lives only in the per-folder `.meetless.json` marker.
141
+ function buildInitConfig(flags, prior) {
142
+ // `mla init` is the SHARED-KEY bootstrap (scripted / CI / `--control-token`),
143
+ // never the browser-login path. So it only ever assembles a shared-key or a
144
+ // 'none' auth. The one exception is idempotence: a re-run while a browser
145
+ // session is live (prior.auth.mode === 'user-token') must PRESERVE that login
146
+ // rather than silently downgrade it to a shared key (which would also freeze a
147
+ // short-lived access token as if it were permanent). `mla login`/`mla logout`
148
+ // own the user-token lifecycle (§6.6).
149
+ let auth;
150
+ if (flags.controlToken) {
151
+ auth = { mode: "shared-key", accessToken: flags.controlToken };
152
+ }
153
+ else if (prior?.auth) {
154
+ // Preserve whatever was canonically on disk (none / shared-key / user-token).
155
+ auth = prior.auth;
156
+ }
157
+ else if (prior?.controlToken) {
158
+ // Legacy prior (pre-nested-auth) with only a top-level token: shared-key.
159
+ auth = { mode: "shared-key", accessToken: prior.controlToken };
160
+ }
161
+ else {
162
+ // Fresh init with no token: logged out until `mla login` or a later
163
+ // `mla init --control-token`.
164
+ auth = { mode: "none" };
165
+ }
166
+ // P3: under a preserved user session the actor is pinned to the authenticated
167
+ // user; otherwise it is the explicit flag or the inherited value.
168
+ const actorUserId = auth.mode === "user-token"
169
+ ? auth.user.id
170
+ : (flags.actorUserId ?? prior?.actorUserId);
171
+ return {
172
+ controlUrl: flags.controlUrl ?? prior?.controlUrl ?? config_1.DEFAULT_CONTROL_URL,
173
+ // Derived projection of auth (= accessToken, "" for none). Never persisted.
174
+ controlToken: auth.mode === "none" ? "" : auth.accessToken,
175
+ intelUrl: flags.intelUrl ?? prior?.intelUrl ?? config_1.DEFAULT_INTEL_URL,
176
+ mlaPath: (0, wire_1.resolveMlaPath)(),
177
+ intelRoot: prior?.intelRoot,
178
+ consoleUrl: prior?.consoleUrl,
179
+ actorUserId,
180
+ auth,
181
+ };
182
+ }
183
+ // Human-readable one-liner for the auth state a fresh/updated init just wrote,
184
+ // shown in the init summary. `none` is the DEFAULT (no --control-token): the
185
+ // machine is wired but logged out, so `mla login` is the next step. shared-key
186
+ // is the opt-in headless path; user-token only appears on an idempotent re-run
187
+ // over a live browser session (init preserves it, never downgrades).
188
+ function describeInitAuthMode(mode) {
189
+ if (mode === "user-token")
190
+ return "user-token (browser login preserved)";
191
+ if (mode === "shared-key")
192
+ return "shared-key (headless)";
193
+ return "none (logged out; run `mla login` to sign in)";
194
+ }
195
+ async function runInit(argv) {
196
+ let flags;
197
+ try {
198
+ flags = parseInitArgs(argv);
199
+ }
200
+ catch (e) {
201
+ console.error(e.message);
202
+ return 2;
203
+ }
204
+ if (flags.unsafeCaptureNonBash) {
205
+ console.error("--unsafe-capture-non-bash is v0.1; rejected in v0.");
206
+ return 2;
207
+ }
208
+ if (flags.skillOnly) {
209
+ const res = (0, wire_1.runWire)({ skillOnly: true });
210
+ (0, wire_1.printWireResult)(res, { skillOnly: true });
211
+ return 0;
212
+ }
213
+ // Idempotent re-run: when cli-config.json exists, inherit each field
214
+ // the operator did not explicitly override. This lets `mla init` double
215
+ // as "rotate token" (`mla init --control-token NEW`) or "change backend"
216
+ // (`mla init --control-url ...`) without forcing the operator to retype
217
+ // every previously-set value. On a first run with nothing to inherit, the
218
+ // auth defaults to 'none' (see below) rather than demanding a token.
219
+ let prior = null;
220
+ if ((0, config_1.configExists)()) {
221
+ try {
222
+ prior = (0, config_1.readConfig)();
223
+ }
224
+ catch {
225
+ prior = null;
226
+ }
227
+ }
228
+ // §6.4: `mla init` DEFAULTS to auth.mode 'none' (machine wired, logged out)
229
+ // when no --control-token is given. The shared-key bootstrap is now opt-in via
230
+ // --control-token (headless / CI); the interactive path is `mla init` then
231
+ // `mla login`. buildInitConfig already assembles the 'none' auth, and a
232
+ // tokenless re-run over a live user-token PRESERVES it (no downgrade), so there
233
+ // is no token guard here: a tokenless first run is a supported, audited-by-login
234
+ // setup, not an error.
235
+ const cfg = buildInitConfig(flags, prior);
236
+ fs.mkdirSync(config_1.QUEUE_DIR, { recursive: true });
237
+ (0, config_1.writeConfig)(cfg);
238
+ const wire = (0, wire_1.runWire)({
239
+ noPostToolUse: !!flags.noPostToolUse,
240
+ noInstallFlock: !!flags.noInstallFlock,
241
+ noProjectRules: !!flags.noProjectRules,
242
+ noMcp: !!flags.noMcp,
243
+ });
244
+ const authMode = cfg.auth.mode;
245
+ console.log(`Wrote ${config_1.CFG_PATH}${prior ? " (updated)" : ""}`);
246
+ console.log(` controlUrl: ${cfg.controlUrl}`);
247
+ console.log(` intelUrl: ${cfg.intelUrl}`);
248
+ console.log(` mlaPath: ${cfg.mlaPath}`);
249
+ console.log(` auth: ${describeInitAuthMode(authMode)}`);
250
+ if (cfg.actorUserId) {
251
+ console.log(` actorUserId: ${cfg.actorUserId}`);
252
+ }
253
+ else if (authMode !== "none") {
254
+ // Under 'none' the actor is stamped by `mla login` (pinned to auth.user.id),
255
+ // so only the headless shared-key path needs the explicit --actor nag.
256
+ console.log(" actorUserId: (unset; required for `mla kb` curation commands. " +
257
+ "Re-run `mla init --actor <id>` to set it.)");
258
+ }
259
+ (0, wire_1.printWireResult)(wire);
260
+ // 4.4 first-run telemetry disclosure. Stated once, at setup, rather than on
261
+ // every invocation (a per-run notice would pollute scriptable output). Crash
262
+ // reporting is OFF unless a Sentry DSN is configured; run traces, when a
263
+ // backend enables them, go ONLY to the control URL above (your own server),
264
+ // never to Meetless. Hard-disable everything with MEETLESS_TELEMETRY=off.
265
+ console.log("Telemetry: crash reporting OFF (no Sentry DSN); run traces go only to " +
266
+ "your configured control, never to Meetless. Disable all with " +
267
+ "MEETLESS_TELEMETRY=off. See TELEMETRY.md.");
268
+ // A logged-out machine's next step is the browser login; a headless shared-key
269
+ // install goes straight to doctor.
270
+ console.log(`Next: ${authMode === "none" ? "mla login" : "mla doctor"}`);
271
+ return wire.flock?.ok ? 0 : 1;
272
+ }