openmerit 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.6 — 2026-11-06
|
|
4
|
+
|
|
5
|
+
- Distinguish a connected Langfuse key from incomplete score-import setup. Connection status exposes only score-mapping and model-alias counts, and the web UI explains when either is missing. The CLI preserves those counts when the server provides them. Requires the corresponding Scout deployment and npm patch; does not change credentials, mappings or experiment attribution.
|
|
6
|
+
- Update an existing Langfuse connection's non-secret settings through CLI, MCP or API without retrieving or re-entering its Viewer key. Omit both Viewer credentials; Scout reuses and reverifies the encrypted key internally. New connections still require a protected Viewer pair, and partial pairs are rejected. Settings changes invalidate imported aggregates; sync again afterwards. Requires the matching Scout deployment.
|
|
7
|
+
|
|
3
8
|
## 0.3.5 — 2026-11-05
|
|
4
9
|
|
|
5
10
|
- Add optional headless Langfuse setup through the CLI, HTTP API and `scout_connection` MCP tool. A separately approved `scout:connections` key manages the authenticated user's connection and evaluation data; recommendation keys retain their existing permission. Viewer credentials enter through protected CLI input or trusted client configuration, never model-visible tool arguments. The web connection UI remains available, with revised spacing, mobile controls and the official Langfuse logo. Hosted features require a matching Scout deployment; saving Langfuse credentials also requires its dedicated encryption secret. Publishing this package does not deploy or enable the hosted connector.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"format":1,"contract":"scout-recommend-v2","version":"0.3.
|
|
1
|
+
{"format":1,"contract":"scout-recommend-v2","version":"0.3.6","skill":"---\nname: openmerit-scout\ndescription: Consults OpenMerit Scout before choosing, adding, downloading, replacing or configuring any application inference model, including implicit choices while building features, pretrained browser/local models, SDK defaults, embeddings, OCR, speech, classification, detection, segmentation, LLMs and agents. Not for unrelated edits, ordinary inference calls or this coding agent's own model.\n---\n\n# OpenMerit · Scout\n\nBefore introducing, recommending, replacing or configuring an application\ninference model, call the `scout_models` tool on the `openmerit` MCP server.\nThis applies even when the user never mentions models or Scout. Downloading local\nweights, using a pretrained browser model or accepting an SDK default is a model\ndecision: consult Scout before model-specific code, installs or downloads.\nPreserve the user's explicit model choice; assess it rather than silently replacing\nit. Leave unchanged, approved application selections in place.\n\n## Project policy\n\nRead `.openmerit/scout.json` before searching. If it is absent, ask once whether this\nproject uses **existing-only** (only endpoints it can already reach) or\n**existing-first** (prefer them, ask before searching the whole catalogue), and\nwhich public catalogue endpoint IDs it can access. Save the answer:\n\n```sh\nnpx -y openmerit@latest project --policy existing-only --endpoint-id <id> ...\n```\n\nNever infer access from a model name, SDK or environment-variable name. Never\nrecord credentials, private URLs, prompts or customer data. An empty inventory\nis not permission to search all models.\n\n## Searching\n\nCall `scout_models` with a non-confidential task description as `prompt` and\n`endpointIds` set to the saved inventory, including `[]` when empty. Send\nonly task requirements, never source files, secrets or real customer records.\nIf the MCP tool is unavailable, run\n`npx -y openmerit@latest scout \"<task>\" --json`; it applies the saved inventory.\n\nScout is a conversation with the agent behind openmerit.ai/scout. When\n`status` is `needs_answers`, fill in what the user or project already states,\nshow the user Scout's brief and remaining questions, and wait for their answers.\nThen call again with the returned `conversationId` and `brief` set to the\nrewritten components, or `skip: true` if the user wants Scout to assume. Never\nanswer Scout's questions with guesses. Send later refinements to the same\n`conversationId`. A call with only a `conversationId` reads an interrupted turn.\n\nWhen `status` is `recommended`, Scout has split the work into `tasks`, one\nper model, each with up to five ranked `models`; cover every task. Each\nmodel's `cost` names the `endpointId` and `providerModelId` to call.\nExisting-only never broadens. For existing-first, if no existing candidate fits a\ntask, explain the gap and ask before a new conversation without `endpointIds`.\nCompare quality evidence, reference cost/time and watch-outs. Prefer the cheapest\nusable option the evidence supports, without claiming benchmarks prove\napplication accuracy. Use the project's actual SDK and protocol.\n\n## Measuring candidates\n\nEach task also has an `evaluation`: the checks (per model call, agent run or\nend-to-end outcome), labelled examples per candidate and when to stop a losing\ncandidate. Offer to run it before the user commits to a model. Use the evals the\nproject already has, such as datasets and experiments in its eval or tracing\nplatform, or its own eval scripts and fixtures: add the shortlisted candidates as\nextra runs of those evals. Do not build a second eval or copy their datasets.\nIf the project has no eval for the task, propose a minimal one built from its\nexisting traces and the decisions people already make, and create it only where\nand how the user agrees. Ask before spending on model calls or writing to an\neval platform.\n\nReport what you measured with `scout_models`: the same `conversationId` and\n`results`, one aggregate per model and metric (`level`, `task` title, `scope`,\n`model` endpoint or model ID, `metric`, `value`, `higherIsBetter`,\n`samples`, `source`). Set `kind` to `usd` or `seconds` for measured cost\nor time (per call at the task level, per run at the agent level), so Scout uses\nyour cost instead of its estimate. Report each agent's own checks at the agent\nlevel: an end-to-end result also measures the agents you did not swap. Send\naggregates only, never inputs, outputs or records.\nScout ranks them above public benchmarks for this user only; models whose\n`quality.measured` is true rest on them.\n\nSwap one agent at a time, holding the other agents, prompts, fixtures and controls\nfixed. Use each agent's own checks to attribute failures. If all candidates score\n100%, the eval cannot separate their quality: add harder labelled cases before\nclaiming equivalent quality. Cost may break the observed tie, not prove equality.\n\nIf the user has Langfuse, use `openmerit connect langfuse --help`: the web UI is\noptional. Headless setup requires a separate connection-manager approval with\n`openmerit connect langfuse --authorize --no-open`. Relay its approval link and\nexpiry; after approval, rerun that command. Existing recommendation keys cannot\nmanage connections. The user creates a separate Viewer key; receive it through\nprotected stdin or a secret-manager-injected environment, never chat, tool\narguments, shell literals, traced commands or tracked files. The CLI accepts\nnon-secret settings via `--config mappings.json` and reads LANGFUSE_PUBLIC_KEY\nand LANGFUSE_SECRET_KEY from its environment, or reads full settings via --stdin.\nA separate trusted MCP connection with the management key exposes\n`scout_connection` (status/configure/sync/disconnect/clear). For configure, keys\nmust come from client-controlled HTTP headers outside model context; if the\nclient cannot do this securely, use protected CLI input or the web UI instead.\nAfter they confirm connection and score/model mappings, call `scout_models` with\n`sync: \"langfuse\"` to refresh aggregate measurements before recommending. The CLI\nequivalent is `openmerit scout --conversation <id> --sync langfuse`. Never read\ntrace bodies to work around missing mappings or untagged runs; use the aggregate\nreport path instead. Results are stored per user, used in new conversations and\nexpire after 90 days. Disconnect deletes the Viewer key and imported aggregates;\nDelete all evaluation data also deletes manually reported aggregates. Obtain\nconsent before deleting: headless CLI requires --yes, MCP requires confirm: true.\nDeleting the connection does not revoke the separate management device key.\nPast conversation text is not erased. Never put record IDs, emails or secrets in\n`scope` or `source`; use labels such as \"coding agent\" and \"held-out eval\".\n\n## Boundaries\n\nAsk before adding providers or credentials, spending, deploying or external\nwrites. Report recommendation, endpoint connectivity and application checks as\nseparate results, each only after it succeeds. Do not switch this coding agent's\nown model.\n\nIf Scout fails or has no suitable candidate/evidence for the required deployment,\nsay so and pause the model decision; do not substitute a remembered recommendation\nor SDK default. Continue only model-independent work. Local/browser models are not\nexempt when the catalogue lacks coverage. When an install or login waits for approval (exit code\n10), show the user the approval link and its UTC expiry in your reply, not only in\ncommand output, then rerun the same command once they approve. If it reports that the device key is missing,\nexpired or revoked, run `npx -y openmerit@latest login` and then\n`npx -y openmerit@latest install` again. Never ask the user to paste a key.\n","rule":"# Application model decisions · OpenMerit Scout\n\nBefore choosing, recommending, adding, downloading, replacing or configuring\nANY application inference model, load the `openmerit-scout` skill and consult\n`scout_models` on the `openmerit` MCP server before committing to a model.\nThis applies even when the user only asks you to build a feature, never mentions\nmodels or Scout, or names a model themselves (assess it; do not silently replace it).\n\nA pretrained model, local weights, browser inference, an SDK's default model,\nembeddings, OCR, speech, image classification, detection and segmentation all\ncount as model choices, not implementation details. Identify this decision before\nwriting model-specific code, installing a model package or downloading weights.\n\nFollow the skill's project access policy. If it is missing, ask and save it first.\nScout may answer with clarifying questions: relay them to the user and continue\nthe same Scout conversation with their answers before choosing.\nIf Scout is unavailable, fails or has no suitable evidence/candidate, disclose the\ngap and pause the model decision; do not fall back to a remembered or SDK-default\nmodel. You may continue work that does not commit to a model.\n\nDo not consult Scout for unrelated edits, normal inference calls using an unchanged\napproved model, or this coding agent's own model. Do not reselect approved models\nunless the task introduces or changes a model decision.\n\nWhen the user says \"update openmerit\", run\n`npx -y openmerit@latest update --scope user` (use `--scope project` if this\nrule is in the project's .claude/rules directory). Report the result, including\nany conflict or manual-upgrade requirement. Do not delete edited files, bypass\npermissions or rerun login automatically. A new session loads updated instructions.\n"}
|
|
@@ -19,7 +19,8 @@ Rerun --authorize if pending (exit 10). This never replaces recommendation keys.
|
|
|
19
19
|
The management key is saved separately with owner-only file permissions.
|
|
20
20
|
|
|
21
21
|
--config reads non-secret region, from (YYYY-MM-DD), tagPrefix, mappings and models.
|
|
22
|
-
|
|
22
|
+
For a new connection, supply LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY through
|
|
23
|
+
a secret manager. Omit both to update settings using the saved Viewer key.
|
|
23
24
|
--stdin reads the full JSON settings including the Viewer key pair from a protected
|
|
24
25
|
pipe (maximum 18 KB), never echoes them, and does not save them locally.
|
|
25
26
|
Never put keys in arguments, chat, shell history or a tracked file. Use a separate
|
|
@@ -67,6 +68,11 @@ async function settings(file, stdin, root) {
|
|
|
67
68
|
throw new Error('Use non-secret settings in --config; credentials must come from a secret manager or --stdin.');
|
|
68
69
|
if (!stdin)
|
|
69
70
|
config = { ...config, publicKey: process.env.LANGFUSE_PUBLIC_KEY, secretKey: process.env.LANGFUSE_SECRET_KEY };
|
|
71
|
+
if (object(config) && !stdin && config.publicKey === undefined && config.secretKey === undefined) {
|
|
72
|
+
delete config.publicKey;
|
|
73
|
+
delete config.secretKey;
|
|
74
|
+
return config;
|
|
75
|
+
}
|
|
70
76
|
if (!object(config) || typeof config.publicKey !== 'string' || typeof config.secretKey !== 'string' || !config.publicKey || !config.secretKey)
|
|
71
77
|
throw new Error('Supply a separate Viewer key pair through a secret manager or --stdin.');
|
|
72
78
|
return config;
|
|
@@ -139,7 +145,7 @@ export async function connection(args, { root = process.cwd(), print = console.l
|
|
|
139
145
|
const value = await response.json();
|
|
140
146
|
if (!object(value))
|
|
141
147
|
throw new Error('OpenMerit returned an invalid connection response.');
|
|
142
|
-
const state = Object.fromEntries(Object.entries(value).filter(([name]) => ['connected', 'connectedAt', 'syncedAt', 'experiments', 'unmapped', 'results', 'busy', 'cached', 'deleted'].includes(name)));
|
|
148
|
+
const state = Object.fromEntries(Object.entries(value).filter(([name]) => ['connected', 'connectedAt', 'syncedAt', 'mappingCount', 'modelAliasCount', 'experiments', 'unmapped', 'results', 'busy', 'cached', 'deleted'].includes(name)));
|
|
143
149
|
print(JSON.stringify(state, null, 2));
|
|
144
150
|
return 0;
|
|
145
151
|
}
|
package/docs/scout-close-loop.md
CHANGED
|
@@ -77,8 +77,10 @@ not promise that Scout stores or processes your data in that region.
|
|
|
77
77
|
|
|
78
78
|
You can connect the key first with empty mappings. To import results, expand
|
|
79
79
|
**Score and model mappings** and supply a start date, experiment-tag prefix,
|
|
80
|
-
score mappings and model aliases.
|
|
81
|
-
|
|
80
|
+
score mappings and model aliases. In npm 0.3.6 with the matching Scout deployment,
|
|
81
|
+
the headless paths below can update settings without re-entering the saved Viewer
|
|
82
|
+
key. Changing settings invalidates old imports; sync again afterwards. Reported
|
|
83
|
+
results remain. Older deployments require disconnecting and reconnecting.
|
|
82
84
|
|
|
83
85
|
### Headless CLI setup
|
|
84
86
|
|
|
@@ -124,6 +126,14 @@ openmerit connect langfuse --status
|
|
|
124
126
|
openmerit connect langfuse --sync
|
|
125
127
|
```
|
|
126
128
|
|
|
129
|
+
**Updating an existing connection (npm 0.3.6 and matching deployment):** edit the
|
|
130
|
+
non-secret settings file and run the same `--config` command with both
|
|
131
|
+
`LANGFUSE_PUBLIC_KEY` and `LANGFUSE_SECRET_KEY` absent. Scout reuses and reverifies
|
|
132
|
+
the encrypted Viewer key internally; neither CLI nor model receives it. One key
|
|
133
|
+
without the other is rejected. Without a connected key, first connect through a
|
|
134
|
+
protected credential path. Settings changes remove prior imports, not reported
|
|
135
|
+
results, and require a new sync.
|
|
136
|
+
|
|
127
137
|
Alternatively, `openmerit connect langfuse --stdin` reads a full JSON object with
|
|
128
138
|
the same settings plus `publicKey` and `secretKey` from a protected pipe, up to
|
|
129
139
|
18 KB. It does not echo or save the Viewer credentials locally. Do not use inline
|
|
@@ -155,6 +165,12 @@ records these headers. If your MCP client cannot securely inject headers outside
|
|
|
155
165
|
model context, have the agent invoke the CLI with protected input instead, or
|
|
156
166
|
use the web UI; do not fall back to putting credentials in tool arguments.
|
|
157
167
|
|
|
168
|
+
On the matching 0.3.6 deployment, omit both Viewer headers to update an existing
|
|
169
|
+
connection using its saved encrypted key. A new connection still needs both.
|
|
170
|
+
The authenticated HTTP POST similarly accepts non-secret settings without either
|
|
171
|
+
key field for an existing connection. The saved key is never exported. Settings
|
|
172
|
+
changes reverify Viewer access and invalidate imported results before a new sync.
|
|
173
|
+
|
|
158
174
|
```json
|
|
159
175
|
{"action": "configure", "config": {"region": "us", "from": "2026-11-01", "tagPrefix": "experiment:", "mappings": [], "models": {}}}
|
|
160
176
|
```
|
|
@@ -219,8 +235,9 @@ read per sync. Narrow the date if a response or import exceeds its limit. Only
|
|
|
219
235
|
experiment headers/metadata and aggregate Metrics v2 reads are requested. A
|
|
220
236
|
deliberately invalid dataset-create request checks read-only permission without
|
|
221
237
|
ever sending a valid write payload. Only an authenticated read followed by HTTP
|
|
222
|
-
403 on that probe is accepted; other responses fail closed.
|
|
223
|
-
acceptance
|
|
238
|
+
403 on that probe is accepted; other responses fail closed. Live Viewer-key
|
|
239
|
+
connection acceptance was verified on 6 November 2026; fresh mapped aggregate
|
|
240
|
+
import and reranking remain separate release checks.
|
|
224
241
|
|
|
225
242
|
Click **Sync aggregates**, or request a fresh recommendation with:
|
|
226
243
|
|
|
@@ -233,6 +250,26 @@ failed read cannot be retried for one minute. A failed import leaves the previou
|
|
|
233
250
|
complete set intact. `conversationId` alone reads a saved answer, not a rerank;
|
|
234
251
|
send a follow-up or `sync` to recompute with the current results.
|
|
235
252
|
|
|
253
|
+
### When a sync imports zero aggregates
|
|
254
|
+
|
|
255
|
+
A connected Viewer key and a successful experiment read do not establish that
|
|
256
|
+
score import is configured. Empty mappings are allowed when first connecting.
|
|
257
|
+
Before repeating sync, check the score mappings and model aliases, then check
|
|
258
|
+
that scored traces carry the exact experiment tag, trace name and metric name
|
|
259
|
+
in those mappings. Merely linking a trace through Langfuse's native experiment
|
|
260
|
+
attributes does not add the explicit experiment tag required by this connector.
|
|
261
|
+
Do not remove the tag filter to make an import nonempty: that can combine scores
|
|
262
|
+
from different models or runs. Untagged historical results need attributable
|
|
263
|
+
aggregate reporting or a separately approved, verified tagging backfill.
|
|
264
|
+
|
|
265
|
+
**Diagnostic version requirement:** a matching Scout serving deployment adds
|
|
266
|
+
`mappingCount` and `modelAliasCount` to connection status, without returning the
|
|
267
|
+
saved keys or mapping values. The web page distinguishes a connected key from
|
|
268
|
+
incomplete setup and warns when a sync imports no matching scores. npm 0.3.5
|
|
269
|
+
does not display these new counts; use authenticated API/MCP status until a
|
|
270
|
+
matching CLI patch is published. These counts diagnose missing configuration,
|
|
271
|
+
not whether matching scores exist or whether a model improves quality.
|
|
272
|
+
|
|
236
273
|
## Choose and delete
|
|
237
274
|
|
|
238
275
|
Check measured quality, the quality floor, price calibration and limitations
|
package/docs/security.md
CHANGED
|
@@ -12,14 +12,15 @@ OpenMerit accepts no model-provider or Jev credential. Credentials belong to the
|
|
|
12
12
|
|
|
13
13
|
Never place secrets in evaluation configuration, task fixtures, Scout project policy, traces, or committed environment files.
|
|
14
14
|
|
|
15
|
-
### Langfuse connector
|
|
15
|
+
### Langfuse connector
|
|
16
16
|
|
|
17
|
-
The [connection guide](scout-close-loop.md#connect-langfuse)
|
|
18
|
-
|
|
17
|
+
The [connection guide](scout-close-loop.md#connect-langfuse) requires npm 0.3.5
|
|
18
|
+
and the matching hosted deployment. Only a separate
|
|
19
19
|
Viewer key pair is accepted. A successful read plus a deliberately invalid
|
|
20
20
|
dataset-create permission probe (HTTP 403 required) fails closed for Full keys;
|
|
21
|
-
no valid write payload is sent.
|
|
22
|
-
|
|
21
|
+
no valid write payload is sent. Live Viewer connection acceptance was verified
|
|
22
|
+
on 6 November 2026; fresh mapped import/reranking remain separate release gates.
|
|
23
|
+
Fixed US/EU/HIPAA hosts, manual redirects, timeouts and bounded reads
|
|
23
24
|
prevent credential forwarding and unbounded response bodies. The connector reads
|
|
24
25
|
only experiment headers/metadata and aggregate Metrics v2 values, never trace,
|
|
25
26
|
observation, experiment-item or raw-score bodies. Extra metadata fields are
|
|
@@ -29,6 +30,10 @@ Credentials and mappings are AES-GCM encrypted in one Cloudflare Durable Object
|
|
|
29
30
|
per authenticated user, bound to that object's ID with a dedicated Worker secret.
|
|
30
31
|
Keys never enter browser storage, URLs or analytics. Keep that encryption secret
|
|
31
32
|
stable: replacing it invalidates stored connections and requires reconnecting.
|
|
33
|
+
With npm 0.3.6 and the matching deployment, authenticated settings-only updates
|
|
34
|
+
reuse and reverify the saved encrypted key without exporting it. Supplying a
|
|
35
|
+
partial key pair fails; first connection still requires a protected Viewer pair.
|
|
36
|
+
Changing settings invalidates imported aggregates and requires syncing again.
|
|
32
37
|
Disconnect deletes the key and imported aggregates; deleting all evaluation data
|
|
33
38
|
also deletes reported aggregates. Neither erases conversation text. Retention,
|
|
34
39
|
limits and processor caveats are in the [data policy](scout-data-policy.md).
|