humanish 0.75.0 → 0.77.0

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/program.js CHANGED
@@ -13,7 +13,7 @@ import { runInit } from "./init.js";
13
13
  import { computeStats, formatStatsHuman } from "./stats.js";
14
14
  import { PortInUseError } from "./listen.js";
15
15
  import { DEFAULT_EXPORT_MAX_BYTES, exportRun, formatExportHuman } from "./export.js";
16
- import { buildPayload, disabledByEnvironment, inHumanishCheckout, durationBucket, readTelemetryState, sendTelemetry, telemetryStatePath, deriveStudyFacts, TELEMETRY_NOTICE, writeTelemetryState } from "./telemetry.js";
16
+ import { buildPayload, disabledByEnvironment, durationBucket, readTelemetryState, sendTelemetry, telemetryStatePath, deriveStudyFacts, TELEMETRY_NOTICE, writeTelemetryState, isOwnCheckoutRun } from "./telemetry.js";
17
17
  import { inspectLabManifest, listLabManifests, resolveLabManifest } from "./labs.js";
18
18
  import { runLabPreflight } from "./lab-preflight.js";
19
19
  import { runLab, resolveLabDryRun, selectLabBackend } from "./lab-engine.js";
@@ -107,8 +107,9 @@ async function recordCommandTelemetry(command, ok, durationMs, exitCode) {
107
107
  return;
108
108
  if (disabledByEnvironment(process.env))
109
109
  return;
110
- // Our own checkout never reports. See inHumanishCheckout for the measured reason.
111
- if (inHumanishCheckout(process.cwd(), (p) => readFileSync(p, "utf8")))
110
+ // Our own checkout never reports, from whichever directory the command was started: see
111
+ // isOwnCheckoutRun for the measured reason both walks exist.
112
+ if (isOwnCheckoutRun(process.cwd(), dirname(fileURLToPath(import.meta.url)), (p) => readFileSync(p, "utf8")))
112
113
  return;
113
114
  const state = await readTelemetryState();
114
115
  if (!state.enabled)
@@ -1744,9 +1745,10 @@ function registerFeedbackCommands(parent, io) {
1744
1745
  .description("Generate a public-safe feedback draft from verified evidence.")
1745
1746
  .option("--run <id>", "Run id or latest pointer.", "latest")
1746
1747
  .option("--cwd <path>", "Target project directory.", ".")
1748
+ .option("--candidate <id>", "Which finding to draft (ids from `feedback list`); default: the first.")
1747
1749
  .option("--json", JSON_OPTION_DESCRIPTION)
1748
1750
  .action(async (options, command) => {
1749
- const result = await draftFeedback(options.cwd, options.run);
1751
+ const result = await draftFeedback(options.cwd, options.run, candidateOption(options));
1750
1752
  writeResult(command, io, result, formatFeedbackHuman);
1751
1753
  io.setExitCode(result.ok ? 0 : 2);
1752
1754
  });
@@ -1755,9 +1757,10 @@ function registerFeedbackCommands(parent, io) {
1755
1757
  .description("Verify the feedback draft for public issue eligibility.")
1756
1758
  .option("--run <id>", "Run id or latest pointer.", "latest")
1757
1759
  .option("--cwd <path>", "Target project directory.", ".")
1760
+ .option("--candidate <id>", "Which finding to verify (ids from `feedback list`); default: the first.")
1758
1761
  .option("--json", JSON_OPTION_DESCRIPTION)
1759
1762
  .action(async (options, command) => {
1760
- const result = await verifyFeedback(options.cwd, options.run);
1763
+ const result = await verifyFeedback(options.cwd, options.run, candidateOption(options));
1761
1764
  writeResult(command, io, result, formatFeedbackHuman);
1762
1765
  io.setExitCode(result.ok ? 0 : 2);
1763
1766
  });
@@ -1768,9 +1771,10 @@ function registerFeedbackCommands(parent, io) {
1768
1771
  .option("--cwd <path>", "Target project directory.", ".")
1769
1772
  .requiredOption("--repo <owner/repo>", "Repository slug used in rendered filing instructions.")
1770
1773
  .option("--format <format>", "Output format.", "markdown")
1774
+ .option("--candidate <id>", "Which finding to file (ids from `feedback list`); default: the first.")
1771
1775
  .option("--json", JSON_OPTION_DESCRIPTION)
1772
1776
  .action(async (options, command) => {
1773
- const result = await renderIssueMarkdown(options.cwd, options.run, options.repo);
1777
+ const result = await renderIssueMarkdown(options.cwd, options.run, options.repo, candidateOption(options));
1774
1778
  if (wantsJson(command)) {
1775
1779
  io.writeOut(`${JSON.stringify(result, null, 2)}\n`);
1776
1780
  }
@@ -1793,9 +1797,10 @@ function registerFeedbackCommands(parent, io) {
1793
1797
  .option("--run <id>", "Run id or latest pointer.", "latest")
1794
1798
  .option("--cwd <path>", "Target project directory.", ".")
1795
1799
  .requiredOption("--repo <owner/repo>", "Repository slug used in the generated URL.")
1800
+ .option("--candidate <id>", "Which finding to link (ids from `feedback list`); default: the first.")
1796
1801
  .option("--json", JSON_OPTION_DESCRIPTION)
1797
1802
  .action(async (options, command) => {
1798
- const result = await renderIssueUrl(options.cwd, options.run, options.repo);
1803
+ const result = await renderIssueUrl(options.cwd, options.run, options.repo, candidateOption(options));
1799
1804
  if (wantsJson(command)) {
1800
1805
  io.writeOut(`${JSON.stringify(result, null, 2)}\n`);
1801
1806
  }
@@ -3438,15 +3443,28 @@ function exitCodeForSignal(signal) {
3438
3443
  return 129;
3439
3444
  }
3440
3445
  }
3446
+ /** `--candidate` as the module option, absent when not given (exactOptionalPropertyTypes). */
3447
+ function candidateOption(options) {
3448
+ return options.candidate === undefined ? {} : { candidate: options.candidate };
3449
+ }
3441
3450
  function formatFeedbackHuman(result) {
3442
3451
  if (!result.ok) {
3443
3452
  return `${result.error?.code}: ${result.error?.message}\n`;
3444
3453
  }
3454
+ const candidates = result.candidates ?? [];
3445
3455
  return [
3446
3456
  "humanish feedback ready",
3447
3457
  `run: ${result.run}`,
3448
3458
  ...(result.draftPath ? [`draft: ${result.draftPath}`] : []),
3449
- ...(result.issuePath ? [`issue: ${result.issuePath}`] : [])
3459
+ ...(result.issuePath ? [`issue: ${result.issuePath}`] : []),
3460
+ ...(result.draft?.source_candidate_id ? [`candidate: ${result.draft.source_candidate_id}`] : []),
3461
+ // Every finding the run produced, so the second and third are one flag away (#609).
3462
+ ...(candidates.length > 1 || (candidates.length === 1 && result.draft === undefined)
3463
+ ? [
3464
+ `candidates (${candidates.length}; choose one with --candidate <id>):`,
3465
+ ...candidates.map((item) => `- ${item.id} [${item.failure_owner}] ${item.persona_id}: ${item.summary}`)
3466
+ ]
3467
+ : [])
3450
3468
  ].join("\n") + "\n";
3451
3469
  }
3452
3470
  function formatOssLabHuman(result) {