Skip to content

Commit 616892d

Browse files
committed
W857-W864 100%-completion sweep — account-page forms + CLI fixes + NL classifier + homepage cleanup
W857-W862 account-page completion (insurance enterprise onboarding tier): - /account/distill/new.html: distill job submission form with strategy + student picker - /account/builds/new.html: compile trigger with namespace + .kolm output preview - /account/datasets.html: dataset/corpus upload + listing - /account/enterprise/sso.html: SAML/SSO config UI (IdP metadata XML upload + SCIM token) - /account/audit-log.html: filter + CSV/JSON export W860 — cli/kolm.js: 3 BLOCKER half-baked CLI verbs fixed (full handlers, no stub envelopes) W863 — src/intent.js: NL classifier paraphrase table + per-verb confidence thresholds; routes phrasings like "cut my openai bill" / "fit on a single 5090" / "prove to compliance" through to real verbs with confidence >= 0.65 W864 — homepage cleanup (patchwork -> finished): - public/index.html: 330 KB / 1997 lines -> 86 KB / 1371 lines (74% smaller) - Deleted hidden test-anchor scaffolding: W220 floor recovery payload, footer tag cloud, W410 loop-strip, W404 numbers-strip, W706/W705/W681 mirror blocks, W850 quantize forge hidden preview, W845/W844/W646 lock-in mirrors - Cut 2 of 3 pipeline explanations (kept kolm-arch SVG; removed hero "Drop in/Compile/Own" mini-card and W837 "Capture -> Distill -> Quantize -> Seal" section) - Merged "Why kolm" footnote into "What you get when you compile" (links live in footer) - Unified nav vocab: Wrapper/Studio -> Product/Use cases (canonical nav from nav.js) - Scrubbed "forever" promises from H1 / lede / kolm-whatis paragraph; preserved as legitimate stage-3 name "Own forever" in the architecture diagram - W864-D: relaxed tests/wave220 #10 byte-floor 200 KB -> 50 KB + #12 SEO window 3 KB -> 8 KB; deleted tests/wave271 #26/#27/#28 (demo-anchor + v0.2 release-verbs lock-ins for content that no longer exists) - sw.js v91 -> v92 wave864-homepage-cleanup-scaffolding-purge vercel.json: rewrites for the 3 new account pages
1 parent be4afed commit 616892d

18 files changed

Lines changed: 3516 additions & 790 deletions

cli/kolm.js

Lines changed: 95 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22853,6 +22853,18 @@ async function cmdMenu(args) {
2285322853
}
2285422854
console.log('');
2285522855
}
22856+
// W860 — readline.question hangs forever on non-TTY stdin (CI, piped input,
22857+
// background process). Refuse early with an actionable hint instead of
22858+
// wedging the parent shell. The picker is intrinsically interactive.
22859+
if (!process.stdin.isTTY) {
22860+
console.error(' kolm menu requires an interactive terminal (TTY).');
22861+
console.error(' for non-interactive picks, invoke the verb directly:');
22862+
console.error(' kolm quickstart # guided setup');
22863+
console.error(' kolm tui # full dashboard');
22864+
console.error(' kolm whoami # current tenant');
22865+
console.error(' or use `kolm help` for the full verb list.');
22866+
process.exit(EXIT.USAGE);
22867+
}
2285622868
const readline = await import('node:readline');
2285722869
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
2285822870
const raw = await new Promise(resolve => rl.question(' > ', resolve));
@@ -30935,7 +30947,7 @@ async function cmdImprove(args) {
3093530947
if (maybeHelp('improve', args)) return;
3093630948
const id = args.find(a => !a.startsWith('--'));
3093730949
if (!id) {
30938-
const e = new Error('usage: kolm improve <artifact-id> [--epsilon 0.01] [--dry-run]');
30950+
const e = new Error('usage: kolm improve <artifact-id> [--epsilon 0.01] [--dry-run] [--json]');
3093930951
e.exitCode = EXIT.BAD_ARGS;
3094030952
throw e;
3094130953
}
@@ -30945,6 +30957,7 @@ async function cmdImprove(args) {
3094530957
};
3094630958
const epsilon = Number(get('--epsilon')) || 0.01;
3094730959
const dryRun = args.includes('--dry-run');
30960+
const jsonMode = args.includes('--json');
3094830961

3094930962
const base = process.env.KOLM_BASE_URL || 'https://kolm.ai';
3095030963
const token = process.env.KOLM_API_KEY || (function () {
@@ -30987,14 +31000,41 @@ async function cmdImprove(args) {
3098731000
console.log(`found ${candidates.length} high-uncertainty event(s) since last compile`);
3098831001

3098931002
if (!candidates.length) {
30990-
console.log('nothing to improve. K-score gate already holding.');
31003+
// W860 — structured envelope so scripted callers (CI, account UI poller)
31004+
// can tell `nothing to improve` apart from an upstream error. Human path
31005+
// unchanged: a single line that says K-score already holds.
31006+
if (jsonMode) {
31007+
console.log(JSON.stringify({
31008+
ok: true,
31009+
artifact_id: id,
31010+
k_score: oldK,
31011+
candidates: 0,
31012+
action: 'noop',
31013+
reason: 'no_high_uncertainty_events',
31014+
message: 'K-score gate is holding. No fallback or low-confidence audit events since the last compile.',
31015+
next: { command: `kolm capture --tail`, hint: 'tail captures to surface uncertainty before re-running improve' },
31016+
}, null, 2));
31017+
} else {
31018+
console.log('nothing to improve. K-score gate already holding.');
31019+
}
3099131020
return;
3099231021
}
3099331022
if (dryRun) {
30994-
console.log('--dry-run: not recompiling. Examples that would be added:');
30995-
candidates.slice(0, 10).forEach((e, i) => {
30996-
console.log(` ${i + 1}. ${JSON.stringify(e.payload).slice(0, 120)}`);
30997-
});
31023+
if (jsonMode) {
31024+
console.log(JSON.stringify({
31025+
ok: true,
31026+
artifact_id: id,
31027+
k_score: oldK,
31028+
candidates: candidates.length,
31029+
action: 'dry_run',
31030+
examples: candidates.slice(0, 10).map(e => ({ op: e.op, payload: e.payload })),
31031+
}, null, 2));
31032+
} else {
31033+
console.log('--dry-run: not recompiling. Examples that would be added:');
31034+
candidates.slice(0, 10).forEach((e, i) => {
31035+
console.log(` ${i + 1}. ${JSON.stringify(e.payload).slice(0, 120)}`);
31036+
});
31037+
}
3099831038
return;
3099931039
}
3100031040

@@ -31022,16 +31062,40 @@ async function cmdImprove(args) {
3102231062
});
3102331063
const newJob = await newRes.json();
3102431064
if (!newRes.ok || newJob.error) {
31025-
console.log(`recompile rejected: ${newJob.error || newRes.status}`);
31026-
console.log(`old artifact ${id} unchanged. K stayed at ${oldK.toFixed(3)}.`);
31065+
if (jsonMode) {
31066+
console.log(JSON.stringify({
31067+
ok: false,
31068+
artifact_id: id,
31069+
old_k_score: oldK,
31070+
action: 'recompile_rejected',
31071+
reason: newJob.error || `http_${newRes.status}`,
31072+
message: `recompile rejected. old artifact ${id} unchanged.`,
31073+
}, null, 2));
31074+
} else {
31075+
console.log(`recompile rejected: ${newJob.error || newRes.status}`);
31076+
console.log(`old artifact ${id} unchanged. K stayed at ${oldK.toFixed(3)}.`);
31077+
}
3102731078
return;
3102831079
}
3102931080
const newK = Number(newJob.k_score) || 0;
31030-
console.log(`new K: ${newK.toFixed(3)} (threshold ${(oldK + epsilon).toFixed(3)})`);
31031-
if (newK <= oldK + epsilon) {
31032-
console.log(`improvement below epsilon. old artifact ${id} kept.`);
31081+
const kept = newK <= oldK + epsilon;
31082+
if (jsonMode) {
31083+
console.log(JSON.stringify({
31084+
ok: true,
31085+
artifact_id: id,
31086+
old_k_score: oldK,
31087+
new_k_score: newK,
31088+
threshold: oldK + epsilon,
31089+
action: kept ? 'kept_old' : 'replaced',
31090+
new_artifact_id: kept ? null : (newJob.job_id || null),
31091+
}, null, 2));
3103331092
} else {
31034-
console.log(`new artifact ${newJob.job_id} replaces ${id} for K-score regression guard.`);
31093+
console.log(`new K: ${newK.toFixed(3)} (threshold ${(oldK + epsilon).toFixed(3)})`);
31094+
if (kept) {
31095+
console.log(`improvement below epsilon. old artifact ${id} kept.`);
31096+
} else {
31097+
console.log(`new artifact ${newJob.job_id} replaces ${id} for K-score regression guard.`);
31098+
}
3103531099
}
3103631100
}
3103731101

@@ -31073,6 +31137,25 @@ async function cmdInstant(args) {
3107331137

3107431138
const python = process.env.KOLM_PYTHON
3107531139
|| (process.platform === 'win32' ? 'python' : 'python3');
31140+
// W860 — probe python availability before spawning the synth script. Without
31141+
// this, missing python on the PATH surfaces as an opaque ENOENT inside the
31142+
// shelled-out spawn and the user sees no actionable hint. Honest exit:
31143+
// MISSING_PREREQ (3) with a one-liner pointing at the env override.
31144+
{
31145+
const probe = spawnSync(python, ['-V'], { encoding: 'utf8' });
31146+
if (probe.error || probe.status !== 0) {
31147+
const e = new Error(
31148+
`python interpreter '${python}' not found on PATH.\n` +
31149+
`kolm instant shells out to the python trainer for teacher-driven synthesis.\n` +
31150+
`fixes:\n` +
31151+
` • install Python 3.10+ from https://python.org\n` +
31152+
` • or set KOLM_PYTHON=/path/to/python to point at an existing interpreter\n` +
31153+
` • or use \`kolm distill\` for the cloud-only path (no python required)`
31154+
);
31155+
e.exitCode = EXIT.MISSING_PREREQ;
31156+
throw e;
31157+
}
31158+
}
3107631159
const script = `
3107731160
import json, sys
3107831161
cfg = json.loads(sys.stdin.read())

0 commit comments

Comments
 (0)