@aayambansal/squint 0.4.8 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +3 -0
  2. package/dist/App-KTNAMHY6.js +24 -0
  3. package/dist/{cdp-2VVQOHWM.js → cdp-D2F4P7UQ.js} +1 -1
  4. package/dist/{chrome-SBV3H77F.js → chrome-EEXJCG6W.js} +2 -2
  5. package/dist/{chunk-QCHBDP46.js → chunk-2I3YHT6P.js} +3 -3
  6. package/dist/{chunk-JZMJGLIZ.js → chunk-2NYNTVMX.js} +2 -2
  7. package/dist/{chunk-BGBG2MNY.js → chunk-3YCG234A.js} +80 -2
  8. package/dist/{flows-6LK7NGWS.js → chunk-4XSHHGA6.js} +2 -1
  9. package/dist/{chunk-VH7OOFQP.js → chunk-6NPUVPQD.js} +2 -2
  10. package/dist/{chunk-ATNTD3V5.js → chunk-AMA3F2Y2.js} +1 -1
  11. package/dist/{chunk-7RFQWOQV.js → chunk-ERF2SPUW.js} +4 -4
  12. package/dist/{chunk-YGPVP4YB.js → chunk-G5NS2IFQ.js} +68 -17
  13. package/dist/{chunk-KVYGPLWW.js → chunk-GV2HAALP.js} +4 -0
  14. package/dist/chunk-IEQGTVWN.js +52 -0
  15. package/dist/{chunk-YGSF2TSO.js → chunk-J7ITMK6X.js} +1 -1
  16. package/dist/{contextDoctor-A26C2ZDN.js → chunk-LESZB7DT.js} +6 -3
  17. package/dist/{chunk-IMDRXXFU.js → chunk-PYC53J7D.js} +1 -1
  18. package/dist/{chunk-ARDV4XH6.js → chunk-UBADCBPT.js} +14 -59
  19. package/dist/{chunk-43NQNIJY.js → chunk-VJ2QKHYK.js} +2 -0
  20. package/dist/cli.js +105 -27
  21. package/dist/{commands-BY44HDQ6.js → commands-WC7V6EAE.js} +1 -1
  22. package/dist/contextDoctor-LHKGSIEM.js +12 -0
  23. package/dist/designLog-S67J7SO2.js +11 -0
  24. package/dist/flows-MXJL45HW.js +11 -0
  25. package/dist/{preview-FBNVDQIV.js → preview-JN5PTWLX.js} +4 -4
  26. package/dist/{registry-MIJ6LSAY.js → registry-JBP7J3JB.js} +1 -1
  27. package/dist/{remote-OH2P4S2H.js → remote-UOV4ZXWU.js} +11 -10
  28. package/dist/{run-NDSNTVYP.js → run-GDDIYEBP.js} +2 -2
  29. package/dist/{sentinel-42NZRTTS.js → sentinel-4SKSSCXX.js} +0 -0
  30. package/dist/server-2WPGU3KQ.js +156 -0
  31. package/dist/shots-6DRTXFDI.js +13 -0
  32. package/dist/{skills-POB4ZZY5.js → skills-DQTE5Q77.js} +2 -1
  33. package/dist/{variants-3IEP7DFY.js → variants-VURXVIQO.js} +3 -3
  34. package/package.json +1 -1
  35. package/dist/App-766KSGON.js +0 -23
  36. package/dist/shots-OKWOYF7F.js +0 -13
@@ -1,70 +1,28 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ decisionsSection
4
+ } from "./chunk-IEQGTVWN.js";
2
5
 
3
6
  // src/prompt/skills.ts
4
- import fs3 from "fs";
5
- import path3 from "path";
7
+ import fs2 from "fs";
8
+ import path2 from "path";
6
9
 
7
- // src/session/designLog.ts
10
+ // src/prompt/registry.ts
8
11
  import fs from "fs";
9
12
  import path from "path";
10
- function logFile(cwd) {
11
- return path.join(cwd, ".squint", "design-log.jsonl");
12
- }
13
- function appendDecision(cwd, entry) {
14
- try {
15
- fs.mkdirSync(path.join(cwd, ".squint"), { recursive: true });
16
- const record = { ts: (/* @__PURE__ */ new Date()).toISOString(), ...entry };
17
- fs.appendFileSync(logFile(cwd), JSON.stringify(record) + "\n");
18
- } catch {
19
- }
20
- }
21
- function loadDecisions(cwd, limit = 8) {
22
- try {
23
- const lines = fs.readFileSync(logFile(cwd), "utf8").trim().split("\n");
24
- const decisions = [];
25
- for (const line of lines.slice(-limit * 2)) {
26
- try {
27
- const parsed = JSON.parse(line);
28
- if (typeof parsed?.decision === "string" && typeof parsed?.ts === "string") decisions.push(parsed);
29
- } catch {
30
- }
31
- }
32
- return decisions.slice(-limit);
33
- } catch {
34
- return [];
35
- }
36
- }
37
- function decisionsSection(cwd) {
38
- const decisions = loadDecisions(cwd);
39
- if (decisions.length === 0) return "";
40
- const lines = decisions.map((d) => {
41
- const days = Math.floor((Date.now() - Date.parse(d.ts)) / 864e5);
42
- const age = days <= 0 ? "today" : `${days}d ago`;
43
- return `- ${d.decision} (${d.source}, ${age}${d.screenshot ? `, evidence: ${d.screenshot}` : ""})`;
44
- });
45
- return `## Design decisions on record
46
-
47
- ${lines.join("\n")}
48
-
49
- These were decided deliberately. Do not silently undo them; if a task genuinely requires reversing one, say so explicitly first.`;
50
- }
51
-
52
- // src/prompt/registry.ts
53
- import fs2 from "fs";
54
- import path2 from "path";
55
13
  function loadComponentInventory(cwd) {
56
14
  let config;
57
15
  try {
58
- config = JSON.parse(fs2.readFileSync(path2.join(cwd, "components.json"), "utf8"));
16
+ config = JSON.parse(fs.readFileSync(path.join(cwd, "components.json"), "utf8"));
59
17
  } catch {
60
18
  return null;
61
19
  }
62
20
  const alias = config.aliases?.ui ?? (config.aliases?.components ? `${config.aliases.components}/ui` : "@/components/ui");
63
21
  const relative = alias.replace(/^@\//, "src/").replace(/^~\//, "");
64
- const uiDir = path2.join(cwd, relative);
22
+ const uiDir = path.join(cwd, relative);
65
23
  let entries;
66
24
  try {
67
- entries = fs2.readdirSync(uiDir);
25
+ entries = fs.readdirSync(uiDir);
68
26
  } catch {
69
27
  return null;
70
28
  }
@@ -100,17 +58,17 @@ function parseSkill(name, raw) {
100
58
  return { name, triggers, body };
101
59
  }
102
60
  function loadSkills(cwd) {
103
- const dir = path3.join(cwd, ".squint", "skills");
61
+ const dir = path2.join(cwd, ".squint", "skills");
104
62
  let entries;
105
63
  try {
106
- entries = fs3.readdirSync(dir).filter((f) => f.endsWith(".md"));
64
+ entries = fs2.readdirSync(dir).filter((f) => f.endsWith(".md"));
107
65
  } catch {
108
66
  return [];
109
67
  }
110
68
  const skills = [];
111
69
  for (const entry of entries.sort()) {
112
70
  try {
113
- const skill = parseSkill(entry.replace(/\.md$/, ""), fs3.readFileSync(path3.join(dir, entry), "utf8"));
71
+ const skill = parseSkill(entry.replace(/\.md$/, ""), fs2.readFileSync(path2.join(dir, entry), "utf8"));
114
72
  if (skill) skills.push(skill);
115
73
  } catch {
116
74
  }
@@ -119,7 +77,7 @@ function loadSkills(cwd) {
119
77
  }
120
78
  function loadRules(cwd) {
121
79
  try {
122
- const text = fs3.readFileSync(path3.join(cwd, ".squint", "rules.md"), "utf8").trim();
80
+ const text = fs2.readFileSync(path2.join(cwd, ".squint", "rules.md"), "utf8").trim();
123
81
  return text.length > 0 ? text : null;
124
82
  } catch {
125
83
  return null;
@@ -131,7 +89,7 @@ function matchSkills(skills, ask) {
131
89
  }
132
90
  function loadLocks(cwd) {
133
91
  try {
134
- return fs3.readFileSync(path3.join(cwd, ".squint", "locks"), "utf8").split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
92
+ return fs2.readFileSync(path2.join(cwd, ".squint", "locks"), "utf8").split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
135
93
  } catch {
136
94
  return [];
137
95
  }
@@ -180,9 +138,6 @@ ${parts.join("\n\n")}` : "",
180
138
  }
181
139
 
182
140
  export {
183
- appendDecision,
184
- loadDecisions,
185
- decisionsSection,
186
141
  loadComponentInventory,
187
142
  inventorySection,
188
143
  parseSkill,
@@ -27,6 +27,8 @@ var COMMANDS = [
27
27
  { name: "save", group: "session", description: "export the transcript to .squint/transcripts/" },
28
28
  { name: "find", args: "<term>", group: "session", description: "search this session and saved transcripts" },
29
29
  { name: "decide", args: "<text>", group: "session", description: "record a design decision; injected into every future ask" },
30
+ { name: "goal", args: "[text|off]", group: "build", description: "arm a standing objective; auto-fix presses until checks are clean" },
31
+ { name: "distill", group: "session", description: "compress the design ledger into rules.md lines and proposed checks" },
30
32
  { name: "context", group: "session", description: "what squint injects per ask, token-costed, with staleness warnings" },
31
33
  { name: "yes", args: "[note]", group: "build", description: "approve the engine's pending visual-approval request" },
32
34
  { name: "no", args: "[note]", group: "build", description: "reject the engine's pending visual-approval request" },
package/dist/cli.js CHANGED
@@ -1,35 +1,36 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ App
4
+ } from "./chunk-2NYNTVMX.js";
5
+ import "./chunk-VJ2QKHYK.js";
2
6
  import {
3
7
  connectDaemon,
4
8
  socketPath,
5
9
  startDaemon
6
- } from "./chunk-ATNTD3V5.js";
7
- import {
8
- App
9
- } from "./chunk-JZMJGLIZ.js";
10
- import "./chunk-43NQNIJY.js";
11
- import "./chunk-YGPVP4YB.js";
12
- import "./chunk-ARDV4XH6.js";
10
+ } from "./chunk-AMA3F2Y2.js";
11
+ import "./chunk-G5NS2IFQ.js";
12
+ import "./chunk-UBADCBPT.js";
13
+ import "./chunk-IEQGTVWN.js";
13
14
  import "./chunk-AUJJGMZG.js";
14
15
  import "./chunk-YHRAOBI2.js";
15
- import "./chunk-QCHBDP46.js";
16
- import "./chunk-YGSF2TSO.js";
16
+ import "./chunk-2I3YHT6P.js";
17
+ import "./chunk-J7ITMK6X.js";
17
18
  import {
18
19
  runAgent
19
- } from "./chunk-VH7OOFQP.js";
20
+ } from "./chunk-6NPUVPQD.js";
20
21
  import "./chunk-K5QJMSJH.js";
21
22
  import {
22
23
  composePrompt
23
24
  } from "./chunk-WAJXATCO.js";
24
25
  import "./chunk-62JNF5M2.js";
25
- import "./chunk-7RFQWOQV.js";
26
+ import "./chunk-ERF2SPUW.js";
26
27
  import "./chunk-7CAGWFAQ.js";
27
- import "./chunk-BGBG2MNY.js";
28
- import "./chunk-IMDRXXFU.js";
28
+ import "./chunk-3YCG234A.js";
29
+ import "./chunk-PYC53J7D.js";
29
30
  import {
30
31
  detectEngines,
31
32
  getEngine
32
- } from "./chunk-KVYGPLWW.js";
33
+ } from "./chunk-GV2HAALP.js";
33
34
 
34
35
  // src/cli.tsx
35
36
  import { Command } from "commander";
@@ -185,15 +186,19 @@ function registerDaemon(program2) {
185
186
  process.on("SIGINT", stop);
186
187
  process.on("SIGTERM", stop);
187
188
  });
189
+ program2.command("mcp").description("serve the gates as MCP tools over stdio (check, shot, flows, context)").action(async () => {
190
+ const { runMcpServer } = await import("./server-2WPGU3KQ.js");
191
+ runMcpServer(process.cwd());
192
+ });
188
193
  program2.command("attach").description("attach this terminal to a running squint daemon (full TUI; --plain for line mode)").option("--plain", "line-mode attach instead of the full TUI").action(async (opts) => {
189
194
  const cwd = process.cwd();
190
195
  if (!opts.plain) {
191
196
  try {
192
- const { RemoteSession } = await import("./remote-OH2P4S2H.js");
197
+ const { RemoteSession } = await import("./remote-UOV4ZXWU.js");
193
198
  const remote = await RemoteSession.connect(cwd);
194
199
  const config = loadConfig(defaultPaths(cwd));
195
200
  const { render: render2 } = await import("ink");
196
- const { App: App2 } = await import("./App-766KSGON.js");
201
+ const { App: App2 } = await import("./App-KTNAMHY6.js");
197
202
  const React = await import("react");
198
203
  render2(
199
204
  React.createElement(App2, {
@@ -287,7 +292,7 @@ function registerEnv(program2) {
287
292
  console.log(`${status} ${engine.name}${binaryPath ? "" : pc3.dim(` \u2014 install: ${engine.install}`)}`);
288
293
  }
289
294
  if (options.probe) {
290
- const { runAgent: runAgent2 } = await import("./run-NDSNTVYP.js");
295
+ const { runAgent: runAgent2 } = await import("./run-GDDIYEBP.js");
291
296
  console.log(pc3.dim("\nprobing engines with a one-word prompt (verifies auth end to end)\u2026"));
292
297
  for (const { engine, path: binaryPath } of detected) {
293
298
  if (!binaryPath) continue;
@@ -309,8 +314,8 @@ function registerEnv(program2) {
309
314
  );
310
315
  }
311
316
  }
312
- const { findChrome } = await import("./chrome-SBV3H77F.js");
313
- const { hasWebSocket } = await import("./cdp-2VVQOHWM.js");
317
+ const { findChrome } = await import("./chrome-EEXJCG6W.js");
318
+ const { hasWebSocket } = await import("./cdp-D2F4P7UQ.js");
314
319
  const chrome = findChrome();
315
320
  console.log(
316
321
  chrome ? `${pc3.green("\u2713")} Chrome ${pc3.dim(chrome)}` : `${pc3.yellow("\u25CB")} Chrome ${pc3.dim("\u2014 screenshots and runtime probing disabled")}`
@@ -334,7 +339,7 @@ import pc4 from "picocolors";
334
339
  function registerProject(program2) {
335
340
  const skillsCommand = program2.command("skills").description("Project knowledge injected into asks (.squint/rules.md + .squint/skills/)");
336
341
  skillsCommand.command("list").description("Show always-on rules and trigger-matched skills").action(async () => {
337
- const { loadRules, loadSkills } = await import("./skills-POB4ZZY5.js");
342
+ const { loadRules, loadSkills } = await import("./skills-DQTE5Q77.js");
338
343
  const cwd = process.cwd();
339
344
  const rules = loadRules(cwd);
340
345
  console.log(
@@ -451,7 +456,7 @@ function registerProject(program2) {
451
456
  process.exitCode = 1;
452
457
  return;
453
458
  }
454
- const { runVariants, cleanVariants } = await import("./variants-3IEP7DFY.js");
459
+ const { runVariants, cleanVariants } = await import("./variants-VURXVIQO.js");
455
460
  const config = loadConfig(defaultPaths(cwd));
456
461
  const engineId = resolveEngineId(config, options.engine);
457
462
  const engine = getEngine(engineId);
@@ -469,7 +474,7 @@ function registerProject(program2) {
469
474
  );
470
475
  const succeeded = runs.filter((r) => r.result.ok);
471
476
  if (options.shots && succeeded.length > 0) {
472
- const { screenshotVariants } = await import("./shots-OKWOYF7F.js");
477
+ const { screenshotVariants } = await import("./shots-6DRTXFDI.js");
473
478
  console.log(pc4.dim("capturing screenshots\u2026"));
474
479
  const shots = await screenshotVariants(cwd, succeeded.map((r) => r.variant));
475
480
  for (const shot of shots) {
@@ -484,7 +489,7 @@ ${succeeded.length}/${runs.length} variants ready in .squint/variants/ \u2014 `
484
489
  }
485
490
  );
486
491
  variantsCommand.command("list").description("List generated variants").action(async () => {
487
- const { listVariants } = await import("./variants-3IEP7DFY.js");
492
+ const { listVariants } = await import("./variants-VURXVIQO.js");
488
493
  const ids = listVariants(process.cwd());
489
494
  if (ids.length === 0) {
490
495
  console.log(pc4.dim('no variants \u2014 squint variants gen <n> "<ask>"'));
@@ -493,7 +498,7 @@ ${succeeded.length}/${runs.length} variants ready in .squint/variants/ \u2014 `
493
498
  for (const id of ids) console.log(id);
494
499
  });
495
500
  variantsCommand.command("apply").description("Apply one variant\u2019s changes to the main tree and discard the rest").argument("<id>", "family id of the winning variant").action(async (id) => {
496
- const { applyVariant, cleanVariants } = await import("./variants-3IEP7DFY.js");
501
+ const { applyVariant, cleanVariants } = await import("./variants-VURXVIQO.js");
497
502
  const cwd = process.cwd();
498
503
  const result = applyVariant(cwd, id);
499
504
  if (!result.ok) {
@@ -505,7 +510,7 @@ ${succeeded.length}/${runs.length} variants ready in .squint/variants/ \u2014 `
505
510
  console.log(pc4.green(`\u2713 applied ${id} to the working tree`) + pc4.dim(" \u2014 review with git diff"));
506
511
  });
507
512
  variantsCommand.command("clean").description("Discard all variants").action(async () => {
508
- const { cleanVariants } = await import("./variants-3IEP7DFY.js");
513
+ const { cleanVariants } = await import("./variants-VURXVIQO.js");
509
514
  const count = cleanVariants(process.cwd());
510
515
  console.log(pc4.dim(`removed ${count} variant(s)`));
511
516
  });
@@ -532,8 +537,81 @@ function registerQuality(program2) {
532
537
  });
533
538
  if (results.some((r) => !r.ok)) process.exitCode = 1;
534
539
  });
540
+ program2.command("ci").description("One-shot verification for pipelines: gates (+ audits and flows with --url), JSON report, non-zero exit on failure").option("--url <url>", "also audit a running app URL (runtime, a11y, phantoms, jank) and replay flows").option("--json <path>", "write the machine-readable report here").action(async (opts) => {
541
+ const cwd = process.cwd();
542
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
543
+ const report = { startedAt, cwd };
544
+ let failed = false;
545
+ const { detectGates, runGates } = await import("./gates-ZC67NMW3.js");
546
+ const gates = detectGates(cwd);
547
+ const gateResults = await runGates(cwd, gates, (result) => {
548
+ console.log(`${result.ok ? pc5.green("\u2713") : pc5.red("\u2717")} ${result.gate.id} ${pc5.dim(`${(result.durationMs / 1e3).toFixed(1)}s`)}`);
549
+ if (!result.ok) console.log(pc5.dim(result.outputTail.split("\n").slice(-12).join("\n")));
550
+ });
551
+ report.gates = gateResults.map((r) => ({ id: r.gate.id, ok: r.ok, durationMs: r.durationMs, outputTail: r.ok ? void 0 : r.outputTail }));
552
+ if (gateResults.some((r) => !r.ok)) failed = true;
553
+ if (opts.url) {
554
+ const { captureViewports, runtimeSummary, previewDir } = await import("./preview-JN5PTWLX.js");
555
+ const capture = await captureViewports(cwd, opts.url);
556
+ if (!capture) {
557
+ console.log(pc5.red("\u2717 audit: capture failed (Chrome missing or URL unreachable)"));
558
+ report.audit = { ok: false };
559
+ failed = true;
560
+ } else {
561
+ const runtime = capture.runtime ? runtimeSummary(capture.runtime) : null;
562
+ const hard = {
563
+ runtime,
564
+ phantoms: capture.phantoms ?? [],
565
+ viewTransitions: (capture.viewTransitions ?? []).filter((v) => v.startsWith("duplicate")),
566
+ checkFailures: capture.checkFailures ?? []
567
+ };
568
+ const advisories = {
569
+ a11y: capture.a11y ?? [],
570
+ slop: capture.slop ?? [],
571
+ jank: capture.jank ?? []
572
+ };
573
+ const hardCount = (runtime ? 1 : 0) + hard.phantoms.length + hard.viewTransitions.length + hard.checkFailures.length;
574
+ report.audit = { ok: hardCount === 0, hard, advisories, shots: capture.shots.map((s) => s.path) };
575
+ if (hardCount > 0) {
576
+ failed = true;
577
+ console.log(pc5.red(`\u2717 audit: ${hardCount} hard finding(s)`));
578
+ for (const [k, v] of Object.entries(hard)) {
579
+ if (Array.isArray(v) && v.length > 0) console.log(pc5.dim(` ${k}: ${v.join(" \xB7 ")}`));
580
+ else if (typeof v === "string" && v) console.log(pc5.dim(` ${k}: ${v}`));
581
+ }
582
+ } else {
583
+ console.log(`${pc5.green("\u2713")} audit ${pc5.dim(`(${advisories.a11y.length} a11y, ${advisories.slop.length} slop, ${advisories.jank.length} jank advisories)`)}`);
584
+ }
585
+ }
586
+ const { loadFlows } = await import("./flows-MXJL45HW.js");
587
+ const flows = loadFlows(cwd);
588
+ if (flows.length > 0) {
589
+ const { findChrome } = await import("./chrome-EEXJCG6W.js");
590
+ const chrome = findChrome();
591
+ const flowReport = [];
592
+ if (chrome) {
593
+ const { runFlow } = await import("./cdp-D2F4P7UQ.js");
594
+ for (const flow of flows) {
595
+ const result = await runFlow(chrome, opts.url, flow, previewDir(cwd));
596
+ flowReport.push({ name: flow.name, ok: result.ok, detail: result.ok ? void 0 : `step ${result.failedStep}: ${result.detail}` });
597
+ console.log(result.ok ? `${pc5.green("\u2713")} flow ${flow.name}` : pc5.red(`\u2717 flow ${flow.name} \u2014 step ${result.failedStep}: ${result.detail}`));
598
+ if (!result.ok) failed = true;
599
+ }
600
+ }
601
+ report.flows = flowReport;
602
+ }
603
+ }
604
+ report.ok = !failed;
605
+ report.finishedAt = (/* @__PURE__ */ new Date()).toISOString();
606
+ if (opts.json) {
607
+ const fs2 = await import("fs");
608
+ fs2.writeFileSync(opts.json, JSON.stringify(report, null, 2));
609
+ console.log(pc5.dim(`report \u2192 ${opts.json}`));
610
+ }
611
+ if (failed) process.exitCode = 1;
612
+ });
535
613
  program2.command("shot").description("Screenshot a running app at mobile/tablet/desktop viewports (+ .squint/routes)").argument("<url>", "URL of the running app (e.g. http://localhost:5173)").action(async (url) => {
536
- const { captureViewports } = await import("./preview-FBNVDQIV.js");
614
+ const { captureViewports } = await import("./preview-JN5PTWLX.js");
537
615
  const result = await captureViewports(process.cwd(), url);
538
616
  if (!result) {
539
617
  console.error(pc5.red("\u2717 no Chrome/Chromium found"));
@@ -720,7 +798,7 @@ function registerTui(program2) {
720
798
  }
721
799
 
722
800
  // src/cli.tsx
723
- var VERSION = true ? "0.4.8" : "0.0.0-dev";
801
+ var VERSION = true ? "0.5.1" : "0.0.0-dev";
724
802
  var program = new Command();
725
803
  program.name("squint").description("Lovable for your terminal \u2014 a frontend harness on top of Claude Code, Codex, and friends.").version(VERSION);
726
804
  registerRun(program);
@@ -3,7 +3,7 @@ import {
3
3
  COMMANDS,
4
4
  commandHelp,
5
5
  completeCommand
6
- } from "./chunk-43NQNIJY.js";
6
+ } from "./chunk-VJ2QKHYK.js";
7
7
  export {
8
8
  COMMANDS,
9
9
  commandHelp,
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ contextReport,
4
+ formatContextReport
5
+ } from "./chunk-LESZB7DT.js";
6
+ import "./chunk-UBADCBPT.js";
7
+ import "./chunk-IEQGTVWN.js";
8
+ import "./chunk-WAJXATCO.js";
9
+ export {
10
+ contextReport,
11
+ formatContextReport
12
+ };
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ appendDecision,
4
+ decisionsSection,
5
+ loadDecisions
6
+ } from "./chunk-IEQGTVWN.js";
7
+ export {
8
+ appendDecision,
9
+ decisionsSection,
10
+ loadDecisions
11
+ };
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ loadFlows,
4
+ parseFlow,
5
+ stepExpression
6
+ } from "./chunk-4XSHHGA6.js";
7
+ export {
8
+ loadFlows,
9
+ parseFlow,
10
+ stepExpression
11
+ };
@@ -11,11 +11,11 @@ import {
11
11
  probeRuntime,
12
12
  routeShotName,
13
13
  runtimeSummary
14
- } from "./chunk-7RFQWOQV.js";
14
+ } from "./chunk-ERF2SPUW.js";
15
15
  import "./chunk-7CAGWFAQ.js";
16
- import "./chunk-BGBG2MNY.js";
17
- import "./chunk-IMDRXXFU.js";
18
- import "./chunk-KVYGPLWW.js";
16
+ import "./chunk-3YCG234A.js";
17
+ import "./chunk-PYC53J7D.js";
18
+ import "./chunk-GV2HAALP.js";
19
19
  export {
20
20
  VIEWPORTS,
21
21
  buildReviewPrompt,
@@ -5,7 +5,7 @@ import {
5
5
  findBinary,
6
6
  findEngineBinary,
7
7
  getEngine
8
- } from "./chunk-KVYGPLWW.js";
8
+ } from "./chunk-GV2HAALP.js";
9
9
  export {
10
10
  detectEngines,
11
11
  engines,
@@ -2,22 +2,23 @@
2
2
  import {
3
3
  connectDaemon,
4
4
  socketPath
5
- } from "./chunk-ATNTD3V5.js";
6
- import "./chunk-YGPVP4YB.js";
7
- import "./chunk-ARDV4XH6.js";
5
+ } from "./chunk-AMA3F2Y2.js";
6
+ import "./chunk-G5NS2IFQ.js";
7
+ import "./chunk-UBADCBPT.js";
8
+ import "./chunk-IEQGTVWN.js";
8
9
  import "./chunk-AUJJGMZG.js";
9
10
  import "./chunk-YHRAOBI2.js";
10
- import "./chunk-QCHBDP46.js";
11
- import "./chunk-YGSF2TSO.js";
12
- import "./chunk-VH7OOFQP.js";
11
+ import "./chunk-2I3YHT6P.js";
12
+ import "./chunk-J7ITMK6X.js";
13
+ import "./chunk-6NPUVPQD.js";
13
14
  import "./chunk-K5QJMSJH.js";
14
15
  import "./chunk-WAJXATCO.js";
15
16
  import "./chunk-62JNF5M2.js";
16
- import "./chunk-7RFQWOQV.js";
17
+ import "./chunk-ERF2SPUW.js";
17
18
  import "./chunk-7CAGWFAQ.js";
18
- import "./chunk-BGBG2MNY.js";
19
- import "./chunk-IMDRXXFU.js";
20
- import "./chunk-KVYGPLWW.js";
19
+ import "./chunk-3YCG234A.js";
20
+ import "./chunk-PYC53J7D.js";
21
+ import "./chunk-GV2HAALP.js";
21
22
 
22
23
  // src/daemon/remote.ts
23
24
  var noteId = 0;
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runAgent
4
- } from "./chunk-VH7OOFQP.js";
5
- import "./chunk-KVYGPLWW.js";
4
+ } from "./chunk-6NPUVPQD.js";
5
+ import "./chunk-GV2HAALP.js";
6
6
  export {
7
7
  runAgent
8
8
  };
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ contextReport,
4
+ formatContextReport
5
+ } from "./chunk-LESZB7DT.js";
6
+ import "./chunk-UBADCBPT.js";
7
+ import "./chunk-IEQGTVWN.js";
8
+ import "./chunk-WAJXATCO.js";
9
+ import {
10
+ detectGates,
11
+ runGates
12
+ } from "./chunk-62JNF5M2.js";
13
+ import {
14
+ loadFlows
15
+ } from "./chunk-4XSHHGA6.js";
16
+ import {
17
+ captureViewports,
18
+ previewDir,
19
+ runtimeSummary
20
+ } from "./chunk-ERF2SPUW.js";
21
+ import "./chunk-7CAGWFAQ.js";
22
+ import "./chunk-3YCG234A.js";
23
+ import {
24
+ findChrome
25
+ } from "./chunk-PYC53J7D.js";
26
+ import "./chunk-GV2HAALP.js";
27
+
28
+ // src/mcp/server.ts
29
+ import readline from "readline";
30
+ var TOOLS = [
31
+ {
32
+ name: "squint_check",
33
+ description: "Run the repo quality gates (typecheck, lint, format, test, build as detected). Returns each gate with pass/fail and failure output.",
34
+ inputSchema: { type: "object", properties: {} },
35
+ async run(_args, cwd) {
36
+ const gates = detectGates(cwd);
37
+ if (gates.length === 0) return "no gates detected (no package.json scripts or known tools)";
38
+ const results = await runGates(cwd, gates);
39
+ return results.map((r) => `${r.ok ? "\u2713" : "\u2717"} ${r.gate.display}${r.ok ? "" : `
40
+ ${r.outputTail.slice(-1500)}`}`).join("\n");
41
+ }
42
+ },
43
+ {
44
+ name: "squint_shot",
45
+ description: "Screenshot and audit a running app URL headlessly: runtime errors, accessibility sweep, anti-slop tells, phantom classes, view-transition breakage, jank attribution, screen-reader narration. Returns findings; screenshots land in .squint/preview/.",
46
+ inputSchema: { type: "object", properties: { url: { type: "string" } }, required: ["url"] },
47
+ async run(args, cwd) {
48
+ const url = String(args.url ?? "");
49
+ const result = await captureViewports(cwd, url);
50
+ if (!result) return "capture failed \u2014 is Chrome installed and the URL reachable?";
51
+ const sections = [`shots: ${result.shots.map((s) => s.path).join(", ")}`];
52
+ const runtime = result.runtime ? runtimeSummary(result.runtime) : null;
53
+ if (runtime) sections.push(`runtime: ${runtime}`);
54
+ for (const [label, list] of [
55
+ ["a11y", result.a11y],
56
+ ["slop", result.slop],
57
+ ["phantom classes", result.phantoms],
58
+ ["view transitions", result.viewTransitions],
59
+ ["jank", result.jank],
60
+ ["components", result.components]
61
+ ]) {
62
+ if (list && list.length > 0) sections.push(`${label}:
63
+ ${list.join("\n")}`);
64
+ }
65
+ return sections.join("\n\n");
66
+ }
67
+ },
68
+ {
69
+ name: "squint_flows",
70
+ description: "Replay the repo's declared user journeys (.squint/flows/*.flow) headlessly against a URL. Returns pass/fail per flow with the failing step.",
71
+ inputSchema: { type: "object", properties: { url: { type: "string" } }, required: ["url"] },
72
+ async run(args, cwd) {
73
+ const url = String(args.url ?? "");
74
+ const flows = loadFlows(cwd);
75
+ if (flows.length === 0) return "no flows declared \u2014 add .squint/flows/<name>.flow";
76
+ const chrome = findChrome();
77
+ if (!chrome) return "no Chrome/Chromium found";
78
+ const { runFlow } = await import("./cdp-D2F4P7UQ.js");
79
+ const lines = [];
80
+ for (const flow of flows) {
81
+ const result = await runFlow(chrome, url, flow, previewDir(cwd));
82
+ lines.push(
83
+ result.ok ? `\u2713 ${flow.name} (${flow.steps.length} steps)` : `\u2717 ${flow.name} at step ${result.failedStep}: ${result.detail}`
84
+ );
85
+ }
86
+ return lines.join("\n");
87
+ }
88
+ },
89
+ {
90
+ name: "squint_context",
91
+ description: "Itemize what squint injects into engine asks \u2014 token cost per source with staleness warnings (stale locks, generic skill triggers, oversized always-on context).",
92
+ inputSchema: { type: "object", properties: {} },
93
+ async run(_args, cwd) {
94
+ return formatContextReport(contextReport(cwd));
95
+ }
96
+ }
97
+ ];
98
+ function runMcpServer(cwd, input = process.stdin, output = process.stdout) {
99
+ const write = (msg) => output.write(`${JSON.stringify(msg)}
100
+ `);
101
+ const rl = readline.createInterface({ input });
102
+ rl.on("line", (line) => {
103
+ if (!line.trim()) return;
104
+ let req;
105
+ try {
106
+ req = JSON.parse(line);
107
+ } catch {
108
+ return;
109
+ }
110
+ void handle(req, cwd, write);
111
+ });
112
+ }
113
+ async function handle(req, cwd, write) {
114
+ const reply = (result) => {
115
+ if (req.id !== void 0) write({ jsonrpc: "2.0", id: req.id, result });
116
+ };
117
+ const fail = (code, message) => {
118
+ if (req.id !== void 0) write({ jsonrpc: "2.0", id: req.id, error: { code, message } });
119
+ };
120
+ switch (req.method) {
121
+ case "initialize":
122
+ reply({
123
+ protocolVersion: "2025-06-18",
124
+ capabilities: { tools: {} },
125
+ serverInfo: { name: "squint", version: "0" }
126
+ });
127
+ return;
128
+ case "notifications/initialized":
129
+ case "ping":
130
+ if (req.method === "ping") reply({});
131
+ return;
132
+ case "tools/list":
133
+ reply({ tools: TOOLS.map(({ name, description, inputSchema }) => ({ name, description, inputSchema })) });
134
+ return;
135
+ case "tools/call": {
136
+ const name = String(req.params?.name ?? "");
137
+ const tool = TOOLS.find((t) => t.name === name);
138
+ if (!tool) return fail(-32602, `unknown tool: ${name}`);
139
+ try {
140
+ const text = await tool.run(req.params?.arguments ?? {}, cwd);
141
+ reply({ content: [{ type: "text", text }] });
142
+ } catch (error) {
143
+ reply({
144
+ content: [{ type: "text", text: `tool failed: ${error instanceof Error ? error.message : String(error)}` }],
145
+ isError: true
146
+ });
147
+ }
148
+ return;
149
+ }
150
+ default:
151
+ fail(-32601, `method not found: ${req.method}`);
152
+ }
153
+ }
154
+ export {
155
+ runMcpServer
156
+ };
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ screenshotVariants
4
+ } from "./chunk-2I3YHT6P.js";
5
+ import "./chunk-J7ITMK6X.js";
6
+ import "./chunk-6NPUVPQD.js";
7
+ import "./chunk-K5QJMSJH.js";
8
+ import "./chunk-WAJXATCO.js";
9
+ import "./chunk-PYC53J7D.js";
10
+ import "./chunk-GV2HAALP.js";
11
+ export {
12
+ screenshotVariants
13
+ };