@fusengine/harness 0.1.65 → 0.1.67

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 fileSizeGuard, c as readClaudeInput, i as denyResponse, l as systemMessage, n as blockResponse, o as guard, r as contextResponse, s as informResponse, t as attachSystemMessage, u as toClaudeResponse } from "../../claude-CVQlXOl8.mjs";
1
+ import { a as fileSizeGuard, c as readClaudeInput, i as denyResponse, l as systemMessage, n as blockResponse, o as guard, r as contextResponse, s as informResponse, t as attachSystemMessage, u as toClaudeResponse } from "../../claude-Cu6rPxUZ.mjs";
2
2
  export { attachSystemMessage, blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, informResponse, readClaudeInput, systemMessage, toClaudeResponse };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-I9CAwUlI.mjs";
1
+ import { t as evaluate } from "../../evaluate-CxgYAODk.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/cline/index.ts
4
4
  /**
@@ -1,8 +1,8 @@
1
1
  import { f as countLines } from "../../home-state-D0RLWP8J.mjs";
2
- import { t as evaluate } from "../../evaluate-I9CAwUlI.mjs";
2
+ import { t as evaluate } from "../../evaluate-CxgYAODk.mjs";
3
3
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
4
4
  import { n as parseApplyPatch, t as isBypassPermissions } from "../../permission-mode-BN3MNgbm.mjs";
5
- import { c as readClaudeInput, i as denyResponse, r as contextResponse, s as informResponse, v as commandToString } from "../../claude-CVQlXOl8.mjs";
5
+ import { c as readClaudeInput, i as denyResponse, r as contextResponse, s as informResponse, v as commandToString } from "../../claude-Cu6rPxUZ.mjs";
6
6
  //#region src/adapters/codex/index.ts
7
7
  /**
8
8
  * OpenAI Codex CLI adapter (hook-mode). Codex's `PreToolUse` hook (since 2026)
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-I9CAwUlI.mjs";
1
+ import { t as evaluate } from "../../evaluate-CxgYAODk.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-I9CAwUlI.mjs";
1
+ import { t as evaluate } from "../../evaluate-CxgYAODk.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/gemini/index.ts
4
4
  /**
@@ -1,2 +1,2 @@
1
- import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-DKTAji46.mjs";
1
+ import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-BpD0nlyR.mjs";
2
2
  export { guard, readHermesInput, toHermesResponse };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "./evaluate-I9CAwUlI.mjs";
1
+ import { t as evaluate } from "./evaluate-CxgYAODk.mjs";
2
2
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
3
3
  import { dirname, join } from "node:path";
4
4
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
package/dist/cli/bin.mjs CHANGED
@@ -2,10 +2,10 @@
2
2
  import { r as loadDotenv, s as resolveTtlSec } from "../dotenv-Jj8aL1FL.mjs";
3
3
  import { t as detectHarness } from "../harness-Cb9xR8dC.mjs";
4
4
  import { t as claudeHome } from "../home-state-D0RLWP8J.mjs";
5
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-BCQAHUrx.mjs";
5
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-BfJytXnW.mjs";
6
6
  import { n as writeInitFile, t as initFor } from "../run-Do2JltgU.mjs";
7
- import { J as runningVersion, Lt as todayUtc, Y as versionBanner, q as runDoctor, t as handleHook } from "../handle-DnxRzNuY.mjs";
8
- import { p as readStdin$1 } from "../claude-CVQlXOl8.mjs";
7
+ import { J as runningVersion, Lt as todayUtc, Y as versionBanner, q as runDoctor, t as handleHook } from "../handle-CU5UdAei.mjs";
8
+ import { p as readStdin$1 } from "../claude-Cu6rPxUZ.mjs";
9
9
  import { delimiter, join } from "node:path";
10
10
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
11
11
  import { homedir } from "node:os";
@@ -1,2 +1,2 @@
1
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-BCQAHUrx.mjs";
1
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-BfJytXnW.mjs";
2
2
  export { checkStaged, stagedContent, stagedFiles };
@@ -754,6 +754,49 @@ const CHAIN_RE = /&&|\|\||[;|`]|&(?!>)|\$\(|\n/;
754
754
  function isSingleCommand(cmd) {
755
755
  return !CHAIN_RE.test(cmd);
756
756
  }
757
+ /**
758
+ * Commands exempt from `ask` under Codex `approval_policy=never` — a superset
759
+ * of {@link RALPH_SAFE} plus `git push`. Kept as its OWN list, never merged
760
+ * into RALPH_SAFE: the RALPH_MODE path (evaluate.ts's `ralphSafe`) has no
761
+ * equivalent to {@link isSafePushForm}, only the shared GIT_BLOCKED +
762
+ * isSingleCommand guards — adding push to RALPH_SAFE would auto-allow
763
+ * `git push origin --delete branch` under RALPH_MODE, since GIT_BLOCKED only
764
+ * covers force-push, not remote deletion. Only the neverApproval path in
765
+ * evaluate.ts consults NEVER_SAFE, and it always pairs it with
766
+ * isSafePushForm for any push entry.
767
+ */
768
+ const NEVER_SAFE = [...RALPH_SAFE, "git push"];
769
+ /**
770
+ * `--delete`/`-d` (git-push(1): "deleted from the remote repository", no
771
+ * `--force` needed), `--mirror` (force-updates AND deletes remote-only refs),
772
+ * `--prune` (removes remote refs with no local counterpart) — all delete or
773
+ * force-overwrite a remote ref without going through the `--force` flag
774
+ * GIT_BLOCKED already checks. Boundary-anchored like patterns.ts's FORCE_FLAG
775
+ * so `-d` never matches inside a longer token (e.g. a branch name).
776
+ */
777
+ const PUSH_DESTRUCTIVE_FLAG = /\s(?:--delete|--mirror|--prune|-d)(?:\s|=|$)/;
778
+ /** A refspec colon (e.g. `git push origin :branch`) deletes the remote ref — the legacy form of `--delete` (git-push(1): "prefixing all refs with a colon"). */
779
+ const REFSPEC_COLON = /\s:\S/;
780
+ /**
781
+ * A leading `+` on a pushed refspec force-updates the remote ref on a
782
+ * non-fast-forward — git-push(1): "The `+` is optional and does the same thing
783
+ * as `--force`". It carries NO `--force`/`-f` flag, so GIT_BLOCKED's FORCE_FLAG
784
+ * misses it; this guard is the `--force` twin. The `\s` anchor makes `+` open
785
+ * its token (`+main`, `+src:dst`), never a mid-token `feature+x` ref name.
786
+ */
787
+ const REFSPEC_FORCE = /\s\+\S/;
788
+ /**
789
+ * True unless `cmd` is a `git push` carrying an irreversible remote-mutation
790
+ * form GIT_BLOCKED doesn't already cover: `--delete`/`-d`/`--mirror`/`--prune`,
791
+ * a `:refspec` remote-delete, or a `+refspec` force-update (the `--force` twin
792
+ * FORCE_FLAG misses). Plain `--force`/`-f` stays GIT_BLOCKED's job, checked
793
+ * upstream in evaluate.ts. Non-push commands always pass — this guard exists
794
+ * solely to narrow the `git push` entry of {@link NEVER_SAFE}.
795
+ */
796
+ function isSafePushForm(cmd) {
797
+ if (!cmd.startsWith("git push")) return true;
798
+ return !PUSH_DESTRUCTIVE_FLAG.test(cmd) && !REFSPEC_COLON.test(cmd) && !REFSPEC_FORCE.test(cmd);
799
+ }
757
800
  /** Next steps offered on the auto-approve notice — the only channel left once `ask` is unavailable. */
758
801
  const ACTIONS = [
759
802
  "Set approval_policy=on-request for interactive confirmation",
@@ -794,7 +837,7 @@ function evaluate(ctx) {
794
837
  };
795
838
  const cmd = ctx.command;
796
839
  const ralphSafe = !!cmd && isRalphMode() && RALPH_SAFE.some((s) => cmd.startsWith(s));
797
- if (!ralphSafe && !!ctx.neverApproval && !!cmd && !matchPatterns(cmd, GIT_BLOCKED) && isSingleCommand(cmd) && RALPH_SAFE.some((s) => cmd.startsWith(s)) && cmd) {
840
+ if (!ralphSafe && !!ctx.neverApproval && !!cmd && !matchPatterns(cmd, GIT_BLOCKED) && isSingleCommand(cmd) && NEVER_SAFE.some((s) => cmd.startsWith(s)) && isSafePushForm(cmd) && cmd) {
798
841
  const prompt = buildNeverApprovalPrompt(cmd);
799
842
  return {
800
843
  decision: "warn",
@@ -4,7 +4,7 @@ import { r as projectLayout } from "./layout-C0jaaCQC.mjs";
4
4
  import { i as walkUpFor, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-3kk7gCOp.mjs";
5
5
  import { A as detectCreationIntent, E as isExcludedSwiftPath, F as docConsultedGate, H as detectProjectType$1, I as evaluateApex, M as POST_AUTH_GATES, N as PRE_AUTH_GATES, S as usesTailwindUtilities, T as isExcludedJsPath, V as detectModularArchitecture, W as requiredArchSkill, _ as scanPlugin, c as EXCLUDE_DIRS$1, d as buildApexTaskInjection, h as buildClaudeMdContext, k as capVerbosity, l as PROJECT_INDICATORS, n as missingSeoElements, o as parseEnrichment, r as descFromText, s as parseEntry, t as isHtmlLike, w as frameworkSolidGate, x as skillTriggerGate, y as parseField, z as detectFramework } from "./validate-DnOqIZD_.mjs";
6
6
  import { a as sanitizeSessionId, c as sessionsDir, d as countFrameworkCodeLines, f as countLines, i as loadSessionState, l as PLUGINS_DIR, n as fuseHarnessHome, o as saveSessionState, r as fusengineCache, t as claudeHome } from "./home-state-D0RLWP8J.mjs";
7
- import { n as FAIL_CLOSED, t as evaluate } from "./evaluate-I9CAwUlI.mjs";
7
+ import { n as FAIL_CLOSED, t as evaluate } from "./evaluate-CxgYAODk.mjs";
8
8
  import { a as writeJsonFile, i as readJsonFile, r as hashText, t as atomicWrite } from "./json-io-DisYd2fb.mjs";
9
9
  import { r as isDocConsulted } from "./doc-helpers-CWZegVdR.mjs";
10
10
  import { n as findMarketplacePlugins, r as readPluginMeta, t as resolveSkillPath } from "./skill-path-DhItkBzk.mjs";
@@ -14,8 +14,8 @@ import { d as loadIndex, i as cacheLookupMeta, n as webfetchCacheWrite, o as cac
14
14
  import { t as loadRefs } from "./loader-AGz4nK7d.mjs";
15
15
  import { a as writeLastNonce, c as recordAgent, d as recordRefRead, f as recordTarget, h as apexAuthorizationGate, i as verifyTrack, l as recordBrainstormRequired, m as trivialCount, n as saveTrack, o as agentsFresh, p as recordTrivialEdit, r as signTrack, s as emptyTrack, t as loadTrack, u as recordDoc } from "./store-CQ4roWrU.mjs";
16
16
  import { n as parseApplyPatch, t as isBypassPermissions } from "./permission-mode-BN3MNgbm.mjs";
17
- import { _ as writeText, d as collectFiles, f as pathExists, g as spawnCapture, h as sleep, i as denyResponse, l as systemMessage, m as readText, n as blockResponse, r as contextResponse, s as informResponse, t as attachSystemMessage, v as commandToString } from "./claude-CVQlXOl8.mjs";
18
- import { r as toHermesResponse } from "./hermes-DKTAji46.mjs";
17
+ import { _ as writeText, d as collectFiles, f as pathExists, g as spawnCapture, h as sleep, i as denyResponse, l as systemMessage, m as readText, n as blockResponse, r as contextResponse, s as informResponse, t as attachSystemMessage, v as commandToString } from "./claude-Cu6rPxUZ.mjs";
18
+ import { r as toHermesResponse } from "./hermes-BpD0nlyR.mjs";
19
19
  import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
20
20
  import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
21
21
  import { homedir } from "node:os";
@@ -7885,6 +7885,92 @@ function activityFor(event) {
7885
7885
  return out;
7886
7886
  }
7887
7887
  //#endregion
7888
+ //#region src/freshness/codex-spawn-evidence.ts
7889
+ /**
7890
+ * Codex multi_agent_v2 `spawn_agent` -> session evidence bridge. Codex's custom
7891
+ * agents (fusengine multi_agent_v2, e.g. sniper/explore-codebase) are launched
7892
+ * via a `spawn_agent` TOOL CALL inside the SAME session -- Codex has no
7893
+ * SubagentStart/SubagentStop lifecycle for them, so the existing Claude-side
7894
+ * evidence paths (agent-evidence-record.ts `classifyAgentEvidence`, the
7895
+ * SubagentStop harvest) never observe them; the harness only ever saw a
7896
+ * generic tool call. This module credits the SAME session track
7897
+ * ({@link recordAgent}, read back by `agent-evidence-record.ts`
7898
+ * `agentsFreshInTrack`) straight from that PostToolUse `spawn_agent` call.
7899
+ *
7900
+ * SOURCE (openai/codex@44918ea1, tag rust-v0.144.1 -- verified upstream,
7901
+ * not re-checked here): the hook `tool_name` is `"spawn_agent"` normally, or
7902
+ * the SEPARATOR-LESS namespace-prefixed `{namespace}spawn_agent` when the
7903
+ * `namespace_tools` capability provider is active (e.g.
7904
+ * `"fusengine_agentsspawn_agent"`, `"collaborationspawn_agent"`). Detection is
7905
+ * `tool_name === "spawn_agent" || tool_name.endsWith("spawn_agent")` -- a tool
7906
+ * that merely CONTAINS the substring without being an exact/suffix match
7907
+ * (`"spawn_agentX"`, `"myspawn_agent_tool"`) is correctly rejected.
7908
+ * `tool_input.agent_type` carries the spawned agent's type only when Codex's
7909
+ * `hide_spawn_agent_metadata=false`; treat it as always-optional.
7910
+ *
7911
+ * INVARIANT (multi-harness parity): every entry point here is gated on
7912
+ * `id === "codex"` FIRST -- claude-code/cursor/cline/gemini-cli/hermes always
7913
+ * take the early return, touching neither the track nor disk. Byte-identical
7914
+ * elsewhere by construction.
7915
+ */
7916
+ /**
7917
+ * True when `tool` is Codex's `spawn_agent` primitive, bare or
7918
+ * namespace-prefixed (no separator). Rejects any tool that merely contains
7919
+ * the substring elsewhere in its name.
7920
+ * @param tool - Raw/normalized `tool_name` from the hook payload.
7921
+ */
7922
+ function isCodexSpawnAgentTool(tool) {
7923
+ return tool === "spawn_agent" || tool.endsWith("spawn_agent");
7924
+ }
7925
+ /**
7926
+ * Extract the spawned agent's type from a `spawn_agent` `tool_input`, or
7927
+ * `undefined` when absent/blank (`hide_spawn_agent_metadata=true`, or a
7928
+ * future Codex build omitting it) -- never throws.
7929
+ * @param input - Raw `tool_input` payload (harness `event.input`).
7930
+ */
7931
+ function codexSpawnAgentType(input) {
7932
+ const v = input?.agent_type;
7933
+ return typeof v === "string" && v.trim() !== "" ? v.trim() : void 0;
7934
+ }
7935
+ /**
7936
+ * Pure classifier + folder: credit a Codex `spawn_agent` call into
7937
+ * `track.agents` under the SAME `subagent-<name>` convention the Claude-side
7938
+ * explore/research evidence uses -- so an `agent_type` that happens to match
7939
+ * a `REQUIRED_AGENTS` name (e.g. `"explore-codebase"`) is picked up by
7940
+ * `agentsFreshInTrack`'s substring match exactly like genuine Claude
7941
+ * Task/Agent evidence. Immutable: returns `track` UNCHANGED (same reference)
7942
+ * for any other harness `id`, any non-spawn tool, or a missing `agent_type`.
7943
+ * @param id - Harness id (only `"codex"` ever credits).
7944
+ * @param tool - Normalized event tool name (raw `tool_name`).
7945
+ * @param input - Raw `tool_input` payload.
7946
+ * @param track - The current session track.
7947
+ * @param ts - Epoch-ms timestamp of the tool call.
7948
+ * @returns The credited track, or `track` itself when nothing was credited.
7949
+ */
7950
+ function creditCodexSpawnAgent(id, tool, input, track, ts) {
7951
+ if (id !== "codex" || !isCodexSpawnAgentTool(tool)) return track;
7952
+ const agentType = codexSpawnAgentType(input);
7953
+ if (!agentType) return track;
7954
+ return recordAgent(track, `subagent-${agentType}`, ts, "sufficient");
7955
+ }
7956
+ /**
7957
+ * I/O wiring for {@link creditCodexSpawnAgent}: load the session track, fold
7958
+ * in the credit, and persist only when something actually changed (skips a
7959
+ * write for the strict no-op cases). Mirrors `agent-evidence-record.ts`
7960
+ * `recordAgentEvidence`'s async load/save shape.
7961
+ * @param file - Session track file path (same one the freshness gate reads).
7962
+ * @param id - Harness id (only `"codex"` ever credits).
7963
+ * @param tool - Normalized event tool name (raw `tool_name`).
7964
+ * @param input - Raw `tool_input` payload.
7965
+ * @param ts - Epoch-ms timestamp of the tool call.
7966
+ */
7967
+ async function recordCodexSpawnEvidence(file, id, tool, input, ts) {
7968
+ if (id !== "codex" || !isCodexSpawnAgentTool(tool)) return;
7969
+ const track = await loadTrack(file);
7970
+ const next = creditCodexSpawnAgent(id, tool, input, track, ts);
7971
+ if (next !== track) await saveTrack(file, next);
7972
+ }
7973
+ //#endregion
7888
7974
  //#region src/runtime/handle-post.ts
7889
7975
  /**
7890
7976
  * Run the PostToolUse pipeline: store the MCP response, emit a design warning,
@@ -7909,6 +7995,7 @@ async function handlePost(ctx) {
7909
7995
  for (const activity of activities) await recordActivity(file, activity);
7910
7996
  const evidence = classifyAgentEvidence(event.tool, event.input, response);
7911
7997
  if (evidence) await recordAgentEvidence(file, evidence, opts.now, typeof payload.agent_id === "string" ? payload.agent_id : void 0);
7998
+ await recordCodexSpawnEvidence(file, id, event.tool, event.input, opts.now);
7912
7999
  if (event.tool === "Bash" && event.command) {
7913
8000
  const r = payload.tool_result ?? response;
7914
8001
  const out = `${typeof r?.stdout === "string" ? r.stdout : ""}\n${typeof r?.stderr === "string" ? r.stderr : ""}`;
@@ -1,6 +1,6 @@
1
- import { t as evaluate } from "./evaluate-I9CAwUlI.mjs";
1
+ import { t as evaluate } from "./evaluate-CxgYAODk.mjs";
2
2
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
3
- import { c as readClaudeInput, v as commandToString } from "./claude-CVQlXOl8.mjs";
3
+ import { c as readClaudeInput, v as commandToString } from "./claude-Cu6rPxUZ.mjs";
4
4
  //#region src/adapters/hermes/index.ts
5
5
  /**
6
6
  * Hermes Agent adapter (hook-mode). Nous Research's hermes-agent (2026) pipes a
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import { i as walkUpFor, n as projectRoot, r as projectRootOrNull, t as isCodeFi
6
6
  import { n as detectMode, r as modeFor, t as detectHarness } from "./harness-Cb9xR8dC.mjs";
7
7
  import { A as detectCreationIntent, B as DEV_KEYWORDS, C as SKILL_TRIGGERS, D as MAX_EXA_RESULTS, F as docConsultedGate, H as detectProjectType, I as evaluateApex, L as freshnessGate, M as POST_AUTH_GATES, N as PRE_AUTH_GATES, O as MAX_TOKENS, P as brainstormGate, R as solidReadGate, S as usesTailwindUtilities, U as isApexCommand, V as detectModularArchitecture, W as requiredArchSkill, a as firstHeading, b as detectRequiredSkills, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as detectClaudeMdProjectType, h as buildClaudeMdContext, i as firstComment, j as APEX_GATES, k as capVerbosity, l as PROJECT_INDICATORS, m as buildApexInstruction, n as missingSeoElements, o as parseEnrichment, p as DEV_VERBS, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, v as parseBodyDesc, w as frameworkSolidGate, x as skillTriggerGate, y as parseField, z as detectFramework } from "./validate-DnOqIZD_.mjs";
8
8
  import { d as countFrameworkCodeLines, f as countLines, l as PLUGINS_DIR, p as evaluateFileSize, u as SOLID_REF } from "./home-state-D0RLWP8J.mjs";
9
- import { A as PROJECT_INSTALL, C as PROTECTED_GIT_RE, D as securityGuard, E as CRITICAL_PATTERNS, M as SYSTEM_INSTALL, N as isRalphMode, O as GIT_ASK, P as matchPatterns, S as PROTECTED_FRAGMENTS, T as ASK_PATTERNS, _ as CODE_MUTATORS, a as registerGuard, b as SAFE_PREFIXES, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as ASK_WRITERS, h as bashWriteGuard, i as clearUserGuards, j as RALPH_SAFE, k as GIT_BLOCKED, 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 CODE_REDIRECT, w as protectedPathGuard, x as SESSION_STATE_FRAGMENT, y as FILE_REDIRECT } from "./evaluate-I9CAwUlI.mjs";
9
+ import { A as PROJECT_INSTALL, C as PROTECTED_GIT_RE, D as securityGuard, E as CRITICAL_PATTERNS, M as SYSTEM_INSTALL, N as isRalphMode, O as GIT_ASK, P as matchPatterns, S as PROTECTED_FRAGMENTS, T as ASK_PATTERNS, _ as CODE_MUTATORS, a as registerGuard, b as SAFE_PREFIXES, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as ASK_WRITERS, h as bashWriteGuard, i as clearUserGuards, j as RALPH_SAFE, k as GIT_BLOCKED, 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 CODE_REDIRECT, w as protectedPathGuard, x as SESSION_STATE_FRAGMENT, y as FILE_REDIRECT } from "./evaluate-CxgYAODk.mjs";
10
10
  import { i as resolveSessions, n as formatDocSatisfactionStatus, r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-CWZegVdR.mjs";
11
11
  import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./router-PKVNBHge.mjs";
12
12
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
@@ -1,5 +1,5 @@
1
1
  import { A as detectCreationIntent, B as DEV_KEYWORDS, C as SKILL_TRIGGERS, D as MAX_EXA_RESULTS, F as docConsultedGate, H as detectProjectType, I as evaluateApex, L as freshnessGate, M as POST_AUTH_GATES, N as PRE_AUTH_GATES, O as MAX_TOKENS, P as brainstormGate, R as solidReadGate, S as usesTailwindUtilities, U as isApexCommand, V as detectModularArchitecture, W as requiredArchSkill, a as firstHeading, b as detectRequiredSkills, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as detectClaudeMdProjectType, h as buildClaudeMdContext, i as firstComment, j as APEX_GATES, k as capVerbosity, l as PROJECT_INDICATORS, m as buildApexInstruction, n as missingSeoElements, o as parseEnrichment, p as DEV_VERBS, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, v as parseBodyDesc, w as frameworkSolidGate, x as skillTriggerGate, y as parseField, z as detectFramework } from "../validate-DnOqIZD_.mjs";
2
2
  import { d as countFrameworkCodeLines, f as countLines, l as PLUGINS_DIR, p as evaluateFileSize, u as SOLID_REF } from "../home-state-D0RLWP8J.mjs";
3
- import { A as PROJECT_INSTALL, C as PROTECTED_GIT_RE, D as securityGuard, E as CRITICAL_PATTERNS, M as SYSTEM_INSTALL, N as isRalphMode, O as GIT_ASK, P as matchPatterns, S as PROTECTED_FRAGMENTS, T as ASK_PATTERNS, _ as CODE_MUTATORS, a as registerGuard, b as SAFE_PREFIXES, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as ASK_WRITERS, h as bashWriteGuard, i as clearUserGuards, j as RALPH_SAFE, k as GIT_BLOCKED, 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 CODE_REDIRECT, w as protectedPathGuard, x as SESSION_STATE_FRAGMENT, y as FILE_REDIRECT } from "../evaluate-I9CAwUlI.mjs";
3
+ import { A as PROJECT_INSTALL, C as PROTECTED_GIT_RE, D as securityGuard, E as CRITICAL_PATTERNS, M as SYSTEM_INSTALL, N as isRalphMode, O as GIT_ASK, P as matchPatterns, S as PROTECTED_FRAGMENTS, T as ASK_PATTERNS, _ as CODE_MUTATORS, a as registerGuard, b as SAFE_PREFIXES, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as ASK_WRITERS, h as bashWriteGuard, i as clearUserGuards, j as RALPH_SAFE, k as GIT_BLOCKED, 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 CODE_REDIRECT, w as protectedPathGuard, x as SESSION_STATE_FRAGMENT, y as FILE_REDIRECT } from "../evaluate-CxgYAODk.mjs";
4
4
  import "../policy-la_KkjCS.mjs";
5
5
  export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, FILE_REDIRECT, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GUARDS, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_TOKENS, PHP_DECL_RE, PLUGINS_DIR, POST_AUTH_GATES, PRE_AUTH_GATES, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, RALPH_SAFE, SAFE_PREFIXES, SESSION_STATE_FRAGMENT, SKILL_TRIGGERS, SOLID_REF, SWIFT_PROTO_RE, SYSTEM_INSTALL, TS_DECL_RE, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, capVerbosity, clearUserGuards, countFrameworkCodeLines, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, firstComment, firstHeading, frameworkSolidGate, freshnessGate, installGuard, interfaceSeparationGuard, isApexCommand, isHtmlLike, isRalphMode, loadApexTaskState, matchPatterns, missingSeoElements, parseBodyDesc, parseEnrichment, parseEntry, parseField, protectedPathGuard, registerGuard, requiredArchSkill, runGuards, securityGuard, skillTriggerGate, solidReadGate, usesTailwindUtilities };
@@ -1,5 +1,5 @@
1
1
  import { t as isCodeFile } from "./project-root-3kk7gCOp.mjs";
2
- import { t as evaluate } from "./evaluate-I9CAwUlI.mjs";
2
+ import { t as evaluate } from "./evaluate-CxgYAODk.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,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 { $ as postEditTypescript, A as trackSkillRead, At as trackFile, B as isProject, C as seoPostToolUse, Ct as gitContext, D as postTrackingSideEffects, Dt as taskContext, E as securityAdvisory, Et as promptSubmitContext, F as dispatchLessons, Ft as securityStateDir, G as getFileDesc, H as loadEnriched, I as cartoSessionStart, It as securityStatePath, K as listChildren, L as generateEcosystemMap, Lt as todayUtc, M as dispatchLifecycle, Mt as isoUtc, N as aipilotPostToolUse, Nt as loadSecurityState, O as trackWatchResearch, Ot as defaultStateDir, P as dispatchAipilot, Pt as saveSecurityState, Q as lessonsStateFileFor, R as writePluginMap, S as postEditContext, St as devContext, T as dispatchMemory, Tt as claudeMdKey, U as mergeLines, V as writeTree, W as countFiles, X as lessonsArchiveFileFor, Z as lessonsFileFor, _ as preCommitGate, _t as sessionStartCore, a as recordActivity, at as validateTeammateOutput, b as extractSymbols, bt as removeOldFiles, c as MCP_TTL_MS, ct as validateTailwind, d as isMcpTool, dt as countLoc, et as trackSessionChanges, f as queryOf, ft as detectSolidProfile, g as gate, gt as runSessionStartCleanups, h as TRIVIAL_BUDGET, ht as readRules, i as respond, it as logToolFailure, j as trackEnrichment, jt as normalizeEvent, k as trackMcpResearch, kt as projectHash, l as WEBFETCH_TTL_MS, lt as validateSolidGate, m as REQUIRED_AGENTS, mt as injectRules, n as activityFor, nt as cleanupSession, o as mcpPostStore, ot as trackAgentMemory, p as DEFAULT_WINDOW_MS, pt as solidDetectStart, r as handlePre, rt as saveApexState, s as mcpPreIntercept, st as subagentCacheContext, t as handleHook, tt as validateRulesLoaded, u as cacheQueryOf, ut as checkFileSize, v as detectDuplication, vt as pruneEmptyDirs, w as seoPostToolUseResponse, wt as projectContext, x as lifecycleStdout, xt as trimLogFile, y as dryGate, yt as purgeTtlTree, z as generateProjectMap } from "../handle-DnxRzNuY.mjs";
3
+ import { $ as postEditTypescript, A as trackSkillRead, At as trackFile, B as isProject, C as seoPostToolUse, Ct as gitContext, D as postTrackingSideEffects, Dt as taskContext, E as securityAdvisory, Et as promptSubmitContext, F as dispatchLessons, Ft as securityStateDir, G as getFileDesc, H as loadEnriched, I as cartoSessionStart, It as securityStatePath, K as listChildren, L as generateEcosystemMap, Lt as todayUtc, M as dispatchLifecycle, Mt as isoUtc, N as aipilotPostToolUse, Nt as loadSecurityState, O as trackWatchResearch, Ot as defaultStateDir, P as dispatchAipilot, Pt as saveSecurityState, Q as lessonsStateFileFor, R as writePluginMap, S as postEditContext, St as devContext, T as dispatchMemory, Tt as claudeMdKey, U as mergeLines, V as writeTree, W as countFiles, X as lessonsArchiveFileFor, Z as lessonsFileFor, _ as preCommitGate, _t as sessionStartCore, a as recordActivity, at as validateTeammateOutput, b as extractSymbols, bt as removeOldFiles, c as MCP_TTL_MS, ct as validateTailwind, d as isMcpTool, dt as countLoc, et as trackSessionChanges, f as queryOf, ft as detectSolidProfile, g as gate, gt as runSessionStartCleanups, h as TRIVIAL_BUDGET, ht as readRules, i as respond, it as logToolFailure, j as trackEnrichment, jt as normalizeEvent, k as trackMcpResearch, kt as projectHash, l as WEBFETCH_TTL_MS, lt as validateSolidGate, m as REQUIRED_AGENTS, mt as injectRules, n as activityFor, nt as cleanupSession, o as mcpPostStore, ot as trackAgentMemory, p as DEFAULT_WINDOW_MS, pt as solidDetectStart, r as handlePre, rt as saveApexState, s as mcpPreIntercept, st as subagentCacheContext, t as handleHook, tt as validateRulesLoaded, u as cacheQueryOf, ut as checkFileSize, v as detectDuplication, vt as pruneEmptyDirs, w as seoPostToolUseResponse, wt as projectContext, x as lifecycleStdout, xt as trimLogFile, y as dryGate, yt as purgeTtlTree, z as generateProjectMap } from "../handle-CU5UdAei.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.65",
3
+ "version": "0.1.67",
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",