@wrongstack/cli 1.0.19 → 1.0.24
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/dist/{acp-INCNOH42.js → acp-AJWSKWE5.js} +18 -7
- package/dist/arg-parser.d.ts +1 -0
- package/dist/{auth-YXK3EDUL.js → auth-GRBZ7Y3D.js} +61 -15
- package/dist/auth-menu/direct.d.ts +1 -0
- package/dist/auth-menu/local.d.ts +2 -0
- package/dist/auth-menu/oauth-menu.d.ts +3 -1
- package/dist/auth-menu/panel-service.d.ts +20 -0
- package/dist/{bench-YBU6BVQP.js → bench-N5K7Z5O3.js} +2 -2
- package/dist/boot/config-backup-recovery.d.ts +2 -1
- package/dist/boot/dispatch-webui.d.ts +11 -0
- package/dist/boot/short-circuit-desktop.d.ts +1 -0
- package/dist/boot/tui-project-picker-callback.d.ts +1 -1
- package/dist/boot/tui-settings-adapter.d.ts +15 -2
- package/dist/{boot-auto-thin-MANHOYHE.js → boot-auto-thin-6Q56FY3F.js} +3 -2
- package/dist/{chunk-6WRKAACA.js → chunk-2BKFWIER.js} +4 -2
- package/dist/{chunk-JY52HWL6.js → chunk-2EBVTYJR.js} +2 -2
- package/dist/chunk-3OCUS3VN.js +46 -0
- package/dist/chunk-424ORSE7.js +56 -0
- package/dist/{chunk-KEPABQYT.js → chunk-5SEYGOCH.js} +8 -82
- package/dist/chunk-BBHWW6LR.js +549 -0
- package/dist/{chunk-CJTBLTS4.js → chunk-BLD5DSVA.js} +4 -3
- package/dist/{chunk-KK2LB3ZS.js → chunk-DRM7PSW7.js} +9 -5
- package/dist/{chunk-XJ7K67PP.js → chunk-JF2MULWF.js} +17 -10
- package/dist/{chunk-SIS37L3W.js → chunk-L2RVEQWO.js} +211 -193
- package/dist/{chunk-RDHFXOJM.js → chunk-LFMVHT3R.js} +106 -57
- package/dist/chunk-LUMETJFO.js +171 -0
- package/dist/{chunk-C3Z4N6A6.js → chunk-MHEBWVXL.js} +6 -2
- package/dist/{chunk-2ENZU66X.js → chunk-PGKJ2OQP.js} +5 -5
- package/dist/{chunk-672UXYL3.js → chunk-QBBF7GIK.js} +2 -2
- package/dist/{chunk-DE7BZDNK.js → chunk-QFPQXKCG.js} +11 -3
- package/dist/chunk-R4QGL6GB.js +10 -0
- package/dist/chunk-S4FFHDJG.js +93 -0
- package/dist/chunk-SFBFYIOW.js +271 -0
- package/dist/{chunk-JX6KL7OF.js → chunk-SKPDE62W.js} +4 -3
- package/dist/{chunk-RMQNCHGO.js → chunk-U46QR4WR.js} +5 -9
- package/dist/{chunk-B4JLSXZB.js → chunk-WSTVGC2C.js} +73 -45
- package/dist/chunk-YBUCXXYZ.js +36 -0
- package/dist/{chunk-2VMJ3E5Z.js → chunk-YTEOAWOJ.js} +6 -2
- package/dist/{chunk-GPPRNAKW.js → chunk-ZMX5HRLI.js} +2 -2
- package/dist/{chunk-YLQEGYV4.js → chunk-ZZRSG7VK.js} +14 -4
- package/dist/{cli-context-33F74CSZ.js → cli-context-34Q5IJRA.js} +121 -89
- package/dist/cli-entry-point.d.ts +2 -0
- package/dist/{cli-main-FNGMKPBA.js → cli-main-AELJDBGU.js} +1439 -1276
- package/dist/config-doctor.d.ts +10 -2
- package/dist/{config-transfer-2YF3CRTN.js → config-transfer-RUWLDCNK.js} +34 -13
- package/dist/{diag-doctor-ANPRUYFM.js → diag-doctor-WIFJH3XH.js} +2 -2
- package/dist/execute-deps.d.ts +2 -1
- package/dist/{execution-A6WJLSOC.js → execution-PYC5FCS4.js} +303 -256
- package/dist/{hq-XQWQTRDA.js → hq-JTUTFI4L.js} +274 -258
- package/dist/hq-command-controller.d.ts +1 -1
- package/dist/{hq-server-IIBZQZU4.js → hq-server-PC7GZMPT.js} +2 -2
- package/dist/{hq-service-L5INQFM4.js → hq-service-NW56MUP2.js} +11 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -12
- package/dist/kanban-supervisor-67ECABTD.js +7 -0
- package/dist/live-settings-input.d.ts +7 -0
- package/dist/{mailbox-serve-3GFOK2I7.js → mailbox-serve-WDOCH6KR.js} +3 -3
- package/dist/{mcp-DC5WSBOO.js → mcp-LBS45HWZ.js} +4 -4
- package/dist/modeldiag-36OGAL5C.js +828 -0
- package/dist/{per-subcommand-help-DHTYU524.js → per-subcommand-help-XE77MTGJ.js} +3 -3
- package/dist/permission-prompt-mirror.d.ts +1 -1
- package/dist/permission-prompt.d.ts +2 -2
- package/dist/plugin-config.d.ts +12 -0
- package/dist/plugin-management-types.d.ts +31 -0
- package/dist/plugin-management.d.ts +2 -30
- package/dist/plugin-package-install.d.ts +3 -0
- package/dist/{plugin-usage-M6KET4OZ.js → plugin-usage-S5LVGMBW.js} +6 -5
- package/dist/{plugins-WJLW6ULV.js → plugins-RHBIVLI7.js} +4 -3
- package/dist/provider-config-utils.d.ts +1 -6
- package/dist/{providers-models-LFNZ5WI7.js → providers-models-2CFG46RD.js} +41 -31
- package/dist/release-asset-download.d.ts +3 -0
- package/dist/services/dispatch-classifier.d.ts +39 -5
- package/dist/{sessions-config-UL45XKX7.js → sessions-config-IQUH2GXT.js} +13 -5
- package/dist/settings-menu.d.ts +2 -0
- package/dist/short-circuit-flags-SDT53OML.js +10 -0
- package/dist/{simpleui-dist-CXSIDAXZ.js → simpleui-dist-7BQISSEP.js} +7 -3
- package/dist/skill-suggest-L2EVWB6R.js +290 -0
- package/dist/slash-commands/effort.d.ts +1 -1
- package/dist/slash-commands/fallback.d.ts +1 -1
- package/dist/slash-commands/gitid.d.ts +1 -1
- package/dist/slash-commands/jev.d.ts +4 -0
- package/dist/slash-commands/openai-quota.d.ts +15 -0
- package/dist/slash-commands/sdd-task-mutations.d.ts +4 -0
- package/dist/slash-commands/settings-keys.d.ts +2 -0
- package/dist/slash-commands/settings-reset.d.ts +6 -0
- package/dist/standalone-update-MW47J3AK.js +164 -0
- package/dist/standalone-update.d.ts +19 -0
- package/dist/subcommands/handlers/hq-alerts.d.ts +3 -0
- package/dist/subcommands/handlers/hq-audit.d.ts +46 -0
- package/dist/subcommands/handlers/hq-data-dir.d.ts +13 -0
- package/dist/subcommands/handlers/skill-suggest.d.ts +21 -0
- package/dist/subcommands/handlers/typesafe-brain-replay.d.ts +26 -0
- package/dist/subcommands/handlers/typesafe-judgment-check.d.ts +3 -0
- package/dist/subcommands/handlers/typesafe-topic-replay.d.ts +19 -0
- package/dist/subcommands/handlers/typesafe-triage-replay.d.ts +18 -0
- package/dist/subcommands/handlers/typesafe.d.ts +23 -0
- package/dist/{subcommands-XSLXMIDP.js → subcommands-ZTSIN7LG.js} +2 -2
- package/dist/typesafe-HVEVPA6R.js +316 -0
- package/dist/typesafe-brain-replay-C5276FVR.js +222 -0
- package/dist/typesafe-judgment-check-GGYYV5UF.js +29 -0
- package/dist/typesafe-topic-replay-4W73BOLV.js +218 -0
- package/dist/typesafe-triage-replay-FGAW7QM7.js +215 -0
- package/dist/{update-5DPB4YD4.js → update-7XIOEXTD.js} +4 -3
- package/dist/{update-check-BS3DHTSI.js → update-check-2POMBHFB.js} +3 -2
- package/dist/update-check.d.ts +1 -1
- package/dist/version-help-WZ623NWM.js +10 -0
- package/dist/version.d.ts +3 -2
- package/dist/webui-client-observability.d.ts +7 -0
- package/dist/{webui-server-MRPGTTKL.js → webui-server-L2SICPTB.js} +158 -94
- package/dist/webui-server-options.d.ts +11 -0
- package/dist/webui-server.d.ts +15 -1
- package/dist/wiring/domain-glossary.d.ts +5 -4
- package/dist/wiring/plugins.d.ts +1 -1
- package/dist/wiring/provider-persisters.d.ts +24 -0
- package/dist/wiring/provider-runtime.d.ts +9 -1
- package/dist/wiring/runtime-dispatch-state.d.ts +3 -1
- package/package.json +28 -28
- package/dist/chunk-2CZEORLV.js +0 -54
- package/dist/chunk-DR2OXU46.js +0 -174
- package/dist/chunk-JACOMTIH.js +0 -275
- package/dist/chunk-XJXDOF63.js +0 -28
- package/dist/modeldiag-CJSFHZ3J.js +0 -1356
- package/dist/short-circuit-flags-7GQIGMVD.js +0 -10
- package/dist/version-help-WXI42PZ3.js +0 -10
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `wstack typesafe replay-topic-shift` — calibrate the topic-shift front on
|
|
3
|
+
* this project's own sessions.
|
|
4
|
+
*
|
|
5
|
+
* Session journals record every user prompt (`user_input`) and every message
|
|
6
|
+
* appended to the conversation, so the history the advisor saw at each prompt
|
|
7
|
+
* can be rebuilt. Each prompt is replayed through the real `TopicShiftAdvisor`
|
|
8
|
+
* twice — once with only the TypeSafe judge, once with only the configured
|
|
9
|
+
* provider (the path it has always had, with its production request) — and only
|
|
10
|
+
* prompts that pass the advisor's own local gate are counted, because the
|
|
11
|
+
* rest never reach a classifier in production either.
|
|
12
|
+
*
|
|
13
|
+
* Reported: how often each classifier answers at all, what it answers, and
|
|
14
|
+
* how the two agree where Jev is decisive. `--json` includes the prompt and
|
|
15
|
+
* the previous user prompt for hand-labelling. Nothing is written.
|
|
16
|
+
*/
|
|
17
|
+
import type { SubcommandDeps } from '../contracts.js';
|
|
18
|
+
export declare function replayTopicShift(deps: SubcommandDeps, write: (line: string) => void): Promise<number>;
|
|
19
|
+
//# sourceMappingURL=typesafe-topic-replay.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `wstack typesafe replay-memory-triage` — calibrate the triage front on this
|
|
3
|
+
* project's own memories.
|
|
4
|
+
*
|
|
5
|
+
* Opens the project's SAGE database READ-ONLY, runs the deterministic Phases
|
|
6
|
+
* 1–2 exactly as `/memory triage` does to find the gray zone, samples it, and
|
|
7
|
+
* asks both Jev (`probeMemoryValue`, raw distribution) and the configured LLM
|
|
8
|
+
* (the same prompt and parser `/memory triage` uses) for a 1–5 rating.
|
|
9
|
+
*
|
|
10
|
+
* The report compares them on the rating and — what actually matters — on the
|
|
11
|
+
* triage ACTION each rating would cause (keep / stale / propose archive),
|
|
12
|
+
* overall and for the subset the front would settle at each confidence
|
|
13
|
+
* threshold. The LLM is the reference, not ground truth; `--no-llm` skips it
|
|
14
|
+
* and reports Jev's distribution alone. Nothing is written anywhere.
|
|
15
|
+
*/
|
|
16
|
+
import type { SubcommandDeps } from '../contracts.js';
|
|
17
|
+
export declare function replayMemoryTriage(deps: SubcommandDeps, write: (line: string) => void): Promise<number>;
|
|
18
|
+
//# sourceMappingURL=typesafe-triage-replay.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `wstack typesafe` — the account surface for the System One features.
|
|
3
|
+
*
|
|
4
|
+
* TypeSafe is not a provider and deliberately does not appear in `wstack auth`:
|
|
5
|
+
* it answers typed questions rather than generating text, so putting it in the
|
|
6
|
+
* provider list would leak `jev-latest` into the model picker, the subagent
|
|
7
|
+
* lanes and the fallback chain, where selecting it would simply break a turn.
|
|
8
|
+
* But "not a provider" is not "not an account" — it has a credential, a host
|
|
9
|
+
* and a bill, and until this command existed the only way to configure any of
|
|
10
|
+
* that was to hand-edit a config file. Nothing in any UI mentioned it.
|
|
11
|
+
*
|
|
12
|
+
* wstack typesafe what is configured (no network request)
|
|
13
|
+
* wstack typesafe login store a key (and pick a route)
|
|
14
|
+
* wstack typesafe test spend one cheap question proving it works
|
|
15
|
+
*
|
|
16
|
+
* `test` is the point of the whole command. Both consumers degrade silently by
|
|
17
|
+
* design, so a wrong or revoked key produces no error anywhere — it produces
|
|
18
|
+
* slightly worse routing and no skill suggestions, forever. This is the only
|
|
19
|
+
* place that asks the host directly and reports what it said.
|
|
20
|
+
*/
|
|
21
|
+
import type { SubcommandHandler } from '../contracts.js';
|
|
22
|
+
export declare const typesafeCmd: SubcommandHandler;
|
|
23
|
+
//# sourceMappingURL=typesafe.d.ts.map
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import {
|
|
2
|
+
activeProfileConfigPath
|
|
3
|
+
} from "./chunk-YMXXOOFN.js";
|
|
4
|
+
import {
|
|
5
|
+
maskedKey,
|
|
6
|
+
mutateConfigProviders
|
|
7
|
+
} from "./chunk-LUMETJFO.js";
|
|
8
|
+
|
|
9
|
+
// src/subcommands/handlers/typesafe.ts
|
|
10
|
+
import { execFile } from "node:child_process";
|
|
11
|
+
import { readFile } from "node:fs/promises";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
import {
|
|
14
|
+
BUILT_IN_ROUTES,
|
|
15
|
+
BUILT_IN_SEMANTIC_LINT_RULES,
|
|
16
|
+
estimateTypeSafeCostUsd,
|
|
17
|
+
findSemanticLintCandidates,
|
|
18
|
+
isTypeSafeJudgmentEnabled,
|
|
19
|
+
isTypeSafeRoute,
|
|
20
|
+
judgeSemanticLintCandidates,
|
|
21
|
+
parseSemanticLintRules,
|
|
22
|
+
resolveTypeSafeAccount,
|
|
23
|
+
resolveTypeSafeJudge,
|
|
24
|
+
resolveTypeSafeRoute,
|
|
25
|
+
TYPESAFE_JUDGMENT_FEATURES,
|
|
26
|
+
TYPESAFE_ROUTES
|
|
27
|
+
} from "@wrongstack/core/typesafe";
|
|
28
|
+
import { buildChildEnv, color } from "@wrongstack/core/utils";
|
|
29
|
+
var USAGE = [
|
|
30
|
+
"Usage:",
|
|
31
|
+
" wstack typesafe [status] show account and feature configuration",
|
|
32
|
+
" wstack typesafe login [--route <id>] store an API key in the active profile",
|
|
33
|
+
" [--endpoint <url>] [--model <id>] configure a proxy or pin a model",
|
|
34
|
+
" wstack typesafe test send one question and report the answer",
|
|
35
|
+
" wstack typesafe lint-conventions judge convention-rule hits in the diff",
|
|
36
|
+
" [--staged | --base <ref>] [--threshold <0..1>] [--json]",
|
|
37
|
+
" rules: built-in + .wrongstack/semantic-lint.json; exit 1 on findings",
|
|
38
|
+
" wstack typesafe check-judgments run every judgment on known cases (live)",
|
|
39
|
+
" wstack typesafe replay-brain-ledger compare Jev with past Brain decisions",
|
|
40
|
+
" [--ledger <path>] [--limit <per kind>] [--kind <signal>] [--json]",
|
|
41
|
+
" wstack typesafe replay-topic-shift compare Jev with the provider on past session prompts",
|
|
42
|
+
" [--sessions <dir>] [--limit <n>] [--max-context <n>] [--no-llm] [--json]",
|
|
43
|
+
" wstack typesafe replay-memory-triage compare Jev with the LLM on SAGE gray-zone memories",
|
|
44
|
+
" [--limit <n>] [--provider <id>] [--model <id>] [--llm-max-tokens <n>]",
|
|
45
|
+
" [--no-llm] [--json]",
|
|
46
|
+
"",
|
|
47
|
+
`Routes: ${BUILT_IN_ROUTES.map((r) => `${r} (${TYPESAFE_ROUTES[r].env})`).join(", ")}, custom (typesafe.endpoint)`,
|
|
48
|
+
"",
|
|
49
|
+
"TypeSafe is not a chat provider and is not listed by `wstack auth`."
|
|
50
|
+
].join("\n");
|
|
51
|
+
var typesafeCmd = async (args, deps) => {
|
|
52
|
+
const write = (line) => deps.renderer.write(`${line}
|
|
53
|
+
`);
|
|
54
|
+
const flags = deps.flags ?? {};
|
|
55
|
+
if (flags["help"] === true || flags["h"] === true) {
|
|
56
|
+
write(USAGE);
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
const sub = (args[0] ?? "status").toLowerCase();
|
|
60
|
+
switch (sub) {
|
|
61
|
+
case "status":
|
|
62
|
+
return showStatus(deps, write);
|
|
63
|
+
case "login":
|
|
64
|
+
return await login(deps, write);
|
|
65
|
+
case "test":
|
|
66
|
+
return await test(deps, write);
|
|
67
|
+
case "lint-conventions":
|
|
68
|
+
return await lintConventions(deps, write);
|
|
69
|
+
case "replay-topic-shift":
|
|
70
|
+
return await (await import("./typesafe-topic-replay-4W73BOLV.js")).replayTopicShift(deps, write);
|
|
71
|
+
case "replay-memory-triage":
|
|
72
|
+
return await (await import("./typesafe-triage-replay-FGAW7QM7.js")).replayMemoryTriage(deps, write);
|
|
73
|
+
case "replay-brain-ledger":
|
|
74
|
+
return await (await import("./typesafe-brain-replay-C5276FVR.js")).replayBrainLedger(deps, write);
|
|
75
|
+
case "check-judgments":
|
|
76
|
+
return await (await import("./typesafe-judgment-check-GGYYV5UF.js")).checkJudgments(deps, write);
|
|
77
|
+
default:
|
|
78
|
+
write(`Unknown subcommand: ${sub}
|
|
79
|
+
`);
|
|
80
|
+
write(USAGE);
|
|
81
|
+
return 1;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
function requestedFeatures(deps) {
|
|
85
|
+
const requested = [];
|
|
86
|
+
if (deps.config.skills?.suggest?.enabled === true) requested.push("skills.suggest");
|
|
87
|
+
if (deps.config.fleet?.dispatch?.typesafeClassifier === true) {
|
|
88
|
+
requested.push("fleet.dispatch.typesafeClassifier");
|
|
89
|
+
}
|
|
90
|
+
return requested;
|
|
91
|
+
}
|
|
92
|
+
function showStatus(deps, write) {
|
|
93
|
+
const account = resolveTypeSafeAccount({ config: deps.config });
|
|
94
|
+
const route = resolveTypeSafeRoute(deps.config, process.env);
|
|
95
|
+
const features = requestedFeatures(deps);
|
|
96
|
+
write(color.bold("TypeSafe account"));
|
|
97
|
+
write(` route ${route}${route === "custom" ? color.dim(" (from typesafe.endpoint)") : ""}`);
|
|
98
|
+
if (account.status === "ready") {
|
|
99
|
+
write(` endpoint ${account.endpoint}`);
|
|
100
|
+
write(` model ${account.model}`);
|
|
101
|
+
write(
|
|
102
|
+
` key ${account.keySource === "config" ? `${maskedKey(deps.config.typesafe?.apiKey ?? "")} ${color.dim("(typesafe.apiKey)")}` : color.dim(`from $${account.keyEnv}`)}`
|
|
103
|
+
);
|
|
104
|
+
write(" connection not tested \u2014 run `wstack typesafe test` to verify");
|
|
105
|
+
} else {
|
|
106
|
+
write(` key ${color.dim("\u2014")}`);
|
|
107
|
+
write(` ${color.amber("!")} ${account.reason}`);
|
|
108
|
+
}
|
|
109
|
+
write("");
|
|
110
|
+
write(
|
|
111
|
+
color.bold("Judgments") + color.dim(" (on with an account; typesafe.judgments.<id>: false turns one off)")
|
|
112
|
+
);
|
|
113
|
+
for (const feature of TYPESAFE_JUDGMENT_FEATURES) {
|
|
114
|
+
const on = isTypeSafeJudgmentEnabled(deps.config, feature);
|
|
115
|
+
write(
|
|
116
|
+
` ${!on ? color.dim("off") : account.status === "ready" ? color.green("on ") : color.dim("idle")} ${feature}`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
write("");
|
|
120
|
+
write(color.bold("Features"));
|
|
121
|
+
if (features.length === 0) {
|
|
122
|
+
write(` ${color.dim("none enabled")} \u2014 see docs/skills-suggestion.md`);
|
|
123
|
+
} else {
|
|
124
|
+
for (const feature of features) {
|
|
125
|
+
write(
|
|
126
|
+
account.status === "ready" ? ` ${color.green("on")} ${feature}` : ` ${color.amber("on, but not running")} ${feature}`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (account.status !== "ready" && features.length > 0) {
|
|
131
|
+
write("");
|
|
132
|
+
write(` ${color.amber("Run `wstack typesafe login` \u2014 these switches do nothing today.")}`);
|
|
133
|
+
return 1;
|
|
134
|
+
}
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
async function login(deps, write) {
|
|
138
|
+
const flags = deps.flags ?? {};
|
|
139
|
+
for (const name of ["route", "endpoint", "model", "key"]) {
|
|
140
|
+
if (flags[name] !== void 0 && (typeof flags[name] !== "string" || !String(flags[name]).trim())) {
|
|
141
|
+
write(`--${name} requires a value.`);
|
|
142
|
+
return 1;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const requested = flags["route"];
|
|
146
|
+
let route;
|
|
147
|
+
if (typeof requested === "string") {
|
|
148
|
+
if (!isTypeSafeRoute(requested)) {
|
|
149
|
+
write(`Unknown route: ${requested}`);
|
|
150
|
+
write(USAGE);
|
|
151
|
+
return 1;
|
|
152
|
+
}
|
|
153
|
+
route = requested;
|
|
154
|
+
}
|
|
155
|
+
const endpoint = typeof flags["endpoint"] === "string" ? flags["endpoint"].trim() : void 0;
|
|
156
|
+
const model = typeof flags["model"] === "string" ? flags["model"].trim() : void 0;
|
|
157
|
+
if (endpoint && !route) route = "custom";
|
|
158
|
+
const update = (existing) => {
|
|
159
|
+
const next = { ...existing };
|
|
160
|
+
if (route && route !== resolveTypeSafeRoute({ typesafe: existing }, {})) {
|
|
161
|
+
delete next.endpoint;
|
|
162
|
+
delete next.model;
|
|
163
|
+
}
|
|
164
|
+
if (route) next.route = route;
|
|
165
|
+
if (endpoint) next.endpoint = endpoint;
|
|
166
|
+
if (model) next.model = model;
|
|
167
|
+
return next;
|
|
168
|
+
};
|
|
169
|
+
const settings = update(deps.config.typesafe ?? {});
|
|
170
|
+
const preview = resolveTypeSafeAccount({ config: { typesafe: settings }, env: {} });
|
|
171
|
+
if (preview.status === "unusable") {
|
|
172
|
+
write(`${preview.reason}. For a custom route, pass --endpoint <url>.`);
|
|
173
|
+
return 1;
|
|
174
|
+
}
|
|
175
|
+
const effectiveRoute = resolveTypeSafeRoute({ typesafe: settings }, {});
|
|
176
|
+
const label = effectiveRoute !== "custom" ? TYPESAFE_ROUTES[effectiveRoute].label : "TypeSafe (custom)";
|
|
177
|
+
const fromFlag = typeof flags["key"] === "string" ? flags["key"].trim() : "";
|
|
178
|
+
const key = fromFlag || await deps.reader.readSecret(` ${color.amber("?")} ${label} API key: `);
|
|
179
|
+
if (!key.trim()) {
|
|
180
|
+
write("No key entered; nothing written.");
|
|
181
|
+
return 1;
|
|
182
|
+
}
|
|
183
|
+
const configPath = activeProfileConfigPath(deps.paths, deps.config);
|
|
184
|
+
await mutateConfigProviders(configPath, deps.vault, (_providers, config) => {
|
|
185
|
+
const existing = typeof config["typesafe"] === "object" && config["typesafe"] !== null ? config["typesafe"] : {};
|
|
186
|
+
config["typesafe"] = { ...update(existing), apiKey: key.trim() };
|
|
187
|
+
});
|
|
188
|
+
write(`${color.green("\u2713")} Key stored in ${configPath}`);
|
|
189
|
+
if (route) write(` route set to ${route}`);
|
|
190
|
+
write(` Verify it with ${color.bold("wstack typesafe test")}.`);
|
|
191
|
+
return 0;
|
|
192
|
+
}
|
|
193
|
+
async function test(deps, write) {
|
|
194
|
+
const account = resolveTypeSafeAccount({ config: deps.config, restGate: null });
|
|
195
|
+
if (account.status !== "ready") {
|
|
196
|
+
write(`${color.red("\u2717")} ${account.reason}`);
|
|
197
|
+
write(" Run `wstack typesafe login`.");
|
|
198
|
+
return 1;
|
|
199
|
+
}
|
|
200
|
+
write(`Asking ${account.endpoint} (${account.model})\u2026`);
|
|
201
|
+
const started = Date.now();
|
|
202
|
+
try {
|
|
203
|
+
const result = await account.client.systemOne({
|
|
204
|
+
state: { text: "The service returned this request successfully." },
|
|
205
|
+
questions: {
|
|
206
|
+
reachable: {
|
|
207
|
+
type: "noul",
|
|
208
|
+
instructions: "Is the text in the state written in English?"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
const answer = result.answers["reachable"];
|
|
213
|
+
const elapsed = Date.now() - started;
|
|
214
|
+
if (answer?.type !== "noul") {
|
|
215
|
+
write(`${color.red("\u2717")} Reached the host but the answer was missing or malformed.`);
|
|
216
|
+
return 1;
|
|
217
|
+
}
|
|
218
|
+
write(`${color.green("\u2713")} ${account.route} route works \u2014 answered in ${elapsed}ms`);
|
|
219
|
+
write(` model reported ${result.model ?? color.dim("(none in response)")}`);
|
|
220
|
+
write(
|
|
221
|
+
` cost ${result.usage.inputTokens} input tokens ` + color.dim(`(~$${estimateTypeSafeCostUsd(result.usage.inputTokens).toFixed(6)})`)
|
|
222
|
+
);
|
|
223
|
+
if (result.model && deps.config.typesafe?.model && result.model !== deps.config.typesafe.model) {
|
|
224
|
+
write(
|
|
225
|
+
color.dim(` note: asked for ${deps.config.typesafe.model}, answered by ${result.model}`)
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
return 0;
|
|
229
|
+
} catch (err) {
|
|
230
|
+
const status = err.status;
|
|
231
|
+
write(`${color.red("\u2717")} ${err instanceof Error ? err.message : String(err)}`);
|
|
232
|
+
if (status === 401 || status === 403) {
|
|
233
|
+
write(" The host rejected the key. Re-run `wstack typesafe login`.");
|
|
234
|
+
} else if (status === 429 || status === 529) {
|
|
235
|
+
write(" Rate limited or overloaded \u2014 the key is probably fine; try again shortly.");
|
|
236
|
+
} else if (status === 422) {
|
|
237
|
+
write(" The host rejected the request shape, not the key. This is a bug; please report it.");
|
|
238
|
+
}
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function runGit(cwd, args) {
|
|
243
|
+
return new Promise((resolve, reject) => {
|
|
244
|
+
execFile(
|
|
245
|
+
"git",
|
|
246
|
+
args,
|
|
247
|
+
{
|
|
248
|
+
cwd,
|
|
249
|
+
env: buildChildEnv(),
|
|
250
|
+
encoding: "utf8",
|
|
251
|
+
timeout: 3e4,
|
|
252
|
+
windowsHide: true,
|
|
253
|
+
maxBuffer: 32 * 1024 * 1024
|
|
254
|
+
},
|
|
255
|
+
(err, stdout) => err ? reject(err) : resolve(stdout)
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
async function lintConventions(deps, write) {
|
|
260
|
+
const flags = deps.flags ?? {};
|
|
261
|
+
const judge = resolveTypeSafeJudge({ config: deps.config, feature: "semanticLint" });
|
|
262
|
+
if (!judge) {
|
|
263
|
+
const account = resolveTypeSafeAccount({ config: deps.config });
|
|
264
|
+
write(
|
|
265
|
+
`${color.red("\u2717")} ${account.status === "ready" ? "typesafe.judgments.semanticLint is false." : `${account.reason}. Run \`wstack typesafe login\`.`}`
|
|
266
|
+
);
|
|
267
|
+
return 2;
|
|
268
|
+
}
|
|
269
|
+
const rules = [...BUILT_IN_SEMANTIC_LINT_RULES];
|
|
270
|
+
const rulesPath = path.join(deps.projectRoot, ".wrongstack", "semantic-lint.json");
|
|
271
|
+
try {
|
|
272
|
+
const parsed = parseSemanticLintRules(JSON.parse(await readFile(rulesPath, "utf8")));
|
|
273
|
+
for (const error of parsed.errors) write(color.amber(`! ${rulesPath}: ${error}`));
|
|
274
|
+
rules.push(...parsed.rules);
|
|
275
|
+
} catch (err) {
|
|
276
|
+
if (err.code !== "ENOENT") {
|
|
277
|
+
write(color.amber(`! ${rulesPath}: ${err instanceof Error ? err.message : String(err)}`));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const base = typeof flags["base"] === "string" ? flags["base"] : void 0;
|
|
281
|
+
const diffArgs = ["diff", "--no-color", "--no-ext-diff", "-U24"];
|
|
282
|
+
if (flags["staged"] === true) diffArgs.push("--cached");
|
|
283
|
+
else if (base) diffArgs.push(`${base}...HEAD`);
|
|
284
|
+
let diff;
|
|
285
|
+
try {
|
|
286
|
+
diff = await runGit(deps.projectRoot, diffArgs);
|
|
287
|
+
} catch (err) {
|
|
288
|
+
write(`${color.red("\u2717")} git diff failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
289
|
+
return 2;
|
|
290
|
+
}
|
|
291
|
+
const candidates = findSemanticLintCandidates(diff, rules);
|
|
292
|
+
const thresholdFlag = Number(flags["threshold"]);
|
|
293
|
+
const threshold = Number.isFinite(thresholdFlag) && thresholdFlag > 0 && thresholdFlag <= 1 ? thresholdFlag : 0.7;
|
|
294
|
+
const result = candidates.length === 0 ? { findings: [], cleared: 0, unjudged: 0 } : await judgeSemanticLintCandidates(judge, rules, candidates, { threshold });
|
|
295
|
+
if (flags["json"] === true) {
|
|
296
|
+
write(JSON.stringify({ candidates: candidates.length, ...result }, null, 2));
|
|
297
|
+
} else {
|
|
298
|
+
for (const f of result.findings) {
|
|
299
|
+
write(
|
|
300
|
+
`${color.amber(`${f.file}:${f.line}`)} ${color.bold(f.ruleId)} ` + color.dim(`p=${f.probability.toFixed(2)}`)
|
|
301
|
+
);
|
|
302
|
+
write(` ${f.text.slice(0, 160)}`);
|
|
303
|
+
}
|
|
304
|
+
write(
|
|
305
|
+
color.dim(
|
|
306
|
+
`${candidates.length} candidate(s) across ${rules.length} rule(s): ${result.findings.length} finding(s), ${result.cleared} cleared` + (result.unjudged ? `, ${result.unjudged} not judged (host unavailable)` : "")
|
|
307
|
+
)
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
if (result.findings.length > 0) return 1;
|
|
311
|
+
return result.unjudged > 0 ? 2 : 0;
|
|
312
|
+
}
|
|
313
|
+
export {
|
|
314
|
+
typesafeCmd
|
|
315
|
+
};
|
|
316
|
+
//# sourceMappingURL=typesafe-HVEVPA6R.js.map
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
|
|
2
|
+
// src/subcommands/handlers/typesafe-brain-replay.ts
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import {
|
|
6
|
+
probeSystemOneBrain,
|
|
7
|
+
systemOneBrainSettles
|
|
8
|
+
} from "@wrongstack/core/execution";
|
|
9
|
+
import { resolveTypeSafeAccount } from "@wrongstack/core/typesafe";
|
|
10
|
+
import { color } from "@wrongstack/core/utils";
|
|
11
|
+
var MONITOR_OPTIONS = [
|
|
12
|
+
{
|
|
13
|
+
id: "steer",
|
|
14
|
+
label: "Steer the agent with corrective guidance",
|
|
15
|
+
consequence: "A steer message is injected before its next step."
|
|
16
|
+
},
|
|
17
|
+
{ id: "continue", label: "Let the agent continue unaided" }
|
|
18
|
+
];
|
|
19
|
+
function monitorKind(question) {
|
|
20
|
+
if (/has been edited \d+ times within/.test(question)) return "file_churn";
|
|
21
|
+
if (/has failed \d+ times in a row/.test(question)) return "tool_failure";
|
|
22
|
+
if (/no observable progress/.test(question)) return "stall";
|
|
23
|
+
if (/errors occurred within/.test(question)) return "error_storm";
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
function monitorContext(kind, question) {
|
|
27
|
+
if (kind === "file_churn") {
|
|
28
|
+
const m = /file "([^"]+)" has been edited (\d+) times within (\d+) minutes/.exec(question);
|
|
29
|
+
if (m) return `File: ${m[1]}
|
|
30
|
+
Edits in window: ${m[2]}
|
|
31
|
+
Window: ${Number(m[3]) * 60}s`;
|
|
32
|
+
}
|
|
33
|
+
if (kind === "tool_failure") {
|
|
34
|
+
const m = /tool "([^"]+)" has failed (\d+) times/.exec(question);
|
|
35
|
+
if (m) return `Tool: ${m[1]}
|
|
36
|
+
Consecutive failures: ${m[2]}`;
|
|
37
|
+
}
|
|
38
|
+
return question;
|
|
39
|
+
}
|
|
40
|
+
function parseFlag(value, fallback) {
|
|
41
|
+
const n = Number(value);
|
|
42
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;
|
|
43
|
+
}
|
|
44
|
+
async function replayBrainLedger(deps, write) {
|
|
45
|
+
const flags = deps.flags ?? {};
|
|
46
|
+
const account = resolveTypeSafeAccount({ config: deps.config, restGate: null });
|
|
47
|
+
if (account.status !== "ready") {
|
|
48
|
+
write(`${color.red("\u2717")} ${account.reason}. Run \`wstack typesafe login\`.`);
|
|
49
|
+
return 2;
|
|
50
|
+
}
|
|
51
|
+
const ledgerPath = typeof flags["ledger"] === "string" ? path.resolve(flags["ledger"]) : path.join(deps.paths.projectDir, "brain-ledger.jsonl");
|
|
52
|
+
const perKind = parseFlag(flags["limit"], 40);
|
|
53
|
+
const onlyKind = typeof flags["kind"] === "string" ? flags["kind"] : void 0;
|
|
54
|
+
let raw;
|
|
55
|
+
try {
|
|
56
|
+
raw = await readFile(ledgerPath, "utf8");
|
|
57
|
+
} catch (err) {
|
|
58
|
+
write(`${color.red("\u2717")} cannot read ${ledgerPath}: ${err.message}`);
|
|
59
|
+
return 2;
|
|
60
|
+
}
|
|
61
|
+
const rows = [];
|
|
62
|
+
for (const line of raw.split("\n")) {
|
|
63
|
+
if (!line.trim()) continue;
|
|
64
|
+
try {
|
|
65
|
+
rows.push(JSON.parse(line));
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const outcomes = /* @__PURE__ */ new Map();
|
|
70
|
+
for (const r of rows) if (r.kind === "outcome" && r.outcome) outcomes.set(r.requestId, r.outcome);
|
|
71
|
+
const byKind = /* @__PURE__ */ new Map();
|
|
72
|
+
const seen = /* @__PURE__ */ new Set();
|
|
73
|
+
for (const r of rows) {
|
|
74
|
+
if (r.kind !== "answered" || !r.question || !r.optionId) continue;
|
|
75
|
+
if (r.optionId !== "steer" && r.optionId !== "continue") continue;
|
|
76
|
+
const kind = monitorKind(r.question);
|
|
77
|
+
if (!kind || onlyKind && kind !== onlyKind || seen.has(r.question)) continue;
|
|
78
|
+
seen.add(r.question);
|
|
79
|
+
const list = byKind.get(kind) ?? [];
|
|
80
|
+
list.push({
|
|
81
|
+
kind,
|
|
82
|
+
question: r.question,
|
|
83
|
+
recorded: r.optionId,
|
|
84
|
+
recordedBy: r.detail?.startsWith("Council") ? "council" : "other",
|
|
85
|
+
outcome: outcomes.get(r.requestId)
|
|
86
|
+
});
|
|
87
|
+
byKind.set(kind, list);
|
|
88
|
+
}
|
|
89
|
+
const cases = [];
|
|
90
|
+
for (const list of byKind.values()) {
|
|
91
|
+
const step = Math.max(1, list.length / perKind);
|
|
92
|
+
for (let i = 0; i < list.length && cases.length < 1e4; i += step) {
|
|
93
|
+
const picked = list[Math.floor(i)];
|
|
94
|
+
if (picked) cases.push(picked);
|
|
95
|
+
if (cases.filter((c) => c.kind === picked?.kind).length >= perKind) break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (cases.length === 0) {
|
|
99
|
+
write("No replayable BrainMonitor decisions in the ledger.");
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
if (flags["json"] !== true) {
|
|
103
|
+
write(color.dim(`Replaying ${cases.length} decision(s) from ${ledgerPath}\u2026`));
|
|
104
|
+
}
|
|
105
|
+
const judge = { client: account.client, model: account.model, feature: "brain" };
|
|
106
|
+
const CONCURRENCY = 8;
|
|
107
|
+
for (let i = 0; i < cases.length; i += CONCURRENCY) {
|
|
108
|
+
await Promise.all(
|
|
109
|
+
cases.slice(i, i + CONCURRENCY).map(async (c) => {
|
|
110
|
+
const request = {
|
|
111
|
+
id: `replay-${i}`,
|
|
112
|
+
source: "system",
|
|
113
|
+
question: c.question,
|
|
114
|
+
context: monitorContext(c.kind, c.question),
|
|
115
|
+
risk: "medium",
|
|
116
|
+
fallback: "ask_human",
|
|
117
|
+
options: MONITOR_OPTIONS
|
|
118
|
+
};
|
|
119
|
+
try {
|
|
120
|
+
c.probe = await probeSystemOneBrain(judge, request, { timeoutMs: 15e3 });
|
|
121
|
+
if (!c.probe) c.error = "malformed answer";
|
|
122
|
+
} catch (err) {
|
|
123
|
+
c.error = err instanceof Error ? err.message : String(err);
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
const report = summarize(cases);
|
|
129
|
+
if (flags["json"] === true) {
|
|
130
|
+
write(JSON.stringify({ ledger: ledgerPath, ...report }, null, 2));
|
|
131
|
+
return 0;
|
|
132
|
+
}
|
|
133
|
+
const pct = (a, b) => b === 0 ? "\u2014" : `${Math.round(a / b * 100)}%`;
|
|
134
|
+
for (const k of report.kinds) {
|
|
135
|
+
write(color.bold(`${k.kind}`) + color.dim(` n=${k.n} (council ${k.council})`));
|
|
136
|
+
write(
|
|
137
|
+
` recorded steer ${k.recordedSteer} / continue ${k.n - k.recordedSteer} Jev steer ${k.jevSteer} / continue ${k.judged - k.jevSteer}`
|
|
138
|
+
);
|
|
139
|
+
write(` agreement ${pct(k.agree, k.judged)} of ${k.judged} judged`);
|
|
140
|
+
write(
|
|
141
|
+
` settles ${pct(k.settled, k.judged)} at current thresholds, agreeing ${pct(k.settledAgree, k.settled)}`
|
|
142
|
+
);
|
|
143
|
+
if (k.futileSteers > 0) {
|
|
144
|
+
write(
|
|
145
|
+
` futile steers (signal re-fired): ${k.futileSteers}, Jev said continue on ${k.futileSteersJevContinue}`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
write("");
|
|
150
|
+
write(color.bold("Sweep (decidable threshold; confidence/probability at defaults)"));
|
|
151
|
+
for (const s of report.sweep) {
|
|
152
|
+
write(
|
|
153
|
+
` decidable \u2265 ${s.threshold.toFixed(2)} settles ${pct(s.settled, report.judged)} agreeing ${pct(s.agree, s.settled)}`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
if (report.errors > 0) write(color.amber(`${report.errors} case(s) not judged (host error).`));
|
|
157
|
+
write(color.dim(`model ${report.model ?? account.model}`));
|
|
158
|
+
write(
|
|
159
|
+
color.dim(
|
|
160
|
+
"Replayed contexts lack the tool output the live monitor attaches, so tool_failure reads as signal-only here."
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
function summarize(cases) {
|
|
166
|
+
const kinds = [...new Set(cases.map((c) => c.kind))].map((kind) => {
|
|
167
|
+
const list = cases.filter((c) => c.kind === kind);
|
|
168
|
+
const judged2 = list.filter((c) => c.probe);
|
|
169
|
+
const settled = judged2.filter((c) => systemOneBrainSettles(c.probe));
|
|
170
|
+
const futile = list.filter((c) => c.recorded === "steer" && c.outcome === "failure");
|
|
171
|
+
return {
|
|
172
|
+
kind,
|
|
173
|
+
n: list.length,
|
|
174
|
+
council: list.filter((c) => c.recordedBy === "council").length,
|
|
175
|
+
recordedSteer: list.filter((c) => c.recorded === "steer").length,
|
|
176
|
+
judged: judged2.length,
|
|
177
|
+
jevSteer: judged2.filter((c) => c.probe.optionId === "steer").length,
|
|
178
|
+
agree: judged2.filter((c) => c.probe.optionId === c.recorded).length,
|
|
179
|
+
settled: settled.length,
|
|
180
|
+
settledAgree: settled.filter((c) => c.probe.optionId === c.recorded).length,
|
|
181
|
+
futileSteers: futile.length,
|
|
182
|
+
futileSteersJevContinue: futile.filter((c) => c.probe?.optionId === "continue").length
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
const judged = cases.filter((c) => c.probe);
|
|
186
|
+
const sweep = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6].map((threshold) => {
|
|
187
|
+
const settled = judged.filter(
|
|
188
|
+
(c) => c.probe.decidable >= threshold && systemOneBrainSettles(c.probe, { minDecidable: 0 })
|
|
189
|
+
);
|
|
190
|
+
return {
|
|
191
|
+
threshold,
|
|
192
|
+
settled: settled.length,
|
|
193
|
+
agree: settled.filter((c) => c.probe.optionId === c.recorded).length
|
|
194
|
+
};
|
|
195
|
+
});
|
|
196
|
+
return {
|
|
197
|
+
kinds,
|
|
198
|
+
sweep,
|
|
199
|
+
judged: judged.length,
|
|
200
|
+
errors: cases.filter((c) => c.error).length,
|
|
201
|
+
model: judged[0]?.probe?.model,
|
|
202
|
+
cases: judged.map((c) => ({
|
|
203
|
+
kind: c.kind,
|
|
204
|
+
recorded: c.recorded,
|
|
205
|
+
jev: c.probe.optionId,
|
|
206
|
+
p: Number(c.probe.probability.toFixed(3)),
|
|
207
|
+
decidable: Number(c.probe.decidable.toFixed(3))
|
|
208
|
+
})),
|
|
209
|
+
disagreements: judged.filter((c) => c.probe.optionId !== c.recorded).slice(0, 20).map((c) => ({
|
|
210
|
+
kind: c.kind,
|
|
211
|
+
question: c.question.slice(0, 200),
|
|
212
|
+
recorded: c.recorded,
|
|
213
|
+
jev: c.probe.optionId,
|
|
214
|
+
p: Number(c.probe.probability.toFixed(3)),
|
|
215
|
+
decidable: Number(c.probe.decidable.toFixed(3))
|
|
216
|
+
}))
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
export {
|
|
220
|
+
replayBrainLedger
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=typesafe-brain-replay-C5276FVR.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
// src/subcommands/handlers/typesafe-judgment-check.ts
|
|
3
|
+
import { checkJevJudgments } from "@wrongstack/runtime/jev-checks";
|
|
4
|
+
async function checkJudgments(deps, write) {
|
|
5
|
+
try {
|
|
6
|
+
const report = await checkJevJudgments(deps.config);
|
|
7
|
+
let feature = "";
|
|
8
|
+
for (const result of report.cases) {
|
|
9
|
+
if (feature !== result.feature) {
|
|
10
|
+
feature = result.feature;
|
|
11
|
+
write(feature);
|
|
12
|
+
}
|
|
13
|
+
write(
|
|
14
|
+
`${result.ok ? "\u2713" : "\u2717"} ${result.name} (${result.ms}ms) \u2014 expected ${result.expected}, got ${result.actual}${result.note ? ` [${result.note}]` : ""}`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
write(
|
|
18
|
+
`${report.passed}/${report.total} as expected \u2014 ${report.route} route, model ${report.model}`
|
|
19
|
+
);
|
|
20
|
+
return report.passed === report.total ? 0 : 1;
|
|
21
|
+
} catch {
|
|
22
|
+
write("Jev checks unavailable. Configure an account with wstack typesafe login.");
|
|
23
|
+
return 2;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
checkJudgments
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=typesafe-judgment-check-GGYYV5UF.js.map
|