@fusengine/harness 0.1.60 → 0.1.62

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 denyResponse, c as informResponse, d as toClaudeResponse, i as contextResponse, l as readClaudeInput, n as attachSystemMessage, o as fileSizeGuard, r as blockResponse, s as guard, t as ClaudeHookInput, u as systemMessage } from "../../index-DZCLmSoO.mjs";
1
+ import { a as denyResponse, c as informResponse, d as toClaudeResponse, i as contextResponse, l as readClaudeInput, n as attachSystemMessage, o as fileSizeGuard, r as blockResponse, s as guard, t as ClaudeHookInput, u as systemMessage } from "../../index-ce2J1bHC.mjs";
2
2
  export { ClaudeHookInput, attachSystemMessage, blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, informResponse, readClaudeInput, systemMessage, toClaudeResponse };
@@ -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-k1SG-ROm.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-C0xGMbeA.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-PuyQPU36.mjs";
1
+ import { t as evaluate } from "../../evaluate-wDDbojx6.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/cline/index.ts
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  import { t as Prompt } from "../../types-DVbIl9md.mjs";
2
- import { a as denyResponse, i as contextResponse, l as readClaudeInput, t as ClaudeHookInput } from "../../index-DZCLmSoO.mjs";
2
+ import { a as denyResponse, i as contextResponse, l as readClaudeInput, t as ClaudeHookInput } from "../../index-ce2J1bHC.mjs";
3
3
 
4
4
  //#region src/adapters/codex/index.d.ts
5
5
  /** Render a portable {@link Prompt} as a Codex hook response, `ask` → explicit deny. */
@@ -1,8 +1,8 @@
1
1
  import { f as countLines } from "../../home-state-D0RLWP8J.mjs";
2
- import { t as evaluate } from "../../evaluate-PuyQPU36.mjs";
2
+ import { t as evaluate } from "../../evaluate-wDDbojx6.mjs";
3
3
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
4
4
  import { t as parseApplyPatch } from "../../apply-patch-CIS2EZ_q.mjs";
5
- import { c as readClaudeInput, i as denyResponse, r as contextResponse } from "../../claude-k1SG-ROm.mjs";
5
+ import { _ as commandToString, c as readClaudeInput, i as denyResponse, r as contextResponse } from "../../claude-C0xGMbeA.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)
@@ -49,7 +49,7 @@ function resolvePrompt(input) {
49
49
  tool: input.tool_name ?? "Write",
50
50
  filePath: i?.file_path,
51
51
  content: i?.content ?? i?.new_string,
52
- command: i?.command
52
+ command: commandToString(i?.command)
53
53
  });
54
54
  return r.decision === "allow" || !r.prompt ? null : r.prompt;
55
55
  }
@@ -59,7 +59,7 @@ function resolvePrompt(input) {
59
59
  * into per-file checks; every other tool routes through the portable policy.
60
60
  */
61
61
  function guard(input) {
62
- const prompt = input.tool_name === "apply_patch" ? applyPatchPrompt(input.tool_input?.command ?? "") : resolvePrompt(input);
62
+ const prompt = input.tool_name === "apply_patch" ? applyPatchPrompt(commandToString(input.tool_input?.command) ?? "") : resolvePrompt(input);
63
63
  return prompt ? toCodexResponse(prompt) : null;
64
64
  }
65
65
  //#endregion
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-PuyQPU36.mjs";
1
+ import { t as evaluate } from "../../evaluate-wDDbojx6.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-PuyQPU36.mjs";
1
+ import { t as evaluate } from "../../evaluate-wDDbojx6.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/gemini/index.ts
4
4
  /**
@@ -15,7 +15,7 @@ interface HermesHookInput {
15
15
  path?: string;
16
16
  file_path?: string;
17
17
  content?: string;
18
- command?: string;
18
+ command?: string | string[];
19
19
  };
20
20
  session_id?: string;
21
21
  cwd?: string;
@@ -1,2 +1,2 @@
1
- import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-DQ0XFn7u.mjs";
1
+ import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-C1gt6ooE.mjs";
2
2
  export { guard, readHermesInput, toHermesResponse };
@@ -1,8 +1,49 @@
1
- import { t as evaluate } from "./evaluate-PuyQPU36.mjs";
1
+ import { t as evaluate } from "./evaluate-wDDbojx6.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";
5
5
  import { spawnSync } from "node:child_process";
6
+ //#region src/runtime/command-string.ts
7
+ /** Shell basenames whose `-c`-style argv carries the real script in argv[2]. */
8
+ const SHELLS = /* @__PURE__ */ new Set([
9
+ "bash",
10
+ "sh",
11
+ "zsh",
12
+ "dash"
13
+ ]);
14
+ /** True when `arg` is (a path to) a POSIX shell we know wraps a `-c` script. */
15
+ function isShell(arg) {
16
+ if (arg === void 0) return false;
17
+ const base = arg.slice(arg.lastIndexOf("/") + 1);
18
+ return SHELLS.has(base);
19
+ }
20
+ /** True for a shell command flag (`-c`, `-lc`, `-ic`, …) — anything ending in `c`. */
21
+ function isCommandFlag(arg) {
22
+ return arg !== void 0 && /^-[a-z]*c$/.test(arg);
23
+ }
24
+ /**
25
+ * Coerce a hook payload's `command` field to the shell string the guard chain
26
+ * expects. Harnesses disagree on the wire shape: Claude Code, Cursor, and Hermes
27
+ * send a plain string, but Codex CLI sends an argv ARRAY
28
+ * (`["bash", "-lc", "git commit -m x"]`). A naive `typeof === "string"` check
29
+ * dropped the array to `undefined`, blinding every `ctx.command` guard
30
+ * (destructive-git, mutators, install…) into a silent fail-open. This restores
31
+ * the script so the array and string payloads reach an identical verdict.
32
+ *
33
+ * @param v - Raw `command` value off the payload (string, argv array, or other).
34
+ * @returns A string as-is; a `[shell, -c|-lc, script]` argv reduced to its
35
+ * script; any other all-string array joined with spaces; and `undefined` for
36
+ * empty arrays, arrays holding non-strings, or any other type.
37
+ */
38
+ function commandToString(v) {
39
+ if (typeof v === "string") return v;
40
+ if (!Array.isArray(v)) return void 0;
41
+ if (v.length === 0 || !v.every((e) => typeof e === "string")) return void 0;
42
+ const argv = v;
43
+ if (argv.length >= 3 && isShell(argv[0]) && isCommandFlag(argv[1])) return argv[2];
44
+ return argv.join(" ");
45
+ }
46
+ //#endregion
6
47
  //#region src/util/runtime-io.ts
7
48
  /**
8
49
  * Cross-runtime I/O helpers (Node + Bun). The published CLI ships a `node`
@@ -165,7 +206,7 @@ function guard(input) {
165
206
  tool: input.tool_name ?? "Write",
166
207
  filePath: input.tool_input?.file_path,
167
208
  content: input.tool_input?.content ?? input.tool_input?.new_string,
168
- command: input.tool_input?.command
209
+ command: commandToString(input.tool_input?.command)
169
210
  });
170
211
  if (result.decision === "allow" || !result.prompt) return null;
171
212
  return toClaudeResponse(input.hook_event_name ?? "PreToolUse", result.prompt);
@@ -173,4 +214,4 @@ function guard(input) {
173
214
  /** @deprecated use {@link guard}. Kept for back-compat. */
174
215
  const fileSizeGuard = guard;
175
216
  //#endregion
176
- export { fileSizeGuard as a, readClaudeInput as c, collectFiles as d, pathExists as f, writeText as g, spawnCapture as h, denyResponse as i, systemMessage as l, sleep as m, blockResponse as n, guard as o, readText as p, contextResponse as r, informResponse as s, attachSystemMessage as t, toClaudeResponse as u };
217
+ export { commandToString as _, fileSizeGuard as a, readClaudeInput as c, collectFiles as d, pathExists as f, writeText as g, spawnCapture as h, denyResponse as i, systemMessage as l, sleep as m, blockResponse as n, guard as o, readText as p, contextResponse as r, informResponse as s, attachSystemMessage as t, toClaudeResponse as u };
package/dist/cli/bin.mjs CHANGED
@@ -2,9 +2,9 @@
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-CvqZrZUR.mjs";
5
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-kVHXFVug.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-DveqiDmL.mjs";
7
+ import { J as runningVersion, Lt as todayUtc, Y as versionBanner, q as runDoctor, t as handleHook } from "../handle-C2-HU8PS.mjs";
8
8
  import { delimiter, join } from "node:path";
9
9
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
10
10
  import { homedir } from "node:os";
@@ -1,2 +1,2 @@
1
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-CvqZrZUR.mjs";
1
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-kVHXFVug.mjs";
2
2
  export { checkStaged, stagedContent, stagedFiles };
@@ -5,17 +5,38 @@ import { homedir } from "node:os";
5
5
  //#region src/policy/patterns.ts
6
6
  /**
7
7
  * Guard pattern data, ported verbatim from the fusengine git/install guards.
8
- * Note (faithful): `git push.*--force` also matches `--force-with-lease` —
9
- * preserved from the source guard.
8
+ * Note (faithful): `--force` also matches `--force-with-lease` — preserved
9
+ * from the source guard, now as an explicit alternation instead of an
10
+ * accidental substring match (see {@link GIT_BLOCKED}).
10
11
  */
12
+ /**
13
+ * Token-boundary suffix for a destructive flag: only whitespace, `=`, or
14
+ * end-of-string may follow — never another word character. Without this, a
15
+ * flag regex matches as a plain substring of any argument (a branch/file name
16
+ * like `fix/guard-false-positives` contains `-f`, `feature-force-refactor`
17
+ * contains `-force`), turning a rename into a false-positive hard block
18
+ * (proven live: `git push -u origin fix/api-keys-fossil` denied as
19
+ * "Destructive git command"). No leading-boundary group is needed on the flag
20
+ * side — every pattern below prefixes the flag with a literal `\s`, and the
21
+ * flag can never be the first character of the whole command since a git
22
+ * verb (`git push`, `git reset`, ...) always precedes it.
23
+ */
24
+ const FLAG_END = "(?:\\s|=|$)";
25
+ /** `-f` / `--force` / `--force-with-lease`, boundary-anchored on both flag forms. */
26
+ const FORCE_FLAG = `\\s(?:--force(?:-with-lease)?|-f)${FLAG_END}`;
27
+ /**
28
+ * `git clean` short-flag cluster containing both `f` and `d` in any order
29
+ * (`-fd`, `-df`, `-fdx`, `-fdX`, `-xfd`…): a MORE destructive superset than a
30
+ * bare `-fd` — must stay blocked, never downgrade to `git clean`'s GIT_ASK.
31
+ */
32
+ const CLEAN_FD_FLAG = `\\s-(?=[a-zA-Z]*f)(?=[a-zA-Z]*d)[a-zA-Z]+${FLAG_END}`;
11
33
  /** Destructive git operations to block outright. */
12
34
  const GIT_BLOCKED = [
13
- /git push.*--force/,
14
- /git push.*-f/,
15
- /git reset.*--hard/,
16
- /git clean.*-fd/,
17
- /git branch.*-D/,
18
- /git rebase.*--force/
35
+ new RegExp(`git push.*${FORCE_FLAG}`),
36
+ new RegExp(`git reset.*\\s--hard${FLAG_END}`),
37
+ new RegExp(`git clean.*${CLEAN_FD_FLAG}`),
38
+ new RegExp(`git branch.*\\s-D${FLAG_END}`),
39
+ new RegExp(`git rebase.*${FORCE_FLAG}`)
19
40
  ];
20
41
  /** Git operations that warrant a confirmation prompt. */
21
42
  const GIT_ASK = [
@@ -2,9 +2,9 @@ import { a as parseEnvInt, i as splitTarget, r as resolveMaxLines } from "./limi
2
2
  import { s as resolveTtlSec } from "./dotenv-Jj8aL1FL.mjs";
3
3
  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
- 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-DCQ8dkdL.mjs";
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-CjpoH2bf.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-PuyQPU36.mjs";
7
+ import { n as FAIL_CLOSED, t as evaluate } from "./evaluate-wDDbojx6.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 { t as parseApplyPatch } from "./apply-patch-CIS2EZ_q.mjs";
17
- import { d as collectFiles, f as pathExists, g as writeText, h as spawnCapture, i as denyResponse, l as systemMessage, m as sleep, n as blockResponse, p as readText, r as contextResponse, s as informResponse, t as attachSystemMessage } from "./claude-k1SG-ROm.mjs";
18
- import { r as toHermesResponse } from "./hermes-DQ0XFn7u.mjs";
17
+ import { _ as commandToString, d as collectFiles, f as pathExists, g as writeText, h as spawnCapture, i as denyResponse, l as systemMessage, m as sleep, n as blockResponse, p as readText, r as contextResponse, s as informResponse, t as attachSystemMessage } from "./claude-C0xGMbeA.mjs";
18
+ import { r as toHermesResponse } from "./hermes-C1gt6ooE.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";
@@ -111,7 +111,7 @@ function normalizeEvent(id, payload) {
111
111
  ...base,
112
112
  filePath: str(input.file_path) ?? str(input.path) ?? str(payload.file_path),
113
113
  content: str(input.content) ?? str(input.new_string),
114
- command: str(input.command) ?? str(payload.command)
114
+ command: commandToString(input.command) ?? commandToString(payload.command)
115
115
  };
116
116
  }
117
117
  //#endregion
@@ -1,6 +1,6 @@
1
- import { t as evaluate } from "./evaluate-PuyQPU36.mjs";
1
+ import { t as evaluate } from "./evaluate-wDDbojx6.mjs";
2
2
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
3
- import { c as readClaudeInput } from "./claude-k1SG-ROm.mjs";
3
+ import { _ as commandToString, c as readClaudeInput } from "./claude-C0xGMbeA.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
@@ -45,7 +45,7 @@ function guard(input) {
45
45
  tool: input.tool_name ?? "write_file",
46
46
  filePath: t?.path ?? t?.file_path,
47
47
  content: t?.content,
48
- command: t?.command
48
+ command: commandToString(t?.command)
49
49
  });
50
50
  if (r.decision === "allow" || !r.prompt) return null;
51
51
  return toHermesResponse(r.prompt);
@@ -96,11 +96,6 @@ declare function countFrameworkCodeLines(content: string): number;
96
96
  declare function evaluateFileSize(lines: number, max?: number, filePath?: string, framework?: string, displayLines?: number): FileSizeVerdict;
97
97
  //#endregion
98
98
  //#region src/policy/patterns.d.ts
99
- /**
100
- * Guard pattern data, ported verbatim from the fusengine git/install guards.
101
- * Note (faithful): `git push.*--force` also matches `--force-with-lease` —
102
- * preserved from the source guard.
103
- */
104
99
  /** Destructive git operations to block outright. */
105
100
  declare const GIT_BLOCKED: ReadonlyArray<RegExp>;
106
101
  /** Git operations that warrant a confirmation prompt. */
@@ -9,7 +9,7 @@ interface ClaudeHookInput {
9
9
  file_path?: string;
10
10
  content?: string;
11
11
  new_string?: string;
12
- command?: string;
12
+ command?: string | string[];
13
13
  };
14
14
  cwd?: string;
15
15
  }
package/dist/index.d.mts CHANGED
@@ -5,7 +5,7 @@ import { a as HarnessInfo, i as HarnessId, n as detectMode, o as HarnessMode, r
5
5
  import { a as isDocConsulted, i as formatDocSatisfactionStatus, n as DocSatisfactionStatus, o as resolveSessions, r as formatDocDeny, t as AuthEntry } from "./doc-helpers-CEKzGg2u.mjs";
6
6
  import { t as incrementTrivialEditCounter } from "./index-BOBXQ91y.mjs";
7
7
  import { a as compactJson, i as walkUpFor, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./index-BEMumjOw.mjs";
8
- import { $ as ASK_PATTERNS, A as FAIL_CLOSED, B as SWIFT_PROTO_RE, C as usesTailwindUtilities, Ct as ModularArchitecture, D as MAX_TOKENS, Dt as isApexCommand, E as MAX_EXA_RESULTS, Et as detectProjectType, F as installGuard, G as CODE_MUTATORS, H as interfaceSeparationGuard, I as GO_DECL_RE, J as SAFE_PREFIXES, K as CODE_REDIRECT, L as JAVA_DECL_RE, M as clearUserGuards, N as registerGuard, O as capVerbosity, Ot as requiredArchSkill, P as runGuards, Q as protectedPathGuard, R as PHP_DECL_RE, S as skillTriggerGate, St as DEV_KEYWORDS, T as frameworkSolidGate, Tt as detectModularArchitecture, U as bashWriteGuard, V as TS_DECL_RE, W as ASK_WRITERS, X as PROTECTED_FRAGMENTS, Y as SESSION_STATE_FRAGMENT, Z as PROTECTED_GIT_RE, _ as DEV_VERBS, _t as SOLID_REF, a as firstHeading, at as evaluate, b as detectClaudeMdProjectType, bt as evaluateFileSize, c as parseEntry, ct as GIT_ASK, d as EXCLUDE_DIRS, dt as RALPH_SAFE, et as CRITICAL_PATTERNS, f as PROJECT_INDICATORS, ft as SYSTEM_INSTALL, g as loadApexTaskState, gt as PLUGINS_DIR, h as buildApexTaskInjection, ht as FileSizeVerdict, i as firstComment, it as GuardContext, j as GUARDS, k as detectCreationIntent, l as parseBodyDesc, lt as GIT_BLOCKED, m as buildApexTaskContext, mt as matchPatterns, n as missingSeoElements, nt as securityGuard, o as TreeEntry, ot as PolicyContext, p as ApexTaskState, pt as isRalphMode, q as FILE_REDIRECT, r as descFromText, rt as Guard, s as parseEnrichment, st as PolicyResult, t as isHtmlLike, tt as LabeledPattern, u as parseField, ut as PROJECT_INSTALL, v as buildApexInstruction, vt as countFrameworkCodeLines, w as SKILL_TRIGGERS, wt as ProjectType, x as detectRequiredSkills, xt as detectFramework, y as buildClaudeMdContext, yt as countLines, z as PY_MODEL_RE } from "./index-BUDzFkeo.mjs";
8
+ import { $ as ASK_PATTERNS, A as FAIL_CLOSED, B as SWIFT_PROTO_RE, C as usesTailwindUtilities, Ct as ModularArchitecture, D as MAX_TOKENS, Dt as isApexCommand, E as MAX_EXA_RESULTS, Et as detectProjectType, F as installGuard, G as CODE_MUTATORS, H as interfaceSeparationGuard, I as GO_DECL_RE, J as SAFE_PREFIXES, K as CODE_REDIRECT, L as JAVA_DECL_RE, M as clearUserGuards, N as registerGuard, O as capVerbosity, Ot as requiredArchSkill, P as runGuards, Q as protectedPathGuard, R as PHP_DECL_RE, S as skillTriggerGate, St as DEV_KEYWORDS, T as frameworkSolidGate, Tt as detectModularArchitecture, U as bashWriteGuard, V as TS_DECL_RE, W as ASK_WRITERS, X as PROTECTED_FRAGMENTS, Y as SESSION_STATE_FRAGMENT, Z as PROTECTED_GIT_RE, _ as DEV_VERBS, _t as SOLID_REF, a as firstHeading, at as evaluate, b as detectClaudeMdProjectType, bt as evaluateFileSize, c as parseEntry, ct as GIT_ASK, d as EXCLUDE_DIRS, dt as RALPH_SAFE, et as CRITICAL_PATTERNS, f as PROJECT_INDICATORS, ft as SYSTEM_INSTALL, g as loadApexTaskState, gt as PLUGINS_DIR, h as buildApexTaskInjection, ht as FileSizeVerdict, i as firstComment, it as GuardContext, j as GUARDS, k as detectCreationIntent, l as parseBodyDesc, lt as GIT_BLOCKED, m as buildApexTaskContext, mt as matchPatterns, n as missingSeoElements, nt as securityGuard, o as TreeEntry, ot as PolicyContext, p as ApexTaskState, pt as isRalphMode, q as FILE_REDIRECT, r as descFromText, rt as Guard, s as parseEnrichment, st as PolicyResult, t as isHtmlLike, tt as LabeledPattern, u as parseField, ut as PROJECT_INSTALL, v as buildApexInstruction, vt as countFrameworkCodeLines, w as SKILL_TRIGGERS, wt as ProjectType, x as detectRequiredSkills, xt as detectFramework, y as buildClaudeMdContext, yt as countLines, z as PY_MODEL_RE } from "./index-C9jYdElK.mjs";
9
9
  import { n as RouteResult, r as ScoredRef, t as RefMeta } from "./types-CY5qT2X1.mjs";
10
10
  import { a as PRE_AUTH_GATES, c as evaluateApex, i as POST_AUTH_GATES, l as freshnessGate, n as ApexContext, o as brainstormGate, r as ApexGate, s as docConsultedGate, t as APEX_GATES, u as solidReadGate } from "./apex-Wdi1nq_w.mjs";
11
11
  import { a as ReminderState, c as readState, d as throttleMs, i as registryFile, l as setStateField, n as addRoot, o as lessonsFileFor, r as readRoots, s as nowStamp, t as ensureMemoryGitignore, u as stateFileFor } from "./index-DLYhervv.mjs";
package/dist/index.mjs CHANGED
@@ -4,9 +4,9 @@ import { n as STATE_ROOT, r as projectLayout, t as STATE_GITIGNORE } from "./lay
4
4
  import { t as compactJson } from "./compact-json-DK2nX-MK.mjs";
5
5
  import { i as walkUpFor, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-3kk7gCOp.mjs";
6
6
  import { n as detectMode, r as modeFor, t as detectHarness } from "./harness-Cb9xR8dC.mjs";
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-DCQ8dkdL.mjs";
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-CjpoH2bf.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-PuyQPU36.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-wDDbojx6.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,3 +1,3 @@
1
- import { $ as ASK_PATTERNS, A as FAIL_CLOSED, B as SWIFT_PROTO_RE, C as usesTailwindUtilities, Ct as ModularArchitecture, D as MAX_TOKENS, Dt as isApexCommand, E as MAX_EXA_RESULTS, Et as detectProjectType, F as installGuard, G as CODE_MUTATORS, H as interfaceSeparationGuard, I as GO_DECL_RE, J as SAFE_PREFIXES, K as CODE_REDIRECT, L as JAVA_DECL_RE, M as clearUserGuards, N as registerGuard, O as capVerbosity, Ot as requiredArchSkill, P as runGuards, Q as protectedPathGuard, R as PHP_DECL_RE, S as skillTriggerGate, St as DEV_KEYWORDS, T as frameworkSolidGate, Tt as detectModularArchitecture, U as bashWriteGuard, V as TS_DECL_RE, W as ASK_WRITERS, X as PROTECTED_FRAGMENTS, Y as SESSION_STATE_FRAGMENT, Z as PROTECTED_GIT_RE, _ as DEV_VERBS, _t as SOLID_REF, a as firstHeading, at as evaluate, b as detectClaudeMdProjectType, bt as evaluateFileSize, c as parseEntry, ct as GIT_ASK, d as EXCLUDE_DIRS, dt as RALPH_SAFE, et as CRITICAL_PATTERNS, f as PROJECT_INDICATORS, ft as SYSTEM_INSTALL, g as loadApexTaskState, gt as PLUGINS_DIR, h as buildApexTaskInjection, ht as FileSizeVerdict, i as firstComment, it as GuardContext, j as GUARDS, k as detectCreationIntent, l as parseBodyDesc, lt as GIT_BLOCKED, m as buildApexTaskContext, mt as matchPatterns, n as missingSeoElements, nt as securityGuard, o as TreeEntry, ot as PolicyContext, p as ApexTaskState, pt as isRalphMode, q as FILE_REDIRECT, r as descFromText, rt as Guard, s as parseEnrichment, st as PolicyResult, t as isHtmlLike, tt as LabeledPattern, u as parseField, ut as PROJECT_INSTALL, v as buildApexInstruction, vt as countFrameworkCodeLines, w as SKILL_TRIGGERS, wt as ProjectType, x as detectRequiredSkills, xt as detectFramework, y as buildClaudeMdContext, yt as countLines, z as PY_MODEL_RE } from "../index-BUDzFkeo.mjs";
1
+ import { $ as ASK_PATTERNS, A as FAIL_CLOSED, B as SWIFT_PROTO_RE, C as usesTailwindUtilities, Ct as ModularArchitecture, D as MAX_TOKENS, Dt as isApexCommand, E as MAX_EXA_RESULTS, Et as detectProjectType, F as installGuard, G as CODE_MUTATORS, H as interfaceSeparationGuard, I as GO_DECL_RE, J as SAFE_PREFIXES, K as CODE_REDIRECT, L as JAVA_DECL_RE, M as clearUserGuards, N as registerGuard, O as capVerbosity, Ot as requiredArchSkill, P as runGuards, Q as protectedPathGuard, R as PHP_DECL_RE, S as skillTriggerGate, St as DEV_KEYWORDS, T as frameworkSolidGate, Tt as detectModularArchitecture, U as bashWriteGuard, V as TS_DECL_RE, W as ASK_WRITERS, X as PROTECTED_FRAGMENTS, Y as SESSION_STATE_FRAGMENT, Z as PROTECTED_GIT_RE, _ as DEV_VERBS, _t as SOLID_REF, a as firstHeading, at as evaluate, b as detectClaudeMdProjectType, bt as evaluateFileSize, c as parseEntry, ct as GIT_ASK, d as EXCLUDE_DIRS, dt as RALPH_SAFE, et as CRITICAL_PATTERNS, f as PROJECT_INDICATORS, ft as SYSTEM_INSTALL, g as loadApexTaskState, gt as PLUGINS_DIR, h as buildApexTaskInjection, ht as FileSizeVerdict, i as firstComment, it as GuardContext, j as GUARDS, k as detectCreationIntent, l as parseBodyDesc, lt as GIT_BLOCKED, m as buildApexTaskContext, mt as matchPatterns, n as missingSeoElements, nt as securityGuard, o as TreeEntry, ot as PolicyContext, p as ApexTaskState, pt as isRalphMode, q as FILE_REDIRECT, r as descFromText, rt as Guard, s as parseEnrichment, st as PolicyResult, t as isHtmlLike, tt as LabeledPattern, u as parseField, ut as PROJECT_INSTALL, v as buildApexInstruction, vt as countFrameworkCodeLines, w as SKILL_TRIGGERS, wt as ProjectType, x as detectRequiredSkills, xt as detectFramework, y as buildClaudeMdContext, yt as countLines, z as PY_MODEL_RE } from "../index-C9jYdElK.mjs";
2
2
  import { a as PRE_AUTH_GATES, c as evaluateApex, i as POST_AUTH_GATES, l as freshnessGate, n as ApexContext, o as brainstormGate, r as ApexGate, s as docConsultedGate, t as APEX_GATES, u as solidReadGate } from "../apex-Wdi1nq_w.mjs";
3
3
  export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, ApexContext, ApexGate, ApexTaskState, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, FILE_REDIRECT, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GUARDS, Guard, GuardContext, JAVA_DECL_RE, LabeledPattern, MAX_EXA_RESULTS, MAX_TOKENS, ModularArchitecture, PHP_DECL_RE, PLUGINS_DIR, POST_AUTH_GATES, PRE_AUTH_GATES, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, type PolicyContext, type PolicyResult, ProjectType, RALPH_SAFE, SAFE_PREFIXES, SESSION_STATE_FRAGMENT, SKILL_TRIGGERS, SOLID_REF, SWIFT_PROTO_RE, SYSTEM_INSTALL, TS_DECL_RE, TreeEntry, 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
- 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-DCQ8dkdL.mjs";
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-CjpoH2bf.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-PuyQPU36.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-wDDbojx6.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-PuyQPU36.mjs";
2
+ import { t as evaluate } from "./evaluate-wDDbojx6.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-DveqiDmL.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-C2-HU8PS.mjs";
4
4
  //#region src/runtime/storage.ts
5
5
  /**
6
6
  * The project's single state dir (`<root>/.harness`) — neutral + harness-agnostic,
@@ -108,6 +108,47 @@ function detectFramework(filePath, content) {
108
108
  return "generic";
109
109
  }
110
110
  //#endregion
111
+ //#region src/refs/ref-key.ts
112
+ /**
113
+ * Path shapes {@link discoverRefs}'s `skillParents` treats as legitimate skill
114
+ * roots: standalone `.claude`/`.codex`/`.cursor`/`.agents` skill dirs, marketplace
115
+ * and version-cache plugins installed UNDER one of those same config dirs, and
116
+ * the system-rooted `/etc/codex/skills`. Kept as a pure path-shape regex (no
117
+ * disk access, no home/cwd) so {@link skillRefKey} stays a cheap string test
118
+ * callable from the synchronous `solidReadGate`. Every alternative uses only
119
+ * bounded `[^/]+` groups — no nested quantifiers, so no ReDoS exposure.
120
+ *
121
+ * ANCHORING: the marketplace/cache branches require the `.claude`/`.codex`/
122
+ * `.cursor`/`.agents` segment to IMMEDIATELY precede `plugins/…/skills/` —
123
+ * a bare `/plugins/cache/<a>/<b>/<c>/skills/` floating anywhere (e.g. under an
124
+ * attacker-writable `/tmp/plugins/cache/...`) is NOT enough. `/etc/codex/skills/`
125
+ * is anchored at the string start (`^`), since that shape is a real absolute
126
+ * system path, not a directory name that can legitimately appear mid-path.
127
+ */
128
+ const RECOGNIZED_SKILL_ROOT_RE = /(^|\/)\.(claude|codex|cursor|agents)\/(skills\/|plugins\/(marketplaces\/[^/]+\/plugins\/[^/]+|cache\/[^/]+\/[^/]+\/[^/]+)\/skills\/)|^\/etc\/codex\/skills\//;
129
+ /**
130
+ * Normalize a reference path to its `skills/<skill>/...` suffix — the part
131
+ * that stays IDENTICAL between a marketplace-first path (what `discoverRefs`
132
+ * returns, carried by `ctx.refs`/`routed.*.filePath`) and the same skill read
133
+ * by a sub-agent/teammate through a different root: a version-cache path
134
+ * (extra version segment, plugin dir name that can diverge from the
135
+ * marketplace one, e.g. `solid` vs `fuse-solid`) or a standalone
136
+ * `.codex`/`.cursor`/`.agents` skills dir.
137
+ *
138
+ * ANTI-FORGERY: returns `null` — never a usable key — unless `path` also
139
+ * matches one of the recognized skill-root SHAPES above. A path like
140
+ * `/tmp/skills/solid-generic/references/solid-principles.md` has the right
141
+ * suffix but no recognized root, so it cannot credit a SOLID read by suffix
142
+ * alone; only an exact byte-for-byte match (same as any unrelated file) would.
143
+ * @param path - Absolute path to normalize (a `ctx.refs` entry or a `refsRead` entry).
144
+ * @returns The `skills/...` suffix, or `null` when `path` isn't a recognized skill path.
145
+ */
146
+ function skillRefKey(path) {
147
+ if (!RECOGNIZED_SKILL_ROOT_RE.test(path)) return null;
148
+ const i = path.lastIndexOf("skills/");
149
+ return i === -1 ? null : path.slice(i);
150
+ }
151
+ //#endregion
111
152
  //#region src/policy/apex-gates.ts
112
153
  /**
113
154
  * True when the SOLID ref read at `path` still counts. Parity require-solid-read.py
@@ -139,7 +180,13 @@ const solidReadGate = (ctx) => {
139
180
  };
140
181
  }
141
182
  const read = new Set((ctx.refsRead ?? []).filter((p) => refReadFresh(ctx, p, windowMs)));
142
- const missing = !!routed.skillPath && read.has(routed.skillPath) ? [] : routed.required.map((r) => r.meta.filePath).filter((p) => !read.has(p));
183
+ const readKeys = new Set([...read].map(skillRefKey).filter((k) => k !== null));
184
+ const credited = (path) => {
185
+ if (read.has(path)) return true;
186
+ const key = skillRefKey(path);
187
+ return key !== null && readKeys.has(key);
188
+ };
189
+ const missing = !!routed.skillPath && credited(routed.skillPath) ? [] : routed.required.map((r) => r.meta.filePath).filter((p) => !credited(p));
143
190
  if (missing.length === 0) return null;
144
191
  const optional = routed.optional.map((r) => r.meta.filePath);
145
192
  const reason = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/harness",
3
- "version": "0.1.60",
3
+ "version": "0.1.62",
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",