@harness-engineering/cli 1.25.1 → 1.25.2

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startServer
4
- } from "../chunk-RX7TUMBR.js";
4
+ } from "../chunk-TBGIHPNA.js";
5
5
  import "../chunk-FES2YEQU.js";
6
6
  import "../chunk-UV3BZMGT.js";
7
7
  import "../chunk-F23H3U5U.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  createProgram,
4
4
  printFirstRunWelcome
5
- } from "../chunk-CJXVNDZZ.js";
5
+ } from "../chunk-5I3W4J5X.js";
6
6
  import "../chunk-5BQ5BOJL.js";
7
7
  import "../chunk-EHRZMOQ2.js";
8
8
  import "../chunk-XTITAVUR.js";
@@ -19,7 +19,7 @@ import "../chunk-P7PANON5.js";
19
19
  import "../chunk-4NK7Z3BP.js";
20
20
  import {
21
21
  dispatchSkillsFromGit
22
- } from "../chunk-RX7TUMBR.js";
22
+ } from "../chunk-TBGIHPNA.js";
23
23
  import "../chunk-FES2YEQU.js";
24
24
  import "../chunk-UV3BZMGT.js";
25
25
  import "../chunk-F23H3U5U.js";
@@ -113,6 +113,96 @@ ${message}
113
113
  }
114
114
  }
115
115
 
116
+ // src/bin/command-telemetry.ts
117
+ import { existsSync, readFileSync, mkdirSync, appendFileSync, writeFileSync } from "fs";
118
+ import { join, parse as parsePath, resolve } from "path";
119
+ import { spawn } from "child_process";
120
+ var EXCLUDED_COMMANDS = /* @__PURE__ */ new Set(["help", "completion"]);
121
+ function findProjectRoot(cwd) {
122
+ let dir = resolve(cwd);
123
+ const { root } = parsePath(dir);
124
+ while (dir !== root) {
125
+ if (existsSync(join(dir, "harness.config.json"))) return dir;
126
+ dir = resolve(dir, "..");
127
+ }
128
+ return cwd;
129
+ }
130
+ var commandName = "";
131
+ var startTime = 0;
132
+ var recorded = false;
133
+ function installCommandTelemetry(program, cwd) {
134
+ if (typeof program.hook !== "function") return;
135
+ const projectRoot = findProjectRoot(cwd);
136
+ flushTelemetryBackground(projectRoot);
137
+ program.hook("preAction", (thisCommand) => {
138
+ commandName = resolveCommandName(thisCommand);
139
+ startTime = Date.now();
140
+ });
141
+ process.on("exit", (code) => {
142
+ if (recorded || !commandName || EXCLUDED_COMMANDS.has(commandName)) return;
143
+ recorded = true;
144
+ const duration = Date.now() - startTime;
145
+ const outcome = code === 0 ? "completed" : "failed";
146
+ writeCommandRecordSync(projectRoot, commandName, duration, outcome);
147
+ });
148
+ }
149
+ function resolveCommandName(cmd) {
150
+ const parts = [];
151
+ let current = cmd;
152
+ while (current) {
153
+ const name = current.name();
154
+ if (name && name !== "harness") {
155
+ parts.unshift(name);
156
+ }
157
+ current = current.parent;
158
+ }
159
+ return parts.length > 0 ? `cli/${parts.join(".")}` : "";
160
+ }
161
+ function writeCommandRecordSync(cwd, command, duration, outcome) {
162
+ try {
163
+ const metricsDir = join(cwd, ".harness", "metrics");
164
+ mkdirSync(metricsDir, { recursive: true });
165
+ const record = {
166
+ skill: command,
167
+ session: `cli-${Date.now()}`,
168
+ startedAt: new Date(Date.now() - duration).toISOString(),
169
+ duration,
170
+ outcome,
171
+ phasesReached: []
172
+ };
173
+ const adoptionFile = join(metricsDir, "adoption.jsonl");
174
+ appendFileSync(adoptionFile, JSON.stringify(record) + "\n");
175
+ } catch {
176
+ }
177
+ }
178
+ function flushTelemetryBackground(cwd) {
179
+ try {
180
+ const adoptionFile = join(cwd, ".harness", "metrics", "adoption.jsonl");
181
+ if (!existsSync(adoptionFile)) return;
182
+ const configPath = join(cwd, "harness.config.json");
183
+ if (existsSync(configPath)) {
184
+ try {
185
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
186
+ if (config?.telemetry?.enabled === false) return;
187
+ } catch {
188
+ }
189
+ }
190
+ if (process.env.DO_NOT_TRACK === "1") return;
191
+ if (process.env.HARNESS_TELEMETRY_OPTOUT === "1") return;
192
+ const reporterPath = join(cwd, ".harness", "hooks", "telemetry-reporter.js");
193
+ if (!existsSync(reporterPath)) return;
194
+ const child = spawn(process.execPath, [reporterPath], {
195
+ cwd,
196
+ stdio: ["pipe", "ignore", "ignore"],
197
+ detached: true
198
+ });
199
+ child.stdin?.write("{}");
200
+ child.stdin?.end();
201
+ child.unref();
202
+ } catch {
203
+ }
204
+ }
205
+
116
206
  // src/skill/dispatch-session.ts
117
207
  import { execSync } from "child_process";
118
208
  import fs from "fs";
@@ -211,6 +301,7 @@ async function main() {
211
301
  () => ({ dispatched: false })
212
302
  );
213
303
  const program = createProgram();
304
+ installCommandTelemetry(program, process.cwd());
214
305
  try {
215
306
  await program.parseAsync(process.argv);
216
307
  } catch (error) {
@@ -56,7 +56,7 @@ import {
56
56
  loadOrRebuildIndex,
57
57
  persistToolingConfig,
58
58
  recommend
59
- } from "./chunk-RX7TUMBR.js";
59
+ } from "./chunk-TBGIHPNA.js";
60
60
  import {
61
61
  findConfigFile,
62
62
  resolveConfig
@@ -3137,7 +3137,12 @@ function buildSettingsHooks(profile) {
3137
3137
  }
3138
3138
  hooks[script.event].push({
3139
3139
  matcher: script.matcher,
3140
- hooks: [{ type: "command", command: `node .harness/hooks/${script.name}.js` }]
3140
+ hooks: [
3141
+ {
3142
+ type: "command",
3143
+ command: `node "$(git rev-parse --show-toplevel)/.harness/hooks/${script.name}.js"`
3144
+ }
3145
+ ]
3141
3146
  });
3142
3147
  }
3143
3148
  return hooks;
@@ -3355,7 +3360,7 @@ function readJson(p) {
3355
3360
  }
3356
3361
  function registerHook(s, ev, matcher, name) {
3357
3362
  if (!s.hooks[ev]) s.hooks[ev] = [];
3358
- const cmd = `node .harness/hooks/${name}.js`;
3363
+ const cmd = `node "$(git rev-parse --show-toplevel)/.harness/hooks/${name}.js"`;
3359
3364
  if (!s.hooks[ev].some((e) => e.hooks?.some((h) => h.command === cmd))) {
3360
3365
  s.hooks[ev].push({ matcher, hooks: [{ type: "command", command: cmd }] });
3361
3366
  }
@@ -5418,7 +5423,7 @@ function createMcpCommand() {
5418
5423
  parseBudget
5419
5424
  ).action(async (opts) => {
5420
5425
  const [{ startServer: startServer2, getToolDefinitions: getToolDefinitions2 }, { selectTier }] = await Promise.all([
5421
- import("./mcp-2553PNUC.js"),
5426
+ import("./mcp-W3FLXSFF.js"),
5422
5427
  import("./tool-tiers-7QGZ3FKY.js")
5423
5428
  ]);
5424
5429
  if (opts.tools && opts.tools.length > 0) {
@@ -6272,6 +6277,18 @@ function prompt(question) {
6272
6277
  });
6273
6278
  });
6274
6279
  }
6280
+ function promptRaw(question) {
6281
+ const rl = readline.createInterface({
6282
+ input: process.stdin,
6283
+ output: process.stdout
6284
+ });
6285
+ return new Promise((resolve35) => {
6286
+ rl.question(question, (answer) => {
6287
+ rl.close();
6288
+ resolve35(answer.trim());
6289
+ });
6290
+ });
6291
+ }
6275
6292
  function isNo(answer) {
6276
6293
  return answer === "n" || answer === "no";
6277
6294
  }
@@ -6312,11 +6329,11 @@ async function promptIdentity() {
6312
6329
  const answer = await prompt(" Set identity fields? (y/N) ");
6313
6330
  const identity = {};
6314
6331
  if (answer === "y" || answer === "yes") {
6315
- const projectName = await prompt(" Project name: ");
6332
+ const projectName = await promptRaw(" Project name: ");
6316
6333
  if (projectName) identity.project = projectName;
6317
- const teamName = await prompt(" Team name: ");
6334
+ const teamName = await promptRaw(" Team name: ");
6318
6335
  if (teamName) identity.team = teamName;
6319
- const alias = await prompt(" Alias: ");
6336
+ const alias = await promptRaw(" Alias: ");
6320
6337
  if (alias) identity.alias = alias;
6321
6338
  }
6322
6339
  return identity;
@@ -564,6 +564,8 @@ function ensureHarnessGitignore(targetDir) {
564
564
  const content = `# Runtime artifacts (generated, ephemeral, session-scoped)
565
565
  graph/
566
566
  debug/
567
+ hooks/
568
+ security/
567
569
  sessions/
568
570
  state.json
569
571
  state/
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  runSnapshotCapture,
13
13
  runUninstall,
14
14
  runUninstallConstraints
15
- } from "./chunk-CJXVNDZZ.js";
15
+ } from "./chunk-5I3W4J5X.js";
16
16
  import {
17
17
  generateAgentsMd
18
18
  } from "./chunk-5BQ5BOJL.js";
@@ -66,7 +66,7 @@ import {
66
66
  generateSlashCommands,
67
67
  getToolDefinitions,
68
68
  startServer
69
- } from "./chunk-RX7TUMBR.js";
69
+ } from "./chunk-TBGIHPNA.js";
70
70
  import "./chunk-FES2YEQU.js";
71
71
  import "./chunk-UV3BZMGT.js";
72
72
  import "./chunk-F23H3U5U.js";
@@ -2,7 +2,7 @@ import {
2
2
  createHarnessServer,
3
3
  getToolDefinitions,
4
4
  startServer
5
- } from "./chunk-RX7TUMBR.js";
5
+ } from "./chunk-TBGIHPNA.js";
6
6
  import "./chunk-FES2YEQU.js";
7
7
  import "./chunk-UV3BZMGT.js";
8
8
  import "./chunk-F23H3U5U.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harness-engineering/cli",
3
- "version": "1.25.1",
3
+ "version": "1.25.2",
4
4
  "description": "CLI for Harness Engineering toolkit",
5
5
  "type": "module",
6
6
  "bin": {
@@ -40,8 +40,8 @@
40
40
  "@harness-engineering/core": "0.22.0",
41
41
  "@harness-engineering/dashboard": "0.1.5",
42
42
  "@harness-engineering/graph": "0.4.3",
43
- "@harness-engineering/orchestrator": "0.2.8",
44
43
  "@harness-engineering/linter-gen": "0.1.6",
44
+ "@harness-engineering/orchestrator": "0.2.8",
45
45
  "@harness-engineering/types": "0.9.2"
46
46
  },
47
47
  "devDependencies": {