@fusengine/harness 0.1.69 → 0.1.70

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/cli/bin.mjs CHANGED
@@ -4,7 +4,7 @@ import { t as detectHarness } from "../harness-Cb9xR8dC.mjs";
4
4
  import { t as claudeHome } from "../home-state-D0RLWP8J.mjs";
5
5
  import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-B9Br7SEr.mjs";
6
6
  import { n as writeInitFile, t as initFor } from "../run-Do2JltgU.mjs";
7
- import { $ as versionBanner, Q as runningVersion, Rt as todayUtc, Z as runDoctor, t as handleHook } from "../handle-CVk0NlTg.mjs";
7
+ import { $ as runningVersion, Q as runDoctor, Z as notify, et as versionBanner, t as handleHook, zt as todayUtc } from "../handle-ClfFahJs.mjs";
8
8
  import { p as readStdin$1 } from "../claude-CHpb1U0A.mjs";
9
9
  import { delimiter, join } from "node:path";
10
10
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
@@ -354,6 +354,57 @@ function discoverRefs(home, cwd, marketplaces) {
354
354
  return [...bySkill.values()].join(delimiter);
355
355
  }
356
356
  //#endregion
357
+ //#region src/cli/hook-sound.ts
358
+ /**
359
+ * @module hook-sound
360
+ * CLI short-circuit for `harness hook ... --sound <kind>` — play the embedded
361
+ * notification sound and exit, bypassing stdin/handleHook entirely. Lets
362
+ * plugin hooks.json entries call the harness directly instead of a native
363
+ * `afplay`. Harness-agnostic by design: no gate on harness id here — codex,
364
+ * cursor, and hermes hooks.json may call this flag exactly the same way.
365
+ * @packageDocumentation
366
+ */
367
+ /** Recognised sound kinds — anything else fails closed (returns `null`). */
368
+ const KINDS = /* @__PURE__ */ new Set([
369
+ "stop",
370
+ "permission",
371
+ "human"
372
+ ]);
373
+ /**
374
+ * Parse a `--sound <kind>` or `--sound=<kind>` flag anywhere in `argv`.
375
+ * Returns the kind only when it is a recognised {@link SoundKind}; an absent
376
+ * flag or an unrecognised value both yield `null` (fail-closed). Pure — no
377
+ * side effects, so it is directly unit-testable.
378
+ * @param argv - Full argv array (e.g. `process.argv`).
379
+ */
380
+ function soundArg(argv) {
381
+ for (let i = 0; i < argv.length; i++) {
382
+ const arg = argv[i];
383
+ if (arg === "--sound") {
384
+ const val = argv[i + 1];
385
+ return val !== void 0 && KINDS.has(val) ? val : null;
386
+ }
387
+ if (arg !== void 0 && arg.startsWith("--sound=")) {
388
+ const val = arg.slice(8);
389
+ return KINDS.has(val) ? val : null;
390
+ }
391
+ }
392
+ return null;
393
+ }
394
+ /**
395
+ * Play the sound requested by a `--sound <kind>` flag in `argv`, if present
396
+ * and valid. Fire-and-forget via {@link notify} (fail-open, respects
397
+ * `FUSE_HARNESS_SOUND=0`). Returns whether a sound was triggered, so the
398
+ * caller can short-circuit (exit 0) without ever reading stdin.
399
+ * @param argv - Full argv array (e.g. `process.argv`).
400
+ */
401
+ function maybePlaySound(argv) {
402
+ const kind = soundArg(argv);
403
+ if (!kind) return false;
404
+ notify(kind);
405
+ return true;
406
+ }
407
+ //#endregion
357
408
  //#region src/cli/bin.ts
358
409
  /**
359
410
  * harness — CLI for @fusengine/harness.
@@ -402,6 +453,7 @@ if (cmd === "--version" || cmd === "-v") {
402
453
  "memory",
403
454
  "tailwindcss"
404
455
  ])).has(scopeArg) ? scopeArg : "core";
456
+ if (maybePlaySound(process.argv)) process.exit(0);
405
457
  const marketplaces = (process.env.FUSE_HARNESS_MARKETPLACES ?? "fusengine-plugins").split(",").map((s) => s.trim()).filter(Boolean);
406
458
  const refsDir = process.env.FUSE_HARNESS_REFS || discoverRefs(homedir(), process.cwd(), marketplaces) || void 0;
407
459
  traceHook("args", {
@@ -8960,4 +8960,4 @@ async function handleHook(id, payload, opts) {
8960
8960
  });
8961
8961
  }
8962
8962
  //#endregion
8963
- export { versionBanner as $, trackMcpResearch as A, projectHash$1 as At, generateProjectMap as B, seoPostToolUse as C, devContext as Ct, securityAdvisoryForPatch as D, promptSubmitContext as Dt, securityAdvisory as E, claudeMdKey as Et, dispatchAipilot as F, saveSecurityState as Ft, countFiles as G, writeTree as H, dispatchLessons as I, securityStateDir as It, lessonsArchiveFileFor as J, getFileDesc as K, cartoSessionStart as L, securityStatePath as Lt, trackEnrichment as M, normalizeEvent as Mt, dispatchLifecycle as N, isoUtc as Nt, postTrackingSideEffects as O, taskContext as Ot, aipilotPostToolUse as P, loadSecurityState as Pt, runningVersion as Q, generateEcosystemMap as R, todayUtc as Rt, postEditContext as S, trimLogFile as St, dispatchMemory as T, projectContext as Tt, loadEnriched as U, isProject as V, mergeLines as W, lessonsStateFileFor as X, lessonsFileFor as Y, runDoctor as Z, preCommitGate as _, runSessionStartCleanups as _t, recordActivity as a, logToolFailure as at, extractSymbols as b, purgeTtlTree as bt, MCP_TTL_MS as c, subagentCacheContext as ct, isMcpTool as d, checkFileSize as dt, postEditTypescript as et, queryOf as f, countLoc as ft, gate as g, readRules as gt, TRIVIAL_BUDGET as h, injectRules as ht, respond as i, saveApexState as it, trackSkillRead as j, trackFile as jt, trackWatchResearch as k, defaultStateDir as kt, WEBFETCH_TTL_MS as l, validateTailwind as lt, REQUIRED_AGENTS as m, solidDetectStart as mt, activityFor as n, validateRulesLoaded as nt, mcpPostStore as o, validateTeammateOutput as ot, DEFAULT_WINDOW_MS as p, detectSolidProfile as pt, listChildren as q, handlePre as r, cleanupSession as rt, mcpPreIntercept as s, trackAgentMemory as st, handleHook as t, trackSessionChanges as tt, cacheQueryOf as u, validateSolidGate as ut, detectDuplication as v, sessionStartCore as vt, seoPostToolUseResponse as w, gitContext as wt, lifecycleStdout as x, removeOldFiles as xt, dryGate as y, pruneEmptyDirs as yt, writePluginMap as z };
8963
+ export { runningVersion as $, trackMcpResearch as A, defaultStateDir as At, generateProjectMap as B, seoPostToolUse as C, trimLogFile as Ct, securityAdvisoryForPatch as D, claudeMdKey as Dt, securityAdvisory as E, projectContext as Et, dispatchAipilot as F, loadSecurityState as Ft, countFiles as G, writeTree as H, dispatchLessons as I, saveSecurityState as It, lessonsArchiveFileFor as J, getFileDesc as K, cartoSessionStart as L, securityStateDir as Lt, trackEnrichment as M, trackFile as Mt, dispatchLifecycle as N, normalizeEvent as Nt, postTrackingSideEffects as O, promptSubmitContext as Ot, aipilotPostToolUse as P, isoUtc as Pt, runDoctor as Q, generateEcosystemMap as R, securityStatePath as Rt, postEditContext as S, removeOldFiles as St, dispatchMemory as T, gitContext as Tt, loadEnriched as U, isProject as V, mergeLines as W, lessonsStateFileFor as X, lessonsFileFor as Y, notify as Z, preCommitGate as _, readRules as _t, recordActivity as a, saveApexState as at, extractSymbols as b, pruneEmptyDirs as bt, MCP_TTL_MS as c, trackAgentMemory as ct, isMcpTool as d, validateSolidGate as dt, versionBanner as et, queryOf as f, checkFileSize as ft, gate as g, injectRules as gt, TRIVIAL_BUDGET as h, solidDetectStart as ht, respond as i, cleanupSession as it, trackSkillRead as j, projectHash$1 as jt, trackWatchResearch as k, taskContext as kt, WEBFETCH_TTL_MS as l, subagentCacheContext as lt, REQUIRED_AGENTS as m, detectSolidProfile as mt, activityFor as n, trackSessionChanges as nt, mcpPostStore as o, logToolFailure as ot, DEFAULT_WINDOW_MS as p, countLoc as pt, listChildren as q, handlePre as r, validateRulesLoaded as rt, mcpPreIntercept as s, validateTeammateOutput as st, handleHook as t, postEditTypescript as tt, cacheQueryOf as u, validateTailwind as ut, detectDuplication as v, runSessionStartCleanups as vt, seoPostToolUseResponse as w, devContext as wt, lifecycleStdout as x, purgeTtlTree as xt, dryGate as y, sessionStartCore as yt, writePluginMap as z, todayUtc as zt };
@@ -1,6 +1,6 @@
1
1
  import { r as projectLayout } from "../layout-C0jaaCQC.mjs";
2
2
  import { a as sanitizeSessionId, c as sessionsDir, i as loadSessionState, n as fuseHarnessHome, o as saveSessionState, r as fusengineCache, s as sessionStatePath, t as claudeHome } from "../home-state-D0RLWP8J.mjs";
3
- import { A as trackMcpResearch, At as projectHash, B as generateProjectMap, C as seoPostToolUse, Ct as devContext, D as securityAdvisoryForPatch, Dt as promptSubmitContext, E as securityAdvisory, Et as claudeMdKey, F as dispatchAipilot, Ft as saveSecurityState, G as countFiles, H as writeTree, I as dispatchLessons, It as securityStateDir, J as lessonsArchiveFileFor, K as getFileDesc, L as cartoSessionStart, Lt as securityStatePath, M as trackEnrichment, Mt as normalizeEvent, N as dispatchLifecycle, Nt as isoUtc, O as postTrackingSideEffects, Ot as taskContext, P as aipilotPostToolUse, Pt as loadSecurityState, R as generateEcosystemMap, Rt as todayUtc, S as postEditContext, St as trimLogFile, T as dispatchMemory, Tt as projectContext, U as loadEnriched, V as isProject, W as mergeLines, X as lessonsStateFileFor, Y as lessonsFileFor, _ as preCommitGate, _t as runSessionStartCleanups, a as recordActivity, at as logToolFailure, b as extractSymbols, bt as purgeTtlTree, c as MCP_TTL_MS, ct as subagentCacheContext, d as isMcpTool, dt as checkFileSize, et as postEditTypescript, f as queryOf, ft as countLoc, g as gate, gt as readRules, h as TRIVIAL_BUDGET, ht as injectRules, i as respond, it as saveApexState, j as trackSkillRead, jt as trackFile, k as trackWatchResearch, kt as defaultStateDir, l as WEBFETCH_TTL_MS, lt as validateTailwind, m as REQUIRED_AGENTS, mt as solidDetectStart, n as activityFor, nt as validateRulesLoaded, o as mcpPostStore, ot as validateTeammateOutput, p as DEFAULT_WINDOW_MS, pt as detectSolidProfile, q as listChildren, r as handlePre, rt as cleanupSession, s as mcpPreIntercept, st as trackAgentMemory, t as handleHook, tt as trackSessionChanges, u as cacheQueryOf, ut as validateSolidGate, v as detectDuplication, vt as sessionStartCore, w as seoPostToolUseResponse, wt as gitContext, x as lifecycleStdout, xt as removeOldFiles, y as dryGate, yt as pruneEmptyDirs, z as writePluginMap } from "../handle-CVk0NlTg.mjs";
3
+ import { A as trackMcpResearch, At as defaultStateDir, B as generateProjectMap, C as seoPostToolUse, Ct as trimLogFile, D as securityAdvisoryForPatch, Dt as claudeMdKey, E as securityAdvisory, Et as projectContext, F as dispatchAipilot, Ft as loadSecurityState, G as countFiles, H as writeTree, I as dispatchLessons, It as saveSecurityState, J as lessonsArchiveFileFor, K as getFileDesc, L as cartoSessionStart, Lt as securityStateDir, M as trackEnrichment, Mt as trackFile, N as dispatchLifecycle, Nt as normalizeEvent, O as postTrackingSideEffects, Ot as promptSubmitContext, P as aipilotPostToolUse, Pt as isoUtc, R as generateEcosystemMap, Rt as securityStatePath, S as postEditContext, St as removeOldFiles, T as dispatchMemory, Tt as gitContext, U as loadEnriched, V as isProject, W as mergeLines, X as lessonsStateFileFor, Y as lessonsFileFor, _ as preCommitGate, _t as readRules, a as recordActivity, at as saveApexState, b as extractSymbols, bt as pruneEmptyDirs, c as MCP_TTL_MS, ct as trackAgentMemory, d as isMcpTool, dt as validateSolidGate, f as queryOf, ft as checkFileSize, g as gate, gt as injectRules, h as TRIVIAL_BUDGET, ht as solidDetectStart, i as respond, it as cleanupSession, j as trackSkillRead, jt as projectHash, k as trackWatchResearch, kt as taskContext, l as WEBFETCH_TTL_MS, lt as subagentCacheContext, m as REQUIRED_AGENTS, mt as detectSolidProfile, n as activityFor, nt as trackSessionChanges, o as mcpPostStore, ot as logToolFailure, p as DEFAULT_WINDOW_MS, pt as countLoc, q as listChildren, r as handlePre, rt as validateRulesLoaded, s as mcpPreIntercept, st as validateTeammateOutput, t as handleHook, tt as postEditTypescript, u as cacheQueryOf, ut as validateTailwind, v as detectDuplication, vt as runSessionStartCleanups, w as seoPostToolUseResponse, wt as devContext, x as lifecycleStdout, xt as purgeTtlTree, y as dryGate, yt as sessionStartCore, z as writePluginMap, zt as todayUtc } from "../handle-ClfFahJs.mjs";
4
4
  //#region src/runtime/storage.ts
5
5
  /**
6
6
  * The project's single state dir (`<root>/.harness`) — neutral + harness-agnostic,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/harness",
3
- "version": "0.1.69",
3
+ "version": "0.1.70",
4
4
  "description": "Harness-agnostic toolkit for AI coding agents: runtime harness detection (Claude Code, Codex, Cursor, Cline, Gemini, Aider...), pure policy core (env config, project/framework detection, SOLID/file-size limits, APEX freshness, guard patterns, portable prompts), cache, project memory, ref routing, state/locks, statusline, per-harness adapters (Claude/Cursor/Cline/Gemini) and a cli-mode harness-check binary. Bun-native, with a built dist for Node + bundlers.",
5
5
  "type": "module",
6
6
  "module": "src/index.ts",