@fusengine/harness 0.1.26 → 0.1.27

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,2 +1,2 @@
1
- import { a as readClaudeInput, i as guard, n as denyResponse, o as toClaudeResponse, r as fileSizeGuard, t as contextResponse } from "../../claude-c2Sskvb6.mjs";
1
+ import { a as readClaudeInput, i as guard, n as denyResponse, o as toClaudeResponse, r as fileSizeGuard, t as contextResponse } from "../../claude-CeNVUGku.mjs";
2
2
  export { contextResponse, denyResponse, fileSizeGuard, guard, readClaudeInput, toClaudeResponse };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-CreJy519.mjs";
1
+ import { t as evaluate } from "../../evaluate-BIK60lOR.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/cline/index.ts
4
4
  /**
@@ -1,2 +1,2 @@
1
- import { a as readClaudeInput, i as guard, n as denyResponse, t as contextResponse } from "../../claude-c2Sskvb6.mjs";
1
+ import { a as readClaudeInput, i as guard, n as denyResponse, t as contextResponse } from "../../claude-CeNVUGku.mjs";
2
2
  export { contextResponse, denyResponse, guard, readClaudeInput as readCodexInput };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-CreJy519.mjs";
1
+ import { t as evaluate } from "../../evaluate-BIK60lOR.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/cursor/index.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-CreJy519.mjs";
1
+ import { t as evaluate } from "../../evaluate-BIK60lOR.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/gemini/index.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "./evaluate-CreJy519.mjs";
1
+ import { t as evaluate } from "./evaluate-BIK60lOR.mjs";
2
2
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/claude/index.ts
4
4
  /**
package/dist/cli/bin.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { r as resolveTtlSec } from "../ttl-BG55s6HZ.mjs";
3
3
  import { t as detectHarness } from "../harness-C8Nxxyn_.mjs";
4
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-0LTLAbmo.mjs";
4
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-BdcSLer0.mjs";
5
5
  import { n as writeInitFile, t as initFor } from "../run-D91N4ul1.mjs";
6
- import { t as handleHook } from "../handle-CqI_i3Re.mjs";
6
+ import { t as handleHook } from "../handle-BJ2xdeA-.mjs";
7
7
  //#region src/cli/bin.ts
8
8
  /**
9
9
  * harness — CLI for @fusengine/harness.
@@ -1,2 +1,2 @@
1
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-0LTLAbmo.mjs";
1
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-BdcSLer0.mjs";
2
2
  export { checkStaged, stagedContent, stagedFiles };
@@ -118,7 +118,7 @@ const CRITICAL_PATTERNS = [
118
118
  /\b(?:curl|wget)\b[^|]*\|\s*(?:sudo\s+)?(?:ba|z|da|k)?sh\b/,
119
119
  /\bchmod\s+(?:-[a-zA-Z]+\s+)*777\s+\//,
120
120
  /\bmkfs(?:\.[a-z0-9]+)?\b/,
121
- /\bdd\b[^\n]*\bif=\/dev\/zero\b[^\n]*\bof=\/dev\//,
121
+ /\bdd\b[^\n]*\bof=\/dev\/(?:disk|sd|hd|nvme|mmcblk|vd)/i,
122
122
  /\bshred\b/,
123
123
  /\bfdisk\b/,
124
124
  /\bdiskutil\s+(?:erase|partitionDisk)/i,
@@ -136,12 +136,17 @@ const ASK_PATTERNS = [
136
136
  /\bdoas\s/,
137
137
  /\bpasswd\b/,
138
138
  /\brm\s/,
139
- /\bunlink\s/
139
+ /\bunlink\s/,
140
+ /\bdel\s/
140
141
  ];
142
+ /** Strip heredoc bodies so their content isn't matched as a command (false positives). */
143
+ function stripHeredoc(cmd) {
144
+ return cmd.replace(/<<-?\s*['"]?(\w+)['"]?[\s\S]*?\n[ \t]*\1\b/g, " ");
145
+ }
141
146
  /** Guards against dangerous Bash commands (critical → block, sensitive → ask). */
142
147
  function securityGuard(ctx) {
143
148
  if (ctx.tool !== "Bash" || !ctx.command) return null;
144
- const cmd = ctx.command;
149
+ const cmd = stripHeredoc(ctx.command);
145
150
  for (const re of CRITICAL_PATTERNS) if (re.test(cmd)) return {
146
151
  kind: "block",
147
152
  title: "Dangerous command",
@@ -1,9 +1,9 @@
1
1
  import { r as projectLayout } from "./layout-C0jaaCQC.mjs";
2
- import { j as detectFramework, n as FAIL_CLOSED, t as evaluate } from "./evaluate-CreJy519.mjs";
3
- import { c as evaluateApex, i as detectCreationIntent, r as capVerbosity } from "./verbosity-BnGJPq6y.mjs";
2
+ import { j as detectFramework, n as FAIL_CLOSED, t as evaluate } from "./evaluate-BIK60lOR.mjs";
3
+ import { c as evaluateApex, i as detectCreationIntent, r as capVerbosity } from "./verbosity-CXpf3aQQ.mjs";
4
4
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
5
5
  import { a as extractText, r as cacheStore, t as cacheLookup } from "./store-DeIsfMg5.mjs";
6
- import { t as loadRefs } from "./loader-6TxEFTND.mjs";
6
+ import { t as loadRefs } from "./loader-CyAoJv2W.mjs";
7
7
  import { a as recordAgent, c as recordRefRead, l as recordTrivialEdit, n as saveTrack, o as recordBrainstormRequired, r as agentsFresh, s as recordDoc, t as loadTrack, u as trivialCount } from "./store-BnHpq2ZB.mjs";
8
8
  import { join } from "node:path";
9
9
  import { existsSync, readFileSync } from "node:fs";
package/dist/index.mjs CHANGED
@@ -5,16 +5,16 @@ import { t as compactJson } from "./compact-json-DK2nX-MK.mjs";
5
5
  import { n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-ff0_poWU.mjs";
6
6
  import { n as detectMode, r as modeFor, t as detectHarness } from "./harness-C8Nxxyn_.mjs";
7
7
  import { n as detectProjectType, r as isApexCommand, t as DEV_KEYWORDS } from "./policy-EuVJ_5hS.mjs";
8
- import { A as evaluateFileSize, C as securityGuard, D as SYSTEM_INSTALL, E as PROJECT_INSTALL, O as matchPatterns, S as CRITICAL_PATTERNS, T as GIT_BLOCKED, _ as CODE_REDIRECT, a as registerGuard, b as protectedPathGuard, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as CODE_MUTATORS, h as ASK_WRITERS, i as clearUserGuards, j as detectFramework, k as countLines, l as JAVA_DECL_RE, m as interfaceSeparationGuard, n as FAIL_CLOSED, o as runGuards, p as TS_DECL_RE, r as GUARDS, s as installGuard, t as evaluate, u as PHP_DECL_RE, v as bashWriteGuard, w as GIT_ASK, x as ASK_PATTERNS, y as PROTECTED_FRAGMENTS } from "./evaluate-CreJy519.mjs";
8
+ import { A as evaluateFileSize, C as securityGuard, D as SYSTEM_INSTALL, E as PROJECT_INSTALL, O as matchPatterns, S as CRITICAL_PATTERNS, T as GIT_BLOCKED, _ as CODE_REDIRECT, a as registerGuard, b as protectedPathGuard, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as CODE_MUTATORS, h as ASK_WRITERS, i as clearUserGuards, j as detectFramework, k as countLines, l as JAVA_DECL_RE, m as interfaceSeparationGuard, n as FAIL_CLOSED, o as runGuards, p as TS_DECL_RE, r as GUARDS, s as installGuard, t as evaluate, u as PHP_DECL_RE, v as bashWriteGuard, w as GIT_ASK, x as ASK_PATTERNS, y as PROTECTED_FRAGMENTS } from "./evaluate-BIK60lOR.mjs";
9
9
  import { i as resolveSessions, n as formatDocSatisfactionStatus, r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-Dd_x1-tZ.mjs";
10
- import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./router-BxA7TgnX.mjs";
11
- import { a as APEX_GATES, c as evaluateApex, i as detectCreationIntent, l as freshnessGate, n as MAX_TOKENS, o as brainstormGate, r as capVerbosity, s as docConsultedGate, t as MAX_EXA_RESULTS, u as solidReadGate } from "./verbosity-BnGJPq6y.mjs";
10
+ import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./router-D8cVrI-s.mjs";
11
+ import { a as APEX_GATES, c as evaluateApex, i as detectCreationIntent, l as freshnessGate, n as MAX_TOKENS, o as brainstormGate, r as capVerbosity, s as docConsultedGate, t as MAX_EXA_RESULTS, u as solidReadGate } from "./verbosity-CXpf3aQQ.mjs";
12
12
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
13
13
  import { a as nowStamp, c as stateFileFor, i as lessonsFileFor, l as throttleMs, n as readRoots, o as readState, r as registryFile, s as setStateField, t as addRoot, u as ensureMemoryGitignore } from "./memory-BkoEbdec.mjs";
14
14
  import { a as queryHash, i as jaccardSimilar, n as summarizeIndex, r as compactMarkdown, t as loadIndex } from "./cache-BzbX-ztL.mjs";
15
15
  import { a as extractText, i as mcpCacheKey, n as cachePath, r as cacheStore, t as cacheLookup } from "./store-DeIsfMg5.mjs";
16
16
  import { t as incrementTrivialEditCounter } from "./freshness-CezohJHo.mjs";
17
- import { n as toRefMeta, t as loadRefs } from "./loader-6TxEFTND.mjs";
17
+ import { n as toRefMeta, t as loadRefs } from "./loader-CyAoJv2W.mjs";
18
18
  import { a as ensureStateDir, c as stateFilePath, i as apexStateDir, l as acquireLock, n as taskCreate, o as loadState, r as taskStart, s as saveState, t as taskComplete } from "./state-Cs0Y0MG_.mjs";
19
19
  import { a as formatPath, c as colors, d as GRADIENT_BLOCKS, f as PROGRESS_BAR_DEFAULTS, i as formatCost, l as progressiveColor, m as TIME_INTERVALS, n as generateProgressBar, o as formatTimeLeft, p as PROGRESS_CHARS, r as formatBasename, s as formatTokens, t as generateGradientBar, u as COLOR_THRESHOLDS } from "./statusline-D87eUNXl.mjs";
20
20
  export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, COLOR_THRESHOLDS, CRITICAL_PATTERNS, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, FAIL_CLOSED, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GRADIENT_BLOCKS, GUARDS, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_LINES_ENV_KEY, MAX_TOKENS, PHP_DECL_RE, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PY_MODEL_RE, STATE_GITIGNORE, STATE_ROOT, SWIFT_PROTO_RE, SYSTEM_INSTALL, TIME_INTERVALS, TS_DECL_RE, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, bashWriteGuard, brainstormGate, cacheLookup, cachePath, cacheStore, capVerbosity, clearUserGuards, colors, compactJson, compactMarkdown, countLines, detectCreationIntent, detectFramework, detectHarness, detectMode, detectProjectType, docConsultedGate, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateApex, evaluateFileSize, extractText, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, installGuard, interfaceSeparationGuard, isApexCommand, isCodeFile, isDocConsulted, jaccardSimilar, lessonsFileFor, loadIndex, loadRefs, loadState, matchPatterns, mcpCacheKey, modeFor, nowStamp, parseEnvInt, parseFrontmatter, progressiveColor, projectLayout, projectRoot, projectRootOrNull, protectedPathGuard, queryHash, readRoots, readState, registerGuard, registryFile, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, runGuards, saveState, scoreReferences, securityGuard, setStateField, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, toRefMeta, ttlLabel };
@@ -1,4 +1,4 @@
1
- import { i as parseFrontmatter } from "./router-BxA7TgnX.mjs";
1
+ import { i as parseFrontmatter } from "./router-D8cVrI-s.mjs";
2
2
  import { delimiter, join } from "node:path";
3
3
  import { readFile, readdir } from "node:fs/promises";
4
4
  //#region src/refs/loader.ts
@@ -9,6 +9,20 @@ function pick(fm, ...keys) {
9
9
  }
10
10
  return "";
11
11
  }
12
+ const SOLID_SLUGS = /* @__PURE__ */ new Set([
13
+ "single-responsibility",
14
+ "open-closed",
15
+ "liskov-substitution",
16
+ "interface-segregation",
17
+ "dependency-inversion",
18
+ "solid-principles"
19
+ ]);
20
+ /** Infer a ref's level from its path when the frontmatter omits it (templates/→template, SOLID slug→principle). */
21
+ function inferLevel(filePath) {
22
+ if (filePath.includes("/templates/")) return "template";
23
+ const stem = (filePath.split("/").pop() ?? "").replace(/\.md$/, "");
24
+ return SOLID_SLUGS.has(stem) ? "principle" : "architecture";
25
+ }
12
26
  /** Build a {@link RefMeta} from parsed frontmatter, tolerant of kebab/camel keys. */
13
27
  function toRefMeta(fm, filePath) {
14
28
  return {
@@ -19,7 +33,7 @@ function toRefMeta(fm, filePath) {
19
33
  related: pick(fm, "related"),
20
34
  appliesTo: pick(fm, "appliesTo", "applies-to", "applies_to"),
21
35
  triggerOnEdit: pick(fm, "triggerOnEdit", "trigger-on-edit", "trigger_on_edit"),
22
- level: pick(fm, "level"),
36
+ level: pick(fm, "level") || inferLevel(filePath),
23
37
  filePath
24
38
  };
25
39
  }
@@ -1,4 +1,4 @@
1
1
  import { n as detectProjectType, r as isApexCommand, t as DEV_KEYWORDS } from "../policy-EuVJ_5hS.mjs";
2
- import { A as evaluateFileSize, C as securityGuard, D as SYSTEM_INSTALL, E as PROJECT_INSTALL, O as matchPatterns, S as CRITICAL_PATTERNS, T as GIT_BLOCKED, _ as CODE_REDIRECT, a as registerGuard, b as protectedPathGuard, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as CODE_MUTATORS, h as ASK_WRITERS, i as clearUserGuards, j as detectFramework, k as countLines, l as JAVA_DECL_RE, m as interfaceSeparationGuard, n as FAIL_CLOSED, o as runGuards, p as TS_DECL_RE, r as GUARDS, s as installGuard, t as evaluate, u as PHP_DECL_RE, v as bashWriteGuard, w as GIT_ASK, x as ASK_PATTERNS, y as PROTECTED_FRAGMENTS } from "../evaluate-CreJy519.mjs";
3
- import { a as APEX_GATES, c as evaluateApex, i as detectCreationIntent, l as freshnessGate, n as MAX_TOKENS, o as brainstormGate, r as capVerbosity, s as docConsultedGate, t as MAX_EXA_RESULTS, u as solidReadGate } from "../verbosity-BnGJPq6y.mjs";
2
+ import { A as evaluateFileSize, C as securityGuard, D as SYSTEM_INSTALL, E as PROJECT_INSTALL, O as matchPatterns, S as CRITICAL_PATTERNS, T as GIT_BLOCKED, _ as CODE_REDIRECT, a as registerGuard, b as protectedPathGuard, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as CODE_MUTATORS, h as ASK_WRITERS, i as clearUserGuards, j as detectFramework, k as countLines, l as JAVA_DECL_RE, m as interfaceSeparationGuard, n as FAIL_CLOSED, o as runGuards, p as TS_DECL_RE, r as GUARDS, s as installGuard, t as evaluate, u as PHP_DECL_RE, v as bashWriteGuard, w as GIT_ASK, x as ASK_PATTERNS, y as PROTECTED_FRAGMENTS } from "../evaluate-BIK60lOR.mjs";
3
+ import { a as APEX_GATES, c as evaluateApex, i as detectCreationIntent, l as freshnessGate, n as MAX_TOKENS, o as brainstormGate, r as capVerbosity, s as docConsultedGate, t as MAX_EXA_RESULTS, u as solidReadGate } from "../verbosity-CXpf3aQQ.mjs";
4
4
  export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, FAIL_CLOSED, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GUARDS, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_TOKENS, PHP_DECL_RE, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PY_MODEL_RE, SWIFT_PROTO_RE, SYSTEM_INSTALL, TS_DECL_RE, bashWriteGuard, brainstormGate, capVerbosity, clearUserGuards, countLines, detectCreationIntent, detectFramework, detectProjectType, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, freshnessGate, installGuard, interfaceSeparationGuard, isApexCommand, matchPatterns, protectedPathGuard, registerGuard, runGuards, securityGuard, solidReadGate };
@@ -1,4 +1,4 @@
1
- import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "../router-BxA7TgnX.mjs";
2
- import { n as toRefMeta, t as loadRefs } from "../loader-6TxEFTND.mjs";
1
+ import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "../router-D8cVrI-s.mjs";
2
+ import { n as toRefMeta, t as loadRefs } from "../loader-CyAoJv2W.mjs";
3
3
  import "../refs-la_KkjCS.mjs";
4
4
  export { globToRe, loadRefs, parseFrontmatter, routeReferences, scoreReferences, toRefMeta };
@@ -37,9 +37,12 @@ function scoreReferences(refs, filePath, content) {
37
37
  if (meta.triggerOnEdit) {
38
38
  for (const frag of meta.triggerOnEdit.split(", ")) if (filePath.includes(frag.trim())) score += 5;
39
39
  }
40
- if (meta.keywords) for (const kw of meta.keywords.split(", ")) {
41
- const k = kw.trim();
42
- if (k && (filePath.includes(k) || content.includes(k))) score += 1;
40
+ if (meta.keywords) {
41
+ const hay = `${filePath} ${content}`.toLowerCase();
42
+ for (const kw of meta.keywords.split(", ")) {
43
+ const k = kw.trim().toLowerCase();
44
+ if (k && hay.includes(k)) score += 1;
45
+ }
43
46
  }
44
47
  if (score > 0) scored.push({
45
48
  meta,
@@ -1,5 +1,5 @@
1
1
  import { t as isCodeFile } from "./project-root-ff0_poWU.mjs";
2
- import { t as evaluate } from "./evaluate-CreJy519.mjs";
2
+ import { t as evaluate } from "./evaluate-BIK60lOR.mjs";
3
3
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
4
4
  import { execSync } from "node:child_process";
5
5
  //#region src/cli/run.ts
@@ -1,5 +1,5 @@
1
1
  import { r as projectLayout } from "../layout-C0jaaCQC.mjs";
2
- import { a as normalizeEvent, c as mcpPostStore, d as DEFAULT_WINDOW_MS, f as REQUIRED_AGENTS, h as activityFor, i as trackFile, l as mcpPreIntercept, m as gate, n as respond, o as MCP_TTL_MS, p as TRIVIAL_BUDGET, r as recordActivity, s as isMcpTool, t as handleHook, u as queryOf } from "../handle-CqI_i3Re.mjs";
2
+ import { a as normalizeEvent, c as mcpPostStore, d as DEFAULT_WINDOW_MS, f as REQUIRED_AGENTS, h as activityFor, i as trackFile, l as mcpPreIntercept, m as gate, n as respond, o as MCP_TTL_MS, p as TRIVIAL_BUDGET, r as recordActivity, s as isMcpTool, t as handleHook, u as queryOf } from "../handle-BJ2xdeA-.mjs";
3
3
  //#region src/runtime/storage.ts
4
4
  /**
5
5
  * The project's single state dir (`<root>/.harness`) — neutral + harness-agnostic,
@@ -1,5 +1,5 @@
1
1
  import { r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-Dd_x1-tZ.mjs";
2
- import { t as routeReferences } from "./router-BxA7TgnX.mjs";
2
+ import { t as routeReferences } from "./router-D8cVrI-s.mjs";
3
3
  //#region src/policy/apex.ts
4
4
  /** Gate: Context7 + Exa must have been consulted this session. */
5
5
  const docConsultedGate = (ctx) => isDocConsulted(ctx.authorizations, ctx.sessionId) ? null : {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/harness",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
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",