@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.
- package/LICENSE +201 -0
- package/README.md +81 -0
- package/dist/build-info.json +9 -0
- package/dist/bundles/ask-core.js +396 -0
- package/dist/bundles/mcp.js +16592 -0
- package/dist/bundles/trace-core.js +263 -0
- package/dist/cli.js +828 -0
- package/dist/commands/activate.js +781 -0
- package/dist/commands/adoption.js +130 -0
- package/dist/commands/ask.js +290 -0
- package/dist/commands/context.js +114 -0
- package/dist/commands/debug.js +313 -0
- package/dist/commands/doctor.js +1021 -0
- package/dist/commands/enrich.js +427 -0
- package/dist/commands/evidence.js +229 -0
- package/dist/commands/flush.js +184 -0
- package/dist/commands/graph.js +104 -0
- package/dist/commands/init.js +272 -0
- package/dist/commands/internal-active-review.js +322 -0
- package/dist/commands/internal-auto-index.js +188 -0
- package/dist/commands/internal-capture-decisions.js +320 -0
- package/dist/commands/internal-evidence-correlate.js +239 -0
- package/dist/commands/internal-evidence-hooks.js +240 -0
- package/dist/commands/internal-evidence-inject.js +231 -0
- package/dist/commands/internal-finalize.js +221 -0
- package/dist/commands/internal-pretool-observe.js +225 -0
- package/dist/commands/internal-refresh.js +136 -0
- package/dist/commands/internal-session-nudge.js +120 -0
- package/dist/commands/internal-steer-sync.js +117 -0
- package/dist/commands/internal-turn-recap.js +140 -0
- package/dist/commands/kb.js +375 -0
- package/dist/commands/kb_add.js +681 -0
- package/dist/commands/kb_forget.js +283 -0
- package/dist/commands/kb_move.js +45 -0
- package/dist/commands/kb_pending.js +410 -0
- package/dist/commands/kb_personal.js +149 -0
- package/dist/commands/kb_promote.js +188 -0
- package/dist/commands/kb_purge.js +168 -0
- package/dist/commands/kb_reingest.js +335 -0
- package/dist/commands/kb_retime.js +170 -0
- package/dist/commands/kb_review.js +391 -0
- package/dist/commands/kb_revision.js +179 -0
- package/dist/commands/kb_show.js +385 -0
- package/dist/commands/label.js +226 -0
- package/dist/commands/login.js +295 -0
- package/dist/commands/logout.js +108 -0
- package/dist/commands/mcp-supervisor.js +93 -0
- package/dist/commands/mcp.js +227 -0
- package/dist/commands/queue-prune.js +98 -0
- package/dist/commands/review.js +358 -0
- package/dist/commands/rewire.js +124 -0
- package/dist/commands/rules.js +728 -0
- package/dist/commands/scan-context.js +67 -0
- package/dist/commands/session.js +347 -0
- package/dist/commands/stats.js +479 -0
- package/dist/commands/status.js +61 -0
- package/dist/commands/summary.js +250 -0
- package/dist/commands/turn.js +114 -0
- package/dist/commands/uninstall.js +222 -0
- package/dist/commands/whoami.js +102 -0
- package/dist/commands/workspace.js +130 -0
- package/dist/hooks-template/ce0-post-tool-use.sh +34 -0
- package/dist/hooks-template/ce0-session-start.sh +49 -0
- package/dist/hooks-template/ce0-stop.sh +29 -0
- package/dist/hooks-template/ce0-user-prompt-submit.sh +38 -0
- package/dist/hooks-template/common.sh +934 -0
- package/dist/hooks-template/event-batch-filter.jq +67 -0
- package/dist/hooks-template/flush.sh +503 -0
- package/dist/hooks-template/post-tool-use.sh +423 -0
- package/dist/hooks-template/pre-tool-use.sh +69 -0
- package/dist/hooks-template/session-start.sh +140 -0
- package/dist/hooks-template/stop.sh +308 -0
- package/dist/hooks-template/user-prompt-submit.sh +1162 -0
- package/dist/lib/activation.js +79 -0
- package/dist/lib/active-conflict-cache.js +141 -0
- package/dist/lib/active-memory.js +59 -0
- package/dist/lib/active-review-runner.js +26 -0
- package/dist/lib/agent-decision/index.js +25 -0
- package/dist/lib/agent-decision/keys.js +49 -0
- package/dist/lib/agent-decision/normalize-claude.js +183 -0
- package/dist/lib/agent-decision/types.js +21 -0
- package/dist/lib/agent-decision/validate.js +216 -0
- package/dist/lib/analytics/capture.js +96 -0
- package/dist/lib/analytics/command-event.js +267 -0
- package/dist/lib/analytics/consent.js +58 -0
- package/dist/lib/analytics/coverage-gap.js +96 -0
- package/dist/lib/analytics/envelope.js +236 -0
- package/dist/lib/analytics/event-id.js +86 -0
- package/dist/lib/analytics/evidence.js +150 -0
- package/dist/lib/analytics/followthrough.js +194 -0
- package/dist/lib/analytics/forwarder.js +109 -0
- package/dist/lib/analytics/logs.js +78 -0
- package/dist/lib/analytics/metrics.js +78 -0
- package/dist/lib/analytics/recorder.js +92 -0
- package/dist/lib/analytics/review-analytics.js +75 -0
- package/dist/lib/analytics/sequence.js +77 -0
- package/dist/lib/analytics/store.js +131 -0
- package/dist/lib/analytics/turn-recap.js +279 -0
- package/dist/lib/artifact_id.js +108 -0
- package/dist/lib/auth-breaker.js +161 -0
- package/dist/lib/auto-index.js +112 -0
- package/dist/lib/classifier.js +88 -0
- package/dist/lib/config.js +298 -0
- package/dist/lib/conflict-advisory.js +64 -0
- package/dist/lib/debug-bundle.js +520 -0
- package/dist/lib/enrichment/ingest.js +301 -0
- package/dist/lib/enrichment/plan.js +253 -0
- package/dist/lib/enrichment/protocol.js +359 -0
- package/dist/lib/enrichment/scout-brief.js +176 -0
- package/dist/lib/failure-telemetry.js +444 -0
- package/dist/lib/git.js +200 -0
- package/dist/lib/governance-cache.js +77 -0
- package/dist/lib/governed-path-cache.js +76 -0
- package/dist/lib/http.js +677 -0
- package/dist/lib/identity-envelope.js +23 -0
- package/dist/lib/kb-candidate.js +65 -0
- package/dist/lib/kb_acl.js +98 -0
- package/dist/lib/login.js +353 -0
- package/dist/lib/mcp-fetchers.js +130 -0
- package/dist/lib/mcp-restart.js +47 -0
- package/dist/lib/observability.js +805 -0
- package/dist/lib/open-url.js +33 -0
- package/dist/lib/orphan-guard.js +70 -0
- package/dist/lib/packaged.js +21 -0
- package/dist/lib/reconcile-sessions.js +171 -0
- package/dist/lib/redactor.js +89 -0
- package/dist/lib/relationship-candidate-query.js +27 -0
- package/dist/lib/render.js +611 -0
- package/dist/lib/rules/applicability.js +64 -0
- package/dist/lib/rules/attest-code-rule-version.js +47 -0
- package/dist/lib/rules/attest-notes-location.js +217 -0
- package/dist/lib/rules/attest-rule-version.js +69 -0
- package/dist/lib/rules/canonical-json.js +97 -0
- package/dist/lib/rules/ce0-emit.js +64 -0
- package/dist/lib/rules/ce0-evidence.js +281 -0
- package/dist/lib/rules/ce0-recall-sample.js +82 -0
- package/dist/lib/rules/ce0-rule.js +55 -0
- package/dist/lib/rules/ce0-sampling-bucket.js +15 -0
- package/dist/lib/rules/ce0-store.js +683 -0
- package/dist/lib/rules/ce0-telemetry-project.js +93 -0
- package/dist/lib/rules/ce0-telemetry.js +158 -0
- package/dist/lib/rules/code-rule-registry.js +17 -0
- package/dist/lib/rules/command-match.js +185 -0
- package/dist/lib/rules/consult-evidence-binding.js +27 -0
- package/dist/lib/rules/consultation-capture-adapter.js +193 -0
- package/dist/lib/rules/content-match.js +56 -0
- package/dist/lib/rules/deny-admission.js +99 -0
- package/dist/lib/rules/durable-observation.js +190 -0
- package/dist/lib/rules/enforce-notes-version.js +421 -0
- package/dist/lib/rules/evaluation-input-hash.js +126 -0
- package/dist/lib/rules/evaluator.js +108 -0
- package/dist/lib/rules/inert-rule-families.js +51 -0
- package/dist/lib/rules/input-authority-resolver.js +241 -0
- package/dist/lib/rules/interception-schema.js +170 -0
- package/dist/lib/rules/interception-store.js +267 -0
- package/dist/lib/rules/live-input-authority.js +66 -0
- package/dist/lib/rules/local-matcher.js +108 -0
- package/dist/lib/rules/local-observe.js +79 -0
- package/dist/lib/rules/local-rule-version-repo.js +214 -0
- package/dist/lib/rules/memory-requirement.js +109 -0
- package/dist/lib/rules/notes-observe.js +39 -0
- package/dist/lib/rules/notes-path.js +261 -0
- package/dist/lib/rules/notes-rule.js +75 -0
- package/dist/lib/rules/observe-adapter.js +114 -0
- package/dist/lib/rules/observed-rule-hash.js +119 -0
- package/dist/lib/rules/prompt-submit-adapter.js +132 -0
- package/dist/lib/rules/requirement-subject.js +240 -0
- package/dist/lib/rules/rule-activity.js +67 -0
- package/dist/lib/rules/rule-version-hash.js +151 -0
- package/dist/lib/rules/runtime-scope.js +55 -0
- package/dist/lib/rules/stop-adapter.js +116 -0
- package/dist/lib/rules/stop-response-snapshot.js +174 -0
- package/dist/lib/rules/types.js +10 -0
- package/dist/lib/rules/ulid.js +46 -0
- package/dist/lib/rules/version-evaluation.js +156 -0
- package/dist/lib/scanner/agent-memory.js +99 -0
- package/dist/lib/scanner/bootstrap-summary.js +87 -0
- package/dist/lib/scanner/cache.js +59 -0
- package/dist/lib/scanner/frontmatter.js +42 -0
- package/dist/lib/scanner/parse-directives.js +69 -0
- package/dist/lib/scanner/parse-structured.js +72 -0
- package/dist/lib/scanner/render.js +73 -0
- package/dist/lib/scanner/scan.js +132 -0
- package/dist/lib/scanner/score.js +38 -0
- package/dist/lib/scanner/scout-mission.js +126 -0
- package/dist/lib/scanner/types.js +7 -0
- package/dist/lib/session-scope.js +195 -0
- package/dist/lib/spool.js +355 -0
- package/dist/lib/staleness.js +100 -0
- package/dist/lib/steer-cache.js +87 -0
- package/dist/lib/tagged-reference.js +20 -0
- package/dist/lib/temporal.js +109 -0
- package/dist/lib/turn-recap-emit.js +67 -0
- package/dist/lib/unwire.js +253 -0
- package/dist/lib/update-check.js +469 -0
- package/dist/lib/update-notifier.js +217 -0
- package/dist/lib/upgrade-apply.js +643 -0
- package/dist/lib/wire.js +1087 -0
- package/dist/lib/workspace.js +96 -0
- package/dist/lib/zip.js +154 -0
- package/dist/pretool-entry.js +37 -0
- package/package.json +75 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// `mla enrich`: the two CLI bookends for agent-orchestrated onboarding enrichment.
|
|
3
|
+
//
|
|
4
|
+
// enrich plan -> derive the workspace + git root, mint a runId, scan the repo into
|
|
5
|
+
// an immutable run record (ranked doc targets + a bounded git-history
|
|
6
|
+
// allowlist), persist it locally, and print the plan the agent reads.
|
|
7
|
+
// enrich ingest -> the agent dispatched read-only scouts against that plan and reports
|
|
8
|
+
// candidates; this loads the authoritative run record, re-verifies it,
|
|
9
|
+
// validates + verifies every candidate, and persists the survivors to
|
|
10
|
+
// the governed KB born PENDING.
|
|
11
|
+
//
|
|
12
|
+
// The agent never supplies plan data: it gets a runId from `plan` and returns only the
|
|
13
|
+
// scout results. All trust enforcement (realpath containment, exist-at-HEAD, line range,
|
|
14
|
+
// commit allowlist, plan-digest match) lives in lib/enrichment, exercised here with the
|
|
15
|
+
// real filesystem, git, and the kb-add route. See
|
|
16
|
+
// notes/20260626-mla-agent-onboarding-enrichment-plan.md (§5, §5b, §6, §6b).
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.resolveBudgetMs = resolveBudgetMs;
|
|
19
|
+
exports.parsePlanArgs = parsePlanArgs;
|
|
20
|
+
exports.parseIngestArgs = parseIngestArgs;
|
|
21
|
+
exports.extractResults = extractResults;
|
|
22
|
+
exports.parseBriefArgs = parseBriefArgs;
|
|
23
|
+
exports.runEnrich = runEnrich;
|
|
24
|
+
const node_child_process_1 = require("node:child_process");
|
|
25
|
+
const node_fs_1 = require("node:fs");
|
|
26
|
+
const node_crypto_1 = require("node:crypto");
|
|
27
|
+
const config_1 = require("../lib/config");
|
|
28
|
+
const workspace_1 = require("../lib/workspace");
|
|
29
|
+
const http_1 = require("../lib/http");
|
|
30
|
+
const plan_1 = require("../lib/enrichment/plan");
|
|
31
|
+
const ingest_1 = require("../lib/enrichment/ingest");
|
|
32
|
+
const scout_brief_1 = require("../lib/enrichment/scout-brief");
|
|
33
|
+
const protocol_1 = require("../lib/enrichment/protocol");
|
|
34
|
+
const USAGE = `mla enrich: agent-orchestrated onboarding enrichment (two bookends).
|
|
35
|
+
|
|
36
|
+
mla enrich plan [--json] [--budget-ms <n>] [--workspace <id>]
|
|
37
|
+
Scan this repository into an immutable run record and print the plan the
|
|
38
|
+
agent reads to dispatch its read-only scouts. --json prints the machine
|
|
39
|
+
plan (the agent contract); without it, a human summary. The runId in the
|
|
40
|
+
output is what you pass back to \`enrich ingest\`.
|
|
41
|
+
|
|
42
|
+
mla enrich brief --run-id <id> --role <documentation|history> [--workspace <id>]
|
|
43
|
+
Print the exact subagent brief for one scout role, rendered from the run
|
|
44
|
+
record named by --run-id. Read-only; used by \`/mla onboard\` to dispatch each
|
|
45
|
+
scout with the run-specific prompt \`enrich ingest\` will validate against.
|
|
46
|
+
|
|
47
|
+
mla enrich ingest --run-id <id> [--results-file <path>] [--json] [--workspace <id>]
|
|
48
|
+
Validate + persist the scouts' candidates against the run record named by
|
|
49
|
+
--run-id. Reads the scout results as JSON from --results-file, or from
|
|
50
|
+
stdin when no file is given (an array of scout results, or an object with a
|
|
51
|
+
\`results\` array). Candidates land in the governed KB born PENDING.
|
|
52
|
+
Exit: 0 clean, 1 a scout needs attention (persistence failed / malformed),
|
|
53
|
+
2 the request was rejected (unknown run, mismatch, corrupt record).`;
|
|
54
|
+
// Mirror kb_add's ingest timeout heuristic (it is module-private there). Generous,
|
|
55
|
+
// scales with document count: the kb-add route runs the full atomic-claim pipeline.
|
|
56
|
+
function ingestTimeoutMs(docCount) {
|
|
57
|
+
return Math.max(120_000, docCount * 20_000);
|
|
58
|
+
}
|
|
59
|
+
// The git toplevel is the enrichment repository root: `git ls-files` / `git log` must
|
|
60
|
+
// run from it so the paths the scouts cite are repo-root-relative and the realpath
|
|
61
|
+
// containment check has the right base. Throws a clean error outside a git repo.
|
|
62
|
+
function resolveRepositoryRoot(startDir) {
|
|
63
|
+
try {
|
|
64
|
+
return (0, node_child_process_1.execFileSync)("git", ["rev-parse", "--show-toplevel"], {
|
|
65
|
+
cwd: startDir,
|
|
66
|
+
encoding: "utf8",
|
|
67
|
+
}).trim();
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
throw new Error(`mla enrich requires a git repository. No git toplevel found at ${startDir}. ` +
|
|
71
|
+
`Run it from inside an activated, git-tracked repository.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// The §8 budget knob. `--budget-ms` wins; else MLA_ENRICH_BUDGET_MS; else the protocol
|
|
75
|
+
// default (createPlan applies it). An invalid env value is IGNORED with a warning rather
|
|
76
|
+
// than failing the command (an explicit flag with a bad value still hard-errors upstream).
|
|
77
|
+
//
|
|
78
|
+
// Contract honesty (§8, Phase 0B): this knob sets the run's `deadlineAt`; it is a SOFT
|
|
79
|
+
// budget. The CLI does not supervise the scouts (the agent does), so the deadline steers
|
|
80
|
+
// the skill's dispatch/wait and the scouts self-limit. Ingest already records a scout that
|
|
81
|
+
// reports `timed_out` as partial-and-rerunnable; no late arrival is rejected on time. Do
|
|
82
|
+
// not call this a hard ceiling until a live hang-test proves the runtime can abandon a
|
|
83
|
+
// straggler at the deadline (background dispatch + scheduled wake + task-stop).
|
|
84
|
+
function resolveBudgetMs(flagBudget, rawEnv) {
|
|
85
|
+
if (flagBudget !== undefined)
|
|
86
|
+
return { budgetMs: flagBudget };
|
|
87
|
+
if (rawEnv === undefined || rawEnv.trim() === "")
|
|
88
|
+
return {};
|
|
89
|
+
const v = Number(rawEnv);
|
|
90
|
+
if (!Number.isFinite(v) || v <= 0) {
|
|
91
|
+
return { warning: `ignoring invalid MLA_ENRICH_BUDGET_MS=${rawEnv} (expected a positive number of milliseconds)` };
|
|
92
|
+
}
|
|
93
|
+
return { budgetMs: v };
|
|
94
|
+
}
|
|
95
|
+
// Exported for unit tests: the pure flag/payload helpers are the only new logic in this
|
|
96
|
+
// shell worth isolating (createPlan/ingestRun are covered by their own specs).
|
|
97
|
+
function parsePlanArgs(argv) {
|
|
98
|
+
const flags = { json: false };
|
|
99
|
+
for (let i = 0; i < argv.length; i++) {
|
|
100
|
+
const a = argv[i];
|
|
101
|
+
if (a === "--json")
|
|
102
|
+
flags.json = true;
|
|
103
|
+
else if (a === "--budget-ms") {
|
|
104
|
+
const v = Number(argv[++i]);
|
|
105
|
+
if (!Number.isFinite(v) || v <= 0)
|
|
106
|
+
throw new Error("--budget-ms must be a positive number of milliseconds");
|
|
107
|
+
flags.budgetMs = v;
|
|
108
|
+
}
|
|
109
|
+
else if (a === "--workspace") {
|
|
110
|
+
flags.workspace = argv[++i];
|
|
111
|
+
if (!flags.workspace)
|
|
112
|
+
throw new Error("--workspace requires a workspace id");
|
|
113
|
+
}
|
|
114
|
+
else
|
|
115
|
+
throw new Error(`Unknown flag for \`mla enrich plan\`: ${a}`);
|
|
116
|
+
}
|
|
117
|
+
return flags;
|
|
118
|
+
}
|
|
119
|
+
async function runEnrichPlan(argv) {
|
|
120
|
+
let flags;
|
|
121
|
+
try {
|
|
122
|
+
flags = parsePlanArgs(argv);
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
console.error(e.message);
|
|
126
|
+
return 2;
|
|
127
|
+
}
|
|
128
|
+
let cfg;
|
|
129
|
+
try {
|
|
130
|
+
cfg = (0, config_1.readKbConfig)(flags.workspace);
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
console.error(e.message);
|
|
134
|
+
return 2;
|
|
135
|
+
}
|
|
136
|
+
let repositoryRoot;
|
|
137
|
+
try {
|
|
138
|
+
const ctx = (0, workspace_1.resolveWorkspaceContext)();
|
|
139
|
+
repositoryRoot = resolveRepositoryRoot(ctx.markerDir);
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
console.error(e.message);
|
|
143
|
+
return 2;
|
|
144
|
+
}
|
|
145
|
+
const budget = resolveBudgetMs(flags.budgetMs, process.env.MLA_ENRICH_BUDGET_MS);
|
|
146
|
+
if (budget.warning)
|
|
147
|
+
console.error(budget.warning);
|
|
148
|
+
const runId = `run-${(0, node_crypto_1.randomUUID)()}`;
|
|
149
|
+
const { run, recordPath, pruned, historyTruncated } = (0, plan_1.createPlan)({
|
|
150
|
+
runId,
|
|
151
|
+
workspaceId: cfg.workspaceId,
|
|
152
|
+
repositoryRoot,
|
|
153
|
+
home: config_1.HOME,
|
|
154
|
+
now: new Date().toISOString(),
|
|
155
|
+
budgetMs: budget.budgetMs,
|
|
156
|
+
});
|
|
157
|
+
if (flags.json) {
|
|
158
|
+
// The agent contract: the run record plus the truncation signal. The agent reads
|
|
159
|
+
// documentationTargets + historyEvidence to dispatch its scouts and passes runId
|
|
160
|
+
// back to `enrich ingest`. It is the SAME record persisted on disk (no divergence).
|
|
161
|
+
console.log(JSON.stringify({ ...run, historyTruncated }, null, 2));
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
const lines = [
|
|
165
|
+
`Onboarding enrichment plan ready.`,
|
|
166
|
+
``,
|
|
167
|
+
` runId: ${run.runId}`,
|
|
168
|
+
` workspace: ${run.workspaceId}`,
|
|
169
|
+
` repository: ${run.repositoryRoot}`,
|
|
170
|
+
` budget: ${run.limits.budgetMs} ms (deadline ${run.deadlineAt})`,
|
|
171
|
+
` doc targets: ${run.documentationTargets.length}`,
|
|
172
|
+
` history commits: ${run.historyEvidence.length}${historyTruncated ? " (truncated)" : ""}`,
|
|
173
|
+
` max candidates: ${run.limits.maxCandidatesTotal}`,
|
|
174
|
+
` record: ${recordPath}${pruned ? ` (pruned ${pruned} stale)` : ""}`,
|
|
175
|
+
``,
|
|
176
|
+
`Run \`mla enrich plan --json\` for the machine plan, then dispatch scouts and`,
|
|
177
|
+
`report with \`mla enrich ingest --run-id ${run.runId}\`.`,
|
|
178
|
+
];
|
|
179
|
+
console.log(lines.join("\n"));
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
function parseIngestArgs(argv) {
|
|
183
|
+
const flags = { json: false };
|
|
184
|
+
for (let i = 0; i < argv.length; i++) {
|
|
185
|
+
const a = argv[i];
|
|
186
|
+
if (a === "--json")
|
|
187
|
+
flags.json = true;
|
|
188
|
+
else if (a === "--run-id") {
|
|
189
|
+
flags.runId = argv[++i];
|
|
190
|
+
if (!flags.runId)
|
|
191
|
+
throw new Error("--run-id requires a value");
|
|
192
|
+
}
|
|
193
|
+
else if (a === "--results-file") {
|
|
194
|
+
flags.resultsFile = argv[++i];
|
|
195
|
+
if (!flags.resultsFile)
|
|
196
|
+
throw new Error("--results-file requires a path");
|
|
197
|
+
}
|
|
198
|
+
else if (a === "--workspace") {
|
|
199
|
+
flags.workspace = argv[++i];
|
|
200
|
+
if (!flags.workspace)
|
|
201
|
+
throw new Error("--workspace requires a workspace id");
|
|
202
|
+
}
|
|
203
|
+
else
|
|
204
|
+
throw new Error(`Unknown flag for \`mla enrich ingest\`: ${a}`);
|
|
205
|
+
}
|
|
206
|
+
if (!flags.runId)
|
|
207
|
+
throw new Error("--run-id is required (the id printed by `mla enrich plan`)");
|
|
208
|
+
return flags;
|
|
209
|
+
}
|
|
210
|
+
function readStdin() {
|
|
211
|
+
return new Promise((resolve, reject) => {
|
|
212
|
+
let data = "";
|
|
213
|
+
process.stdin.setEncoding("utf8");
|
|
214
|
+
process.stdin.on("data", (chunk) => (data += chunk));
|
|
215
|
+
process.stdin.on("end", () => resolve(data));
|
|
216
|
+
process.stdin.on("error", reject);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
// Normalize the agent's payload into the results array. Accept three shapes for
|
|
220
|
+
// ergonomics: a bare array, `{results:[...]}`, or the full `{runId, results}` request.
|
|
221
|
+
// When a runId is present in the body it MUST match --run-id (defense against a stale
|
|
222
|
+
// paste pointing the wrong run's results at this record).
|
|
223
|
+
function extractResults(raw, runId) {
|
|
224
|
+
let parsed;
|
|
225
|
+
try {
|
|
226
|
+
parsed = JSON.parse(raw);
|
|
227
|
+
}
|
|
228
|
+
catch (e) {
|
|
229
|
+
throw new Error(`scout results are not valid JSON: ${e.message}`);
|
|
230
|
+
}
|
|
231
|
+
if (Array.isArray(parsed))
|
|
232
|
+
return parsed;
|
|
233
|
+
if (parsed && typeof parsed === "object") {
|
|
234
|
+
const obj = parsed;
|
|
235
|
+
if (obj.runId !== undefined && obj.runId !== runId) {
|
|
236
|
+
throw new Error(`results runId (${String(obj.runId)}) does not match --run-id (${runId})`);
|
|
237
|
+
}
|
|
238
|
+
if (Array.isArray(obj.results))
|
|
239
|
+
return obj.results;
|
|
240
|
+
}
|
|
241
|
+
throw new Error("scout results must be a JSON array, or an object with a `results` array");
|
|
242
|
+
}
|
|
243
|
+
function renderIngestSummary(outcomes, status) {
|
|
244
|
+
const lines = [`Onboarding ingest complete (state: ${status ?? "unknown"}).`, ``];
|
|
245
|
+
for (const o of outcomes) {
|
|
246
|
+
lines.push(` ${o.scout}: ${o.accepted} accepted, ${o.rejected} rejected, ${o.persisted} persisted (received ${o.received})`);
|
|
247
|
+
for (const e of o.errors) {
|
|
248
|
+
const where = e.index >= 0 ? `candidate ${e.index}` : "scout";
|
|
249
|
+
lines.push(` - ${where}: ${e.code} (${e.message})`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return lines.join("\n");
|
|
253
|
+
}
|
|
254
|
+
async function runEnrichIngest(argv) {
|
|
255
|
+
let flags;
|
|
256
|
+
try {
|
|
257
|
+
flags = parseIngestArgs(argv);
|
|
258
|
+
}
|
|
259
|
+
catch (e) {
|
|
260
|
+
console.error(e.message);
|
|
261
|
+
return 2;
|
|
262
|
+
}
|
|
263
|
+
let cfg;
|
|
264
|
+
try {
|
|
265
|
+
cfg = (0, config_1.readKbConfig)(flags.workspace);
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
console.error(e.message);
|
|
269
|
+
return 2;
|
|
270
|
+
}
|
|
271
|
+
let repositoryRoot;
|
|
272
|
+
try {
|
|
273
|
+
const ctx = (0, workspace_1.resolveWorkspaceContext)();
|
|
274
|
+
repositoryRoot = resolveRepositoryRoot(ctx.markerDir);
|
|
275
|
+
}
|
|
276
|
+
catch (e) {
|
|
277
|
+
console.error(e.message);
|
|
278
|
+
return 2;
|
|
279
|
+
}
|
|
280
|
+
// Source the scout results: an explicit file, or piped stdin. Refuse to hang on a TTY.
|
|
281
|
+
let rawResults;
|
|
282
|
+
try {
|
|
283
|
+
if (flags.resultsFile) {
|
|
284
|
+
rawResults = (0, node_fs_1.readFileSync)(flags.resultsFile, "utf8");
|
|
285
|
+
}
|
|
286
|
+
else if (!process.stdin.isTTY) {
|
|
287
|
+
rawResults = await readStdin();
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
console.error("provide --results-file <path> or pipe the scout results JSON to stdin");
|
|
291
|
+
return 2;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
catch (e) {
|
|
295
|
+
console.error(`could not read scout results: ${e.message}`);
|
|
296
|
+
return 2;
|
|
297
|
+
}
|
|
298
|
+
let results;
|
|
299
|
+
try {
|
|
300
|
+
results = extractResults(rawResults, flags.runId);
|
|
301
|
+
}
|
|
302
|
+
catch (e) {
|
|
303
|
+
console.error(e.message);
|
|
304
|
+
return 2;
|
|
305
|
+
}
|
|
306
|
+
// The real kb-add persister: born-PENDING governed notes. provenance is advisory
|
|
307
|
+
// (the server derives the recorded value from the envelope); the count reflects
|
|
308
|
+
// receipts that landed (ingested or already-present), not failures.
|
|
309
|
+
const persist = async (docs) => {
|
|
310
|
+
const body = {
|
|
311
|
+
workspaceId: cfg.workspaceId,
|
|
312
|
+
actor: cfg.actorUserId,
|
|
313
|
+
documents: docs.map((d) => ({ relPath: d.relPath, content: d.content })),
|
|
314
|
+
provenance: "agent_distilled",
|
|
315
|
+
profile: "markdown_atomic_v1",
|
|
316
|
+
mode: "file",
|
|
317
|
+
};
|
|
318
|
+
const res = await (0, http_1.intelPost)(cfg, "/internal/v1/kb/add", body, ingestTimeoutMs(docs.length));
|
|
319
|
+
const receipts = res.receipts ?? [];
|
|
320
|
+
return { persisted: receipts.filter((r) => r.outcome !== "failed").length };
|
|
321
|
+
};
|
|
322
|
+
const res = await (0, ingest_1.ingestRun)({
|
|
323
|
+
env: { home: config_1.HOME, workspaceId: cfg.workspaceId, repositoryRoot },
|
|
324
|
+
request: { protocolVersion: protocol_1.PROTOCOL_VERSION, runId: flags.runId, results },
|
|
325
|
+
persist,
|
|
326
|
+
now: new Date().toISOString(),
|
|
327
|
+
});
|
|
328
|
+
if (!res.ok) {
|
|
329
|
+
if (flags.json)
|
|
330
|
+
console.log(JSON.stringify(res, null, 2));
|
|
331
|
+
else
|
|
332
|
+
console.error(`enrich ingest rejected: ${res.rejectionReason}`);
|
|
333
|
+
return 2;
|
|
334
|
+
}
|
|
335
|
+
if (flags.json) {
|
|
336
|
+
console.log(JSON.stringify(res, null, 2));
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
console.log(renderIngestSummary(res.outcomes, res.state?.status));
|
|
340
|
+
}
|
|
341
|
+
// 1 when a scout needs attention (infra failure or a malformed envelope worth a retry);
|
|
342
|
+
// 0 otherwise. A scout that merely "timed_out" is rerunnable state, not an error here.
|
|
343
|
+
const needsAttention = (res.state ? Object.values(res.state.scouts) : []).some((s) => s.status === "persistence_failed" || s.status === "malformed");
|
|
344
|
+
return needsAttention ? 1 : 0;
|
|
345
|
+
}
|
|
346
|
+
function parseBriefArgs(argv) {
|
|
347
|
+
const flags = {};
|
|
348
|
+
for (let i = 0; i < argv.length; i++) {
|
|
349
|
+
const a = argv[i];
|
|
350
|
+
if (a === "--run-id") {
|
|
351
|
+
flags.runId = argv[++i];
|
|
352
|
+
if (!flags.runId)
|
|
353
|
+
throw new Error("--run-id requires a value");
|
|
354
|
+
}
|
|
355
|
+
else if (a === "--role") {
|
|
356
|
+
const v = argv[++i];
|
|
357
|
+
if (!v)
|
|
358
|
+
throw new Error("--role requires a value");
|
|
359
|
+
if (!protocol_1.SCOUT_NAMES.includes(v)) {
|
|
360
|
+
throw new Error(`--role must be one of: ${protocol_1.SCOUT_NAMES.join(", ")}`);
|
|
361
|
+
}
|
|
362
|
+
flags.role = v;
|
|
363
|
+
}
|
|
364
|
+
else if (a === "--workspace") {
|
|
365
|
+
flags.workspace = argv[++i];
|
|
366
|
+
if (!flags.workspace)
|
|
367
|
+
throw new Error("--workspace requires a workspace id");
|
|
368
|
+
}
|
|
369
|
+
else
|
|
370
|
+
throw new Error(`Unknown flag for \`mla enrich brief\`: ${a}`);
|
|
371
|
+
}
|
|
372
|
+
if (!flags.runId)
|
|
373
|
+
throw new Error("--run-id is required (the id printed by `mla enrich plan`)");
|
|
374
|
+
if (!flags.role)
|
|
375
|
+
throw new Error(`--role is required (one of: ${protocol_1.SCOUT_NAMES.join(", ")})`);
|
|
376
|
+
return flags;
|
|
377
|
+
}
|
|
378
|
+
// Print one scout's run-specific brief. Pure read of the persisted run record plus
|
|
379
|
+
// buildScoutPrompt; no git, no network, no mutation. `/mla onboard` calls this to get
|
|
380
|
+
// the exact prompt it hands each subagent, so the brief logic stays in tested TS and
|
|
381
|
+
// every scout input matches what `enrich ingest` re-validates against the same record.
|
|
382
|
+
function runEnrichBrief(argv) {
|
|
383
|
+
let flags;
|
|
384
|
+
try {
|
|
385
|
+
flags = parseBriefArgs(argv);
|
|
386
|
+
}
|
|
387
|
+
catch (e) {
|
|
388
|
+
console.error(e.message);
|
|
389
|
+
return 2;
|
|
390
|
+
}
|
|
391
|
+
let cfg;
|
|
392
|
+
try {
|
|
393
|
+
cfg = (0, config_1.readKbConfig)(flags.workspace);
|
|
394
|
+
}
|
|
395
|
+
catch (e) {
|
|
396
|
+
console.error(e.message);
|
|
397
|
+
return 2;
|
|
398
|
+
}
|
|
399
|
+
const run = (0, plan_1.loadRunRecord)(config_1.HOME, cfg.workspaceId, flags.runId);
|
|
400
|
+
if (!run) {
|
|
401
|
+
console.error(`no onboarding run record for ${flags.runId} in workspace ${cfg.workspaceId}. ` +
|
|
402
|
+
"Run `mla enrich plan` first, from the same workspace.");
|
|
403
|
+
return 2;
|
|
404
|
+
}
|
|
405
|
+
console.log((0, scout_brief_1.buildScoutPrompt)(run, flags.role));
|
|
406
|
+
return 0;
|
|
407
|
+
}
|
|
408
|
+
async function runEnrich(argv) {
|
|
409
|
+
const sub = argv[0];
|
|
410
|
+
const rest = argv.slice(1);
|
|
411
|
+
if (sub === undefined || sub === "help" || sub === "--help" || sub === "-h") {
|
|
412
|
+
console.log(USAGE);
|
|
413
|
+
return 0;
|
|
414
|
+
}
|
|
415
|
+
switch (sub) {
|
|
416
|
+
case "plan":
|
|
417
|
+
return runEnrichPlan(rest);
|
|
418
|
+
case "brief":
|
|
419
|
+
return runEnrichBrief(rest);
|
|
420
|
+
case "ingest":
|
|
421
|
+
return runEnrichIngest(rest);
|
|
422
|
+
default:
|
|
423
|
+
console.error(`unknown \`mla enrich\` subcommand: ${sub}\n`);
|
|
424
|
+
console.error(USAGE);
|
|
425
|
+
return 2;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
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.defaultCe0StorePath = void 0;
|
|
37
|
+
exports.runEvidence = runEvidence;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const config_1 = require("../lib/config");
|
|
41
|
+
const workspace_1 = require("../lib/workspace");
|
|
42
|
+
const observability_1 = require("../lib/observability");
|
|
43
|
+
const ce0_store_1 = require("../lib/rules/ce0-store");
|
|
44
|
+
Object.defineProperty(exports, "defaultCe0StorePath", { enumerable: true, get: function () { return ce0_store_1.defaultCe0StorePath; } });
|
|
45
|
+
const ce0_evidence_1 = require("../lib/rules/ce0-evidence");
|
|
46
|
+
const ce0_recall_sample_1 = require("../lib/rules/ce0-recall-sample");
|
|
47
|
+
const ce0_telemetry_project_1 = require("../lib/rules/ce0-telemetry-project");
|
|
48
|
+
const recorder_1 = require("../lib/analytics/recorder");
|
|
49
|
+
const store_1 = require("../lib/analytics/store");
|
|
50
|
+
// `mla evidence` -- the one human-only CE0 labeling workflow
|
|
51
|
+
// (notes/20260617-evidence-consultation-forcing-function-proposal.md §2.3). CE0 is a measurement
|
|
52
|
+
// harness: the runtime hooks only record facts (the per-turn assessment, the consultation attempts)
|
|
53
|
+
// and the first Stop freezes the eligibility boundary. Satisfaction and coverage are graded OFFLINE,
|
|
54
|
+
// by a human, through this command. There is no model call and no external egress here; the response
|
|
55
|
+
// ceiling stays RECORD_ONLY.
|
|
56
|
+
//
|
|
57
|
+
// mla evidence ce0-export Write the JSONL a labeler audits: every deadline-claimed,
|
|
58
|
+
// not-yet-finalized obligation with the deterministic
|
|
59
|
+
// machine baseline recomputed over its eligible consultations.
|
|
60
|
+
// mla evidence ce0-import-labels <file> Read a labeled JSONL back, validate each label against the
|
|
61
|
+
// current export snapshot, and CAS-finalize the matched
|
|
62
|
+
// obligations. Prints the finalize / conflict / reject /
|
|
63
|
+
// agreement report.
|
|
64
|
+
//
|
|
65
|
+
// The command is a thin IO shell over the pure ce0-evidence core; the store path, workspace
|
|
66
|
+
// resolution, and the stdout / stderr sinks are injectable so the workflow is testable end to end.
|
|
67
|
+
const USAGE = "usage: mla evidence <ce0-export | ce0-import-labels <file> | ce0-emit-telemetry>";
|
|
68
|
+
const RECALL_SAMPLE_RATE_FLAG = "--recall-sample-rate";
|
|
69
|
+
/**
|
|
70
|
+
* Parse the optional `--recall-sample-rate <value>` (or `=<value>`) flag for `ce0-export`. Absent ->
|
|
71
|
+
* the pinned DEFAULT_RECALL_SAMPLE_RATE (sample every unflagged turn). Present -> a finite fraction in
|
|
72
|
+
* [0, 1]; anything else (non-numeric, out of range, missing value) is an operator error reported with a
|
|
73
|
+
* non-zero exit so a bad rate never silently narrows the recall denominator
|
|
74
|
+
* (notes/20260617-evidence-consultation-forcing-function-proposal.md lines 2129, 2145).
|
|
75
|
+
*/
|
|
76
|
+
function parseRecallSampleRate(args) {
|
|
77
|
+
let raw;
|
|
78
|
+
for (let i = 0; i < args.length; i++) {
|
|
79
|
+
const tok = args[i];
|
|
80
|
+
if (tok === RECALL_SAMPLE_RATE_FLAG) {
|
|
81
|
+
raw = args[i + 1];
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
else if (tok.startsWith(`${RECALL_SAMPLE_RATE_FLAG}=`)) {
|
|
85
|
+
raw = tok.slice(RECALL_SAMPLE_RATE_FLAG.length + 1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (raw === undefined)
|
|
89
|
+
return { value: ce0_recall_sample_1.DEFAULT_RECALL_SAMPLE_RATE };
|
|
90
|
+
const value = Number(raw);
|
|
91
|
+
if (raw.trim() === "" || !Number.isFinite(value) || value < 0 || value > 1) {
|
|
92
|
+
return { error: `${RECALL_SAMPLE_RATE_FLAG} must be a number in [0, 1] (got "${raw}")` };
|
|
93
|
+
}
|
|
94
|
+
return { value };
|
|
95
|
+
}
|
|
96
|
+
async function runEvidence(argv, deps = {}) {
|
|
97
|
+
const out = deps.out ?? ((line) => console.log(line));
|
|
98
|
+
const err = deps.err ?? ((line) => console.error(line));
|
|
99
|
+
const sub = argv[0];
|
|
100
|
+
if (sub === "ce0-export") {
|
|
101
|
+
const rate = parseRecallSampleRate(argv.slice(1));
|
|
102
|
+
if ("error" in rate) {
|
|
103
|
+
err(`mla evidence ce0-export: ${rate.error}\n${USAGE}`);
|
|
104
|
+
return 2;
|
|
105
|
+
}
|
|
106
|
+
return withWorkspaceAndStore(deps, err, (workspaceId, store) => {
|
|
107
|
+
out((0, ce0_evidence_1.runCe0Export)(store, workspaceId, rate.value));
|
|
108
|
+
return 0;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (sub === "ce0-import-labels") {
|
|
112
|
+
const file = argv[1];
|
|
113
|
+
if (!file) {
|
|
114
|
+
err(`mla evidence ce0-import-labels: missing labels file argument\n${USAGE}`);
|
|
115
|
+
return 2;
|
|
116
|
+
}
|
|
117
|
+
const readFile = deps.readFile ?? ((p) => fs.readFileSync(p, "utf8"));
|
|
118
|
+
const labelJsonl = readFile(file);
|
|
119
|
+
return withWorkspaceAndStore(deps, err, (workspaceId, store) => {
|
|
120
|
+
const report = (0, ce0_evidence_1.runCe0ImportLabels)(store, workspaceId, labelJsonl);
|
|
121
|
+
out(JSON.stringify(report));
|
|
122
|
+
return 0;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (sub === "ce0-emit-telemetry") {
|
|
126
|
+
return runEmitTelemetry(deps, out, err);
|
|
127
|
+
}
|
|
128
|
+
err(`mla evidence: unknown subcommand ${sub ? `"${sub}"` : "(none)"}\n${USAGE}`);
|
|
129
|
+
return 2;
|
|
130
|
+
}
|
|
131
|
+
/** `mla evidence ce0-emit-telemetry`: project the CE0 store into the two §6.4 events it honestly
|
|
132
|
+
* backs (memory_requirement_assessed per assessment, evidence_obligation_finalized per FINALIZED
|
|
133
|
+
* obligation), record each locally, then best-effort forward to control. A repeated sweep is
|
|
134
|
+
* idempotent two ways: the deterministic event_id dedupes on the remote sink, and a local skip-set
|
|
135
|
+
* (the event_ids already in the local log for these two types) avoids re-appending the same lines.
|
|
136
|
+
* Each event carries the ORIGINAL turn's session, so the analytics side joins it to the turn it
|
|
137
|
+
* describes, not to this emit run. */
|
|
138
|
+
async function runEmitTelemetry(deps, out, err) {
|
|
139
|
+
const env = deps.env ?? process.env;
|
|
140
|
+
const record = deps.record ?? recorder_1.recordAnalyticsEvent;
|
|
141
|
+
const read = deps.readEvents ?? store_1.readEvents;
|
|
142
|
+
const readCfg = deps.readCfg ??
|
|
143
|
+
(() => {
|
|
144
|
+
try {
|
|
145
|
+
return (0, config_1.readConfig)();
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
const cfg = readCfg();
|
|
152
|
+
// One run_id per invocation (never derived from trace); reuse the bootstrap-set run/trace when
|
|
153
|
+
// present so all events in this sweep share them, else mint fresh (a standalone measurement run).
|
|
154
|
+
const runId = deps.runId ?? (0, observability_1.getRunId)() ?? (0, observability_1.mintRunId)();
|
|
155
|
+
const traceId = deps.traceId ?? (0, observability_1.getRunTraceId)() ?? (0, observability_1.mintTraceId)();
|
|
156
|
+
const distinctId = deps.distinctId ?? cfg?.actorUserId ?? (deps.machineId ?? store_1.machineId)();
|
|
157
|
+
const nowIso = new Date(deps.nowMs ?? Date.now()).toISOString();
|
|
158
|
+
let assessed = 0;
|
|
159
|
+
let finalized = 0;
|
|
160
|
+
let skipped = 0;
|
|
161
|
+
const code = withWorkspaceAndStore(deps, err, (workspaceId, store) => {
|
|
162
|
+
// Skip-set: every event_id already logged locally for the two projected types. Keeps a repeated
|
|
163
|
+
// sweep from re-appending lines the deterministic event_id would otherwise dedupe only remotely.
|
|
164
|
+
const emitted = new Set();
|
|
165
|
+
for (const ev of read(env)) {
|
|
166
|
+
if ((ev.event_type === "memory_requirement_assessed" ||
|
|
167
|
+
ev.event_type === "evidence_obligation_finalized") &&
|
|
168
|
+
typeof ev.event_id === "string") {
|
|
169
|
+
emitted.add(ev.event_id);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const emit = (sessionId, input) => {
|
|
173
|
+
if (input.eventId && emitted.has(input.eventId)) {
|
|
174
|
+
skipped++;
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
const ctx = { workspaceId, sessionId, distinctId, runId, traceId, now: nowIso };
|
|
178
|
+
record(ctx, input, env);
|
|
179
|
+
if (input.eventId)
|
|
180
|
+
emitted.add(input.eventId);
|
|
181
|
+
return true;
|
|
182
|
+
};
|
|
183
|
+
for (const a of (0, ce0_store_1.listTurnMemoryAssessments)(store, workspaceId)) {
|
|
184
|
+
if (emit(a.sessionId, (0, ce0_telemetry_project_1.projectAssessedEvent)(a)))
|
|
185
|
+
assessed++;
|
|
186
|
+
}
|
|
187
|
+
for (const o of (0, ce0_store_1.listDeadlineClaimedObligations)(store, workspaceId)) {
|
|
188
|
+
if (o.status !== "FINALIZED")
|
|
189
|
+
continue;
|
|
190
|
+
const consultations = (0, ce0_store_1.listConsultationsForTurn)(store, {
|
|
191
|
+
workspaceId: o.workspaceId,
|
|
192
|
+
sessionId: o.sessionId,
|
|
193
|
+
localTurnSequence: o.localTurnSequence,
|
|
194
|
+
});
|
|
195
|
+
if (emit(o.sessionId, (0, ce0_telemetry_project_1.projectFinalizedEvent)(o, consultations)))
|
|
196
|
+
finalized++;
|
|
197
|
+
}
|
|
198
|
+
return 0;
|
|
199
|
+
});
|
|
200
|
+
if (code !== 0)
|
|
201
|
+
return code;
|
|
202
|
+
if (cfg) {
|
|
203
|
+
const flush = deps.flush ?? recorder_1.flushAnalyticsEvents;
|
|
204
|
+
await flush(cfg, env);
|
|
205
|
+
}
|
|
206
|
+
out(JSON.stringify({ emitted: { assessed, finalized }, skipped }));
|
|
207
|
+
return 0;
|
|
208
|
+
}
|
|
209
|
+
/** Resolve the workspace, ensure the store directory exists, open it, run `body`, and close it. A
|
|
210
|
+
* missing workspace is exit 1 (an operator problem: run from a marked repo or set the env var). */
|
|
211
|
+
function withWorkspaceAndStore(deps, err, body) {
|
|
212
|
+
const resolve = deps.resolveWorkspaceId ?? workspace_1.resolveWorkspaceIdWithEnv;
|
|
213
|
+
const workspaceId = resolve();
|
|
214
|
+
if (!workspaceId) {
|
|
215
|
+
err("mla evidence: no workspace resolved. Run from a directory with a .meetless.json marker, " +
|
|
216
|
+
"or set MEETLESS_WORKSPACE_ID.");
|
|
217
|
+
return 1;
|
|
218
|
+
}
|
|
219
|
+
const dbPath = deps.storePath ?? (0, ce0_store_1.defaultCe0StorePath)();
|
|
220
|
+
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
221
|
+
const open = deps.openStore ?? ce0_store_1.openCe0Store;
|
|
222
|
+
const store = open(dbPath);
|
|
223
|
+
try {
|
|
224
|
+
return body(workspaceId, store);
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
(0, ce0_store_1.closeCe0Store)(store);
|
|
228
|
+
}
|
|
229
|
+
}
|