@codacy/verity-cli 0.31.1-experimental.b9b3862 → 0.31.1-experimental.f2f59c0

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
@@ -5,6 +5,31 @@ All notable changes to Verity are documented here. This project follows
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ### ⌨️ The setup questions answer to arrow keys
9
+
10
+ - **`verity init` no longer asks you to type a number.** Analysis intensity and
11
+ the review moments are arrow-key lists: `↑↓` to move, `space` to toggle a
12
+ moment, `enter` to confirm — with the recommended answer already under the
13
+ cursor and the default set already ticked, so **Enter alone still gives exactly
14
+ what it gave before**.
15
+ - **Digits still work.** This prompt used to be "type a number", and muscle memory
16
+ should not be punished for an interface improvement — a digit moves the cursor
17
+ rather than confirming, so it composes with the arrows instead of being a
18
+ second, hidden way to answer. `j`/`k` move too.
19
+ - **An empty moment selection is refused, not accepted.** Unticking everything and
20
+ pressing Enter says so instead of installing a review tool that reviews nothing
21
+ — the same invariant the typed prompt held by falling back.
22
+ - **Three rungs of degradation, same default at each.** Arrow keys on a real
23
+ terminal; the typed number prompt when the terminal cannot do raw mode; the
24
+ default when there is no terminal at all or stdin ends. An interface improvement
25
+ must not become a new way for a setup to get stuck — CI, pipes and agent Bash
26
+ calls behave exactly as before.
27
+ - **The terminal is restored on every exit,** including Ctrl+C, which restores
28
+ before exiting: raw mode left on outlives the process and makes the user's next
29
+ shell prompt unusable.
30
+
31
+ ## [Unreleased]
32
+
8
33
  ### 🤝 Joining a project that already has a Standard
9
34
 
10
35
  - **`verity init` now offers the Standard the service already holds** for this
package/README.md CHANGED
@@ -11,8 +11,9 @@ verity init
11
11
  ```
12
12
 
13
13
  `verity init` is the whole setup. It asks how deeply to review and when
14
- (on stop / before commit / before push), wires everything, offers the optional
15
- GitHub login then either **adopts the Standard your team already has**, or
14
+ (on stop / before commit / before push) with arrow-key lists `↑↓` to move,
15
+ `space` to toggle, `enter` to confirm, and Enter alone takes the recommended
16
+ answers — wires everything, offers the optional GitHub login — then either **adopts the Standard your team already has**, or
16
17
  launches Claude Code to synthesize one from your codebase (`/verity-setup`).
17
18
 
18
19
  ### Joining a project that already uses Verity
package/bin/verity.js CHANGED
@@ -19364,7 +19364,7 @@ function channelSilence(input) {
19364
19364
  // src/lib/cli-version.ts
19365
19365
  function cliVersion() {
19366
19366
  try {
19367
- return true ? "0.31.1-experimental.b9b3862" : "dev";
19367
+ return true ? "0.31.1-experimental.f2f59c0" : "dev";
19368
19368
  } catch {
19369
19369
  return "dev";
19370
19370
  }
@@ -24075,12 +24075,168 @@ function registerMigrateCommand(program2) {
24075
24075
  }
24076
24076
 
24077
24077
  // src/lib/prompt.ts
24078
- var readline2 = __toESM(require("node:readline/promises"));
24078
+ var readline3 = __toESM(require("node:readline/promises"));
24079
+
24080
+ // src/lib/select.ts
24081
+ var readline2 = __toESM(require("node:readline"));
24082
+ function keyToAction(str, key) {
24083
+ const name = key?.name;
24084
+ if (key?.ctrl && (name === "c" || str === "")) return { type: "interrupt" };
24085
+ if (key?.ctrl && (name === "d" || str === "")) return { type: "eof" };
24086
+ switch (name) {
24087
+ case "up":
24088
+ return { type: "move", delta: -1 };
24089
+ case "down":
24090
+ return { type: "move", delta: 1 };
24091
+ case "k":
24092
+ return key?.ctrl ? null : { type: "move", delta: -1 };
24093
+ case "j":
24094
+ return key?.ctrl ? null : { type: "move", delta: 1 };
24095
+ case "space":
24096
+ return { type: "toggle" };
24097
+ case "return":
24098
+ case "enter":
24099
+ return { type: "confirm" };
24100
+ default:
24101
+ break;
24102
+ }
24103
+ if (str === " ") return { type: "toggle" };
24104
+ if (str === "\r" || str === "\n") return { type: "confirm" };
24105
+ if (str && /^[1-9]$/.test(str)) return { type: "jump", index: Number(str) - 1 };
24106
+ return null;
24107
+ }
24108
+ function applyKey(state, action, count, mode2) {
24109
+ switch (action.type) {
24110
+ case "move": {
24111
+ const cursor = (state.cursor + action.delta + count) % count;
24112
+ return { status: "open", state: { cursor, chosen: state.chosen } };
24113
+ }
24114
+ case "jump": {
24115
+ if (action.index >= count) return { status: "open", state };
24116
+ return { status: "open", state: { cursor: action.index, chosen: state.chosen } };
24117
+ }
24118
+ case "toggle": {
24119
+ if (mode2 === "single") {
24120
+ return { status: "open", state: { cursor: state.cursor, chosen: /* @__PURE__ */ new Set([state.cursor]) } };
24121
+ }
24122
+ const chosen = new Set(state.chosen);
24123
+ if (chosen.has(state.cursor)) chosen.delete(state.cursor);
24124
+ else chosen.add(state.cursor);
24125
+ return { status: "open", state: { cursor: state.cursor, chosen } };
24126
+ }
24127
+ case "confirm": {
24128
+ if (mode2 === "single") return { status: "confirmed", indices: [state.cursor] };
24129
+ if (state.chosen.size === 0) {
24130
+ return {
24131
+ status: "open",
24132
+ state: { ...state, hint: "Select at least one \u2014 space toggles the option under the cursor." }
24133
+ };
24134
+ }
24135
+ return { status: "confirmed", indices: [...state.chosen].sort((a, b) => a - b) };
24136
+ }
24137
+ case "interrupt":
24138
+ return { status: "interrupt" };
24139
+ case "eof":
24140
+ return { status: "eof" };
24141
+ }
24142
+ }
24143
+ var GREEN3 = "\x1B[0;32m";
24144
+ var DIM4 = "\x1B[2m";
24145
+ var BOLD2 = "\x1B[1m";
24146
+ var RESET3 = "\x1B[0m";
24147
+ function renderSelect(question, choices, state, mode2, color = colorEnabled()) {
24148
+ const paint = (text, code) => color ? `${code}${text}${RESET3}` : text;
24149
+ const lines = ["", ` ${question}`];
24150
+ const labelOf = (c) => `${c.label}${c.recommended ? " (recommended)" : ""}`;
24151
+ const gutter = Math.max(...choices.map((c) => labelOf(c).length));
24152
+ choices.forEach((choice, i) => {
24153
+ const here = i === state.cursor;
24154
+ const marker = state.chosen.has(i) ? "\u25C9" : "\u25CB";
24155
+ const cursor = here ? "\u276F" : " ";
24156
+ const label2 = labelOf(choice);
24157
+ const pad = choice.hint ? " ".repeat(gutter - label2.length) : "";
24158
+ const hint = choice.hint ? `${pad} ${paint(choice.hint, DIM4)}` : "";
24159
+ lines.push(` ${cursor} ${marker} ${here ? paint(label2, BOLD2) : label2}${hint}`);
24160
+ });
24161
+ const keys = mode2 === "multi" ? "\u2191\u2193 move \xB7 space toggle \xB7 enter confirm" : "\u2191\u2193 move \xB7 enter confirm";
24162
+ lines.push(` ${paint(state.hint ?? keys, state.hint ? GREEN3 : DIM4)}`);
24163
+ return lines;
24164
+ }
24165
+ function runSelect(opts) {
24166
+ const input = opts.input ?? process.stdin;
24167
+ const output = opts.output ?? process.stdout;
24168
+ const { choices, mode: mode2 } = opts;
24169
+ if (typeof input.setRawMode !== "function" || !input.isTTY) return Promise.resolve(null);
24170
+ const initialIdx = choices.map((c, i) => opts.initial.includes(c.id) ? i : -1).filter((i) => i >= 0);
24171
+ let state = {
24172
+ cursor: initialIdx[0] ?? 0,
24173
+ chosen: new Set(mode2 === "single" ? [initialIdx[0] ?? 0] : initialIdx)
24174
+ };
24175
+ return new Promise((resolve4) => {
24176
+ let painted = 0;
24177
+ let settled = false;
24178
+ const draw = () => {
24179
+ if (painted > 0) {
24180
+ readline2.moveCursor(output, 0, -painted);
24181
+ readline2.cursorTo(output, 0);
24182
+ readline2.clearScreenDown(output);
24183
+ }
24184
+ const lines = renderSelect(opts.question, choices, state, mode2);
24185
+ output.write(lines.join("\n") + "\n");
24186
+ painted = lines.length;
24187
+ };
24188
+ const onKey = (str, key) => {
24189
+ const action = keyToAction(str, key);
24190
+ if (!action) return;
24191
+ const outcome = applyKey(state, action, choices.length, mode2);
24192
+ if (outcome.status === "open") {
24193
+ state = outcome.state;
24194
+ draw();
24195
+ return;
24196
+ }
24197
+ if (outcome.status === "confirmed") {
24198
+ state = { ...state, hint: void 0 };
24199
+ draw();
24200
+ finish(outcome.indices.map((i) => choices[i].id));
24201
+ return;
24202
+ }
24203
+ if (outcome.status === "eof") {
24204
+ finish(null);
24205
+ return;
24206
+ }
24207
+ restore();
24208
+ output.write("\n");
24209
+ process.exit(130);
24210
+ };
24211
+ const restore = () => {
24212
+ input.removeListener("keypress", onKey);
24213
+ try {
24214
+ input.setRawMode(false);
24215
+ } catch {
24216
+ }
24217
+ input.pause();
24218
+ };
24219
+ const finish = (value) => {
24220
+ if (settled) return;
24221
+ settled = true;
24222
+ restore();
24223
+ resolve4(value);
24224
+ };
24225
+ readline2.emitKeypressEvents(input);
24226
+ input.setRawMode(true);
24227
+ input.resume();
24228
+ input.on("keypress", onKey);
24229
+ input.once("end", () => finish(null));
24230
+ draw();
24231
+ });
24232
+ }
24233
+
24234
+ // src/lib/prompt.ts
24079
24235
  function interactive() {
24080
24236
  return !!process.stdin.isTTY && !!process.stdout.isTTY;
24081
24237
  }
24082
24238
  async function askLine(question, io = {}) {
24083
- const rl = readline2.createInterface({
24239
+ const rl = readline3.createInterface({
24084
24240
  input: io.input ?? process.stdin,
24085
24241
  output: io.output ?? process.stdout
24086
24242
  });
@@ -24138,6 +24294,8 @@ function printOptions(question, choices) {
24138
24294
  }
24139
24295
  async function promptChoice(question, choices, fallback) {
24140
24296
  if (!interactive()) return fallback;
24297
+ const picked = await runSelect({ question, choices, initial: [fallback], mode: "single" });
24298
+ if (picked !== null) return picked[0] ?? fallback;
24141
24299
  printOptions(question, choices);
24142
24300
  const defaultIdx = choices.findIndex((c) => c.id === fallback);
24143
24301
  const answer = await ask(` Choose [${defaultIdx + 1}]: `);
@@ -24151,6 +24309,8 @@ async function promptChoice(question, choices, fallback) {
24151
24309
  }
24152
24310
  async function promptMultiSelect(question, choices, fallback) {
24153
24311
  if (!interactive()) return [...fallback];
24312
+ const picked = await runSelect({ question, choices, initial: fallback, mode: "multi" });
24313
+ if (picked !== null) return picked.length > 0 ? picked : [...fallback];
24154
24314
  printOptions(question, choices);
24155
24315
  const defaultLabel = choices.map((c, i) => fallback.includes(c.id) ? String(i + 1) : null).filter(Boolean).join(",");
24156
24316
  const answer = await ask(` Choose one or more, comma-separated [${defaultLabel}]: `);
@@ -24853,7 +25013,7 @@ function registerInitCommand(program2) {
24853
25013
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
24854
25014
  init: {
24855
25015
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
24856
- cli_version: true ? "0.31.1-experimental.b9b3862" : "dev"
25016
+ cli_version: true ? "0.31.1-experimental.f2f59c0" : "dev"
24857
25017
  }
24858
25018
  });
24859
25019
  } catch (err) {
@@ -25524,8 +25684,8 @@ function registerTelemetryCommands(program2) {
25524
25684
  }
25525
25685
 
25526
25686
  // src/cli.ts
25527
- program.name("verity").description("CLI for Verity quality gate service").version("0.31.1-experimental.b9b3862").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
25528
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.31.1-experimental.b9b3862");
25687
+ program.name("verity").description("CLI for Verity quality gate service").version("0.31.1-experimental.f2f59c0").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
25688
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.31.1-experimental.f2f59c0");
25529
25689
  setUserNamedServiceUrl(program.opts().serviceUrl);
25530
25690
  try {
25531
25691
  await foldLegacyLocalCredential();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/verity-cli",
3
- "version": "0.31.1-experimental.b9b3862",
3
+ "version": "0.31.1-experimental.f2f59c0",
4
4
  "description": "CLI for Verity quality gate service",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://verity.md",